在Python中读取* .wav文件
我需要分析用.wav文件写的声音。 为此,我需要将此文件转换为一组数字(例如数组)。 我想我需要使用波包。 但是,我不知道它是如何工作的。 例如,我做了以下几点:
import wave w = wave.open('/usr/share/sounds/ekiga/voicemail.wav', 'r') for i in range(w.getnframes()): frame = w.readframes(i) print frame
作为这个代码的结果,我期望看到作为时间函数的声压。 相反,我看到很多奇怪的,神秘的符号(不是hex数字)。 有人可以请求帮助我吗?
根据来源 , scipy.io.wavfile.read(somefile)
返回一个包含两个项目的元组:第一个是每秒样本的采样率,第二个是从文件中读取所有数据的numpy
数组。 看起来很容易使用!
我今天晚上做了一些研究,发现:
import wave, struct waveFile = wave.open('sine.wav', 'r') length = waveFile.getnframes() for i in range(0,length): waveData = waveFile.readframes(1) data = struct.unpack("<h", waveData) print(int(data[0]))
希望这个片段可以帮助别人。 详细信息:使用结构模块 ,可以取波形帧(在-32768; 0x8000和32767; 0x7FFF之间为2s补码)读取MONO,16位,WAVE文件。 我发现这个网页在制定这个相当有用。
恕我直言,从声音文件中获取audio数据到NumPy数组最简单的方法是PySoundFile :
import soundfile as sf data, fs = sf.read('/usr/share/sounds/ekiga/voicemail.wav')
这也支持开箱即用的24位文件。
有很多声音文件库可用,我写了一个概述 ,你可以看到一些优点和缺点。 它还具有一个页面,解释如何使用wave
模块读取24位wav文件 。
不同的python模块来读取wav:
至less有以下这些库可以读取waveaudio文件:
- PySoundFile
- scipy.io.wavfile (来自scipy )
- 波 (读取stream,包括在python2和3)
- scikits.audiolab (似乎没有维护)
- sounddevice (播放和录制声音,适合stream和实时)
- pyglet
最简单的例子:
这是一个Pysoundfile的简单例子:
import soundfile as sf data, samplerate = sf.read('existing_file.wav')
输出格式:
警告,数据并不总是相同的格式,这取决于图书馆。 例如:
from scikits import audiolab from scipy.io import wavfile from sys import argv for filetest in argv[1:]: [x, fs, nbBits] = audiolab.wavread(filePath) print '\nReading with scikits.audiolab.wavread: ', x [fs, x] = wavfile.read(filetest) print '\nReading with scipy.io.wavfile.read: ', x
用scikits.audiolab.wavread阅读:[0。0 …,-0.00097656 -0.00079346 -0.00097656]用scipy.io.wavfile.read读取:[0 0 0 …,-32 -26 -32 ]
PySoundFile和Audiolab在-1和1之间返回float(就像matab那样,这是audio信号的约定)。 Scipy和Wave返回整数,可以根据编码的位数在float中进行转换。
例如:
from scipy.io.wavfile import read as wavread [samplerate, x] = wavread(audiofilename) # x is a numpy array of integer, representing the samples # scale to -1.0 -- 1.0 if x.dtype == 'int16': nb_bits = 16 # -> 16-bit wav files elif x.dtype == 'int32': nb_bits = 32 # -> 32-bit wav files max_nb_bit = float(2 ** (nb_bits - 1)) samples = x / (max_nb_bit + 1.0) # samples is a numpy array of float representing the samples
您可以使用scikits.audiolab模块来完成此操作。 它需要NumPy和SciPy以及libsndfile。
请注意,我只能使它在Ubunutu而不是在OSX上工作。
from scikits.audiolab import wavread filename = "testfile.wav" data, sample_frequency,encoding = wavread(filename)
现在你有了wav数据
如果你想逐块处理一个audio块,一些给定的解决scheme是相当可怕的,因为它们意味着将整个audio加载到内存中,产生许多caching未命中并放慢你的程序。 python-wavefile提供了一些Pythonic结构来进行NumPy逐块处理,使用高效和透明的块pipe理,通过生成器。 其他pythonic niceties文件的上下文pipe理器,元数据作为属性…如果你想要整个文件接口,因为你正在开发一个快速原型,你不关心效率,整个文件接口仍然存在。
一个简单的例子是:
import sys from wavefile import WaveReader, WaveWriter with WaveReader(sys.argv[1]) as r : with WaveWriter( 'output.wav', channels=r.channels, samplerate=r.samplerate, ) as w : # Just to set the metadata w.metadata.title = r.metadata.title + " II" w.metadata.artist = r.metadata.artist # This is the prodessing loop for data in r.read_iter(size=512) : data[1] *= .8 # lower volume on the second channel w.write(data)
该示例重用相同的块来读取整个文件,即使在通常小于所需大小的最后一个块的情况下也是如此。 在这种情况下,你得到一个块的一部分。 因此,请相信返回的块长度,而不是使用硬编码的512大小进行进一步处理。
如果你打算在波形数据上进行传输,那么也许你应该使用SciPy ,特别是scipy.io.wavfile
。
如果只有两个文件和采样率非常高,则可以交织它们。
from scipy.io import wavfile rate1,dat1 = wavfile.read(File1) rate2,dat2 = wavfile.read(File2) if len(dat2) > len(dat1):#swap shortest temp = dat2 dat2 = dat1 dat1 = temp output = dat1 for i in range(len(dat2)/2): output[i*2]=dat2[i*2] wavfile.write(OUTPUT,rate,dat)
我需要读取1个通道的24位WAV文件。 Nak以上的post非常有用。 不过,正如上面提到的那样, 24位的不是简单的。 我终于得到它使用以下代码片段:
from scipy.io import wavfile TheFile = 'example24bit1channelFile.wav' [fs, x] = wavfile.read(TheFile) # convert the loaded data into a 24bit signal nx = len(x) ny = nx/3*4 # four 3-byte samples are contained in three int32 words y = np.zeros((ny,), dtype=np.int32) # initialise array # build the data left aligned in order to keep the sign bit operational. # result will be factor 256 too high y[0:ny:4] = ((x[0:nx:3] & 0x000000FF) << 8) | \ ((x[0:nx:3] & 0x0000FF00) << 8) | ((x[0:nx:3] & 0x00FF0000) << 8) y[1:ny:4] = ((x[0:nx:3] & 0xFF000000) >> 16) | \ ((x[1:nx:3] & 0x000000FF) << 16) | ((x[1:nx:3] & 0x0000FF00) << 16) y[2:ny:4] = ((x[1:nx:3] & 0x00FF0000) >> 8) | \ ((x[1:nx:3] & 0xFF000000) >> 8) | ((x[2:nx:3] & 0x000000FF) << 24) y[3:ny:4] = (x[2:nx:3] & 0x0000FF00) | \ (x[2:nx:3] & 0x00FF0000) | (x[2:nx:3] & 0xFF000000) y = y/256 # correct for building 24 bit data left aligned in 32bit words
如果您需要-1和+1之间的结果,则需要一些额外的缩放比例。 也许你们中有些人可能会觉得这很有用