在Python中读取* .wav文件

时间:2010-01-13 22:03:29

标签: python audio wav wave

我需要分析写在.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

作为此代码的结果,我希望看到声压是时间的函数。相反,我看到很多奇怪的,神秘的符号(不是十六进制数字)。任何人,请求,帮助我吗?

12 个答案:

答案 0 :(得分:72)

the sourcesscipy.io.wavfile.read(somefile)返回两个元组的元组:第一个是每秒样本的采样率,第二个是numpy数组,其中包含从中读取的所有数据文件。看起来很容易使用!

e.g:

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

答案 1 :(得分:56)

我今天晚上做了一些研究并想出了这个:

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

希望这段代码可以帮助某人。 细节: 使用struct module,您可以获取波形帧(在-32768之间的2s互补二进制; 0x8000和32767; 0x7FFF)这将读取MONO,16位,WAVE文件。 我发现this webpage在制定这个问题时非常有用。

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

waveData = waveFile.readframes(13)
data = struct.unpack("<13h", waveData)

答案 2 :(得分:26)

阅读wav的不同python模块:

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

最简单的例子:

这是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. ..., - 0.00097656 -0.00079346  -0.00097656] 使用scipy.io.wavfile.read读取:[0 0 0 ..., - 32 -26 -32]

PySoundFile和Audiolab在-1和1之间返回浮点数(如matab那样,这是音频信号的惯例)。 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 

答案 3 :(得分:12)

恕我直言,将声音文件中的音频数据转换为NumPy数组的最简单方法是PySoundFile

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

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

有很多可用的声音文件库,我写了an overview,你可以看到一些优点和缺点。 它还有一个解释how to read a 24-bit wav file with the wave module的页面。

答案 4 :(得分:8)

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

注意,我只能让它在Ubunutu上运行而不是在OSX上运行。

from scikits.audiolab import wavread

filename = "testfile.wav"

data, sample_frequency,encoding = wavread(filename)

现在你有了wav数据

答案 5 :(得分: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大小进行任何进一步处理。

答案 6 :(得分:1)

如果您要对波形数据执行传输,那么您可能应该使用SciPy,特别是scipy.io.wavfile

答案 7 :(得分:1)

我需要读取1通道24位WAV文件。 Nak上面的帖子非常有用。但是,如上所述,basj 24位并不简单。我终于使用以下代码片段了解它:

<script type="text/javascript"
    src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>

如果需要-1到+1之间的结果,则需要一些额外的缩放。也许你们中的一些人可能会发现这个有用的

答案 8 :(得分: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)

答案 9 :(得分:0)

你也可以使用简单的import wavio库你也需要有一些基本的声音知识。

答案 10 :(得分: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也可以(功能非常强大)。

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

答案 11 :(得分:0)

这是使用内置波模块 [1] 的 Python 3 解决方案,适用于 n 个通道和 8、16、24...位。

import sys
import wave

def read_wav(path):
    with wave.open(path, "rb") as wav:
        nchannels, sampwidth, framerate, nframes, _, _ = wav.getparams()
        print(wav.getparams(), "\nBits per sample =", sampwidth * 8)

        signed = sampwidth > 1  # 8 bit wavs are unsigned
        byteorder = sys.byteorder  # wave module uses sys.byteorder for bytes

        values = []  # e.g. for stereo, values[i] = [left_val, right_val]
        for _ in range(nframes):
            frame = wav.readframes(1)  # read next frame
            channel_vals = []  # mono has 1 channel, stereo 2, etc.
            for channel in range(nchannels):
                as_bytes = frame[channel * sampwidth: (channel + 1) * sampwidth]
                as_int = int.from_bytes(as_bytes, byteorder, signed=signed)
                channel_vals.append(as_int)
            values.append(channel_vals)

    return values, framerate

您可以将结果转换为 NumPy 数组。

import numpy as np

data, rate = read_wav(path)
data = np.array(data)

注意,我试图让它可读而不是快速。我发现一次读取所有数据的速度几乎快了 2 倍。例如

with wave.open(path, "rb") as wav:
    nchannels, sampwidth, framerate, nframes, _, _ = wav.getparams()
    all_bytes = wav.readframes(-1)

framewidth = sampwidth * nchannels
frames = (all_bytes[i * framewidth: (i + 1) * framewidth]
            for i in range(nframes))

for frame in frames:
    ...

虽然 python-soundfile 大约快了 2 个数量级(很难用纯 CPython 达到这个速度)。

[1] https://docs.python.org/3/library/wave.html