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