Чтение.* 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 ответов
Per источники, 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.Ио.wavfile (от scipy)
- волна (читать потоки. Включено в 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 конструкции для обработки NumPy блок за блоком, используя эффективное и прозрачное управление блоками с помощью генераторов. Другие тонкости pythonic-это context manager для файлов, метаданных как свойств... и если вы хотите весь файловый интерфейс, потому что вы разрабатываете быстрый прототип, и вас не волнует эффективность, весь файловый интерфейс все еще существует.
простым примером обработки будет:
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, в частности 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-файл. Сообщение выше НАК было очень полезно. Однако, как упоминалось выше,полезности интернета 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. Может быть, некоторые из вас там могут найти это полезным
u также может использовать simple import wavio
библиотека u также должны иметь некоторые базовые знания звука.