2009-08-29 6 views
1

J'ai ce code, mais il continue de retourner des fréquences aléatoires de 0 à environ 1050. S'il vous plaît pouvez-vous m'aider à comprendre pourquoi cela se produit.FFT Problème (renvoie des résultats aléatoires)

La longueur de mes données est de 1024, la fréquence d'échantillonnage est de 8192, et les données sont un tableau court rempli de données d'entrée provenant du micro.


float *iSignal = new float[2048]; 
float *oSignal = new float[2048]; 
int pitch = 0; 

for(x=0;x<=1024;x++) { 
    iSignal[x] = data[x]; 
} 

fft(iSignal,oSignal,1024); //Input data, output data, length of input and output data 

for(int y=0;y< 2048;y+=2) { 
if((pow(oSignal[y],2)+pow(oSignal[y+1],2))>(pow(oSignal[pitch],2)+pow(oSignal[(pitch)+1],2))) { 
     pitch = y; 
    } 
} 

double pitchF = pitch/(8192.0/1024); 
printf("Pitch: %f\n",pitchF); 

Merci,

Niall. Editer: Modifié le code, mais il renvoie toujours des fréquences aléatoires.

+0

Avec quoi alimentez-vous le micro? Comme je l'ai dit, à moins que ce soit un ton très pur, vous obtiendrez des résultats aléatoires. – avakar

+0

peut-être optimiser légèrement votre code avec la mise en cache de la valeur de résultat de pow (oSignal [pitch], 2) + pow (oSignal [pitch + 1], 2), car dans votre code il est calculé plusieurs fois avec la même valeur de pitch. – moala

+0

Ma voix et quelques bruits de guitare. Pourriez-vous suggérer un moyen de le faire ne pas retourner des résultats aléatoires? Le fenêtrage fonctionnerait-il? – Niall

Répondre

7

En supposant oSignal est rempli de nombres complexes de telle sorte, qui alternent des parties réelles et imaginaires, il pourrait aider à changer

for(int y=0;y< 8191;y++) 

à

for(int y=0;y< 8191;y+=2) 

Edit: Je l'ai même pas remarquez que vous ne transmettez que 1024 échantillons. Vous devez transmettre autant d'échantillons dans le domaine temporel que d'échantillons de domaine fréquentiel, dans votre cas 4096.

Éditer: Encore une chose: vous essayez évidemment de trouver la fréquence de base de quelque chose. À moins que ce soit un son généré par ordinateur ou un sifflet humain (les deux étant des tons très purs), vous pourriez être déçu par le résultat. La méthode simple que vous avez postée fonctionne à peine pour la flûte.

Edit: Pour la voix et la guitare, vous n'avez pas de chance. J'ai écrit a program il y a quelque temps qui affiche le domaine de fréquence, essayez-le, vous verrez le problème. Il y a aussi sources disponible, si vous êtes intéressé.

Édition finale: Vous voudrez peut-être lire le Wikipedia article on pitch detection. Concentrez-vous sur les approches temporelles.

+1

Pour appuyer ce qu'a dit avakar, détecter la hauteur d'un enregistrement audio avec une précision suffisante (à 1/100 d'un demi-ton) est pratiquement impossible avec FFT, car la résolution en fréquence obtenue est proportionnelle à la taille de la fenêtre FFT . Auto-corrélation est une technique plus appropriée à cet effet. – MusiGenesis

0

"fréquences aléatoires de 0 à environ 1050" - le signal audio typique ne consiste-t-il pas en une combinaison de fréquences? Comme votre fréquence d'échantillonnage est de 8192 Hz, votre FFT peut détecter jusqu'à 8192/2 = 4096 Hz. Je m'attendrais à ce que vous voyiez une combinaison de plusieurs fréquences, mais je ne les appellerais pas "aléatoire".

Pourquoi êtes-vous surpris? Qu'est-ce que j'ai raté?

1

Il semble que iSignal [1025] .. iSignal [8191] contient des données aléatoires. Vous pourriez essayer de le mettre à 0. Mais pourquoi passez-vous 8192 à fft() si votre longueur de données est 1024 (ou est-ce 1025)?

De plus, vous perdez une certaine précision dans la division entière. Changez-le en double pitchF = pitch/(8192.0/1024); Est-ce que votre fonction fft attend des données d'entrée réelles ou complexes? Dans le cas où il attend des données complexes, vous devez définir tous les entrée de iSignal à 0.

0

Deux choses:

  • Etes-vous sûr que vous utilisez correctement votre fonction fft?Vous traitez la sortie comme s'il s'agissait d'un tableau complexe organisé [R_1 I_1 R_2 I_2 ...], mais vous traitez le tableau d'entrée comme s'il était organisé [R_1 R_2 R_3 ... R_1024 I_1 I_2 ...] et as Henrik says puis laissez les parties complexes non initialisées.
  • Votre peak detection est extrêmement primitif, bien qu'il devrait le faire pour une entrée simple (comme une piqûre de guitare). Pour une utilisation avec une voix humaine, vous voulez presque certainement une approche plus sophistiquée.

Avez-vous essayé d'entrer un signal simple connu (c'est-à-dire un sinus pur) comme entrée?

Questions connexes