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: 17 RxCallback() : 18 vad_decision(-1) { 19 } 20 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. 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 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. 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. 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 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 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 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 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 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 152 TEST_F(AudioProcessingTest, CanEnableAgcWithAllModes) { 153 TryEnablingAgcWithMode(webrtc::kAgcAdaptiveDigital); 154 TryEnablingAgcWithMode(webrtc::kAgcAdaptiveAnalog); 155 TryEnablingAgcWithMode(webrtc::kAgcFixedDigital); 156 } 157 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 167 TEST_F(AudioProcessingTest, EnablingEcAecShouldEnableEcAec) { 168 TryEnablingEcWithMode(webrtc::kEcAec, webrtc::kEcAec); 169 } 170 171 TEST_F(AudioProcessingTest, EnablingEcConferenceShouldEnableEcAec) { 172 TryEnablingEcWithMode(webrtc::kEcConference, webrtc::kEcAec); 173 } 174 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 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. 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 224 TEST_F(AudioProcessingTest, EnablingEcAecmShouldEnableEcAecm) { 225 // This one apparently applies to Android and iPhone as well. 226 TryEnablingEcWithMode(webrtc::kEcAecm, webrtc::kEcAecm); 227 } 228 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 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 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 260 TEST_F(AudioProcessingTest, CanTurnOnDigitalRxAcg) { 261 TryEnablingRxAgcWithMode(webrtc::kAgcAdaptiveDigital); 262 TryEnablingRxAgcWithMode(webrtc::kAgcFixedDigital); 263 } 264 265 TEST_F(AudioProcessingTest, CannotTurnOnAdaptiveAnalogRxAgc) { 266 EXPECT_EQ(-1, voe_apm_->SetRxAgcStatus( 267 channel_, true, webrtc::kAgcAdaptiveAnalog)); 268 } 269 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 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 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 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 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 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 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 349 TEST_F(AudioProcessingTest, HighPassFilterIsOnByDefault) { 350 EXPECT_TRUE(voe_apm_->IsHighPassFilterEnabled()); 351 } 352 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 360 TEST_F(AudioProcessingTest, StereoChannelSwappingIsOffByDefault) { 361 EXPECT_FALSE(voe_apm_->IsStereoChannelSwappingEnabled()); 362 } 363 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 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 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 391 TEST_F(AudioProcessingTest, CanEnableAgcInAdaptiveDigitalMode) { 392 TryEnablingAgcWithMode(webrtc::kAgcAdaptiveDigital); 393 } 394 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 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 410 TEST_F(AudioProcessingTest, TestVoiceActivityDetection) { 411 TryDetectingSilence(); 412 TryDetectingSpeechAfterSilence(); 413 } 414 415 #endif // WEBRTC_IOS || WEBRTC_ANDROID 416