使用Python读取wav文件的最简单方法是什么[总结]?

9 投票
8 回答
35022 浏览
提问于 2025-04-15 18:01

我想用Python来读取一个wav文件,并把它的内容写成可以分析的形式(比如说数组)。

  1. 我听说“audiolab”是一个合适的工具(它可以把numpy数组转换成wav文件,反之亦然)。
  2. 我安装了“audiolab”,但遇到了numpy版本的问题(我无法使用“from numpy.testing import Tester”)。我当时的numpy版本是1.1.1。
  3. 我安装了一个更新的numpy版本(1.4.0)。但是我又遇到了新的错误:

    错误追踪(最近的调用在最前面): 文件 "test.py",第7行,
    import scikits.audiolab
    文件 "/usr/lib/python2.5/site-packages/scikits/audiolab/init.py",第25行,
    from pysndfile import formatinfo, sndfile
    文件 "/usr/lib/python2.5/site-packages/scikits/audiolab/pysndfile/init.py",第1行,
    from _sndfile import Sndfile, Format, available_file_formats, available_encodings
    文件 "numpy.pxd",第30行,在 scikits.audiolab.pysndfile._sndfile (scikits/audiolab/pysndfile/_sndfile.c:9632)
    ValueError: numpy.dtype似乎不是正确的类型对象

  4. 我放弃了使用audiolab,想用“wave”包来读取wav文件。我问了这个问题,但大家推荐我用scipy。好吧,我决定专注于scipy(我有0.6.0版本)。

  5. 但是当我尝试以下操作时:

    from scipy.io import wavfile
    x = wavfile.read('/usr/share/sounds/purple/receive.wav')

我得到了以下内容:

Traceback (most recent call last):
  File "test3.py", line 4, in <module>
    from scipy.io import wavfile
  File "/usr/lib/python2.5/site-packages/scipy/io/__init__.py", line 23, in <module>
    from numpy.testing import NumpyTest
ImportError: cannot import name NumpyTest
  1. 所以,我放弃了使用scipy。我可以只用wave包吗?我不需要太多。我只需要把wav文件的内容转换成人类可读的格式,然后我再想办法处理。

8 个回答

5

这对我来说已经足够好了

import numpy as np
x = np.fromfile(open('song.wav'),np.int16)[24:]

它会忽略前面24个值,因为那些不是音频数据,而是文件的头部信息。

另外,如果这个文件是立体声的,你的声道会交替出现索引。所以我通常会先用Audacity把它转换成单声道。

8

我写了一个简单的工具,封装了标准库中的wave模块。这个工具叫做 pydub,它有一个方法可以把音频数据中的样本读取为整数。

>>> from pydub import AudioSegment
>>> song = AudioSegment.from_wav("your_song.wav")
<pydub.audio_segment.AudioSegment at 0x1068868d0>

>>> # This song is stereo
>>> song.channels
2

>>> # get the 5000th "frame" in the song
>>> frame = song.get_frame(5000)

>>> sample_left, sample_right = frame[:2], frame[2:]
>>> def sample_to_int(sample): 
        return int(sample.encode("hex"), 16)

>>> sample_to_int(sample_left)
8448

>>> sample_to_int(sample_right)
9984

希望这对你有帮助。

13

你试过使用wave模块吗?这个模块的依赖性比较少:

http://docs.python.org/library/wave.html

def everyOther (v, offset=0):
   return [v[i] for i in range(offset, len(v), 2)]

def wavLoad (fname):
   wav = wave.open (fname, "r")
   (nchannels, sampwidth, framerate, nframes, comptype, compname) = wav.getparams ()
   frames = wav.readframes (nframes * nchannels)
   out = struct.unpack_from ("%dh" % nframes * nchannels, frames)

   # Convert 2 channles to numpy arrays
   if nchannels == 2:
       left = array (list (everyOther (out, 0)))
       right = array (list  (everyOther (out, 1)))
   else:
       left = array (out)
       right = left

撰写回答