干货,记一次解决录音杂音问题

嵌入式Linux

共 2957字,需浏览 6分钟

 ·

2021-01-22 23:26

最近在项目上遇到一个问题,也不能说是最近项目上的问题了,是之前一直存在的问题,但是对项目没什么影响,所以我就不怎么理会,直到最近,同事说这个杂音已经影响到了项目的开发,所以今天花了一天时间整理了下问题,不断的修改测试中,终于搞完了。
说个题外话,年前招了一个帅哥有了新的发展,离开了我们,我内心非常不舍,说不舍有点牵强,他特别喜欢踢足球⚽,平时交集不是特别多。但是他在技术上真的也是我学习的榜样,我喜欢看他对事情认真的样子,总结一个文档和技术也非常有条理,在面对新的问题和技术难点的时候,他总是能找到解决的办法。在这点上,我觉得自己确实从他身上吸收到了好的东西。
然后,他现在去做的也是音频相关的,希望他在新的岗位,新的企业能发展得更好。
之前音频相关的文章
音频系统,Alsa 里面的buff 是怎么计算的?
为什么需要超过48k的采样音频?
我在MTK平台下调试音频ALSA
音频几个重要的参数
openwrt 音频开发
(干货)Ai音箱和Linux音频驱动小谈
Android 音频数据流分析之程序员干架产品经理
Alsa里面恶心的DAPM

1、问题

正常使用tinycap录音,在音频的开始位置会有一段杂波,这段杂波让人看起来会非常不爽。

2、排查过程

先是排查了硬件,我担心是硬件的GPIO口模式不正确,这个也是同事提醒的,后面检查了下,发现这个GPIO口是特殊口,这个GPIO口就是干这个事情的,所以说没有模式正确不正确,它就只有这个功能。
然后检查了上电,因为DMIC有一个供电,之前的文章写过,我担心供电时间过慢导致,后面修改了代码让DMIC持续供电,不过测试几次录音的时候问题还是存在,所以排除了这个问题。
还有就是DMIC的特性了,查看了DMIC的上电特性,DMIC有一个上电的时间,也就是这个时间影响了稳定。
如下图
后面跟思必驰的技术沟通,跟他讨论了这个问题,他也说到他们在其他项目中也遇到过,解决的办法就是写0。

3、解决

上面已经说了解决办法了,就是在开始录音的时候写0,但是在哪里写成了问题,如果应用直接写0就好了,但是我不能直接修改应用的代码。所以只能在内核里面做手脚。
在HAL搞这个事情可能会标准化一些。
先是确定了读音频的函数,流程是
snd_pcm_capture_ioctl1()
->snd_pcm_lib_read()
-->snd_pcm_lib_read_transfer()
修改的patch如下
diff --git a/kernel-4.4/include/sound/pcm.h b/kernel-4.4/include/sound/pcm.h
old mode 100644
new mode 100755
index b0be092799..ecaca74273
--- a/kernel-4.4/include/sound/pcm.h
+++ b/kernel-4.4/include/sound/pcm.h
@@ -460,6 +460,7 @@ struct snd_pcm_substream {
        /* -- assigned files -- */
        void *file;
        int ref_count;
+       int once_f;/*weiqifa modify*/
        atomic_t mmap_count;
        unsigned int f_flags;
        void (*pcm_release)(struct snd_pcm_substream *);
diff --git a/kernel-4.4/sound/core/pcm_lib.c b/kernel-4.4/sound/core/pcm_lib.c
old mode 100644
new mode 100755
index 17e69848d3..8a057f1445
--- a/kernel-4.4/sound/core/pcm_lib.c
+++ b/kernel-4.4/sound/core/pcm_lib.c
@@ -2220,6 +2220,11 @@ static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream,
                        return err;
        } else {
                char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);
+               if(substream->once_f < 1)
+               {
+                       memset(hwbuf,0,frames_to_bytes(runtime, frames));
+                       substream->once_f++;
+               }
                if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, frames)))
                        return -EFAULT;
        }
diff --git a/kernel-4.4/sound/core/pcm_native.c b/kernel-4.4/sound/core/pcm_native.c
old mode 100644
new mode 100755
index 3de88974ee..0ead670a38
--- a/kernel-4.4/sound/core/pcm_native.c
+++ b/kernel-4.4/sound/core/pcm_native.c
@@ -2229,6 +2229,7 @@ static void pcm_release_private(struct snd_pcm_substream *substream)

 void snd_pcm_release_substream(struct snd_pcm_substream *substream)
 {
+       substream->once_f = 0;
        substream->ref_count--;
        if (substream->ref_count > 0)
                return;
@@ -2277,6 +2278,7 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
                goto error;

        substream->hw_opened = 1;
+       substream->once_f = 0;

        err = snd_pcm_hw_constraints_complete(substream);
        if (err < 0) {

里面写0的帧大小需要调试一下,这是我最后测试出来的结果。
修改后录音得到的音频频谱图如下
从之前的文章知道计算公式,从这里反推断mute写0的时间
跟上面截图看到的时间差不多。
完美~ 下班


推荐阅读:
专辑|Linux文章汇总
专辑|程序人生
专辑|C语言
我的知识小密圈


浏览 70
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报