Использование БПФ в Android - PullRequest
0 голосов
/ 04 октября 2011

У меня возникают проблемы с пониманием того, как я должен передавать данные PCM с микрофона в этот класс FFT, который я использую, созданный Петром Вендикером (это класс DoubleFFT_1D в JTransforms).

Я думаю, что должен вернутьдействительное и мнимое число, а затем удвоите действительное число, чтобы в итоге получить Frequency = 8000 * i / 1024, где i - индекс наибольшей величины.

Может ли кто-нибудь помочь мне найти частоту сыгранной ноты?

У меня есть следующий класс записи:

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

Большое спасибо!

Бен

Ответы [ 2 ]

3 голосов
/ 04 октября 2011

Если вы ищете высоту музыкальной ноты, вы обнаружите, что высота часто отличается от пика спектральной частоты, создаваемого БПФ, особенно для более низких нот.

Чтобы найти частотный пик от комплексного БПФ, вам необходимо рассчитать векторную величину как реального, так и мнимого результата.

mag(i) = sqrt(real[i]*real[i] + imag[i]*imag[i]);
2 голосов
/ 31 августа 2012

Поскольку вы используете реальные аудиоданные в качестве входа, вы должны использовать функцию realForward:

fft.realForward(audioDataDoubles);

Затем вы можете вычислить энергию на частоте, вычислив величину действительной и мнимой частей:

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