–
音频可视化,顾名思义就是将声音以视觉的方式呈现出来。如何将音频信号绘制出来?如何将声音的变化在视觉上清晰的表现出来,让视觉和听觉上的感受一致?这些在 Android 上如何实现?本文将针对这些问题做出解答,尽量对 Android 上的音频可视化实现做一个全面的介绍。
傅里叶变换
Android 音频播放的一般流程是:
- 播放器从本地音频文件或网络加载编码后的音频数据,解码为 pcm 数据写入
AudioTrack
AudioTrack
将 pcm 数据写入 FIFOAudioFlinger
中的MixerThread
通过AudioMixer
读取 FIFO 中的数据进行混音后写入 HAL 输出设备进行播放
在这个流程中,直接体现音频特征,可用于可视化绘制的是 pcm 数据。但 pcm 表示各采样时间点上音频信号强度,看起来杂乱无章,难以体现听觉感知到的声音变化。pcm 数据仅可用来绘制体现音频信号平均强度变化的可视化动效,其他大部分动效需要使用对 pcm 数据做傅里叶变换后得到的体现各频率点上信号强度变化的频域数据来绘制。
这里简单回顾下傅里叶变换,它将信号从时域转换为频域,一般用于信号频谱分析,确定其成分。转换结果如下图所示:
pcm 数据是时间离散的,需要使用离散傅里叶变换(DFT),它将包含 N 个复数的序列 {xn}:=x0,x1,…,xN−1\{x_n\}:=x_0, x_1, …, x_{N-1}{xn}:=x0,x1,…,xN−1 转换为另一个复数序列 {Xk}:=X0,X1,…,XN−1\{X_k\}:=X_0, X_1, …, X_{N-1}{Xk}:=X0,X1,…,XN−1,计算公式为:
Xk=∑n=0N−1xn⋅e−i2πknN=∑n=0N−1xn⋅(cos(2πknN)−i⋅sin(2πknN))X_k=\sum_{n=0}^{N-1}x_n \cdot e^{-i2 \pi {kn \over N}}=\sum_{n=0}^{N-1}x_n \cdot (cos(2\pi {kn \over N})-i \cdot sin(2\pi {kn \over N}))Xk=n=0∑N−1xn⋅e−i2πNkn=n=0∑N−1xn⋅(cos(2πNkn)−i⋅sin(2πNkn))
直接用上面公式计算长度为 N 的序列的 DFT,时间复杂度为 O(N2)O(N^2)O(N2),速度较慢,实际应用中,一般会使用快速傅里叶变换(FFT),将时间复杂度降为 O(Nlog(N))O(Nlog(N))O(Nlog(N