要获得PCM频率信息,需要将PCM由时域转换成频域,这里就用到了FFT算法快速傅里叶变换,里面水很深我就没有深入研究了,这里直接用的jmp123里面的FFT实现,纯js代码实现100行不到。我们只管使用就ok了,假设有44100hz采样率的16位PCM数据,取1024个采样数据经过FFT变换后,会输出512个频率信息点,每个点之间的频率间隔为44100/2/512=43hz,0hz是第1个点,1khz是第1000/43个点,以此类推,最高能识别到22050hz,有了这些频率点信息就能绘制不同频率下的音量幅度了,或者获得需要的频率分信号。
通过FFT获得了频率信息,我们就可以绘制直方图了,将所有频率点按照我们需要绘制的直方图柱子数量平均划分成频段(jmp123里面采用的非线性划分,没看懂是什么原理,就采用更多人使用的线性划分),每个频段内取最大值并转换成音量,音量计算公式:dB=20Math.log10(maxValue),然后计算实际的绘制高度:DrawMaxHeight * dB / MaxDB,DrawMaxHeight是你最大绘制高度(画布高度),MaxDB为最大音量等于20Math.log10(0x7FFF)。
这里简单回顾下傅里叶变换,它将信号从时域转换为频域,一般用于信号频谱分析,确定其成分。转换结果如下图所示:
如果只想绘制波形,这将是微不足道的。假设您要绘制一个100像素宽的位图:在帧N处,将以N * 735开头的735(44100/60)个采样,并从中抽取100个点(例如,通过线性插值)在这735个样本中进行缩放,并根据位图的垂直分辨率对其进行缩放)。如果您的PCM数据是立体声的,则可以在插值点取每对样本并将其平均。
省去一万字
拿到amp数据经过转化绘制即可