在android中,如何实时获得正确的频率值?

Posted

技术标签:

【中文标题】在android中,如何实时获得正确的频率值?【英文标题】:In android, How can I get the correct value of frequency in real time? 【发布时间】:2014-03-25 04:19:39 【问题描述】:

我已经查看了这里的每一个答案,但我不明白它们......我能够获得图表,但我怎么能只有一个当前频率的值......我更喜欢代码答案比数学的..

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

            //  double[] audioDataDoubles = new double[(blockSize*2)]; // Same values as above, as doubles
            //   -----------------------------------------------
            double[] re = new double[blockSize];
            double[] im = new double[blockSize];
            double[] magnitude = new double[blockSize];
            int sampleRate = 8000;                             // Sample rate in Hz

            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) 
                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) 
            t.printStackTrace();
            Log.e("AudioRecord", "Recording Failed");
        
        return null;
    
    public   double Index2Freq(int i, double samples, int nFFT) 
        return (double) i * (samples / nFFT / 2.);
    
    public   int calculateF(int sampleRate, double [] audioData)

        int numSamples = audioData.length;
        int numCrossing = 0;
        for (int p = 0; p < numSamples-1; p++)
        
            if ((audioData[p] > 0 && audioData[p + 1] <= 0) ||
                    (audioData[p] < 0 && audioData[p + 1] >= 0))
            
                numCrossing++;
            
        

        float numSecondsRecorded = (float)numSamples/(float)sampleRate;
        float numCycles = numCrossing/2;
        float frequency = numCycles/numSecondsRecorded;

        return (int)frequency;
    

    @Override
    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();

           TxtV.setText("Frequency = "+String.valueOf(calculateF(8000, toTransform[0])));

        // TODO Auto-generated method stub
        // super.onProgressUpdate(values);
    


【问题讨论】:

可能你不喜欢你找到的答案,因为现实并不简单。就是说只有一个频率存在?而且您找到的组件的频率分辨率受到计算傅里叶变换的样本数量的限制(尽管您可以通过零填充在有限程度上作弊)。 我基本上是在寻找根据 toTransform[0] 元素获得正确计算频率的代码 寻找最强的,将bin数转换回频率。如果您发现它令人困惑,请使用已知输入运行测试用例。 如何将 bin 编号转换回频率 用已知的输入做一些实验,你会比让别人给你答案更彻底地理解。 【参考方案1】:

如果您所说的当前频率是指捕获的音频,请意识到现场声音是由大量频率组成的,因此您永远不会只得到一个频率结果。

即使对于单个音高也是如此(可能除了在零噪声下合成的纯正弦测试数据)。

【讨论】:

那么我想做与大多数其他应用程序一样的事情......他们以某种方式给出了一个高度准确的频率!

以上是关于在android中,如何实时获得正确的频率值?的主要内容,如果未能解决你的问题,请参考以下文章

android 如何实时修改cpu频率

如何获得 FFT 中每个值的频率?

如何在 Android 上生成复杂的声音?

当实时数据将由 FCM 更改时,我如何在 android 中获得通知?

具有高分辨率的实时 FFT,同时保持低延迟

C 语言中的数字频率问题,无法为大输入获得正确的频率