使用 Android FFT 获取声音频率

2023-11-30

下面的代码仅显示一个图表,但我想要声音的频率。我正在尝试录制语音并获取实时频率,以便我可以弹奏钢琴或吉他声音并找到频率。

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

如何从这段代码中获取频率?


您的 FFT 代码不会给您频率。它为您提供了一组不同频率的复数值。如果您只是查看 FFT 结果的“实数”或余弦分量,而不是每个复数分量的矢量幅度,那么您的代码中可能存在错误。

FFT 后的 toTransform[i] 数组的每个元素都会为您提供一个围绕或接近 (i * sampleRate / blockSize) 的频率的复数值。您可以找到该数组幅度的最大值来估计幅度最大时的近似频率。您还可以对最大值进行插值以改进此频率估计。

但如果您正在寻找音高估计(例如吉他音符),这可能与峰值频率估计有很大不同。也许您可能想研究一些音高估计算法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Android FFT 获取声音频率 的相关文章

随机推荐