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
15class 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
31class 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
143TEST_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
152TEST_F(AudioProcessingTest, CanEnableAgcWithAllModes) {
153  TryEnablingAgcWithMode(webrtc::kAgcAdaptiveDigital);
154  TryEnablingAgcWithMode(webrtc::kAgcAdaptiveAnalog);
155  TryEnablingAgcWithMode(webrtc::kAgcFixedDigital);
156}
157
158TEST_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
167TEST_F(AudioProcessingTest, EnablingEcAecShouldEnableEcAec) {
168  TryEnablingEcWithMode(webrtc::kEcAec, webrtc::kEcAec);
169}
170
171TEST_F(AudioProcessingTest, EnablingEcConferenceShouldEnableEcAec) {
172  TryEnablingEcWithMode(webrtc::kEcConference, webrtc::kEcAec);
173}
174
175TEST_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
188TEST_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.
203TEST_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
224TEST_F(AudioProcessingTest, EnablingEcAecmShouldEnableEcAecm) {
225  // This one apparently applies to Android and iPhone as well.
226  TryEnablingEcWithMode(webrtc::kEcAecm, webrtc::kEcAecm);
227}
228
229TEST_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
239TEST_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
251TEST_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
260TEST_F(AudioProcessingTest, CanTurnOnDigitalRxAcg) {
261  TryEnablingRxAgcWithMode(webrtc::kAgcAdaptiveDigital);
262  TryEnablingRxAgcWithMode(webrtc::kAgcFixedDigital);
263}
264
265TEST_F(AudioProcessingTest, CannotTurnOnAdaptiveAnalogRxAgc) {
266  EXPECT_EQ(-1, voe_apm_->SetRxAgcStatus(
267      channel_, true, webrtc::kAgcAdaptiveAnalog));
268}
269
270TEST_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
279TEST_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
297TEST_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
306TEST_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
324TEST_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
335TEST_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
342TEST_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
349TEST_F(AudioProcessingTest, HighPassFilterIsOnByDefault) {
350  EXPECT_TRUE(voe_apm_->IsHighPassFilterEnabled());
351}
352
353TEST_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
360TEST_F(AudioProcessingTest, StereoChannelSwappingIsOffByDefault) {
361  EXPECT_FALSE(voe_apm_->IsStereoChannelSwappingEnabled());
362}
363
364TEST_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
371TEST_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
382TEST_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
391TEST_F(AudioProcessingTest, CanEnableAgcInAdaptiveDigitalMode) {
392  TryEnablingAgcWithMode(webrtc::kAgcAdaptiveDigital);
393}
394
395TEST_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
401TEST_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
410TEST_F(AudioProcessingTest, TestVoiceActivityDetection) {
411  TryDetectingSilence();
412  TryDetectingSpeechAfterSilence();
413}
414
415#endif  // WEBRTC_IOS || WEBRTC_ANDROID
416