在Python中读取*.wav文件

Rom*_*man 75 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
Run Code Online (Sandbox Code Playgroud)

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

Ale*_*lli 88

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

例如:

from scipy.io import wavfile
fs, data = wavfile.read('./output/audio.wav')
Run Code Online (Sandbox Code Playgroud)

  • 但它严重缺乏渠道数量.在不知道频道数量的情况下,您应该如何处理音频? (9认同)
  • @bastibe `data` 是一个二维 numpy 数组,因此 `data.shape` 返回一个 (num_samples, num_channels) 的元组 (9认同)
  • 似乎它不适用于24位文件! (4认同)
  • 这个库有用吗?我遇到了很多问题: 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: 整数除或模以零 (2认同)

nak*_*nak 60

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

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]))
Run Code Online (Sandbox Code Playgroud)

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

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

waveData = waveFile.readframes(13)
data = struct.unpack("<13h", waveData)
Run Code Online (Sandbox Code Playgroud)

  • 这给了我错误:"struct.error:unpack需要一个长度为2的字符串参数" (10认同)
  • 对于那些像我一样,想知道什么是2s互补二进制文件的人,请看http://stackoverflow.com/questions/1049722/what-is-2s-complement (3认同)
  • 如何处理 24 位立体声文件? (2认同)

Pat*_*ceG 29

用于阅读wav的不同python模块:

至少有以下这些库来读取wave音频文件:

最简单的例子:

这是Pysoundfile的一个简单示例:

import soundfile as sf
data, samplerate = sf.read('existing_file.wav') 
Run Code Online (Sandbox Code Playgroud)

输出格式:

警告,数据并不总是采用相同的格式,具体取决于库.例如:

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
Run Code Online (Sandbox Code Playgroud)

用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 
Run Code Online (Sandbox Code Playgroud)


Mat*_*ias 12

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

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

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

有很多可用的声音文件库,我写了一个概述,你可以看到一些优点和缺点.它还有一个页面,说明如何使用该wave模块读取24位wav文件.


ch3*_*0ke 9

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

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

from scikits.audiolab import wavread

filename = "testfile.wav"

data, sample_frequency,encoding = wavread(filename)
Run Code Online (Sandbox Code Playgroud)

现在你有了wav数据


vok*_*mon 5

如果您想逐块处理音频,一些给定的解决方案在某种意义上非常糟糕,它们意味着将整个音频加载到内存中,从而产生许多缓存未命中并减慢程序速度。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)
Run Code Online (Sandbox Code Playgroud)

该示例重用同一个块来读取整个文件,即使最后一个块通常小于所需大小也是如此。在这种情况下,您将获得块的一部分。因此,请相信返回的块长度,而不是使用硬编码的 512 大小进行任何进一步处理。