read - reproducir wav en python
Lectura de archivos*.wav en Python (10)
En mi humilde opinión, la forma más fácil de obtener datos de audio de un archivo de sonido en una matriz NumPy es PySoundFile :
import soundfile as sf
data, fs = sf.read(''/usr/share/sounds/ekiga/voicemail.wav'')
Esto también admite archivos de 24 bits listos para usar.
Hay muchas bibliotecas de archivos de sonido disponibles, he escrito una descripción general donde puedes ver algunos pros y contras. También presenta una página que explica cómo leer un archivo wav de 24 bits con el módulo de wave
.
Necesito analizar el sonido escrito en un archivo .wav. Para eso necesito transformar este archivo en un conjunto de números (matrices, por ejemplo). Creo que necesito usar el paquete de onda. Sin embargo, no sé cómo funciona exactamente. Por ejemplo, hice lo siguiente:
import wave
w = wave.open(''/usr/share/sounds/ekiga/voicemail.wav'', ''r'')
for i in range(w.getnframes()):
frame = w.readframes(i)
print frame
Como resultado de este código, esperaba ver la presión sonora como función del tiempo. Por el contrario, veo muchos símbolos misteriosos y extraños (que no son números hexadecimales). ¿Puede alguien, súplicas, ayudarme con eso?
Hice algunas investigaciones esta noche y me di cuenta de esto:
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]))
Espero que este fragmento ayude a alguien. Detalles: utilizando el módulo struct , puede tomar los marcos de onda (que están en el binario complementario 2 entre -32768; 0x8000 y 32767; 0x7FFF) Esto lee un archivo MONO, 16-BIT, WAVE. Encontré esta página web bastante útil para formular esto.
Este fragmento lee 1 fotograma. Para leer más de un cuadro (p. Ej., 13), use
waveData = waveFile.readframes(13)
data = struct.unpack("<13h", waveData)
Necesitaba leer un archivo WAV de 1 canal de 24 bits. La publicación anterior de fue muy útil. Sin embargo, como se mencionó anteriormente por Basj 24 bits no es sencillo. Finalmente lo hice funcionar usando el siguiente fragmento:
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
Se requiere una escala adicional si necesita resultados entre -1 y +1. Tal vez algunos de ustedes puedan encontrar esto útil
Puede lograr esto usando el módulo scikits.audiolab . Requiere que funcionen NumPy y SciPy, y también libsndfile.
Tenga en cuenta que solo pude hacer que funcionara en Ubunutu y no en OSX.
from scikits.audiolab import wavread
filename = "testfile.wav"
data, sample_frequency,encoding = wavread(filename)
Ahora tienes los datos wav
Según las fuentes , scipy.io.wavfile.read(somefile)
devuelve una tupla de dos elementos: la primera es la tasa de muestreo en muestras por segundo, la segunda es una matriz numpy
con todos los datos leídos del archivo. ¡Parece bastante fácil de usar!
p.ej:
from scipy.io import wavfile
fs, data = wavfile.read(''./output/audio.wav'')
Si desea procesar un audio bloque por bloque, algunas de las soluciones dadas son bastante horribles en el sentido de que implican cargar todo el audio en la memoria produciendo muchas fallas de caché y ralentizando su programa. python-wavefile proporciona algunos constructos pitónicos para hacer el procesamiento NumPy bloque por bloque utilizando una gestión de bloques eficiente y transparente por medio de generadores. Otras sutilezas pitónicas son el administrador de contexto para los archivos, los metadatos como propiedades ... y si quiere la interfaz completa del archivo, porque está desarrollando un prototipo rápido y no le importa la eficiencia, toda la interfaz del archivo aún está allí.
Un ejemplo simple de procesamiento sería:
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)
El ejemplo reutiliza el mismo bloque para leer todo el archivo, incluso en el caso del último bloque que generalmente es menor que el tamaño requerido. En este caso, obtienes una porción del bloque. Así que confíe en la longitud del bloque devuelto en lugar de utilizar un tamaño 512 codificado para cualquier procesamiento posterior.
Si va a realizar transferencias en los datos de forma de onda, entonces quizás deba usar SciPy , específicamente scipy.io.wavfile
.
También puede utilizar la biblioteca de import wavio
simple u también necesita tener algunos conocimientos básicos del sonido.
si solo tiene dos archivos y la frecuencia de muestreo es significativamente alta, puede intercalarlos.
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)
Diferentes módulos de python para leer wav:
Hay al menos estas siguientes bibliotecas para leer el archivo de audio wave:
- PySoundFile
- scipy.io.wavfile (desde scipy )
- wave (para leer streams. Incluido en python 2 y 3)
- scikits.audiolab (que parece no mantenido)
- sounddevice (reproducir y grabar sonidos, bueno para transmisiones y en tiempo real)
- pyglet
El ejemplo más simple:
Este es un ejemplo simple con Pysoundfile:
import soundfile as sf
data, samplerate = sf.read(''existing_file.wav'')
Formato de la salida:
Advertencia, los datos no siempre están en el mismo formato, eso depende de la biblioteca. Por ejemplo:
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
Leyendo con scikits.audiolab.wavread: [0. 0. 0. ..., -0.00097656 -0.00079346 -0.00097656] Leyendo con scipy.io.wavfile.read: [0 0 0 ..., -32 -26 -32 ]
PySoundFile y Audiolab devuelven flotación entre -1 y 1 (como lo hace matab, esa es la convención para la señal de audio). Los enteros Scipy y wave return, que se pueden convertir en float según el número de bits de codificación.
Por ejemplo:
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