在Python中读取* .wav文件


90

我需要分析写入.wav文件的声音。为此,我需要将此文件转换为一组数字(例如,数组)。我想我需要使用wave包。但是,我不知道它是如何工作的。例如,我做了以下工作:

import wave
w = wave.open('/usr/share/sounds/ekiga/voicemail.wav', 'r')
for i in range(w.getnframes()):
    frame = w.readframes(i)
    print frame

作为此代码的结果,我希望将声压视为时间的函数。相比之下,我看到了很多奇怪的神秘符号(不是十六进制数字)。有人可以请我帮忙吗?

Answers:


108

根据文档scipy.io.wavfile.read(somefile)返回两个项目的元组:第一个是每秒采样数采样率,第二个是包含numpy从文件读取的所有数据的数组:

from scipy.io import wavfile
samplerate, data = wavfile.read('./output/audio.wav')

您可以将其与命令行转换工具结合使用以打开其他格式。
endlith 2010年

11
但是它严重缺乏渠道数量。您应该如何在不知道频道数的情况下使用音频?
bastibe 2011年

在我的计算机上引发一些奇怪的struct unpacking错误。我认为它使用的是struct.unpack('<i',data)而不是下面使用的struct.unpack('<h',data)nak。
Alex S

1
这个图书馆有效吗?我遇到了许多问题:scipy.io.wavfile.read('/ usr / lib / python2.7 / dist-packages / pygame / examples / data / house_lo.wav')->无数据。scipy.io.wavfile.read('/ usr / lib / python2.7 / dist-packages / pygame / examples / data / secosmic_lo.wav')-> ZeroDivisionError:整数除法或取模为零
FinnÅrupNielsen

6
@bastibedata是一个二维numpy数组,因此data.shape返回一个(num_samples,num_channels)个元组
滚刀

63

使用该struct模块,您可以获取波形帧(它们是-32768和32767之间的2的互补二进制数(即0x80000x7FFF)。它读取一个MONO,16位WAVE文件。我发现此网页在公式化方面非常有用:

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]))

该代码段读取1帧。要读取多个帧(例如13个),请使用

wavedata = wavefile.readframes(13)
data = struct.unpack("<13h", wavedata)

2
如何处理24位立体声文件?
Basj 2013年

12
这给了我错误:“ struct.error:解压缩需要一个长度为2的字符串参数”
Coder404 2014年

1
如果您使用很大的音频文件运行这段代码。由于该程序需要内存,因此您的计算机将被淘汰。需要针对大音频文件逐块处理音频文件
ArthurLambert 2015年

@ Coder404您可能有一个立体声波文件,或不同的位深度。
jmilloy

3
对于那些像我一样,想知道什么是2s补码二进制的人,请参见此处stackoverflow.com/questions/1049722/what-is-2s-complement
Dennis Golomazov

34

读取wav的不同Python模块:

至少有以下这些库可以读取Wave音频文件:

最简单的例子:

这是SoundFile的一个简单示例:

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 filepath in argv[1:]:
    x, fs, nb_bits = audiolab.wavread(filepath)
    print('Reading with scikits.audiolab.wavread:', x)
    fs, x = wavfile.read(filepath)
    print('Reading with scipy.io.wavfile.read:', x)

输出:

Reading with scikits.audiolab.wavread: [ 0.          0.          0.         ..., -0.00097656 -0.00079346 -0.00097656]
Reading with scipy.io.wavfile.read: [  0   0   0 ..., -32 -26 -32]

SoundFile和Audiolab返回的浮点数介于-1和1之间(就像matab一样,这是音频信号的约定)。Scipy和wave返回整数,您可以根据编码的位数将其转换为浮点数,例如:

from scipy.io.wavfile import read as wavread
samplerate, x = wavread(audiofilename)  # x is a numpy array of integers, 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)  # samples is a numpy array of floats representing the samples 

14

恕我直言,将声音数据从声音文件导入NumPy数组的最简单方法是SoundFile

import soundfile as sf
data, fs = sf.read('/usr/share/sounds/ekiga/voicemail.wav')

这也支持开箱即用的24位文件。

有许多可用的声音文件库,我写了一个概述,您可以在其中看到一些优点和缺点。它还具有介绍如何使用wave模块读取24位wav文件的页面


注意:soundfile.read()通过2 ^(n_bits-1)进行归一化,如sandoval的scipy.io.wavfile示例
Quetzalcoatl

9

您可以使用scikits.audiolab模块完成此操作。它需要NumPy和SciPy才能运行,还需要libsndfile。

请注意,我只能使其在Ubunutu上工作,而不能在OSX上工作。

from scikits.audiolab import wavread

filename = "testfile.wav"

data, sample_frequency,encoding = wavread(filename)

现在您有了wav数据


scikits.audiolab自2010年以来未进行过更新,可能只有Python 2。
鲍里斯(Boris)

4

如果要逐块处理音频,则某些给定的解决方案在某种意义上是非常糟糕的,因为它们暗示将整个音频加载到内存中,从而产生许多高速缓存未命中并降低程序速度。python-wavefile提供了一些pythonic构造,可通过生成器使用高效且透明的块管理来进行NumPy逐块处理。其他pythonic的优点是文件的上下文管理器,作为属性的元数据...,如果您想要整个文件接口,因为您正在开发一个快速的原型并且不关心效率,那么整个文件接口仍然存在。

一个简单的处理示例为:

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大小用于任何进一步的处理。



1

我需要读取一个1通道的24位WAV文件。Nak的上述帖子非常有用。但是,如上所述,basj 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之间,则需要一些额外的缩放比例。也许有些人可能会觉得这很有用


0

如果只有两个文件且采样率很高,则可以将它们交织。

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)

0

您还可以使用简单的import wavio库,还需要对声音有一些基本的了解。


0

PyDubhttp://pydub.com/)尚未提及,应予以解决。IMO这是目前用于读取Python中音频文件的最全面的库,尽管并非没有缺点。读取wav文件:

from pydub import AudioSegment

audio_file = AudioSegment.from_wav('path_to.wav')
# or
audio_file = AudioSegment.from_file('path_to.wav')

# do whatever you want with the audio, change bitrate, export, convert, read info, etc.
# Check out the API docs http://pydub.com/

PS。该示例是关于读取wav文件的,但是PyDub可以开箱即用地处理多种格式。需要注意的是,它基于本机Python wav支持和ffmpeg,因此您必须安装ffmpeg,并且许多pydub功能都依赖于ffmpeg版本。通常,如果ffmpeg可以做到,那么pydub也可以(功能非常强大)。

免责声明:我与该项目无关,但是我是一个沉重的用户。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.