2012-04-19 22 views
6

Así que he estado trabajando con FFT, y actualmente estoy tratando de obtener una forma de onda de sonido de un archivo con FFT, (modifíquela eventualmente), pero luego devuelva esa forma de onda modificada a un archivo. Obtuve la FFT de la onda de sonido y luego usé una función FFT inversa en ella, pero el archivo de salida no suena nada bien. No he hecho ningún filtrado en la forma de onda, estoy probando obteniendo los datos de frecuencia y luego volviéndolo a poner en un archivo, debería sonar igual, pero suena muy diferente. ¿Algunas ideas?Python NumPy - FFT y FFT inversa?

- EDITAR -

Desde entonces he estado trabajando en este proyecto un poco, pero todavía no he conseguido los resultados deseados. El archivo de sonido emitido es ruidoso (tanto más ruidoso, como ruido adicional que no estaba presente en el archivo original), y el sonido de un canal se filtró al otro canal (que anteriormente estaba en silencio). El archivo de sonido de entrada es un archivo estéreo de 2 canales cuyo sonido proviene solo de un canal. Aquí está mi código:

import scipy 
import wave 
import struct 
import numpy 
import pylab 

from scipy.io import wavfile 

rate, data = wavfile.read('./TriLeftChannel.wav') 

filtereddata = numpy.fft.rfft(data, axis=0) 

print (data) 

filteredwrite = numpy.fft.irfft(filtereddata, axis=0) 

print (filteredwrite) 

wavfile.write('TestFiltered.wav', rate, filteredwrite) 

No entiendo por qué esto no funciona ...?

EDITAR: He descomprimido el archivo .py problemático y el archivo de audio, si eso puede ayudar a resolver el problema here.

+3

intento de añadir 'filteredwrite = numpy.round (filteredwrite) .astype ('Int16')' antes de guardar –

+0

@Bago - Muchas gracias! Eso solucionó totalmente el problema. Me preguntaba, ¿forzar el ifft filtrado a 'int16' significa que será un archivo de sonido de profundidad de 16 bits? – SolarLune

+0

No sé demasiado sobre los archivos wav, siempre asumí que eran datos sin procesar, sin comprimir, pero tendrá que leer las especificaciones del formato wav para estar seguro. –

Respuesta

4
>>> import numpy as np 
>>> a = np.vstack([np.ones(11), np.arange(11)]) 

# We have two channels along axis 0, the signals are along axis 1 
>>> a 
array([[ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], 
     [ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.]]) 
>>> np.fft.irfft(np.fft.rfft(a, axis=1), axis=1) 
array([[ 1.1  , 1.1  , 1.1  , 1.1  , 
      1.1  , 1.1  , 1.1  , 1.1  , 
      1.1  , 1.1  ], 
     [ 0.55  , 1.01836542, 2.51904294, 3.57565618, 
      4.86463721, 6.05  , 7.23536279, 8.52434382, 
      9.58095706, 11.08163458]]) 
# irfft returns an even number along axis=1, even though a was (2, 11) 

# When a is even along axis 1, we get a back after the irfft. 
>>> a = np.vstack([np.ones(10), np.arange(10)]) 
>>> np.fft.irfft(np.fft.rfft(a, axis=1), axis=1) 
array([[ 1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 
      1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 
      1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 
      1.00000000e+00], 
     [ 7.10542736e-16, 1.00000000e+00, 2.00000000e+00, 
      3.00000000e+00, 4.00000000e+00, 5.00000000e+00, 
      6.00000000e+00, 7.00000000e+00, 8.00000000e+00, 
      9.00000000e+00]]) 

# It seems like you signals are along axis 0, here is an example where the signals are on axis 0 
>>> a = np.vstack([np.ones(10), np.arange(10)]).T 
>>> a 
array([[ 1., 0.], 
     [ 1., 1.], 
     [ 1., 2.], 
     [ 1., 3.], 
     [ 1., 4.], 
     [ 1., 5.], 
     [ 1., 6.], 
     [ 1., 7.], 
     [ 1., 8.], 
     [ 1., 9.]]) 
>>> np.fft.irfft(np.fft.rfft(a, axis=0), axis=0) 
array([[ 1.00000000e+00, 7.10542736e-16], 
     [ 1.00000000e+00, 1.00000000e+00], 
     [ 1.00000000e+00, 2.00000000e+00], 
     [ 1.00000000e+00, 3.00000000e+00], 
     [ 1.00000000e+00, 4.00000000e+00], 
     [ 1.00000000e+00, 5.00000000e+00], 
     [ 1.00000000e+00, 6.00000000e+00], 
     [ 1.00000000e+00, 7.00000000e+00], 
     [ 1.00000000e+00, 8.00000000e+00], 
     [ 1.00000000e+00, 9.00000000e+00]]) 
6
  1. Usted no parece ser de aplicar cualquier filtro de aquí
  2. Es posible que desee tomar el ifft del fft (post-filtrado), no de la forma de onda de entrada.
4

¿No debería ser más como esto?

filtereddata = numpy.fft.fft(data) 
# do fft stuff to filtereddata 
filteredwrite = numpy.fft.ifft(filtereddata) 
wavfile.write('TestFiltered.wav', rate, filteredwrite) 
+0

@wim - Disculpa - edité mi publicación original para tener más información. – SolarLune

2

Dos problemas.

Usted está FFTing 2 canales de datos. Para que los resultados FFT tengan sentido, solo debe usar el canal FFT 1 de datos mono. Si desea procesar 2 canales de datos estéreo, debe IFFT (FFT()) cada canal por separado.

Está utilizando un fft real, que descarta la información y hace que la fft no sea invertible.

Si desea invertir, necesitará usar una FFT que produce un resultado complejo, y luego IFFT este complejo vector de dominio de frecuencia de regreso al dominio del tiempo. Si modifica el vector de dominio de frecuencia, asegúrese de que se mantenga conjugado simétrico si desea un resultado estrictamente real (menos ruido numérico).

+0

puede transferir datos multicanal, solo necesita usar una matriz 2d y asegurarse de que la palabra clave axis esté configurada correctamente (-1 por defecto), y 'irfft (rfft (n))' debe devolver n (dentro de la precisión de la máquina) –

+0

* 'irfft (rfft (n))' parece que se comporta mejor si n.shape [axis] es par. –

+0

@Bago - Perdón por tomar tanto tiempo para hacer esto, ¿pero podrías ampliar un poco lo que quieres decir? ¿A qué te refieres con 'usar una matriz 2d'? Te refieres a una matriz NumPy, ¿verdad? – SolarLune