Чтение.* wav файлы в Python
Мне нужно проанализировать звук, написанный в a .WAV-файл. Для этого мне нужно преобразовать этот файл в набор чисел (массивы, например). Я думаю, что мне нужно использовать пакет wave. Однако я не знаю, как именно это работает. Например, я сделал следующее:
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 ответов:
на источники,
scipy.io.wavfile.read(somefile)
возвращает кортеж из двух элементов: первый-частота дискретизации в выборках в секунду, второй -numpy
массив со всеми данными, считанными из файла. Выглядит довольно простой в использовании!например:
from scipy.io import wavfile fs, data = wavfile.read('./output/audio.wav')
Я сделал некоторые исследования в этот вечер, и понял это:
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, вы можете взять волновые кадры (которые находятся в 2S дополнительном двоичном между -32768; 0x8000 и 32767; 0x7FFF) это читает моно, 16-битный, волновой файл. Я нашел этот сайт весьма полезно в разработке этого.
этот фрагмент считывает 1 кадр. Для чтения более одного кадра (например, 13), используйте
waveData = waveFile.readframes(13) data = struct.unpack("<13h", waveData)
различные модули python для чтения wav:
есть по крайней мере следующие библиотеки для чтения wave audio file:
- PySoundFile
- scipy.io. wavfile (from составляющей)
- волна (читать потоки. Входит в python 2 и 3)
- scikits.audiolab (который, кажется, unmaintained)
- sounddevice (воспроизведение и запись звуков, хорошо для потоков и в режиме реального времени)
- pyglet
самый простой пример:
Это простой пример с 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.аудиолаб.wavread: [ 0. 0. 0. ..., -0.00097656 -0.00079346 -0.00097656] Значение с составляющей.Ио.wavfile.читать: [ 0 0 0 ..., -32 -26 -32]
pysoundfile и Audiolab возвращают поплавок между -1 и 1 (Как matab делает, это Соглашение для звукового сигнала). Scipy и wave возвращают целые числа, которые могут быть преобразованы в float в соответствии с количеством бит кодирования.
например:
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
IMHO, самый простой способ получить звуковые данные из звукового файла в массив NumPy-это PySoundFile:
import soundfile as sf data, fs = sf.read('/usr/share/sounds/ekiga/voicemail.wav')
Это также поддерживает 24-битные файлы из коробки.
есть много доступных библиотек звуковых файлов, я написал обзор где можно увидеть несколько плюсов и минусов. Он также имеет страницу, объясняющую как читать 24-битный wav файл с помощью
wave
модуль.
вы можете сделать это с помощью scikits.audiolab модуль. Это требует NumPy и SciPy для работы, а также libsndfile.
обратите внимание, что я смог заставить его работать только на Ubunutu, а не на OSX.
from scikits.audiolab import wavread filename = "testfile.wav" data, sample_frequency,encoding = wavread(filename)
теперь у вас есть данные wav
Если вы хотите обрабатывать аудио блок за блоком, некоторые из приведенных решений довольно ужасны в том смысле, что они подразумевают загрузку всего аудио в память, производящую много промахов кэша и замедляющую вашу программу. python-wavefile предоставляет некоторые данные конструкции не включает в себя поблочную обработку, используя эффективное и прозрачное управление блоком с помощью генераторов. Другие тонкости pythonic-это контекстный менеджер для файлов, метаданные как свойства... и если вы хотите весь интерфейс файла, потому что вы разрабатываете быстрый прототип, и вы не заботитесь об эффективности, весь интерфейс файла все еще там.
простой пример обработки такой:
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 для любая дальнейшая обработка.
Если вы собираетесь выполнять передачу данных формы волны, то, возможно, вы должны использовать составляющей, в частности
scipy.io.wavfile
.
если его всего два файла и частота дискретизации значительно высока, вы можете просто перемежать их.
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)
Мне нужно было прочитать 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. Может быть, кто-то из вас там может найти это полезным