Импорт звуковых файлов в Python в виде массивов NumPy (альтернативы audiolab)

Раньше я использовал 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.``

Поэтому я бы хотел:

  • Выясните, почему он не работает в версии 2.6 (что-то не так с _sndfile.pyd?) И, возможно, найдите способ расширить его для работы с неподдерживаемыми форматами
  • Найдите полную замену для audiolab

person endolith    schedule 01.03.2010    source источник
comment
Проблема характерна для python 2.6 в Windows (т.е. вы не увидите ее на python 2.5). Я пока не нашел способ исправить это   -  person David Cournapeau    schedule 22.07.2010
comment
И, наконец, я взял паузу между двумя рейсами, и это закончилось ошибкой mingw. Я опубликовал новую версию 0.11.0, которая должна исправить эту проблему.   -  person David Cournapeau    schedule 23.07.2010
comment
Дэвид, вы сделали в аудиолаборатории замечательный инструмент! Я часто им пользуюсь. Спасибо.   -  person Steve Tjoa    schedule 25.07.2010


Ответы (5)


Audiolab работает для меня над Ubuntu 9.04 с Python 2.6.2, так что это может быть проблема Windows. В вашей ссылке на форум автор также предполагает, что это ошибка Windows.

Раньше у меня тоже работала эта опция:

from scipy.io import wavfile
fs, data = wavfile.read(filename)

Просто помните, что data может иметь тип данных int, поэтому он не масштабируется в пределах [-1,1). Например, если data равно int16, необходимо разделить data на 2**15 для масштабирования в пределах [-1,1).

person Steve Tjoa    schedule 01.03.2010
comment
Я не уверен в этом. 16- или 32-битное должно быть хорошо, но я не знаю о 24-битном. - person Steve Tjoa; 02.03.2010
comment
Он почти ничего не читает. Даже 16-битные файлы получаются перевернутыми с ошибками зацикливания для значения -1. 24-битный получает TypeError: тип данных не понят. Наверняка есть что-то получше ... - person endolith; 09.03.2010
comment
Можете ли вы опубликовать файл, в котором возникает эта ошибка? Кроме того, правильно ли проходит набор тестов (scikits.audiolab.test ())? audiolab использует libsndfile, которая на сегодняшний день является лучшей и самой надежной библиотекой ввода-вывода аудио, которую я знаю. Конечно, может быть ошибка в самой аудиолаборатории. - person David Cournapeau; 22.07.2010
comment
Сейчас я не вижу ошибки обертывания, но это была ошибка scipy.io, а не audiolab. - person endolith; 29.07.2010

Sox http://sox.sourceforge.net/ может быть вашим другом в этом. Он может читать много разных форматов и выводить их как сырые в любом типе данных, который вы предпочитаете. Фактически, я просто написал код для чтения блока данных из аудиофайла в массив 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

Фактический код действительно прост. Если вы хотите извлечь весь файл, вы можете удалить элементы 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

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
person travc    schedule 21.03.2012
comment
Интересно, хоть и неуклюже, а может, и не кроссплатформенно? Существует pysox для непосредственного взаимодействия с libSoX. Похоже, SoX поддерживает несколько форматов самостоятельно и может использовать несколько других библиотек для большего. У меня было много проблем с тем, чтобы заставить работать audiolab, и он не поддерживает MP3 и т. Д., Так что pysox, возможно, стоит попробовать. - person endolith; 21.03.2012
comment
Посмотрю на pysox ... спасибо. Хотя подпроцессный подход с использованием sox на самом деле не питонический или симпатичный, он очень мощный и относительно переносимый (поскольку двоичные файлы / установщики sox можно найти для большинства систем). - person travc; 21.04.2012

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)

Отформатируйте данные в массив 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))
person Vincent Berthiaume    schedule 01.06.2016

Если вы хотите сделать это для MP3

Вот что я использую: он использует pydub и scipy.

Полная настройка (на Mac может отличаться в других системах):

import tempfile
import os
import pydub
import scipy
import scipy.io.wavfile


def read_mp3(file_path, as_float = False):
    """
    Read an MP3 File into numpy data.
    :param file_path: String path to a file
    :param as_float: Cast data to float and normalize to [-1, 1]
    :return: Tuple(rate, data), where
        rate is an integer indicating samples/s
        data is an ndarray(n_samples, 2)[int16] if as_float = False
            otherwise ndarray(n_samples, 2)[float] in range [-1, 1]
    """

    path, ext = os.path.splitext(file_path)
    assert ext=='.mp3'
    mp3 = pydub.AudioSegment.from_mp3(file_path)
    _, path = tempfile.mkstemp()
    mp3.export(path, format="wav")
    rate, data = scipy.io.wavfile.read(path)
    os.remove(path)
    if as_float:
        data = data/(2**15)
    return rate, data

Кредит на блог Джеймса Томпсона

person Peter    schedule 26.02.2018
comment
Вам нужно os.close(_) (и, возможно, переименовать _ в fd), чтобы закрыть дескриптор временного файла. В противном случае при запуске в цикле for вы в конечном итоге получите [Errno 24] Too many open files. - person Matthew D. Scholefield; 08.08.2018
comment
Вместо того, чтобы экспортировать в файл wav и перезагружать его с помощью scipy, вы можете напрямую преобразовать его в массив numpy: data = np.reshape(mp3.get_array_of_samples(), (-1, 2)). - person Feodoran; 03.12.2019
comment
что происходит с file_path и FILEPATH? - person cardamom; 24.06.2020

В последнее время я использую PySoundFile вместо Audiolab. Легко устанавливается с conda.

Он не поддерживает mp3, как и большинство других вещей. MP3 больше не запатентован, поэтому нет причин, по которым он не может его поддерживать; кому-то просто нужно записать поддержку в libsndfile.

person endolith    schedule 26.02.2018