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 < 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:
表示要获取幅度和相位可以用一下公式:
//在网页中 < 表示小于号
//再快速傅立叶变换中 采取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]);
}
相位对我们并无作用,幅度和频率相关,结果就是返回的幅度的数组。由于是频域信息 ,下标就表示频率的信息,幅度就表示该频率对应的能量。幅度越大能量越大 。表示该段声音有不同的频率组成,如果硬取一个频率的话就取幅度最大的,即能量最大的频率代表该段声音的频率
频率公式 :
(下标*采样频率)/采样大小