Android:使用FFT从Mic获取频率时出错频率值

时间:2015-01-04 06:47:46

标签: android audio fft

我正在尝试使用FFT从麦克风获取频率。这里给出了 - http://www.wikijava.org/wiki/The_Fast_Fourier_Transform_in_Java_%28part_1%29

FFT函数接受三个参数,实数,虚数和布尔值。 从记录的缓冲区中获得实部和虚部。

FFT函数返回一个数组,从中计算出最大幅度的索引。 这用于获取频率。

但是当我运行应用程序时,我没有得到所需的频率值。 我的采样率/ buffersize / blocksize有问题吗? 或者计算本身是否有问题。

公共类MainActivity扩展了Activity {

int audioSource = MediaRecorder.AudioSource.MIC;    // Audio source is the device MIC
int channelConfig = AudioFormat.CHANNEL_IN_MONO;    // Recording in mono
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT; // Records in 16bit
int blockSize = 1024;                               // deal with this many samples at a time
int sampleRate = 8000;                             // Sample rate in Hz
public double frequency = 0.0;                      // the frequency given
RecordAudio recordTask;                             // Creates a Record Audio command
TextView tv;                                        // Creates a text view for the frequency
boolean started = false;
Button startStopButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    tv = (TextView) findViewById(R.id.textView1);
    startStopButton = (Button) findViewById(R.id.button1);
    startStopButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick (View v){
            if (started) {
                started = false;
                startStopButton.setText("Start");
                recordTask.cancel(true);
            }
            else{
                started = true;
                startStopButton.setText("Stop");
                recordTask = new RecordAudio();
                recordTask.execute();
            }

        }
    });
}

private class RecordAudio extends AsyncTask<Void, Double, Void> {
    @Override
    protected Void doInBackground(Void... params) {
        int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioEncoding);                // Gets the minimum buffer needed
        AudioRecord audioRecord = new AudioRecord(audioSource, sampleRate, channelConfig, audioEncoding, bufferSize);   // The RAW PCM sample recording
        short[] buffer = new short[blockSize];          // Save the raw PCM samples as short bytes
        double[] re = new double[blockSize];
        double[] im = new double[blockSize];
        double[] magnitude = new double[blockSize];
        try {
            audioRecord.startRecording();  //Start
        } catch (Throwable t) {
        }
        while (started) {
            int bufferReadResult = audioRecord.read(buffer, 0, blockSize);
            for (int i = 0; i < blockSize && i < bufferReadResult; i++) {
                re[i] =((double) buffer[i] / 32768.0); // signed 16 bit
                im[i]=0;

            }
            double[] newArray = new double[blockSize*2];
            newArray = FFTbase.fft(re, im,true);
            double real;
            double imag;
            for(int i=0;i<(newArray.length/2)-1;i++)
            {
                real=newArray[2*i];
                imag=newArray[2*i+1];
                magnitude[i]=Math.sqrt(real*real+imag*imag);
    }
            double MaxMagn=-1.0;
            int index=0;
            for (int i = 0; i < (magnitude.length); i++) {
                if (magnitude[i]>MaxMagn)
                {
                    MaxMagn = magnitude[i];
                    index=i;
                }
            }
            publishProgress((double)(index * sampleRate)/blockSize);

        }
        return null;
    }
    @Override
    protected void onProgressUpdate(Double... values) {
        TextView display = (TextView) findViewById(R.id.textView1);
        display.setText(String.valueOf(values[0]));
        }
}

这是我试过的过零法。但这也没有给我所需的频率。

公共类MainActivity扩展了Activity {

int audioSource = MediaRecorder.AudioSource.MIC;    // Audio source is the device MIC
int channelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;    // Recording in mono
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT; // Records in 16bit
int blockSize = 256;                               // deal with this many samples at a time
int sampleRate = 8000;                             // Sample rate in Hz
public double frequency = 0.0;                      // the frequency given
RecordAudio recordTask;                             // Creates a Record Audio command
TextView tv;                                        // Creates a text view for the frequency
boolean started = false;
Button startStopButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    tv = (TextView) findViewById(R.id.textView1);
    startStopButton = (Button) findViewById(R.id.button1);
    startStopButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick (View v){
            if (started) {
                started = false;
                startStopButton.setText("Start");
                recordTask.cancel(true);
            }
            else{
                started = true;
                startStopButton.setText("Stop");
                recordTask = new RecordAudio();
                recordTask.execute();
            }

        }
    });
}

private class RecordAudio extends AsyncTask<Void, Double, Void> {
    @Override
    protected Void doInBackground(Void... params) {
        int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioEncoding);                // Gets the minimum buffer needed
        AudioRecord audioRecord = new AudioRecord(audioSource, sampleRate, channelConfig, audioEncoding, bufferSize);   // The RAW PCM sample recording
        short[] buffer = new short[blockSize];          // Save the raw PCM samples as short bytes
        double[] re = new double[blockSize];
        double[] im = new double[blockSize];
        double[] magnitude = new double[blockSize];
        try {
            audioRecord.startRecording();  //Start
        } catch (Throwable t) {
        }
        int sampling=0;
        while (started) {
            sampling++;
            int bufferReadResult = audioRecord.read(buffer, 0, blockSize);




            int numCrossing=0; //initialize your number of zero crossings to 0
            int p=0;
            for (p=0;p<bufferSize/4;p+=4) {
                if (buffer[p]>0 && buffer[p+1]<=0) numCrossing++;
                if (buffer[p]<0 && buffer[p+1]>=0) numCrossing++;
                if (buffer[p+1]>0 && buffer[p+2]<=0) numCrossing++;
                if (buffer[p+1]<0 && buffer[p+2]>=0) numCrossing++;
                if (buffer[p+2]>0 && buffer[p+3]<=0) numCrossing++;
                if (buffer[p+2]<0 && buffer[p+3]>=0) numCrossing++;
                if (buffer[p+3]>0 && buffer[p+4]<=0) numCrossing++;
                if (buffer[p+3]<0 && buffer[p+4]>=0) numCrossing++;
            }//for p

            for (p=(bufferSize/4)*4;p<bufferSize-1;p++) {
                if (buffer[p]>0 && buffer[p+1]<=0) numCrossing++;
                if (buffer[p]<0 && buffer[p+1]>=0) numCrossing++;
            }



            frequency=(sampleRate/bufferSize)*(numCrossing/2);
            if(sampling>20){
            //publishProgress((double)(index * sampleRate)/bufferSize);
            publishProgress((double)frequency);
            sampling=0;
            }}
        return null;
    }

0 个答案:

没有答案