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

前端之家收集整理的这篇文章主要介绍了在android中每1/4秒获取一个音频文件的频率前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个声音文件(.3gp),大概约1分钟.我想每1/4秒获得一次这个声音文件的频率.我的想法是每隔1/4秒从音频文件接收采样并使用FFT我可能得到频率值.有没有办法做到这一点?

实际上我会将声音文件分成1 / 4sec样本声音文件(alwyas覆盖这些声音文件),然后使用FFT算法并检测magintude最大的频率.但是可能有更简单的解决方案,但我也不知道如何做到这一点.

***更新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,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

吉他弦似乎是正确的,但我自己的声音并不好,因为:

两个峰值的大小在大部分时间都会发生变化,我总能找到最大值来获得基频.

解决方法

我经常在Stack Overflow上询问使用FFT的音高跟踪我写了一个 blog entry with sample code.代码在C中,但是通过解释和链接,你应该能够做你想做的事情.

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

原文链接:https://www.f2er.com/android/310230.html

猜你在找的Android相关文章