C#實(shí)現(xiàn)語(yǔ)音預(yù)處理:降噪、靜音檢測(cè)、自動(dòng)增益(附Demo源碼)
當(dāng)前位置:點(diǎn)晴教程→知識(shí)管理交流
→『 技術(shù)文檔交流 』
無(wú)論是在音視頻錄制系統(tǒng),還是音視頻通話系統(tǒng)、或視頻會(huì)議系統(tǒng)中,對(duì)從麥克風(fēng)采集到的說(shuō)話的聲音數(shù)據(jù)進(jìn)行預(yù)處理,都是是非常必要的。 語(yǔ)音數(shù)據(jù)預(yù)處理主要包括:降噪(Noise Reduction)、靜音檢測(cè)(Silence Detection/VAD)、自動(dòng)增益(Automatic Gain Control, AGC) 。 一. 語(yǔ)音預(yù)處理的作用我們先解釋一下,降噪、靜音檢測(cè)、自動(dòng)增益,這些語(yǔ)音預(yù)處理分別起什么作用。 (1)降噪 降噪,用于消除背景噪聲,比如馬路車流聲、環(huán)境雜音等,以保留清晰的說(shuō)話人聲。 更高級(jí)的,結(jié)合AI模型訓(xùn)練,還可以消除電腦的風(fēng)扇聲、鍵盤敲擊聲等等。 (2)靜音檢測(cè) 靜音檢測(cè),又稱為語(yǔ)音活動(dòng)檢測(cè),用于識(shí)別音頻流中的靜音片段(沒(méi)有講話人聲),這樣可以簡(jiǎn)化后續(xù)的編碼等環(huán)節(jié),并可以節(jié)省傳遞所需要的帶寬。 (3)自動(dòng)增益 自動(dòng)增益,用于動(dòng)態(tài)調(diào)整說(shuō)話聲音的音量,使輸出電平保持穩(wěn)定,以避免講話的聲音忽大忽小。 二. 實(shí)現(xiàn)語(yǔ)音預(yù)處理接下來(lái),我們使用C#實(shí)現(xiàn)一個(gè)Demo,這個(gè)Demo將從麥克風(fēng)采集聲音數(shù)據(jù),然后進(jìn)行語(yǔ)音預(yù)處理,并且將處理后的聲音數(shù)據(jù)實(shí)時(shí)播放出來(lái)。Demo的運(yùn)行效果如下圖所示: Demo 功能很簡(jiǎn)單,那我們來(lái)具體看看代碼是如何實(shí)現(xiàn)的。 1. 創(chuàng)建采集器、預(yù)處理器、播放器麥克風(fēng)聲音數(shù)據(jù)采樣率我們選擇16K、單聲道。 WaveSampleRate sr = WaveSampleRate.S16k; int channelCount = 1; //創(chuàng)建語(yǔ)音預(yù)處理器,開(kāi)啟降噪、自動(dòng)增益、靜音檢測(cè) this.voicePreprocessor = CapturerFactory.CreateVoicePreprocessor(sr, channelCount, true ,true); //創(chuàng)建麥克風(fēng)采集器 this.microphoneCapturer = CapturerFactory.CreateMicrophoneCapturer(int.Parse(this.textBox_mic.Text), sr); this.microphoneCapturer.AudioCaptured += new ESBasic.CbGeneric<byte[]>(microphoneCapturer_AudioCaptured); //創(chuàng)建聲音播放器 this.audioPlayer = PlayerFactory.CreateAudioPlayer(int.Parse(this.textBox_speaker.Text), (int)sr, channelCount, 16, 2); this.microphoneCapturer.Start(); CreateVoicePreprocessor 方法的最后兩個(gè)參數(shù)可以指定在降噪的同時(shí),是否開(kāi)啟靜音檢測(cè)和自動(dòng)增益功能。 2. 預(yù)處理語(yǔ)音數(shù)據(jù)語(yǔ)音預(yù)處理器每次處理10ms的聲音數(shù)據(jù),而現(xiàn)在的麥克風(fēng)采集器每次采集的是20ms的PCM數(shù)據(jù),所以,我們將其拆成兩個(gè)10ms數(shù)據(jù),再提交給預(yù)處理器處理。 void microphoneCapturer_AudioCaptured(byte[] audioData) { if (this.checkBox_enabled.Checked) { //麥克風(fēng)每次采集20ms數(shù)據(jù),降噪器每次處理10ms數(shù)據(jù)。 byte[] frame10ms1 = new byte[audioData.Length / 2]; byte[] frame10ms2 = new byte[audioData.Length / 2]; Buffer.BlockCopy(audioData, 0, frame10ms1, 0, frame10ms1.Length); Buffer.BlockCopy(audioData, frame10ms1.Length, frame10ms2, 0, frame10ms2.Length); this.HandleData(frame10ms1); this.HandleData(frame10ms2); return; } this.audioPlayer.Play(audioData); } (1)通過(guò)一個(gè)CheckBox勾選框來(lái)實(shí)時(shí)控制是否啟用語(yǔ)音預(yù)處理,這樣在測(cè)試時(shí),就可以很方便的對(duì)比體驗(yàn)開(kāi)啟了語(yǔ)音預(yù)處理的效果。 (2)調(diào)用IVoicePreprocessor 的 Process 方法,就可以完成一幀語(yǔ)音數(shù)據(jù)(10ms)的預(yù)處理。如下所示: private void HandleData(byte[] frame10ms) { byte[] res = this.voicePreprocessor.Process(frame10ms); if (res == null) //靜音幀 { ++this.silenceFrameCountTotal; this.audioPlayer.Play(this.voicePreprocessor.SlienceFrame); } else { this.audioPlayer.Play(res); } } 如果Process 方法返回的是null,表示檢測(cè)到該幀是靜音幀,于是,將內(nèi)置的10ms靜音幀 SlienceFrame 提交給播放器去播放。 3. 統(tǒng)計(jì)靜音幀數(shù)量一個(gè)語(yǔ)音幀是10ms,那么1秒鐘就有100個(gè)語(yǔ)音幀,程序中,我們統(tǒng)計(jì)了上一秒出現(xiàn)了多少個(gè)靜音幀,并在UI左下方顯示出來(lái)。 private volatile int silenceFrameCountTotal = 0; private volatile int silenceFrameCountPre = 0; private void timer1_Tick(object sender, EventArgs e) { int delt = this.silenceFrameCountTotal - this.silenceFrameCountPre; this.silenceFrameCountPre = this.silenceFrameCountTotal; //顯示上一秒靜音幀數(shù)量。 this.label_silenceFrameCount.Text = delt.ToString(); } 實(shí)際測(cè)試時(shí)可以發(fā)現(xiàn),當(dāng)不說(shuō)話時(shí),UI實(shí)時(shí)顯示1秒鐘出現(xiàn)的靜音幀是100個(gè)。 三. Demo源碼下載如果不想打開(kāi)VS,可以直接到Debug目錄下,雙擊 Oraycn.VoicePreprocessDemo.exe 即可運(yùn)行Demo,開(kāi)始體驗(yàn)語(yǔ)音降噪、靜音檢測(cè)、自動(dòng)增益的處理效果。 建議使用耳麥測(cè)試,對(duì)比效果會(huì)更明顯。當(dāng)開(kāi)啟預(yù)處理時(shí),能立即感覺(jué)到背景噪音消失了,而且說(shuō)話的聲音變大了(AGC),不說(shuō)話時(shí),UI顯示靜音幀的數(shù)量變多。 來(lái)下載試試語(yǔ)音預(yù)處理的效果吧。 轉(zhuǎn)自https://www.cnblogs.com/zhuweisky/p/18936492 該文章在 2025/7/4 10:27:14 編輯過(guò) |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |