【ESP32-Korvo测评】(6)麦克风阵列算法效果初评
[复制链接]
ESP-Korvo 这块板子吸引我的地方,就是配置了麦克风阵列并且可以在软件中自由使用(尽管不是开源的)阵列算法。在上一篇帖子中我介绍了音频数据流的处理过程以及实现了PCM音频的抓取,再评估音频算法就方便了。现在来抓取麦克风阵列算法处理前后的音频,分别保存到两个文件中,再进行对比,就可以初步评估阵列对于录音效果的作用。
为了保存两个需要的录音文件,需要两个环行缓冲区,然后在阵列算法的任务中加入写缓冲区的调用:
while (1)
{
rb_read(rec_rb, (uint8_t *)mase_in, MASE_FRAME_BYTES * nch, portMAX_DELAY);
mase_process(mase_handle, mase_in, mase_out);
rb_write(mase_rb, mase_out, MASE_FRAME_BYTES, portMAX_DELAY);
if(dump_enabled)
{
rb_write(dump1_rb, mase_in, MASE_FRAME_BYTES, portMAX_DELAY);
rb_write(dump2_rb, mase_out, MASE_FRAME_BYTES, portMAX_DELAY);
}
}
因为阵列算法MASE的输入是AEC算法的输出,从 rec_rb 这个缓冲区获取 mase_in, 处理后将 mase_out 写到 mase_rb 缓冲区,故我只用另外保存 mase_in, mase_out 的数据就实现了抓取。输入是3通道的,输出是单通道的。我只需要一个输入通道音频就够评估了,因此写的两段音频长度相等。这里 AEC 和 MASE 算法的多通道数据格式是非常规的——常规PCM应当是Ch1[n] Ch2[n] Ch3[n] Ch1[n+1] Ch2[n+1] Ch3[n+1] Ch1[n+2] Ch2[n+2] Ch3[n+2] ... 这么排列,然而这里是每个通道连续 MASE_FRAME_BYTES 长度再下一个通道。这样代码有bug的: MASE_FRAME_BYTES 和前面的 AEC_FRAME_BYTES 必须相等,否则数据结构就不一致,必然造成混乱。
好,录一段来回放看看有什么效果提升。为了对比,把MASE前后音频放在两个声道:上面波形是MASE处理之前的,下面是处理后的。
奇怪了,AEC 算法之后的音频有问题。我已经录过原始麦克风的音频,没有这样的异常。仔细看,每隔0.016秒就有一个脉冲波形:
也就是每256个采样会出现一个异常的脉冲,间隔正好是 AEC_FRAME_BYTES 的大小。我怀疑 ESP-Skainet 里面的 AEC 算法有bug,至少在 get_started 这个例子的代码运行表现出来了。
可以很明显地看出:尽管 AEC 处理之后增加了时域上是脉冲串的噪声,MASE 算法居然把这个噪声给消除了。
经过我的听音,我认为 MASE 算法除了抑制这样规律性的噪声,对它所认为的“语音”成分会进行适度的“增强”,否则会削弱;低频范围总体上都是削弱了的。
为了排除 AEC 算法 bug 的影响,我在代码里面将 AEC 处理给取消了,再进行录音实验。
给一段有语音的录音处理前后短时谱的对比:
我个人认为,MASE 处理并不会“提升音质”,只是动态地把不同频率成分进行了增益调节,这种处理对语音识别算法、语音压缩编码等后续处理是有好处的。单纯从录音的角度看来,它并没有使得听不清楚的声音变得清楚,反而会增加一些原本没有的噪音。
阵列对不同方向的声音是否有作用?我尚未从实验得到结论。
最后附一段录音,里面背景噪声主要来源于正在烧开水的壶。有兴趣的网友可以下载来听,比较 MASE 算法处理前后的录音效果。
|