基于C#实现语音预处理
目录
- 一. 语音预处理的作用
- 二. 实现语音预处理
- 1. 创建采集器、预处理器、播放器
- 2. 预处理语音数据
- 3. 统计静音帧数量
无论是在音视频录制系统,还是音视频通话系统、或视频会议系统中,对从麦克风采集到的说话的声音数据进行预处理,都是是非常必要的。
语音数据预处理主要包括:降噪(Noise Reduction)、静音检测(Silence Detection/VAD)、自动增益(Automatic Gain Co编程客栈ntrol, AGC) 。
一. 语音预处理的php作用
我们先解释一下,降噪、静音检测、自动增益,这些语音预处理分别起什么作用。
(1)降噪
降噪,用于消除背景噪声,比如马路车流声、环境杂音等,以保留清晰的说话人声。
更高级的,结合AI模型训练,还可以消除电脑的风扇声、键盘敲击声等等。
(2)静音检测
静音检测,又称为语音活动检测,用于识别音频流中的静音片段(没有讲话人声),这样可以简化后续的编码等环节,并可以节省传递所需要的带宽。
(3)自动增益
自动增益,用于动态调整说话声音的音量,使输出电平保持稳定,以避免讲话的声音忽大忽小。
二. 实现语音预处理
接下来,我们使用C#实现一个Demo,这个Demo将从麦克风采集声音数据,然后进行语音预处理,并且将处理后的声音数据实时播放出来。Demo的运行效果如下图所示:
Demo 功能很简单,那我们来具体看看代码是如何实现的。
1. 创建采集器、预处理器、播放器
麦克风声音数据采样率我们选择16K、单声道。
WaveSampleRate sr = WaveSampleRate.S16k; int channelCount = 1; //创建语音预处理器,开启降噪、自动增益、静音检测 this.voicePreprocessor = CapturerFactory.CreateVoicePreprocessor(sr, channelCount, true ,true); //创建麦克风采集器 this.microphoneCapturer = CapturerFactory.CreateMicrophoneCapturer(int.Parse(this.textBox_mic.Text), sr); this.microphoneCapturer.AudioCaptured += new ESBasic.CbGeneric<byte[]>(microphoneCapturer_Aud编程客栈ioCaptured); //创建声音播放器 this.audioPlayer = PlayerFactory.CreateAudioPlayer(int.Parse(this.textBox_speaker.Text), (int)sr, channelCount, 16, 2); this.microphoneCapturer.Start();
CreateVoicePreprocessor 方法的最后两个参数可以指定在降噪的同时,是否开启静音检测和自动增益功能。
2. 预处理语音数据
语音预处理器每次处理10ms的声音数据,而现在的麦克风采集器每次采EjDDMtT集的是20ms的PCM数据,所以,我们将其拆成两个10ms数据,再提交给预处理器处理。
void microphoneCapturer_AudioCaptured(byte[] audioData) { if (this.checkBox_enabled.Checked) { //麦克风每次采集20ms数据,降噪器每次处理10ms数据。 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)通过一个CheckBox勾选框来实时控制是否启用语音预处理,这样在测试时,就可以很方便的对比体验开启了语音预处理的效果。
(2)调用IVoicePreprocessor 的 Process 方法,就可以完成一帧语音数据(10ms)的预处理。如下所示:
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,表示检测到该帧是静音帧,于是,将内置的10ms静音帧 SlienceFrame 提交给播放器去播放。
3. 统计静音帧数量
一个语音帧是10ms,那么1秒钟就有100个语音帧,程序中,我们统计了上一秒出现了多少个静音帧,并在UI左下方显示出来。
private volatile int silenceFrameCountTotal = 0; private volatile int silenphpceFrameCountPre = 0; private void timer1_Tick(object sender, EventArgs e) { int delt = this.silenceFrameCountTotal - this.silenceFrameCountPre; this.silenceFrameCountPre = this.silenceFrameCountTotal; //显示上一秒静音帧数量。 this.label_silenceFrameCount.Text = delt.ToString(); }
实际测试时可以发现,当不说话时,UI实时显示1秒钟出现的静音帧是100个。
到此这篇关于基于C#实现语音预处理的文章就介绍到这了,更多相关C#语音预处理内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论