干货,记一次解决录音杂音问题
最近在項目上遇到一個問題,也不能說是最近項目上的問題了,是之前一直存在的問題,但是對項目沒什么影響,所以我就不怎么理會,直到最近,同事說這個雜音已經影響到了項目的開發,所以今天花了一天時間整理了下問題,不斷的修改測試中,終于搞完了。
說個題外話,年前招了一個帥哥有了新的發展,離開了我們,我內心非常不舍,說不舍有點牽強,他特別喜歡踢足球?,平時交集不是特別多。但是他在技術上真的也是我學習的榜樣,我喜歡看他對事情認真的樣子,總結一個文檔和技術也非常有條理,在面對新的問題和技術難點的時候,他總是能找到解決的辦法。在這點上,我覺得自己確實從他身上吸收到了好的東西。
然后,他現在去做的也是音頻相關的,希望他在新的崗位,新的企業能發展得更好。
之前音頻相關的文章
音頻系統,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語言
我的知識小密圈
總結
以上是生活随笔為你收集整理的干货,记一次解决录音杂音问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Servlet常见面试题
- 下一篇: 三极管的“非教科书式”解析,什么正偏、反