Чтение * .wav файлов в Python


90

Мне нужно проанализировать звук, записанный в файле .wav. Для этого мне нужно преобразовать этот файл в набор чисел (например, в массивы). Думаю, мне нужно использовать волновой пакет. Однако я не знаю, как именно это работает. Например, я сделал следующее:

import wave
w = wave.open('/usr/share/sounds/ekiga/voicemail.wav', 'r')
for i in range(w.getnframes()):
    frame = w.readframes(i)
    print frame

В результате этого кода я ожидал увидеть звуковое давление как функцию времени. Напротив, я вижу много странных, загадочных символов (которые не являются шестнадцатеричными числами). Кто-нибудь может мне с этим помочь?

Ответы:


110

Согласно документации , scipy.io.wavfile.read(somefile)возвращает кортеж из двух элементов: первый - это частота дискретизации в выборках в секунду, второй - это numpyмассив со всеми данными, считанными из файла:

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

Вы можете комбинировать это с инструментами преобразования командной строки, чтобы открывать другие форматы.
— Эндолит

11
Правда, количества каналов не хватает. Как вы должны работать со звуком, не зная количества каналов?
— Bastibe 02

вызывает на моем компьютере какие-то странные ошибки при распаковке структуры. Я думаю, что он использует struct.unpack ('<i', data) вместо struct.unpack ('<h', data) nak, используемого ниже.
— Alex S

1
Эта библиотека работает? Я столкнулся с рядом проблем: 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: целочисленное деление или по модулю на ноль
— Финн Оруп Нильсен,

6
@bastibe dataявляется NumPy массив 2-D так , data.shapeвозвращает кортеж (num_samples, num_channels)
— варочные панели

63

