2010-01-13 348 views
46

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:Lectura de archivos * .wav en Python

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 en 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?

+12

Es realmente confuso cuando alguien más con mi nombre publica una pregunta que estoy preguntando, pero no recuerdo haberlo hecho :) – Roman

+1

¿Qué demonios son los números hexagonales? – glglgl

+1

@glglgl Probablemente no era lo que se quería decir: https://en.wikipedia.org/wiki/Hexagonal_number :-) – JakeD

Respuesta

46

Por the sources, 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!

+0

Puede combinar esto con herramientas de conversión de línea de comando para abrir otros formatos. – endolith

+7

Sin embargo, carece seriamente del número de canales. ¿Cómo se supone que debes trabajar con audio sin saber la cantidad de canales? – bastibe

+0

arroja algunos extraños errores de desempaquetado de estructuras en mi computadora. Creo que está usando struct.unpack ('

1

Si va a realizar transferencias en los datos de forma de onda, entonces quizás deba usar SciPy, específicamente scipy.io.wavfile.

+1

OK. Acabo de instalar SciPy pero no encuentro ningún ejemplo del uso de scipy.io.wavfile. – Roman

+4

¡Nada como el intérprete interactivo para descubrir cómo funcionan las cosas! ¡Ser ambicioso! –

44

hice algunas investigaciones esta noche y 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])) 

Esperemos que este fragmento de ayuda a alguien. Detalles: usando el struct module, puede tomar los marcos de onda (que están en el binario 2s complementario entre -32768; 0x8000 y 32767; 0x7FFF) Esto lee un archivo MONO, 16-BIT, WAVE. Encontré this webpage bastante útil en la formulación de esto.

+1

cómo manejar archivos estéreos de 24bits? – Basj

+7

me da el error: "struct.error: unpack requiere un argumento de cadena de longitud 2" – Coder404

+0

Si ejecuta este fragmento de código con un archivo de audio muy grande. Su computadora morirá debido a la necesidad de memoria de este programa. Necesita procesar archivos de audio por bloques para archivos de audio grandes – ArthurLambert

8

Puede hacerlo utilizando el módulo scikits.audiolab. Requiere que funcionen NumPy y SciPy, y también libsndfile.

Nota, 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 usted tiene los datos wav

0

si sus sólo dos archivos y la frecuencia de muestreo es significativamente alta, sólo podría entrelazarlo.

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) 
3

Si desea procces un bloque de audio por bloque, algunas de las soluciones dadas son bastante horrible en el sentido de que implican cargar todo el audio en la memoria la producción de muchos errores de caché y ralentizar su programa. python-wavefile proporciona algunos constructos pitónicos para realizar el procesamiento NumPy bloque por bloque utilizando una gestión de bloques eficiente y transparente mediante 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 sencillo 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 vuelve a utilizar el mismo bloque para leer todo el archivo, incluso en el caso de la última secuencia que por lo general 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.

14

módulos de Python diferentes para leer wav:

hay al menos estas bibliotecas siguientes para leer el archivo de audio de onda:

El ejemplo más sencillo:

Este es un simple ejemplo 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, que 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 

lectura con scikits.audiolab.wavread: [0. 0. 0. ..., -0.00097656 -0.00079346 -0.00097656] lectura 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 
0

que necesitaba para leer un archivo WAV de 24 bits de 1 canal. La publicación anterior por Nak fue muy útil. Sin embargo, como se mencionó anteriormente por basj de 24 bits no es sencillo. Finalmente conseguí que funcione mediante el siguiente fragmento: se requiere

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 

Algunos de escala adicional si necesita resultados entre -1 y +1. Tal vez algunos de ustedes por ahí podría resultar útil en mi humilde opinión

10

, 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 es compatible con archivos de 24 bits de la caja.

Hay muchas bibliotecas de archivos de sonido disponibles, he escrito an overview donde puede ver algunos pros y contras. También cuenta con una página que explica how to read a 24-bit wav file with the wave module.

+0

Nota: soundfile.read() se normaliza por 2^(n_bits - 1) como en el ejemplo scipy.io.wavfile de sandoval – Quetzalcoatl

0

u también puede utilizar la biblioteca simple import wavio u también necesita tener algunos conocimientos básicos del sonido.