获取声音的频率与Android FFT [英] Get sound frequency with Android FFT

查看:3465
本文介绍了获取声音的频率与Android FFT的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面code只是显示的图形,但我想要的声音的频率。我想录制的声音,并获得实时的频率,这样我可以演奏钢琴或吉他的声音,找到的频率。

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

我怎样才能获得频率从这个code?

How can I get frequency from this code?

推荐答案

您FFT code不给你的频率。它给你复杂值中的一束不同频率的阵列。而且有可能在你的code中的错误,如果你只是在寻找的FFT结果,而不是每一个复杂组件的矢量幅度的真实或余弦组成部分。

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.

您toTransform的每个元素的FFT之后[I]数组给你周围或附近的频率复值(I *采样率/块大小)。你能找到这个阵列的幅度的最大值来估计近似的频率处的幅度是最大的。你也可以插最大值来提高该频率的估计。

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.

这篇关于获取声音的频率与Android FFT的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