使用Android FFT获取声音频率

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

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)左右频率的复数值.您可以找到此数组幅度的最大值,以估计幅度最大的近似频率.您还可以对最大值进行插值以改善此频率估计.

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

上一篇:[ZJOI2014] 力 - FFT


下一篇:python-这个小波变换实现正确吗?