引言
音频可视化,就是将声音的变化以视觉的方式呈现出来
我们在上篇文章中通过FFmpeg解码了本地mp4文件的音频码流为PCM数据,并通过AudioTrack进行播放
Android FFmpeg系列05--音频解码与播放
播放流程如下
在这个流程中,直接体现音频特征,可用于可视化绘制的就是PCM数据
PCM表示各采样时间点上音频信号的强度,如果我们需要体现各频率点上信号强度变化的话,那么需要先对PCM数据做傅立叶变换
(信号从时域转换为频域)
PCM数据是时间离散的,需要用离散傅立叶变换(DFT)
其中N为时域离散信号的点数,n为时域离散信号的编号(取值范围为0~N-1),m为频域信号的编号(取值范围为0~N-1),频域信号的点数也为N
因此离散傅里叶变换的输入为N个离散的点(时域信号),输出为N个离散的点(频域信号,频域信号的每个点都用一个复数表示)
DFT的特性
(来自参考1)
直接采用公式计算长度为N的序列的DFT,时间复杂度是非常高的
实际应用中我们一般采用快速傅立叶变换(FFT),支持FFT的开源库也非常多,比如Ne10
Ne10的编译与使用
Visualizer
从前面的内容我们可以知道音频可视化涉及的知识点是非常多的,不过我们只需要了解基本原理即可,Google已经提供好了用于音频可视化的轮子,直接拿来用就行
Android系统提供了Visualizer
类,它能让app拿到当前正在播放音频的音频波形数据和FFT数据,用于快速实现音频可视化
一般使用方式如下:
- 首先获取
RECORD_AUDIO
的权限(主要是为了保护某些语音信息的隐私,比如语音邮件) - 用audio sessioin ID创建
Visualizer
类,传0可获取混音后的可视化数据,传特定播放器或者AudioTrack
提供的ID,可获取它们播放音频的可视化数据 - 调用
setCaptureSize
方法设置每次获取的数据大小 - 调用
setDataCaptureListener
方法设置数据回调并制定获取数据频率和数据类型 - 调用
setEnabled
方法开始获取数据 - 不需要使用时调用
release
方法释放资源
在FFmpeg系列教程提供的Demo中,我们添加初始化的Visualizer逻辑
当FFmpeg实时解码音频PCM数据并喂给AudioTrack后,通过Visualizer
不停回调FFT数据
FFT数据的布局如下
以设置captureSize为1024为例:
每1024个实数点放入一个数组,进行FFT变换后得到1024个复数点,其中一共
1 1 (1024 - 2) / 2 = 513个有效FFT数据
获取振幅,然后使用OpenGL或者自定义View绘制即可
这里采用自定义View绘制,音频可视化圆形效果如下
Visualizer
输出的数据大小正比于音量,所以测试的时候手机音量不能调节为0,为0的话输出数据也是0,自定义View上就只能看到一个圆了
最后
网易云音乐大前端团队曾经有篇文章里面说到使用系统Visualizer存在兼容性问题,在有些机型上会导致系统音效失效,如果要在所有机型上都能无副作用的展示音频动效,需要自定义Visualizer,感兴趣的同学可以看看这篇文章,也就是下面的参考1
参考
1.【Android音频可视化】
https://blog.csdn.net/m0_47390782/article/details/109484598
2.【dft公式是什么】
https://baijiahao.baidu.com/s?id=1725625050147421696&wfr=spider&for=pc
~~END~~