背景
在工作群中,偶然看到这样一种场景:在乐谱演奏中,实时分析演奏的音准并进行评分。
在这种场景下,一般性的做法,无非是进行音频采集,再通过音频处理(降噪等),最后通过算法分析得到预测的音准。流程很清楚,现实很骨感,这里涉及到很多链路,那在纯前(zi)端(ji)领(hui)域的领域,目前可以尝试做到一个什么程度呢?
这便产生了以下的demo:
http://demo.onehacker.top/pitch-detection-app/
原理分析
step1:音频采样
无非不过两种
- 录音
- 音频文件
在浏览器侧不管实现哪种音频的采集,都是很方便的,这里为了防止环境噪音的干扰,采用音频文件的方式,基本实现也很简单:
const context = new AudioContext(); const mediaStreamSource = context.createMediaElementSource( stream as HTMLMediaElement ); const analyser = context.createAnalyser(); mediaStreamSource.connect(pitchSetup.analyser); analyser.connect(pitchSetup.audioContext.destination)
通过这种方式实现音频到自己的处理通道,这样就可以拿到音频的二进制数据。拿到的数据通过做法进行数据分析
step2: 数据分析
提取的数据需要进行基因检测,检测的算法五花八门,比如最基础的自相关检测。关于这个算法的优劣这里不做赘述,毕竟也不是本文重点。
获取的数据是一串离线的数字信号,简易设置一个滤波器,在超出范围的数据进行过滤,过滤后的数字进行进行傅里叶频谱转换,这里包含傅里叶正变换、逆变换等一些复杂的数学算法。最终可以得出当前声音的频率和清晰度。
总之使用 service worker + wasm 完成复杂算法的结果运算。
具体的算法可以参考:https://github.com/alesgenova/pitch-detection
step3:将分析的结果进行展示
略
总结
通过以上的方式,即可实现前端进行音频采集,前端进行算法运算,最终前端进行音频展示的能力。整体的效果还很粗糙,但借助于WASM,相信在前端领域内的直接算法运算会变得越来越可为。