2011-10-04 5 views
0

Je n'arrive pas à comprendre comment transmettre les données PCM du micro à cette classe FFT utilisée par Piotr Wendykier (c'est la classe DoubleFFT_1D dans JTransforms).Utilisation de FFT sous Android

Je pense que je dois retourner un nombre réel et imaginaire, puis doubler le nombre réel pour finalement obtenir Fréquence = 8000 * i/1024 où i est l'indice de la magnitude la plus élevée.

Quelqu'un peut-il m'aider à trouver la fréquence d'une note jouée?

J'ai une classe d'enregistrement comme suit:

import edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D; 

...other various imports... 

class recorderThread { 

...public variables... 

    public static void getFFtresult(){ 

     AudioRecord recorder; 
      short[] audioData; 
      int bufferSize; 
      int samplerate = 8000;//or 8192? 


      bufferSize= AudioRecord.getMinBufferSize(samplerate,AudioFormat.CHANNEL_CONFIGURATION_MONO, 
AudioFormat.ENCODING_PCM_16BIT)*2; //get the buffer size to use with this audio record 

recorder = new AudioRecord (AudioSource.MIC,samplerate,AudioFormat.CHANNEL_CONFIGURATION_MONO, 
AudioFormat.ENCODING_PCM_16BIT,bufferSize); //instantiate the AudioRecorder 

recording=true; //variable to use start or stop recording 
audioData = new short [bufferSize]; //short array that pcm data is put into. 

int recordingLoops = 0; 

while (recordingLoops < 4) { //loop while recording is needed 

    if (recorder.getState()==android.media.AudioRecord.STATE_INITIALIZED) // check to see if the recorder has initialized yet. 
    if (recorder.getRecordingState()==android.media.AudioRecord.RECORDSTATE_STOPPED) 
      recorder.startRecording(); //check to see if the Recorder has stopped or is not recording, and make it record. 

    else { 
     recorder.read(audioData,0,bufferSize); //read the PCM audio data into the audioData array 

     DoubleFFT_1D fft = new DoubleFFT_1D(1023); //instance of DoubleFFT_1D class 

     double[] audioDataDoubles = new double[1024]; 

     for (int j=0; j <= 1023; j++) { // get audio data in double[] format 
      audioDataDoubles[j] = (double)audioData[j];   
     } 

     fft.complexForward(audioDataDoubles); //this is where it falls 

     for (int i = 0; i < 1023; i++) { 
      Log.v(TAG, "audiodata=" + audioDataDoubles[i] + " no= " + i); 
     } 

     recordingLoops++; 
     }//else recorder started 

    } //while recording 

    if (recorder.getState()==android.media.AudioRecord.RECORDSTATE_RECORDING) recorder.stop(); //stop the recorder before ending the thread 
    recorder.release(); //release the recorders resources 
    recorder=null; //set the recorder to be garbage collected 

    }//run 

}//recorderThread 

Merci beaucoup!

Ben

+0

en double (même utilisateur): [JTransforms FFT dans les applications de données PCM] (http://stackoverflow.com/questions/7649003/jtransforms-fft-in-android-from-pcm-data) –

+0

C'est en obtenant les données réelles et imaginaires que je demande, je peux sembler passer n'importe quoi à la FFT –

Répondre

3

Si vous recherchez la hauteur d'une note musicale, vous constaterez que le pas est souvent différent du pic de fréquence spectrale produite par une FFT, en particulier pour les notes inférieures.

Pour trouver le pic de fréquence d'une FFT complexe, vous devez calculer l'amplitude vectorielle des résultats réels et imaginaires.

mag(i) = sqrt(real[i]*real[i] + imag[i]*imag[i]); 
2

Puisque vous utilisez de vraies données audio comme entrée, vous devez utiliser la fonction realForward:

fft.realForward(audioDataDoubles); 

Ensuite, vous pouvez calculer l'énergie sur une fréquence en calculant l'amplitude des parties réelles et imaginaires:

magn[i] = audioDataDoubles[2*i]*audioDataDoubles[2*i] + audioDataDoubles[2*i+1]*audioDataDoubles[2*i+1] 
+0

En fait vous avez une puissance de calcul de 2 de magnitude. Pour l'ampleur, vous devez utiliser sqrt. –