Android 实时获取播放音乐的频率 Visualizer用法

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/gongziwushuang/article/details/84853478

Android 实时获取播放音乐的频率 Visualizer用法

前言

笔者正在做的项目有播放声音并实时获取声音音频的需求,在网上搜了许久,都找不到一个满意的答案。于是自己去翻了谷歌文档和请教自己固件的同事,整理出来一套供大家参考

Visualizer 的用法

//声明MediaPlayer 
 mMediaPlayer = new MediaPlayer();
 //声明Visualizer
 visualizer = new Visualizer(mMediaPlayer.getAudioSessionId());
 //设置采样大小
 visualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);  
 
 /**
 *设置采样监听    
 *参数一 监听回调
 *参数二 采样频率
 *参数三 是否获取波形信息
 * 参数四 是否获取fft变换后的信息
 */
 visualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() {
            @Override
            /**
            * 返回波形信息
            */
            public void onWaveFormDataCapture(Visualizer visualizer, byte[] waveform, int samplingRate) {
        

            }

            @Override
            /**
            *返回经过fft变换后的信息
            */
            public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) 					{
      


            }
        }, Visualizer.getMaxCaptureRate() / 2, true, true);
	//开启采样
        visualizer.setEnabled(true);

在结束时不要忘记调用

	 visualizer.setEnabled(false);	 
        if (visualizer != null) {
            visualizer.release();
        }

onFftDataCapture 讲解

/**
*
*visualizer  放返回采样的visualizer
*fft 经傅立叶快速变化后的数据
*samplingRate 手机的采样频率
*/
public void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate) 

傅立叶变换 就是把时域变换为频域
简单来说 时域就是横坐标表示为时间
频域就是横坐标表示为频率
进入谷歌源码 文档关于onFftDataCapture的注解为

  /**
         * Method called when a new frequency capture is available.
         * <p>Data in the fft buffer is valid only within the scope of the callback.
         * Applications which need access to the fft data after returning from the callback
         * should make a copy of the data instead of holding a reference.
         *
         * <p>In order to obtain magnitude and phase values the following formulas can
         * be used:
         *    <pre class="prettyprint">
         *       for (int i = 0; i &lt; fft.size(); i += 2) {
         *           float magnitude = (float)Math.hypot(fft[i], fft[i + 1]);
         *           float phase = (float)Math.atan2(fft[i + 1], fft[i]);
         *       }</pre>
         * @param visualizer Visualizer object on which the listener is registered.
         * @param fft array of bytes containing the frequency representation.
         *    The fft array only contains the first half of the actual
         *    FFT spectrum (frequencies up to Nyquist frequency), exploiting
         *    the symmetry of the spectrum. For each frequencies bin <code>i</code>:
         *    <ul>
         *      <li>the element at index <code>2*i</code> in the array contains
         *          the real part of a complex number,</li>
         *      <li>the element at index <code>2*i+1</code> contains the imaginary
         *          part of the complex number.</li>
         *    </ul>
         * @param samplingRate sampling rate of the visualized audio.
         */
        void onFftDataCapture(Visualizer visualizer, byte[] fft, int samplingRate);

其中 In order to obtain magnitude and phase values the following formulas can be used:表示要获取幅度和相位可以用一下公式:

//在网页中 &lt; 表示小于号
//再快速傅立叶变换中 采取1024 的字节数组 会返回1024个复数,即有实数和虚数组成
//由于快速傅立叶的对称性。Google只返回前512个复数,其中下标为单数的为实数,下标为双的为虚数。
 for (int i = 0; i < fft.size(); i += 2) {
  float magnitude = (float)Math.hypot(fft[i], fft[i + 1]);
  float phase = (float)Math.atan2(fft[i + 1], fft[i]);
 }

相位对我们并无作用,幅度和频率相关,结果就是返回的幅度的数组。由于是频域信息 ,下标就表示频率的信息,幅度就表示该频率对应的能量。幅度越大能量越大 。表示该段声音有不同的频率组成,如果硬取一个频率的话就取幅度最大的,即能量最大的频率代表该段声音的频率
频率公式 :

(下标*采样频率)/采样大小

Demo

项目地址

猜你喜欢

转载自blog.csdn.net/gongziwushuang/article/details/84853478