2011-04-28 1 views
4

Salut tous J'utilise les bibliothèques fftw C pour calculer le spectre de fréquence pour certaines applications de traitement de signal sur des systèmes embarqués. Cependant, dans mon projet j'ai rencontré un léger handicap.Calculer fft et ifft avec fftw.h en C

Voici un programme simple que j'ai écrit pour m'assurer que j'implémente correctement les fonctions fftw. Fondamentalement, je veux calculer le fft d'une séquence de 12 nombres, puis faire le ifft et obtenir à nouveau la même séquence de nombres. Si vous avez fftw3 et gcc ce programme devrait fonctionner si vous compilez avec:

gcc -g -lfftw3 -lm fftw_test.c -o fftw_test 

Actuellement ma longueur fft est la même taille que le tableau d'entrée.

#include <stdio.h> 
#include <stdlib.h> 
#include <sndfile.h> 
#include <stdint.h> 
#include <math.h> 
#include <fftw3.h> 

int main(void) 
{ 
double array[] = {0.1, 0.6, 0.1, 0.4, 0.5, 0, 0.8, 0.7, 0.8, 0.6, 0.1,0}; 
//double array2[] = {1, 6, 1, 4, 5, 0, 8, 7, 8, 6, 1,0}; 
double *out; 
double *err; 
int i,size = 12; 

fftw_complex *out_cpx; 

fftw_plan fft; 
fftw_plan ifft; 
out_cpx = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*size); 
out = (double *) malloc(size*sizeof(double)); 
err = (double *) malloc(size*sizeof(double)); 

fft = fftw_plan_dft_r2c_1d(size, array, out_cpx, FFTW_ESTIMATE); //Setup fftw plan for fft 
ifft = fftw_plan_dft_c2r_1d(size, out_cpx, out, FFTW_ESTIMATE); //Setup fftw plan for ifft 

fftw_execute(fft); 
fftw_execute(ifft); 

//printf("Input: \tOutput: \tError:\n"); 
printf("Input: \tOutput:\n"); 
for(i=0;i<size;i++) 
{ 
err[i] = abs(array[i] - out[i]);  
printf("%f\t%f\n",(array[i]),out[i]); 
//printf("%f\t%f\t%f\n",(array[i]),out[i],err[i]); 
} 

fftw_destroy_plan(fft); 
fftw_destroy_plan(ifft); 
fftw_free(out_cpx); 
free(err); 
free(out); 
return 0; 
} 

qui produit la sortie suivante:

Input:  Output: 
0.100000 1.200000 
0.600000 7.200000 
0.100000 1.200000 
0.400000 4.800000 
0.500000 6.000000 
0.000000 0.000000 
0.800000 9.600000 
0.700000 8.400000 
0.800000 9.600000 
0.600000 7.200000 
0.100000 1.200000 
0.000000 0.000000 

Alors, évidemment, l'IFFT est la production un résultat plus grande échelle. Dans les documents fftw trouvés ici: fftw docs about scaling. Il mentionne une certaine mise à l'échelle, mais j'utilise les transformations "r2c" et "c2r" plutôt que FFT_FORWARD et FFT_BACKWARD. Toute idée serait appréciée.

Répondre

4

En regardant the great documentation for the functions you use, vous verrez sont en utilisant FFT_FORWARD et FFT_BACKWARD, et exactement où il est destiné. Par conséquent, les informations de mise à l'échelle que vous avez trouvées précédemment s'appliquent également ici.

+1

Ok merci, ouais j'ai lu ça à un moment donné. C'était une longue journée ... Ouais résolu avec: out [i] = out [i]/size; – digiphd

2

Désolé d'être pédant, mais votre taille pour out_cpx est incorrecte. Au lieu d'être long, il devrait être de taille/2 + 1. C'est parce que FFT d'un signal réel est hermitienne. Vous pouvez vérifier ce que je dis en initialisant out_cpx à un nombre aléatoire (tous 3.14159). Exécutez à la fois l'avant et l'arrière, puis imprimez out_cpx de la taille/2 + 1 à la taille. Cela n'aura pas changé.

http://www.fftw.org/fftw3_doc/Real_002ddata-DFT-Array-Format.html#Real_002ddata-DFT-Array-Format

+0

Excellent merci j'apprécie votre contribution :) Lire la documentation maintenant. – digiphd

1

R2C et C2R font essentiellement la même que la transformée de Fourier régulière. La seule différence est que la matrice d'entrée et de sortie doit contenir la moitié des nombres. S'il vous plaît jeter un oeil au dernier paragraphe du manuel de FFTW r2c and c2r. Le facteur de normalisation est donc précisément le nombre d'éléments du tableau réel, ou la variable size (== 12) dans votre cas.