wave模块

  • 1. 概述
    • 1.1 Wave_read对象
    • 1.2 Wave_write 对象
  • 2. 实际使用中的问题
    • 2.1 音频保存
  • 3. 源代码:`Lib/wave.py`

1. 概述

wave 模块提供了一个处理 WAV 声音格式的便利接口。它不支持压缩/解压,但是支持单声道/立体声

用法:wave.open(file, mode=None),其中,moderbwb

  • rb:生成 wav_read 对象
  • wb:生成 wav_write 对象
    注意不支持同时读写

注:关于 rwrbwb
rw是普通读和写文件(简单理解为人工编写的文件);
rbwb是读写二进制文件(简单理解为可以操作图片等非手工编写的文件)

1.1 Wave_read对象

import wave# wave.read 对象方法wr = wave.open('/Users/robin/Desktop/WavTest.wav', 'rb')print(wr.getnchannels()) # 返回声道数量(1 为单声道,2 为立体声)
print(wr.getsampwidth()) # 返回采样字节长度
print(wr.getframerate()) # 返回采样频率
print(wr.getnframes()) # 返回音频总的帧数print(wr.getparams()) # 返回一个 namedtuple() (nchannels, sampwidth, framerate, nframes, comptype, compname),与 get*() 方法的输出相同。print(wr.readframes(n))
1
2
16000
103765
_wave_params(nchannels=1, sampwidth=2, framerate=16000, nframes=103765, comptype='NONE', compname='not compressed')
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0
...

1.2 Wave_write 对象

# wave.write 对象方法
#(1)open 创建文件
ww = wave.open('/Users/robin/Desktop/WavTest.wav', 'wb')#(2)set 设置参数
ww.setchannels(n) # 设置通道数
ww.setsampwidth(n) # 设置采样字节长度为 n
ww.setframerate(n) # 设置采样频率为 nww.setparams(n) # 设置所有形参,(nchannels, sampwidth, framerate, nframes, comptype, compname),每项的值应可用于 set*() 方法。# (3) writeframes 写入数据流
ww.writeframes(data) # 写入音频帧并确保 nframes 是正确的# (4) close 关闭
ww.close()

2. 实际使用中的问题

2.1 音频保存

1、setsampwidth采样字节长度 or 采样位数、量化位数

表示用多少bit表达一次采样所采集的数据,通常有8bit、16bit、24bit和32bit等几种,
需要注意的是,在设置setsampwidth时,采用的单位是bytes而不是bit。比如,16 bits per sample (= 2 bytes),应该设置setsampwidth=2而不是setsampwidth=16,否则可能会报错:raise Error('sample width not specified')

代码示例:

channel = 1
bits = 2  # 16 bits = 2 bytes(wave模块中使用byte!!!注意除以8进行转换)
rates = 16000# read(or resample) wav and save
def write_wav(file_name, input_data):wavfile = wave.open(file_name, 'wb')  # 创建(空)文件wavfile.setparams((channel, bits,  rates, 0, 'NONE', 'NONE'))print("wav文件信息:", wavfile.getparams()[:4])wavfile.writeframes(input_data)  # 写入数据wavfile.close()

3. 源代码:Lib/wave.py

