R 语言线性回归应用:拟合 iOS 录音波形图
引言
微信读书有一个录音功能需求:
- 录音时绘制音频波形, 音频以 wav 格式保存
- 再次进入界面,加载 wav,重新渲染音频波形
步骤 1 通过 NSRecorder.averagePowerForChannel 方法获取当前录音的分贝 $$L_p$$ 数组,绘制波形图
步骤 2 需要从 wav 推算出分贝波形图。然而根据分贝公式推算出来的结果如下图所示,与步骤 1 不一致:
不一致的原因,可能是步骤 1 通过硬件 DSP 计算得到 mic 的分贝,与 2 通过公式计算 wav 分贝的算法不同。
我们要解决这样的问题:拟合一个公式,输入一段 wav 采样的均方根值 prmsp_{rms}prms,输出估算的分贝 Lp~tilde{L_p}Lp~ ,使其近似等于 averagePowerForChannel 返回的值 LpL_pLp。
我们通过收集数据,建立线性回归模型,调参,验证等步骤,成功得到了波形图还原方程:
Lp~=−80+6log2prms dBtilde{L_p} = -80 + 6 log_{2} {p_{rms}} dB Lp~=−80+6log2prms dB
最终,还原了近似波形图:
数据收集
在步骤 1,在每个绘制时刻,打印出 NSRecorder.averagePowerForChannel,即 $$L_p$$。录音完成后,得到 wav 文件。
解析 wav 文件,计算每个 $$L_p$$ 对应时间段的 wave 的方均根(root mean square value),即 $$p_{rms}$$。
记 $$L_p$$ 为 y,记 $$p_{rms}$$ 为 x,得到训练数据格式如下
# input.csv
x,y
189.215346535,-38.973255
308.318069307,-37.262684
295.73019802,-31.176888
216.20049505,-32.602692
324.167079208,-33.863483
360.544554455,-34.272976
...
建立线性回归模型
考虑分贝计算公式 wiki
用 R 语言建立线性回归模型,拟合 formula = y ~ log(x)
dat <- read.csv('data/input.csv')
model <- lm(y ~ log(x,2), dat)
summary(model)
对一段 87秒的录音,拟合残差(residuals)和系数(coeeficient)为:
Call:
lm(formula = y ~ log(x, 2), data = dat)
Residuals:
Min 1Q Median 3Q Max
-9.8691 -2.1822 -0.2096 1.7669 13.9694
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -50.54969 0.41839 -120.8 <2e-16 ***
log(x, 2) 2.96202 0.04657 63.6 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 3.362 on 1745 degrees of freedom
Multiple R-squared: 0.6986, Adjusted R-squared: 0.6985
F-statistic: 4045 on 1 and 1745 DF, p-value: < 2.2e-16
调参
得到上述方程后,精度有待提高。
我们用 python 读取 wav,通过上述方程计算分贝波形图,不断调整参数,使拟合波形(左上图)更加接近目标(右上图)。
最终得到还原方程:
- 看吧,这就是现代化 PHP 该有的样子
- 从web图片裁剪出发:了解H5中的Blob
- Android子线程更新UI主线程方法之Handler
- Drawable.Bitmap.Canvas.Paint.Matrix
- 关于JSON.stringify和Unicode编码,需要注意的几点
- 用 PHP 的方式实现的各类算法合集
- Nginx 反向代理解决前后端联调跨域问题
- JavaScript对象length
- Go1.8.4和Go1.9.1版本发布
- Javascript数组操作
- Tensorflow官方语音识别入门教程 | 附Google新语音指令数据集
- jQuery VS JavaScript原生API
- 居于H5的多文件、大文件、多线程上传解决方案
- 抛弃websocket,前端直接打通信道,webRTC搭建音视频聊天
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- JS+CSS 3实现图片滑块效果
- 深入理解 AuthenticationManagerBuilder 【源码篇】
- 每天一道前端面试题:如何进行网站性能优化
- PowerBI DAX 度量值管理 - 驾驭度量值依赖关系,删除无效
- Git 实用命令小抄
- 手把手教你画酷炫环形图(图文详解)
- 为什么说神经网络可以逼近任意函数?
- 缩放|位移|渐变简单动画
- HTTP状态码及其含义
- 卷积神经网络中的参数共享/权重复制
- 前端面试基础题:从浏览器地址栏输入url到显示页面的步骤
- 学会这15个TS面试题,拿到更高薪的offer
- 前端面试基础题:请描述⼀下 cookies , sessionStorage 和 localStorage 的区别?
- matplotlib基础绘图命令之pie
- 【从0到1学算法】快速排序