Question

J'ai un fichier audio et j'Itère le fichier et en prenant 512 échantillons à chaque étape, puis les faisant passer par une FFT.

J'ai les données comme un bloc 514 flotteurs longs (IPP de l'aide ippsFFTFwd_RToCCS_32f_I) avec des composants réels et imaginaires intercalées.

Mon problème est que dois-je faire avec ces nombres complexes une fois que je les ai? En ce moment je fais pour chaque valeur

const float realValue   = buffer[(y * 2) + 0];
const float imagValue   = buffer[(y * 2) + 1];
const float value       = sqrt( (realValue * realValue) + (imagValue * imagValue) );

Cela donne quelque chose un peu utile, mais je préfère une certaine façon d'obtenir les valeurs dans la plage 0 à 1. Le problème ci-dessus, il est que les pics finissent par revenir comme environ 9 ou plus. Cela signifie que les choses deviennent méchamment saturées et puis il y a d'autres parties du spectrogramme qui apparaît à peine, malgré le fait qu'ils semblent être assez forte quand je lance l'audio via le spectrogramme d'audition. Je reconnais pleinement que je ne suis pas 100% sûr de ce que les données renvoyées par la FFT est (autre que celui qu'elle représente les valeurs de fréquence du bloc long de 512 échantillons Je passe dans). Surtout ma compréhension fait défaut sur quoi exactement le nombre de Compex représente.

Des conseils et de l'aide serait très apprécié!

Edit: Juste pour clarifier. Mon gros problème est que les valeurs de FFT retournées sont vides de sens sans une certaine idée de ce que l'échelle est. Quelqu'un peut-il me diriger vers le travail à cette échelle?

Edit2: Je comprends vraiment agréable à regarder les résultats en procédant comme suit:

size_t count2   = 0;
size_t max2     = kFFTSize + 2;
while( count2 < max2 )
{
    const float realValue   = buffer[(count2) + 0];
    const float imagValue   = buffer[(count2) + 1];
    const float value   = (log10f( sqrtf( (realValue * realValue) + (imagValue * imagValue) ) * rcpVerticalZoom ) + 1.0f) * 0.5f;
    buffer[count2 >> 1] = value;
    count2 += 2;
}

A mes yeux cela ressemble encore mieux que la plupart des autres implémentations spectrogramme j'ai regardé.

Y at-il Majorly mal avec ce que je fais?

Était-ce utile?

La solution

La chose habituelle à faire pour obtenir la totalité d'une FFT visible est de prendre le logarithme de l'ampleur.

Alors, vous indique quelle fréquence a été détectée la position du tampon de sortie. L'amplitude (norme L2) du nombre complexe, vous indique la force de la fréquence détectée était, et la phase (arctangente) vous donne des informations qui est beaucoup plus important dans l'espace de l'image que l'espace audio. Étant donné que la FFT est discrète, les fréquences vont de 0 à la fréquence de Nyquist. En images, le premier terme (DC) est généralement le plus grand, et donc un bon candidat pour une utilisation dans la normalisation si tel est votre objectif. Je ne sais pas si cela est vrai aussi pour l'audio (je doute)

Autres conseils

Pour chaque fenêtre de 512 échantillons, vous calculer l'ampleur de la FFT que vous avez fait. Chaque valeur représente l'amplitude de la fréquence correspondante présente dans le signal.

mag
 /\
 |
 |      !         !
 |      !    !    !
 +--!---!----!----!---!--> freq
 0          Fs/2      Fs

Maintenant, nous devons comprendre les fréquences.

Etant donné que le signal d'entrée est des valeurs réelles, la FFT est symétrique autour de la moyenne (composant Nyquist), le premier terme étant la composante continue. Connaissant la fréquence d'échantillonnage du signal Fs, la fréquence de Nyquist est Fs / 2. Et donc pour le k d'index, la fréquence correspondante est k*Fs/512

Ainsi, pour chaque fenêtre de longueur 512, nous obtenons les grandeurs à la fréquence spécifiée. Le groupe des plus de fenêtres consécutives forment le spectrogramme.

Pour que les gens savent que je l'ai fait beaucoup de travail sur ce problème dans son ensemble. La principale chose que j'ai découvert est que la FFT exige la normalisation après l'avoir fait.

Pour ce faire, vous en moyenne toutes les valeurs de votre vecteur de fenêtre ensemble pour obtenir une valeur légèrement inférieure à 1 (ou 1 si vous utilisez une fenêtre rectangulaire). Vous pouvez ensuite diviser ce nombre par le nombre de bacs de fréquence vous transformer la FFT afficher.

Enfin, vous divisez le nombre réel retourné par la FFT par le nombre de normalisation. Vos valeurs d'amplitude devraient maintenant être dans les -Inf 1 plage. Connectez-vous, etc, comme vous s'il vous plaît. Vous serez toujours travailler avec une plage connue.

Il y a quelques petites choses que je pense que vous trouverez utile.

L'attaquant FT aura tendance à donner un plus grand nombre dans la production que dans l'entrée. Vous pouvez penser que toute l'intensité à une certaine fréquence affichée à un endroit plutôt que d'être distribués par l'ensemble de données. Est-ce que cette question? Probablement pas parce que vous pouvez toujours l'échelle les données pour répondre à vos besoins. J'ai écrit un entier à base paire FFT / IFFT et chaque passage nécessaire redimensionnant pour éviter le débordement d'entier.

Les données réelles qui sont vos commentaires sont convertis en quelque chose qui est presque complexe. Il se trouve que tampon [0] et un tampon [n / 2] sont réels et indépendants. Il y a une bonne discussion sur ce sujet .

Les données d'entrée sont des valeurs d'intensité sonore prises au cours du temps, également espacées. Ils sont censés être, comme il se doit, dans le domaine temporel. La sortie du FT est dit être dans le domaine des fréquences, car l'axe horizontal est la fréquence. L'échelle verticale reste intensité. Bien qu'il ne soit pas évident à partir des données d'entrée, il y a des informations de phase dans l'entrée ainsi. Bien que tous le son est sinusoïdale, il n'y a rien qui fixe les phases des ondes sinusoïdales. Ces informations de phase apparaît dans le domaine de fréquence que les phases des différents nombres complexes, mais souvent nous ne se soucient pas (et souvent nous aussi!). Cela dépend de ce que vous faites. Le calcul

const float value = sqrt((realValue * realValue) + (imagValue * imagValue));

récupère les informations d'intensité, mais supprime l'information de phase. En prenant le logarithme essentiellement amortit juste les grands pics.

Espérons que cela est utile.

Si vous obtenez des résultats étranges alors une chose à vérifier est la documentation de la bibliothèque FFT pour voir comment la sortie est emballé. Certaines routines utilisent un format compressé où les valeurs réelles / imaginaires sont intercalés, ou ils peuvent commencer à l'élément N / 2 et enrouler autour.

Pour un test de cohérence, je suggère de créer des données d'échantillons avec des caractéristiques connues, par exemple Fs / 2, Fs / 4 (Fs = fréquence d'échantillonnage) et comparer la sortie de la routine FFT avec ce que vous attendez. Essayez de créer à la fois un sinus et cosinus à la même fréquence, que ceux-ci doivent avoir la même amplitude dans le spectre, mais ont des phases différentes (à savoir le RealValue / imagValue sera différent, mais la somme des carrés doit être le même.

Si vous avez l'intention d'utiliser la FFT si vous avez vraiment besoin de savoir comment il fonctionne mathématiquement, sinon vous risquez de rencontrer d'autres problèmes étranges tels que aliasing.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top