"""Stuff to parse WAVE files.
Usage.
Reading WAVE files:f = wave.open(file, 'r')
where file is either the name of a file or an open file pointer.
The open file pointer must have methods read(), seek(), and close().
When the setpos() and rewind() methods are not used, the seek()
method is not  necessary.
This returns an instance of a class with the following public methods:getnchannels()  -- returns number of audio channels (1 formono, 2 for stereo)getsampwidth()  -- returns sample width in bytesgetframerate()  -- returns sampling frequencygetnframes()    -- returns number of audio framesgetcomptype()   -- returns compression type ('NONE' for linear samples)getcompname()   -- returns human-readable version ofcompression type ('not compressed' linear samples)getparams()     -- returns a namedtuple consisting of all of theabove in the above ordergetmarkers()    -- returns None (for compatibility with theaifc module)getmark(id)     -- raises an error since the mark does notexist (for compatibility with the aifc module)readframes(n)   -- returns at most n frames of audiorewind()        -- rewind to the beginning of the audio streamsetpos(pos)     -- seek to the specified positiontell()          -- return the current positionclose()         -- close the instance (make it unusable)
The position returned by tell() and the position given to setpos()
are compatible and have nothing to do with the actual position in the
file.
The close() method is called automatically when the class instance
is destroyed.
Writing WAVE files:f = wave.open(file, 'w')
where file is either the name of a file or an open file pointer.
The open file pointer must have methods write(), tell(), seek(), and
close().
This returns an instance of a class with the following public methods:setnchannels(n) -- set the number of channelssetsampwidth(n) -- set the sample widthsetframerate(n) -- set the frame ratesetnframes(n)   -- set the number of framessetcomptype(type, name)-- set the compression type and thehuman-readable compression typesetparams(tuple)-- set all parameters at oncetell()          -- return current position in output filewriteframesraw(data)-- write audio frames without patching up thefile headerwriteframes(data)-- write audio frames and patch up the file headerclose()         -- patch up the file header and close theoutput file
You should set the parameters before the first writeframesraw or
writeframes.  The total number of frames does not need to be set,
but when it is set to the correct value, the header does not have to
be patched up.
It is best to first set all parameters, perhaps possibly the
compression type, and then write audio frames using writeframesraw.
When all frames have been written, either call writeframes(b'') or
close() to patch up the sizes in the header.
The close() method is called automatically when the class instance
is destroyed.
"""from chunk import Chunk
from collections import namedtuple
import audioop
import builtins
import struct
import sys__all__ = ["open", "Error", "Wave_read", "Wave_write"]class Error(Exception):passWAVE_FORMAT_PCM = 0x0001_array_fmts = None, 'b', 'h', None, 'i'_wave_params = namedtuple('_wave_params','nchannels sampwidth framerate nframes comptype compname')class Wave_read:"""Variables used in this class:These variables are available to the user though appropriatemethods of this class:_file -- the open file with methods read(), close(), and seek()set through the __init__() method_nchannels -- the number of audio channelsavailable through the getnchannels() method_nframes -- the number of audio framesavailable through the getnframes() method_sampwidth -- the number of bytes per audio sampleavailable through the getsampwidth() method_framerate -- the sampling frequencyavailable through the getframerate() method_comptype -- the AIFF-C compression type ('NONE' if AIFF)available through the getcomptype() method_compname -- the human-readable AIFF-C compression typeavailable through the getcomptype() method_soundpos -- the position in the audio streamavailable through the tell() method, set through thesetpos() methodThese variables are used internally only:_fmt_chunk_read -- 1 iff the FMT chunk has been read_data_seek_needed -- 1 iff positioned correctly in audiofile for readframes()_data_chunk -- instantiation of a chunk class for the DATA chunk_framesize -- size of one frame in the file"""def initfp(self, file):self._convert = Noneself._soundpos = 0self._file = Chunk(file, bigendian = 0)if self._file.getname() != b'RIFF':raise Error('file does not start with RIFF id')if self._file.read(4) != b'WAVE':raise Error('not a WAVE file')self._fmt_chunk_read = 0self._data_chunk = Nonewhile 1:self._data_seek_needed = 1try:chunk = Chunk(self._file, bigendian = 0)except EOFError:breakchunkname = chunk.getname()if chunkname == b'fmt ':self._read_fmt_chunk(chunk)self._fmt_chunk_read = 1elif chunkname == b'data':if not self._fmt_chunk_read:raise Error('data chunk before fmt chunk')self._data_chunk = chunkself._nframes = chunk.chunksize // self._framesizeself._data_seek_needed = 0breakchunk.skip()if not self._fmt_chunk_read or not self._data_chunk:raise Error('fmt chunk and/or data chunk missing')def __init__(self, f):self._i_opened_the_file = Noneif isinstance(f, str):f = builtins.open(f, 'rb')self._i_opened_the_file = f# else, assume it is an open file object alreadytry:self.initfp(f)except:if self._i_opened_the_file:f.close()raisedef __del__(self):self.close()def __enter__(self):return selfdef __exit__(self, *args):self.close()## User visible methods.#def getfp(self):return self._filedef rewind(self):self._data_seek_needed = 1self._soundpos = 0def close(self):self._file = Nonefile = self._i_opened_the_fileif file:self._i_opened_the_file = Nonefile.close()def tell(self):return self._soundposdef getnchannels(self):return self._nchannelsdef getnframes(self):return self._nframesdef getsampwidth(self):return self._sampwidthdef getframerate(self):return self._frameratedef getcomptype(self):return self._comptypedef getcompname(self):return self._compnamedef getparams(self):return _wave_params(self.getnchannels(), self.getsampwidth(),self.getframerate(), self.getnframes(),self.getcomptype(), self.getcompname())def getmarkers(self):return Nonedef getmark(self, id):raise Error('no marks')def setpos(self, pos):if pos < 0 or pos > self._nframes:raise Error('position not in range')self._soundpos = posself._data_seek_needed = 1def readframes(self, nframes):if self._data_seek_needed:self._data_chunk.seek(0, 0)pos = self._soundpos * self._framesizeif pos:self._data_chunk.seek(pos, 0)self._data_seek_needed = 0if nframes == 0:return b''data = self._data_chunk.read(nframes * self._framesize)if self._sampwidth != 1 and sys.byteorder == 'big':data = audioop.byteswap(data, self._sampwidth)if self._convert and data:data = self._convert(data)self._soundpos = self._soundpos + len(data) // (self._nchannels * self._sampwidth)return data## Internal methods.#def _read_fmt_chunk(self, chunk):try:wFormatTag, self._nchannels, self._framerate, dwAvgBytesPerSec, wBlockAlign = struct.unpack_from('<HHLLH', chunk.read(14))except struct.error:raise EOFError from Noneif wFormatTag == WAVE_FORMAT_PCM:try:sampwidth = struct.unpack_from('<H', chunk.read(2))[0]except struct.error:raise EOFError from Noneself._sampwidth = (sampwidth + 7) // 8if not self._sampwidth:raise Error('bad sample width')else:raise Error('unknown format: %r' % (wFormatTag,))if not self._nchannels:raise Error('bad # of channels')self._framesize = self._nchannels * self._sampwidthself._comptype = 'NONE'self._compname = 'not compressed'class Wave_write:"""Variables used in this class:These variables are user settable through appropriate methodsof this class:_file -- the open file with methods write(), close(), tell(), seek()set through the __init__() method_comptype -- the AIFF-C compression type ('NONE' in AIFF)set through the setcomptype() or setparams() method_compname -- the human-readable AIFF-C compression typeset through the setcomptype() or setparams() method_nchannels -- the number of audio channelsset through the setnchannels() or setparams() method_sampwidth -- the number of bytes per audio sampleset through the setsampwidth() or setparams() method_framerate -- the sampling frequencyset through the setframerate() or setparams() method_nframes -- the number of audio frames written to the headerset through the setnframes() or setparams() methodThese variables are used internally only:_datalength -- the size of the audio samples written to the header_nframeswritten -- the number of frames actually written_datawritten -- the size of the audio samples actually written"""def __init__(self, f):self._i_opened_the_file = Noneif isinstance(f, str):f = builtins.open(f, 'wb')self._i_opened_the_file = ftry:self.initfp(f)except:if self._i_opened_the_file:f.close()raisedef initfp(self, file):self._file = fileself._convert = Noneself._nchannels = 0self._sampwidth = 0self._framerate = 0self._nframes = 0self._nframeswritten = 0self._datawritten = 0self._datalength = 0self._headerwritten = Falsedef __del__(self):self.close()def __enter__(self):return selfdef __exit__(self, *args):self.close()## User visible methods.#def setnchannels(self, nchannels):if self._datawritten:raise Error('cannot change parameters after starting to write')if nchannels < 1:raise Error('bad # of channels')self._nchannels = nchannelsdef getnchannels(self):if not self._nchannels:raise Error('number of channels not set')return self._nchannelsdef setsampwidth(self, sampwidth):if self._datawritten:raise Error('cannot change parameters after starting to write')if sampwidth < 1 or sampwidth > 4:raise Error('bad sample width')self._sampwidth = sampwidthdef getsampwidth(self):if not self._sampwidth:raise Error('sample width not set')return self._sampwidthdef setframerate(self, framerate):if self._datawritten:raise Error('cannot change parameters after starting to write')if framerate <= 0:raise Error('bad frame rate')self._framerate = int(round(framerate))def getframerate(self):if not self._framerate:raise Error('frame rate not set')return self._frameratedef setnframes(self, nframes):if self._datawritten:raise Error('cannot change parameters after starting to write')self._nframes = nframesdef getnframes(self):return self._nframeswrittendef setcomptype(self, comptype, compname):if self._datawritten:raise Error('cannot change parameters after starting to write')if comptype not in ('NONE',):raise Error('unsupported compression type')self._comptype = comptypeself._compname = compnamedef getcomptype(self):return self._comptypedef getcompname(self):return self._compnamedef setparams(self, params):nchannels, sampwidth, framerate, nframes, comptype, compname = paramsif self._datawritten:raise Error('cannot change parameters after starting to write')self.setnchannels(nchannels)self.setsampwidth(sampwidth)self.setframerate(framerate)self.setnframes(nframes)self.setcomptype(comptype, compname)def getparams(self):if not self._nchannels or not self._sampwidth or not self._framerate:raise Error('not all parameters set')return _wave_params(self._nchannels, self._sampwidth, self._framerate,self._nframes, self._comptype, self._compname)def setmark(self, id, pos, name):raise Error('setmark() not supported')def getmark(self, id):raise Error('no marks')def getmarkers(self):return Nonedef tell(self):return self._nframeswrittendef writeframesraw(self, data):if not isinstance(data, (bytes, bytearray)):data = memoryview(data).cast('B')self._ensure_header_written(len(data))nframes = len(data) // (self._sampwidth * self._nchannels)if self._convert:data = self._convert(data)if self._sampwidth != 1 and sys.byteorder == 'big':data = audioop.byteswap(data, self._sampwidth)self._file.write(data)self._datawritten += len(data)self._nframeswritten = self._nframeswritten + nframesdef writeframes(self, data):self.writeframesraw(data)if self._datalength != self._datawritten:self._patchheader()def close(self):try:if self._file:self._ensure_header_written(0)if self._datalength != self._datawritten:self._patchheader()self._file.flush()finally:self._file = Nonefile = self._i_opened_the_fileif file:self._i_opened_the_file = Nonefile.close()## Internal methods.#def _ensure_header_written(self, datasize):if not self._headerwritten:if not self._nchannels:raise Error('# channels not specified')if not self._sampwidth:raise Error('sample width not specified')if not self._framerate:raise Error('sampling rate not specified')self._write_header(datasize)def _write_header(self, initlength):assert not self._headerwrittenself._file.write(b'RIFF')if not self._nframes:self._nframes = initlength // (self._nchannels * self._sampwidth)self._datalength = self._nframes * self._nchannels * self._sampwidthtry:self._form_length_pos = self._file.tell()except (AttributeError, OSError):self._form_length_pos = Noneself._file.write(struct.pack('<L4s4sLHHLLHH4s',36 + self._datalength, b'WAVE', b'fmt ', 16,WAVE_FORMAT_PCM, self._nchannels, self._framerate,self._nchannels * self._framerate * self._sampwidth,self._nchannels * self._sampwidth,self._sampwidth * 8, b'data'))if self._form_length_pos is not None:self._data_length_pos = self._file.tell()self._file.write(struct.pack('<L', self._datalength))self._headerwritten = Truedef _patchheader(self):assert self._headerwrittenif self._datawritten == self._datalength:returncurpos = self._file.tell()self._file.seek(self._form_length_pos, 0)self._file.write(struct.pack('<L', 36 + self._datawritten))self._file.seek(self._data_length_pos, 0)self._file.write(struct.pack('<L', self._datawritten))self._file.seek(curpos, 0)self._datalength = self._datawrittendef open(f, mode=None):if mode is None:if hasattr(f, 'mode'):mode = f.modeelse:mode = 'rb'if mode in ('r', 'rb'):return Wave_read(f)elif mode in ('w', 'wb'):return Wave_write(f)else:raise Error("mode must be 'r', 'rb', 'w', or 'wb'")

