onFrameRecorded 传过来的是MP3帧,但是,这个帧有的时候是不完整的帧,好像是小程序的性能问题或者之类的其他问题。
使用js-mp3,把MP3帧解码成PCM数据,然后再按照pcm数据,来计算分贝数。
踩坑的地方:
1.famebuffer设置的太小,造成传过来的arrayBuffer里面没有一个完整的mp3帧,结果就是Decode失败。以为是小程序的黑箱问题。
2.js-mp3声称自己不支持mpeg2,感觉心里凉了半截,后来“高坚果”给了一个表格:

原来是采样率设置问题,修改为44.1khz采样率,搞定。
3.“高坚果”提供的Recoder里面的源码是使用getChannelData来计算的,里面返回的是一个Float16Array,但是js-mp3解码出来的pcm,如果转换成Float16Array,会有很多NaN,所以没有使用Recoder里面计算分贝大小的方法。但是这个计算方法是仓促写出来的,所以问题多多,已知问题:会出现突然100的情况;并不是对所有声音都敏感。
4.效率很差。因为中间经过了mp3压缩,然后再解码,再判断分贝大小,所以,效率真的很差。
代码摘抄如下:
-
recordTest: function () { -
var ctx = wx.createCanvasContext("firstCanvas") -
ctx.draw(); -
var curr_index = 0; -
var reclength = 30; //录音30秒 -
var step = reclength / app.globalData.windowWidth; -
var startTime = new Date(); -
var powerArr = []; -
var ctx_height = 200; -
var rm = wx.getRecorderManager() -
rm.onFrameRecorded((res) => { -
const { frameBuffer } = res -
var decoder = Mp3.newDecoder(frameBuffer) -
if (decoder != null) { -
var pcmArrayBuffer = decoder.decode() -
var pcmArr = new Int16Array(pcmArrayBuffer) -
var size = pcmArr.length -
var sum = 0; -
for (var i = 0; i < size; i++) { -
sum += Math.abs(pcmArr[i]); -
} -
var powerLevel = sum * 500.0 / (size * 16383); -
if (powerLevel >= 100) { -
powerLevel = 100 -
} -
if (powerLevel <= 5) { -
powerLevel = 2 -
} -
powerLevel = parseInt(powerLevel) -
if(powerArr[curr_index] * 2 < powerLevel && powerLevel == 100) -
{ -
powerLevel = powerArr[curr_index] -
} -
var bufferDuration = (new Date() - startTime) / 1000; //计算开始了多少秒了 -
while (bufferDuration > curr_index * step) //每次循环进来不止前进一次 -
{ -
powerArr[curr_index] = powerLevel -
curr_index++ -
ctx.setFillStyle("#6E6FAC") -
var curr_height = powerLevel / 100 * ctx_height -
var curr_y = (ctx_height - curr_height) / 2 -
ctx.fillRect(curr_index, curr_y, 1, curr_height) -
ctx.draw(true) -
} -
} -
}) -
rm.onStart(() => { -
console.log('recorder start') -
this.setData({buttonText: "录音中"}) -
}) -
rm.onPause(() => { -
console.log('recorder pause') -
console.log(farms); -
}) -
rm.onStop((res) => { -
this.setData({buttonText: "录音结束"}) -
console.log('recorder stop', res) -
console.log("curr_index:" + curr_index) -
const { tempFilePath } = res -
const fs = wx.getFileSystemManager() -
// // 从临时文件中读取音频 -
fs.readFile({ -
filePath: tempFilePath, -
success(res) { -
var decoder = Mp3.newDecoder(res.data) -
if (decoder == null) { -
console.log("decoder error") -
} -
else { -
console.log("decode ok") -
var pcmArrayBuffer = decoder.decode() -
console.log(pcmArrayBuffer) -
} -
}, -
fail(e) { -
console.log('read fail') -
console.log(e) -
} -
}) -
}) -
const options = { -
duration: 30000, -
sampleRate: 44100, -
numberOfChannels: 1, -
encodeBitRate: 64000, -
format: 'mp3', -
frameSize: 1 -
} -
rm.start(options) -
}
pcm计算分贝大小:https://www.jianshu.com/p/d3745dd23056
js-mp3:https://github.com/soundbus-technologies/js-mp3
本文介绍了一种在小程序环境中通过MP3帧记录并计算音频分贝大小的方法。使用js-mp3解码MP3帧为PCM数据,并解决了解码过程中遇到的各种问题,如设置错误的采样率和缓冲区大小不足等。
862

被折叠的 条评论
为什么被折叠?



