android - 在android中每1/4秒获取音频文件的频率

标签 android audio fft frequency

我有一个声音文件 (.3gp),大约 1 分钟。我想每 1/4 秒获取一次该声音文件的频率。我的想法是每 1/4 秒从音频文件中接收样本并使用 FFT 我可能会得到频率值。有什么办法吗?

实际上我会将声音文件拆分为 1/4 秒样本声音文件(总是覆盖之前的声音文件),然后使用 FFT 算法并检测幅度最大的频率。但可能有更简单的解决方案,但我也不知道如何做到这一点。

***更新 2 - 新代码

到目前为止我使用这段代码:

public class RecordAudio extends AsyncTask<Void, double[], Void> {

    @Override
    protected Void doInBackground(Void... arg0) {

        try {
             int bufferSize = AudioRecord.getMinBufferSize(frequency,
             AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);


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


            // started = true; hopes this should true before calling
            // following while loop

            while (started) {
               sampling++;

               double[] re = new double[blockSize];
               double[] im = new double[blockSize];

               double[] newArray = new double[blockSize*2];
               double[] magns = new double[blockSize];

               double MaxMagn=0;
               double pitch = 0;

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


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

               newArray = FFTbase.fft(re, im,true);

               for (int i = 0; i < newArray.length; i+=2) {

                   re[i/2]=newArray[i];
                   im[i/2]=newArray[i+1];
                   magns[i/2] = Math.sqrt(re[i/2]*re[i/2]+im[i/2]*im[i/2]);
               }

              // I only need the first half      

              for (int i = 0; i < (magns.length)/2; i++) {
                   if (magns[i]>MaxMagn)
                   {
                       MaxMagn = magns[i];
                       pitch=i;
                   }
               }                                           
                 if (sampling > 50) {
                   Log.i("pitch and magnitude", "" + MaxMagn + "   " + pitch*15.625f);
                   sampling=0;
                   MaxMagn=0;pitch=0;
                   }                   


            }

            audioRecord.stop();

        } catch (Throwable t) {
            t.printStackTrace();
            Log.e("AudioRecord", "Recording Failed");
        }
        return null;
    }

我用这个:http://www.wikijava.org/wiki/The_Fast_Fourier_Transform_in_Java_%28part_1%29

吉他弦貌似是对的,但是我自己的音色不好是因为这个:

enter image description here

两个峰值的幅度大部分时间都在变化,我总是找到最大的以获得基频。

最佳答案

在 Stack Overflow 上经常询问使用 FFT 进行音高跟踪,我写了一个 blog entry with sample code .代码是用 C 语言编写的,但有了解释和链接,您应该能够做您想做的事。

至于将它分成 1/4 秒的增量,您可以按照您的建议简单地采用 1/4 秒段的 FFT,而不是默认值(我认为大约是 1 秒)。如果这不能为您提供所需的频率分辨率,您可能必须使用不同的音高识别方法。您可以做的另一件事是使用长度超过 1/4 秒的重叠 fragment ,但以相隔 1/4 秒的间隔开始。博客条目中提到了此方法,但它可能不符合您的设计规范。

关于android - 在android中每1/4秒获取音频文件的频率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11844914/

相关文章:

Android xml CSS 类似布局边距

android - Android-从没有android.permission.WRITE_EXTERNAL_STORAGE的 Assets 中播放声音

fft.rfft 的 Python 绘图频率

python - 使用 Pytorch 实现 FFT

java - 如何在 Android 中将 JSON 参数作为 Web 服务请求发送?

Android——首次启动互动教程

android-layout - Android layout-sw600dp 不适用于 8"Galaxy Tab

java - 尝试播放 AudioClip 时出现 NullPointerException

javascript - 每页上的音量按钮控制

java - FFT 中频率检测的问题