参考:

  1. wave — 读写WAV格式文件
  2. python 3x - about writing with the python wave module

Python 音频处理:wave相关推荐

  1. python的pyaudio教程入门_『开发技巧』Python音频操作工具PyAudio上手教程

    『开发技巧』Python音频操作工具PyAudio上手教程 ​ 0.引子 当需要使用Python处理音频数据时,使用python读取与播放声音必不可少,下面介绍一个好用的处理音频PyAudio工具包. ...

  2. python音频分析工具_『开发技巧』Python音频操作工具PyAudio上手教程

    『开发技巧』Python音频操作工具PyAudio上手教程 ​ 0.引子 当需要使用Python处理音频数据时,使用python读取与播放声音必不可少,下面介绍一个好用的处理音频PyAudio工具包. ...

  3. python音频实时频谱分析_基于python的音频设计及频谱分析

    74 Internet Technology 互联网 + 技术 一.引言 WAV 是 Microsoft 开发的一种声音文件格式,虽然它支持多种压缩格式,但是它通常被用来保存未压缩的声音数据(PCM ...

  4. python音频转数组_python音频处理的示例详解

    准备工作: 首先,我们需要 import 几个工具包,一个是 python 标准库中的 wave 模块,用于音频处理操作,另外两个是 numpy 和 matplot,提供数据处理函数. 一:读取本地音 ...

  5. python处理音频的软件_『开发技巧』Python音频操作工具PyAudio上手教程

    『开发技巧』Python音频操作工具PyAudio上手教程 ​ 0.引子 当需要使用Python处理音频数据时,使用python读取与播放声音必不可少,下面介绍一个好用的处理音频PyAudio工具包. ...

  6. python音频播放问题解决方法

    获取音频 只是为了验证问题存在,所以就提供了一个获取音频的方法,就是白嫖了. 根据有道翻译的发音获取到地址:https://dict.youdao.com/dictvoice?le=auto& ...

  7. Python音频处理:创建一个正弦波并保存为wav文件

    Python音频处理:创建一个正弦波并保存为wav文件 0. 预备知识 0.1 数字信号基础 0.2 声学概念基础 1. 创建一个正弦波 2. 保存为wav文件 0. 预备知识 0.1 数字信号基础 ...

  8. python录音pyaudio_『开发技巧』Python音频操作工具PyAudio上手教程

    『开发技巧』Python音频操作工具PyAudio上手教程 ​ 0.引子 当需要使用Python处理音频数据时,使用python读取与播放声音必不可少,下面介绍一个好用的处理音频PyAudio工具包. ...

  9. 最好用的python音频库之一:pydub的中文文档(含API)

    pydub 中文文档(含API) 0x00 写在最前 Pydub lets you do stuff to audio in a way that isn't stupid. pydub 提供了简洁的 ...

  10. Python音频信号处理 2.使用谱减法去除音频底噪

    使用谱减法去除音频底噪 上一篇文章我主要分享了短时傅立叶变换及其逆变换在python中的实现,有兴趣的可以阅读一下该篇文章,地址如下: Python音频信号处理 1.短时傅里叶变换及其逆变换 那么在本 ...

最新文章

  1. sqlbulkcopy mysql_SqlBulkCopy 的 Timeout 和 BatchSize
  2. 如何使用 AutoPilot 对作业自动调优?
  3. 通过rxjs的一个例子, 来学习SwitchMap的使用方法
  4. Shell 控制并发
  5. ux和ui_阅读10个UI / UX设计系统所获得的经验教训
  6. echarts box
  7. 2020级C语言大作业 - 王国保卫战
  8. NOI模拟(5.8) HNOID2T3 道路 (bzoj5290)
  9. 业务流程的设计 (附加案例)
  10. 使用 Keras 进行面部表情识别
  11. Honey Badger BFT(异步共识算法)笔记
  12. 增值电信业务经营许可证怎么续期,需要什么材料
  13. 【正点原子MP157连载】 第十二章 呼吸灯实验-摘自【正点原子】【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7
  14. java地图代码_如何在Java中生成地图?
  15. c语言程序设计韦良芬答案,论高职院校《C语言程序设计》的教学改革
  16. aot慈善币跑路了_慈善币AOT:用公益收割“韭菜”
  17. js 金额千分位转换
  18. 百度地图搜索框在弹出层中无法显示问题
  19. uni-app 打包H5项目
  20. Spring程序员的春天

热门文章

  1. 分布式消息队列RocketMQ继承SpringBoot
  2. 东华软件反统方:一个能扼住医疗信息泄露咽喉的解决方案
  3. centos7搭建lnmp架构
  4. Excel 数据透视表教程大全之 05 数据透视表绘制各种二维排列的数据,实现双向枢轴(教程含数据)
  5. 酷睿i7十代支持的linux系统,10nm首秀!这就是英特尔十代酷睿
  6. [I T]2012伦敦奥运会10大最酷高科技
  7. 神器 JMH Arthas 性能监控
  8. 二进制转化为十进制和二进制转化为二进制
  9. 中国互联网产业的50个细分领域
  10. 黑帽seo收徒:目录站群的十三项功能