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