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