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

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

71 голосов
/ 14 января 2010

Мне нужно проанализировать звук, записанный в файле .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

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

Ответы [ 10 ]

76 голосов
/ 14 января 2010

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

например:

from scipy.io import wavfile
fs, data = wavfile.read('./output/audio.wav')
59 голосов
/ 12 марта 2011

Сегодня вечером я провел небольшое исследование и выяснил:

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

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

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

waveData = waveFile.readframes(13)
data = struct.unpack("<13h", waveData)
26 голосов
/ 03 ноября 2014

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

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

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

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

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 filetest in argv[1:]:
    [x, fs, nbBits] = audiolab.wavread(filePath)
    print '\nReading with scikits.audiolab.wavread: ', x
    [fs, x] = wavfile.read(filetest)
    print '\nReading with scipy.io.wavfile.read: ', x

Чтение с scikits.audiolab.wavread: [0. 0. 0. ..., -0.00097656 -0.00079346 -0,00097656] Чтение с scipy.io.wavfile.read: [0 0 0 ..., -32 -26 -32]

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

Например:

from scipy.io.wavfile import read as wavread
[samplerate, x] = wavread(audiofilename) # x is a numpy array of integer, 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.0) # samples is a numpy array of float representing the samples 
12 голосов
/ 17 сентября 2015

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

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

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

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

8 голосов
/ 18 июня 2011

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

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

from scikits.audiolab import wavread

filename = "testfile.wav"

data, sample_frequency,encoding = wavread(filename)

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

4 голосов
/ 16 сентября 2014

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

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

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 голос
/ 14 июня 2015

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

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

1 голос
/ 14 января 2010

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

0 голосов
/ 27 января 2018

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

0 голосов
/ 23 августа 2013

если его всего два файла и частота дискретизации значительно высока, вы можете просто чередовать их.

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