引言
微信读书有一个录音功能需求:
-
录音时绘制音频波形, 音频以 wav 格式保存
-
再次进入界面,加载 wav,重新渲染音频波形
步骤 1 通过 NSRecorder.averagePowerForChannel 方法获取当前录音的分贝 数组,绘制波形图
步骤 2 需要从 wav 推算出分贝波形图。然而根据分贝公式推算出来的结果如下图所示,与步骤 1 不一致:
不一致的原因,可能是步骤 1 通过硬件 DSP 计算得到 mic 的分贝,与 2 通过公式计算 wav 分贝的算法不同。
我们要解决这样的问题:拟合一个公式,输入一段 wav 采样的均方根值 ,输出估算的分贝 ,使其近似等于 averagePowerForChannel 返回的值 。
我们通过收集数据,建立线性回归模型,调参,验证等步骤,成功得到了波形图还原方程:
最终,还原了近似波形图:
数据收集
在步骤 1,在每个绘制时刻,打印出 NSRecorder.averagePowerForChannel,即 。录音完成后,得到 wav 文件。
解析 wav 文件,计算每个 对应时间段的 wave 的方均根(root mean square value),即 。
记 为 y,记 为 x,得到训练数据格式如下
1 | # input.csv |
建立线性回归模型
考虑分贝计算公式 wiki
用 R 语言建立线性回归模型,拟合 formula = y ~ log(x)
1 | dat <- read.csv('data/input.csv') |
对一段 87秒的录音,拟合残差(residuals)和系数(coeeficient)为:
1 | Call: |
调参
得到上述方程后,精度有待提高。
我们用 python 读取 wav,通过上述方程计算分贝波形图,不断调整参数,使拟合波形(左上图)更加接近目标(右上图)。
最终得到还原方程: