CSND已永久停更,最新版唯一来源点击下面链接跳转:
语音增强和语音识别网页书
WebRTC是google开源的一个免插件实时视频通信技术,其分为web开发和native开发;目前支持chrome,firefox,android,ios,opera,edge。是一个真正意义上的跨平台免插件实时视频通信技术。视频应用一般是基于web层次的开发。本文主要是webRTC的native层语音处理的代码架构和对一个native层语音算法测试程序的梳理。
native层的一些语音算法可以用于语音识别前处理。
http://blog.csdn.net/shichaog/article/details/50246155,为了得到测试程序,需要先安装并编译native层代码(源码量比较大,可能下载较慢)
如果想只使用native层的语音处理算法(aec,aecm,agc,ns,vad等),那么可以选择安装下面的代码库,有几点要说明一下:
git://anongit.freedesktop.org/pulseaudio/webrtc-audio-processing
首先audio算法相关的代码在modules/audio_processing目录下,该目录的所有文件如下:
完成上述连接中的步骤后,即可找到一个可执行的测试文件audioproc,该而进行文件可以完成上述相关算法的测试。该文件的位置是:
webrtc-checkout/src/out/Debug$ ./audioproc
使用help选项该文件的输出如下:
gsc@gsc-250:~/webrtc-checkout/src/out/Debug$ ./audioproc --help
Usage: process_test [options] [-pb PROTOBUF_FILE]
[-ir REVERSE_FILE] [-i PRIMARY_FILE] [-o OUT_FILE]
process_test is a test application for AudioProcessing.
When a protobuf debug file is available, specify it with -pb. Alternately,
when -ir or -i is used, the specified files will be processed directly in
a simulation mode. Otherwise the full set of legacy test files is expected
to be present in the working directory. OUT_FILE should be specified
without extension to support both raw and wav output.
Options
General configuration (only used for the simulation mode):
-fs SAMPLE_RATE_HZ
-ch CHANNELS_IN CHANNELS_OUT
-rch REVERSE_CHANNELS
Component configuration:
All components are disabled by default. Each block below begins with a
flag to enable the component with default settings. The subsequent flags
in the block are used to provide configuration settings.
-aec Echo cancellation
--drift_compensation
--no_drift_compensation
--no_echo_metrics
--no_delay_logging
--aec_suppression_level LEVEL [0 - 2]
--extended_filter
--no_reported_delay
-aecm Echo control mobile
--aecm_echo_path_in_file FILE
--aecm_echo_path_out_file FILE
--no_comfort_noise
--routing_mode MODE [0 - 4]
-agc Gain control
--analog
--adaptive_digital
--fixed_digital
--target_level LEVEL
--compression_gain GAIN
--limiter
--no_limiter
-hpf High pass filter
-ns Noise suppression
--ns_low
--ns_moderate
--ns_high
--ns_very_high
--ns_prob_file FILE
-vad Voice activity detection
--vad_out_file FILE
-expns Experimental noise suppression
Level metrics (enabled by default)
--no_level_metrics
Modifiers:
--noasm Disable SSE optimization.
--add_delay DELAY Add DELAY ms to input value.
--delay DELAY Override input delay with DELAY ms.
--perf Measure performance.
--quiet Suppress text output.
--no_progress Suppress progress.
--raw_output Raw output instead of WAV file.
--debug_file FILE Dump a debug recording.
在这个目录下有一个BUILD.gn文件,这个文件,指定了编译的规则和目标以及生成目标的源文件,这里可以看一下audioproc是如何生成的,并且该目录下还有哪些其它的可以使用的测试程序。该文件的一些目标罗列如下:
rtc_static_library:编译生成静态库
rtc_executable:将会生成可执行程序,这里指示生成的可执行程序,
以下是可执行程序和其依赖的源程序关系
audioproc:test/process_test.cc
unpack_aecdump:test/unpack.cc
audioproc_f:test/aec_dump_based_simulator.cc;test/audio_processing_simulator.cc;test/audioproc_float.cc;test/wav_based_simulator.cc
transient_suppression_test:transient/transient_suppression_test.cc
nonlinear_beamformer_test:beamformer/nonlinear_beamformer_test.cc
intelligibility_proc:intelligibility/test/intelligibility_proc.cc
这篇文章不打算涉及具体的算法,而是梳理代码,所以这里就以process_test.cc来看看最重要的APM(audio processing module)。
1141 } // namespace
1142 } // namespace webrtc
1143
1144 int main(int argc, char* argv[]) {
1145 webrtc::void_main(argc, argv);
1146
1147 // Optional, but removes memory leak noise from Valgrind.
1148 google::protobuf::ShutdownProtobufLibrary();
1149 return 0;
1150 }
这个全局的main函数调用了webrtc命令空间中的void_main函数。
在这个cc文件的48行
48:namespace webrtc {
...
143 // void function for gtest.
144 void void_main(int argc, char* argv[]) {
...
创建关键对象
155 std::unique_ptr apm(AudioProcessing::Create());
183 AudioProcessing::Config apm_config;
...
//aec模式使能
227 } else if (strcmp(argv[i], "-aec") == 0) {
228 ASSERT_EQ(apm->kNoError, apm->echo_cancellation()->Enable(true));
229 ASSERT_EQ(apm->kNoError,
230 apm->echo_cancellation()->enable_metrics(true));
231 ASSERT_EQ(apm->kNoError,
232 apm->echo_cancellation()->enable_delay_logging(true));
...
//这个是回声抑制系数,分为low, moderate以及high三种模式
258 } else if (strcmp(argv[i], "--aec_suppression_level") == 0) {
259 i++;
260 ASSERT_LT(i, argc) << "Specify level after --aec_suppression_level";
261 int suppression_level;
262 ASSERT_EQ(1, sscanf(argv[i], "%d", &suppression_level));
263 ASSERT_EQ(apm->kNoError,
264 apm->echo_cancellation()->set_suppression_level(
265 static_cast(
266 suppression_level)));
...
458 apm->ApplyConfig(apm_config);
//对于智能语音音箱,近端信号就是说话人对其说话采集到的语音,远端信号就是智能音箱自身发出的声音
//对于VoIP,近端信号就是人对电脑说话,电脑采集到的声音,远端信号就是Voip另外一端人将的语音信号。
767 err = apm->ProcessStream(&near_frame);
//执行远端处理,这里是进行回声消除,这里还有一个延迟估计,暂时跳过
691 ASSERT_EQ(apm->kNoError,
692 apm->ProcessReverseStream(&far_frame));
1159 } // namespace
1160 } // namespace webrtc
这里可以看出,就是执行这里的void_main函数,这个函数执行pb格式的文件,pb格式文件就是google的protocol buffer协议格式的文件,和pb相关的可以选择跳过。其它变量的命名是不言自明的。
我们将155行创建apm模块的方法也可以换一种更为清楚的写法:
webrtc::AudioProcessing* apm = webrtc::AudioProcessing::Create();
上述可以看出webrtc命名空间中的AudioProcessing是一个关键的类。
这个类定义于
这个类包括了实时语音处理的若干组件,其基于逐帧处理,主要帧(做为ProcessStream()括号中的帧参数)将会经过所有使能组件(算法)处理(实际上ProcessStream的参数就是近端信号),ProcessReverseStream()方法则是逐帧处理远端信号。这个模块通常被放在HAL或者是应用之下层(实际上它和应用没有关系,如果确实要和应用打交到,也最好通过socket或者其它通信方式时间,而不是直接嵌入应用程序代码)。
所有的组件在创建时都是disable的,在缺省设置值基础上进行调优,在使能一个组件时,才会触发内存分配和初始化。
免锁线程安全依赖于如下条件:
APM只接受10ms的数据,int16是交叉数据排列方式,而float接口是非交叉排列方式。
一个使用的例子是:
197 // Usage example, omitting error checking:
198 // AudioProcessing* apm = AudioProcessing::Create(0);
199 //
200 // AudioProcessing::Config config;
201 // config.level_controller.enabled = true;
202 // apm->ApplyConfig(config)
203 //
204 // apm->high_pass_filter()->Enable(true);
205 //
206 // apm->echo_cancellation()->enable_drift_compensation(false);
207 // apm->echo_cancellation()->Enable(true);
208 //
209 // apm->noise_reduction()->set_level(kHighSuppression);
210 // apm->noise_reduction()->Enable(true);
211 //
212 // apm->gain_control()->set_analog_level_limits(0, 255);
213 // apm->gain_control()->set_mode(kAdaptiveAnalog);
214 // apm->gain_control()->Enable(true);
215 //
216 // apm->voice_detection()->Enable(true);
217 //
218 // // Start a voice call...
219 //
220 // // ... Render frame arrives bound for the audio HAL ...
221 // apm->ProcessReverseStream(render_frame);
222 //
223 // // ... Capture frame arrives from the audio HAL ...
224 // // Call required set_stream_ functions.
225 // apm->set_stream_delay_ms(delay_ms);
226 // apm->gain_control()->set_stream_analog_level(analog_level);
227 //
228 // apm->ProcessStream(capture_frame);
229 //
230 // // Call required stream_ functions.
231 // analog_level = apm->gain_control()->stream_analog_level();
232 // has_voice = apm->stream_has_voice();
233 //
234 // // Repeate render and capture processing for the duration of the call...
235 // // Start a new call...
236 // apm->Initialize();
237 //
238 // // Close the application...
239 // delete apm;
其创建方法位于audio_processing_impl.cc文件:
AudioProcessing* AudioProcessing::Create() {
Config config;
return Create(config, nullptr);
}
AudioProcessing* AudioProcessing::Create(const Config& config) {
return Create(config, nullptr);
}
AudioProcessing* AudioProcessing::Create(const Config& config,
Beamformer* beamformer) {
AudioProcessingImpl* apm = new AudioProcessingImpl(config, beamformer);
if (apm->Initialize() != kNoError) {
delete apm;
apm = NULL;
}
return apm;
}
含有纯虚函数是无法实例化(new)的,必然会有继承类来重载这些纯虚函数,这个继承类就是AudioProcessingImpl类,AudioProcessingImpl是继承基类AudioProcessing的。如果想看具体实现,就看这个文件以及里面定义的方法。
这里面的设计思想还是很巧妙的,其它每一个算法模块分割成一个类,在这个中再实例化算法模块类,然后再调用相应类的enable方法以使能,所以会有若干的impl.cc结尾的函数,这些函数(如noise_suppresion_impl.cc)就是对核心算法的封装,封装后提供给这里APM模块实例化和使用,代码分格简洁/高效/可扩展性好。
总结如下:编译,测试
python webrtc/build/gyp_webrtc
ninja -C out/Debug
./nonlinear_beamformer_test -i out2.wav -mic_positions "1.0 1.0 1.0 2.0 2.2 2.2 1.1 1.2 0" out.wav
20170630之后只能使用audio_proc_f,文件在:
webrtc/modules/audio_processing/test/audioproc_float.cc