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 wave. Sin embargo, no sé exactamente cómo funciona. 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 del sonido como función del tiempo. En contraste, veo muchos símbolos extraños y misteriosos (que no son números hexadecimales). ¿Alguien, por favor, puede ayudarme con eso?
data
es una matriz numpy 2-D de mododata.shape
devuelve una tupla de (num_samples, num_channels)Usando el
struct
módulo , puede tomar los marcos de onda (que están en el binario complementario de 2 entre -32768 y 32767 (es decir,0x8000
y0x7FFF
). Esto lee un archivo MONO, 16-BIT, WAVE. Encontré esta página web bastante útil para formular 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]))
Este fragmento lee 1 fotograma. Para leer más de un cuadro (por ejemplo, 13), utilice
wavedata = wavefile.readframes(13) data = struct.unpack("<13h", wavedata)
fuente
Diferentes módulos de Python para leer wav:
Existen al menos las siguientes bibliotecas para leer archivos de audio wave:
El ejemplo más simple:
Este es un ejemplo simple con SoundFile:
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 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)
Salida:
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 y Audiolab devuelven flota entre -1 y 1 (como hace matab, esa es la convención para las señales de audio). Scipy y wave devuelven enteros, que puede convertir en flotantes de acuerdo con la cantidad 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 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
fuente
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 SoundFile :
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 se pueden ver algunos pros y contras. También presenta una página que explica cómo leer un archivo wav de 24 bits con el
wave
módulo .fuente
Puede lograr esto usando el módulo scikits.audiolab . Requiere NumPy y SciPy para funcionar, y también libsndfile.
Tenga en cuenta que solo pude hacer que funcione 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
fuente
scikits.audiolab
no se ha actualizado desde 2010 y probablemente sea solo Python 2.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, lo que produce muchas pérdidas de caché y ralentiza su programa. python-wavefile proporciona algunas construcciones pitónicas para realizar el procesamiento bloque por bloque de NumPy utilizando una gestión de bloques eficiente y transparente por medio de generadores. Otras sutilezas de Pythonic son el administrador de contexto para archivos, metadatos como propiedades ... y si desea la interfaz de archivo completa, porque está desarrollando un prototipo rápido y no le importa la eficiencia, la interfaz de archivo completa todavía está ahí.
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 normalmente 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 devuelta en lugar de usar un tamaño 512 codificado para cualquier procesamiento posterior.
fuente
Si va a realizar transferencias en los datos de forma de onda, tal vez debería usar SciPy , específicamente
scipy.io.wavfile
.fuente
Necesitaba leer un archivo WAV de 1 canal y 24 bits. La publicación anterior de Nak fue muy útil. Sin embargo, como se mencionó anteriormente por basj 24-bit 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
fuente
si son solo dos archivos y la frecuencia de muestreo es significativamente alta, puede simplemente 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)
fuente
También puede usar una
import wavio
biblioteca simple. También necesita tener algunos conocimientos básicos del sonido.fuente
PyDub ( http://pydub.com/ ) no se ha mencionado y eso debería corregirse . En mi opinión, esta es la biblioteca más completa para leer archivos de audio en Python en este momento, aunque no sin sus fallas. Leyendo un archivo 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/
PD. El ejemplo trata sobre la lectura de un archivo wav, pero PyDub puede manejar muchos formatos distintos desde el primer momento. La advertencia es que se basa tanto en el soporte nativo de Python wav como en ffmpeg, por lo que debe tener instalado ffmpeg y muchas de las capacidades de pydub dependen de la versión ffmpeg. Por lo general, si ffmpeg puede hacerlo, también puede hacerlo pydub (que es bastante poderoso).
No descargo de responsabilidad: no estoy relacionado con el proyecto, pero soy un gran usuario.
fuente