Je viens donc de réviser mon algorithme de calcul de hauteur en utilisant un algorithme de spectre de produit harmonique. Jétais juste curieux de savoir pourquoi cette explication de Harmonic Product Spectrum indique que vous devez implémenter une fenêtre Hanning dans lensemble de données. Quel serait leffet de la mise en œuvre dautres fonctions de Windows sur un ensemble de données (puis de sa FFT)? Quelle fonction de fenêtrage est réellement la meilleure pour la détection de fréquence? Voici les méthodes pertinentes que jai utilisées dans mon code:

/** * Calculates the Frequency based off of the byte array, * @param bytes The audioData you want to analyze * @return The calculated frequency in Hertz. */ private int getFrequency(byte[] bytes){ double[] audioData = this.bytesToDoubleArray(bytes); audioData = applyHanningWindow(audioData); Complex[] complex = new Complex[audioData.length]; for(int i = 0; i<complex.length; i++){ complex[i] = new Complex(audioData[i], 0); } Complex[] fftTransformed = FFT.fft(complex); //return calculateFrequency(fftTransformed); System.out.println("Max size:" + (fftTransformed.length*getFFTBinSize(fftTransformed.length)/4)); return calculateFundamentalFrequency(fftTransformed,4); } private double[] applyHanningWindow(double[] data){ return applyHanningWindow(data, 0, data.length); } private double[] applyHanningWindow(double[] signal_in, int pos, int size) { for (int i = pos; i < pos + size; i++) { int j = i - pos; // j = index into Hann window function signal_in[i] = (double)(signal_in[i] * 0.5 * (1.0 - Math.cos(2.0 * Math.PI * j / size))); } return signal_in; } /** * Harmonic Product Spectrum * @param fftData * @param n * @return */ private int calculateFundamentalFrequency(Complex[] fftData, int n){ Complex[][] data = new Complex[n][fftData.length/n]; for(int i = 0; i<n; i++){ for(int j = 0; j<data[0].length; j++){ data[i][j] = fftData[j*(i+1)]; } } Complex[] result = new Complex[fftData.length/n];//Combines the arrays for(int i = 0; i<result.length; i++){ Complex tmp = new Complex(1,0); for(int j = 0; j<n; j++){ tmp = tmp.times(data[j][i]); } result[i] = tmp; } //Calculates Maximum Magnitude of the array double max = Double.MIN_VALUE; int index = -1; for(int i = 0; i<result.length; i++){ Complex c = result[i]; double tmp = c.getMagnitude(); if(tmp>max){ max = tmp;; index = i; } } return index*getFFTBinSize(fftData.length); } 

Réponse

La FFT ne peut être effectuée que sur un morceau limité de données. Le calcul de base est basé sur lhypothèse que le signal du domaine temporel est périodique, cest-à-dire que votre bloc de données est répété dans le temps. Cela se traduit généralement par une discontinuité majeure aux bords du bloc. Prenons un exemple rapide: taille FFT = 1000 points, fréquence d’échantillonnage = 1000 Hz, résolution en fréquence = 1 Hz. Si vous avez une onde sinusoïdale de 10 Hz, vous n’avez pas de discontinuité car exactement 10 périodes entrent dans votre fenêtre FFT et les valeurs (et dérivées) aux bords sont les mêmes. La FFT de ce siganl sera zéro sauf pour une seule valeur dans le bac # 10. Cela fonctionne également pour une onde sinusoïdale de 11 Hz. Cependant, pour une onde sinusoïdale de 10,3 HZ, vous vous retrouvez avec beaucoup de discontinuité et la FFT aura de lénergie dans tous les bacs avec un maximum denviron 10 ou 11, puis des «jupes» qui roulent sur les côtés. Ainsi, un petit changement de fréquence entraîne un changement massif de limage FFT.

Le fenêtrage est utilisé pour éviter ceci: Windows sassure que les données aux bords sont nulles, donc il ny a pas de discontinuité. Cependant, la multiplication dans le domaine temporel est une convolution dans le domaine fréquentiel et cela se traduit par un élargissement des raies spectrales et également des lobes latéraux. Le choix de la fenêtre contrôle les compromis entre la largeur du lobe principal et lespacement et la hauteur des lobes latéraux. Les exigences spécifiques de votre application déterminent la fenêtre à utiliser et il existe des dizaines de choix. Hanning nest que lun dentre eux. Cest « fondamentalement » la fenêtre de choix si vous navez « pas de meilleures idées ». Personnellement, je préfère les fenêtres Kaiser car elles ont un paramètre continu qui peut contrôler le comportement de la fenêtre sur une large plage.

En général, la FFT nest pas une bonne méthode pour la détection de hauteur. Pour la plupart des signaux audio, le maximum du spectre nest PAS le fondamental (généralement les harmoniques ont une énergie plus élevée), afin dobtenir une résolution décente, vous avez besoin de longs éléments de données, mais cela rend lalgorithme très lent et lent pour répondre aux changements. De bien meilleures options sont les boucles à recherche de phase, les boucles à recherche de retard, les autocorrélations, le suivi max / min, le suivi de passage à zéro, etc.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *