java - 在 Android 中使用 FFT

标签 java android fft pcm

我无法理解如何将 PCM 数据从麦克风传递到我正在使用的由 Piotr Wendykier 制作的 FFT 类(它是 JTransforms 中的 DoubleFFT_1D 类)。

我想我必须返回一个实数和虚数,然后将实数加倍才能最终获得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

非常感谢!

最佳答案

如果您正在寻找音符的音高,您会发现音高通常与 FFT 生成的频谱频率峰值不同,尤其是对于低音音符。

要从复数 FFT 中找到频率峰值,您需要计算实部和虚部结果的 vector 幅度。

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

关于java - 在 Android 中使用 FFT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7651633/

相关文章:

java - 为什么 Arrays.fill() 不再在 HashMap.clear() 中使用?

android - 如何在android中读取谷歌地图的kmz文件

java - 将 POI 与 gradle 一起使用时出现重复输入错误

python - 在 Python 中绘制快速傅里叶变换

java - MyISAM 存储引擎在 Java Hibernate 中更可取吗?

java - 使用 Jackson 在有或没有编码(marshal)处理的情况下构建自定义 JSON?

java - 关于java列表删除的问题

android - 有滚动条时 map 对触摸没有反应

linux - 编译 Fortran 示例时找不到 -lfftw

matlab - 为什么频率不对?