Funciones para trabajar con wav’s vectorialmente en python
Posted by hordia on December 27th, 2006
A raíz de que desde hace un tiempo me puse en campaña para intentar reemplazar matlab con python (en realidad usar python para lo que hasta ahora usaba matlab) es que me vi obligado a implementar las siguientes funciones para poder trabajar con archivos wavs como si fueran vectores.
Serían las equivalentes a las funciones wavread y wavwrite de matlab.
wavread: recibe un wav y devuelve un vector normalizado entre -1 y 1, su frecuencia de muestreo y la cantidad de bits por muestra.
# Example: [ y, Fs, bits ] = wavread( 'filename' )
def wavread( name ):
file = wave.open( name, 'r' )
[Channels,Bytes,Fs,Frames,Compress,CompressName] = file.getparams() # (nchannels, sampwidth in bytes, sampling frequency, nframes, comptype, compname)
Bits = Bytes*8 # 16 bits per sample
Data = file.readframes( Frames )
Data = fromstring( Data, Int16 ) / 32767.0 # -1..1 values, Int16 because Bits=2x8=16
print "Fs: ",Fs,"\nBits: ",Bits,"\nChannels: ",Channels
file.close()
return Data, Fs, Bits
# Example: wavwrite( y, Fs, filename )
def wavwrite( data_array, Fs, name ):
file = wave.open( name, 'w' )
file.setframerate( Fs ) # sets sampling frequency
file.setnchannels( 1 ) # sets number of channels
file.setsampwidth( 2 ) # number of bytes: 16bits/8=2, 16 bits per sample
clipped = False
block_size = 1024*10 # write block size: 10k
a_max = 32767 # max amp
a_min = -32767 # min amp
n = 0
len_data_array = len( data_array ) # 2 bytes (int16) data
while n < len_data_array :
frame = '' # string frame of 'block_size'
for i in range( block_size ) :
if n < len_data_array :
twodatabytes = int( data_array[n] * a_max )
if twodatabytes > a_max or twodatabytes < a_min : clipped = True
twodatabytes = min( max(twodatabytes,a_min), a_max ) # normalization, -32767..32767
#twodatabytes.clip( min=a_min, max=a_max ) # normalization, -32767..32767
frame += chr( twodatabytes & 0xFF ) # takes first byte, converts it to char and adds it to the frame
frame += chr( (twodatabytes >> 8) & 0xFF ) # takes the second byte
n += 1
file.writeframes( frame )
if clipped == True : print "Warning: Some values were clipped"
print "Final length:", len_data_array/512,"kb" # n*2/1024 (bytes size/1024) = n/512
file.close()
Nota: recomiendo bajar este archivo wav_array.py y no copiar directamente el código desde aca ya que debido al plugin para syntax highlight, el código puede no haber quedado correctamente indentado y tal vez no funcione bien al ser interpretado por python
Update: Aprovechando estas funciones y a manera de ejemplo también escribí el equivalente al post “Convolución circular rápida (aplicación en reverbs)” pero en python. El código es este: fast_conv.py.
Update 2: Para wavs de 8 bits ver: “Trabajar con wavs de 8 bits en python”




