跨平台WebRTC
WebRTC是google開源的一個免外掛程式即時視頻通訊技術,其分為web開發和native開發;目前支援chrome,firefox,android,ios,opera,edge。是一個真正意義上的跨平台免外掛程式即時視頻通訊技術。視頻應用一般是基於web層次的開發。本文主要是webRTC的native層語音處理的代碼架構和對一個native層語音演算法測試程式的梳理。
native層的一些語音演算法可以用於語音辨識前處理。 native層的安裝編譯
http://blog.csdn.net/shichaog/article/details/50246155,為了得到測試程式,需要先安裝並編譯native層代碼(源碼量比較大,可能下載較慢)
如果想只使用native層的語音處理演算法(aec,aecm,agc,ns,vad等),那麼可以選擇安裝下面的程式碼程式庫,有幾點要說明一下: .該程式碼程式庫是基於Linux系統的,考慮安卓,請繞過 該代碼裡預設沒有帶audioproc處理例子,需要自己寫測試程式,可以使用cmake,並且參考audioproc的來源程式。 這個代碼和最新的webRTC並不是同步的,晚上半年是很正常的。
git://anongit.freedesktop.org/pulseaudio/webrtc-audio-processing
native層語音演算法測試程式
首先audio演算法相關的代碼在modules/audio_processing目錄下,該目錄的所有檔案如下:
完成上述串連中的步驟後,即可找到一個可執行檔測試檔案audioproc,該而進行檔案可以完成上述相關演算法的測試。該檔案的位置是:
webrtc-checkout/src/out/Debug$ ./audioproc
使用help選項該檔案的輸出如下:
gsc@gsc-250:~/webrtc-checkout/src/out/Debug$ ./audioproc --helpUsage: 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 ina simulation mode. Otherwise the full set of legacy test files is expectedto be present in the working directory. OUT_FILE should be specifiedwithout extension to support both raw and wav output.OptionsGeneral configuration (only used for the simulation mode): -fs SAMPLE_RATE_HZ -ch CHANNELS_IN CHANNELS_OUT -rch REVERSE_CHANNELSComponent configuration:All components are disabled by default. Each block below begins with aflag to enable the component with default settings. The subsequent flagsin 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_metricsModifiers: --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.ccunpack_aecdump:test/unpack.ccaudioproc_f:test/aec_dump_based_simulator.cc;test/audio_processing_simulator.cc;test/audioproc_float.cc;test/wav_based_simulator.cctransient_suppression_test:transient/transient_suppression_test.ccnonlinear_beamformer_test:beamformer/nonlinear_beamformer_test.ccintelligibility_proc:intelligibility/test/intelligibility_proc.cc
這篇文章不打算涉及具體的演算法,而是梳理代碼,所以這裡就以process_test.cc來看看最重要的APM(audio processing module)。 process_test.cc(在最新的webRTC中已經沒有這個檔案)
1141 } // namespace1142 } // namespace webrtc1143 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<AudioProcessing> 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<webrtc::EchoCancellation::SuppressionLevel>(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 } // namespace1160 } // namespace webrtc這裡可以看出,就是執行這裡的void_main函數,這個函數執行pb格式的檔案,pb格式檔案就是google的protocol buffer協議格式的檔案,和pb相關的可以選擇跳過。其它變數的命名是不言自明的。
我們將155行建立apm模組的方法也可以換一種更為清楚的寫法:
webrtc::AudioProcessing* apm = webrtc::AudioProcessing::Create();
上述可以看出webrtc命名空間中的AudioProcessing是一個關鍵的類。
AudioProcessing類
這個類定義於<include/audio_processing.h>是應用程式要包括的標頭檔(演算法實現被編譯成庫了),有接近三百行,不過由於這個類是溝通演算法和應用程式的橋樑,還是非常重要的,所以這裡就將其全展開了,但是其調用的一些演算法實現方法,就不展開了。最新的webRTC中該類繼承於rtc::RefCountInterface類。
這個類包括了即時語音處理的若干組件,其基於逐幀處理,主要幀(做為ProcessStream()括弧中的幀參數)將會經過所有使能組件(演算法)處理(實際上ProcessStream的參數就是近端訊號),ProcessReverseStream()方法則是逐幀處理遠端訊號。這個模組通常被放在HAL或者是應用之下層(實際上它和應用沒有關係,如果確實要和應用打交到,也最好通過socket或者其它通訊方式時間,而不是直接嵌入應用程式代碼)。
所有的組件在建立時都是disable的,在預設設定值基礎上進行調優,在使能一個組件時,才會觸發記憶體配置和初始化。
免鎖安全執行緒依賴於如下條件: stream擷取和設定在同一個ProcessStream()線程中,不允許在多個線程中操作。 參數擷取和設定不能夠並發調用
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<float>* 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_webrtcninja -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.wav20170630之後只能使用audio_proc_f,檔案在:webrtc/modules/audio_processing/test/audioproc_float.cc