获取音频文件的频率,在Android的每1/4秒(Get the frequency of an a

2019-07-30 20:00发布

我有一个声音文件(名为.3gp)及其约〜1分钟。 我想获得这个声音文件的频率,每1/4秒。 我的想法是接收样品中每1/4秒的音频文件,并使用FFT我可能得到的频率值。 有没有办法做到这一点?

实际上我将声音文件分成1/4秒样品的声音文件(alwyas覆盖preveious之一),然后使用FFT算法和检测频率,其中magintude是bigggest。 但是,无论我没有线索如何可以做到这一点有可能是更容易的解决方案。

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

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

两个峰的大小改变的大部分时间,我总能找到最大的,以获得基本频率。

Answer 1:

间距与FFT跟踪被要求经常对堆栈溢出我写了一个与示例代码博客条目 。 该代码是C,但说明和链接,你应该能够做你想做的。

至于将它分成1/4秒为单位,你可以简单地采取1/4秒段的FFT如你所说,而不是默认的(我认为这是约1秒)。 如果不给你你想要的频率分辨率,您可能需要使用不同的音高的识别方法。 你可以做的另一件事是使用重叠是比1/4秒的时间越长,但在这相隔1/4秒的时间间隔开始细分。 这种方法是暗示了博客条目,但它可能无法满足您的设计规范。



Answer 2:

尝试的AsyncTask:

class GetFrequency extends AsyncTask<String, Void, Void> {
   public Void doInBackground(String... params) {
          while (true) {

             // Apply Logic Here

           try {
                Thread.sleep(250);
               } catch (Exception ie) {
                  // TODO Auto-generated catch block
                e.printStackTrace();
               }
       }
   }  
}

在您的MainActivity调用此,

frequencyButtonListener.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

        new GetFrequency.execute(params);

        }
    });


文章来源: Get the frequency of an audio file in every 1/4 seconds in android