将声音文件作为NumPy数组导入Python(audiolab的替代品)

end*_*ith 11 python audio numpy scipy

我过去一直在使用Audiolab导入声音文件,而且效果很好.然而:

-

In [2]: from scikits import audiolab
--------------------------------------------------------------------

ImportError                               Traceback (most recent call last)

C:\Python26\Scripts\<ipython console> in <module>()

C:\Python26\lib\site-packages\scikits\audiolab\__init__.py in <module>()
     23 __version__ = _version
     24
---> 25 from pysndfile import formatinfo, sndfile
     26 from pysndfile import supported_format, supported_endianness, \
     27                       supported_encoding, PyaudioException, \

C:\Python26\lib\site-packages\scikits\audiolab\pysndfile\__init__.py in <module>()
----> 1 from _sndfile import Sndfile, Format, available_file_formats, available_encodings
      2 from compat import formatinfo, sndfile, PyaudioException, PyaudioIOError
      3 from compat import supported_format, supported_endianness, supported_encoding

ImportError: DLL load failed: The specified module could not be found.``
Run Code Online (Sandbox Code Playgroud)

所以我想要:

  • 找出为什么它不能在2.6中工作(_sndfile.pyd出错?)并且可能找到一种方法来扩展它以使用不支持的格式
  • 找到完整的audiolab替代品

Ste*_*joa 11

Audiolab正在使用Python 2.6.2在Ubuntu 9.04上为我工作,所以它可能是一个Windows问题.在您的论坛链接中,作者还建议它是Windows错误.

在过去,这个选项对我也有用:

from scipy.io import wavfile
fs, data = wavfile.read(filename)
Run Code Online (Sandbox Code Playgroud)

请注意,data可能有int数据类型,因此它不会在[-1,1]范围内缩放.例如,如果dataint16,你必须把data通过2**15为[-1,1)内规模.


tra*_*avc 5

Sox http://sox.sourceforge.net/可以成为你的朋友.它可以读取许多不同的格式,并以您喜欢的任何数据类型将其输出为raw.实际上,我只是编写代码来将一个数据块从一个音频文件读入一个numpy数组.

我决定采用这种方式实现可移植性(sox可以广泛使用)并最大限度地提高我可以使用的输入音频类型的灵活性.实际上,从最初的测试来看,它对于我正在使用它的速度并没有明显变慢......这是从很长(小时)的文件中读取短(几秒)的音频.

你需要的变量:

SOX_EXEC # the sox / sox.exe executable filename
filename # the audio filename of course
num_channels # duh... the number of channels
out_byps # Bytes per sample you want, must be 1, 2, 4, or 8

start_samp # sample number to start reading at
len_samp   # number of samples to read
Run Code Online (Sandbox Code Playgroud)

实际的代码非常简单.如果要提取整个文件,可以删除start_samp,len_samp和'trim'.

import subprocess # need the subprocess module
import numpy as NP # I'm lazy and call numpy NP

cmd = [SOX_EXEC,
       filename,              # input filename
       '-t','raw',            # output file type raw
       '-e','signed-integer', # output encode as signed ints
       '-L',                  # output little endin
       '-b',str(out_byps*8),  # output bytes per sample
       '-',                   # output to stdout
       'trim',str(start_samp)+'s',str(len_samp)+'s'] # only extract requested part 

data = NP.fromstring(subprocess.check_output(cmd),'<i%d'%(out_byps))
data = data.reshape(len(data)/num_channels, num_channels) # make samples x channels
Run Code Online (Sandbox Code Playgroud)

PS:这是使用sox从音频文件头读取内容的代码...

    info = subprocess.check_output([SOX_EXEC,'--i',filename])
    reading_comments_flag = False
    for l in info.splitlines():
        if( not l.strip() ):
            continue
        if( reading_comments_flag and l.strip() ):
            if( comments ):
                comments += '\n'
            comments += l
        else:
            if( l.startswith('Input File') ):
                input_file = l.split(':',1)[1].strip()[1:-1]
            elif( l.startswith('Channels') ):
                num_channels = int(l.split(':',1)[1].strip())
            elif( l.startswith('Sample Rate') ):
                sample_rate = int(l.split(':',1)[1].strip())
            elif( l.startswith('Precision') ):
                bits_per_sample = int(l.split(':',1)[1].strip()[0:-4])
            elif( l.startswith('Duration') ):
                tmp = l.split(':',1)[1].strip()
                tmp = tmp.split('=',1)
                duration_time = tmp[0]
                duration_samples = int(tmp[1].split(None,1)[0])
            elif( l.startswith('Sample Encoding') ):
                encoding = l.split(':',1)[1].strip()
            elif( l.startswith('Comments') ):
                comments = ''
                reading_comments_flag = True
            else:
                if( other ):
                    other += '\n'+l
                else:
                    other = l
                if( output_unhandled ):
                    print >>sys.stderr, "Unhandled:",l
                pass
Run Code Online (Sandbox Code Playgroud)

  • 我会看看 pysox...谢谢。虽然使用 sox 的子进程方法并不是真正的 Pythonic 或漂亮,但它非常强大并且相对可移植(因为大多数系统都可以找到 sox 二进制文件/安装程序)。 (2认同)

Vin*_*ume 5

FFmpeg支持mp3,并且可以在Windows上运行(http://zulko.github.io/blog/2013/10/04/read-and-write-audio-files-in-python-using-ffmpeg/)。

读取mp3档案:

import subprocess as sp

FFMPEG_BIN = "ffmpeg.exe"

command = [ FFMPEG_BIN,
        '-i', 'mySong.mp3',
        '-f', 's16le',
        '-acodec', 'pcm_s16le',
        '-ar', '44100', # ouput will have 44100 Hz
        '-ac', '2', # stereo (set to '1' for mono)
        '-']
pipe = sp.Popen(command, stdout=sp.PIPE, bufsize=10**8)
Run Code Online (Sandbox Code Playgroud)

将数据格式化为numpy数组:

raw_audio = pipe.proc.stdout.read(88200*4)

import numpy

audio_array = numpy.fromstring(raw_audio, dtype="int16")
audio_array = audio_array.reshape((len(audio_array)/2,2))
Run Code Online (Sandbox Code Playgroud)


end*_*ith 2

我最近一直在使用PySoundFile而不是 Audiolab。它可以轻松安装conda

像大多数东西一样,它不支持 mp3 。MP3不再有专利,所以没有理由不支持;有人只需要将支持写入 libsndfile 即可