C#使用 NAudio 实现音频可视化的方法
预览:
捕捉声卡输出:
实现音频可视化, 第一步就是获得音频采样, 这里我们选择使用计算机正在播放的音频作为采样源进行处理:
naudio 中, 可以借助 wasapiloopbackcapture 来进行捕捉:
分离左右通道:
获取完采样后, 我们还需要对采样进行一点小处理, 因为捕获的数据是分通道的, 一般是左右声道:
取通道平均值
将采样分为一个个通道的采样后, 我们可以将其合并, 取平均值, 以便于绘制:
绘制时域图象:
处理刚刚的采样后, 你可以直接将其作为数据绘制到窗口中, 这即是时域图象, 这里使用最简单的折线绘制.
傅里叶变换:
naudio 中还提供了快速傅里叶变换的方法, 通过傅里叶变换, 可以将时域数据转换为频域数据, 也就是我们所说的频谱
分析频域信息:
对于傅里叶变换的频域信息, 需要稍加处理才可以方便的使用, 首先是提取有用的信息:
绘制频域图象:
得到上面分析后的 finaldata 后, 我们就可以直接绘制出来了, 这次使用柔和的曲线绘制
更优的绘制:
上面的时域和频域图象, 我们都是一股脑的将数据的索引作为 x 坐标, 窗口高度减去数据值作为 y 坐标, 有两个突出的问题:
- 数据可能无法填满窗口的宽度或者超出窗口的宽度范围
- 数据太大时, 也会导致绘制的线条超出窗口高度
第一个问题好解决, 直接使索引所占数据长度的百分比恰好等于 x 坐标相对于窗口宽度的百分比即可:
\[x = index \div datalength * windowwidth\]
对于第二个问题, 有两个解决方案, 一是直接为数据加权重, 例如统一乘 0.5, 使数据减小一节, 二就是套一个函数, 例如 log 函数, 毕竟 log 函数在较高自变量的情况下, 因变量的变化趋势越来越小, 我们只需要对这个 log 函数进行稍加处理, 就可以直接应用到数据变换数据上, 使其不超出窗口绘图区域
另外, 我们也可以平滑频谱显示(指动画变换), 它的原理大概是这样:
- 例如这次进行傅里叶变换的结果是:
{0, 100, 50}
, - 下一次傅里叶变换的结果是:
{100, 0, 0}
, - 可以得出, 增量为:
{100, -100, -50}
, - 在更新变换结果时, 我们不再直接将新的结果替换旧的结果, 而是在旧的结果的基础上, 加上增量×权重
- 例如权重是
0.5
时, 那么实际增量是:{50, -50, -25}
, - 那么实际新的值是:
{50, 50, 25}
, - 如果下一次变换的结果还是
{100, 0, 0}
, 那我们再次从{50, 50, 25}
向新值逼近, 权重仍然是0.5
, 那么实际增量是:{25, -25, -12.5}
,
注意到了吗? 这次的增量是上次增量的一半, 这正好是一个减速运动, 而且新值与旧值的差越大, 变化的就越快, 而它们会不断重合, 因而速度不断变慢, 形成减速运动的频谱图.
更多内容: