Читання файлів * .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.03.11

видає деякі дивні помилки розпакування структури на моєму комп'ютері. Я думаю, що він використовує struct.unpack ('<i', data) замість struct.unpack ('<h', data) nak, який використовується нижче.
Alex S 02

1
Чи працює ця бібліотека? Я стикаюся з низкою проблем: scipy.io.wavfile.read ('/ usr / lib / python2.7 / dist-package / pygame / examples / data / house_lo.wav') -> Немає даних. scipy.io.wavfile.read ('/ usr / lib / python2.7 / dist-package / 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-бітні стереофайли?
Бас

14
це призводить до помилки: "struct.error: для розпакування потрібен аргумент рядка довжиною 2"
Coder404,

1
Якщо запустити цей фрагмент коду з дуже великим звуковим файлом. Ваш комп'ютер загине через необхідність цієї програми в пам'яті. Потрібно обробити аудіофайл блоком для великого аудіофайлу
ArthurLambert,

@ Coder404 У вас, ймовірно, є файл стерео хвилі або інша бітова глибина.
jmilloy

3
Для тих , хто, як я, цікаво , що 2s доповнюють бінарне, дивіться тут stackoverflow.com/questions/1049722/what-is-2s-complement
Денніс Голомазов

34

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

Існують принаймні такі бібліотеки для зчитування хвильових аудіофайлів:

  • SoundFile
  • scipy.io.wavfile (від scipy )
  • хвиля (для читання потоків. Входить до складу Python 2 та 3)
  • scikits.audiolab (не підтримується з 2010 р.)
  • звуковий пристрій (відтворювати та записувати звуки, добре для потоків та в реальному часі)
  • піглет
  • librosa (аналіз музики та звуку)
  • мадам (сильна увага до завдань пошуку музичної інформації (MIR))

Найпростіший приклад:

Це простий приклад із 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 і цілі числа з хвильовим поверненням, які ви можете перетворити в плаваючі залежно від кількості бітів кодування, наприклад:

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), як у прикладі scipy.io.wavfile Сандовала
Кетцалькоатль,

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, використовуючи ефективне та прозоре управління блоками за допомогою генераторів. Інші пітонічні приємності - це контекстний менеджер для файлів, метадані як властивості ... і якщо вам потрібен цілий інтерфейс файлу, оскільки ви розробляєте швидкий прототип і вам не важлива ефективність, весь інтерфейс файлу все ще є.

Простим прикладом обробки може бути:

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.wav.
Роман

6
Ніщо інше як інтерактивний перекладач для з’ясування того, як все працює! Будь амбіційним!
Ігнасіо Васкес-Абрамс

1

Мені потрібно було прочитати 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, потрібне додаткове масштабування. Можливо, комусь із вас це може стати в нагоді


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/ ) не згадувався, і це слід виправити. IMO - це найповніша бібліотека для читання аудіофайлів на 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.