2011-10-14 10 views
7

por lo que pidió todo en el título:cómo convertir archivo de onda para flotar amplitud

Tengo un archivo de onda (escrito por PyAudio de una entrada de audio) y quiero convertirlo en datos de flotación correspondientes del sonido nivel (amplitud) para hacer una transformación fourier, etc. ...

¿Alguien tiene una idea para convertir datos WAVE para flotar?

Respuesta

0

El formato Microsoft WAVE está bastante bien documentado. Ver https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ por ejemplo. No tomaría mucho escribir un analizador de archivos para abrir e interpretar los datos para obtener la información que necesita ... Dicho esto, es casi seguro que se haya hecho antes, por lo que estoy seguro de que alguien dará una respuesta "más fácil";)

5

La mayoría de los archivos de onda están en formato entero PCM de 16 bits.

Lo que se quiere a:

  • analizar la cabecera al conocido formato es (marque el enlace desde Xophmeister)
  • Leer los datos, tomar los valores enteros y convertirlos a flotar

Los valores enteros van desde -32768 a 32767, y debe convertir a valores de -1.0 a 1.0 en puntos flotantes.

no tengo el código en Python, sin embargo, en C++, aquí es un extracto de código si los datos PCM es entero de 16 bits, y convertirlo a flotar (32-bit):

short* pBuffer = (short*)pReadBuffer; 

const float ONEOVERSHORTMAX = 3.0517578125e-5f; // 1/32768 
unsigned int uFrameRead = dwRead/m_fmt.Format.nBlockAlign; 

for (unsigned int i = 0; i < uFrameCount * m_fmt.Format.nChannels; ++i) 
{ 
    short i16In = pBuffer[i]; 
    out_pBuffer[i] = (float)i16In * ONEOVERSHORTMAX; 
} 

Tenga cuidado con los archivos estéreo, ya que los datos PCM estéreo en los archivos de onda están intercalados, lo que significa que los datos se parecen a LRLRLRLRLRLRLRLR (en lugar de LLLLLLLLRRRRRRRR). Puede o no necesitar desentrelazar dependiendo de lo que haga con los datos.

5

Pasé horas tratando de encontrar la respuesta a esto. La solución resulta ser realmente simple: struct.unpack es lo que estás buscando. El código final se verá algo como esto:

rawdata=stream.read()     # The raw PCM data in need of conversion 
from struct import unpack    # Import unpack -- this is what does the conversion 
npts=len(rawdata)      # Number of data points to be converted 
formatstr='%ih' % npts     # The format to convert the data; use '%iB' for unsigned PCM 
int_data=unpack(formatstr,rawdata)  # Convert from raw PCM to integer tuple 

La mayor parte del crédito va a Interpreting WAV Data. El único truco es obtener el formato correcto para desempaquetar: tiene que ser el número correcto de bytes y el formato correcto (firmado o sin firmar).

7

He identificado dos maneras decentes de hacer esto.

Método 1: utilizar el módulo WAVEFILE

Utilice este método si no te importa la instalación de algunas bibliotecas adicionales que implicaron un poco de andar por ahí en mi Mac, pero que era fácil en mi servidor de Ubuntu.

https://github.com/vokimon/python-wavefile

import wavefile 

# returns the contents of the wav file as a double precision float array 
def wav_to_floats(filename = 'file1.wav'): 
    w = wavefile.load(filename) 
    return w[1][0] 

signal = wav_to_floats(sys.argv[1]) 
print "read "+str(len(signal))+" frames" 
print "in the range "+str(min(signal))+" to "+str(min(signal)) 

Método 2: utilizando el módulo de onda

Utilice este método si desea instalar el módulo menos molestias.

Lee un archivo wav del sistema de archivos y lo convierte en flotantes en el rango de -1 a 1. Funciona con archivos de 16 bits y si son> 1 canal, intercalará las muestras de la misma manera en que se encuentran en el archivo. Para otras profundidades de bits, cambiar la 'h' en el argumento de struct.unpack acuerdo con la tabla en la parte inferior de esta página:

https://docs.python.org/2/library/struct.html

que no funcionará para los archivos de 24 bits ya que no hay datos escriba que es de 24 bits, por lo que no hay forma de decirle a struct.unpack qué hacer.

import wave 
import struct 
import sys 

def wav_to_floats(wave_file): 
    w = wave.open(wave_file) 
    astr = w.readframes(w.getnframes()) 
    # convert binary chunks to short 
    a = struct.unpack("%ih" % (w.getnframes()* w.getnchannels()), astr) 
    a = [float(val)/pow(2, 15) for val in a] 
    return a 

# read the wav file specified as first command line arg 
signal = wav_to_floats(sys.argv[1]) 
print "read "+str(len(signal))+" frames" 
print "in the range "+str(min(signal))+" to "+str(min(signal)) 
+0

¿No debería ser esta la respuesta aceptada? –

+0

Si obtiene 'OSError' o' wave.Error' intente utilizar el comando ffmpeg 'ffmpeg -i song.mp3 song.wav' mediante cli para convertir el archivo de audio. Debería funcionar entonces ([src] (https://stackoverflow.com/a/36571441/3854436)) –

Cuestiones relacionadas