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

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

最近在项目上遇到一个问题,也不能说是最近项目上的问题了,是之前一直存在的问题,但是对项目没什么影响,所以我就不怎么理会,直到最近,同事说这个杂音已经影响到了项目的开发,所以今天花了一天时间整理了下问题,不断的修改测试中,终于搞完了。

说个题外话,年前招了一个帅哥有了新的发展,离开了我们,我内心非常不舍,说不舍有点牵强,他特别喜欢踢足球⚽,平时交集不是特别多。但是他在技术上真的也是我学习的榜样,我喜欢看他对事情认真的样子,总结一个文档和技术也非常有条理,在面对新的问题和技术难点的时候,他总是能找到解决的办法。在这点上,我觉得自己确实从他身上吸收到了好的东西。

然后,他现在去做的也是音频相关的,希望他在新的岗位,新的企业能发展得更好。

之前音频相关的文章

音频系统,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语言

我的知识小密圈

相关推荐

星痕共鸣日常活动产出及时间大全
2026年世界杯门票抽签惹争议

2026年世界杯门票抽签惹争议

📅 10-07 👁️ 8419
滴滴顺风车 出发后车主位置速查指南