1 /*
2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "webrtc/test/testsupport/fileutils.h"
12 #include "webrtc/voice_engine/test/auto_test/fixtures/after_streaming_fixture.h"
13 #include "webrtc/voice_engine/test/auto_test/voe_standard_test.h"
14 
15 class RxCallback : public webrtc::VoERxVadCallback {
16  public:
RxCallback()17   RxCallback() :
18     vad_decision(-1) {
19   }
20 
OnRxVad(int,int vadDecision)21   virtual void OnRxVad(int, int vadDecision) {
22     char msg[128];
23     sprintf(msg, "RX VAD detected decision %d \n", vadDecision);
24     TEST_LOG("%s", msg);
25     vad_decision = vadDecision;
26   }
27 
28   int vad_decision;
29 };
30 
31 class AudioProcessingTest : public AfterStreamingFixture {
32  protected:
33   // Note: Be careful with this one, it is used in the
34   // Android / iPhone part too.
TryEnablingAgcWithMode(webrtc::AgcModes agc_mode_to_set)35   void TryEnablingAgcWithMode(webrtc::AgcModes agc_mode_to_set) {
36     EXPECT_EQ(0, voe_apm_->SetAgcStatus(true, agc_mode_to_set));
37 
38     bool agc_enabled = false;
39     webrtc::AgcModes agc_mode = webrtc::kAgcDefault;
40 
41     EXPECT_EQ(0, voe_apm_->GetAgcStatus(agc_enabled, agc_mode));
42     EXPECT_TRUE(agc_enabled);
43     EXPECT_EQ(agc_mode_to_set, agc_mode);
44   }
45 
TryEnablingRxAgcWithMode(webrtc::AgcModes agc_mode_to_set)46   void TryEnablingRxAgcWithMode(webrtc::AgcModes agc_mode_to_set) {
47     EXPECT_EQ(0, voe_apm_->SetRxAgcStatus(channel_, true, agc_mode_to_set));
48 
49     bool rx_agc_enabled = false;
50     webrtc::AgcModes agc_mode = webrtc::kAgcDefault;
51 
52     EXPECT_EQ(0, voe_apm_->GetRxAgcStatus(channel_, rx_agc_enabled, agc_mode));
53     EXPECT_TRUE(rx_agc_enabled);
54     EXPECT_EQ(agc_mode_to_set, agc_mode);
55   }
56 
57   // EC modes can map to other EC modes, so we have a separate parameter
58   // for what we expect the EC mode to be set to.
TryEnablingEcWithMode(webrtc::EcModes ec_mode_to_set,webrtc::EcModes expected_mode)59   void TryEnablingEcWithMode(webrtc::EcModes ec_mode_to_set,
60                              webrtc::EcModes expected_mode) {
61     EXPECT_EQ(0, voe_apm_->SetEcStatus(true, ec_mode_to_set));
62 
63     bool ec_enabled = true;
64     webrtc::EcModes ec_mode = webrtc::kEcDefault;
65 
66     EXPECT_EQ(0, voe_apm_->GetEcStatus(ec_enabled, ec_mode));
67 
68     EXPECT_EQ(expected_mode, ec_mode);
69   }
70 
71   // Here, the CNG mode will be expected to be on or off depending on the mode.
TryEnablingAecmWithMode(webrtc::AecmModes aecm_mode_to_set,bool cng_enabled_to_set)72   void TryEnablingAecmWithMode(webrtc::AecmModes aecm_mode_to_set,
73                                bool cng_enabled_to_set) {
74     EXPECT_EQ(0, voe_apm_->SetAecmMode(aecm_mode_to_set, cng_enabled_to_set));
75 
76     bool cng_enabled = false;
77     webrtc::AecmModes aecm_mode = webrtc::kAecmEarpiece;
78 
79     voe_apm_->GetAecmMode(aecm_mode, cng_enabled);
80 
81     EXPECT_EQ(cng_enabled_to_set, cng_enabled);
82     EXPECT_EQ(aecm_mode_to_set, aecm_mode);
83   }
84 
TryEnablingNsWithMode(webrtc::NsModes ns_mode_to_set,webrtc::NsModes expected_ns_mode)85   void TryEnablingNsWithMode(webrtc::NsModes ns_mode_to_set,
86                              webrtc::NsModes expected_ns_mode) {
87     EXPECT_EQ(0, voe_apm_->SetNsStatus(true, ns_mode_to_set));
88 
89     bool ns_status = true;
90     webrtc::NsModes ns_mode = webrtc::kNsDefault;
91     EXPECT_EQ(0, voe_apm_->GetNsStatus(ns_status, ns_mode));
92 
93     EXPECT_TRUE(ns_status);
94     EXPECT_EQ(expected_ns_mode, ns_mode);
95   }
96 
TryEnablingRxNsWithMode(webrtc::NsModes ns_mode_to_set,webrtc::NsModes expected_ns_mode)97   void TryEnablingRxNsWithMode(webrtc::NsModes ns_mode_to_set,
98                                webrtc::NsModes expected_ns_mode) {
99     EXPECT_EQ(0, voe_apm_->SetRxNsStatus(channel_, true, ns_mode_to_set));
100 
101     bool ns_status = true;
102     webrtc::NsModes ns_mode = webrtc::kNsDefault;
103     EXPECT_EQ(0, voe_apm_->GetRxNsStatus(channel_, ns_status, ns_mode));
104 
105     EXPECT_TRUE(ns_status);
106     EXPECT_EQ(expected_ns_mode, ns_mode);
107   }
108 
TryDetectingSilence()109   void TryDetectingSilence() {
110     // Here, speech is running. Shut down speech.
111     EXPECT_EQ(0, voe_codec_->SetVADStatus(channel_, true));
112     EXPECT_EQ(0, voe_volume_control_->SetInputMute(channel_, true));
113     EXPECT_EQ(0, voe_file_->StopPlayingFileAsMicrophone(channel_));
114 
115     // We should detect the silence after a short time.
116     Sleep(50);
117     for (int i = 0; i < 25; i++) {
118       EXPECT_EQ(0, voe_apm_->VoiceActivityIndicator(channel_));
119       Sleep(10);
120     }
121   }
122 
TryDetectingSpeechAfterSilence()123   void TryDetectingSpeechAfterSilence() {
124     // Re-enable speech.
125     RestartFakeMicrophone();
126     EXPECT_EQ(0, voe_codec_->SetVADStatus(channel_, false));
127     EXPECT_EQ(0, voe_volume_control_->SetInputMute(channel_, false));
128 
129     // We should detect the speech after a short time.
130     for (int i = 0; i < 50; i++) {
131       if (voe_apm_->VoiceActivityIndicator(channel_) == 1) {
132         return;
133       }
134       Sleep(10);
135     }
136 
137     ADD_FAILURE() << "Failed to detect speech within 500 ms.";
138   }
139 };
140 
141 #if !defined(WEBRTC_IOS) && !defined(WEBRTC_ANDROID)
142 
TEST_F(AudioProcessingTest,AgcIsOnByDefault)143 TEST_F(AudioProcessingTest, AgcIsOnByDefault) {
144   bool agc_enabled = false;
145   webrtc::AgcModes agc_mode = webrtc::kAgcAdaptiveAnalog;
146 
147   EXPECT_EQ(0, voe_apm_->GetAgcStatus(agc_enabled, agc_mode));
148   EXPECT_TRUE(agc_enabled);
149   EXPECT_EQ(webrtc::kAgcAdaptiveAnalog, agc_mode);
150 }
151 
TEST_F(AudioProcessingTest,CanEnableAgcWithAllModes)152 TEST_F(AudioProcessingTest, CanEnableAgcWithAllModes) {
153   TryEnablingAgcWithMode(webrtc::kAgcAdaptiveDigital);
154   TryEnablingAgcWithMode(webrtc::kAgcAdaptiveAnalog);
155   TryEnablingAgcWithMode(webrtc::kAgcFixedDigital);
156 }
157 
TEST_F(AudioProcessingTest,EcIsDisabledAndAecIsDefaultEcMode)158 TEST_F(AudioProcessingTest, EcIsDisabledAndAecIsDefaultEcMode) {
159   bool ec_enabled = true;
160   webrtc::EcModes ec_mode = webrtc::kEcDefault;
161 
162   EXPECT_EQ(0, voe_apm_->GetEcStatus(ec_enabled, ec_mode));
163   EXPECT_FALSE(ec_enabled);
164   EXPECT_EQ(webrtc::kEcAec, ec_mode);
165 }
166 
TEST_F(AudioProcessingTest,EnablingEcAecShouldEnableEcAec)167 TEST_F(AudioProcessingTest, EnablingEcAecShouldEnableEcAec) {
168   TryEnablingEcWithMode(webrtc::kEcAec, webrtc::kEcAec);
169 }
170 
TEST_F(AudioProcessingTest,EnablingEcConferenceShouldEnableEcAec)171 TEST_F(AudioProcessingTest, EnablingEcConferenceShouldEnableEcAec) {
172   TryEnablingEcWithMode(webrtc::kEcConference, webrtc::kEcAec);
173 }
174 
TEST_F(AudioProcessingTest,EcModeIsPreservedWhenEcIsTurnedOff)175 TEST_F(AudioProcessingTest, EcModeIsPreservedWhenEcIsTurnedOff) {
176   TryEnablingEcWithMode(webrtc::kEcConference, webrtc::kEcAec);
177 
178   EXPECT_EQ(0, voe_apm_->SetEcStatus(false));
179 
180   bool ec_enabled = true;
181   webrtc::EcModes ec_mode = webrtc::kEcDefault;
182   EXPECT_EQ(0, voe_apm_->GetEcStatus(ec_enabled, ec_mode));
183 
184   EXPECT_FALSE(ec_enabled);
185   EXPECT_EQ(webrtc::kEcAec, ec_mode);
186 }
187 
TEST_F(AudioProcessingTest,CanEnableAndDisableEcModeSeveralTimesInARow)188 TEST_F(AudioProcessingTest, CanEnableAndDisableEcModeSeveralTimesInARow) {
189   for (int i = 0; i < 10; i++) {
190     EXPECT_EQ(0, voe_apm_->SetEcStatus(true));
191     EXPECT_EQ(0, voe_apm_->SetEcStatus(false));
192   }
193 
194   bool ec_enabled = true;
195   webrtc::EcModes ec_mode = webrtc::kEcDefault;
196   EXPECT_EQ(0, voe_apm_->GetEcStatus(ec_enabled, ec_mode));
197 
198   EXPECT_FALSE(ec_enabled);
199   EXPECT_EQ(webrtc::kEcAec, ec_mode);
200 }
201 
202 // TODO(phoglund): Reenable below test when it's no longer flaky.
TEST_F(AudioProcessingTest,DISABLED_TestVoiceActivityDetectionWithObserver)203 TEST_F(AudioProcessingTest, DISABLED_TestVoiceActivityDetectionWithObserver) {
204   RxCallback rx_callback;
205   EXPECT_EQ(0, voe_apm_->RegisterRxVadObserver(channel_, rx_callback));
206 
207   // The extra sleeps are to allow decisions some time to propagate to the
208   // observer.
209   TryDetectingSilence();
210   Sleep(100);
211 
212   EXPECT_EQ(0, rx_callback.vad_decision);
213 
214   TryDetectingSpeechAfterSilence();
215   Sleep(100);
216 
217   EXPECT_EQ(1, rx_callback.vad_decision);
218 
219   EXPECT_EQ(0, voe_apm_->DeRegisterRxVadObserver(channel_));
220 }
221 
222 #endif   // !WEBRTC_IOS && !WEBRTC_ANDROID
223 
TEST_F(AudioProcessingTest,EnablingEcAecmShouldEnableEcAecm)224 TEST_F(AudioProcessingTest, EnablingEcAecmShouldEnableEcAecm) {
225   // This one apparently applies to Android and iPhone as well.
226   TryEnablingEcWithMode(webrtc::kEcAecm, webrtc::kEcAecm);
227 }
228 
TEST_F(AudioProcessingTest,EcAecmModeIsEnabledAndSpeakerphoneByDefault)229 TEST_F(AudioProcessingTest, EcAecmModeIsEnabledAndSpeakerphoneByDefault) {
230   bool cng_enabled = false;
231   webrtc::AecmModes aecm_mode = webrtc::kAecmEarpiece;
232 
233   voe_apm_->GetAecmMode(aecm_mode, cng_enabled);
234 
235   EXPECT_TRUE(cng_enabled);
236   EXPECT_EQ(webrtc::kAecmSpeakerphone, aecm_mode);
237 }
238 
TEST_F(AudioProcessingTest,CanSetAecmMode)239 TEST_F(AudioProcessingTest, CanSetAecmMode) {
240   EXPECT_EQ(0, voe_apm_->SetEcStatus(true, webrtc::kEcAecm));
241 
242   // Try some AECM mode - CNG enabled combinations.
243   TryEnablingAecmWithMode(webrtc::kAecmEarpiece, true);
244   TryEnablingAecmWithMode(webrtc::kAecmEarpiece, false);
245   TryEnablingAecmWithMode(webrtc::kAecmLoudEarpiece, true);
246   TryEnablingAecmWithMode(webrtc::kAecmLoudSpeakerphone, false);
247   TryEnablingAecmWithMode(webrtc::kAecmQuietEarpieceOrHeadset, true);
248   TryEnablingAecmWithMode(webrtc::kAecmSpeakerphone, false);
249 }
250 
TEST_F(AudioProcessingTest,RxAgcShouldBeOffByDefault)251 TEST_F(AudioProcessingTest, RxAgcShouldBeOffByDefault) {
252   bool rx_agc_enabled = true;
253   webrtc::AgcModes agc_mode = webrtc::kAgcDefault;
254 
255   EXPECT_EQ(0, voe_apm_->GetRxAgcStatus(channel_, rx_agc_enabled, agc_mode));
256   EXPECT_FALSE(rx_agc_enabled);
257   EXPECT_EQ(webrtc::kAgcAdaptiveDigital, agc_mode);
258 }
259 
TEST_F(AudioProcessingTest,CanTurnOnDigitalRxAcg)260 TEST_F(AudioProcessingTest, CanTurnOnDigitalRxAcg) {
261   TryEnablingRxAgcWithMode(webrtc::kAgcAdaptiveDigital);
262   TryEnablingRxAgcWithMode(webrtc::kAgcFixedDigital);
263 }
264 
TEST_F(AudioProcessingTest,CannotTurnOnAdaptiveAnalogRxAgc)265 TEST_F(AudioProcessingTest, CannotTurnOnAdaptiveAnalogRxAgc) {
266   EXPECT_EQ(-1, voe_apm_->SetRxAgcStatus(
267       channel_, true, webrtc::kAgcAdaptiveAnalog));
268 }
269 
TEST_F(AudioProcessingTest,NsIsOffWithModerateSuppressionByDefault)270 TEST_F(AudioProcessingTest, NsIsOffWithModerateSuppressionByDefault) {
271   bool ns_status = true;
272   webrtc::NsModes ns_mode = webrtc::kNsDefault;
273   EXPECT_EQ(0, voe_apm_->GetNsStatus(ns_status, ns_mode));
274 
275   EXPECT_FALSE(ns_status);
276   EXPECT_EQ(webrtc::kNsModerateSuppression, ns_mode);
277 }
278 
TEST_F(AudioProcessingTest,CanSetNsMode)279 TEST_F(AudioProcessingTest, CanSetNsMode) {
280   // Concrete suppression values map to themselves.
281   TryEnablingNsWithMode(webrtc::kNsHighSuppression,
282                         webrtc::kNsHighSuppression);
283   TryEnablingNsWithMode(webrtc::kNsLowSuppression,
284                         webrtc::kNsLowSuppression);
285   TryEnablingNsWithMode(webrtc::kNsModerateSuppression,
286                         webrtc::kNsModerateSuppression);
287   TryEnablingNsWithMode(webrtc::kNsVeryHighSuppression,
288                         webrtc::kNsVeryHighSuppression);
289 
290   // Conference and Default map to concrete values.
291   TryEnablingNsWithMode(webrtc::kNsConference,
292                         webrtc::kNsHighSuppression);
293   TryEnablingNsWithMode(webrtc::kNsDefault,
294                         webrtc::kNsModerateSuppression);
295 }
296 
TEST_F(AudioProcessingTest,RxNsIsOffWithModerateSuppressionByDefault)297 TEST_F(AudioProcessingTest, RxNsIsOffWithModerateSuppressionByDefault) {
298   bool ns_status = true;
299   webrtc::NsModes ns_mode = webrtc::kNsDefault;
300   EXPECT_EQ(0, voe_apm_->GetRxNsStatus(channel_, ns_status, ns_mode));
301 
302   EXPECT_FALSE(ns_status);
303   EXPECT_EQ(webrtc::kNsModerateSuppression, ns_mode);
304 }
305 
TEST_F(AudioProcessingTest,CanSetRxNsMode)306 TEST_F(AudioProcessingTest, CanSetRxNsMode) {
307   EXPECT_EQ(0, voe_apm_->SetRxNsStatus(channel_, true));
308 
309   // See comments on the regular NS test above.
310   TryEnablingRxNsWithMode(webrtc::kNsHighSuppression,
311                           webrtc::kNsHighSuppression);
312   TryEnablingRxNsWithMode(webrtc::kNsLowSuppression,
313                           webrtc::kNsLowSuppression);
314   TryEnablingRxNsWithMode(webrtc::kNsModerateSuppression,
315                           webrtc::kNsModerateSuppression);
316   TryEnablingRxNsWithMode(webrtc::kNsVeryHighSuppression,
317                           webrtc::kNsVeryHighSuppression);
318   TryEnablingRxNsWithMode(webrtc::kNsConference,
319                           webrtc::kNsHighSuppression);
320   TryEnablingRxNsWithMode(webrtc::kNsDefault,
321                           webrtc::kNsModerateSuppression);
322 }
323 
TEST_F(AudioProcessingTest,VadIsDisabledByDefault)324 TEST_F(AudioProcessingTest, VadIsDisabledByDefault) {
325   bool vad_enabled;
326   bool disabled_dtx;
327   webrtc::VadModes vad_mode;
328 
329   EXPECT_EQ(0, voe_codec_->GetVADStatus(
330       channel_, vad_enabled, vad_mode, disabled_dtx));
331 
332   EXPECT_FALSE(vad_enabled);
333 }
334 
TEST_F(AudioProcessingTest,VoiceActivityIndicatorReturns1WithSpeechOn)335 TEST_F(AudioProcessingTest, VoiceActivityIndicatorReturns1WithSpeechOn) {
336   // This sleep is necessary since the voice detection algorithm needs some
337   // time to detect the speech from the fake microphone.
338   Sleep(500);
339   EXPECT_EQ(1, voe_apm_->VoiceActivityIndicator(channel_));
340 }
341 
TEST_F(AudioProcessingTest,CanSetDelayOffset)342 TEST_F(AudioProcessingTest, CanSetDelayOffset) {
343   voe_apm_->SetDelayOffsetMs(50);
344   EXPECT_EQ(50, voe_apm_->DelayOffsetMs());
345   voe_apm_->SetDelayOffsetMs(-50);
346   EXPECT_EQ(-50, voe_apm_->DelayOffsetMs());
347 }
348 
TEST_F(AudioProcessingTest,HighPassFilterIsOnByDefault)349 TEST_F(AudioProcessingTest, HighPassFilterIsOnByDefault) {
350   EXPECT_TRUE(voe_apm_->IsHighPassFilterEnabled());
351 }
352 
TEST_F(AudioProcessingTest,CanSetHighPassFilter)353 TEST_F(AudioProcessingTest, CanSetHighPassFilter) {
354   EXPECT_EQ(0, voe_apm_->EnableHighPassFilter(true));
355   EXPECT_TRUE(voe_apm_->IsHighPassFilterEnabled());
356   EXPECT_EQ(0, voe_apm_->EnableHighPassFilter(false));
357   EXPECT_FALSE(voe_apm_->IsHighPassFilterEnabled());
358 }
359 
TEST_F(AudioProcessingTest,StereoChannelSwappingIsOffByDefault)360 TEST_F(AudioProcessingTest, StereoChannelSwappingIsOffByDefault) {
361   EXPECT_FALSE(voe_apm_->IsStereoChannelSwappingEnabled());
362 }
363 
TEST_F(AudioProcessingTest,CanSetStereoChannelSwapping)364 TEST_F(AudioProcessingTest, CanSetStereoChannelSwapping) {
365   voe_apm_->EnableStereoChannelSwapping(true);
366   EXPECT_TRUE(voe_apm_->IsStereoChannelSwappingEnabled());
367   voe_apm_->EnableStereoChannelSwapping(false);
368   EXPECT_FALSE(voe_apm_->IsStereoChannelSwappingEnabled());
369 }
370 
TEST_F(AudioProcessingTest,CanStartAndStopDebugRecording)371 TEST_F(AudioProcessingTest, CanStartAndStopDebugRecording) {
372   std::string output_path = webrtc::test::OutputPath();
373   std::string output_file = output_path + "apm_debug.txt";
374 
375   EXPECT_EQ(0, voe_apm_->StartDebugRecording(output_file.c_str()));
376   Sleep(1000);
377   EXPECT_EQ(0, voe_apm_->StopDebugRecording());
378 }
379 
380 #if defined(WEBRTC_IOS) || defined(WEBRTC_ANDROID)
381 
TEST_F(AudioProcessingTest,AgcIsOffByDefaultAndDigital)382 TEST_F(AudioProcessingTest, AgcIsOffByDefaultAndDigital) {
383   bool agc_enabled = true;
384   webrtc::AgcModes agc_mode = webrtc::kAgcAdaptiveAnalog;
385 
386   EXPECT_EQ(0, voe_apm_->GetAgcStatus(agc_enabled, agc_mode));
387   EXPECT_FALSE(agc_enabled);
388   EXPECT_EQ(webrtc::kAgcAdaptiveDigital, agc_mode);
389 }
390 
TEST_F(AudioProcessingTest,CanEnableAgcInAdaptiveDigitalMode)391 TEST_F(AudioProcessingTest, CanEnableAgcInAdaptiveDigitalMode) {
392   TryEnablingAgcWithMode(webrtc::kAgcAdaptiveDigital);
393 }
394 
TEST_F(AudioProcessingTest,AgcIsPossibleExceptInAdaptiveAnalogMode)395 TEST_F(AudioProcessingTest, AgcIsPossibleExceptInAdaptiveAnalogMode) {
396   EXPECT_EQ(-1, voe_apm_->SetAgcStatus(true, webrtc::kAgcAdaptiveAnalog));
397   EXPECT_EQ(0, voe_apm_->SetAgcStatus(true, webrtc::kAgcFixedDigital));
398   EXPECT_EQ(0, voe_apm_->SetAgcStatus(true, webrtc::kAgcAdaptiveDigital));
399 }
400 
TEST_F(AudioProcessingTest,EcIsDisabledAndAecmIsDefaultEcMode)401 TEST_F(AudioProcessingTest, EcIsDisabledAndAecmIsDefaultEcMode) {
402   bool ec_enabled = true;
403   webrtc::EcModes ec_mode = webrtc::kEcDefault;
404 
405   EXPECT_EQ(0, voe_apm_->GetEcStatus(ec_enabled, ec_mode));
406   EXPECT_FALSE(ec_enabled);
407   EXPECT_EQ(webrtc::kEcAecm, ec_mode);
408 }
409 
TEST_F(AudioProcessingTest,TestVoiceActivityDetection)410 TEST_F(AudioProcessingTest, TestVoiceActivityDetection) {
411   TryDetectingSilence();
412   TryDetectingSpeechAfterSilence();
413 }
414 
415 #endif  // WEBRTC_IOS || WEBRTC_ANDROID
416