Get sound frequency with Android FFT

删除回忆录丶 提交于 2019-11-29 23:12:49

问题


The following code just shows a graph, but I want the sound's frequency. I am trying to record voice and get real-time frequency, so that I can play a piano or guitar sound and find the frequency.

public class AudioProcessing extends Activity implements OnClickListener {

int frequency = 8000;
int channelConfiguration = AudioFormat.CHANNEL_CONFIGURATION_MONO;
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;

private RealDoubleFFT transformer;
int blockSize = 256;

Button startStopButton;
boolean started = false;

RecordAudio recordTask;

ImageView imageView;
Bitmap bitmap;
Canvas canvas;
Paint paint;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    startStopButton = (Button) this.findViewById(R.id.StartStopButton);
    startStopButton.setOnClickListener(this);

    transformer = new RealDoubleFFT(blockSize);

    imageView = (ImageView) this.findViewById(R.id.ImageView01);
    bitmap = Bitmap.createBitmap((int) 256, (int) 100,
            Bitmap.Config.ARGB_8888);
    canvas = new Canvas(bitmap);
    paint = new Paint();
    paint.setColor(Color.GREEN);
    imageView.setImageBitmap(bitmap);
}



private class RecordAudio extends AsyncTask<Void, double[], Void> {
    @Override
    protected Void doInBackground(Void... params) {
        try {
            int bufferSize = AudioRecord.getMinBufferSize(frequency,
                    channelConfiguration, audioEncoding);

            AudioRecord audioRecord = new AudioRecord(
                    MediaRecorder.AudioSource.MIC, frequency,
                    channelConfiguration, audioEncoding, bufferSize);

            short[] buffer = new short[blockSize];
            double[] toTransform = new double[blockSize];

            audioRecord.startRecording();

            while (started) {
                int bufferReadResult = audioRecord.read(buffer, 0,
                        blockSize);

                for (int i = 0; i < blockSize && i < bufferReadResult; i++) {
                    toTransform[i] = (double) buffer[i] / 32768.0; // signed
                    // 16
                    // bit
                }

                transformer.ft(toTransform);

                publishProgress(toTransform);
            }

            audioRecord.stop();
        } catch (Throwable t) {
            Log.e("AudioRecord", "Recording Failed");
        }

        return null;
    }

    protected void onProgressUpdate(double[]... toTransform) {
        canvas.drawColor(Color.BLACK);

        for (int i = 0; i < toTransform[0].length; i++) {
            int x = i;
            int downy = (int) (100 - (toTransform[0][i] * 10));
            int upy = 100;

            canvas.drawLine(x, downy, x, upy, paint);
        }
        imageView.invalidate();
    }
}

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();
    }
}
  }

How can I get frequency from this code?


回答1:


Your FFT code doesn't give you frequency. It gives you an array of complex values at a bunch of different frequencies. And there may be a bug in your code if you are just looking at the "real" or cosine component of the FFT result instead of the vector magnitude of each complex component.

Each element of your toTransform[i] array after the FFT gives you a complex value for frequencies around or near (i * sampleRate / blockSize). You could find the maxima of the magnitudes of this array to estimate the approximate frequency at which the magnitude was greatest. You could also interpolate the maxima to improve this frequency estimate.

But if you are looking for a pitch estimate (of a guitar note for instance), that can be very different from a peak frequency estimate. Perhaps you might want to look into some pitch estimation algorithms instead.



来源:https://stackoverflow.com/questions/9325123/get-sound-frequency-with-android-fft

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!