Android 音频FFT提取分析

通过Record_Audio获取MediaPlayer播放器的声音,利用自带的FFT功能进行音频分析

放于线程中

visualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1])
设置采样窗口1024点(实测:当大于1024时,例如4096,android仍然取1024)


n=getCaptureSize()
即 n = 1024

每1024个实数点放入一个数组,进行FFT快速傅里叶变换,得到1024个复数点,由于对称性,前512个点与后512个点对称,取前513个点(包括第0点)

其中第0点和第512点为实数,中间511点为复数


onFftDataCapture(Visualizer visualizer, byte[] bytes, int samplingRate)
FFT数据为byte类型,放于byte[1024]中,其中一共1+1+(1024-2)/2=513个有效FFT数据

除了直流和n/2对应的点占一个坑儿,其他频率数据都是 实部+i虚部 两个坑儿



bytes[i]
直流 实数 实部 虚部 实部 虚部 …… 实部 虚部
0 1 2 3 4 5   n-2 n-1
R0 Rn/2 R1 L1 R2 L2   R(n-1)/2 L(n-1)/2

获得的频率范围= 0~采样率/2 = 0~22.05kHz之间

即513个频率分布在 [ 0Hz,22.05kHz ]之间


每相邻两个频率间隔(mHz) = 采样率 / (1024 / 2) = 44 100 000 / 512 = 86.132Hz分辨率为86.132Hz,再小的频率间隔将无法分辨

采样率:每秒采集音频流的点数

frequencyEach = samplingRate * 2 / visualizer.getCaptureSize();  //86132  samplingRate=44,100,000 mHz  getCaptureSize()=1024

k为0~512中的某个点,第k个点对应的频率 = k * frequencyEach,亦即

k(Hz)=getSamplingRate() * k /(getCaptureSize()/2)

完整代码,写在线程中执行

new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    if (mediaPlayer.isPlaying())
                    {

                        try
                        {
                            Visualizer visualizer = new Visualizer(mediaPlayer.getAudioSessionId());     //mediaPlayer.getAudioSessionId()=1538 1540 1542...
                            visualizer.setEnabled(false);
                            visualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]); /** 64,128,256,512,1024 */  //前面若没有setEnabled(false)  会在此出异常
                            visualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener()
                            {
                                //采集波形数据
                                @Override
                                public void onWaveFormDataCapture(Visualizer visualizer, byte[] wave, int samplingRate)
                                {

                                }
                                //采集FFT数据   bytes数组大小=
                                @Override
                                public void onFftDataCapture(Visualizer visualizer, byte[] bytes, int samplingRate)
                                {
                                    //   直流      实部 虚部      频率范围 0-采样率/2 getSamplingRate()
                                    //    0    1    2    3    4    5       n-2       n-1        n=getCaptureSize()
                                    //    R0  Rn/2 R1   L1    R2   L2    R(n-1)/2  L(n-1)/2
                                    //   k次频率 = getSamplingRate() * k / (n/2)                   int getFft (byte[] fft)
                                    int frequencyCounts = bytes.length/2+1; //  =513
                                    fft = new byte[frequencyCounts];    //  (n-2)/2+2 = n/2+1  容量 = getCaptureSize()/2+
                                    fft[0] = (byte) Math.abs(bytes[0]);
                                    for (int i = 1; i390)
                                        {
                                            WaveHeight[i] = 390;
                                        }
                                    }
                                }
                            },Visualizer.getMaxCaptureRate()/2,false,true); //rate(采样周期 mHz)  isWave  isFFT
                            visualizer.setEnabled(true);
                        }
                        catch (Exception e)
                        {
                            e.printStackTrace();//这里没有WaveHeight异常
                        }
                    }
                }
            }).start();

        }
        catch (Exception e)
        {
            flagTest = 233;
            e.printStackTrace();
        }


 
 

你可能感兴趣的:(Android 音频FFT提取分析)