java - Android应用程序可实时录制声音并识别频率

标签 java android fft android-audiorecord frequency-analysis

我需要开发一个应用程序来使用手机的麦克风实时记录频率,然后显示它们(以文本形式)。我在这里发布我的代码。 FFT 和复数类已从 http://introcs.cs.princeton.edu/java/97data/FFT.java.html 开始使用和 http://introcs.cs.princeton.edu/java/97data/Complex.java.html .问题是当我在模拟器上运行它时,频率从某个随机值开始并一直增加到 7996。然后它重复整个过程。有人可以帮我吗?

public class Main extends Activity {

TextView disp;
private static int[] sampleRate = new int[] { 44100, 22050, 11025, 8000 };
short audioData[];
double finalData[];
int bufferSize,srate;
String TAG;
public boolean recording;
AudioRecord recorder;
Complex[] fftArray;
float freq;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    disp = (TextView) findViewById(R.id.display);

    Thread t1 = new Thread(new Runnable(){

        public void run() {

            Log.i(TAG,"Setting up recording");
            for (int rate : sampleRate) {
                try{

                    Log.d(TAG, "Attempting rate " + rate);

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

            if (bufferSize != AudioRecord.ERROR_BAD_VALUE) {

            recorder = new AudioRecord (MediaRecorder.AudioSource.MIC,rate,AudioFormat.CHANNEL_CONFIGURATION_MONO,
            AudioFormat.ENCODING_PCM_16BIT,2048); //instantiate the AudioRecorder
            Log.d(TAG, "BufferSize " +bufferSize);
            srate = rate;

            }

            } catch (Exception e) {
                Log.e(TAG, rate + "Exception, keep trying.",e);
            }
        }
            bufferSize=2048;
            recording=true; //variable to use start or stop recording
            audioData = new short [bufferSize]; //short array that pcm data is put into.
            Log.i(TAG,"Got buffer size =" + bufferSize);                
            while (recording) {  //loop while recording is needed
                   Log.i(TAG,"in while 1");
            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 {
                   Log.i(TAG,"in else");
                  // audiorecord();
                finalData=convert_to_double(audioData);
                Findfft();
                for(int k=0;k<fftArray.length;k++)
                {
                    freq = ((float)srate/(float) fftArray.length) *(float)k;
                    runOnUiThread(new Runnable(){
                     public void run()
                     {
                         disp.setText("The frequency is " + freq);
                         if(freq>=15000)
                             recording = false;
                     }
                 });


                }


             }//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

    });
    t1.start();
}





private void Findfft() {
    // TODO Auto-generated method stub
    Complex[] fftTempArray = new Complex[bufferSize];
    for (int i=0; i<bufferSize; i++)
    {
        fftTempArray[i] = new Complex(finalData[i], 0);
    }
    fftArray = FFT.fft(fftTempArray);
}


private double[] convert_to_double(short data[]) {
    // TODO Auto-generated method stub
    double[] transformed = new double[data.length];

    for (int j=0;j<data.length;j++) {
    transformed[j] = (double)data[j];
    }

    return transformed;

}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
 }
 }       

最佳答案

您的问题已得到简洁回答,但是,为了进一步实现您的目标并完成循环...

是的,FFT 在有限的 CPU 上不是最佳的音调/频率识别。 YIN 描述了一种更优化的方法 here .您可以在 Tarsos 找到一个实现. 您将面临的问题是 ADK 中缺少 javax.sound.sampled,因此将短裤/字节从 AudioRecord 转换为引用实现所需的 float 。

关于java - Android应用程序可实时录制声音并识别频率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16982623/

相关文章:

android - layout_gravity ="center_vertical"不工作

android - 如何向发送和接收的 WebRTC 视频轨道添加模糊和背景模糊

Android 将父 View 的 'pressed' 状态传递给 subview

python - 如何找到脉冲的频率?

java - J2me 的 FFT 示例

java - 将值发送到 android ndk 中的 C 并获取示例(if)响应

java - 包名与导入的包冲突

java - 如何在运行时根据泛型类型定义和运行时类型参数构建 Java 类型对象?

java - 使用正则表达式进行 tar 扩展名匹配

matlab - 从相位和幅度获取傅里叶变换 - Matlab