Чтение * .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 
PatriceG
источник
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

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

ProgJos
источник
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)
leec
источник
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 (который довольно мощный).

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

Wanaryytel
источник