1/*
2 *  Copyright (c) 2011 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 <cstdio>
12
13#include <gtest/gtest.h>
14
15#include "audio_processing.h"
16#include "audio_processing_unittest.pb.h"
17#include "event_wrapper.h"
18#include "module_common_types.h"
19#include "thread_wrapper.h"
20#include "trace.h"
21#include "signal_processing_library.h"
22
23using webrtc::AudioProcessing;
24using webrtc::AudioFrame;
25using webrtc::GainControl;
26using webrtc::NoiseSuppression;
27using webrtc::EchoCancellation;
28using webrtc::EventWrapper;
29using webrtc::Trace;
30using webrtc::LevelEstimator;
31using webrtc::EchoCancellation;
32using webrtc::EchoControlMobile;
33using webrtc::VoiceDetection;
34
35namespace {
36// When true, this will compare the output data with the results stored to
37// file. This is the typical case. When the file should be updated, it can
38// be set to false with the command-line switch --write_output_data.
39bool global_read_output_data = true;
40
41class ApmEnvironment : public ::testing::Environment {
42 public:
43  virtual void SetUp() {
44    Trace::CreateTrace();
45    ASSERT_EQ(0, Trace::SetTraceFile("apm_trace.txt"));
46  }
47
48  virtual void TearDown() {
49    Trace::ReturnTrace();
50  }
51};
52
53class ApmTest : public ::testing::Test {
54 protected:
55  ApmTest();
56  virtual void SetUp();
57  virtual void TearDown();
58
59  webrtc::AudioProcessing* apm_;
60  webrtc::AudioFrame* frame_;
61  webrtc::AudioFrame* revframe_;
62  FILE* far_file_;
63  FILE* near_file_;
64  bool update_output_data_;
65};
66
67ApmTest::ApmTest()
68    : apm_(NULL),
69      far_file_(NULL),
70      near_file_(NULL),
71      frame_(NULL),
72      revframe_(NULL) {}
73
74void ApmTest::SetUp() {
75  apm_ = AudioProcessing::Create(0);
76  ASSERT_TRUE(apm_ != NULL);
77
78  frame_ = new AudioFrame();
79  revframe_ = new AudioFrame();
80
81  ASSERT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(32000));
82  ASSERT_EQ(apm_->kNoError, apm_->set_num_channels(2, 2));
83  ASSERT_EQ(apm_->kNoError, apm_->set_num_reverse_channels(2));
84
85  frame_->_payloadDataLengthInSamples = 320;
86  frame_->_audioChannel = 2;
87  frame_->_frequencyInHz = 32000;
88  revframe_->_payloadDataLengthInSamples = 320;
89  revframe_->_audioChannel = 2;
90  revframe_->_frequencyInHz = 32000;
91
92  far_file_ = fopen("aec_far.pcm", "rb");
93  ASSERT_TRUE(far_file_ != NULL) << "Could not open input file aec_far.pcm\n";
94  near_file_ = fopen("aec_near.pcm", "rb");
95  ASSERT_TRUE(near_file_ != NULL) << "Could not open input file aec_near.pcm\n";
96}
97
98void ApmTest::TearDown() {
99  if (frame_) {
100    delete frame_;
101  }
102  frame_ = NULL;
103
104  if (revframe_) {
105    delete revframe_;
106  }
107  revframe_ = NULL;
108
109  if (far_file_) {
110    ASSERT_EQ(0, fclose(far_file_));
111  }
112  far_file_ = NULL;
113
114  if (near_file_) {
115    ASSERT_EQ(0, fclose(near_file_));
116  }
117  near_file_ = NULL;
118
119  if (apm_ != NULL) {
120    AudioProcessing::Destroy(apm_);
121  }
122  apm_ = NULL;
123}
124
125void MixStereoToMono(WebRtc_Word16* stereo,
126                     WebRtc_Word16* mono,
127                     int numSamples) {
128  for (int i = 0; i < numSamples; i++) {
129    int int32 = (static_cast<int>(stereo[i * 2]) +
130                 static_cast<int>(stereo[i * 2 + 1])) >> 1;
131    mono[i] = static_cast<WebRtc_Word16>(int32);
132  }
133}
134
135void WriteMessageLiteToFile(const char* filename,
136                            const ::google::protobuf::MessageLite& message) {
137  assert(filename != NULL);
138
139  FILE* file = fopen(filename, "wb");
140  ASSERT_TRUE(file != NULL) << "Could not open " << filename;
141  int size = message.ByteSize();
142  ASSERT_GT(size, 0);
143  unsigned char* array = new unsigned char[size];
144  ASSERT_TRUE(message.SerializeToArray(array, size));
145
146  ASSERT_EQ(1, fwrite(&size, sizeof(int), 1, file));
147  ASSERT_EQ(size, fwrite(array, sizeof(unsigned char), size, file));
148
149  delete [] array;
150  fclose(file);
151}
152
153void ReadMessageLiteFromFile(const char* filename,
154                             ::google::protobuf::MessageLite* message) {
155  assert(filename != NULL);
156  assert(message != NULL);
157
158  FILE* file = fopen(filename, "rb");
159  ASSERT_TRUE(file != NULL) << "Could not open " << filename;
160  int size = 0;
161  ASSERT_EQ(1, fread(&size, sizeof(int), 1, file));
162  ASSERT_GT(size, 0);
163  unsigned char* array = new unsigned char[size];
164  ASSERT_EQ(size, fread(array, sizeof(unsigned char), size, file));
165
166  ASSERT_TRUE(message->ParseFromArray(array, size));
167
168  delete [] array;
169  fclose(file);
170}
171
172struct ThreadData {
173  ThreadData(int thread_num_, AudioProcessing* ap_)
174      : thread_num(thread_num_),
175        error(false),
176        ap(ap_) {}
177  int thread_num;
178  bool error;
179  AudioProcessing* ap;
180};
181
182// Don't use GTest here; non-thread-safe on Windows (as of 1.5.0).
183bool DeadlockProc(void* thread_object) {
184  ThreadData* thread_data = static_cast<ThreadData*>(thread_object);
185  AudioProcessing* ap = thread_data->ap;
186  int err = ap->kNoError;
187
188  AudioFrame primary_frame;
189  AudioFrame reverse_frame;
190  primary_frame._payloadDataLengthInSamples = 320;
191  primary_frame._audioChannel = 2;
192  primary_frame._frequencyInHz = 32000;
193  reverse_frame._payloadDataLengthInSamples = 320;
194  reverse_frame._audioChannel = 2;
195  reverse_frame._frequencyInHz = 32000;
196
197  ap->echo_cancellation()->Enable(true);
198  ap->gain_control()->Enable(true);
199  ap->high_pass_filter()->Enable(true);
200  ap->level_estimator()->Enable(true);
201  ap->noise_suppression()->Enable(true);
202  ap->voice_detection()->Enable(true);
203
204  if (thread_data->thread_num % 2 == 0) {
205    err = ap->AnalyzeReverseStream(&reverse_frame);
206    if (err != ap->kNoError) {
207      printf("Error in AnalyzeReverseStream(): %d\n", err);
208      thread_data->error = true;
209      return false;
210    }
211  }
212
213  if (thread_data->thread_num % 2 == 1) {
214    ap->set_stream_delay_ms(0);
215    ap->echo_cancellation()->set_stream_drift_samples(0);
216    ap->gain_control()->set_stream_analog_level(0);
217    err = ap->ProcessStream(&primary_frame);
218    if (err == ap->kStreamParameterNotSetError) {
219      printf("Expected kStreamParameterNotSetError in ProcessStream(): %d\n",
220          err);
221    } else if (err != ap->kNoError) {
222      printf("Error in ProcessStream(): %d\n", err);
223      thread_data->error = true;
224      return false;
225    }
226    ap->gain_control()->stream_analog_level();
227  }
228
229  EventWrapper* event = EventWrapper::Create();
230  event->Wait(1);
231  delete event;
232  event = NULL;
233
234  return true;
235}
236
237/*TEST_F(ApmTest, Deadlock) {
238  const int num_threads = 16;
239  std::vector<ThreadWrapper*> threads(num_threads);
240  std::vector<ThreadData*> thread_data(num_threads);
241
242  ASSERT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(32000));
243  ASSERT_EQ(apm_->kNoError, apm_->set_num_channels(2, 2));
244  ASSERT_EQ(apm_->kNoError, apm_->set_num_reverse_channels(2));
245
246  for (int i = 0; i < num_threads; i++) {
247    thread_data[i] = new ThreadData(i, apm_);
248    threads[i] = ThreadWrapper::CreateThread(DeadlockProc,
249                                             thread_data[i],
250                                             kNormalPriority,
251                                             0);
252    ASSERT_TRUE(threads[i] != NULL);
253    unsigned int thread_id = 0;
254    threads[i]->Start(thread_id);
255  }
256
257  EventWrapper* event = EventWrapper::Create();
258  ASSERT_EQ(kEventTimeout, event->Wait(5000));
259  delete event;
260  event = NULL;
261
262  for (int i = 0; i < num_threads; i++) {
263    // This will return false if the thread has deadlocked.
264    ASSERT_TRUE(threads[i]->Stop());
265    ASSERT_FALSE(thread_data[i]->error);
266    delete threads[i];
267    threads[i] = NULL;
268    delete thread_data[i];
269    thread_data[i] = NULL;
270  }
271}*/
272
273TEST_F(ApmTest, StreamParameters) {
274  // No errors when the components are disabled.
275  EXPECT_EQ(apm_->kNoError,
276            apm_->ProcessStream(frame_));
277
278  // Missing agc level
279  EXPECT_EQ(apm_->kNoError, apm_->Initialize());
280  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
281  EXPECT_EQ(apm_->kStreamParameterNotSetError,
282            apm_->ProcessStream(frame_));
283  EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
284  EXPECT_EQ(apm_->kNoError,
285            apm_->echo_cancellation()->set_stream_drift_samples(0));
286  EXPECT_EQ(apm_->kStreamParameterNotSetError,
287            apm_->ProcessStream(frame_));
288  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(false));
289
290  // Missing delay
291  EXPECT_EQ(apm_->kNoError, apm_->Initialize());
292  EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
293  EXPECT_EQ(apm_->kStreamParameterNotSetError,
294            apm_->ProcessStream(frame_));
295  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
296  EXPECT_EQ(apm_->kNoError,
297            apm_->echo_cancellation()->set_stream_drift_samples(0));
298  EXPECT_EQ(apm_->kNoError,
299            apm_->gain_control()->set_stream_analog_level(127));
300  EXPECT_EQ(apm_->kStreamParameterNotSetError,
301            apm_->ProcessStream(frame_));
302  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(false));
303
304  // Missing drift
305  EXPECT_EQ(apm_->kNoError, apm_->Initialize());
306  EXPECT_EQ(apm_->kNoError,
307            apm_->echo_cancellation()->enable_drift_compensation(true));
308  EXPECT_EQ(apm_->kStreamParameterNotSetError,
309            apm_->ProcessStream(frame_));
310  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
311  EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
312  EXPECT_EQ(apm_->kNoError,
313            apm_->gain_control()->set_stream_analog_level(127));
314  EXPECT_EQ(apm_->kStreamParameterNotSetError,
315            apm_->ProcessStream(frame_));
316
317  // No stream parameters
318  EXPECT_EQ(apm_->kNoError, apm_->Initialize());
319  EXPECT_EQ(apm_->kNoError,
320            apm_->AnalyzeReverseStream(revframe_));
321  EXPECT_EQ(apm_->kStreamParameterNotSetError,
322            apm_->ProcessStream(frame_));
323
324  // All there
325  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
326  EXPECT_EQ(apm_->kNoError, apm_->Initialize());
327  EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
328  EXPECT_EQ(apm_->kNoError,
329            apm_->echo_cancellation()->set_stream_drift_samples(0));
330  EXPECT_EQ(apm_->kNoError,
331            apm_->gain_control()->set_stream_analog_level(127));
332  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
333}
334
335TEST_F(ApmTest, Channels) {
336  // Testing number of invalid channels
337  EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_channels(0, 1));
338  EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_channels(1, 0));
339  EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_channels(3, 1));
340  EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_channels(1, 3));
341  EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_reverse_channels(0));
342  EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_reverse_channels(3));
343  // Testing number of valid channels
344  for (int i = 1; i < 3; i++) {
345    for (int j = 1; j < 3; j++) {
346      if (j > i) {
347        EXPECT_EQ(apm_->kBadParameterError, apm_->set_num_channels(i, j));
348      } else {
349        EXPECT_EQ(apm_->kNoError, apm_->set_num_channels(i, j));
350        EXPECT_EQ(j, apm_->num_output_channels());
351      }
352    }
353    EXPECT_EQ(i, apm_->num_input_channels());
354    EXPECT_EQ(apm_->kNoError, apm_->set_num_reverse_channels(i));
355    EXPECT_EQ(i, apm_->num_reverse_channels());
356  }
357}
358
359TEST_F(ApmTest, SampleRates) {
360  // Testing invalid sample rates
361  EXPECT_EQ(apm_->kBadParameterError, apm_->set_sample_rate_hz(10000));
362  // Testing valid sample rates
363  int fs[] = {8000, 16000, 32000};
364  for (size_t i = 0; i < sizeof(fs) / sizeof(*fs); i++) {
365    EXPECT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(fs[i]));
366    EXPECT_EQ(fs[i], apm_->sample_rate_hz());
367  }
368}
369
370TEST_F(ApmTest, Process) {
371  GOOGLE_PROTOBUF_VERIFY_VERSION;
372  audio_processing_unittest::OutputData output_data;
373
374  if (global_read_output_data) {
375    ReadMessageLiteFromFile("output_data.pb", &output_data);
376
377  } else {
378    // We don't have a file; add the required tests to the protobuf.
379    int rev_ch[] = {1, 2};
380    int ch[] = {1, 2};
381    int fs[] = {8000, 16000, 32000};
382    for (size_t i = 0; i < sizeof(rev_ch) / sizeof(*rev_ch); i++) {
383      for (size_t j = 0; j < sizeof(ch) / sizeof(*ch); j++) {
384        for (size_t k = 0; k < sizeof(fs) / sizeof(*fs); k++) {
385          audio_processing_unittest::Test* test = output_data.add_test();
386          test->set_numreversechannels(rev_ch[i]);
387          test->set_numchannels(ch[j]);
388          test->set_samplerate(fs[k]);
389        }
390      }
391    }
392  }
393
394  EXPECT_EQ(apm_->kNoError,
395            apm_->echo_cancellation()->enable_drift_compensation(true));
396  EXPECT_EQ(apm_->kNoError,
397            apm_->echo_cancellation()->enable_metrics(true));
398  EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
399
400  EXPECT_EQ(apm_->kNoError,
401            apm_->gain_control()->set_mode(GainControl::kAdaptiveAnalog));
402  EXPECT_EQ(apm_->kNoError,
403            apm_->gain_control()->set_analog_level_limits(0, 255));
404  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
405
406  EXPECT_EQ(apm_->kNoError,
407            apm_->high_pass_filter()->Enable(true));
408
409  //EXPECT_EQ(apm_->kNoError,
410  //          apm_->level_estimator()->Enable(true));
411
412  EXPECT_EQ(apm_->kNoError,
413            apm_->noise_suppression()->Enable(true));
414
415  EXPECT_EQ(apm_->kNoError,
416            apm_->voice_detection()->Enable(true));
417
418  for (int i = 0; i < output_data.test_size(); i++) {
419    printf("Running test %d of %d...\n", i + 1, output_data.test_size());
420
421    audio_processing_unittest::Test* test = output_data.mutable_test(i);
422    const int num_samples = test->samplerate() / 100;
423    revframe_->_payloadDataLengthInSamples = num_samples;
424    revframe_->_audioChannel = test->numreversechannels();
425    revframe_->_frequencyInHz = test->samplerate();
426    frame_->_payloadDataLengthInSamples = num_samples;
427    frame_->_audioChannel = test->numchannels();
428    frame_->_frequencyInHz = test->samplerate();
429
430    EXPECT_EQ(apm_->kNoError, apm_->Initialize());
431    ASSERT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(test->samplerate()));
432    ASSERT_EQ(apm_->kNoError, apm_->set_num_channels(frame_->_audioChannel,
433                                                     frame_->_audioChannel));
434    ASSERT_EQ(apm_->kNoError,
435        apm_->set_num_reverse_channels(revframe_->_audioChannel));
436
437
438    int has_echo_count = 0;
439    int has_voice_count = 0;
440    int is_saturated_count = 0;
441
442    while (1) {
443      WebRtc_Word16 temp_data[640];
444      int analog_level = 127;
445
446      // Read far-end frame
447      size_t read_count = fread(temp_data,
448                                sizeof(WebRtc_Word16),
449                                num_samples * 2,
450                                far_file_);
451      if (read_count != static_cast<size_t>(num_samples * 2)) {
452        // Check that the file really ended.
453        ASSERT_NE(0, feof(far_file_));
454        break; // This is expected.
455      }
456
457      if (revframe_->_audioChannel == 1) {
458        MixStereoToMono(temp_data, revframe_->_payloadData,
459            revframe_->_payloadDataLengthInSamples);
460      } else {
461        memcpy(revframe_->_payloadData,
462               &temp_data[0],
463               sizeof(WebRtc_Word16) * read_count);
464      }
465
466      EXPECT_EQ(apm_->kNoError,
467          apm_->AnalyzeReverseStream(revframe_));
468
469      EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0));
470      EXPECT_EQ(apm_->kNoError,
471          apm_->echo_cancellation()->set_stream_drift_samples(0));
472      EXPECT_EQ(apm_->kNoError,
473          apm_->gain_control()->set_stream_analog_level(analog_level));
474
475      // Read near-end frame
476      read_count = fread(temp_data,
477                         sizeof(WebRtc_Word16),
478                         num_samples * 2,
479                         near_file_);
480      if (read_count != static_cast<size_t>(num_samples * 2)) {
481        // Check that the file really ended.
482        ASSERT_NE(0, feof(near_file_));
483        break; // This is expected.
484      }
485
486      if (frame_->_audioChannel == 1) {
487        MixStereoToMono(temp_data, frame_->_payloadData, num_samples);
488      } else {
489        memcpy(frame_->_payloadData,
490               &temp_data[0],
491               sizeof(WebRtc_Word16) * read_count);
492      }
493
494      EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
495
496      if (apm_->echo_cancellation()->stream_has_echo()) {
497        has_echo_count++;
498      }
499
500      analog_level = apm_->gain_control()->stream_analog_level();
501      if (apm_->gain_control()->stream_is_saturated()) {
502        is_saturated_count++;
503      }
504      if (apm_->voice_detection()->stream_has_voice()) {
505        has_voice_count++;
506      }
507    }
508
509    //<-- Statistics -->
510    //LevelEstimator::Metrics far_metrics;
511    //LevelEstimator::Metrics near_metrics;
512    //EchoCancellation::Metrics echo_metrics;
513    //LevelEstimator::Metrics far_metrics_ref_;
514    //LevelEstimator::Metrics near_metrics_ref_;
515    //EchoCancellation::Metrics echo_metrics_ref_;
516    //EXPECT_EQ(apm_->kNoError,
517    //          apm_->echo_cancellation()->GetMetrics(&echo_metrics));
518    //EXPECT_EQ(apm_->kNoError,
519    //          apm_->level_estimator()->GetMetrics(&near_metrics,
520
521    // TODO(ajm): check echo metrics and output audio.
522    if (global_read_output_data) {
523      EXPECT_EQ(has_echo_count,
524                test->hasechocount());
525      EXPECT_EQ(has_voice_count,
526                test->hasvoicecount());
527      EXPECT_EQ(is_saturated_count,
528                test->issaturatedcount());
529    } else {
530      test->set_hasechocount(has_echo_count);
531      test->set_hasvoicecount(has_voice_count);
532      test->set_issaturatedcount(is_saturated_count);
533    }
534
535    rewind(far_file_);
536    rewind(near_file_);
537  }
538
539  if (!global_read_output_data) {
540    WriteMessageLiteToFile("output_data.pb", output_data);
541  }
542
543  google::protobuf::ShutdownProtobufLibrary();
544}
545
546TEST_F(ApmTest, EchoCancellation) {
547  EXPECT_EQ(apm_->kNoError,
548            apm_->echo_cancellation()->enable_drift_compensation(true));
549  EXPECT_TRUE(apm_->echo_cancellation()->is_drift_compensation_enabled());
550  EXPECT_EQ(apm_->kNoError,
551            apm_->echo_cancellation()->enable_drift_compensation(false));
552  EXPECT_FALSE(apm_->echo_cancellation()->is_drift_compensation_enabled());
553
554  EXPECT_EQ(apm_->kBadParameterError,
555      apm_->echo_cancellation()->set_device_sample_rate_hz(4000));
556  EXPECT_EQ(apm_->kBadParameterError,
557      apm_->echo_cancellation()->set_device_sample_rate_hz(100000));
558
559  int rate[] = {16000, 44100, 48000};
560  for (size_t i = 0; i < sizeof(rate)/sizeof(*rate); i++) {
561    EXPECT_EQ(apm_->kNoError,
562        apm_->echo_cancellation()->set_device_sample_rate_hz(rate[i]));
563    EXPECT_EQ(rate[i],
564        apm_->echo_cancellation()->device_sample_rate_hz());
565  }
566
567  EXPECT_EQ(apm_->kBadParameterError,
568      apm_->echo_cancellation()->set_suppression_level(
569          static_cast<EchoCancellation::SuppressionLevel>(-1)));
570
571  EXPECT_EQ(apm_->kBadParameterError,
572      apm_->echo_cancellation()->set_suppression_level(
573          static_cast<EchoCancellation::SuppressionLevel>(4)));
574
575  EchoCancellation::SuppressionLevel level[] = {
576    EchoCancellation::kLowSuppression,
577    EchoCancellation::kModerateSuppression,
578    EchoCancellation::kHighSuppression,
579  };
580  for (size_t i = 0; i < sizeof(level)/sizeof(*level); i++) {
581    EXPECT_EQ(apm_->kNoError,
582        apm_->echo_cancellation()->set_suppression_level(level[i]));
583    EXPECT_EQ(level[i],
584        apm_->echo_cancellation()->suppression_level());
585  }
586
587  EchoCancellation::Metrics metrics;
588  EXPECT_EQ(apm_->kNotEnabledError,
589            apm_->echo_cancellation()->GetMetrics(&metrics));
590
591  EXPECT_EQ(apm_->kNoError,
592            apm_->echo_cancellation()->enable_metrics(true));
593  EXPECT_TRUE(apm_->echo_cancellation()->are_metrics_enabled());
594  EXPECT_EQ(apm_->kNoError,
595            apm_->echo_cancellation()->enable_metrics(false));
596  EXPECT_FALSE(apm_->echo_cancellation()->are_metrics_enabled());
597
598  EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
599  EXPECT_TRUE(apm_->echo_cancellation()->is_enabled());
600  EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false));
601  EXPECT_FALSE(apm_->echo_cancellation()->is_enabled());
602}
603
604TEST_F(ApmTest, EchoControlMobile) {
605  // AECM won't use super-wideband.
606  EXPECT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(32000));
607  EXPECT_EQ(apm_->kBadSampleRateError, apm_->echo_control_mobile()->Enable(true));
608  EXPECT_EQ(apm_->kNoError, apm_->set_sample_rate_hz(16000));
609  // Turn AECM on (and AEC off)
610  EXPECT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(true));
611  EXPECT_TRUE(apm_->echo_control_mobile()->is_enabled());
612
613  EXPECT_EQ(apm_->kBadParameterError,
614      apm_->echo_control_mobile()->set_routing_mode(
615      static_cast<EchoControlMobile::RoutingMode>(-1)));
616  EXPECT_EQ(apm_->kBadParameterError,
617      apm_->echo_control_mobile()->set_routing_mode(
618      static_cast<EchoControlMobile::RoutingMode>(5)));
619
620  // Toggle routing modes
621  EchoControlMobile::RoutingMode mode[] = {
622      EchoControlMobile::kQuietEarpieceOrHeadset,
623      EchoControlMobile::kEarpiece,
624      EchoControlMobile::kLoudEarpiece,
625      EchoControlMobile::kSpeakerphone,
626      EchoControlMobile::kLoudSpeakerphone,
627  };
628  for (size_t i = 0; i < sizeof(mode)/sizeof(*mode); i++) {
629    EXPECT_EQ(apm_->kNoError,
630        apm_->echo_control_mobile()->set_routing_mode(mode[i]));
631    EXPECT_EQ(mode[i],
632        apm_->echo_control_mobile()->routing_mode());
633  }
634  // Turn comfort noise off/on
635  EXPECT_EQ(apm_->kNoError,
636      apm_->echo_control_mobile()->enable_comfort_noise(false));
637  EXPECT_FALSE(apm_->echo_control_mobile()->is_comfort_noise_enabled());
638  EXPECT_EQ(apm_->kNoError,
639      apm_->echo_control_mobile()->enable_comfort_noise(true));
640  EXPECT_TRUE(apm_->echo_control_mobile()->is_comfort_noise_enabled());
641  // Turn AECM off
642  EXPECT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(false));
643  EXPECT_FALSE(apm_->echo_control_mobile()->is_enabled());
644}
645
646TEST_F(ApmTest, GainControl) {
647  // Testing gain modes
648  EXPECT_EQ(apm_->kBadParameterError,
649      apm_->gain_control()->set_mode(static_cast<GainControl::Mode>(-1)));
650
651  EXPECT_EQ(apm_->kBadParameterError,
652      apm_->gain_control()->set_mode(static_cast<GainControl::Mode>(3)));
653
654  EXPECT_EQ(apm_->kNoError,
655      apm_->gain_control()->set_mode(
656      apm_->gain_control()->mode()));
657
658  GainControl::Mode mode[] = {
659    GainControl::kAdaptiveAnalog,
660    GainControl::kAdaptiveDigital,
661    GainControl::kFixedDigital
662  };
663  for (size_t i = 0; i < sizeof(mode)/sizeof(*mode); i++) {
664    EXPECT_EQ(apm_->kNoError,
665        apm_->gain_control()->set_mode(mode[i]));
666    EXPECT_EQ(mode[i], apm_->gain_control()->mode());
667  }
668  // Testing invalid target levels
669  EXPECT_EQ(apm_->kBadParameterError,
670      apm_->gain_control()->set_target_level_dbfs(-3));
671  EXPECT_EQ(apm_->kBadParameterError,
672      apm_->gain_control()->set_target_level_dbfs(-40));
673  // Testing valid target levels
674  EXPECT_EQ(apm_->kNoError,
675      apm_->gain_control()->set_target_level_dbfs(
676      apm_->gain_control()->target_level_dbfs()));
677
678  int level_dbfs[] = {0, 6, 31};
679  for (size_t i = 0; i < sizeof(level_dbfs)/sizeof(*level_dbfs); i++) {
680    EXPECT_EQ(apm_->kNoError,
681        apm_->gain_control()->set_target_level_dbfs(level_dbfs[i]));
682    EXPECT_EQ(level_dbfs[i], apm_->gain_control()->target_level_dbfs());
683  }
684
685  // Testing invalid compression gains
686  EXPECT_EQ(apm_->kBadParameterError,
687      apm_->gain_control()->set_compression_gain_db(-1));
688  EXPECT_EQ(apm_->kBadParameterError,
689      apm_->gain_control()->set_compression_gain_db(100));
690
691  // Testing valid compression gains
692  EXPECT_EQ(apm_->kNoError,
693      apm_->gain_control()->set_compression_gain_db(
694      apm_->gain_control()->compression_gain_db()));
695
696  int gain_db[] = {0, 10, 90};
697  for (size_t i = 0; i < sizeof(gain_db)/sizeof(*gain_db); i++) {
698    EXPECT_EQ(apm_->kNoError,
699        apm_->gain_control()->set_compression_gain_db(gain_db[i]));
700    EXPECT_EQ(gain_db[i], apm_->gain_control()->compression_gain_db());
701  }
702
703  // Testing limiter off/on
704  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->enable_limiter(false));
705  EXPECT_FALSE(apm_->gain_control()->is_limiter_enabled());
706  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->enable_limiter(true));
707  EXPECT_TRUE(apm_->gain_control()->is_limiter_enabled());
708
709  // Testing invalid level limits
710  EXPECT_EQ(apm_->kBadParameterError,
711      apm_->gain_control()->set_analog_level_limits(-1, 512));
712  EXPECT_EQ(apm_->kBadParameterError,
713      apm_->gain_control()->set_analog_level_limits(100000, 512));
714  EXPECT_EQ(apm_->kBadParameterError,
715      apm_->gain_control()->set_analog_level_limits(512, -1));
716  EXPECT_EQ(apm_->kBadParameterError,
717      apm_->gain_control()->set_analog_level_limits(512, 100000));
718  EXPECT_EQ(apm_->kBadParameterError,
719      apm_->gain_control()->set_analog_level_limits(512, 255));
720
721  // Testing valid level limits
722  EXPECT_EQ(apm_->kNoError,
723      apm_->gain_control()->set_analog_level_limits(
724      apm_->gain_control()->analog_level_minimum(),
725      apm_->gain_control()->analog_level_maximum()));
726
727  int min_level[] = {0, 255, 1024};
728  for (size_t i = 0; i < sizeof(min_level)/sizeof(*min_level); i++) {
729    EXPECT_EQ(apm_->kNoError,
730        apm_->gain_control()->set_analog_level_limits(min_level[i], 1024));
731    EXPECT_EQ(min_level[i], apm_->gain_control()->analog_level_minimum());
732  }
733
734  int max_level[] = {0, 1024, 65535};
735  for (size_t i = 0; i < sizeof(min_level)/sizeof(*min_level); i++) {
736    EXPECT_EQ(apm_->kNoError,
737        apm_->gain_control()->set_analog_level_limits(0, max_level[i]));
738    EXPECT_EQ(max_level[i], apm_->gain_control()->analog_level_maximum());
739  }
740
741  // TODO(ajm): stream_is_saturated() and stream_analog_level()
742
743  // Turn AGC off
744  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(false));
745  EXPECT_FALSE(apm_->gain_control()->is_enabled());
746}
747
748TEST_F(ApmTest, NoiseSuppression) {
749  // Tesing invalid suppression levels
750  EXPECT_EQ(apm_->kBadParameterError,
751      apm_->noise_suppression()->set_level(
752          static_cast<NoiseSuppression::Level>(-1)));
753
754  EXPECT_EQ(apm_->kBadParameterError,
755      apm_->noise_suppression()->set_level(
756          static_cast<NoiseSuppression::Level>(5)));
757
758  // Tesing valid suppression levels
759  NoiseSuppression::Level level[] = {
760    NoiseSuppression::kLow,
761    NoiseSuppression::kModerate,
762    NoiseSuppression::kHigh,
763    NoiseSuppression::kVeryHigh
764  };
765  for (size_t i = 0; i < sizeof(level)/sizeof(*level); i++) {
766    EXPECT_EQ(apm_->kNoError,
767        apm_->noise_suppression()->set_level(level[i]));
768    EXPECT_EQ(level[i], apm_->noise_suppression()->level());
769  }
770
771  // Turing NS on/off
772  EXPECT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(true));
773  EXPECT_TRUE(apm_->noise_suppression()->is_enabled());
774  EXPECT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(false));
775  EXPECT_FALSE(apm_->noise_suppression()->is_enabled());
776}
777
778TEST_F(ApmTest, HighPassFilter) {
779  // Turing HP filter on/off
780  EXPECT_EQ(apm_->kNoError, apm_->high_pass_filter()->Enable(true));
781  EXPECT_TRUE(apm_->high_pass_filter()->is_enabled());
782  EXPECT_EQ(apm_->kNoError, apm_->high_pass_filter()->Enable(false));
783  EXPECT_FALSE(apm_->high_pass_filter()->is_enabled());
784}
785
786TEST_F(ApmTest, LevelEstimator) {
787  // Turing Level estimator on/off
788  EXPECT_EQ(apm_->kUnsupportedComponentError,
789            apm_->level_estimator()->Enable(true));
790  EXPECT_FALSE(apm_->level_estimator()->is_enabled());
791  EXPECT_EQ(apm_->kUnsupportedComponentError,
792            apm_->level_estimator()->Enable(false));
793  EXPECT_FALSE(apm_->level_estimator()->is_enabled());
794}
795
796TEST_F(ApmTest, VoiceDetection) {
797  // Test external VAD
798  EXPECT_EQ(apm_->kNoError,
799            apm_->voice_detection()->set_stream_has_voice(true));
800  EXPECT_TRUE(apm_->voice_detection()->stream_has_voice());
801  EXPECT_EQ(apm_->kNoError,
802            apm_->voice_detection()->set_stream_has_voice(false));
803  EXPECT_FALSE(apm_->voice_detection()->stream_has_voice());
804
805  // Tesing invalid likelihoods
806  EXPECT_EQ(apm_->kBadParameterError,
807      apm_->voice_detection()->set_likelihood(
808          static_cast<VoiceDetection::Likelihood>(-1)));
809
810  EXPECT_EQ(apm_->kBadParameterError,
811      apm_->voice_detection()->set_likelihood(
812          static_cast<VoiceDetection::Likelihood>(5)));
813
814  // Tesing valid likelihoods
815  VoiceDetection::Likelihood likelihood[] = {
816      VoiceDetection::kVeryLowLikelihood,
817      VoiceDetection::kLowLikelihood,
818      VoiceDetection::kModerateLikelihood,
819      VoiceDetection::kHighLikelihood
820  };
821  for (size_t i = 0; i < sizeof(likelihood)/sizeof(*likelihood); i++) {
822    EXPECT_EQ(apm_->kNoError,
823              apm_->voice_detection()->set_likelihood(likelihood[i]));
824    EXPECT_EQ(likelihood[i], apm_->voice_detection()->likelihood());
825  }
826
827  /* TODO(bjornv): Enable once VAD supports other frame lengths than 10 ms
828  // Tesing invalid frame sizes
829  EXPECT_EQ(apm_->kBadParameterError,
830      apm_->voice_detection()->set_frame_size_ms(12));
831
832  // Tesing valid frame sizes
833  for (int i = 10; i <= 30; i += 10) {
834    EXPECT_EQ(apm_->kNoError,
835        apm_->voice_detection()->set_frame_size_ms(i));
836    EXPECT_EQ(i, apm_->voice_detection()->frame_size_ms());
837  }
838  */
839
840  // Turing VAD on/off
841  EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true));
842  EXPECT_TRUE(apm_->voice_detection()->is_enabled());
843  EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(false));
844  EXPECT_FALSE(apm_->voice_detection()->is_enabled());
845
846  // TODO(bjornv): Add tests for streamed voice; stream_has_voice()
847}
848
849// Below are some ideas for tests from VPM.
850
851/*TEST_F(VideoProcessingModuleTest, GetVersionTest)
852{
853}
854
855TEST_F(VideoProcessingModuleTest, HandleNullBuffer)
856{
857}
858
859TEST_F(VideoProcessingModuleTest, HandleBadSize)
860{
861}
862
863TEST_F(VideoProcessingModuleTest, IdenticalResultsAfterReset)
864{
865}
866*/
867}  // namespace
868
869int main(int argc, char** argv) {
870  ::testing::InitGoogleTest(&argc, argv);
871  ApmEnvironment* env = new ApmEnvironment; // GTest takes ownership.
872  ::testing::AddGlobalTestEnvironment(env);
873
874  for (int i = 1; i < argc; i++) {
875    if (strcmp(argv[i], "--write_output_data") == 0) {
876      global_read_output_data = false;
877    }
878  }
879
880  return RUN_ALL_TESTS();
881}
882