Convierte archivos WAV estéreo de 3 bytes en una matriz numpy

Me han dado un gran archivo WAV de grabación subacuática continua que me gustaría convertir a una matriz numpy para su análisis. Estoy luchando para hacer esto.

Hasta ahora tengo:

import numpy as np import scipy as sp import wave as wv import struct wavefile = wv.open(filename,'r') (nchannels,sampwidth,framerate,nframes,comptype,compname) = wavefile.getparams() // read a sample as example wavedata =wavefile.readframes(1) 

El primer cuadro se ve así: ‘\ xcd \ xbc \ xff @ \ x01 \ x00’. He intentado descomprimirlo utilizando struct, pero descomprimiré lo que haga, aparece el siguiente error: “el tamaño de la cadena no coincide con el formato “. Supongo que esto está relacionado con el hecho de que la estructura Python no puede manejar datos de 24 bits.

El parámetro del archivo de onda se ve como sigue:

  • nchannels = 2
  • sampwidth = 3
  • velocidad de cuadro = 48000
  • nframes = 283516532L
  • comptype = ‘NONE’
  • compname = ‘no comprimido’

Alguien sabe cómo leer un archivo WAV estéreo de 24 bits en una matriz numpy?

    Aquí hay un bucle que maneja archivos WAV de 2, 3 y 4 bytes con números arbitrarios de canales:

     def dataFromWave(fname): """ return list with interleaved samples """ f = wave.open(fname, 'rb') chans = f.getnchannels() samps = f.getnframes() sampwidth = f.getsampwidth() if sampwidth == 3: #have to read this one sample at a time s = '' for k in xrange(samps): fr = f.readframes(1) for c in xrange(0,3*chans,3): s += '\0'+fr[c:(c+3)] # put TRAILING 0 to make 32-bit (file is little-endian) else: s = f.readframes(samps) f.close() unpstr = '<{0}{1}'.format(samps*chans, {1:'b',2:'h',3:'i',4:'i',8:'q'}[sampwidth]) x = list(struct.unpack(unpstr, s)) if sampwidth == 3: x = [k >> 8 for k in x] #downshift to get +/- 2^24 with sign extension return x 

    Para aquellos con problemas similares publico mi solución. Tenga en cuenta que esto convierte un archivo de onda de 24 bits en una matriz numpy de punto flotante firmada. Deje la parte / int2float cuando solo se convierta a enteros.

     frames = wavfile.readframes(nsamples) ch1 = np.zeros(nsamples) ch2 = np.zeros(nsamples) int2float = (2**23)-1 for x in np.arange(int(nsamples)): ch1_24bit_sample = frames[x*6:x*6+3] ch2_24bit_sample = frames[x*6+3:x*6+6] ch1_32bit_sample = bit24_2_32(ch1_24bit_sample) ch2_32bit_sample = bit24_2_32(ch2_24bit_sample) ch1[x]=struct.unpack('i',ch_32bit_sample)[0] ch2[x]=struct.unpack('i',ch_32bit_sample)[0] ch1[x]=ch1[x]/int2float ch2[x]=ch2[x]/int2float def bit24_2_32(strbytes): if strbytes[2] < '\x80': return strbytes+'\x00' else: return strbytes+'\xff' 

    Esta es una pregunta antigua, pero si alguien necesita opciones adicionales y no hay restricciones en el uso de módulos externos, entonces es probable que pueda usar librosa

     myNdArray = librosa.core.load(wav_path, sr=sample_rate)[0]