Используя structмодуль , вы можете взять кадры волны (которые находятся в дополнительном двоичном коде 2 между -32768 и 32767 (т.е. 0x8000и 0x7FFF). Он читает файл MONO, 16-BIT, WAVE. Я нашел эту веб-страницу весьма полезной для формулировки этого:

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

Этот фрагмент читает 1 кадр. Чтобы прочитать более одного кадра (например, 13), используйте

wavedata = wavefile.readframes(13)
data = struct.unpack("<13h", wavedata)

2
как обрабатывать 24-битные стерео файлы?
— Basj

14
это дает мне ошибку: «struct.error: unpack требует строкового аргумента длины 2»
— Coder404,

1
Если вы запустите этот фрагмент кода с очень большим аудиофайлом. Ваш компьютер выйдет из строя из-за того, что этой программе не хватает памяти. Необходимо обрабатывать аудиофайл по
— блокам

@ Coder404 У вас, вероятно, есть файл стереофонической волны или другая битовая глубина.
— jmilloy

3
Для тех, кто, как и я, задается вопросом, что такое дополнительный двоичный файл 2s, см. Здесь stackoverflow.com/questions/1049722/what-is-2s-complement
— Деннис Голомазов

34

Различные модули Python для чтения wav:

Для чтения аудиофайлов в формате wave есть как минимум следующие библиотеки:

Самый простой пример:

Это простой пример с SoundFile:

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 filepath in argv[1:]:
    x, fs, nb_bits = audiolab.wavread(filepath)
    print('Reading with scikits.audiolab.wavread:', x)
    fs, x = wavfile.read(filepath)
    print('Reading with scipy.io.wavfile.read:', x)

Выход:

Reading with scikits.audiolab.wavread: [ 0.          0.          0.         ..., -0.00097656 -0.00079346 -0.00097656]
Reading with scipy.io.wavfile.read: [  0   0   0 ..., -32 -26 -32]

SoundFile и Audiolab возвращают значения с плавающей запятой между -1 и 1 (как и matab, это соглашение для аудиосигналов). Scipy и wave возвращают целые числа, которые вы можете преобразовать в числа с плавающей запятой в соответствии с количеством бит кодирования, например:

from scipy.io.wavfile import read as wavread
samplerate, x = wavread(audiofilename)  # x is a numpy array of integers, 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)  # samples is a numpy array of floats representing the samples 

14

IMHO, самый простой способ получить аудиоданные из звукового файла в массив NumPy - это SoundFile :

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

Это также поддерживает 24-битные файлы из коробки.

Доступно множество библиотек звуковых файлов, я написал обзор, в котором вы можете увидеть несколько плюсов и минусов. На нем также есть страница, объясняющая, как читать 24-битный файл WAV с помощью waveмодуля .


Примечание: soundfile.read () нормализуется на 2 ^ (n_bits - 1), как в примере sandoval scipy.io.wavfile
— Quetzalcoatl

9

Вы можете сделать это с помощью модуля scikits.audiolab . Для работы требуется NumPy и SciPy, а также libsndfile.

Обратите внимание, мне удалось заставить его работать только на Ubunutu, но не на OSX.

from scikits.audiolab import wavread

filename = "testfile.wav"

data, sample_frequency,encoding = wavread(filename)

Теперь у вас есть данные wav


scikits.audiolabне обновлялся с 2010 года и, вероятно, это только Python 2.
— Борис

4

Если вы хотите обрабатывать аудио блок за блоком, некоторые из данных решений довольно ужасны в том смысле, что они подразумевают загрузку всего аудио в память, вызывая множество промахов кеша и замедляя вашу программу. python-wavefile предоставляет некоторые питонические конструкции для поблочной обработки NumPy с использованием эффективного и прозрачного управления блоками с помощью генераторов. Другие тонкости Python - это менеджер контекста для файлов, метаданные как свойства ... и если вам нужен весь файловый интерфейс, потому что вы разрабатываете быстрый прототип и вам не важна эффективность, весь файловый интерфейс все еще существует.

Простой пример обработки:

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 для дальнейшей обработки.


1

Если вы собираетесь выполнять передачу данных формы сигнала, возможно, вам следует использовать SciPy , в частности scipy.io.wavfile.


2
ОК. Я только что установил SciPy, но не могу найти ни одного примера использования scipy.io.wavfile.
— Роман

6
Нет ничего лучше интерактивного интерпретатора для понимания того, как все работает! Будь амбициозным!
— Игнасио Васкес-Абрамс,

1

Мне нужно было прочитать 1-канальный 24-битный WAV файл. Сообщение Нака выше было очень полезным. Однако, как упоминалось выше, с помощью basj 24-bit не так просто. Наконец-то я заставил его работать, используя следующий фрагмент:

from scipy.io import wavfile
TheFile = 'example24bit1channelFile.wav'
[fs, x] = wavfile.read(TheFile)

# convert the loaded data into a 24bit signal

nx = len(x)
ny = nx/3*4    # four 3-byte samples are contained in three int32 words

y = np.zeros((ny,), dtype=np.int32)    # initialise array

# build the data left aligned in order to keep the sign bit operational.
# result will be factor 256 too high

y[0:ny:4] = ((x[0:nx:3] & 0x000000FF) << 8) | \
  ((x[0:nx:3] & 0x0000FF00) << 8) | ((x[0:nx:3] & 0x00FF0000) << 8)
y[1:ny:4] = ((x[0:nx:3] & 0xFF000000) >> 16) | \
  ((x[1:nx:3] & 0x000000FF) << 16) | ((x[1:nx:3] & 0x0000FF00) << 16)
y[2:ny:4] = ((x[1:nx:3] & 0x00FF0000) >> 8) | \
  ((x[1:nx:3] & 0xFF000000) >> 8) | ((x[2:nx:3] & 0x000000FF) << 24)
y[3:ny:4] = (x[2:nx:3] & 0x0000FF00) | \
  (x[2:nx:3] & 0x00FF0000) | (x[2:nx:3] & 0xFF000000)

y = y/256   # correct for building 24 bit data left aligned in 32bit words

Некоторое дополнительное масштабирование требуется, если вам нужны результаты от -1 до +1. Возможно, некоторые из вас найдут это полезным


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)

0

Вы также можете использовать простую import wavioбиблиотеку. Вам также необходимо иметь некоторые базовые знания о звуке.


0

PyDub ( http://pydub.com/ ) не упоминается, и это следует исправить. ИМО, это самая полная библиотека для чтения аудиофайлов на 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 может обрабатывать множество различных форматов из коробки. Предостережение заключается в том, что он основан как на собственной поддержке wav Python, так и на ffmpeg, поэтому вам необходимо установить ffmpeg, а многие возможности pydub полагаются на версию ffmpeg. Обычно, если это умеет ffmpeg, то может и pydub (который довольно мощный).

Отсутствие отказа от ответственности: я не имею отношения к проекту, но я активный пользователь.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.