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 <math.h>
12#include <stdio.h>
13#include <algorithm>
14#include <limits>
15#include <queue>
16
17#include "webrtc/common_audio/include/audio_util.h"
18#include "webrtc/common_audio/resampler/include/push_resampler.h"
19#include "webrtc/common_audio/resampler/push_sinc_resampler.h"
20#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
21#include "webrtc/modules/audio_processing/include/audio_processing.h"
22#include "webrtc/modules/audio_processing/test/test_utils.h"
23#include "webrtc/modules/interface/module_common_types.h"
24#include "webrtc/system_wrappers/interface/event_wrapper.h"
25#include "webrtc/system_wrappers/interface/scoped_ptr.h"
26#include "webrtc/system_wrappers/interface/trace.h"
27#include "webrtc/test/testsupport/fileutils.h"
28#include "webrtc/test/testsupport/gtest_disable.h"
29#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
30#include "gtest/gtest.h"
31#include "external/webrtc/webrtc/modules/audio_processing/test/unittest.pb.h"
32#else
33#include "testing/gtest/include/gtest/gtest.h"
34#include "webrtc/audio_processing/unittest.pb.h"
35#endif
36
37namespace webrtc {
38namespace {
39
40// TODO(bjornv): This is not feasible until the functionality has been
41// re-implemented; see comment at the bottom of this file. For now, the user has
42// to hard code the |write_ref_data| value.
43// When false, this will compare the output data with the results stored to
44// file. This is the typical case. When the file should be updated, it can
45// be set to true with the command-line switch --write_ref_data.
46bool write_ref_data = false;
47const int kChannels[] = {1, 2};
48const size_t kChannelsSize = sizeof(kChannels) / sizeof(*kChannels);
49
50const int kSampleRates[] = {8000, 16000, 32000};
51const size_t kSampleRatesSize = sizeof(kSampleRates) / sizeof(*kSampleRates);
52
53#if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE)
54// AECM doesn't support super-wb.
55const int kProcessSampleRates[] = {8000, 16000};
56#elif defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
57const int kProcessSampleRates[] = {8000, 16000, 32000};
58#endif
59const size_t kProcessSampleRatesSize = sizeof(kProcessSampleRates) /
60    sizeof(*kProcessSampleRates);
61
62void ConvertToFloat(const int16_t* int_data, ChannelBuffer<float>* cb) {
63  ChannelBuffer<int16_t> cb_int(cb->samples_per_channel(),
64                                cb->num_channels());
65  Deinterleave(int_data,
66               cb->samples_per_channel(),
67               cb->num_channels(),
68               cb_int.channels());
69  ScaleToFloat(cb_int.data(),
70               cb->samples_per_channel() * cb->num_channels(),
71               cb->data());
72}
73
74void ConvertToFloat(const AudioFrame& frame, ChannelBuffer<float>* cb) {
75  ConvertToFloat(frame.data_, cb);
76}
77
78// Number of channels including the keyboard channel.
79int TotalChannelsFromLayout(AudioProcessing::ChannelLayout layout) {
80  switch (layout) {
81    case AudioProcessing::kMono:
82      return 1;
83    case AudioProcessing::kMonoAndKeyboard:
84    case AudioProcessing::kStereo:
85      return 2;
86    case AudioProcessing::kStereoAndKeyboard:
87      return 3;
88  }
89  assert(false);
90  return -1;
91}
92
93int TruncateToMultipleOf10(int value) {
94  return (value / 10) * 10;
95}
96
97void MixStereoToMono(const float* stereo, float* mono,
98                     int samples_per_channel) {
99  for (int i = 0; i < samples_per_channel; ++i) {
100    mono[i] = (stereo[i * 2] + stereo[i * 2 + 1]) / 2;
101  }
102}
103
104void MixStereoToMono(const int16_t* stereo, int16_t* mono,
105                     int samples_per_channel) {
106  for (int i = 0; i < samples_per_channel; i++)
107    mono[i] = (stereo[i * 2] + stereo[i * 2 + 1]) >> 1;
108}
109
110void CopyLeftToRightChannel(int16_t* stereo, int samples_per_channel) {
111  for (int i = 0; i < samples_per_channel; i++) {
112    stereo[i * 2 + 1] = stereo[i * 2];
113  }
114}
115
116void VerifyChannelsAreEqual(int16_t* stereo, int samples_per_channel) {
117  for (int i = 0; i < samples_per_channel; i++) {
118    EXPECT_EQ(stereo[i * 2 + 1], stereo[i * 2]);
119  }
120}
121
122void SetFrameTo(AudioFrame* frame, int16_t value) {
123  for (int i = 0; i < frame->samples_per_channel_ * frame->num_channels_; ++i) {
124    frame->data_[i] = value;
125  }
126}
127
128void SetFrameTo(AudioFrame* frame, int16_t left, int16_t right) {
129  ASSERT_EQ(2, frame->num_channels_);
130  for (int i = 0; i < frame->samples_per_channel_ * 2; i += 2) {
131    frame->data_[i] = left;
132    frame->data_[i + 1] = right;
133  }
134}
135
136void ScaleFrame(AudioFrame* frame, float scale) {
137  for (int i = 0; i < frame->samples_per_channel_ * frame->num_channels_; ++i) {
138    frame->data_[i] = RoundToInt16(frame->data_[i] * scale);
139  }
140}
141
142bool FrameDataAreEqual(const AudioFrame& frame1, const AudioFrame& frame2) {
143  if (frame1.samples_per_channel_ != frame2.samples_per_channel_) {
144    return false;
145  }
146  if (frame1.num_channels_ != frame2.num_channels_) {
147    return false;
148  }
149  if (memcmp(frame1.data_, frame2.data_,
150             frame1.samples_per_channel_ * frame1.num_channels_ *
151                 sizeof(int16_t))) {
152    return false;
153  }
154  return true;
155}
156
157void EnableAllAPComponents(AudioProcessing* ap) {
158#if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE)
159  EXPECT_NOERR(ap->echo_control_mobile()->Enable(true));
160
161  EXPECT_NOERR(ap->gain_control()->set_mode(GainControl::kAdaptiveDigital));
162  EXPECT_NOERR(ap->gain_control()->Enable(true));
163#elif defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
164  EXPECT_NOERR(ap->echo_cancellation()->enable_drift_compensation(true));
165  EXPECT_NOERR(ap->echo_cancellation()->enable_metrics(true));
166  EXPECT_NOERR(ap->echo_cancellation()->enable_delay_logging(true));
167  EXPECT_NOERR(ap->echo_cancellation()->Enable(true));
168
169  EXPECT_NOERR(ap->gain_control()->set_mode(GainControl::kAdaptiveAnalog));
170  EXPECT_NOERR(ap->gain_control()->set_analog_level_limits(0, 255));
171  EXPECT_NOERR(ap->gain_control()->Enable(true));
172#endif
173
174  EXPECT_NOERR(ap->high_pass_filter()->Enable(true));
175  EXPECT_NOERR(ap->level_estimator()->Enable(true));
176  EXPECT_NOERR(ap->noise_suppression()->Enable(true));
177
178  EXPECT_NOERR(ap->voice_detection()->Enable(true));
179}
180
181// These functions are only used by ApmTest.Process.
182template <class T>
183T AbsValue(T a) {
184  return a > 0 ? a: -a;
185}
186
187int16_t MaxAudioFrame(const AudioFrame& frame) {
188  const int length = frame.samples_per_channel_ * frame.num_channels_;
189  int16_t max_data = AbsValue(frame.data_[0]);
190  for (int i = 1; i < length; i++) {
191    max_data = std::max(max_data, AbsValue(frame.data_[i]));
192  }
193
194  return max_data;
195}
196
197#if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
198void TestStats(const AudioProcessing::Statistic& test,
199               const audioproc::Test::Statistic& reference) {
200  EXPECT_EQ(reference.instant(), test.instant);
201  EXPECT_EQ(reference.average(), test.average);
202  EXPECT_EQ(reference.maximum(), test.maximum);
203  EXPECT_EQ(reference.minimum(), test.minimum);
204}
205
206void WriteStatsMessage(const AudioProcessing::Statistic& output,
207                       audioproc::Test::Statistic* msg) {
208  msg->set_instant(output.instant);
209  msg->set_average(output.average);
210  msg->set_maximum(output.maximum);
211  msg->set_minimum(output.minimum);
212}
213#endif
214
215void OpenFileAndWriteMessage(const std::string filename,
216                             const ::google::protobuf::MessageLite& msg) {
217#if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID)
218  FILE* file = fopen(filename.c_str(), "wb");
219  ASSERT_TRUE(file != NULL);
220
221  int32_t size = msg.ByteSize();
222  ASSERT_GT(size, 0);
223  scoped_ptr<uint8_t[]> array(new uint8_t[size]);
224  ASSERT_TRUE(msg.SerializeToArray(array.get(), size));
225
226  ASSERT_EQ(1u, fwrite(&size, sizeof(size), 1, file));
227  ASSERT_EQ(static_cast<size_t>(size),
228      fwrite(array.get(), sizeof(array[0]), size, file));
229  fclose(file);
230#else
231  std::cout << "Warning: Writing new reference is only allowed on Linux!"
232      << std::endl;
233#endif
234}
235
236std::string ResourceFilePath(std::string name, int sample_rate_hz) {
237  std::ostringstream ss;
238  // Resource files are all stereo.
239  ss << name << sample_rate_hz / 1000 << "_stereo";
240  return test::ResourcePath(ss.str(), "pcm");
241}
242
243std::string OutputFilePath(std::string name,
244                           int input_rate,
245                           int output_rate,
246                           int reverse_rate,
247                           int num_input_channels,
248                           int num_output_channels,
249                           int num_reverse_channels) {
250  std::ostringstream ss;
251  ss << name << "_i" << num_input_channels << "_" << input_rate / 1000
252     << "_r" << num_reverse_channels << "_" << reverse_rate  / 1000 << "_";
253  if (num_output_channels == 1) {
254    ss << "mono";
255  } else if (num_output_channels == 2) {
256    ss << "stereo";
257  } else {
258    assert(false);
259  }
260  ss << output_rate / 1000 << ".pcm";
261
262  return test::OutputPath() + ss.str();
263}
264
265void OpenFileAndReadMessage(const std::string filename,
266                            ::google::protobuf::MessageLite* msg) {
267  FILE* file = fopen(filename.c_str(), "rb");
268  ASSERT_TRUE(file != NULL);
269  ReadMessageFromFile(file, msg);
270  fclose(file);
271}
272
273class ApmTest : public ::testing::Test {
274 protected:
275  ApmTest();
276  virtual void SetUp();
277  virtual void TearDown();
278
279  static void SetUpTestCase() {
280    Trace::CreateTrace();
281    std::string trace_filename = test::OutputPath() + "audioproc_trace.txt";
282    ASSERT_EQ(0, Trace::SetTraceFile(trace_filename.c_str()));
283  }
284
285  static void TearDownTestCase() {
286    Trace::ReturnTrace();
287  }
288
289  // Used to select between int and float interface tests.
290  enum Format {
291    kIntFormat,
292    kFloatFormat
293  };
294
295  void Init(int sample_rate_hz,
296            int output_sample_rate_hz,
297            int reverse_sample_rate_hz,
298            int num_reverse_channels,
299            int num_input_channels,
300            int num_output_channels,
301            bool open_output_file);
302  void Init(AudioProcessing* ap);
303  void EnableAllComponents();
304  bool ReadFrame(FILE* file, AudioFrame* frame);
305  bool ReadFrame(FILE* file, AudioFrame* frame, ChannelBuffer<float>* cb);
306  void ReadFrameWithRewind(FILE* file, AudioFrame* frame);
307  void ReadFrameWithRewind(FILE* file, AudioFrame* frame,
308                           ChannelBuffer<float>* cb);
309  void ProcessWithDefaultStreamParameters(AudioFrame* frame);
310  void ProcessDelayVerificationTest(int delay_ms, int system_delay_ms,
311                                    int delay_min, int delay_max);
312  void TestChangingChannels(int num_channels,
313                            AudioProcessing::Error expected_return);
314  void RunQuantizedVolumeDoesNotGetStuckTest(int sample_rate);
315  void RunManualVolumeChangeIsPossibleTest(int sample_rate);
316  void StreamParametersTest(Format format);
317  int ProcessStreamChooser(Format format);
318  int AnalyzeReverseStreamChooser(Format format);
319  void ProcessDebugDump(const std::string& in_filename,
320                        const std::string& out_filename,
321                        Format format);
322  void VerifyDebugDumpTest(Format format);
323
324  const std::string output_path_;
325  const std::string ref_path_;
326  const std::string ref_filename_;
327  scoped_ptr<AudioProcessing> apm_;
328  AudioFrame* frame_;
329  AudioFrame* revframe_;
330  scoped_ptr<ChannelBuffer<float> > float_cb_;
331  scoped_ptr<ChannelBuffer<float> > revfloat_cb_;
332  int output_sample_rate_hz_;
333  int num_output_channels_;
334  FILE* far_file_;
335  FILE* near_file_;
336  FILE* out_file_;
337};
338
339ApmTest::ApmTest()
340    : output_path_(test::OutputPath()),
341      ref_path_(test::ProjectRootPath() + "data/audio_processing/"),
342#if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE)
343      ref_filename_(ref_path_ + "output_data_fixed.pb"),
344#elif defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
345      ref_filename_(ref_path_ + "output_data_float.pb"),
346#endif
347      frame_(NULL),
348      revframe_(NULL),
349      output_sample_rate_hz_(0),
350      num_output_channels_(0),
351      far_file_(NULL),
352      near_file_(NULL),
353      out_file_(NULL) {
354  Config config;
355  config.Set<ExperimentalAgc>(new ExperimentalAgc(false));
356  apm_.reset(AudioProcessing::Create(config));
357}
358
359void ApmTest::SetUp() {
360  ASSERT_TRUE(apm_.get() != NULL);
361
362  frame_ = new AudioFrame();
363  revframe_ = new AudioFrame();
364
365#if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE)
366  Init(16000, 16000, 16000, 2, 2, 2, false);
367#else
368  Init(32000, 32000, 32000, 2, 2, 2, false);
369#endif
370}
371
372void ApmTest::TearDown() {
373  if (frame_) {
374    delete frame_;
375  }
376  frame_ = NULL;
377
378  if (revframe_) {
379    delete revframe_;
380  }
381  revframe_ = NULL;
382
383  if (far_file_) {
384    ASSERT_EQ(0, fclose(far_file_));
385  }
386  far_file_ = NULL;
387
388  if (near_file_) {
389    ASSERT_EQ(0, fclose(near_file_));
390  }
391  near_file_ = NULL;
392
393  if (out_file_) {
394    ASSERT_EQ(0, fclose(out_file_));
395  }
396  out_file_ = NULL;
397}
398
399void ApmTest::Init(AudioProcessing* ap) {
400  ASSERT_EQ(kNoErr,
401            ap->Initialize(frame_->sample_rate_hz_,
402                           output_sample_rate_hz_,
403                           revframe_->sample_rate_hz_,
404                           LayoutFromChannels(frame_->num_channels_),
405                           LayoutFromChannels(num_output_channels_),
406                           LayoutFromChannels(revframe_->num_channels_)));
407}
408
409void ApmTest::Init(int sample_rate_hz,
410                   int output_sample_rate_hz,
411                   int reverse_sample_rate_hz,
412                   int num_input_channels,
413                   int num_output_channels,
414                   int num_reverse_channels,
415                   bool open_output_file) {
416  SetContainerFormat(sample_rate_hz, num_input_channels, frame_, &float_cb_);
417  output_sample_rate_hz_ = output_sample_rate_hz;
418  num_output_channels_ = num_output_channels;
419
420  SetContainerFormat(reverse_sample_rate_hz, num_reverse_channels, revframe_,
421                     &revfloat_cb_);
422  Init(apm_.get());
423
424  if (far_file_) {
425    ASSERT_EQ(0, fclose(far_file_));
426  }
427  std::string filename = ResourceFilePath("far", sample_rate_hz);
428  far_file_ = fopen(filename.c_str(), "rb");
429  ASSERT_TRUE(far_file_ != NULL) << "Could not open file " <<
430      filename << "\n";
431
432  if (near_file_) {
433    ASSERT_EQ(0, fclose(near_file_));
434  }
435  filename = ResourceFilePath("near", sample_rate_hz);
436  near_file_ = fopen(filename.c_str(), "rb");
437  ASSERT_TRUE(near_file_ != NULL) << "Could not open file " <<
438        filename << "\n";
439
440  if (open_output_file) {
441    if (out_file_) {
442      ASSERT_EQ(0, fclose(out_file_));
443    }
444    filename = OutputFilePath("out",
445                              sample_rate_hz,
446                              output_sample_rate_hz,
447                              reverse_sample_rate_hz,
448                              num_input_channels,
449                              num_output_channels,
450                              num_reverse_channels);
451    out_file_ = fopen(filename.c_str(), "wb");
452    ASSERT_TRUE(out_file_ != NULL) << "Could not open file " <<
453          filename << "\n";
454  }
455}
456
457void ApmTest::EnableAllComponents() {
458  EnableAllAPComponents(apm_.get());
459}
460
461bool ApmTest::ReadFrame(FILE* file, AudioFrame* frame,
462                        ChannelBuffer<float>* cb) {
463  // The files always contain stereo audio.
464  size_t frame_size = frame->samples_per_channel_ * 2;
465  size_t read_count = fread(frame->data_,
466                            sizeof(int16_t),
467                            frame_size,
468                            file);
469  if (read_count != frame_size) {
470    // Check that the file really ended.
471    EXPECT_NE(0, feof(file));
472    return false;  // This is expected.
473  }
474
475  if (frame->num_channels_ == 1) {
476    MixStereoToMono(frame->data_, frame->data_,
477                    frame->samples_per_channel_);
478  }
479
480  if (cb) {
481    ConvertToFloat(*frame, cb);
482  }
483  return true;
484}
485
486bool ApmTest::ReadFrame(FILE* file, AudioFrame* frame) {
487  return ReadFrame(file, frame, NULL);
488}
489
490// If the end of the file has been reached, rewind it and attempt to read the
491// frame again.
492void ApmTest::ReadFrameWithRewind(FILE* file, AudioFrame* frame,
493                                  ChannelBuffer<float>* cb) {
494  if (!ReadFrame(near_file_, frame_, cb)) {
495    rewind(near_file_);
496    ASSERT_TRUE(ReadFrame(near_file_, frame_, cb));
497  }
498}
499
500void ApmTest::ReadFrameWithRewind(FILE* file, AudioFrame* frame) {
501  ReadFrameWithRewind(file, frame, NULL);
502}
503
504void ApmTest::ProcessWithDefaultStreamParameters(AudioFrame* frame) {
505  EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0));
506  apm_->echo_cancellation()->set_stream_drift_samples(0);
507  EXPECT_EQ(apm_->kNoError,
508      apm_->gain_control()->set_stream_analog_level(127));
509  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame));
510}
511
512int ApmTest::ProcessStreamChooser(Format format) {
513  if (format == kIntFormat) {
514    return apm_->ProcessStream(frame_);
515  }
516  return apm_->ProcessStream(float_cb_->channels(),
517                             frame_->samples_per_channel_,
518                             frame_->sample_rate_hz_,
519                             LayoutFromChannels(frame_->num_channels_),
520                             output_sample_rate_hz_,
521                             LayoutFromChannels(num_output_channels_),
522                             float_cb_->channels());
523}
524
525int ApmTest::AnalyzeReverseStreamChooser(Format format) {
526  if (format == kIntFormat) {
527    return apm_->AnalyzeReverseStream(revframe_);
528  }
529  return apm_->AnalyzeReverseStream(
530      revfloat_cb_->channels(),
531      revframe_->samples_per_channel_,
532      revframe_->sample_rate_hz_,
533      LayoutFromChannels(revframe_->num_channels_));
534}
535
536void ApmTest::ProcessDelayVerificationTest(int delay_ms, int system_delay_ms,
537                                           int delay_min, int delay_max) {
538  // The |revframe_| and |frame_| should include the proper frame information,
539  // hence can be used for extracting information.
540  AudioFrame tmp_frame;
541  std::queue<AudioFrame*> frame_queue;
542  bool causal = true;
543
544  tmp_frame.CopyFrom(*revframe_);
545  SetFrameTo(&tmp_frame, 0);
546
547  EXPECT_EQ(apm_->kNoError, apm_->Initialize());
548  // Initialize the |frame_queue| with empty frames.
549  int frame_delay = delay_ms / 10;
550  while (frame_delay < 0) {
551    AudioFrame* frame = new AudioFrame();
552    frame->CopyFrom(tmp_frame);
553    frame_queue.push(frame);
554    frame_delay++;
555    causal = false;
556  }
557  while (frame_delay > 0) {
558    AudioFrame* frame = new AudioFrame();
559    frame->CopyFrom(tmp_frame);
560    frame_queue.push(frame);
561    frame_delay--;
562  }
563  // Run for 4.5 seconds, skipping statistics from the first 2.5 seconds.  We
564  // need enough frames with audio to have reliable estimates, but as few as
565  // possible to keep processing time down.  4.5 seconds seemed to be a good
566  // compromise for this recording.
567  for (int frame_count = 0; frame_count < 450; ++frame_count) {
568    AudioFrame* frame = new AudioFrame();
569    frame->CopyFrom(tmp_frame);
570    // Use the near end recording, since that has more speech in it.
571    ASSERT_TRUE(ReadFrame(near_file_, frame));
572    frame_queue.push(frame);
573    AudioFrame* reverse_frame = frame;
574    AudioFrame* process_frame = frame_queue.front();
575    if (!causal) {
576      reverse_frame = frame_queue.front();
577      // When we call ProcessStream() the frame is modified, so we can't use the
578      // pointer directly when things are non-causal. Use an intermediate frame
579      // and copy the data.
580      process_frame = &tmp_frame;
581      process_frame->CopyFrom(*frame);
582    }
583    EXPECT_EQ(apm_->kNoError, apm_->AnalyzeReverseStream(reverse_frame));
584    EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(system_delay_ms));
585    EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(process_frame));
586    frame = frame_queue.front();
587    frame_queue.pop();
588    delete frame;
589
590    if (frame_count == 250) {
591      int median;
592      int std;
593      // Discard the first delay metrics to avoid convergence effects.
594      EXPECT_EQ(apm_->kNoError,
595                apm_->echo_cancellation()->GetDelayMetrics(&median, &std));
596    }
597  }
598
599  rewind(near_file_);
600  while (!frame_queue.empty()) {
601    AudioFrame* frame = frame_queue.front();
602    frame_queue.pop();
603    delete frame;
604  }
605  // Calculate expected delay estimate and acceptable regions. Further,
606  // limit them w.r.t. AEC delay estimation support.
607  const int samples_per_ms = std::min(16, frame_->samples_per_channel_ / 10);
608  int expected_median = std::min(std::max(delay_ms - system_delay_ms,
609                                          delay_min), delay_max);
610  int expected_median_high = std::min(std::max(
611      expected_median + 96 / samples_per_ms, delay_min), delay_max);
612  int expected_median_low = std::min(std::max(
613      expected_median - 96 / samples_per_ms, delay_min), delay_max);
614  // Verify delay metrics.
615  int median;
616  int std;
617  EXPECT_EQ(apm_->kNoError,
618            apm_->echo_cancellation()->GetDelayMetrics(&median, &std));
619  EXPECT_GE(expected_median_high, median);
620  EXPECT_LE(expected_median_low, median);
621}
622
623void ApmTest::StreamParametersTest(Format format) {
624  // No errors when the components are disabled.
625  EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
626
627  // -- Missing AGC level --
628  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
629  EXPECT_EQ(apm_->kStreamParameterNotSetError,
630            ProcessStreamChooser(format));
631
632  // Resets after successful ProcessStream().
633  EXPECT_EQ(apm_->kNoError,
634            apm_->gain_control()->set_stream_analog_level(127));
635  EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
636  EXPECT_EQ(apm_->kStreamParameterNotSetError,
637            ProcessStreamChooser(format));
638
639  // Other stream parameters set correctly.
640  EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
641  EXPECT_EQ(apm_->kNoError,
642            apm_->echo_cancellation()->enable_drift_compensation(true));
643  EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
644  apm_->echo_cancellation()->set_stream_drift_samples(0);
645  EXPECT_EQ(apm_->kStreamParameterNotSetError,
646            ProcessStreamChooser(format));
647  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(false));
648  EXPECT_EQ(apm_->kNoError,
649            apm_->echo_cancellation()->enable_drift_compensation(false));
650
651  // -- Missing delay --
652  EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
653  EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
654  EXPECT_EQ(apm_->kStreamParameterNotSetError,
655            ProcessStreamChooser(format));
656
657  // Resets after successful ProcessStream().
658  EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
659  EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
660  EXPECT_EQ(apm_->kStreamParameterNotSetError,
661            ProcessStreamChooser(format));
662
663  // Other stream parameters set correctly.
664  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
665  EXPECT_EQ(apm_->kNoError,
666            apm_->echo_cancellation()->enable_drift_compensation(true));
667  apm_->echo_cancellation()->set_stream_drift_samples(0);
668  EXPECT_EQ(apm_->kNoError,
669            apm_->gain_control()->set_stream_analog_level(127));
670  EXPECT_EQ(apm_->kStreamParameterNotSetError,
671            ProcessStreamChooser(format));
672  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(false));
673
674  // -- Missing drift --
675  EXPECT_EQ(apm_->kStreamParameterNotSetError,
676            ProcessStreamChooser(format));
677
678  // Resets after successful ProcessStream().
679  EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
680  apm_->echo_cancellation()->set_stream_drift_samples(0);
681  EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
682  EXPECT_EQ(apm_->kStreamParameterNotSetError,
683            ProcessStreamChooser(format));
684
685  // Other stream parameters set correctly.
686  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
687  EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
688  EXPECT_EQ(apm_->kNoError,
689            apm_->gain_control()->set_stream_analog_level(127));
690  EXPECT_EQ(apm_->kStreamParameterNotSetError,
691            ProcessStreamChooser(format));
692
693  // -- No stream parameters --
694  EXPECT_EQ(apm_->kNoError,
695            AnalyzeReverseStreamChooser(format));
696  EXPECT_EQ(apm_->kStreamParameterNotSetError,
697            ProcessStreamChooser(format));
698
699  // -- All there --
700  EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
701  apm_->echo_cancellation()->set_stream_drift_samples(0);
702  EXPECT_EQ(apm_->kNoError,
703            apm_->gain_control()->set_stream_analog_level(127));
704  EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
705}
706
707TEST_F(ApmTest, StreamParametersInt) {
708  StreamParametersTest(kIntFormat);
709}
710
711TEST_F(ApmTest, StreamParametersFloat) {
712  StreamParametersTest(kFloatFormat);
713}
714
715TEST_F(ApmTest, DefaultDelayOffsetIsZero) {
716  EXPECT_EQ(0, apm_->delay_offset_ms());
717  EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(50));
718  EXPECT_EQ(50, apm_->stream_delay_ms());
719}
720
721TEST_F(ApmTest, DelayOffsetWithLimitsIsSetProperly) {
722  // High limit of 500 ms.
723  apm_->set_delay_offset_ms(100);
724  EXPECT_EQ(100, apm_->delay_offset_ms());
725  EXPECT_EQ(apm_->kBadStreamParameterWarning, apm_->set_stream_delay_ms(450));
726  EXPECT_EQ(500, apm_->stream_delay_ms());
727  EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
728  EXPECT_EQ(200, apm_->stream_delay_ms());
729
730  // Low limit of 0 ms.
731  apm_->set_delay_offset_ms(-50);
732  EXPECT_EQ(-50, apm_->delay_offset_ms());
733  EXPECT_EQ(apm_->kBadStreamParameterWarning, apm_->set_stream_delay_ms(20));
734  EXPECT_EQ(0, apm_->stream_delay_ms());
735  EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
736  EXPECT_EQ(50, apm_->stream_delay_ms());
737}
738
739void ApmTest::TestChangingChannels(int num_channels,
740                                   AudioProcessing::Error expected_return) {
741  frame_->num_channels_ = num_channels;
742  EXPECT_EQ(expected_return, apm_->ProcessStream(frame_));
743  EXPECT_EQ(expected_return, apm_->AnalyzeReverseStream(frame_));
744}
745
746TEST_F(ApmTest, Channels) {
747  // Testing number of invalid channels.
748  TestChangingChannels(0, apm_->kBadNumberChannelsError);
749  TestChangingChannels(3, apm_->kBadNumberChannelsError);
750  // Testing number of valid channels.
751  for (int i = 1; i < 3; i++) {
752    TestChangingChannels(i, kNoErr);
753    EXPECT_EQ(i, apm_->num_input_channels());
754    // We always force the number of reverse channels used for processing to 1.
755    EXPECT_EQ(1, apm_->num_reverse_channels());
756  }
757}
758
759TEST_F(ApmTest, SampleRatesInt) {
760  // Testing invalid sample rates
761  SetContainerFormat(10000, 2, frame_, &float_cb_);
762  EXPECT_EQ(apm_->kBadSampleRateError, ProcessStreamChooser(kIntFormat));
763  // Testing valid sample rates
764  int fs[] = {8000, 16000, 32000};
765  for (size_t i = 0; i < sizeof(fs) / sizeof(*fs); i++) {
766    SetContainerFormat(fs[i], 2, frame_, &float_cb_);
767    EXPECT_NOERR(ProcessStreamChooser(kIntFormat));
768    EXPECT_EQ(fs[i], apm_->input_sample_rate_hz());
769  }
770}
771
772TEST_F(ApmTest, EchoCancellation) {
773  EXPECT_EQ(apm_->kNoError,
774            apm_->echo_cancellation()->enable_drift_compensation(true));
775  EXPECT_TRUE(apm_->echo_cancellation()->is_drift_compensation_enabled());
776  EXPECT_EQ(apm_->kNoError,
777            apm_->echo_cancellation()->enable_drift_compensation(false));
778  EXPECT_FALSE(apm_->echo_cancellation()->is_drift_compensation_enabled());
779
780  EchoCancellation::SuppressionLevel level[] = {
781    EchoCancellation::kLowSuppression,
782    EchoCancellation::kModerateSuppression,
783    EchoCancellation::kHighSuppression,
784  };
785  for (size_t i = 0; i < sizeof(level)/sizeof(*level); i++) {
786    EXPECT_EQ(apm_->kNoError,
787        apm_->echo_cancellation()->set_suppression_level(level[i]));
788    EXPECT_EQ(level[i],
789        apm_->echo_cancellation()->suppression_level());
790  }
791
792  EchoCancellation::Metrics metrics;
793  EXPECT_EQ(apm_->kNotEnabledError,
794            apm_->echo_cancellation()->GetMetrics(&metrics));
795
796  EXPECT_EQ(apm_->kNoError,
797            apm_->echo_cancellation()->enable_metrics(true));
798  EXPECT_TRUE(apm_->echo_cancellation()->are_metrics_enabled());
799  EXPECT_EQ(apm_->kNoError,
800            apm_->echo_cancellation()->enable_metrics(false));
801  EXPECT_FALSE(apm_->echo_cancellation()->are_metrics_enabled());
802
803  int median = 0;
804  int std = 0;
805  EXPECT_EQ(apm_->kNotEnabledError,
806            apm_->echo_cancellation()->GetDelayMetrics(&median, &std));
807
808  EXPECT_EQ(apm_->kNoError,
809            apm_->echo_cancellation()->enable_delay_logging(true));
810  EXPECT_TRUE(apm_->echo_cancellation()->is_delay_logging_enabled());
811  EXPECT_EQ(apm_->kNoError,
812            apm_->echo_cancellation()->enable_delay_logging(false));
813  EXPECT_FALSE(apm_->echo_cancellation()->is_delay_logging_enabled());
814
815  EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
816  EXPECT_TRUE(apm_->echo_cancellation()->is_enabled());
817  EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false));
818  EXPECT_FALSE(apm_->echo_cancellation()->is_enabled());
819
820  EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
821  EXPECT_TRUE(apm_->echo_cancellation()->is_enabled());
822  EXPECT_TRUE(apm_->echo_cancellation()->aec_core() != NULL);
823  EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false));
824  EXPECT_FALSE(apm_->echo_cancellation()->is_enabled());
825  EXPECT_FALSE(apm_->echo_cancellation()->aec_core() != NULL);
826}
827
828TEST_F(ApmTest, DISABLED_EchoCancellationReportsCorrectDelays) {
829  // Enable AEC only.
830  EXPECT_EQ(apm_->kNoError,
831            apm_->echo_cancellation()->enable_drift_compensation(false));
832  EXPECT_EQ(apm_->kNoError,
833            apm_->echo_cancellation()->enable_metrics(false));
834  EXPECT_EQ(apm_->kNoError,
835            apm_->echo_cancellation()->enable_delay_logging(true));
836  EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
837  Config config;
838  config.Set<ReportedDelay>(new ReportedDelay(true));
839  apm_->SetExtraOptions(config);
840
841  // Internally in the AEC the amount of lookahead the delay estimation can
842  // handle is 15 blocks and the maximum delay is set to 60 blocks.
843  const int kLookaheadBlocks = 15;
844  const int kMaxDelayBlocks = 60;
845  // The AEC has a startup time before it actually starts to process. This
846  // procedure can flush the internal far-end buffer, which of course affects
847  // the delay estimation. Therefore, we set a system_delay high enough to
848  // avoid that. The smallest system_delay you can report without flushing the
849  // buffer is 66 ms in 8 kHz.
850  //
851  // It is known that for 16 kHz (and 32 kHz) sampling frequency there is an
852  // additional stuffing of 8 ms on the fly, but it seems to have no impact on
853  // delay estimation. This should be noted though. In case of test failure,
854  // this could be the cause.
855  const int kSystemDelayMs = 66;
856  // Test a couple of corner cases and verify that the estimated delay is
857  // within a valid region (set to +-1.5 blocks). Note that these cases are
858  // sampling frequency dependent.
859  for (size_t i = 0; i < kProcessSampleRatesSize; i++) {
860    Init(kProcessSampleRates[i],
861         kProcessSampleRates[i],
862         kProcessSampleRates[i],
863         2,
864         2,
865         2,
866         false);
867    // Sampling frequency dependent variables.
868    const int num_ms_per_block = std::max(4,
869                                          640 / frame_->samples_per_channel_);
870    const int delay_min_ms = -kLookaheadBlocks * num_ms_per_block;
871    const int delay_max_ms = (kMaxDelayBlocks - 1) * num_ms_per_block;
872
873    // 1) Verify correct delay estimate at lookahead boundary.
874    int delay_ms = TruncateToMultipleOf10(kSystemDelayMs + delay_min_ms);
875    ProcessDelayVerificationTest(delay_ms, kSystemDelayMs, delay_min_ms,
876                                 delay_max_ms);
877    // 2) A delay less than maximum lookahead should give an delay estimate at
878    //    the boundary (= -kLookaheadBlocks * num_ms_per_block).
879    delay_ms -= 20;
880    ProcessDelayVerificationTest(delay_ms, kSystemDelayMs, delay_min_ms,
881                                 delay_max_ms);
882    // 3) Three values around zero delay. Note that we need to compensate for
883    //    the fake system_delay.
884    delay_ms = TruncateToMultipleOf10(kSystemDelayMs - 10);
885    ProcessDelayVerificationTest(delay_ms, kSystemDelayMs, delay_min_ms,
886                                 delay_max_ms);
887    delay_ms = TruncateToMultipleOf10(kSystemDelayMs);
888    ProcessDelayVerificationTest(delay_ms, kSystemDelayMs, delay_min_ms,
889                                 delay_max_ms);
890    delay_ms = TruncateToMultipleOf10(kSystemDelayMs + 10);
891    ProcessDelayVerificationTest(delay_ms, kSystemDelayMs, delay_min_ms,
892                                 delay_max_ms);
893    // 4) Verify correct delay estimate at maximum delay boundary.
894    delay_ms = TruncateToMultipleOf10(kSystemDelayMs + delay_max_ms);
895    ProcessDelayVerificationTest(delay_ms, kSystemDelayMs, delay_min_ms,
896                                 delay_max_ms);
897    // 5) A delay above the maximum delay should give an estimate at the
898    //    boundary (= (kMaxDelayBlocks - 1) * num_ms_per_block).
899    delay_ms += 20;
900    ProcessDelayVerificationTest(delay_ms, kSystemDelayMs, delay_min_ms,
901                                 delay_max_ms);
902  }
903}
904
905TEST_F(ApmTest, EchoControlMobile) {
906  // AECM won't use super-wideband.
907  SetFrameSampleRate(frame_, 32000);
908  EXPECT_NOERR(apm_->ProcessStream(frame_));
909  EXPECT_EQ(apm_->kBadSampleRateError,
910            apm_->echo_control_mobile()->Enable(true));
911  SetFrameSampleRate(frame_, 16000);
912  EXPECT_NOERR(apm_->ProcessStream(frame_));
913  EXPECT_EQ(apm_->kNoError,
914            apm_->echo_control_mobile()->Enable(true));
915  SetFrameSampleRate(frame_, 32000);
916  EXPECT_EQ(apm_->kUnsupportedComponentError, apm_->ProcessStream(frame_));
917
918  // Turn AECM on (and AEC off)
919  Init(16000, 16000, 16000, 2, 2, 2, false);
920  EXPECT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(true));
921  EXPECT_TRUE(apm_->echo_control_mobile()->is_enabled());
922
923  // Toggle routing modes
924  EchoControlMobile::RoutingMode mode[] = {
925      EchoControlMobile::kQuietEarpieceOrHeadset,
926      EchoControlMobile::kEarpiece,
927      EchoControlMobile::kLoudEarpiece,
928      EchoControlMobile::kSpeakerphone,
929      EchoControlMobile::kLoudSpeakerphone,
930  };
931  for (size_t i = 0; i < sizeof(mode)/sizeof(*mode); i++) {
932    EXPECT_EQ(apm_->kNoError,
933        apm_->echo_control_mobile()->set_routing_mode(mode[i]));
934    EXPECT_EQ(mode[i],
935        apm_->echo_control_mobile()->routing_mode());
936  }
937  // Turn comfort noise off/on
938  EXPECT_EQ(apm_->kNoError,
939      apm_->echo_control_mobile()->enable_comfort_noise(false));
940  EXPECT_FALSE(apm_->echo_control_mobile()->is_comfort_noise_enabled());
941  EXPECT_EQ(apm_->kNoError,
942      apm_->echo_control_mobile()->enable_comfort_noise(true));
943  EXPECT_TRUE(apm_->echo_control_mobile()->is_comfort_noise_enabled());
944  // Set and get echo path
945  const size_t echo_path_size =
946      apm_->echo_control_mobile()->echo_path_size_bytes();
947  scoped_ptr<char[]> echo_path_in(new char[echo_path_size]);
948  scoped_ptr<char[]> echo_path_out(new char[echo_path_size]);
949  EXPECT_EQ(apm_->kNullPointerError,
950            apm_->echo_control_mobile()->SetEchoPath(NULL, echo_path_size));
951  EXPECT_EQ(apm_->kNullPointerError,
952            apm_->echo_control_mobile()->GetEchoPath(NULL, echo_path_size));
953  EXPECT_EQ(apm_->kBadParameterError,
954            apm_->echo_control_mobile()->GetEchoPath(echo_path_out.get(), 1));
955  EXPECT_EQ(apm_->kNoError,
956            apm_->echo_control_mobile()->GetEchoPath(echo_path_out.get(),
957                                                     echo_path_size));
958  for (size_t i = 0; i < echo_path_size; i++) {
959    echo_path_in[i] = echo_path_out[i] + 1;
960  }
961  EXPECT_EQ(apm_->kBadParameterError,
962            apm_->echo_control_mobile()->SetEchoPath(echo_path_in.get(), 1));
963  EXPECT_EQ(apm_->kNoError,
964            apm_->echo_control_mobile()->SetEchoPath(echo_path_in.get(),
965                                                     echo_path_size));
966  EXPECT_EQ(apm_->kNoError,
967            apm_->echo_control_mobile()->GetEchoPath(echo_path_out.get(),
968                                                     echo_path_size));
969  for (size_t i = 0; i < echo_path_size; i++) {
970    EXPECT_EQ(echo_path_in[i], echo_path_out[i]);
971  }
972
973  // Process a few frames with NS in the default disabled state. This exercises
974  // a different codepath than with it enabled.
975  EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0));
976  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
977  EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0));
978  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
979
980  // Turn AECM off
981  EXPECT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(false));
982  EXPECT_FALSE(apm_->echo_control_mobile()->is_enabled());
983}
984
985TEST_F(ApmTest, GainControl) {
986  // Testing gain modes
987  EXPECT_EQ(apm_->kNoError,
988      apm_->gain_control()->set_mode(
989      apm_->gain_control()->mode()));
990
991  GainControl::Mode mode[] = {
992    GainControl::kAdaptiveAnalog,
993    GainControl::kAdaptiveDigital,
994    GainControl::kFixedDigital
995  };
996  for (size_t i = 0; i < sizeof(mode)/sizeof(*mode); i++) {
997    EXPECT_EQ(apm_->kNoError,
998        apm_->gain_control()->set_mode(mode[i]));
999    EXPECT_EQ(mode[i], apm_->gain_control()->mode());
1000  }
1001  // Testing invalid target levels
1002  EXPECT_EQ(apm_->kBadParameterError,
1003      apm_->gain_control()->set_target_level_dbfs(-3));
1004  EXPECT_EQ(apm_->kBadParameterError,
1005      apm_->gain_control()->set_target_level_dbfs(-40));
1006  // Testing valid target levels
1007  EXPECT_EQ(apm_->kNoError,
1008      apm_->gain_control()->set_target_level_dbfs(
1009      apm_->gain_control()->target_level_dbfs()));
1010
1011  int level_dbfs[] = {0, 6, 31};
1012  for (size_t i = 0; i < sizeof(level_dbfs)/sizeof(*level_dbfs); i++) {
1013    EXPECT_EQ(apm_->kNoError,
1014        apm_->gain_control()->set_target_level_dbfs(level_dbfs[i]));
1015    EXPECT_EQ(level_dbfs[i], apm_->gain_control()->target_level_dbfs());
1016  }
1017
1018  // Testing invalid compression gains
1019  EXPECT_EQ(apm_->kBadParameterError,
1020      apm_->gain_control()->set_compression_gain_db(-1));
1021  EXPECT_EQ(apm_->kBadParameterError,
1022      apm_->gain_control()->set_compression_gain_db(100));
1023
1024  // Testing valid compression gains
1025  EXPECT_EQ(apm_->kNoError,
1026      apm_->gain_control()->set_compression_gain_db(
1027      apm_->gain_control()->compression_gain_db()));
1028
1029  int gain_db[] = {0, 10, 90};
1030  for (size_t i = 0; i < sizeof(gain_db)/sizeof(*gain_db); i++) {
1031    EXPECT_EQ(apm_->kNoError,
1032        apm_->gain_control()->set_compression_gain_db(gain_db[i]));
1033    EXPECT_EQ(gain_db[i], apm_->gain_control()->compression_gain_db());
1034  }
1035
1036  // Testing limiter off/on
1037  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->enable_limiter(false));
1038  EXPECT_FALSE(apm_->gain_control()->is_limiter_enabled());
1039  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->enable_limiter(true));
1040  EXPECT_TRUE(apm_->gain_control()->is_limiter_enabled());
1041
1042  // Testing invalid level limits
1043  EXPECT_EQ(apm_->kBadParameterError,
1044      apm_->gain_control()->set_analog_level_limits(-1, 512));
1045  EXPECT_EQ(apm_->kBadParameterError,
1046      apm_->gain_control()->set_analog_level_limits(100000, 512));
1047  EXPECT_EQ(apm_->kBadParameterError,
1048      apm_->gain_control()->set_analog_level_limits(512, -1));
1049  EXPECT_EQ(apm_->kBadParameterError,
1050      apm_->gain_control()->set_analog_level_limits(512, 100000));
1051  EXPECT_EQ(apm_->kBadParameterError,
1052      apm_->gain_control()->set_analog_level_limits(512, 255));
1053
1054  // Testing valid level limits
1055  EXPECT_EQ(apm_->kNoError,
1056      apm_->gain_control()->set_analog_level_limits(
1057      apm_->gain_control()->analog_level_minimum(),
1058      apm_->gain_control()->analog_level_maximum()));
1059
1060  int min_level[] = {0, 255, 1024};
1061  for (size_t i = 0; i < sizeof(min_level)/sizeof(*min_level); i++) {
1062    EXPECT_EQ(apm_->kNoError,
1063        apm_->gain_control()->set_analog_level_limits(min_level[i], 1024));
1064    EXPECT_EQ(min_level[i], apm_->gain_control()->analog_level_minimum());
1065  }
1066
1067  int max_level[] = {0, 1024, 65535};
1068  for (size_t i = 0; i < sizeof(min_level)/sizeof(*min_level); i++) {
1069    EXPECT_EQ(apm_->kNoError,
1070        apm_->gain_control()->set_analog_level_limits(0, max_level[i]));
1071    EXPECT_EQ(max_level[i], apm_->gain_control()->analog_level_maximum());
1072  }
1073
1074  // TODO(ajm): stream_is_saturated() and stream_analog_level()
1075
1076  // Turn AGC off
1077  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(false));
1078  EXPECT_FALSE(apm_->gain_control()->is_enabled());
1079}
1080
1081void ApmTest::RunQuantizedVolumeDoesNotGetStuckTest(int sample_rate) {
1082  Init(sample_rate, sample_rate, sample_rate, 2, 2, 2, false);
1083  EXPECT_EQ(apm_->kNoError,
1084            apm_->gain_control()->set_mode(GainControl::kAdaptiveAnalog));
1085  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
1086
1087  int out_analog_level = 0;
1088  for (int i = 0; i < 2000; ++i) {
1089    ReadFrameWithRewind(near_file_, frame_);
1090    // Ensure the audio is at a low level, so the AGC will try to increase it.
1091    ScaleFrame(frame_, 0.25);
1092
1093    // Always pass in the same volume.
1094    EXPECT_EQ(apm_->kNoError,
1095        apm_->gain_control()->set_stream_analog_level(100));
1096    EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1097    out_analog_level = apm_->gain_control()->stream_analog_level();
1098  }
1099
1100  // Ensure the AGC is still able to reach the maximum.
1101  EXPECT_EQ(255, out_analog_level);
1102}
1103
1104// Verifies that despite volume slider quantization, the AGC can continue to
1105// increase its volume.
1106TEST_F(ApmTest, QuantizedVolumeDoesNotGetStuck) {
1107  for (size_t i = 0; i < kSampleRatesSize; ++i) {
1108    RunQuantizedVolumeDoesNotGetStuckTest(kSampleRates[i]);
1109  }
1110}
1111
1112void ApmTest::RunManualVolumeChangeIsPossibleTest(int sample_rate) {
1113  Init(sample_rate, sample_rate, sample_rate, 2, 2, 2, false);
1114  EXPECT_EQ(apm_->kNoError,
1115            apm_->gain_control()->set_mode(GainControl::kAdaptiveAnalog));
1116  EXPECT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
1117
1118  int out_analog_level = 100;
1119  for (int i = 0; i < 1000; ++i) {
1120    ReadFrameWithRewind(near_file_, frame_);
1121    // Ensure the audio is at a low level, so the AGC will try to increase it.
1122    ScaleFrame(frame_, 0.25);
1123
1124    EXPECT_EQ(apm_->kNoError,
1125        apm_->gain_control()->set_stream_analog_level(out_analog_level));
1126    EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1127    out_analog_level = apm_->gain_control()->stream_analog_level();
1128  }
1129
1130  // Ensure the volume was raised.
1131  EXPECT_GT(out_analog_level, 100);
1132  int highest_level_reached = out_analog_level;
1133  // Simulate a user manual volume change.
1134  out_analog_level = 100;
1135
1136  for (int i = 0; i < 300; ++i) {
1137    ReadFrameWithRewind(near_file_, frame_);
1138    ScaleFrame(frame_, 0.25);
1139
1140    EXPECT_EQ(apm_->kNoError,
1141        apm_->gain_control()->set_stream_analog_level(out_analog_level));
1142    EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1143    out_analog_level = apm_->gain_control()->stream_analog_level();
1144    // Check that AGC respected the manually adjusted volume.
1145    EXPECT_LT(out_analog_level, highest_level_reached);
1146  }
1147  // Check that the volume was still raised.
1148  EXPECT_GT(out_analog_level, 100);
1149}
1150
1151TEST_F(ApmTest, ManualVolumeChangeIsPossible) {
1152  for (size_t i = 0; i < kSampleRatesSize; ++i) {
1153    RunManualVolumeChangeIsPossibleTest(kSampleRates[i]);
1154  }
1155}
1156
1157TEST_F(ApmTest, NoiseSuppression) {
1158  // Test valid suppression levels.
1159  NoiseSuppression::Level level[] = {
1160    NoiseSuppression::kLow,
1161    NoiseSuppression::kModerate,
1162    NoiseSuppression::kHigh,
1163    NoiseSuppression::kVeryHigh
1164  };
1165  for (size_t i = 0; i < sizeof(level)/sizeof(*level); i++) {
1166    EXPECT_EQ(apm_->kNoError,
1167        apm_->noise_suppression()->set_level(level[i]));
1168    EXPECT_EQ(level[i], apm_->noise_suppression()->level());
1169  }
1170
1171  // Turn NS on/off
1172  EXPECT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(true));
1173  EXPECT_TRUE(apm_->noise_suppression()->is_enabled());
1174  EXPECT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(false));
1175  EXPECT_FALSE(apm_->noise_suppression()->is_enabled());
1176}
1177
1178TEST_F(ApmTest, HighPassFilter) {
1179  // Turn HP filter on/off
1180  EXPECT_EQ(apm_->kNoError, apm_->high_pass_filter()->Enable(true));
1181  EXPECT_TRUE(apm_->high_pass_filter()->is_enabled());
1182  EXPECT_EQ(apm_->kNoError, apm_->high_pass_filter()->Enable(false));
1183  EXPECT_FALSE(apm_->high_pass_filter()->is_enabled());
1184}
1185
1186TEST_F(ApmTest, LevelEstimator) {
1187  // Turn level estimator on/off
1188  EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(false));
1189  EXPECT_FALSE(apm_->level_estimator()->is_enabled());
1190
1191  EXPECT_EQ(apm_->kNotEnabledError, apm_->level_estimator()->RMS());
1192
1193  EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true));
1194  EXPECT_TRUE(apm_->level_estimator()->is_enabled());
1195
1196  // Run this test in wideband; in super-wb, the splitting filter distorts the
1197  // audio enough to cause deviation from the expectation for small values.
1198  frame_->samples_per_channel_ = 160;
1199  frame_->num_channels_ = 2;
1200  frame_->sample_rate_hz_ = 16000;
1201
1202  // Min value if no frames have been processed.
1203  EXPECT_EQ(127, apm_->level_estimator()->RMS());
1204
1205  // Min value on zero frames.
1206  SetFrameTo(frame_, 0);
1207  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1208  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1209  EXPECT_EQ(127, apm_->level_estimator()->RMS());
1210
1211  // Try a few RMS values.
1212  // (These also test that the value resets after retrieving it.)
1213  SetFrameTo(frame_, 32767);
1214  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1215  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1216  EXPECT_EQ(0, apm_->level_estimator()->RMS());
1217
1218  SetFrameTo(frame_, 30000);
1219  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1220  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1221  EXPECT_EQ(1, apm_->level_estimator()->RMS());
1222
1223  SetFrameTo(frame_, 10000);
1224  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1225  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1226  EXPECT_EQ(10, apm_->level_estimator()->RMS());
1227
1228  SetFrameTo(frame_, 10);
1229  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1230  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1231  EXPECT_EQ(70, apm_->level_estimator()->RMS());
1232
1233  // Verify reset after enable/disable.
1234  SetFrameTo(frame_, 32767);
1235  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1236  EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(false));
1237  EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true));
1238  SetFrameTo(frame_, 1);
1239  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1240  EXPECT_EQ(90, apm_->level_estimator()->RMS());
1241
1242  // Verify reset after initialize.
1243  SetFrameTo(frame_, 32767);
1244  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1245  EXPECT_EQ(apm_->kNoError, apm_->Initialize());
1246  SetFrameTo(frame_, 1);
1247  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1248  EXPECT_EQ(90, apm_->level_estimator()->RMS());
1249}
1250
1251TEST_F(ApmTest, VoiceDetection) {
1252  // Test external VAD
1253  EXPECT_EQ(apm_->kNoError,
1254            apm_->voice_detection()->set_stream_has_voice(true));
1255  EXPECT_TRUE(apm_->voice_detection()->stream_has_voice());
1256  EXPECT_EQ(apm_->kNoError,
1257            apm_->voice_detection()->set_stream_has_voice(false));
1258  EXPECT_FALSE(apm_->voice_detection()->stream_has_voice());
1259
1260  // Test valid likelihoods
1261  VoiceDetection::Likelihood likelihood[] = {
1262      VoiceDetection::kVeryLowLikelihood,
1263      VoiceDetection::kLowLikelihood,
1264      VoiceDetection::kModerateLikelihood,
1265      VoiceDetection::kHighLikelihood
1266  };
1267  for (size_t i = 0; i < sizeof(likelihood)/sizeof(*likelihood); i++) {
1268    EXPECT_EQ(apm_->kNoError,
1269              apm_->voice_detection()->set_likelihood(likelihood[i]));
1270    EXPECT_EQ(likelihood[i], apm_->voice_detection()->likelihood());
1271  }
1272
1273  /* TODO(bjornv): Enable once VAD supports other frame lengths than 10 ms
1274  // Test invalid frame sizes
1275  EXPECT_EQ(apm_->kBadParameterError,
1276      apm_->voice_detection()->set_frame_size_ms(12));
1277
1278  // Test valid frame sizes
1279  for (int i = 10; i <= 30; i += 10) {
1280    EXPECT_EQ(apm_->kNoError,
1281        apm_->voice_detection()->set_frame_size_ms(i));
1282    EXPECT_EQ(i, apm_->voice_detection()->frame_size_ms());
1283  }
1284  */
1285
1286  // Turn VAD on/off
1287  EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true));
1288  EXPECT_TRUE(apm_->voice_detection()->is_enabled());
1289  EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(false));
1290  EXPECT_FALSE(apm_->voice_detection()->is_enabled());
1291
1292  // Test that AudioFrame activity is maintained when VAD is disabled.
1293  EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(false));
1294  AudioFrame::VADActivity activity[] = {
1295      AudioFrame::kVadActive,
1296      AudioFrame::kVadPassive,
1297      AudioFrame::kVadUnknown
1298  };
1299  for (size_t i = 0; i < sizeof(activity)/sizeof(*activity); i++) {
1300    frame_->vad_activity_ = activity[i];
1301    EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1302    EXPECT_EQ(activity[i], frame_->vad_activity_);
1303  }
1304
1305  // Test that AudioFrame activity is set when VAD is enabled.
1306  EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true));
1307  frame_->vad_activity_ = AudioFrame::kVadUnknown;
1308  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1309  EXPECT_NE(AudioFrame::kVadUnknown, frame_->vad_activity_);
1310
1311  // TODO(bjornv): Add tests for streamed voice; stream_has_voice()
1312}
1313
1314TEST_F(ApmTest, AllProcessingDisabledByDefault) {
1315  EXPECT_FALSE(apm_->echo_cancellation()->is_enabled());
1316  EXPECT_FALSE(apm_->echo_control_mobile()->is_enabled());
1317  EXPECT_FALSE(apm_->gain_control()->is_enabled());
1318  EXPECT_FALSE(apm_->high_pass_filter()->is_enabled());
1319  EXPECT_FALSE(apm_->level_estimator()->is_enabled());
1320  EXPECT_FALSE(apm_->noise_suppression()->is_enabled());
1321  EXPECT_FALSE(apm_->voice_detection()->is_enabled());
1322}
1323
1324TEST_F(ApmTest, NoProcessingWhenAllComponentsDisabled) {
1325  for (size_t i = 0; i < kSampleRatesSize; i++) {
1326    Init(kSampleRates[i], kSampleRates[i], kSampleRates[i], 2, 2, 2, false);
1327    SetFrameTo(frame_, 1000, 2000);
1328    AudioFrame frame_copy;
1329    frame_copy.CopyFrom(*frame_);
1330    for (int j = 0; j < 1000; j++) {
1331      EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1332      EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy));
1333    }
1334  }
1335}
1336
1337TEST_F(ApmTest, IdenticalInputChannelsResultInIdenticalOutputChannels) {
1338  EnableAllComponents();
1339
1340  for (size_t i = 0; i < kProcessSampleRatesSize; i++) {
1341    Init(kProcessSampleRates[i],
1342         kProcessSampleRates[i],
1343         kProcessSampleRates[i],
1344         2,
1345         2,
1346         2,
1347         false);
1348    int analog_level = 127;
1349    ASSERT_EQ(0, feof(far_file_));
1350    ASSERT_EQ(0, feof(near_file_));
1351    while (ReadFrame(far_file_, revframe_) && ReadFrame(near_file_, frame_)) {
1352      CopyLeftToRightChannel(revframe_->data_, revframe_->samples_per_channel_);
1353
1354      ASSERT_EQ(kNoErr, apm_->AnalyzeReverseStream(revframe_));
1355
1356      CopyLeftToRightChannel(frame_->data_, frame_->samples_per_channel_);
1357      frame_->vad_activity_ = AudioFrame::kVadUnknown;
1358
1359      ASSERT_EQ(kNoErr, apm_->set_stream_delay_ms(0));
1360      apm_->echo_cancellation()->set_stream_drift_samples(0);
1361      ASSERT_EQ(kNoErr,
1362          apm_->gain_control()->set_stream_analog_level(analog_level));
1363      ASSERT_EQ(kNoErr, apm_->ProcessStream(frame_));
1364      analog_level = apm_->gain_control()->stream_analog_level();
1365
1366      VerifyChannelsAreEqual(frame_->data_, frame_->samples_per_channel_);
1367    }
1368    rewind(far_file_);
1369    rewind(near_file_);
1370  }
1371}
1372
1373TEST_F(ApmTest, SplittingFilter) {
1374  // Verify the filter is not active through undistorted audio when:
1375  // 1. No components are enabled...
1376  SetFrameTo(frame_, 1000);
1377  AudioFrame frame_copy;
1378  frame_copy.CopyFrom(*frame_);
1379  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1380  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1381  EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy));
1382
1383  // 2. Only the level estimator is enabled...
1384  SetFrameTo(frame_, 1000);
1385  frame_copy.CopyFrom(*frame_);
1386  EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true));
1387  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1388  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1389  EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy));
1390  EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(false));
1391
1392  // 3. Only VAD is enabled...
1393  SetFrameTo(frame_, 1000);
1394  frame_copy.CopyFrom(*frame_);
1395  EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true));
1396  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1397  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1398  EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy));
1399  EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(false));
1400
1401  // 4. Both VAD and the level estimator are enabled...
1402  SetFrameTo(frame_, 1000);
1403  frame_copy.CopyFrom(*frame_);
1404  EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true));
1405  EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true));
1406  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1407  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1408  EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy));
1409  EXPECT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(false));
1410  EXPECT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(false));
1411
1412  // 5. Not using super-wb.
1413  frame_->samples_per_channel_ = 160;
1414  frame_->num_channels_ = 2;
1415  frame_->sample_rate_hz_ = 16000;
1416  // Enable AEC, which would require the filter in super-wb. We rely on the
1417  // first few frames of data being unaffected by the AEC.
1418  // TODO(andrew): This test, and the one below, rely rather tenuously on the
1419  // behavior of the AEC. Think of something more robust.
1420  EXPECT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
1421  // Make sure we have extended filter enabled. This makes sure nothing is
1422  // touched until we have a farend frame.
1423  Config config;
1424  config.Set<DelayCorrection>(new DelayCorrection(true));
1425  apm_->SetExtraOptions(config);
1426  SetFrameTo(frame_, 1000);
1427  frame_copy.CopyFrom(*frame_);
1428  EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0));
1429  apm_->echo_cancellation()->set_stream_drift_samples(0);
1430  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1431  EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0));
1432  apm_->echo_cancellation()->set_stream_drift_samples(0);
1433  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1434  EXPECT_TRUE(FrameDataAreEqual(*frame_, frame_copy));
1435
1436  // Check the test is valid. We should have distortion from the filter
1437  // when AEC is enabled (which won't affect the audio).
1438  frame_->samples_per_channel_ = 320;
1439  frame_->num_channels_ = 2;
1440  frame_->sample_rate_hz_ = 32000;
1441  SetFrameTo(frame_, 1000);
1442  frame_copy.CopyFrom(*frame_);
1443  EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0));
1444  apm_->echo_cancellation()->set_stream_drift_samples(0);
1445  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1446  EXPECT_FALSE(FrameDataAreEqual(*frame_, frame_copy));
1447}
1448
1449#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
1450void ApmTest::ProcessDebugDump(const std::string& in_filename,
1451                               const std::string& out_filename,
1452                               Format format) {
1453  FILE* in_file = fopen(in_filename.c_str(), "rb");
1454  ASSERT_TRUE(in_file != NULL);
1455  audioproc::Event event_msg;
1456  bool first_init = true;
1457
1458  while (ReadMessageFromFile(in_file, &event_msg)) {
1459    if (event_msg.type() == audioproc::Event::INIT) {
1460      const audioproc::Init msg = event_msg.init();
1461      int reverse_sample_rate = msg.sample_rate();
1462      if (msg.has_reverse_sample_rate()) {
1463        reverse_sample_rate = msg.reverse_sample_rate();
1464      }
1465      int output_sample_rate = msg.sample_rate();
1466      if (msg.has_output_sample_rate()) {
1467        output_sample_rate = msg.output_sample_rate();
1468      }
1469
1470      Init(msg.sample_rate(),
1471           output_sample_rate,
1472           reverse_sample_rate,
1473           msg.num_input_channels(),
1474           msg.num_output_channels(),
1475           msg.num_reverse_channels(),
1476           false);
1477      if (first_init) {
1478        // StartDebugRecording() writes an additional init message. Don't start
1479        // recording until after the first init to avoid the extra message.
1480        EXPECT_NOERR(apm_->StartDebugRecording(out_filename.c_str()));
1481        first_init = false;
1482      }
1483
1484    } else if (event_msg.type() == audioproc::Event::REVERSE_STREAM) {
1485      const audioproc::ReverseStream msg = event_msg.reverse_stream();
1486
1487      if (msg.channel_size() > 0) {
1488        ASSERT_EQ(revframe_->num_channels_, msg.channel_size());
1489        for (int i = 0; i < msg.channel_size(); ++i) {
1490           memcpy(revfloat_cb_->channel(i), msg.channel(i).data(),
1491                  msg.channel(i).size());
1492        }
1493      } else {
1494        memcpy(revframe_->data_, msg.data().data(), msg.data().size());
1495        if (format == kFloatFormat) {
1496          // We're using an int16 input file; convert to float.
1497          ConvertToFloat(*revframe_, revfloat_cb_.get());
1498        }
1499      }
1500      AnalyzeReverseStreamChooser(format);
1501
1502    } else if (event_msg.type() == audioproc::Event::STREAM) {
1503      const audioproc::Stream msg = event_msg.stream();
1504      // ProcessStream could have changed this for the output frame.
1505      frame_->num_channels_ = apm_->num_input_channels();
1506
1507      EXPECT_NOERR(apm_->gain_control()->set_stream_analog_level(msg.level()));
1508      EXPECT_NOERR(apm_->set_stream_delay_ms(msg.delay()));
1509      apm_->echo_cancellation()->set_stream_drift_samples(msg.drift());
1510      if (msg.has_keypress()) {
1511        apm_->set_stream_key_pressed(msg.keypress());
1512      } else {
1513        apm_->set_stream_key_pressed(true);
1514      }
1515
1516      if (msg.input_channel_size() > 0) {
1517        ASSERT_EQ(frame_->num_channels_, msg.input_channel_size());
1518        for (int i = 0; i < msg.input_channel_size(); ++i) {
1519           memcpy(float_cb_->channel(i), msg.input_channel(i).data(),
1520                  msg.input_channel(i).size());
1521        }
1522      } else {
1523        memcpy(frame_->data_, msg.input_data().data(), msg.input_data().size());
1524        if (format == kFloatFormat) {
1525          // We're using an int16 input file; convert to float.
1526          ConvertToFloat(*frame_, float_cb_.get());
1527        }
1528      }
1529      ProcessStreamChooser(format);
1530    }
1531  }
1532  EXPECT_NOERR(apm_->StopDebugRecording());
1533  fclose(in_file);
1534}
1535
1536void ApmTest::VerifyDebugDumpTest(Format format) {
1537  const std::string in_filename = test::ResourcePath("ref03", "aecdump");
1538  std::string format_string;
1539  switch (format) {
1540    case kIntFormat:
1541      format_string = "_int";
1542      break;
1543    case kFloatFormat:
1544      format_string = "_float";
1545      break;
1546  }
1547  const std::string ref_filename =
1548      test::OutputPath() + "ref" + format_string + ".aecdump";
1549  const std::string out_filename =
1550      test::OutputPath() + "out" + format_string + ".aecdump";
1551  EnableAllComponents();
1552  ProcessDebugDump(in_filename, ref_filename, format);
1553  ProcessDebugDump(ref_filename, out_filename, format);
1554
1555  FILE* ref_file = fopen(ref_filename.c_str(), "rb");
1556  FILE* out_file = fopen(out_filename.c_str(), "rb");
1557  ASSERT_TRUE(ref_file != NULL);
1558  ASSERT_TRUE(out_file != NULL);
1559  scoped_ptr<uint8_t[]> ref_bytes;
1560  scoped_ptr<uint8_t[]> out_bytes;
1561
1562  size_t ref_size = ReadMessageBytesFromFile(ref_file, &ref_bytes);
1563  size_t out_size = ReadMessageBytesFromFile(out_file, &out_bytes);
1564  size_t bytes_read = 0;
1565  while (ref_size > 0 && out_size > 0) {
1566    bytes_read += ref_size;
1567    EXPECT_EQ(ref_size, out_size);
1568    EXPECT_EQ(0, memcmp(ref_bytes.get(), out_bytes.get(), ref_size));
1569    ref_size = ReadMessageBytesFromFile(ref_file, &ref_bytes);
1570    out_size = ReadMessageBytesFromFile(out_file, &out_bytes);
1571  }
1572  EXPECT_GT(bytes_read, 0u);
1573  EXPECT_NE(0, feof(ref_file));
1574  EXPECT_NE(0, feof(out_file));
1575  ASSERT_EQ(0, fclose(ref_file));
1576  ASSERT_EQ(0, fclose(out_file));
1577}
1578
1579TEST_F(ApmTest, VerifyDebugDumpInt) {
1580  VerifyDebugDumpTest(kIntFormat);
1581}
1582
1583TEST_F(ApmTest, VerifyDebugDumpFloat) {
1584  VerifyDebugDumpTest(kFloatFormat);
1585}
1586#endif
1587
1588// TODO(andrew): expand test to verify output.
1589TEST_F(ApmTest, DebugDump) {
1590  const std::string filename = test::OutputPath() + "debug.aec";
1591  EXPECT_EQ(apm_->kNullPointerError,
1592            apm_->StartDebugRecording(static_cast<const char*>(NULL)));
1593
1594#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
1595  // Stopping without having started should be OK.
1596  EXPECT_EQ(apm_->kNoError, apm_->StopDebugRecording());
1597
1598  EXPECT_EQ(apm_->kNoError, apm_->StartDebugRecording(filename.c_str()));
1599  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1600  EXPECT_EQ(apm_->kNoError, apm_->AnalyzeReverseStream(revframe_));
1601  EXPECT_EQ(apm_->kNoError, apm_->StopDebugRecording());
1602
1603  // Verify the file has been written.
1604  FILE* fid = fopen(filename.c_str(), "r");
1605  ASSERT_TRUE(fid != NULL);
1606
1607  // Clean it up.
1608  ASSERT_EQ(0, fclose(fid));
1609  ASSERT_EQ(0, remove(filename.c_str()));
1610#else
1611  EXPECT_EQ(apm_->kUnsupportedFunctionError,
1612            apm_->StartDebugRecording(filename.c_str()));
1613  EXPECT_EQ(apm_->kUnsupportedFunctionError, apm_->StopDebugRecording());
1614
1615  // Verify the file has NOT been written.
1616  ASSERT_TRUE(fopen(filename.c_str(), "r") == NULL);
1617#endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
1618}
1619
1620// TODO(andrew): expand test to verify output.
1621TEST_F(ApmTest, DebugDumpFromFileHandle) {
1622  FILE* fid = NULL;
1623  EXPECT_EQ(apm_->kNullPointerError, apm_->StartDebugRecording(fid));
1624  const std::string filename = test::OutputPath() + "debug.aec";
1625  fid = fopen(filename.c_str(), "w");
1626  ASSERT_TRUE(fid);
1627
1628#ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
1629  // Stopping without having started should be OK.
1630  EXPECT_EQ(apm_->kNoError, apm_->StopDebugRecording());
1631
1632  EXPECT_EQ(apm_->kNoError, apm_->StartDebugRecording(fid));
1633  EXPECT_EQ(apm_->kNoError, apm_->AnalyzeReverseStream(revframe_));
1634  EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1635  EXPECT_EQ(apm_->kNoError, apm_->StopDebugRecording());
1636
1637  // Verify the file has been written.
1638  fid = fopen(filename.c_str(), "r");
1639  ASSERT_TRUE(fid != NULL);
1640
1641  // Clean it up.
1642  ASSERT_EQ(0, fclose(fid));
1643  ASSERT_EQ(0, remove(filename.c_str()));
1644#else
1645  EXPECT_EQ(apm_->kUnsupportedFunctionError,
1646            apm_->StartDebugRecording(fid));
1647  EXPECT_EQ(apm_->kUnsupportedFunctionError, apm_->StopDebugRecording());
1648
1649  ASSERT_EQ(0, fclose(fid));
1650#endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
1651}
1652
1653TEST_F(ApmTest, FloatAndIntInterfacesGiveIdenticalResults) {
1654  audioproc::OutputData ref_data;
1655  OpenFileAndReadMessage(ref_filename_, &ref_data);
1656
1657  Config config;
1658  config.Set<ExperimentalAgc>(new ExperimentalAgc(false));
1659  scoped_ptr<AudioProcessing> fapm(AudioProcessing::Create(config));
1660  EnableAllComponents();
1661  EnableAllAPComponents(fapm.get());
1662  for (int i = 0; i < ref_data.test_size(); i++) {
1663    printf("Running test %d of %d...\n", i + 1, ref_data.test_size());
1664
1665    audioproc::Test* test = ref_data.mutable_test(i);
1666    // TODO(ajm): Restore downmixing test cases.
1667    if (test->num_input_channels() != test->num_output_channels())
1668      continue;
1669
1670    const int num_render_channels = test->num_reverse_channels();
1671    const int num_input_channels = test->num_input_channels();
1672    const int num_output_channels = test->num_output_channels();
1673    const int samples_per_channel = test->sample_rate() *
1674        AudioProcessing::kChunkSizeMs / 1000;
1675    const int output_length = samples_per_channel * num_output_channels;
1676
1677    Init(test->sample_rate(), test->sample_rate(), test->sample_rate(),
1678         num_input_channels, num_output_channels, num_render_channels, true);
1679    Init(fapm.get());
1680
1681    ChannelBuffer<int16_t> output_cb(samples_per_channel, num_input_channels);
1682    scoped_ptr<int16_t[]> output_int16(new int16_t[output_length]);
1683
1684    int analog_level = 127;
1685    while (ReadFrame(far_file_, revframe_, revfloat_cb_.get()) &&
1686           ReadFrame(near_file_, frame_, float_cb_.get())) {
1687      frame_->vad_activity_ = AudioFrame::kVadUnknown;
1688
1689      EXPECT_NOERR(apm_->AnalyzeReverseStream(revframe_));
1690      EXPECT_NOERR(fapm->AnalyzeReverseStream(
1691          revfloat_cb_->channels(),
1692          samples_per_channel,
1693          test->sample_rate(),
1694          LayoutFromChannels(num_render_channels)));
1695
1696      EXPECT_NOERR(apm_->set_stream_delay_ms(0));
1697      EXPECT_NOERR(fapm->set_stream_delay_ms(0));
1698      apm_->echo_cancellation()->set_stream_drift_samples(0);
1699      fapm->echo_cancellation()->set_stream_drift_samples(0);
1700      EXPECT_NOERR(apm_->gain_control()->set_stream_analog_level(analog_level));
1701      EXPECT_NOERR(fapm->gain_control()->set_stream_analog_level(analog_level));
1702
1703      EXPECT_NOERR(apm_->ProcessStream(frame_));
1704      // TODO(ajm): Update to support different output rates.
1705      EXPECT_NOERR(fapm->ProcessStream(
1706          float_cb_->channels(),
1707          samples_per_channel,
1708          test->sample_rate(),
1709          LayoutFromChannels(num_input_channels),
1710          test->sample_rate(),
1711          LayoutFromChannels(num_output_channels),
1712          float_cb_->channels()));
1713
1714      // Convert to interleaved int16.
1715      ScaleAndRoundToInt16(float_cb_->data(), output_length, output_cb.data());
1716      Interleave(output_cb.channels(),
1717                 samples_per_channel,
1718                 num_output_channels,
1719                 output_int16.get());
1720      // Verify float and int16 paths produce identical output.
1721      EXPECT_EQ(0, memcmp(frame_->data_, output_int16.get(), output_length));
1722
1723      analog_level = fapm->gain_control()->stream_analog_level();
1724      EXPECT_EQ(apm_->gain_control()->stream_analog_level(),
1725                fapm->gain_control()->stream_analog_level());
1726      EXPECT_EQ(apm_->echo_cancellation()->stream_has_echo(),
1727                fapm->echo_cancellation()->stream_has_echo());
1728      EXPECT_EQ(apm_->voice_detection()->stream_has_voice(),
1729                fapm->voice_detection()->stream_has_voice());
1730      EXPECT_EQ(apm_->noise_suppression()->speech_probability(),
1731                fapm->noise_suppression()->speech_probability());
1732
1733      // Reset in case of downmixing.
1734      frame_->num_channels_ = test->num_input_channels();
1735    }
1736    rewind(far_file_);
1737    rewind(near_file_);
1738  }
1739}
1740
1741// TODO(andrew): Add a test to process a few frames with different combinations
1742// of enabled components.
1743
1744TEST_F(ApmTest, Process) {
1745  GOOGLE_PROTOBUF_VERIFY_VERSION;
1746  audioproc::OutputData ref_data;
1747
1748  if (!write_ref_data) {
1749    OpenFileAndReadMessage(ref_filename_, &ref_data);
1750  } else {
1751    // Write the desired tests to the protobuf reference file.
1752    for (size_t i = 0; i < kChannelsSize; i++) {
1753      for (size_t j = 0; j < kChannelsSize; j++) {
1754        for (size_t l = 0; l < kProcessSampleRatesSize; l++) {
1755          audioproc::Test* test = ref_data.add_test();
1756          test->set_num_reverse_channels(kChannels[i]);
1757          test->set_num_input_channels(kChannels[j]);
1758          test->set_num_output_channels(kChannels[j]);
1759          test->set_sample_rate(kProcessSampleRates[l]);
1760        }
1761      }
1762    }
1763  }
1764
1765  EnableAllComponents();
1766
1767  for (int i = 0; i < ref_data.test_size(); i++) {
1768    printf("Running test %d of %d...\n", i + 1, ref_data.test_size());
1769
1770    audioproc::Test* test = ref_data.mutable_test(i);
1771    // TODO(ajm): We no longer allow different input and output channels. Skip
1772    // these tests for now, but they should be removed from the set.
1773    if (test->num_input_channels() != test->num_output_channels())
1774      continue;
1775
1776    Init(test->sample_rate(),
1777         test->sample_rate(),
1778         test->sample_rate(),
1779         test->num_input_channels(),
1780         test->num_output_channels(),
1781         test->num_reverse_channels(),
1782         true);
1783
1784    int frame_count = 0;
1785    int has_echo_count = 0;
1786    int has_voice_count = 0;
1787    int is_saturated_count = 0;
1788    int analog_level = 127;
1789    int analog_level_average = 0;
1790    int max_output_average = 0;
1791    float ns_speech_prob_average = 0.0f;
1792
1793    while (ReadFrame(far_file_, revframe_) && ReadFrame(near_file_, frame_)) {
1794      EXPECT_EQ(apm_->kNoError, apm_->AnalyzeReverseStream(revframe_));
1795
1796      frame_->vad_activity_ = AudioFrame::kVadUnknown;
1797
1798      EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0));
1799      apm_->echo_cancellation()->set_stream_drift_samples(0);
1800      EXPECT_EQ(apm_->kNoError,
1801          apm_->gain_control()->set_stream_analog_level(analog_level));
1802
1803      EXPECT_EQ(apm_->kNoError, apm_->ProcessStream(frame_));
1804
1805      // Ensure the frame was downmixed properly.
1806      EXPECT_EQ(test->num_output_channels(), frame_->num_channels_);
1807
1808      max_output_average += MaxAudioFrame(*frame_);
1809
1810      if (apm_->echo_cancellation()->stream_has_echo()) {
1811        has_echo_count++;
1812      }
1813
1814      analog_level = apm_->gain_control()->stream_analog_level();
1815      analog_level_average += analog_level;
1816      if (apm_->gain_control()->stream_is_saturated()) {
1817        is_saturated_count++;
1818      }
1819      if (apm_->voice_detection()->stream_has_voice()) {
1820        has_voice_count++;
1821        EXPECT_EQ(AudioFrame::kVadActive, frame_->vad_activity_);
1822      } else {
1823        EXPECT_EQ(AudioFrame::kVadPassive, frame_->vad_activity_);
1824      }
1825
1826      ns_speech_prob_average += apm_->noise_suppression()->speech_probability();
1827
1828      size_t frame_size = frame_->samples_per_channel_ * frame_->num_channels_;
1829      size_t write_count = fwrite(frame_->data_,
1830                                  sizeof(int16_t),
1831                                  frame_size,
1832                                  out_file_);
1833      ASSERT_EQ(frame_size, write_count);
1834
1835      // Reset in case of downmixing.
1836      frame_->num_channels_ = test->num_input_channels();
1837      frame_count++;
1838    }
1839    max_output_average /= frame_count;
1840    analog_level_average /= frame_count;
1841    ns_speech_prob_average /= frame_count;
1842
1843#if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
1844    EchoCancellation::Metrics echo_metrics;
1845    EXPECT_EQ(apm_->kNoError,
1846              apm_->echo_cancellation()->GetMetrics(&echo_metrics));
1847    int median = 0;
1848    int std = 0;
1849    EXPECT_EQ(apm_->kNoError,
1850              apm_->echo_cancellation()->GetDelayMetrics(&median, &std));
1851
1852    int rms_level = apm_->level_estimator()->RMS();
1853    EXPECT_LE(0, rms_level);
1854    EXPECT_GE(127, rms_level);
1855#endif
1856
1857    if (!write_ref_data) {
1858      const int kIntNear = 1;
1859      // When running the test on a N7 we get a {2, 6} difference of
1860      // |has_voice_count| and |max_output_average| is up to 18 higher.
1861      // All numbers being consistently higher on N7 compare to ref_data.
1862      // TODO(bjornv): If we start getting more of these offsets on Android we
1863      // should consider a different approach. Either using one slack for all,
1864      // or generate a separate android reference.
1865#if defined(WEBRTC_ANDROID)
1866      const int kHasVoiceCountOffset = 3;
1867      const int kHasVoiceCountNear = 3;
1868      const int kMaxOutputAverageOffset = 9;
1869      const int kMaxOutputAverageNear = 9;
1870#else
1871      const int kHasVoiceCountOffset = 0;
1872      const int kHasVoiceCountNear = kIntNear;
1873      const int kMaxOutputAverageOffset = 0;
1874      const int kMaxOutputAverageNear = kIntNear;
1875#endif
1876      EXPECT_NEAR(test->has_echo_count(), has_echo_count, kIntNear);
1877      EXPECT_NEAR(test->has_voice_count(),
1878                  has_voice_count - kHasVoiceCountOffset,
1879                  kHasVoiceCountNear);
1880      EXPECT_NEAR(test->is_saturated_count(), is_saturated_count, kIntNear);
1881
1882      EXPECT_NEAR(test->analog_level_average(), analog_level_average, kIntNear);
1883      EXPECT_NEAR(test->max_output_average(),
1884                  max_output_average - kMaxOutputAverageOffset,
1885                  kMaxOutputAverageNear);
1886
1887#if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
1888      audioproc::Test::EchoMetrics reference = test->echo_metrics();
1889      TestStats(echo_metrics.residual_echo_return_loss,
1890                reference.residual_echo_return_loss());
1891      TestStats(echo_metrics.echo_return_loss,
1892                reference.echo_return_loss());
1893      TestStats(echo_metrics.echo_return_loss_enhancement,
1894                reference.echo_return_loss_enhancement());
1895      TestStats(echo_metrics.a_nlp,
1896                reference.a_nlp());
1897
1898      const double kFloatNear = 0.0005;
1899      audioproc::Test::DelayMetrics reference_delay = test->delay_metrics();
1900      EXPECT_NEAR(reference_delay.median(), median, kIntNear);
1901      EXPECT_NEAR(reference_delay.std(), std, kIntNear);
1902
1903      EXPECT_NEAR(test->rms_level(), rms_level, kIntNear);
1904
1905      EXPECT_NEAR(test->ns_speech_probability_average(),
1906                  ns_speech_prob_average,
1907                  kFloatNear);
1908#endif
1909    } else {
1910      test->set_has_echo_count(has_echo_count);
1911      test->set_has_voice_count(has_voice_count);
1912      test->set_is_saturated_count(is_saturated_count);
1913
1914      test->set_analog_level_average(analog_level_average);
1915      test->set_max_output_average(max_output_average);
1916
1917#if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
1918      audioproc::Test::EchoMetrics* message = test->mutable_echo_metrics();
1919      WriteStatsMessage(echo_metrics.residual_echo_return_loss,
1920                        message->mutable_residual_echo_return_loss());
1921      WriteStatsMessage(echo_metrics.echo_return_loss,
1922                        message->mutable_echo_return_loss());
1923      WriteStatsMessage(echo_metrics.echo_return_loss_enhancement,
1924                        message->mutable_echo_return_loss_enhancement());
1925      WriteStatsMessage(echo_metrics.a_nlp,
1926                        message->mutable_a_nlp());
1927
1928      audioproc::Test::DelayMetrics* message_delay =
1929          test->mutable_delay_metrics();
1930      message_delay->set_median(median);
1931      message_delay->set_std(std);
1932
1933      test->set_rms_level(rms_level);
1934
1935      EXPECT_LE(0.0f, ns_speech_prob_average);
1936      EXPECT_GE(1.0f, ns_speech_prob_average);
1937      test->set_ns_speech_probability_average(ns_speech_prob_average);
1938#endif
1939    }
1940
1941    rewind(far_file_);
1942    rewind(near_file_);
1943  }
1944
1945  if (write_ref_data) {
1946    OpenFileAndWriteMessage(ref_filename_, ref_data);
1947  }
1948}
1949
1950TEST_F(ApmTest, NoErrorsWithKeyboardChannel) {
1951  struct ChannelFormat {
1952    AudioProcessing::ChannelLayout in_layout;
1953    AudioProcessing::ChannelLayout out_layout;
1954  };
1955  ChannelFormat cf[] = {
1956    {AudioProcessing::kMonoAndKeyboard, AudioProcessing::kMono},
1957    {AudioProcessing::kStereoAndKeyboard, AudioProcessing::kMono},
1958    {AudioProcessing::kStereoAndKeyboard, AudioProcessing::kStereo},
1959  };
1960  size_t channel_format_size = sizeof(cf) / sizeof(*cf);
1961
1962  scoped_ptr<AudioProcessing> ap(AudioProcessing::Create());
1963  // Enable one component just to ensure some processing takes place.
1964  ap->noise_suppression()->Enable(true);
1965  for (size_t i = 0; i < channel_format_size; ++i) {
1966    const int in_rate = 44100;
1967    const int out_rate = 48000;
1968    ChannelBuffer<float> in_cb(SamplesFromRate(in_rate),
1969                               TotalChannelsFromLayout(cf[i].in_layout));
1970    ChannelBuffer<float> out_cb(SamplesFromRate(out_rate),
1971                                ChannelsFromLayout(cf[i].out_layout));
1972
1973    // Run over a few chunks.
1974    for (int j = 0; j < 10; ++j) {
1975      EXPECT_NOERR(ap->ProcessStream(
1976          in_cb.channels(),
1977          in_cb.samples_per_channel(),
1978          in_rate,
1979          cf[i].in_layout,
1980          out_rate,
1981          cf[i].out_layout,
1982          out_cb.channels()));
1983    }
1984  }
1985}
1986
1987// Reads a 10 ms chunk of int16 interleaved audio from the given (assumed
1988// stereo) file, converts to deinterleaved float (optionally downmixing) and
1989// returns the result in |cb|. Returns false if the file ended (or on error) and
1990// true otherwise.
1991//
1992// |int_data| and |float_data| are just temporary space that must be
1993// sufficiently large to hold the 10 ms chunk.
1994bool ReadChunk(FILE* file, int16_t* int_data, float* float_data,
1995               ChannelBuffer<float>* cb) {
1996  // The files always contain stereo audio.
1997  size_t frame_size = cb->samples_per_channel() * 2;
1998  size_t read_count = fread(int_data, sizeof(int16_t), frame_size, file);
1999  if (read_count != frame_size) {
2000    // Check that the file really ended.
2001    assert(feof(file));
2002    return false;  // This is expected.
2003  }
2004
2005  ScaleToFloat(int_data, frame_size, float_data);
2006  if (cb->num_channels() == 1) {
2007    MixStereoToMono(float_data, cb->data(), cb->samples_per_channel());
2008  } else {
2009    Deinterleave(float_data, cb->samples_per_channel(), 2,
2010                 cb->channels());
2011  }
2012
2013  return true;
2014}
2015
2016// Compares the reference and test arrays over a region around the expected
2017// delay. Finds the highest SNR in that region and adds the variance and squared
2018// error results to the supplied accumulators.
2019void UpdateBestSNR(const float* ref,
2020                   const float* test,
2021                   int length,
2022                   int expected_delay,
2023                   double* variance_acc,
2024                   double* sq_error_acc) {
2025  double best_snr = std::numeric_limits<double>::min();
2026  double best_variance = 0;
2027  double best_sq_error = 0;
2028  // Search over a region of eight samples around the expected delay.
2029  for (int delay = std::max(expected_delay - 4, 0); delay <= expected_delay + 4;
2030       ++delay) {
2031    double sq_error = 0;
2032    double variance = 0;
2033    for (int i = 0; i < length - delay; ++i) {
2034      double error = test[i + delay] - ref[i];
2035      sq_error += error * error;
2036      variance += ref[i] * ref[i];
2037    }
2038
2039    if (sq_error == 0) {
2040      *variance_acc += variance;
2041      return;
2042    }
2043    double snr = variance / sq_error;
2044    if (snr > best_snr) {
2045      best_snr = snr;
2046      best_variance = variance;
2047      best_sq_error = sq_error;
2048    }
2049  }
2050
2051  *variance_acc += best_variance;
2052  *sq_error_acc += best_sq_error;
2053}
2054
2055// Used to test a multitude of sample rate and channel combinations. It works
2056// by first producing a set of reference files (in SetUpTestCase) that are
2057// assumed to be correct, as the used parameters are verified by other tests
2058// in this collection. Primarily the reference files are all produced at
2059// "native" rates which do not involve any resampling.
2060
2061// Each test pass produces an output file with a particular format. The output
2062// is matched against the reference file closest to its internal processing
2063// format. If necessary the output is resampled back to its process format.
2064// Due to the resampling distortion, we don't expect identical results, but
2065// enforce SNR thresholds which vary depending on the format. 0 is a special
2066// case SNR which corresponds to inf, or zero error.
2067typedef std::tr1::tuple<int, int, int, double> AudioProcessingTestData;
2068class AudioProcessingTest
2069    : public testing::TestWithParam<AudioProcessingTestData> {
2070 public:
2071  AudioProcessingTest()
2072      : input_rate_(std::tr1::get<0>(GetParam())),
2073        output_rate_(std::tr1::get<1>(GetParam())),
2074        reverse_rate_(std::tr1::get<2>(GetParam())),
2075        expected_snr_(std::tr1::get<3>(GetParam())) {}
2076
2077  virtual ~AudioProcessingTest() {}
2078
2079  static void SetUpTestCase() {
2080    // Create all needed output reference files.
2081    const int kNativeRates[] = {8000, 16000, 32000};
2082    const size_t kNativeRatesSize =
2083        sizeof(kNativeRates) / sizeof(*kNativeRates);
2084    const int kNumChannels[] = {1, 2};
2085    const size_t kNumChannelsSize =
2086        sizeof(kNumChannels) / sizeof(*kNumChannels);
2087    for (size_t i = 0; i < kNativeRatesSize; ++i) {
2088      for (size_t j = 0; j < kNumChannelsSize; ++j) {
2089        for (size_t k = 0; k < kNumChannelsSize; ++k) {
2090          // The reference files always have matching input and output channels.
2091          ProcessFormat(kNativeRates[i],
2092                        kNativeRates[i],
2093                        kNativeRates[i],
2094                        kNumChannels[j],
2095                        kNumChannels[j],
2096                        kNumChannels[k],
2097                        "ref");
2098        }
2099      }
2100    }
2101  }
2102
2103  // Runs a process pass on files with the given parameters and dumps the output
2104  // to a file specified with |output_file_prefix|.
2105  static void ProcessFormat(int input_rate,
2106                            int output_rate,
2107                            int reverse_rate,
2108                            int num_input_channels,
2109                            int num_output_channels,
2110                            int num_reverse_channels,
2111                            std::string output_file_prefix) {
2112    scoped_ptr<AudioProcessing> ap(AudioProcessing::Create());
2113    EnableAllAPComponents(ap.get());
2114    ap->Initialize(input_rate,
2115                   output_rate,
2116                   reverse_rate,
2117                   LayoutFromChannels(num_input_channels),
2118                   LayoutFromChannels(num_output_channels),
2119                   LayoutFromChannels(num_reverse_channels));
2120
2121    FILE* far_file = fopen(ResourceFilePath("far", reverse_rate).c_str(), "rb");
2122    FILE* near_file = fopen(ResourceFilePath("near", input_rate).c_str(), "rb");
2123    FILE* out_file = fopen(OutputFilePath(output_file_prefix,
2124                                          input_rate,
2125                                          output_rate,
2126                                          reverse_rate,
2127                                          num_input_channels,
2128                                          num_output_channels,
2129                                          num_reverse_channels).c_str(), "wb");
2130    ASSERT_TRUE(far_file != NULL);
2131    ASSERT_TRUE(near_file != NULL);
2132    ASSERT_TRUE(out_file != NULL);
2133
2134    ChannelBuffer<float> fwd_cb(SamplesFromRate(input_rate),
2135                                num_input_channels);
2136    ChannelBuffer<float> rev_cb(SamplesFromRate(reverse_rate),
2137                                num_reverse_channels);
2138    ChannelBuffer<float> out_cb(SamplesFromRate(output_rate),
2139                                num_output_channels);
2140
2141    // Temporary buffers.
2142    const int max_length =
2143        2 * std::max(out_cb.samples_per_channel(),
2144                     std::max(fwd_cb.samples_per_channel(),
2145                              rev_cb.samples_per_channel()));
2146    scoped_ptr<float[]> float_data(new float[max_length]);
2147    scoped_ptr<int16_t[]> int_data(new int16_t[max_length]);
2148
2149    int analog_level = 127;
2150    while (ReadChunk(far_file, int_data.get(), float_data.get(), &rev_cb) &&
2151           ReadChunk(near_file, int_data.get(), float_data.get(), &fwd_cb)) {
2152      EXPECT_NOERR(ap->AnalyzeReverseStream(
2153          rev_cb.channels(),
2154          rev_cb.samples_per_channel(),
2155          reverse_rate,
2156          LayoutFromChannels(num_reverse_channels)));
2157
2158      EXPECT_NOERR(ap->set_stream_delay_ms(0));
2159      ap->echo_cancellation()->set_stream_drift_samples(0);
2160      EXPECT_NOERR(ap->gain_control()->set_stream_analog_level(analog_level));
2161
2162      EXPECT_NOERR(ap->ProcessStream(
2163          fwd_cb.channels(),
2164          fwd_cb.samples_per_channel(),
2165          input_rate,
2166          LayoutFromChannels(num_input_channels),
2167          output_rate,
2168          LayoutFromChannels(num_output_channels),
2169          out_cb.channels()));
2170
2171      Interleave(out_cb.channels(),
2172                 out_cb.samples_per_channel(),
2173                 out_cb.num_channels(),
2174                 float_data.get());
2175      // Dump output to file.
2176      ASSERT_EQ(static_cast<size_t>(out_cb.length()),
2177                fwrite(float_data.get(), sizeof(float_data[0]),
2178                       out_cb.length(), out_file));
2179
2180      analog_level = ap->gain_control()->stream_analog_level();
2181    }
2182    fclose(far_file);
2183    fclose(near_file);
2184    fclose(out_file);
2185  }
2186
2187 protected:
2188  int input_rate_;
2189  int output_rate_;
2190  int reverse_rate_;
2191  double expected_snr_;
2192};
2193
2194TEST_P(AudioProcessingTest, Formats) {
2195  struct ChannelFormat {
2196    int num_input;
2197    int num_output;
2198    int num_reverse;
2199  };
2200  ChannelFormat cf[] = {
2201    {1, 1, 1},
2202    {1, 1, 2},
2203    {2, 1, 1},
2204    {2, 1, 2},
2205    {2, 2, 1},
2206    {2, 2, 2},
2207  };
2208  size_t channel_format_size = sizeof(cf) / sizeof(*cf);
2209
2210  for (size_t i = 0; i < channel_format_size; ++i) {
2211    ProcessFormat(input_rate_,
2212                  output_rate_,
2213                  reverse_rate_,
2214                  cf[i].num_input,
2215                  cf[i].num_output,
2216                  cf[i].num_reverse,
2217                  "out");
2218    int min_ref_rate = std::min(input_rate_, output_rate_);
2219    int ref_rate;
2220    if (min_ref_rate > 16000) {
2221      ref_rate = 32000;
2222    } else if (min_ref_rate > 8000) {
2223      ref_rate = 16000;
2224    } else {
2225      ref_rate = 8000;
2226    }
2227#ifdef WEBRTC_AUDIOPROC_FIXED_PROFILE
2228    ref_rate = std::min(ref_rate, 16000);
2229#endif
2230
2231    FILE* out_file = fopen(OutputFilePath("out",
2232                                          input_rate_,
2233                                          output_rate_,
2234                                          reverse_rate_,
2235                                          cf[i].num_input,
2236                                          cf[i].num_output,
2237                                          cf[i].num_reverse).c_str(), "rb");
2238    // The reference files always have matching input and output channels.
2239    FILE* ref_file = fopen(OutputFilePath("ref",
2240                                          ref_rate,
2241                                          ref_rate,
2242                                          ref_rate,
2243                                          cf[i].num_output,
2244                                          cf[i].num_output,
2245                                          cf[i].num_reverse).c_str(), "rb");
2246    ASSERT_TRUE(out_file != NULL);
2247    ASSERT_TRUE(ref_file != NULL);
2248
2249    const int ref_length = SamplesFromRate(ref_rate) * cf[i].num_output;
2250    const int out_length = SamplesFromRate(output_rate_) * cf[i].num_output;
2251    // Data from the reference file.
2252    scoped_ptr<float[]> ref_data(new float[ref_length]);
2253    // Data from the output file.
2254    scoped_ptr<float[]> out_data(new float[out_length]);
2255    // Data from the resampled output, in case the reference and output rates
2256    // don't match.
2257    scoped_ptr<float[]> cmp_data(new float[ref_length]);
2258
2259    PushResampler<float> resampler;
2260    resampler.InitializeIfNeeded(output_rate_, ref_rate, cf[i].num_output);
2261
2262    // Compute the resampling delay of the output relative to the reference,
2263    // to find the region over which we should search for the best SNR.
2264    float expected_delay_sec = 0;
2265    if (input_rate_ != ref_rate) {
2266      // Input resampling delay.
2267      expected_delay_sec +=
2268          PushSincResampler::AlgorithmicDelaySeconds(input_rate_);
2269    }
2270    if (output_rate_ != ref_rate) {
2271      // Output resampling delay.
2272      expected_delay_sec +=
2273          PushSincResampler::AlgorithmicDelaySeconds(ref_rate);
2274      // Delay of converting the output back to its processing rate for testing.
2275      expected_delay_sec +=
2276          PushSincResampler::AlgorithmicDelaySeconds(output_rate_);
2277    }
2278    int expected_delay = floor(expected_delay_sec * ref_rate + 0.5f) *
2279                         cf[i].num_output;
2280
2281    double variance = 0;
2282    double sq_error = 0;
2283    while (fread(out_data.get(), sizeof(out_data[0]), out_length, out_file) &&
2284           fread(ref_data.get(), sizeof(ref_data[0]), ref_length, ref_file)) {
2285      float* out_ptr = out_data.get();
2286      if (output_rate_ != ref_rate) {
2287        // Resample the output back to its internal processing rate if necssary.
2288        ASSERT_EQ(ref_length, resampler.Resample(out_ptr,
2289                                                 out_length,
2290                                                 cmp_data.get(),
2291                                                 ref_length));
2292        out_ptr = cmp_data.get();
2293      }
2294
2295      // Update the |sq_error| and |variance| accumulators with the highest SNR
2296      // of reference vs output.
2297      UpdateBestSNR(ref_data.get(),
2298                    out_ptr,
2299                    ref_length,
2300                    expected_delay,
2301                    &variance,
2302                    &sq_error);
2303    }
2304
2305    std::cout << "(" << input_rate_ << ", "
2306                     << output_rate_ << ", "
2307                     << reverse_rate_ << ", "
2308                     << cf[i].num_input << ", "
2309                     << cf[i].num_output << ", "
2310                     << cf[i].num_reverse << "): ";
2311    if (sq_error > 0) {
2312      double snr = 10 * log10(variance / sq_error);
2313      EXPECT_GE(snr, expected_snr_);
2314      EXPECT_NE(0, expected_snr_);
2315      std::cout << "SNR=" << snr << " dB" << std::endl;
2316    } else {
2317      EXPECT_EQ(expected_snr_, 0);
2318      std::cout << "SNR=" << "inf dB" << std::endl;
2319    }
2320
2321    fclose(out_file);
2322    fclose(ref_file);
2323  }
2324}
2325
2326#if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
2327INSTANTIATE_TEST_CASE_P(
2328    CommonFormats, AudioProcessingTest, testing::Values(
2329        std::tr1::make_tuple(48000, 48000, 48000, 20),
2330        std::tr1::make_tuple(48000, 48000, 32000, 20),
2331        std::tr1::make_tuple(48000, 48000, 16000, 20),
2332        std::tr1::make_tuple(48000, 44100, 48000, 15),
2333        std::tr1::make_tuple(48000, 44100, 32000, 15),
2334        std::tr1::make_tuple(48000, 44100, 16000, 15),
2335        std::tr1::make_tuple(48000, 32000, 48000, 20),
2336        std::tr1::make_tuple(48000, 32000, 32000, 20),
2337        std::tr1::make_tuple(48000, 32000, 16000, 20),
2338        std::tr1::make_tuple(48000, 16000, 48000, 20),
2339        std::tr1::make_tuple(48000, 16000, 32000, 20),
2340        std::tr1::make_tuple(48000, 16000, 16000, 20),
2341
2342        std::tr1::make_tuple(44100, 48000, 48000, 20),
2343        std::tr1::make_tuple(44100, 48000, 32000, 20),
2344        std::tr1::make_tuple(44100, 48000, 16000, 20),
2345        std::tr1::make_tuple(44100, 44100, 48000, 15),
2346        std::tr1::make_tuple(44100, 44100, 32000, 15),
2347        std::tr1::make_tuple(44100, 44100, 16000, 15),
2348        std::tr1::make_tuple(44100, 32000, 48000, 20),
2349        std::tr1::make_tuple(44100, 32000, 32000, 20),
2350        std::tr1::make_tuple(44100, 32000, 16000, 20),
2351        std::tr1::make_tuple(44100, 16000, 48000, 20),
2352        std::tr1::make_tuple(44100, 16000, 32000, 20),
2353        std::tr1::make_tuple(44100, 16000, 16000, 20),
2354
2355        std::tr1::make_tuple(32000, 48000, 48000, 25),
2356        std::tr1::make_tuple(32000, 48000, 32000, 25),
2357        std::tr1::make_tuple(32000, 48000, 16000, 25),
2358        std::tr1::make_tuple(32000, 44100, 48000, 20),
2359        std::tr1::make_tuple(32000, 44100, 32000, 20),
2360        std::tr1::make_tuple(32000, 44100, 16000, 20),
2361        std::tr1::make_tuple(32000, 32000, 48000, 30),
2362        std::tr1::make_tuple(32000, 32000, 32000, 0),
2363        std::tr1::make_tuple(32000, 32000, 16000, 30),
2364        std::tr1::make_tuple(32000, 16000, 48000, 20),
2365        std::tr1::make_tuple(32000, 16000, 32000, 20),
2366        std::tr1::make_tuple(32000, 16000, 16000, 20),
2367
2368        std::tr1::make_tuple(16000, 48000, 48000, 25),
2369        std::tr1::make_tuple(16000, 48000, 32000, 25),
2370        std::tr1::make_tuple(16000, 48000, 16000, 25),
2371        std::tr1::make_tuple(16000, 44100, 48000, 15),
2372        std::tr1::make_tuple(16000, 44100, 32000, 15),
2373        std::tr1::make_tuple(16000, 44100, 16000, 15),
2374        std::tr1::make_tuple(16000, 32000, 48000, 25),
2375        std::tr1::make_tuple(16000, 32000, 32000, 25),
2376        std::tr1::make_tuple(16000, 32000, 16000, 25),
2377        std::tr1::make_tuple(16000, 16000, 48000, 30),
2378        std::tr1::make_tuple(16000, 16000, 32000, 30),
2379        std::tr1::make_tuple(16000, 16000, 16000, 0)));
2380
2381#elif defined(WEBRTC_AUDIOPROC_FIXED_PROFILE)
2382INSTANTIATE_TEST_CASE_P(
2383    CommonFormats, AudioProcessingTest, testing::Values(
2384        std::tr1::make_tuple(48000, 48000, 48000, 20),
2385        std::tr1::make_tuple(48000, 48000, 32000, 20),
2386        std::tr1::make_tuple(48000, 48000, 16000, 20),
2387        std::tr1::make_tuple(48000, 44100, 48000, 15),
2388        std::tr1::make_tuple(48000, 44100, 32000, 15),
2389        std::tr1::make_tuple(48000, 44100, 16000, 15),
2390        std::tr1::make_tuple(48000, 32000, 48000, 20),
2391        std::tr1::make_tuple(48000, 32000, 32000, 20),
2392        std::tr1::make_tuple(48000, 32000, 16000, 20),
2393        std::tr1::make_tuple(48000, 16000, 48000, 20),
2394        std::tr1::make_tuple(48000, 16000, 32000, 20),
2395        std::tr1::make_tuple(48000, 16000, 16000, 20),
2396
2397        std::tr1::make_tuple(44100, 48000, 48000, 19),
2398        std::tr1::make_tuple(44100, 48000, 32000, 19),
2399        std::tr1::make_tuple(44100, 48000, 16000, 19),
2400        std::tr1::make_tuple(44100, 44100, 48000, 15),
2401        std::tr1::make_tuple(44100, 44100, 32000, 15),
2402        std::tr1::make_tuple(44100, 44100, 16000, 15),
2403        std::tr1::make_tuple(44100, 32000, 48000, 19),
2404        std::tr1::make_tuple(44100, 32000, 32000, 19),
2405        std::tr1::make_tuple(44100, 32000, 16000, 19),
2406        std::tr1::make_tuple(44100, 16000, 48000, 19),
2407        std::tr1::make_tuple(44100, 16000, 32000, 19),
2408        std::tr1::make_tuple(44100, 16000, 16000, 19),
2409
2410        std::tr1::make_tuple(32000, 48000, 48000, 19),
2411        std::tr1::make_tuple(32000, 48000, 32000, 19),
2412        std::tr1::make_tuple(32000, 48000, 16000, 19),
2413        std::tr1::make_tuple(32000, 44100, 48000, 15),
2414        std::tr1::make_tuple(32000, 44100, 32000, 15),
2415        std::tr1::make_tuple(32000, 44100, 16000, 15),
2416        std::tr1::make_tuple(32000, 32000, 48000, 19),
2417        std::tr1::make_tuple(32000, 32000, 32000, 19),
2418        std::tr1::make_tuple(32000, 32000, 16000, 19),
2419        std::tr1::make_tuple(32000, 16000, 48000, 19),
2420        std::tr1::make_tuple(32000, 16000, 32000, 19),
2421        std::tr1::make_tuple(32000, 16000, 16000, 19),
2422
2423        std::tr1::make_tuple(16000, 48000, 48000, 25),
2424        std::tr1::make_tuple(16000, 48000, 32000, 25),
2425        std::tr1::make_tuple(16000, 48000, 16000, 25),
2426        std::tr1::make_tuple(16000, 44100, 48000, 15),
2427        std::tr1::make_tuple(16000, 44100, 32000, 15),
2428        std::tr1::make_tuple(16000, 44100, 16000, 15),
2429        std::tr1::make_tuple(16000, 32000, 48000, 25),
2430        std::tr1::make_tuple(16000, 32000, 32000, 25),
2431        std::tr1::make_tuple(16000, 32000, 16000, 25),
2432        std::tr1::make_tuple(16000, 16000, 48000, 30),
2433        std::tr1::make_tuple(16000, 16000, 32000, 30),
2434        std::tr1::make_tuple(16000, 16000, 16000, 0)));
2435#endif
2436
2437// TODO(henrike): re-implement functionality lost when removing the old main
2438//                function. See
2439//                https://code.google.com/p/webrtc/issues/detail?id=1981
2440
2441}  // namespace
2442}  // namespace webrtc
2443