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 #include "modules/audio_processing/include/audio_processing.h"
11 
12 #include <math.h>
13 #include <stdio.h>
14 
15 #include <algorithm>
16 #include <cmath>
17 #include <limits>
18 #include <memory>
19 #include <numeric>
20 #include <queue>
21 
22 #include "absl/flags/flag.h"
23 #include "common_audio/include/audio_util.h"
24 #include "common_audio/resampler/include/push_resampler.h"
25 #include "common_audio/resampler/push_sinc_resampler.h"
26 #include "common_audio/signal_processing/include/signal_processing_library.h"
27 #include "modules/audio_processing/aec_dump/aec_dump_factory.h"
28 #include "modules/audio_processing/audio_processing_impl.h"
29 #include "modules/audio_processing/common.h"
30 #include "modules/audio_processing/include/mock_audio_processing.h"
31 #include "modules/audio_processing/test/audio_processing_builder_for_testing.h"
32 #include "modules/audio_processing/test/protobuf_utils.h"
33 #include "modules/audio_processing/test/test_utils.h"
34 #include "rtc_base/arraysize.h"
35 #include "rtc_base/checks.h"
36 #include "rtc_base/fake_clock.h"
37 #include "rtc_base/gtest_prod_util.h"
38 #include "rtc_base/ignore_wundef.h"
39 #include "rtc_base/numerics/safe_conversions.h"
40 #include "rtc_base/numerics/safe_minmax.h"
41 #include "rtc_base/protobuf_utils.h"
42 #include "rtc_base/ref_counted_object.h"
43 #include "rtc_base/strings/string_builder.h"
44 #include "rtc_base/swap_queue.h"
45 #include "rtc_base/system/arch.h"
46 #include "rtc_base/task_queue_for_test.h"
47 #include "rtc_base/thread.h"
48 #include "test/gtest.h"
49 #include "test/testsupport/file_utils.h"
50 
51 RTC_PUSH_IGNORING_WUNDEF()
52 #ifdef WEBRTC_ANDROID_PLATFORM_BUILD
53 #include "external/webrtc/webrtc/modules/audio_processing/test/unittest.pb.h"
54 #else
55 #include "modules/audio_processing/test/unittest.pb.h"
56 #endif
57 RTC_POP_IGNORING_WUNDEF()
58 
59 ABSL_FLAG(bool,
60           write_apm_ref_data,
61           false,
62           "Write ApmTest.Process results to file, instead of comparing results "
63           "to the existing reference data file.");
64 
65 namespace webrtc {
66 namespace {
67 
68 // TODO(ekmeyerson): Switch to using StreamConfig and ProcessingConfig where
69 // applicable.
70 
71 const int32_t kChannels[] = {1, 2};
72 const int kSampleRates[] = {8000, 16000, 32000, 48000};
73 
74 #if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE)
75 // Android doesn't support 48kHz.
76 const int kProcessSampleRates[] = {8000, 16000, 32000};
77 #elif defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
78 const int kProcessSampleRates[] = {8000, 16000, 32000, 48000};
79 #endif
80 
81 enum StreamDirection { kForward = 0, kReverse };
82 
ConvertToFloat(const int16_t * int_data,ChannelBuffer<float> * cb)83 void ConvertToFloat(const int16_t* int_data, ChannelBuffer<float>* cb) {
84   ChannelBuffer<int16_t> cb_int(cb->num_frames(), cb->num_channels());
85   Deinterleave(int_data, cb->num_frames(), cb->num_channels(),
86                cb_int.channels());
87   for (size_t i = 0; i < cb->num_channels(); ++i) {
88     S16ToFloat(cb_int.channels()[i], cb->num_frames(), cb->channels()[i]);
89   }
90 }
91 
ConvertToFloat(const Int16FrameData & frame,ChannelBuffer<float> * cb)92 void ConvertToFloat(const Int16FrameData& frame, ChannelBuffer<float>* cb) {
93   ConvertToFloat(frame.data.data(), cb);
94 }
95 
96 // Number of channels including the keyboard channel.
TotalChannelsFromLayout(AudioProcessing::ChannelLayout layout)97 size_t TotalChannelsFromLayout(AudioProcessing::ChannelLayout layout) {
98   switch (layout) {
99     case AudioProcessing::kMono:
100       return 1;
101     case AudioProcessing::kMonoAndKeyboard:
102     case AudioProcessing::kStereo:
103       return 2;
104     case AudioProcessing::kStereoAndKeyboard:
105       return 3;
106   }
107   RTC_NOTREACHED();
108   return 0;
109 }
110 
MixStereoToMono(const float * stereo,float * mono,size_t samples_per_channel)111 void MixStereoToMono(const float* stereo,
112                      float* mono,
113                      size_t samples_per_channel) {
114   for (size_t i = 0; i < samples_per_channel; ++i)
115     mono[i] = (stereo[i * 2] + stereo[i * 2 + 1]) / 2;
116 }
117 
MixStereoToMono(const int16_t * stereo,int16_t * mono,size_t samples_per_channel)118 void MixStereoToMono(const int16_t* stereo,
119                      int16_t* mono,
120                      size_t samples_per_channel) {
121   for (size_t i = 0; i < samples_per_channel; ++i)
122     mono[i] = (stereo[i * 2] + stereo[i * 2 + 1]) >> 1;
123 }
124 
CopyLeftToRightChannel(int16_t * stereo,size_t samples_per_channel)125 void CopyLeftToRightChannel(int16_t* stereo, size_t samples_per_channel) {
126   for (size_t i = 0; i < samples_per_channel; i++) {
127     stereo[i * 2 + 1] = stereo[i * 2];
128   }
129 }
130 
VerifyChannelsAreEqual(const int16_t * stereo,size_t samples_per_channel)131 void VerifyChannelsAreEqual(const int16_t* stereo, size_t samples_per_channel) {
132   for (size_t i = 0; i < samples_per_channel; i++) {
133     EXPECT_EQ(stereo[i * 2 + 1], stereo[i * 2]);
134   }
135 }
136 
SetFrameTo(Int16FrameData * frame,int16_t value)137 void SetFrameTo(Int16FrameData* frame, int16_t value) {
138   for (size_t i = 0; i < frame->samples_per_channel * frame->num_channels;
139        ++i) {
140     frame->data[i] = value;
141   }
142 }
143 
SetFrameTo(Int16FrameData * frame,int16_t left,int16_t right)144 void SetFrameTo(Int16FrameData* frame, int16_t left, int16_t right) {
145   ASSERT_EQ(2u, frame->num_channels);
146   for (size_t i = 0; i < frame->samples_per_channel * 2; i += 2) {
147     frame->data[i] = left;
148     frame->data[i + 1] = right;
149   }
150 }
151 
ScaleFrame(Int16FrameData * frame,float scale)152 void ScaleFrame(Int16FrameData* frame, float scale) {
153   for (size_t i = 0; i < frame->samples_per_channel * frame->num_channels;
154        ++i) {
155     frame->data[i] = FloatS16ToS16(frame->data[i] * scale);
156   }
157 }
158 
FrameDataAreEqual(const Int16FrameData & frame1,const Int16FrameData & frame2)159 bool FrameDataAreEqual(const Int16FrameData& frame1,
160                        const Int16FrameData& frame2) {
161   if (frame1.samples_per_channel != frame2.samples_per_channel) {
162     return false;
163   }
164   if (frame1.num_channels != frame2.num_channels) {
165     return false;
166   }
167   if (memcmp(
168           frame1.data.data(), frame2.data.data(),
169           frame1.samples_per_channel * frame1.num_channels * sizeof(int16_t))) {
170     return false;
171   }
172   return true;
173 }
174 
GetMutableFrameData(Int16FrameData * frame)175 rtc::ArrayView<int16_t> GetMutableFrameData(Int16FrameData* frame) {
176   int16_t* ptr = frame->data.data();
177   const size_t len = frame->samples_per_channel * frame->num_channels;
178   return rtc::ArrayView<int16_t>(ptr, len);
179 }
180 
GetFrameData(const Int16FrameData & frame)181 rtc::ArrayView<const int16_t> GetFrameData(const Int16FrameData& frame) {
182   const int16_t* ptr = frame.data.data();
183   const size_t len = frame.samples_per_channel * frame.num_channels;
184   return rtc::ArrayView<const int16_t>(ptr, len);
185 }
186 
EnableAllAPComponents(AudioProcessing * ap)187 void EnableAllAPComponents(AudioProcessing* ap) {
188   AudioProcessing::Config apm_config = ap->GetConfig();
189   apm_config.echo_canceller.enabled = true;
190 #if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE)
191   apm_config.echo_canceller.mobile_mode = true;
192 
193   apm_config.gain_controller1.enabled = true;
194   apm_config.gain_controller1.mode =
195       AudioProcessing::Config::GainController1::kAdaptiveDigital;
196 #elif defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
197   apm_config.echo_canceller.mobile_mode = false;
198 
199   apm_config.gain_controller1.enabled = true;
200   apm_config.gain_controller1.mode =
201       AudioProcessing::Config::GainController1::kAdaptiveAnalog;
202   apm_config.gain_controller1.analog_level_minimum = 0;
203   apm_config.gain_controller1.analog_level_maximum = 255;
204 #endif
205 
206   apm_config.noise_suppression.enabled = true;
207 
208   apm_config.high_pass_filter.enabled = true;
209   apm_config.level_estimation.enabled = true;
210   apm_config.voice_detection.enabled = true;
211   apm_config.pipeline.maximum_internal_processing_rate = 48000;
212   ap->ApplyConfig(apm_config);
213 }
214 
215 // These functions are only used by ApmTest.Process.
216 template <class T>
AbsValue(T a)217 T AbsValue(T a) {
218   return a > 0 ? a : -a;
219 }
220 
MaxAudioFrame(const Int16FrameData & frame)221 int16_t MaxAudioFrame(const Int16FrameData& frame) {
222   const size_t length = frame.samples_per_channel * frame.num_channels;
223   int16_t max_data = AbsValue(frame.data[0]);
224   for (size_t i = 1; i < length; i++) {
225     max_data = std::max(max_data, AbsValue(frame.data[i]));
226   }
227 
228   return max_data;
229 }
230 
OpenFileAndWriteMessage(const std::string & filename,const MessageLite & msg)231 void OpenFileAndWriteMessage(const std::string& filename,
232                              const MessageLite& msg) {
233   FILE* file = fopen(filename.c_str(), "wb");
234   ASSERT_TRUE(file != NULL);
235 
236   int32_t size = rtc::checked_cast<int32_t>(msg.ByteSizeLong());
237   ASSERT_GT(size, 0);
238   std::unique_ptr<uint8_t[]> array(new uint8_t[size]);
239   ASSERT_TRUE(msg.SerializeToArray(array.get(), size));
240 
241   ASSERT_EQ(1u, fwrite(&size, sizeof(size), 1, file));
242   ASSERT_EQ(static_cast<size_t>(size),
243             fwrite(array.get(), sizeof(array[0]), size, file));
244   fclose(file);
245 }
246 
ResourceFilePath(const std::string & name,int sample_rate_hz)247 std::string ResourceFilePath(const std::string& name, int sample_rate_hz) {
248   rtc::StringBuilder ss;
249   // Resource files are all stereo.
250   ss << name << sample_rate_hz / 1000 << "_stereo";
251   return test::ResourcePath(ss.str(), "pcm");
252 }
253 
254 // Temporary filenames unique to this process. Used to be able to run these
255 // tests in parallel as each process needs to be running in isolation they can't
256 // have competing filenames.
257 std::map<std::string, std::string> temp_filenames;
258 
OutputFilePath(const std::string & name,int input_rate,int output_rate,int reverse_input_rate,int reverse_output_rate,size_t num_input_channels,size_t num_output_channels,size_t num_reverse_input_channels,size_t num_reverse_output_channels,StreamDirection file_direction)259 std::string OutputFilePath(const std::string& name,
260                            int input_rate,
261                            int output_rate,
262                            int reverse_input_rate,
263                            int reverse_output_rate,
264                            size_t num_input_channels,
265                            size_t num_output_channels,
266                            size_t num_reverse_input_channels,
267                            size_t num_reverse_output_channels,
268                            StreamDirection file_direction) {
269   rtc::StringBuilder ss;
270   ss << name << "_i" << num_input_channels << "_" << input_rate / 1000 << "_ir"
271      << num_reverse_input_channels << "_" << reverse_input_rate / 1000 << "_";
272   if (num_output_channels == 1) {
273     ss << "mono";
274   } else if (num_output_channels == 2) {
275     ss << "stereo";
276   } else {
277     RTC_NOTREACHED();
278   }
279   ss << output_rate / 1000;
280   if (num_reverse_output_channels == 1) {
281     ss << "_rmono";
282   } else if (num_reverse_output_channels == 2) {
283     ss << "_rstereo";
284   } else {
285     RTC_NOTREACHED();
286   }
287   ss << reverse_output_rate / 1000;
288   ss << "_d" << file_direction << "_pcm";
289 
290   std::string filename = ss.str();
291   if (temp_filenames[filename].empty())
292     temp_filenames[filename] = test::TempFilename(test::OutputPath(), filename);
293   return temp_filenames[filename];
294 }
295 
ClearTempFiles()296 void ClearTempFiles() {
297   for (auto& kv : temp_filenames)
298     remove(kv.second.c_str());
299 }
300 
301 // Only remove "out" files. Keep "ref" files.
ClearTempOutFiles()302 void ClearTempOutFiles() {
303   for (auto it = temp_filenames.begin(); it != temp_filenames.end();) {
304     const std::string& filename = it->first;
305     if (filename.substr(0, 3).compare("out") == 0) {
306       remove(it->second.c_str());
307       temp_filenames.erase(it++);
308     } else {
309       it++;
310     }
311   }
312 }
313 
OpenFileAndReadMessage(const std::string & filename,MessageLite * msg)314 void OpenFileAndReadMessage(const std::string& filename, MessageLite* msg) {
315   FILE* file = fopen(filename.c_str(), "rb");
316   ASSERT_TRUE(file != NULL);
317   ReadMessageFromFile(file, msg);
318   fclose(file);
319 }
320 
321 // Reads a 10 ms chunk of int16 interleaved audio from the given (assumed
322 // stereo) file, converts to deinterleaved float (optionally downmixing) and
323 // returns the result in |cb|. Returns false if the file ended (or on error) and
324 // true otherwise.
325 //
326 // |int_data| and |float_data| are just temporary space that must be
327 // sufficiently large to hold the 10 ms chunk.
ReadChunk(FILE * file,int16_t * int_data,float * float_data,ChannelBuffer<float> * cb)328 bool ReadChunk(FILE* file,
329                int16_t* int_data,
330                float* float_data,
331                ChannelBuffer<float>* cb) {
332   // The files always contain stereo audio.
333   size_t frame_size = cb->num_frames() * 2;
334   size_t read_count = fread(int_data, sizeof(int16_t), frame_size, file);
335   if (read_count != frame_size) {
336     // Check that the file really ended.
337     RTC_DCHECK(feof(file));
338     return false;  // This is expected.
339   }
340 
341   S16ToFloat(int_data, frame_size, float_data);
342   if (cb->num_channels() == 1) {
343     MixStereoToMono(float_data, cb->channels()[0], cb->num_frames());
344   } else {
345     Deinterleave(float_data, cb->num_frames(), 2, cb->channels());
346   }
347 
348   return true;
349 }
350 
351 class ApmTest : public ::testing::Test {
352  protected:
353   ApmTest();
354   virtual void SetUp();
355   virtual void TearDown();
356 
SetUpTestSuite()357   static void SetUpTestSuite() {}
358 
TearDownTestSuite()359   static void TearDownTestSuite() { ClearTempFiles(); }
360 
361   // Used to select between int and float interface tests.
362   enum Format { kIntFormat, kFloatFormat };
363 
364   void Init(int sample_rate_hz,
365             int output_sample_rate_hz,
366             int reverse_sample_rate_hz,
367             size_t num_input_channels,
368             size_t num_output_channels,
369             size_t num_reverse_channels,
370             bool open_output_file);
371   void Init(AudioProcessing* ap);
372   void EnableAllComponents();
373   bool ReadFrame(FILE* file, Int16FrameData* frame);
374   bool ReadFrame(FILE* file, Int16FrameData* frame, ChannelBuffer<float>* cb);
375   void ReadFrameWithRewind(FILE* file, Int16FrameData* frame);
376   void ReadFrameWithRewind(FILE* file,
377                            Int16FrameData* frame,
378                            ChannelBuffer<float>* cb);
379   void ProcessDelayVerificationTest(int delay_ms,
380                                     int system_delay_ms,
381                                     int delay_min,
382                                     int delay_max);
383   void TestChangingChannelsInt16Interface(
384       size_t num_channels,
385       AudioProcessing::Error expected_return);
386   void TestChangingForwardChannels(size_t num_in_channels,
387                                    size_t num_out_channels,
388                                    AudioProcessing::Error expected_return);
389   void TestChangingReverseChannels(size_t num_rev_channels,
390                                    AudioProcessing::Error expected_return);
391   void RunQuantizedVolumeDoesNotGetStuckTest(int sample_rate);
392   void RunManualVolumeChangeIsPossibleTest(int sample_rate);
393   void StreamParametersTest(Format format);
394   int ProcessStreamChooser(Format format);
395   int AnalyzeReverseStreamChooser(Format format);
396   void ProcessDebugDump(const std::string& in_filename,
397                         const std::string& out_filename,
398                         Format format,
399                         int max_size_bytes);
400   void VerifyDebugDumpTest(Format format);
401 
402   const std::string output_path_;
403   const std::string ref_filename_;
404   std::unique_ptr<AudioProcessing> apm_;
405   Int16FrameData frame_;
406   Int16FrameData revframe_;
407   std::unique_ptr<ChannelBuffer<float> > float_cb_;
408   std::unique_ptr<ChannelBuffer<float> > revfloat_cb_;
409   int output_sample_rate_hz_;
410   size_t num_output_channels_;
411   FILE* far_file_;
412   FILE* near_file_;
413   FILE* out_file_;
414 };
415 
ApmTest()416 ApmTest::ApmTest()
417     : output_path_(test::OutputPath()),
418 #if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE)
419       ref_filename_(
420           test::ResourcePath("audio_processing/output_data_fixed", "pb")),
421 #elif defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
422       ref_filename_(
423           test::ResourcePath("audio_processing/output_data_float", "pb")),
424 #endif
425       output_sample_rate_hz_(0),
426       num_output_channels_(0),
427       far_file_(NULL),
428       near_file_(NULL),
429       out_file_(NULL) {
430   apm_.reset(AudioProcessingBuilderForTesting().Create());
431   AudioProcessing::Config apm_config = apm_->GetConfig();
432   apm_config.gain_controller1.analog_gain_controller.enabled = false;
433   apm_config.pipeline.maximum_internal_processing_rate = 48000;
434   apm_->ApplyConfig(apm_config);
435 }
436 
SetUp()437 void ApmTest::SetUp() {
438   ASSERT_TRUE(apm_.get() != NULL);
439 
440   Init(32000, 32000, 32000, 2, 2, 2, false);
441 }
442 
TearDown()443 void ApmTest::TearDown() {
444   if (far_file_) {
445     ASSERT_EQ(0, fclose(far_file_));
446   }
447   far_file_ = NULL;
448 
449   if (near_file_) {
450     ASSERT_EQ(0, fclose(near_file_));
451   }
452   near_file_ = NULL;
453 
454   if (out_file_) {
455     ASSERT_EQ(0, fclose(out_file_));
456   }
457   out_file_ = NULL;
458 }
459 
Init(AudioProcessing * ap)460 void ApmTest::Init(AudioProcessing* ap) {
461   ASSERT_EQ(
462       kNoErr,
463       ap->Initialize({{{frame_.sample_rate_hz, frame_.num_channels},
464                        {output_sample_rate_hz_, num_output_channels_},
465                        {revframe_.sample_rate_hz, revframe_.num_channels},
466                        {revframe_.sample_rate_hz, revframe_.num_channels}}}));
467 }
468 
Init(int sample_rate_hz,int output_sample_rate_hz,int reverse_sample_rate_hz,size_t num_input_channels,size_t num_output_channels,size_t num_reverse_channels,bool open_output_file)469 void ApmTest::Init(int sample_rate_hz,
470                    int output_sample_rate_hz,
471                    int reverse_sample_rate_hz,
472                    size_t num_input_channels,
473                    size_t num_output_channels,
474                    size_t num_reverse_channels,
475                    bool open_output_file) {
476   SetContainerFormat(sample_rate_hz, num_input_channels, &frame_, &float_cb_);
477   output_sample_rate_hz_ = output_sample_rate_hz;
478   num_output_channels_ = num_output_channels;
479 
480   SetContainerFormat(reverse_sample_rate_hz, num_reverse_channels, &revframe_,
481                      &revfloat_cb_);
482   Init(apm_.get());
483 
484   if (far_file_) {
485     ASSERT_EQ(0, fclose(far_file_));
486   }
487   std::string filename = ResourceFilePath("far", sample_rate_hz);
488   far_file_ = fopen(filename.c_str(), "rb");
489   ASSERT_TRUE(far_file_ != NULL) << "Could not open file " << filename << "\n";
490 
491   if (near_file_) {
492     ASSERT_EQ(0, fclose(near_file_));
493   }
494   filename = ResourceFilePath("near", sample_rate_hz);
495   near_file_ = fopen(filename.c_str(), "rb");
496   ASSERT_TRUE(near_file_ != NULL) << "Could not open file " << filename << "\n";
497 
498   if (open_output_file) {
499     if (out_file_) {
500       ASSERT_EQ(0, fclose(out_file_));
501     }
502     filename = OutputFilePath(
503         "out", sample_rate_hz, output_sample_rate_hz, reverse_sample_rate_hz,
504         reverse_sample_rate_hz, num_input_channels, num_output_channels,
505         num_reverse_channels, num_reverse_channels, kForward);
506     out_file_ = fopen(filename.c_str(), "wb");
507     ASSERT_TRUE(out_file_ != NULL)
508         << "Could not open file " << filename << "\n";
509   }
510 }
511 
EnableAllComponents()512 void ApmTest::EnableAllComponents() {
513   EnableAllAPComponents(apm_.get());
514 }
515 
ReadFrame(FILE * file,Int16FrameData * frame,ChannelBuffer<float> * cb)516 bool ApmTest::ReadFrame(FILE* file,
517                         Int16FrameData* frame,
518                         ChannelBuffer<float>* cb) {
519   // The files always contain stereo audio.
520   size_t frame_size = frame->samples_per_channel * 2;
521   size_t read_count =
522       fread(frame->data.data(), sizeof(int16_t), frame_size, file);
523   if (read_count != frame_size) {
524     // Check that the file really ended.
525     EXPECT_NE(0, feof(file));
526     return false;  // This is expected.
527   }
528 
529   if (frame->num_channels == 1) {
530     MixStereoToMono(frame->data.data(), frame->data.data(),
531                     frame->samples_per_channel);
532   }
533 
534   if (cb) {
535     ConvertToFloat(*frame, cb);
536   }
537   return true;
538 }
539 
ReadFrame(FILE * file,Int16FrameData * frame)540 bool ApmTest::ReadFrame(FILE* file, Int16FrameData* frame) {
541   return ReadFrame(file, frame, NULL);
542 }
543 
544 // If the end of the file has been reached, rewind it and attempt to read the
545 // frame again.
ReadFrameWithRewind(FILE * file,Int16FrameData * frame,ChannelBuffer<float> * cb)546 void ApmTest::ReadFrameWithRewind(FILE* file,
547                                   Int16FrameData* frame,
548                                   ChannelBuffer<float>* cb) {
549   if (!ReadFrame(near_file_, &frame_, cb)) {
550     rewind(near_file_);
551     ASSERT_TRUE(ReadFrame(near_file_, &frame_, cb));
552   }
553 }
554 
ReadFrameWithRewind(FILE * file,Int16FrameData * frame)555 void ApmTest::ReadFrameWithRewind(FILE* file, Int16FrameData* frame) {
556   ReadFrameWithRewind(file, frame, NULL);
557 }
558 
ProcessStreamChooser(Format format)559 int ApmTest::ProcessStreamChooser(Format format) {
560   if (format == kIntFormat) {
561     return apm_->ProcessStream(
562         frame_.data.data(),
563         StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
564         StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
565         frame_.data.data());
566   }
567   return apm_->ProcessStream(
568       float_cb_->channels(),
569       StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
570       StreamConfig(output_sample_rate_hz_, num_output_channels_),
571       float_cb_->channels());
572 }
573 
AnalyzeReverseStreamChooser(Format format)574 int ApmTest::AnalyzeReverseStreamChooser(Format format) {
575   if (format == kIntFormat) {
576     return apm_->ProcessReverseStream(
577         revframe_.data.data(),
578         StreamConfig(revframe_.sample_rate_hz, revframe_.num_channels),
579         StreamConfig(revframe_.sample_rate_hz, revframe_.num_channels),
580         revframe_.data.data());
581   }
582   return apm_->AnalyzeReverseStream(
583       revfloat_cb_->channels(),
584       StreamConfig(revframe_.sample_rate_hz, revframe_.num_channels));
585 }
586 
ProcessDelayVerificationTest(int delay_ms,int system_delay_ms,int delay_min,int delay_max)587 void ApmTest::ProcessDelayVerificationTest(int delay_ms,
588                                            int system_delay_ms,
589                                            int delay_min,
590                                            int delay_max) {
591   // The |revframe_| and |frame_| should include the proper frame information,
592   // hence can be used for extracting information.
593   Int16FrameData tmp_frame;
594   std::queue<Int16FrameData*> frame_queue;
595   bool causal = true;
596 
597   tmp_frame.CopyFrom(revframe_);
598   SetFrameTo(&tmp_frame, 0);
599 
600   EXPECT_EQ(apm_->kNoError, apm_->Initialize());
601   // Initialize the |frame_queue| with empty frames.
602   int frame_delay = delay_ms / 10;
603   while (frame_delay < 0) {
604     Int16FrameData* frame = new Int16FrameData();
605     frame->CopyFrom(tmp_frame);
606     frame_queue.push(frame);
607     frame_delay++;
608     causal = false;
609   }
610   while (frame_delay > 0) {
611     Int16FrameData* frame = new Int16FrameData();
612     frame->CopyFrom(tmp_frame);
613     frame_queue.push(frame);
614     frame_delay--;
615   }
616   // Run for 4.5 seconds, skipping statistics from the first 2.5 seconds.  We
617   // need enough frames with audio to have reliable estimates, but as few as
618   // possible to keep processing time down.  4.5 seconds seemed to be a good
619   // compromise for this recording.
620   for (int frame_count = 0; frame_count < 450; ++frame_count) {
621     Int16FrameData* frame = new Int16FrameData();
622     frame->CopyFrom(tmp_frame);
623     // Use the near end recording, since that has more speech in it.
624     ASSERT_TRUE(ReadFrame(near_file_, frame));
625     frame_queue.push(frame);
626     Int16FrameData* reverse_frame = frame;
627     Int16FrameData* process_frame = frame_queue.front();
628     if (!causal) {
629       reverse_frame = frame_queue.front();
630       // When we call ProcessStream() the frame is modified, so we can't use the
631       // pointer directly when things are non-causal. Use an intermediate frame
632       // and copy the data.
633       process_frame = &tmp_frame;
634       process_frame->CopyFrom(*frame);
635     }
636     EXPECT_EQ(apm_->kNoError, apm_->ProcessReverseStream(
637                                   reverse_frame->data.data(),
638                                   StreamConfig(reverse_frame->sample_rate_hz,
639                                                reverse_frame->num_channels),
640                                   StreamConfig(reverse_frame->sample_rate_hz,
641                                                reverse_frame->num_channels),
642                                   reverse_frame->data.data()));
643     EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(system_delay_ms));
644     EXPECT_EQ(apm_->kNoError,
645               apm_->ProcessStream(process_frame->data.data(),
646                                   StreamConfig(process_frame->sample_rate_hz,
647                                                process_frame->num_channels),
648                                   StreamConfig(process_frame->sample_rate_hz,
649                                                process_frame->num_channels),
650                                   process_frame->data.data()));
651     frame = frame_queue.front();
652     frame_queue.pop();
653     delete frame;
654 
655     if (frame_count == 250) {
656       // Discard the first delay metrics to avoid convergence effects.
657       static_cast<void>(apm_->GetStatistics());
658     }
659   }
660 
661   rewind(near_file_);
662   while (!frame_queue.empty()) {
663     Int16FrameData* frame = frame_queue.front();
664     frame_queue.pop();
665     delete frame;
666   }
667   // Calculate expected delay estimate and acceptable regions. Further,
668   // limit them w.r.t. AEC delay estimation support.
669   const size_t samples_per_ms =
670       rtc::SafeMin<size_t>(16u, frame_.samples_per_channel / 10);
671   const int expected_median =
672       rtc::SafeClamp<int>(delay_ms - system_delay_ms, delay_min, delay_max);
673   const int expected_median_high = rtc::SafeClamp<int>(
674       expected_median + rtc::dchecked_cast<int>(96 / samples_per_ms), delay_min,
675       delay_max);
676   const int expected_median_low = rtc::SafeClamp<int>(
677       expected_median - rtc::dchecked_cast<int>(96 / samples_per_ms), delay_min,
678       delay_max);
679   // Verify delay metrics.
680   AudioProcessingStats stats = apm_->GetStatistics();
681   ASSERT_TRUE(stats.delay_median_ms.has_value());
682   int32_t median = *stats.delay_median_ms;
683   EXPECT_GE(expected_median_high, median);
684   EXPECT_LE(expected_median_low, median);
685 }
686 
StreamParametersTest(Format format)687 void ApmTest::StreamParametersTest(Format format) {
688   // No errors when the components are disabled.
689   EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
690 
691   // -- Missing AGC level --
692   AudioProcessing::Config apm_config = apm_->GetConfig();
693   apm_config.gain_controller1.enabled = true;
694   apm_->ApplyConfig(apm_config);
695   EXPECT_EQ(apm_->kStreamParameterNotSetError, ProcessStreamChooser(format));
696 
697   // Resets after successful ProcessStream().
698   apm_->set_stream_analog_level(127);
699   EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
700   EXPECT_EQ(apm_->kStreamParameterNotSetError, ProcessStreamChooser(format));
701 
702   // Other stream parameters set correctly.
703   apm_config.echo_canceller.enabled = true;
704   apm_config.echo_canceller.mobile_mode = false;
705   apm_->ApplyConfig(apm_config);
706   EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
707   EXPECT_EQ(apm_->kStreamParameterNotSetError, ProcessStreamChooser(format));
708   apm_config.gain_controller1.enabled = false;
709   apm_->ApplyConfig(apm_config);
710 
711   // -- Missing delay --
712   EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
713   EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
714 
715   // Resets after successful ProcessStream().
716   EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
717   EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
718   EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
719 
720   // Other stream parameters set correctly.
721   apm_config.gain_controller1.enabled = true;
722   apm_->ApplyConfig(apm_config);
723   apm_->set_stream_analog_level(127);
724   EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
725   apm_config.gain_controller1.enabled = false;
726   apm_->ApplyConfig(apm_config);
727 
728   // -- No stream parameters --
729   EXPECT_EQ(apm_->kNoError, AnalyzeReverseStreamChooser(format));
730   EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
731 
732   // -- All there --
733   EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(100));
734   apm_->set_stream_analog_level(127);
735   EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(format));
736 }
737 
TEST_F(ApmTest,StreamParametersInt)738 TEST_F(ApmTest, StreamParametersInt) {
739   StreamParametersTest(kIntFormat);
740 }
741 
TEST_F(ApmTest,StreamParametersFloat)742 TEST_F(ApmTest, StreamParametersFloat) {
743   StreamParametersTest(kFloatFormat);
744 }
745 
TestChangingChannelsInt16Interface(size_t num_channels,AudioProcessing::Error expected_return)746 void ApmTest::TestChangingChannelsInt16Interface(
747     size_t num_channels,
748     AudioProcessing::Error expected_return) {
749   frame_.num_channels = num_channels;
750 
751   EXPECT_EQ(expected_return,
752             apm_->ProcessStream(
753                 frame_.data.data(),
754                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
755                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
756                 frame_.data.data()));
757   EXPECT_EQ(expected_return,
758             apm_->ProcessReverseStream(
759                 frame_.data.data(),
760                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
761                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
762                 frame_.data.data()));
763 }
764 
TestChangingForwardChannels(size_t num_in_channels,size_t num_out_channels,AudioProcessing::Error expected_return)765 void ApmTest::TestChangingForwardChannels(
766     size_t num_in_channels,
767     size_t num_out_channels,
768     AudioProcessing::Error expected_return) {
769   const StreamConfig input_stream = {frame_.sample_rate_hz, num_in_channels};
770   const StreamConfig output_stream = {output_sample_rate_hz_, num_out_channels};
771 
772   EXPECT_EQ(expected_return,
773             apm_->ProcessStream(float_cb_->channels(), input_stream,
774                                 output_stream, float_cb_->channels()));
775 }
776 
TestChangingReverseChannels(size_t num_rev_channels,AudioProcessing::Error expected_return)777 void ApmTest::TestChangingReverseChannels(
778     size_t num_rev_channels,
779     AudioProcessing::Error expected_return) {
780   const ProcessingConfig processing_config = {
781       {{frame_.sample_rate_hz, apm_->num_input_channels()},
782        {output_sample_rate_hz_, apm_->num_output_channels()},
783        {frame_.sample_rate_hz, num_rev_channels},
784        {frame_.sample_rate_hz, num_rev_channels}}};
785 
786   EXPECT_EQ(
787       expected_return,
788       apm_->ProcessReverseStream(
789           float_cb_->channels(), processing_config.reverse_input_stream(),
790           processing_config.reverse_output_stream(), float_cb_->channels()));
791 }
792 
TEST_F(ApmTest,ChannelsInt16Interface)793 TEST_F(ApmTest, ChannelsInt16Interface) {
794   // Testing number of invalid and valid channels.
795   Init(16000, 16000, 16000, 4, 4, 4, false);
796 
797   TestChangingChannelsInt16Interface(0, apm_->kBadNumberChannelsError);
798 
799   for (size_t i = 1; i < 4; i++) {
800     TestChangingChannelsInt16Interface(i, kNoErr);
801     EXPECT_EQ(i, apm_->num_input_channels());
802   }
803 }
804 
TEST_F(ApmTest,Channels)805 TEST_F(ApmTest, Channels) {
806   // Testing number of invalid and valid channels.
807   Init(16000, 16000, 16000, 4, 4, 4, false);
808 
809   TestChangingForwardChannels(0, 1, apm_->kBadNumberChannelsError);
810   TestChangingReverseChannels(0, apm_->kBadNumberChannelsError);
811 
812   for (size_t i = 1; i < 4; ++i) {
813     for (size_t j = 0; j < 1; ++j) {
814       // Output channels much be one or match input channels.
815       if (j == 1 || i == j) {
816         TestChangingForwardChannels(i, j, kNoErr);
817         TestChangingReverseChannels(i, kNoErr);
818 
819         EXPECT_EQ(i, apm_->num_input_channels());
820         EXPECT_EQ(j, apm_->num_output_channels());
821         // The number of reverse channels used for processing to is always 1.
822         EXPECT_EQ(1u, apm_->num_reverse_channels());
823       } else {
824         TestChangingForwardChannels(i, j,
825                                     AudioProcessing::kBadNumberChannelsError);
826       }
827     }
828   }
829 }
830 
TEST_F(ApmTest,SampleRatesInt)831 TEST_F(ApmTest, SampleRatesInt) {
832   // Testing some valid sample rates.
833   for (int sample_rate : {8000, 12000, 16000, 32000, 44100, 48000, 96000}) {
834     SetContainerFormat(sample_rate, 2, &frame_, &float_cb_);
835     EXPECT_NOERR(ProcessStreamChooser(kIntFormat));
836   }
837 }
838 
839 // This test repeatedly reconfigures the pre-amplifier in APM, processes a
840 // number of frames, and checks that output signal has the right level.
TEST_F(ApmTest,PreAmplifier)841 TEST_F(ApmTest, PreAmplifier) {
842   // Fill the audio frame with a sawtooth pattern.
843   rtc::ArrayView<int16_t> frame_data = GetMutableFrameData(&frame_);
844   const size_t samples_per_channel = frame_.samples_per_channel;
845   for (size_t i = 0; i < samples_per_channel; i++) {
846     for (size_t ch = 0; ch < frame_.num_channels; ++ch) {
847       frame_data[i + ch * samples_per_channel] = 10000 * ((i % 3) - 1);
848     }
849   }
850   // Cache the frame in tmp_frame.
851   Int16FrameData tmp_frame;
852   tmp_frame.CopyFrom(frame_);
853 
854   auto compute_power = [](const Int16FrameData& frame) {
855     rtc::ArrayView<const int16_t> data = GetFrameData(frame);
856     return std::accumulate(data.begin(), data.end(), 0.0f,
857                            [](float a, float b) { return a + b * b; }) /
858            data.size() / 32768 / 32768;
859   };
860 
861   const float input_power = compute_power(tmp_frame);
862   // Double-check that the input data is large compared to the error kEpsilon.
863   constexpr float kEpsilon = 1e-4f;
864   RTC_DCHECK_GE(input_power, 10 * kEpsilon);
865 
866   // 1. Enable pre-amp with 0 dB gain.
867   AudioProcessing::Config config = apm_->GetConfig();
868   config.pre_amplifier.enabled = true;
869   config.pre_amplifier.fixed_gain_factor = 1.0f;
870   apm_->ApplyConfig(config);
871 
872   for (int i = 0; i < 20; ++i) {
873     frame_.CopyFrom(tmp_frame);
874     EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(kIntFormat));
875   }
876   float output_power = compute_power(frame_);
877   EXPECT_NEAR(output_power, input_power, kEpsilon);
878   config = apm_->GetConfig();
879   EXPECT_EQ(config.pre_amplifier.fixed_gain_factor, 1.0f);
880 
881   // 2. Change pre-amp gain via ApplyConfig.
882   config.pre_amplifier.fixed_gain_factor = 2.0f;
883   apm_->ApplyConfig(config);
884 
885   for (int i = 0; i < 20; ++i) {
886     frame_.CopyFrom(tmp_frame);
887     EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(kIntFormat));
888   }
889   output_power = compute_power(frame_);
890   EXPECT_NEAR(output_power, 4 * input_power, kEpsilon);
891   config = apm_->GetConfig();
892   EXPECT_EQ(config.pre_amplifier.fixed_gain_factor, 2.0f);
893 
894   // 3. Change pre-amp gain via a RuntimeSetting.
895   apm_->SetRuntimeSetting(
896       AudioProcessing::RuntimeSetting::CreateCapturePreGain(1.5f));
897 
898   for (int i = 0; i < 20; ++i) {
899     frame_.CopyFrom(tmp_frame);
900     EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(kIntFormat));
901   }
902   output_power = compute_power(frame_);
903   EXPECT_NEAR(output_power, 2.25 * input_power, kEpsilon);
904   config = apm_->GetConfig();
905   EXPECT_EQ(config.pre_amplifier.fixed_gain_factor, 1.5f);
906 }
907 
TEST_F(ApmTest,GainControl)908 TEST_F(ApmTest, GainControl) {
909   AudioProcessing::Config config = apm_->GetConfig();
910   config.gain_controller1.enabled = false;
911   apm_->ApplyConfig(config);
912   config.gain_controller1.enabled = true;
913   apm_->ApplyConfig(config);
914 
915   // Testing gain modes
916   for (auto mode :
917        {AudioProcessing::Config::GainController1::kAdaptiveDigital,
918         AudioProcessing::Config::GainController1::kFixedDigital,
919         AudioProcessing::Config::GainController1::kAdaptiveAnalog}) {
920     config.gain_controller1.mode = mode;
921     apm_->ApplyConfig(config);
922     apm_->set_stream_analog_level(100);
923     EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(kFloatFormat));
924   }
925 
926   // Testing target levels
927   for (int target_level_dbfs : {0, 15, 31}) {
928     config.gain_controller1.target_level_dbfs = target_level_dbfs;
929     apm_->ApplyConfig(config);
930     apm_->set_stream_analog_level(100);
931     EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(kFloatFormat));
932   }
933 
934   // Testing compression gains
935   for (int compression_gain_db : {0, 10, 90}) {
936     config.gain_controller1.compression_gain_db = compression_gain_db;
937     apm_->ApplyConfig(config);
938     apm_->set_stream_analog_level(100);
939     EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(kFloatFormat));
940   }
941 
942   // Testing limiter off/on
943   for (bool enable : {false, true}) {
944     config.gain_controller1.enable_limiter = enable;
945     apm_->ApplyConfig(config);
946     apm_->set_stream_analog_level(100);
947     EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(kFloatFormat));
948   }
949 
950   // Testing level limits
951   std::array<int, 4> kMinLevels = {0, 0, 255, 65000};
952   std::array<int, 4> kMaxLevels = {255, 1024, 65535, 65535};
953   for (size_t i = 0; i < kMinLevels.size(); ++i) {
954     int min_level = kMinLevels[i];
955     int max_level = kMaxLevels[i];
956     config.gain_controller1.analog_level_minimum = min_level;
957     config.gain_controller1.analog_level_maximum = max_level;
958     apm_->ApplyConfig(config);
959     apm_->set_stream_analog_level((min_level + max_level) / 2);
960     EXPECT_EQ(apm_->kNoError, ProcessStreamChooser(kFloatFormat));
961   }
962 }
963 
964 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
965 using ApmDeathTest = ApmTest;
966 
TEST_F(ApmDeathTest,GainControlDiesOnTooLowTargetLevelDbfs)967 TEST_F(ApmDeathTest, GainControlDiesOnTooLowTargetLevelDbfs) {
968   auto config = apm_->GetConfig();
969   config.gain_controller1.enabled = true;
970   config.gain_controller1.target_level_dbfs = -1;
971   EXPECT_DEATH(apm_->ApplyConfig(config), "");
972 }
973 
TEST_F(ApmDeathTest,GainControlDiesOnTooHighTargetLevelDbfs)974 TEST_F(ApmDeathTest, GainControlDiesOnTooHighTargetLevelDbfs) {
975   auto config = apm_->GetConfig();
976   config.gain_controller1.enabled = true;
977   config.gain_controller1.target_level_dbfs = 32;
978   EXPECT_DEATH(apm_->ApplyConfig(config), "");
979 }
980 
TEST_F(ApmDeathTest,GainControlDiesOnTooLowCompressionGainDb)981 TEST_F(ApmDeathTest, GainControlDiesOnTooLowCompressionGainDb) {
982   auto config = apm_->GetConfig();
983   config.gain_controller1.enabled = true;
984   config.gain_controller1.compression_gain_db = -1;
985   EXPECT_DEATH(apm_->ApplyConfig(config), "");
986 }
987 
TEST_F(ApmDeathTest,GainControlDiesOnTooHighCompressionGainDb)988 TEST_F(ApmDeathTest, GainControlDiesOnTooHighCompressionGainDb) {
989   auto config = apm_->GetConfig();
990   config.gain_controller1.enabled = true;
991   config.gain_controller1.compression_gain_db = 91;
992   EXPECT_DEATH(apm_->ApplyConfig(config), "");
993 }
994 
TEST_F(ApmDeathTest,GainControlDiesOnTooLowAnalogLevelLowerLimit)995 TEST_F(ApmDeathTest, GainControlDiesOnTooLowAnalogLevelLowerLimit) {
996   auto config = apm_->GetConfig();
997   config.gain_controller1.enabled = true;
998   config.gain_controller1.analog_level_minimum = -1;
999   EXPECT_DEATH(apm_->ApplyConfig(config), "");
1000 }
1001 
TEST_F(ApmDeathTest,GainControlDiesOnTooHighAnalogLevelUpperLimit)1002 TEST_F(ApmDeathTest, GainControlDiesOnTooHighAnalogLevelUpperLimit) {
1003   auto config = apm_->GetConfig();
1004   config.gain_controller1.enabled = true;
1005   config.gain_controller1.analog_level_maximum = 65536;
1006   EXPECT_DEATH(apm_->ApplyConfig(config), "");
1007 }
1008 
TEST_F(ApmDeathTest,GainControlDiesOnInvertedAnalogLevelLimits)1009 TEST_F(ApmDeathTest, GainControlDiesOnInvertedAnalogLevelLimits) {
1010   auto config = apm_->GetConfig();
1011   config.gain_controller1.enabled = true;
1012   config.gain_controller1.analog_level_minimum = 512;
1013   config.gain_controller1.analog_level_maximum = 255;
1014   EXPECT_DEATH(apm_->ApplyConfig(config), "");
1015 }
1016 
TEST_F(ApmDeathTest,ApmDiesOnTooLowAnalogLevel)1017 TEST_F(ApmDeathTest, ApmDiesOnTooLowAnalogLevel) {
1018   auto config = apm_->GetConfig();
1019   config.gain_controller1.enabled = true;
1020   config.gain_controller1.analog_level_minimum = 255;
1021   config.gain_controller1.analog_level_maximum = 512;
1022   apm_->ApplyConfig(config);
1023   EXPECT_DEATH(apm_->set_stream_analog_level(254), "");
1024 }
1025 
TEST_F(ApmDeathTest,ApmDiesOnTooHighAnalogLevel)1026 TEST_F(ApmDeathTest, ApmDiesOnTooHighAnalogLevel) {
1027   auto config = apm_->GetConfig();
1028   config.gain_controller1.enabled = true;
1029   config.gain_controller1.analog_level_minimum = 255;
1030   config.gain_controller1.analog_level_maximum = 512;
1031   apm_->ApplyConfig(config);
1032   EXPECT_DEATH(apm_->set_stream_analog_level(513), "");
1033 }
1034 #endif
1035 
RunQuantizedVolumeDoesNotGetStuckTest(int sample_rate)1036 void ApmTest::RunQuantizedVolumeDoesNotGetStuckTest(int sample_rate) {
1037   Init(sample_rate, sample_rate, sample_rate, 2, 2, 2, false);
1038   auto config = apm_->GetConfig();
1039   config.gain_controller1.enabled = true;
1040   config.gain_controller1.mode =
1041       AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1042   apm_->ApplyConfig(config);
1043 
1044   int out_analog_level = 0;
1045   for (int i = 0; i < 2000; ++i) {
1046     ReadFrameWithRewind(near_file_, &frame_);
1047     // Ensure the audio is at a low level, so the AGC will try to increase it.
1048     ScaleFrame(&frame_, 0.25);
1049 
1050     // Always pass in the same volume.
1051     apm_->set_stream_analog_level(100);
1052     EXPECT_EQ(apm_->kNoError,
1053               apm_->ProcessStream(
1054                   frame_.data.data(),
1055                   StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1056                   StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1057                   frame_.data.data()));
1058     out_analog_level = apm_->recommended_stream_analog_level();
1059   }
1060 
1061   // Ensure the AGC is still able to reach the maximum.
1062   EXPECT_EQ(255, out_analog_level);
1063 }
1064 
1065 // Verifies that despite volume slider quantization, the AGC can continue to
1066 // increase its volume.
TEST_F(ApmTest,QuantizedVolumeDoesNotGetStuck)1067 TEST_F(ApmTest, QuantizedVolumeDoesNotGetStuck) {
1068   for (size_t i = 0; i < arraysize(kSampleRates); ++i) {
1069     RunQuantizedVolumeDoesNotGetStuckTest(kSampleRates[i]);
1070   }
1071 }
1072 
RunManualVolumeChangeIsPossibleTest(int sample_rate)1073 void ApmTest::RunManualVolumeChangeIsPossibleTest(int sample_rate) {
1074   Init(sample_rate, sample_rate, sample_rate, 2, 2, 2, false);
1075   auto config = apm_->GetConfig();
1076   config.gain_controller1.enabled = true;
1077   config.gain_controller1.mode =
1078       AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1079   apm_->ApplyConfig(config);
1080 
1081   int out_analog_level = 100;
1082   for (int i = 0; i < 1000; ++i) {
1083     ReadFrameWithRewind(near_file_, &frame_);
1084     // Ensure the audio is at a low level, so the AGC will try to increase it.
1085     ScaleFrame(&frame_, 0.25);
1086 
1087     apm_->set_stream_analog_level(out_analog_level);
1088     EXPECT_EQ(apm_->kNoError,
1089               apm_->ProcessStream(
1090                   frame_.data.data(),
1091                   StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1092                   StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1093                   frame_.data.data()));
1094     out_analog_level = apm_->recommended_stream_analog_level();
1095   }
1096 
1097   // Ensure the volume was raised.
1098   EXPECT_GT(out_analog_level, 100);
1099   int highest_level_reached = out_analog_level;
1100   // Simulate a user manual volume change.
1101   out_analog_level = 100;
1102 
1103   for (int i = 0; i < 300; ++i) {
1104     ReadFrameWithRewind(near_file_, &frame_);
1105     ScaleFrame(&frame_, 0.25);
1106 
1107     apm_->set_stream_analog_level(out_analog_level);
1108     EXPECT_EQ(apm_->kNoError,
1109               apm_->ProcessStream(
1110                   frame_.data.data(),
1111                   StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1112                   StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1113                   frame_.data.data()));
1114     out_analog_level = apm_->recommended_stream_analog_level();
1115     // Check that AGC respected the manually adjusted volume.
1116     EXPECT_LT(out_analog_level, highest_level_reached);
1117   }
1118   // Check that the volume was still raised.
1119   EXPECT_GT(out_analog_level, 100);
1120 }
1121 
TEST_F(ApmTest,ManualVolumeChangeIsPossible)1122 TEST_F(ApmTest, ManualVolumeChangeIsPossible) {
1123   for (size_t i = 0; i < arraysize(kSampleRates); ++i) {
1124     RunManualVolumeChangeIsPossibleTest(kSampleRates[i]);
1125   }
1126 }
1127 
TEST_F(ApmTest,HighPassFilter)1128 TEST_F(ApmTest, HighPassFilter) {
1129   // Turn HP filter on/off
1130   AudioProcessing::Config apm_config;
1131   apm_config.high_pass_filter.enabled = true;
1132   apm_->ApplyConfig(apm_config);
1133   apm_config.high_pass_filter.enabled = false;
1134   apm_->ApplyConfig(apm_config);
1135 }
1136 
TEST_F(ApmTest,AllProcessingDisabledByDefault)1137 TEST_F(ApmTest, AllProcessingDisabledByDefault) {
1138   AudioProcessing::Config config = apm_->GetConfig();
1139   EXPECT_FALSE(config.echo_canceller.enabled);
1140   EXPECT_FALSE(config.high_pass_filter.enabled);
1141   EXPECT_FALSE(config.gain_controller1.enabled);
1142   EXPECT_FALSE(config.level_estimation.enabled);
1143   EXPECT_FALSE(config.noise_suppression.enabled);
1144   EXPECT_FALSE(config.voice_detection.enabled);
1145 }
1146 
TEST_F(ApmTest,NoProcessingWhenAllComponentsDisabled)1147 TEST_F(ApmTest, NoProcessingWhenAllComponentsDisabled) {
1148   for (size_t i = 0; i < arraysize(kSampleRates); i++) {
1149     Init(kSampleRates[i], kSampleRates[i], kSampleRates[i], 2, 2, 2, false);
1150     SetFrameTo(&frame_, 1000, 2000);
1151     Int16FrameData frame_copy;
1152     frame_copy.CopyFrom(frame_);
1153     for (int j = 0; j < 1000; j++) {
1154       EXPECT_EQ(apm_->kNoError,
1155                 apm_->ProcessStream(
1156                     frame_.data.data(),
1157                     StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1158                     StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1159                     frame_.data.data()));
1160       EXPECT_TRUE(FrameDataAreEqual(frame_, frame_copy));
1161       EXPECT_EQ(apm_->kNoError,
1162                 apm_->ProcessReverseStream(
1163                     frame_.data.data(),
1164                     StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1165                     StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1166                     frame_.data.data()));
1167       EXPECT_TRUE(FrameDataAreEqual(frame_, frame_copy));
1168     }
1169   }
1170 }
1171 
TEST_F(ApmTest,NoProcessingWhenAllComponentsDisabledFloat)1172 TEST_F(ApmTest, NoProcessingWhenAllComponentsDisabledFloat) {
1173   // Test that ProcessStream copies input to output even with no processing.
1174   const size_t kSamples = 160;
1175   const int sample_rate = 16000;
1176   const float src[kSamples] = {-1.0f, 0.0f, 1.0f};
1177   float dest[kSamples] = {};
1178 
1179   auto src_channels = &src[0];
1180   auto dest_channels = &dest[0];
1181 
1182   apm_.reset(AudioProcessingBuilderForTesting().Create());
1183   EXPECT_NOERR(apm_->ProcessStream(&src_channels, StreamConfig(sample_rate, 1),
1184                                    StreamConfig(sample_rate, 1),
1185                                    &dest_channels));
1186 
1187   for (size_t i = 0; i < kSamples; ++i) {
1188     EXPECT_EQ(src[i], dest[i]);
1189   }
1190 
1191   // Same for ProcessReverseStream.
1192   float rev_dest[kSamples] = {};
1193   auto rev_dest_channels = &rev_dest[0];
1194 
1195   StreamConfig input_stream = {sample_rate, 1};
1196   StreamConfig output_stream = {sample_rate, 1};
1197   EXPECT_NOERR(apm_->ProcessReverseStream(&src_channels, input_stream,
1198                                           output_stream, &rev_dest_channels));
1199 
1200   for (size_t i = 0; i < kSamples; ++i) {
1201     EXPECT_EQ(src[i], rev_dest[i]);
1202   }
1203 }
1204 
TEST_F(ApmTest,IdenticalInputChannelsResultInIdenticalOutputChannels)1205 TEST_F(ApmTest, IdenticalInputChannelsResultInIdenticalOutputChannels) {
1206   EnableAllComponents();
1207 
1208   for (size_t i = 0; i < arraysize(kProcessSampleRates); i++) {
1209     Init(kProcessSampleRates[i], kProcessSampleRates[i], kProcessSampleRates[i],
1210          2, 2, 2, false);
1211     int analog_level = 127;
1212     ASSERT_EQ(0, feof(far_file_));
1213     ASSERT_EQ(0, feof(near_file_));
1214     while (ReadFrame(far_file_, &revframe_) && ReadFrame(near_file_, &frame_)) {
1215       CopyLeftToRightChannel(revframe_.data.data(),
1216                              revframe_.samples_per_channel);
1217 
1218       ASSERT_EQ(
1219           kNoErr,
1220           apm_->ProcessReverseStream(
1221               revframe_.data.data(),
1222               StreamConfig(revframe_.sample_rate_hz, revframe_.num_channels),
1223               StreamConfig(revframe_.sample_rate_hz, revframe_.num_channels),
1224               revframe_.data.data()));
1225 
1226       CopyLeftToRightChannel(frame_.data.data(), frame_.samples_per_channel);
1227 
1228       ASSERT_EQ(kNoErr, apm_->set_stream_delay_ms(0));
1229       apm_->set_stream_analog_level(analog_level);
1230       ASSERT_EQ(kNoErr,
1231                 apm_->ProcessStream(
1232                     frame_.data.data(),
1233                     StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1234                     StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1235                     frame_.data.data()));
1236       analog_level = apm_->recommended_stream_analog_level();
1237 
1238       VerifyChannelsAreEqual(frame_.data.data(), frame_.samples_per_channel);
1239     }
1240     rewind(far_file_);
1241     rewind(near_file_);
1242   }
1243 }
1244 
TEST_F(ApmTest,SplittingFilter)1245 TEST_F(ApmTest, SplittingFilter) {
1246   // Verify the filter is not active through undistorted audio when:
1247   // 1. No components are enabled...
1248   SetFrameTo(&frame_, 1000);
1249   Int16FrameData frame_copy;
1250   frame_copy.CopyFrom(frame_);
1251   EXPECT_EQ(apm_->kNoError,
1252             apm_->ProcessStream(
1253                 frame_.data.data(),
1254                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1255                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1256                 frame_.data.data()));
1257   EXPECT_EQ(apm_->kNoError,
1258             apm_->ProcessStream(
1259                 frame_.data.data(),
1260                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1261                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1262                 frame_.data.data()));
1263   EXPECT_TRUE(FrameDataAreEqual(frame_, frame_copy));
1264 
1265   // 2. Only the level estimator is enabled...
1266   auto apm_config = apm_->GetConfig();
1267   SetFrameTo(&frame_, 1000);
1268   frame_copy.CopyFrom(frame_);
1269   apm_config.level_estimation.enabled = true;
1270   apm_->ApplyConfig(apm_config);
1271   EXPECT_EQ(apm_->kNoError,
1272             apm_->ProcessStream(
1273                 frame_.data.data(),
1274                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1275                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1276                 frame_.data.data()));
1277   EXPECT_EQ(apm_->kNoError,
1278             apm_->ProcessStream(
1279                 frame_.data.data(),
1280                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1281                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1282                 frame_.data.data()));
1283   EXPECT_TRUE(FrameDataAreEqual(frame_, frame_copy));
1284   apm_config.level_estimation.enabled = false;
1285   apm_->ApplyConfig(apm_config);
1286 
1287   // 3. Only GetStatistics-reporting VAD is enabled...
1288   SetFrameTo(&frame_, 1000);
1289   frame_copy.CopyFrom(frame_);
1290   apm_config.voice_detection.enabled = true;
1291   apm_->ApplyConfig(apm_config);
1292   EXPECT_EQ(apm_->kNoError,
1293             apm_->ProcessStream(
1294                 frame_.data.data(),
1295                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1296                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1297                 frame_.data.data()));
1298   EXPECT_EQ(apm_->kNoError,
1299             apm_->ProcessStream(
1300                 frame_.data.data(),
1301                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1302                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1303                 frame_.data.data()));
1304   EXPECT_TRUE(FrameDataAreEqual(frame_, frame_copy));
1305   apm_config.voice_detection.enabled = false;
1306   apm_->ApplyConfig(apm_config);
1307 
1308   // 4. Both the VAD and the level estimator are enabled...
1309   SetFrameTo(&frame_, 1000);
1310   frame_copy.CopyFrom(frame_);
1311   apm_config.voice_detection.enabled = true;
1312   apm_config.level_estimation.enabled = true;
1313   apm_->ApplyConfig(apm_config);
1314   EXPECT_EQ(apm_->kNoError,
1315             apm_->ProcessStream(
1316                 frame_.data.data(),
1317                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1318                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1319                 frame_.data.data()));
1320   EXPECT_EQ(apm_->kNoError,
1321             apm_->ProcessStream(
1322                 frame_.data.data(),
1323                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1324                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1325                 frame_.data.data()));
1326   EXPECT_TRUE(FrameDataAreEqual(frame_, frame_copy));
1327   apm_config.voice_detection.enabled = false;
1328   apm_config.level_estimation.enabled = false;
1329   apm_->ApplyConfig(apm_config);
1330 
1331   // Check the test is valid. We should have distortion from the filter
1332   // when AEC is enabled (which won't affect the audio).
1333   apm_config.echo_canceller.enabled = true;
1334   apm_config.echo_canceller.mobile_mode = false;
1335   apm_->ApplyConfig(apm_config);
1336   frame_.samples_per_channel = 320;
1337   frame_.num_channels = 2;
1338   frame_.sample_rate_hz = 32000;
1339   SetFrameTo(&frame_, 1000);
1340   frame_copy.CopyFrom(frame_);
1341   EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0));
1342   EXPECT_EQ(apm_->kNoError,
1343             apm_->ProcessStream(
1344                 frame_.data.data(),
1345                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1346                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1347                 frame_.data.data()));
1348   EXPECT_FALSE(FrameDataAreEqual(frame_, frame_copy));
1349 }
1350 
1351 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
ProcessDebugDump(const std::string & in_filename,const std::string & out_filename,Format format,int max_size_bytes)1352 void ApmTest::ProcessDebugDump(const std::string& in_filename,
1353                                const std::string& out_filename,
1354                                Format format,
1355                                int max_size_bytes) {
1356   TaskQueueForTest worker_queue("ApmTest_worker_queue");
1357   FILE* in_file = fopen(in_filename.c_str(), "rb");
1358   ASSERT_TRUE(in_file != NULL);
1359   audioproc::Event event_msg;
1360   bool first_init = true;
1361 
1362   while (ReadMessageFromFile(in_file, &event_msg)) {
1363     if (event_msg.type() == audioproc::Event::INIT) {
1364       const audioproc::Init msg = event_msg.init();
1365       int reverse_sample_rate = msg.sample_rate();
1366       if (msg.has_reverse_sample_rate()) {
1367         reverse_sample_rate = msg.reverse_sample_rate();
1368       }
1369       int output_sample_rate = msg.sample_rate();
1370       if (msg.has_output_sample_rate()) {
1371         output_sample_rate = msg.output_sample_rate();
1372       }
1373 
1374       Init(msg.sample_rate(), output_sample_rate, reverse_sample_rate,
1375            msg.num_input_channels(), msg.num_output_channels(),
1376            msg.num_reverse_channels(), false);
1377       if (first_init) {
1378         // AttachAecDump() writes an additional init message. Don't start
1379         // recording until after the first init to avoid the extra message.
1380         auto aec_dump =
1381             AecDumpFactory::Create(out_filename, max_size_bytes, &worker_queue);
1382         EXPECT_TRUE(aec_dump);
1383         apm_->AttachAecDump(std::move(aec_dump));
1384         first_init = false;
1385       }
1386 
1387     } else if (event_msg.type() == audioproc::Event::REVERSE_STREAM) {
1388       const audioproc::ReverseStream msg = event_msg.reverse_stream();
1389 
1390       if (msg.channel_size() > 0) {
1391         ASSERT_EQ(revframe_.num_channels,
1392                   static_cast<size_t>(msg.channel_size()));
1393         for (int i = 0; i < msg.channel_size(); ++i) {
1394           memcpy(revfloat_cb_->channels()[i], msg.channel(i).data(),
1395                  msg.channel(i).size());
1396         }
1397       } else {
1398         memcpy(revframe_.data.data(), msg.data().data(), msg.data().size());
1399         if (format == kFloatFormat) {
1400           // We're using an int16 input file; convert to float.
1401           ConvertToFloat(revframe_, revfloat_cb_.get());
1402         }
1403       }
1404       AnalyzeReverseStreamChooser(format);
1405 
1406     } else if (event_msg.type() == audioproc::Event::STREAM) {
1407       const audioproc::Stream msg = event_msg.stream();
1408       // ProcessStream could have changed this for the output frame.
1409       frame_.num_channels = apm_->num_input_channels();
1410 
1411       apm_->set_stream_analog_level(msg.level());
1412       EXPECT_NOERR(apm_->set_stream_delay_ms(msg.delay()));
1413       if (msg.has_keypress()) {
1414         apm_->set_stream_key_pressed(msg.keypress());
1415       } else {
1416         apm_->set_stream_key_pressed(true);
1417       }
1418 
1419       if (msg.input_channel_size() > 0) {
1420         ASSERT_EQ(frame_.num_channels,
1421                   static_cast<size_t>(msg.input_channel_size()));
1422         for (int i = 0; i < msg.input_channel_size(); ++i) {
1423           memcpy(float_cb_->channels()[i], msg.input_channel(i).data(),
1424                  msg.input_channel(i).size());
1425         }
1426       } else {
1427         memcpy(frame_.data.data(), msg.input_data().data(),
1428                msg.input_data().size());
1429         if (format == kFloatFormat) {
1430           // We're using an int16 input file; convert to float.
1431           ConvertToFloat(frame_, float_cb_.get());
1432         }
1433       }
1434       ProcessStreamChooser(format);
1435     }
1436   }
1437   apm_->DetachAecDump();
1438   fclose(in_file);
1439 }
1440 
VerifyDebugDumpTest(Format format)1441 void ApmTest::VerifyDebugDumpTest(Format format) {
1442   rtc::ScopedFakeClock fake_clock;
1443   const std::string in_filename = test::ResourcePath("ref03", "aecdump");
1444   std::string format_string;
1445   switch (format) {
1446     case kIntFormat:
1447       format_string = "_int";
1448       break;
1449     case kFloatFormat:
1450       format_string = "_float";
1451       break;
1452   }
1453   const std::string ref_filename = test::TempFilename(
1454       test::OutputPath(), std::string("ref") + format_string + "_aecdump");
1455   const std::string out_filename = test::TempFilename(
1456       test::OutputPath(), std::string("out") + format_string + "_aecdump");
1457   const std::string limited_filename = test::TempFilename(
1458       test::OutputPath(), std::string("limited") + format_string + "_aecdump");
1459   const size_t logging_limit_bytes = 100000;
1460   // We expect at least this many bytes in the created logfile.
1461   const size_t logging_expected_bytes = 95000;
1462   EnableAllComponents();
1463   ProcessDebugDump(in_filename, ref_filename, format, -1);
1464   ProcessDebugDump(ref_filename, out_filename, format, -1);
1465   ProcessDebugDump(ref_filename, limited_filename, format, logging_limit_bytes);
1466 
1467   FILE* ref_file = fopen(ref_filename.c_str(), "rb");
1468   FILE* out_file = fopen(out_filename.c_str(), "rb");
1469   FILE* limited_file = fopen(limited_filename.c_str(), "rb");
1470   ASSERT_TRUE(ref_file != NULL);
1471   ASSERT_TRUE(out_file != NULL);
1472   ASSERT_TRUE(limited_file != NULL);
1473   std::unique_ptr<uint8_t[]> ref_bytes;
1474   std::unique_ptr<uint8_t[]> out_bytes;
1475   std::unique_ptr<uint8_t[]> limited_bytes;
1476 
1477   size_t ref_size = ReadMessageBytesFromFile(ref_file, &ref_bytes);
1478   size_t out_size = ReadMessageBytesFromFile(out_file, &out_bytes);
1479   size_t limited_size = ReadMessageBytesFromFile(limited_file, &limited_bytes);
1480   size_t bytes_read = 0;
1481   size_t bytes_read_limited = 0;
1482   while (ref_size > 0 && out_size > 0) {
1483     bytes_read += ref_size;
1484     bytes_read_limited += limited_size;
1485     EXPECT_EQ(ref_size, out_size);
1486     EXPECT_GE(ref_size, limited_size);
1487     EXPECT_EQ(0, memcmp(ref_bytes.get(), out_bytes.get(), ref_size));
1488     EXPECT_EQ(0, memcmp(ref_bytes.get(), limited_bytes.get(), limited_size));
1489     ref_size = ReadMessageBytesFromFile(ref_file, &ref_bytes);
1490     out_size = ReadMessageBytesFromFile(out_file, &out_bytes);
1491     limited_size = ReadMessageBytesFromFile(limited_file, &limited_bytes);
1492   }
1493   EXPECT_GT(bytes_read, 0u);
1494   EXPECT_GT(bytes_read_limited, logging_expected_bytes);
1495   EXPECT_LE(bytes_read_limited, logging_limit_bytes);
1496   EXPECT_NE(0, feof(ref_file));
1497   EXPECT_NE(0, feof(out_file));
1498   EXPECT_NE(0, feof(limited_file));
1499   ASSERT_EQ(0, fclose(ref_file));
1500   ASSERT_EQ(0, fclose(out_file));
1501   ASSERT_EQ(0, fclose(limited_file));
1502   remove(ref_filename.c_str());
1503   remove(out_filename.c_str());
1504   remove(limited_filename.c_str());
1505 }
1506 
TEST_F(ApmTest,VerifyDebugDumpInt)1507 TEST_F(ApmTest, VerifyDebugDumpInt) {
1508   VerifyDebugDumpTest(kIntFormat);
1509 }
1510 
TEST_F(ApmTest,VerifyDebugDumpFloat)1511 TEST_F(ApmTest, VerifyDebugDumpFloat) {
1512   VerifyDebugDumpTest(kFloatFormat);
1513 }
1514 #endif
1515 
1516 // TODO(andrew): expand test to verify output.
TEST_F(ApmTest,DebugDump)1517 TEST_F(ApmTest, DebugDump) {
1518   TaskQueueForTest worker_queue("ApmTest_worker_queue");
1519   const std::string filename =
1520       test::TempFilename(test::OutputPath(), "debug_aec");
1521   {
1522     auto aec_dump = AecDumpFactory::Create("", -1, &worker_queue);
1523     EXPECT_FALSE(aec_dump);
1524   }
1525 
1526 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
1527   // Stopping without having started should be OK.
1528   apm_->DetachAecDump();
1529 
1530   auto aec_dump = AecDumpFactory::Create(filename, -1, &worker_queue);
1531   EXPECT_TRUE(aec_dump);
1532   apm_->AttachAecDump(std::move(aec_dump));
1533   EXPECT_EQ(apm_->kNoError,
1534             apm_->ProcessStream(
1535                 frame_.data.data(),
1536                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1537                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1538                 frame_.data.data()));
1539   EXPECT_EQ(apm_->kNoError,
1540             apm_->ProcessReverseStream(
1541                 revframe_.data.data(),
1542                 StreamConfig(revframe_.sample_rate_hz, revframe_.num_channels),
1543                 StreamConfig(revframe_.sample_rate_hz, revframe_.num_channels),
1544                 revframe_.data.data()));
1545   apm_->DetachAecDump();
1546 
1547   // Verify the file has been written.
1548   FILE* fid = fopen(filename.c_str(), "r");
1549   ASSERT_TRUE(fid != NULL);
1550 
1551   // Clean it up.
1552   ASSERT_EQ(0, fclose(fid));
1553   ASSERT_EQ(0, remove(filename.c_str()));
1554 #else
1555   // Verify the file has NOT been written.
1556   ASSERT_TRUE(fopen(filename.c_str(), "r") == NULL);
1557 #endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
1558 }
1559 
1560 // TODO(andrew): expand test to verify output.
TEST_F(ApmTest,DebugDumpFromFileHandle)1561 TEST_F(ApmTest, DebugDumpFromFileHandle) {
1562   TaskQueueForTest worker_queue("ApmTest_worker_queue");
1563 
1564   const std::string filename =
1565       test::TempFilename(test::OutputPath(), "debug_aec");
1566   FileWrapper f = FileWrapper::OpenWriteOnly(filename.c_str());
1567   ASSERT_TRUE(f.is_open());
1568 
1569 #ifdef WEBRTC_AUDIOPROC_DEBUG_DUMP
1570   // Stopping without having started should be OK.
1571   apm_->DetachAecDump();
1572 
1573   auto aec_dump = AecDumpFactory::Create(std::move(f), -1, &worker_queue);
1574   EXPECT_TRUE(aec_dump);
1575   apm_->AttachAecDump(std::move(aec_dump));
1576   EXPECT_EQ(apm_->kNoError,
1577             apm_->ProcessReverseStream(
1578                 revframe_.data.data(),
1579                 StreamConfig(revframe_.sample_rate_hz, revframe_.num_channels),
1580                 StreamConfig(revframe_.sample_rate_hz, revframe_.num_channels),
1581                 revframe_.data.data()));
1582   EXPECT_EQ(apm_->kNoError,
1583             apm_->ProcessStream(
1584                 frame_.data.data(),
1585                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1586                 StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1587                 frame_.data.data()));
1588   apm_->DetachAecDump();
1589 
1590   // Verify the file has been written.
1591   FILE* fid = fopen(filename.c_str(), "r");
1592   ASSERT_TRUE(fid != NULL);
1593 
1594   // Clean it up.
1595   ASSERT_EQ(0, fclose(fid));
1596   ASSERT_EQ(0, remove(filename.c_str()));
1597 #endif  // WEBRTC_AUDIOPROC_DEBUG_DUMP
1598 }
1599 
1600 // TODO(andrew): Add a test to process a few frames with different combinations
1601 // of enabled components.
1602 
TEST_F(ApmTest,Process)1603 TEST_F(ApmTest, Process) {
1604   GOOGLE_PROTOBUF_VERIFY_VERSION;
1605   audioproc::OutputData ref_data;
1606 
1607   if (!absl::GetFlag(FLAGS_write_apm_ref_data)) {
1608     OpenFileAndReadMessage(ref_filename_, &ref_data);
1609   } else {
1610     // Write the desired tests to the protobuf reference file.
1611     for (size_t i = 0; i < arraysize(kChannels); i++) {
1612       for (size_t j = 0; j < arraysize(kChannels); j++) {
1613         for (size_t l = 0; l < arraysize(kProcessSampleRates); l++) {
1614           audioproc::Test* test = ref_data.add_test();
1615           test->set_num_reverse_channels(kChannels[i]);
1616           test->set_num_input_channels(kChannels[j]);
1617           test->set_num_output_channels(kChannels[j]);
1618           test->set_sample_rate(kProcessSampleRates[l]);
1619           test->set_use_aec_extended_filter(false);
1620         }
1621       }
1622     }
1623 #if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
1624     // To test the extended filter mode.
1625     audioproc::Test* test = ref_data.add_test();
1626     test->set_num_reverse_channels(2);
1627     test->set_num_input_channels(2);
1628     test->set_num_output_channels(2);
1629     test->set_sample_rate(AudioProcessing::kSampleRate32kHz);
1630     test->set_use_aec_extended_filter(true);
1631 #endif
1632   }
1633 
1634   for (int i = 0; i < ref_data.test_size(); i++) {
1635     printf("Running test %d of %d...\n", i + 1, ref_data.test_size());
1636 
1637     audioproc::Test* test = ref_data.mutable_test(i);
1638     // TODO(ajm): We no longer allow different input and output channels. Skip
1639     // these tests for now, but they should be removed from the set.
1640     if (test->num_input_channels() != test->num_output_channels())
1641       continue;
1642 
1643     apm_.reset(AudioProcessingBuilderForTesting().Create());
1644     AudioProcessing::Config apm_config = apm_->GetConfig();
1645     apm_config.gain_controller1.analog_gain_controller.enabled = false;
1646     apm_->ApplyConfig(apm_config);
1647 
1648     EnableAllComponents();
1649 
1650     Init(test->sample_rate(), test->sample_rate(), test->sample_rate(),
1651          static_cast<size_t>(test->num_input_channels()),
1652          static_cast<size_t>(test->num_output_channels()),
1653          static_cast<size_t>(test->num_reverse_channels()), true);
1654 
1655     int frame_count = 0;
1656     int has_voice_count = 0;
1657     int analog_level = 127;
1658     int analog_level_average = 0;
1659     int max_output_average = 0;
1660     float rms_dbfs_average = 0.0f;
1661 #if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
1662     int stats_index = 0;
1663 #endif
1664 
1665     while (ReadFrame(far_file_, &revframe_) && ReadFrame(near_file_, &frame_)) {
1666       EXPECT_EQ(
1667           apm_->kNoError,
1668           apm_->ProcessReverseStream(
1669               revframe_.data.data(),
1670               StreamConfig(revframe_.sample_rate_hz, revframe_.num_channels),
1671               StreamConfig(revframe_.sample_rate_hz, revframe_.num_channels),
1672               revframe_.data.data()));
1673 
1674       EXPECT_EQ(apm_->kNoError, apm_->set_stream_delay_ms(0));
1675       apm_->set_stream_analog_level(analog_level);
1676 
1677       EXPECT_EQ(apm_->kNoError,
1678                 apm_->ProcessStream(
1679                     frame_.data.data(),
1680                     StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1681                     StreamConfig(frame_.sample_rate_hz, frame_.num_channels),
1682                     frame_.data.data()));
1683 
1684       // Ensure the frame was downmixed properly.
1685       EXPECT_EQ(static_cast<size_t>(test->num_output_channels()),
1686                 frame_.num_channels);
1687 
1688       max_output_average += MaxAudioFrame(frame_);
1689 
1690       analog_level = apm_->recommended_stream_analog_level();
1691       analog_level_average += analog_level;
1692       AudioProcessingStats stats = apm_->GetStatistics();
1693       EXPECT_TRUE(stats.voice_detected);
1694       EXPECT_TRUE(stats.output_rms_dbfs);
1695       has_voice_count += *stats.voice_detected ? 1 : 0;
1696       rms_dbfs_average += *stats.output_rms_dbfs;
1697 
1698       size_t frame_size = frame_.samples_per_channel * frame_.num_channels;
1699       size_t write_count =
1700           fwrite(frame_.data.data(), sizeof(int16_t), frame_size, out_file_);
1701       ASSERT_EQ(frame_size, write_count);
1702 
1703       // Reset in case of downmixing.
1704       frame_.num_channels = static_cast<size_t>(test->num_input_channels());
1705       frame_count++;
1706 
1707 #if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
1708       const int kStatsAggregationFrameNum = 100;  // 1 second.
1709       if (frame_count % kStatsAggregationFrameNum == 0) {
1710         // Get echo and delay metrics.
1711         AudioProcessingStats stats = apm_->GetStatistics();
1712 
1713         // Echo metrics.
1714         const float echo_return_loss = stats.echo_return_loss.value_or(-1.0f);
1715         const float echo_return_loss_enhancement =
1716             stats.echo_return_loss_enhancement.value_or(-1.0f);
1717         const float residual_echo_likelihood =
1718             stats.residual_echo_likelihood.value_or(-1.0f);
1719         const float residual_echo_likelihood_recent_max =
1720             stats.residual_echo_likelihood_recent_max.value_or(-1.0f);
1721 
1722         if (!absl::GetFlag(FLAGS_write_apm_ref_data)) {
1723           const audioproc::Test::EchoMetrics& reference =
1724               test->echo_metrics(stats_index);
1725           constexpr float kEpsilon = 0.01;
1726           EXPECT_NEAR(echo_return_loss, reference.echo_return_loss(), kEpsilon);
1727           EXPECT_NEAR(echo_return_loss_enhancement,
1728                       reference.echo_return_loss_enhancement(), kEpsilon);
1729           EXPECT_NEAR(residual_echo_likelihood,
1730                       reference.residual_echo_likelihood(), kEpsilon);
1731           EXPECT_NEAR(residual_echo_likelihood_recent_max,
1732                       reference.residual_echo_likelihood_recent_max(),
1733                       kEpsilon);
1734           ++stats_index;
1735         } else {
1736           audioproc::Test::EchoMetrics* message_echo = test->add_echo_metrics();
1737           message_echo->set_echo_return_loss(echo_return_loss);
1738           message_echo->set_echo_return_loss_enhancement(
1739               echo_return_loss_enhancement);
1740           message_echo->set_residual_echo_likelihood(residual_echo_likelihood);
1741           message_echo->set_residual_echo_likelihood_recent_max(
1742               residual_echo_likelihood_recent_max);
1743         }
1744       }
1745 #endif  // defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE).
1746     }
1747     max_output_average /= frame_count;
1748     analog_level_average /= frame_count;
1749     rms_dbfs_average /= frame_count;
1750 
1751     if (!absl::GetFlag(FLAGS_write_apm_ref_data)) {
1752       const int kIntNear = 1;
1753       // When running the test on a N7 we get a {2, 6} difference of
1754       // |has_voice_count| and |max_output_average| is up to 18 higher.
1755       // All numbers being consistently higher on N7 compare to ref_data.
1756       // TODO(bjornv): If we start getting more of these offsets on Android we
1757       // should consider a different approach. Either using one slack for all,
1758       // or generate a separate android reference.
1759 #if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
1760       const int kHasVoiceCountOffset = 3;
1761       const int kHasVoiceCountNear = 8;
1762       const int kMaxOutputAverageOffset = 9;
1763       const int kMaxOutputAverageNear = 26;
1764 #else
1765       const int kHasVoiceCountOffset = 0;
1766       const int kHasVoiceCountNear = kIntNear;
1767       const int kMaxOutputAverageOffset = 0;
1768       const int kMaxOutputAverageNear = kIntNear;
1769 #endif
1770       EXPECT_NEAR(test->has_voice_count(),
1771                   has_voice_count - kHasVoiceCountOffset, kHasVoiceCountNear);
1772 
1773       EXPECT_NEAR(test->analog_level_average(), analog_level_average, kIntNear);
1774       EXPECT_NEAR(test->max_output_average(),
1775                   max_output_average - kMaxOutputAverageOffset,
1776                   kMaxOutputAverageNear);
1777 #if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
1778       const double kFloatNear = 0.0005;
1779       EXPECT_NEAR(test->rms_dbfs_average(), rms_dbfs_average, kFloatNear);
1780 #endif
1781     } else {
1782       test->set_has_voice_count(has_voice_count);
1783 
1784       test->set_analog_level_average(analog_level_average);
1785       test->set_max_output_average(max_output_average);
1786 
1787 #if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
1788       test->set_rms_dbfs_average(rms_dbfs_average);
1789 #endif
1790     }
1791 
1792     rewind(far_file_);
1793     rewind(near_file_);
1794   }
1795 
1796   if (absl::GetFlag(FLAGS_write_apm_ref_data)) {
1797     OpenFileAndWriteMessage(ref_filename_, ref_data);
1798   }
1799 }
1800 
TEST_F(ApmTest,NoErrorsWithKeyboardChannel)1801 TEST_F(ApmTest, NoErrorsWithKeyboardChannel) {
1802   struct ChannelFormat {
1803     AudioProcessing::ChannelLayout in_layout;
1804     AudioProcessing::ChannelLayout out_layout;
1805   };
1806   ChannelFormat cf[] = {
1807       {AudioProcessing::kMonoAndKeyboard, AudioProcessing::kMono},
1808       {AudioProcessing::kStereoAndKeyboard, AudioProcessing::kMono},
1809       {AudioProcessing::kStereoAndKeyboard, AudioProcessing::kStereo},
1810   };
1811 
1812   std::unique_ptr<AudioProcessing> ap(
1813       AudioProcessingBuilderForTesting().Create());
1814   // Enable one component just to ensure some processing takes place.
1815   AudioProcessing::Config config;
1816   config.noise_suppression.enabled = true;
1817   ap->ApplyConfig(config);
1818   for (size_t i = 0; i < arraysize(cf); ++i) {
1819     const int in_rate = 44100;
1820     const int out_rate = 48000;
1821     ChannelBuffer<float> in_cb(SamplesFromRate(in_rate),
1822                                TotalChannelsFromLayout(cf[i].in_layout));
1823     ChannelBuffer<float> out_cb(SamplesFromRate(out_rate),
1824                                 ChannelsFromLayout(cf[i].out_layout));
1825     bool has_keyboard = cf[i].in_layout == AudioProcessing::kMonoAndKeyboard ||
1826                         cf[i].in_layout == AudioProcessing::kStereoAndKeyboard;
1827     StreamConfig in_sc(in_rate, ChannelsFromLayout(cf[i].in_layout),
1828                        has_keyboard);
1829     StreamConfig out_sc(out_rate, ChannelsFromLayout(cf[i].out_layout));
1830 
1831     // Run over a few chunks.
1832     for (int j = 0; j < 10; ++j) {
1833       EXPECT_NOERR(ap->ProcessStream(in_cb.channels(), in_sc, out_sc,
1834                                      out_cb.channels()));
1835     }
1836   }
1837 }
1838 
1839 // Compares the reference and test arrays over a region around the expected
1840 // delay. Finds the highest SNR in that region and adds the variance and squared
1841 // error results to the supplied accumulators.
UpdateBestSNR(const float * ref,const float * test,size_t length,int expected_delay,double * variance_acc,double * sq_error_acc)1842 void UpdateBestSNR(const float* ref,
1843                    const float* test,
1844                    size_t length,
1845                    int expected_delay,
1846                    double* variance_acc,
1847                    double* sq_error_acc) {
1848   double best_snr = std::numeric_limits<double>::min();
1849   double best_variance = 0;
1850   double best_sq_error = 0;
1851   // Search over a region of eight samples around the expected delay.
1852   for (int delay = std::max(expected_delay - 4, 0); delay <= expected_delay + 4;
1853        ++delay) {
1854     double sq_error = 0;
1855     double variance = 0;
1856     for (size_t i = 0; i < length - delay; ++i) {
1857       double error = test[i + delay] - ref[i];
1858       sq_error += error * error;
1859       variance += ref[i] * ref[i];
1860     }
1861 
1862     if (sq_error == 0) {
1863       *variance_acc += variance;
1864       return;
1865     }
1866     double snr = variance / sq_error;
1867     if (snr > best_snr) {
1868       best_snr = snr;
1869       best_variance = variance;
1870       best_sq_error = sq_error;
1871     }
1872   }
1873 
1874   *variance_acc += best_variance;
1875   *sq_error_acc += best_sq_error;
1876 }
1877 
1878 // Used to test a multitude of sample rate and channel combinations. It works
1879 // by first producing a set of reference files (in SetUpTestCase) that are
1880 // assumed to be correct, as the used parameters are verified by other tests
1881 // in this collection. Primarily the reference files are all produced at
1882 // "native" rates which do not involve any resampling.
1883 
1884 // Each test pass produces an output file with a particular format. The output
1885 // is matched against the reference file closest to its internal processing
1886 // format. If necessary the output is resampled back to its process format.
1887 // Due to the resampling distortion, we don't expect identical results, but
1888 // enforce SNR thresholds which vary depending on the format. 0 is a special
1889 // case SNR which corresponds to inf, or zero error.
1890 typedef std::tuple<int, int, int, int, double, double> AudioProcessingTestData;
1891 class AudioProcessingTest
1892     : public ::testing::TestWithParam<AudioProcessingTestData> {
1893  public:
AudioProcessingTest()1894   AudioProcessingTest()
1895       : input_rate_(std::get<0>(GetParam())),
1896         output_rate_(std::get<1>(GetParam())),
1897         reverse_input_rate_(std::get<2>(GetParam())),
1898         reverse_output_rate_(std::get<3>(GetParam())),
1899         expected_snr_(std::get<4>(GetParam())),
1900         expected_reverse_snr_(std::get<5>(GetParam())) {}
1901 
~AudioProcessingTest()1902   virtual ~AudioProcessingTest() {}
1903 
SetUpTestSuite()1904   static void SetUpTestSuite() {
1905     // Create all needed output reference files.
1906     const int kNativeRates[] = {8000, 16000, 32000, 48000};
1907     const size_t kNumChannels[] = {1, 2};
1908     for (size_t i = 0; i < arraysize(kNativeRates); ++i) {
1909       for (size_t j = 0; j < arraysize(kNumChannels); ++j) {
1910         for (size_t k = 0; k < arraysize(kNumChannels); ++k) {
1911           // The reference files always have matching input and output channels.
1912           ProcessFormat(kNativeRates[i], kNativeRates[i], kNativeRates[i],
1913                         kNativeRates[i], kNumChannels[j], kNumChannels[j],
1914                         kNumChannels[k], kNumChannels[k], "ref");
1915         }
1916       }
1917     }
1918   }
1919 
TearDown()1920   void TearDown() {
1921     // Remove "out" files after each test.
1922     ClearTempOutFiles();
1923   }
1924 
TearDownTestSuite()1925   static void TearDownTestSuite() { ClearTempFiles(); }
1926 
1927   // Runs a process pass on files with the given parameters and dumps the output
1928   // to a file specified with |output_file_prefix|. Both forward and reverse
1929   // output streams are dumped.
ProcessFormat(int input_rate,int output_rate,int reverse_input_rate,int reverse_output_rate,size_t num_input_channels,size_t num_output_channels,size_t num_reverse_input_channels,size_t num_reverse_output_channels,const std::string & output_file_prefix)1930   static void ProcessFormat(int input_rate,
1931                             int output_rate,
1932                             int reverse_input_rate,
1933                             int reverse_output_rate,
1934                             size_t num_input_channels,
1935                             size_t num_output_channels,
1936                             size_t num_reverse_input_channels,
1937                             size_t num_reverse_output_channels,
1938                             const std::string& output_file_prefix) {
1939     std::unique_ptr<AudioProcessing> ap(
1940         AudioProcessingBuilderForTesting().Create());
1941     AudioProcessing::Config apm_config = ap->GetConfig();
1942     apm_config.gain_controller1.analog_gain_controller.enabled = false;
1943     ap->ApplyConfig(apm_config);
1944 
1945     EnableAllAPComponents(ap.get());
1946 
1947     ProcessingConfig processing_config = {
1948         {{input_rate, num_input_channels},
1949          {output_rate, num_output_channels},
1950          {reverse_input_rate, num_reverse_input_channels},
1951          {reverse_output_rate, num_reverse_output_channels}}};
1952     ap->Initialize(processing_config);
1953 
1954     FILE* far_file =
1955         fopen(ResourceFilePath("far", reverse_input_rate).c_str(), "rb");
1956     FILE* near_file = fopen(ResourceFilePath("near", input_rate).c_str(), "rb");
1957     FILE* out_file = fopen(
1958         OutputFilePath(
1959             output_file_prefix, input_rate, output_rate, reverse_input_rate,
1960             reverse_output_rate, num_input_channels, num_output_channels,
1961             num_reverse_input_channels, num_reverse_output_channels, kForward)
1962             .c_str(),
1963         "wb");
1964     FILE* rev_out_file = fopen(
1965         OutputFilePath(
1966             output_file_prefix, input_rate, output_rate, reverse_input_rate,
1967             reverse_output_rate, num_input_channels, num_output_channels,
1968             num_reverse_input_channels, num_reverse_output_channels, kReverse)
1969             .c_str(),
1970         "wb");
1971     ASSERT_TRUE(far_file != NULL);
1972     ASSERT_TRUE(near_file != NULL);
1973     ASSERT_TRUE(out_file != NULL);
1974     ASSERT_TRUE(rev_out_file != NULL);
1975 
1976     ChannelBuffer<float> fwd_cb(SamplesFromRate(input_rate),
1977                                 num_input_channels);
1978     ChannelBuffer<float> rev_cb(SamplesFromRate(reverse_input_rate),
1979                                 num_reverse_input_channels);
1980     ChannelBuffer<float> out_cb(SamplesFromRate(output_rate),
1981                                 num_output_channels);
1982     ChannelBuffer<float> rev_out_cb(SamplesFromRate(reverse_output_rate),
1983                                     num_reverse_output_channels);
1984 
1985     // Temporary buffers.
1986     const int max_length =
1987         2 * std::max(std::max(out_cb.num_frames(), rev_out_cb.num_frames()),
1988                      std::max(fwd_cb.num_frames(), rev_cb.num_frames()));
1989     std::unique_ptr<float[]> float_data(new float[max_length]);
1990     std::unique_ptr<int16_t[]> int_data(new int16_t[max_length]);
1991 
1992     int analog_level = 127;
1993     while (ReadChunk(far_file, int_data.get(), float_data.get(), &rev_cb) &&
1994            ReadChunk(near_file, int_data.get(), float_data.get(), &fwd_cb)) {
1995       EXPECT_NOERR(ap->ProcessReverseStream(
1996           rev_cb.channels(), processing_config.reverse_input_stream(),
1997           processing_config.reverse_output_stream(), rev_out_cb.channels()));
1998 
1999       EXPECT_NOERR(ap->set_stream_delay_ms(0));
2000       ap->set_stream_analog_level(analog_level);
2001 
2002       EXPECT_NOERR(ap->ProcessStream(
2003           fwd_cb.channels(), StreamConfig(input_rate, num_input_channels),
2004           StreamConfig(output_rate, num_output_channels), out_cb.channels()));
2005 
2006       // Dump forward output to file.
2007       Interleave(out_cb.channels(), out_cb.num_frames(), out_cb.num_channels(),
2008                  float_data.get());
2009       size_t out_length = out_cb.num_channels() * out_cb.num_frames();
2010 
2011       ASSERT_EQ(out_length, fwrite(float_data.get(), sizeof(float_data[0]),
2012                                    out_length, out_file));
2013 
2014       // Dump reverse output to file.
2015       Interleave(rev_out_cb.channels(), rev_out_cb.num_frames(),
2016                  rev_out_cb.num_channels(), float_data.get());
2017       size_t rev_out_length =
2018           rev_out_cb.num_channels() * rev_out_cb.num_frames();
2019 
2020       ASSERT_EQ(rev_out_length, fwrite(float_data.get(), sizeof(float_data[0]),
2021                                        rev_out_length, rev_out_file));
2022 
2023       analog_level = ap->recommended_stream_analog_level();
2024     }
2025     fclose(far_file);
2026     fclose(near_file);
2027     fclose(out_file);
2028     fclose(rev_out_file);
2029   }
2030 
2031  protected:
2032   int input_rate_;
2033   int output_rate_;
2034   int reverse_input_rate_;
2035   int reverse_output_rate_;
2036   double expected_snr_;
2037   double expected_reverse_snr_;
2038 };
2039 
TEST_P(AudioProcessingTest,Formats)2040 TEST_P(AudioProcessingTest, Formats) {
2041   struct ChannelFormat {
2042     int num_input;
2043     int num_output;
2044     int num_reverse_input;
2045     int num_reverse_output;
2046   };
2047   ChannelFormat cf[] = {
2048       {1, 1, 1, 1}, {1, 1, 2, 1}, {2, 1, 1, 1},
2049       {2, 1, 2, 1}, {2, 2, 1, 1}, {2, 2, 2, 2},
2050   };
2051 
2052   for (size_t i = 0; i < arraysize(cf); ++i) {
2053     ProcessFormat(input_rate_, output_rate_, reverse_input_rate_,
2054                   reverse_output_rate_, cf[i].num_input, cf[i].num_output,
2055                   cf[i].num_reverse_input, cf[i].num_reverse_output, "out");
2056 
2057     // Verify output for both directions.
2058     std::vector<StreamDirection> stream_directions;
2059     stream_directions.push_back(kForward);
2060     stream_directions.push_back(kReverse);
2061     for (StreamDirection file_direction : stream_directions) {
2062       const int in_rate = file_direction ? reverse_input_rate_ : input_rate_;
2063       const int out_rate = file_direction ? reverse_output_rate_ : output_rate_;
2064       const int out_num =
2065           file_direction ? cf[i].num_reverse_output : cf[i].num_output;
2066       const double expected_snr =
2067           file_direction ? expected_reverse_snr_ : expected_snr_;
2068 
2069       const int min_ref_rate = std::min(in_rate, out_rate);
2070       int ref_rate;
2071 
2072       if (min_ref_rate > 32000) {
2073         ref_rate = 48000;
2074       } else if (min_ref_rate > 16000) {
2075         ref_rate = 32000;
2076       } else if (min_ref_rate > 8000) {
2077         ref_rate = 16000;
2078       } else {
2079         ref_rate = 8000;
2080       }
2081 
2082       FILE* out_file = fopen(
2083           OutputFilePath("out", input_rate_, output_rate_, reverse_input_rate_,
2084                          reverse_output_rate_, cf[i].num_input,
2085                          cf[i].num_output, cf[i].num_reverse_input,
2086                          cf[i].num_reverse_output, file_direction)
2087               .c_str(),
2088           "rb");
2089       // The reference files always have matching input and output channels.
2090       FILE* ref_file =
2091           fopen(OutputFilePath("ref", ref_rate, ref_rate, ref_rate, ref_rate,
2092                                cf[i].num_output, cf[i].num_output,
2093                                cf[i].num_reverse_output,
2094                                cf[i].num_reverse_output, file_direction)
2095                     .c_str(),
2096                 "rb");
2097       ASSERT_TRUE(out_file != NULL);
2098       ASSERT_TRUE(ref_file != NULL);
2099 
2100       const size_t ref_length = SamplesFromRate(ref_rate) * out_num;
2101       const size_t out_length = SamplesFromRate(out_rate) * out_num;
2102       // Data from the reference file.
2103       std::unique_ptr<float[]> ref_data(new float[ref_length]);
2104       // Data from the output file.
2105       std::unique_ptr<float[]> out_data(new float[out_length]);
2106       // Data from the resampled output, in case the reference and output rates
2107       // don't match.
2108       std::unique_ptr<float[]> cmp_data(new float[ref_length]);
2109 
2110       PushResampler<float> resampler;
2111       resampler.InitializeIfNeeded(out_rate, ref_rate, out_num);
2112 
2113       // Compute the resampling delay of the output relative to the reference,
2114       // to find the region over which we should search for the best SNR.
2115       float expected_delay_sec = 0;
2116       if (in_rate != ref_rate) {
2117         // Input resampling delay.
2118         expected_delay_sec +=
2119             PushSincResampler::AlgorithmicDelaySeconds(in_rate);
2120       }
2121       if (out_rate != ref_rate) {
2122         // Output resampling delay.
2123         expected_delay_sec +=
2124             PushSincResampler::AlgorithmicDelaySeconds(ref_rate);
2125         // Delay of converting the output back to its processing rate for
2126         // testing.
2127         expected_delay_sec +=
2128             PushSincResampler::AlgorithmicDelaySeconds(out_rate);
2129       }
2130       int expected_delay =
2131           std::floor(expected_delay_sec * ref_rate + 0.5f) * out_num;
2132 
2133       double variance = 0;
2134       double sq_error = 0;
2135       while (fread(out_data.get(), sizeof(out_data[0]), out_length, out_file) &&
2136              fread(ref_data.get(), sizeof(ref_data[0]), ref_length, ref_file)) {
2137         float* out_ptr = out_data.get();
2138         if (out_rate != ref_rate) {
2139           // Resample the output back to its internal processing rate if
2140           // necssary.
2141           ASSERT_EQ(ref_length,
2142                     static_cast<size_t>(resampler.Resample(
2143                         out_ptr, out_length, cmp_data.get(), ref_length)));
2144           out_ptr = cmp_data.get();
2145         }
2146 
2147         // Update the |sq_error| and |variance| accumulators with the highest
2148         // SNR of reference vs output.
2149         UpdateBestSNR(ref_data.get(), out_ptr, ref_length, expected_delay,
2150                       &variance, &sq_error);
2151       }
2152 
2153       std::cout << "(" << input_rate_ << ", " << output_rate_ << ", "
2154                 << reverse_input_rate_ << ", " << reverse_output_rate_ << ", "
2155                 << cf[i].num_input << ", " << cf[i].num_output << ", "
2156                 << cf[i].num_reverse_input << ", " << cf[i].num_reverse_output
2157                 << ", " << file_direction << "): ";
2158       if (sq_error > 0) {
2159         double snr = 10 * log10(variance / sq_error);
2160         EXPECT_GE(snr, expected_snr);
2161         EXPECT_NE(0, expected_snr);
2162         std::cout << "SNR=" << snr << " dB" << std::endl;
2163       } else {
2164         std::cout << "SNR=inf dB" << std::endl;
2165       }
2166 
2167       fclose(out_file);
2168       fclose(ref_file);
2169     }
2170   }
2171 }
2172 
2173 #if defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
2174 INSTANTIATE_TEST_SUITE_P(
2175     CommonFormats,
2176     AudioProcessingTest,
2177     ::testing::Values(std::make_tuple(48000, 48000, 48000, 48000, 0, 0),
2178                       std::make_tuple(48000, 48000, 32000, 48000, 40, 30),
2179                       std::make_tuple(48000, 48000, 16000, 48000, 40, 20),
2180                       std::make_tuple(48000, 44100, 48000, 44100, 20, 20),
2181                       std::make_tuple(48000, 44100, 32000, 44100, 20, 15),
2182                       std::make_tuple(48000, 44100, 16000, 44100, 20, 15),
2183                       std::make_tuple(48000, 32000, 48000, 32000, 30, 35),
2184                       std::make_tuple(48000, 32000, 32000, 32000, 30, 0),
2185                       std::make_tuple(48000, 32000, 16000, 32000, 30, 20),
2186                       std::make_tuple(48000, 16000, 48000, 16000, 25, 20),
2187                       std::make_tuple(48000, 16000, 32000, 16000, 25, 20),
2188                       std::make_tuple(48000, 16000, 16000, 16000, 25, 0),
2189 
2190                       std::make_tuple(44100, 48000, 48000, 48000, 30, 0),
2191                       std::make_tuple(44100, 48000, 32000, 48000, 30, 30),
2192                       std::make_tuple(44100, 48000, 16000, 48000, 30, 20),
2193                       std::make_tuple(44100, 44100, 48000, 44100, 20, 20),
2194                       std::make_tuple(44100, 44100, 32000, 44100, 20, 15),
2195                       std::make_tuple(44100, 44100, 16000, 44100, 20, 15),
2196                       std::make_tuple(44100, 32000, 48000, 32000, 30, 35),
2197                       std::make_tuple(44100, 32000, 32000, 32000, 30, 0),
2198                       std::make_tuple(44100, 32000, 16000, 32000, 30, 20),
2199                       std::make_tuple(44100, 16000, 48000, 16000, 25, 20),
2200                       std::make_tuple(44100, 16000, 32000, 16000, 25, 20),
2201                       std::make_tuple(44100, 16000, 16000, 16000, 25, 0),
2202 
2203                       std::make_tuple(32000, 48000, 48000, 48000, 15, 0),
2204                       std::make_tuple(32000, 48000, 32000, 48000, 15, 30),
2205                       std::make_tuple(32000, 48000, 16000, 48000, 15, 20),
2206                       std::make_tuple(32000, 44100, 48000, 44100, 19, 20),
2207                       std::make_tuple(32000, 44100, 32000, 44100, 19, 15),
2208                       std::make_tuple(32000, 44100, 16000, 44100, 19, 15),
2209                       std::make_tuple(32000, 32000, 48000, 32000, 40, 35),
2210                       std::make_tuple(32000, 32000, 32000, 32000, 0, 0),
2211                       std::make_tuple(32000, 32000, 16000, 32000, 40, 20),
2212                       std::make_tuple(32000, 16000, 48000, 16000, 25, 20),
2213                       std::make_tuple(32000, 16000, 32000, 16000, 25, 20),
2214                       std::make_tuple(32000, 16000, 16000, 16000, 25, 0),
2215 
2216                       std::make_tuple(16000, 48000, 48000, 48000, 9, 0),
2217                       std::make_tuple(16000, 48000, 32000, 48000, 9, 30),
2218                       std::make_tuple(16000, 48000, 16000, 48000, 9, 20),
2219                       std::make_tuple(16000, 44100, 48000, 44100, 15, 20),
2220                       std::make_tuple(16000, 44100, 32000, 44100, 15, 15),
2221                       std::make_tuple(16000, 44100, 16000, 44100, 15, 15),
2222                       std::make_tuple(16000, 32000, 48000, 32000, 25, 35),
2223                       std::make_tuple(16000, 32000, 32000, 32000, 25, 0),
2224                       std::make_tuple(16000, 32000, 16000, 32000, 25, 20),
2225                       std::make_tuple(16000, 16000, 48000, 16000, 39, 20),
2226                       std::make_tuple(16000, 16000, 32000, 16000, 40, 20),
2227                       std::make_tuple(16000, 16000, 16000, 16000, 0, 0)));
2228 
2229 #elif defined(WEBRTC_AUDIOPROC_FIXED_PROFILE)
2230 INSTANTIATE_TEST_SUITE_P(
2231     CommonFormats,
2232     AudioProcessingTest,
2233     ::testing::Values(std::make_tuple(48000, 48000, 48000, 48000, 19, 0),
2234                       std::make_tuple(48000, 48000, 32000, 48000, 19, 30),
2235                       std::make_tuple(48000, 48000, 16000, 48000, 19, 20),
2236                       std::make_tuple(48000, 44100, 48000, 44100, 15, 20),
2237                       std::make_tuple(48000, 44100, 32000, 44100, 15, 15),
2238                       std::make_tuple(48000, 44100, 16000, 44100, 15, 15),
2239                       std::make_tuple(48000, 32000, 48000, 32000, 19, 35),
2240                       std::make_tuple(48000, 32000, 32000, 32000, 19, 0),
2241                       std::make_tuple(48000, 32000, 16000, 32000, 19, 20),
2242                       std::make_tuple(48000, 16000, 48000, 16000, 20, 20),
2243                       std::make_tuple(48000, 16000, 32000, 16000, 20, 20),
2244                       std::make_tuple(48000, 16000, 16000, 16000, 20, 0),
2245 
2246                       std::make_tuple(44100, 48000, 48000, 48000, 15, 0),
2247                       std::make_tuple(44100, 48000, 32000, 48000, 15, 30),
2248                       std::make_tuple(44100, 48000, 16000, 48000, 15, 20),
2249                       std::make_tuple(44100, 44100, 48000, 44100, 15, 20),
2250                       std::make_tuple(44100, 44100, 32000, 44100, 15, 15),
2251                       std::make_tuple(44100, 44100, 16000, 44100, 15, 15),
2252                       std::make_tuple(44100, 32000, 48000, 32000, 18, 35),
2253                       std::make_tuple(44100, 32000, 32000, 32000, 18, 0),
2254                       std::make_tuple(44100, 32000, 16000, 32000, 18, 20),
2255                       std::make_tuple(44100, 16000, 48000, 16000, 19, 20),
2256                       std::make_tuple(44100, 16000, 32000, 16000, 19, 20),
2257                       std::make_tuple(44100, 16000, 16000, 16000, 19, 0),
2258 
2259                       std::make_tuple(32000, 48000, 48000, 48000, 17, 0),
2260                       std::make_tuple(32000, 48000, 32000, 48000, 17, 30),
2261                       std::make_tuple(32000, 48000, 16000, 48000, 17, 20),
2262                       std::make_tuple(32000, 44100, 48000, 44100, 20, 20),
2263                       std::make_tuple(32000, 44100, 32000, 44100, 20, 15),
2264                       std::make_tuple(32000, 44100, 16000, 44100, 20, 15),
2265                       std::make_tuple(32000, 32000, 48000, 32000, 27, 35),
2266                       std::make_tuple(32000, 32000, 32000, 32000, 0, 0),
2267                       std::make_tuple(32000, 32000, 16000, 32000, 30, 20),
2268                       std::make_tuple(32000, 16000, 48000, 16000, 20, 20),
2269                       std::make_tuple(32000, 16000, 32000, 16000, 20, 20),
2270                       std::make_tuple(32000, 16000, 16000, 16000, 20, 0),
2271 
2272                       std::make_tuple(16000, 48000, 48000, 48000, 11, 0),
2273                       std::make_tuple(16000, 48000, 32000, 48000, 11, 30),
2274                       std::make_tuple(16000, 48000, 16000, 48000, 11, 20),
2275                       std::make_tuple(16000, 44100, 48000, 44100, 15, 20),
2276                       std::make_tuple(16000, 44100, 32000, 44100, 15, 15),
2277                       std::make_tuple(16000, 44100, 16000, 44100, 15, 15),
2278                       std::make_tuple(16000, 32000, 48000, 32000, 24, 35),
2279                       std::make_tuple(16000, 32000, 32000, 32000, 24, 0),
2280                       std::make_tuple(16000, 32000, 16000, 32000, 25, 20),
2281                       std::make_tuple(16000, 16000, 48000, 16000, 28, 20),
2282                       std::make_tuple(16000, 16000, 32000, 16000, 28, 20),
2283                       std::make_tuple(16000, 16000, 16000, 16000, 0, 0)));
2284 #endif
2285 
2286 // Produces a scoped trace debug output.
ProduceDebugText(int render_input_sample_rate_hz,int render_output_sample_rate_hz,int capture_input_sample_rate_hz,int capture_output_sample_rate_hz,size_t render_input_num_channels,size_t render_output_num_channels,size_t capture_input_num_channels,size_t capture_output_num_channels)2287 std::string ProduceDebugText(int render_input_sample_rate_hz,
2288                              int render_output_sample_rate_hz,
2289                              int capture_input_sample_rate_hz,
2290                              int capture_output_sample_rate_hz,
2291                              size_t render_input_num_channels,
2292                              size_t render_output_num_channels,
2293                              size_t capture_input_num_channels,
2294                              size_t capture_output_num_channels) {
2295   rtc::StringBuilder ss;
2296   ss << "Sample rates:"
2297         "\n Render input: "
2298      << render_input_sample_rate_hz
2299      << " Hz"
2300         "\n Render output: "
2301      << render_output_sample_rate_hz
2302      << " Hz"
2303         "\n Capture input: "
2304      << capture_input_sample_rate_hz
2305      << " Hz"
2306         "\n Capture output: "
2307      << capture_output_sample_rate_hz
2308      << " Hz"
2309         "\nNumber of channels:"
2310         "\n Render input: "
2311      << render_input_num_channels
2312      << "\n Render output: " << render_output_num_channels
2313      << "\n Capture input: " << capture_input_num_channels
2314      << "\n Capture output: " << capture_output_num_channels;
2315   return ss.Release();
2316 }
2317 
2318 // Validates that running the audio processing module using various combinations
2319 // of sample rates and number of channels works as intended.
RunApmRateAndChannelTest(rtc::ArrayView<const int> sample_rates_hz,rtc::ArrayView<const int> render_channel_counts,rtc::ArrayView<const int> capture_channel_counts)2320 void RunApmRateAndChannelTest(
2321     rtc::ArrayView<const int> sample_rates_hz,
2322     rtc::ArrayView<const int> render_channel_counts,
2323     rtc::ArrayView<const int> capture_channel_counts) {
2324   std::unique_ptr<AudioProcessing> apm(
2325       AudioProcessingBuilderForTesting().Create());
2326   webrtc::AudioProcessing::Config apm_config;
2327   apm_config.echo_canceller.enabled = true;
2328   apm->ApplyConfig(apm_config);
2329 
2330   StreamConfig render_input_stream_config;
2331   StreamConfig render_output_stream_config;
2332   StreamConfig capture_input_stream_config;
2333   StreamConfig capture_output_stream_config;
2334 
2335   std::vector<float> render_input_frame_channels;
2336   std::vector<float*> render_input_frame;
2337   std::vector<float> render_output_frame_channels;
2338   std::vector<float*> render_output_frame;
2339   std::vector<float> capture_input_frame_channels;
2340   std::vector<float*> capture_input_frame;
2341   std::vector<float> capture_output_frame_channels;
2342   std::vector<float*> capture_output_frame;
2343 
2344   for (auto render_input_sample_rate_hz : sample_rates_hz) {
2345     for (auto render_output_sample_rate_hz : sample_rates_hz) {
2346       for (auto capture_input_sample_rate_hz : sample_rates_hz) {
2347         for (auto capture_output_sample_rate_hz : sample_rates_hz) {
2348           for (size_t render_input_num_channels : render_channel_counts) {
2349             for (size_t capture_input_num_channels : capture_channel_counts) {
2350               size_t render_output_num_channels = render_input_num_channels;
2351               size_t capture_output_num_channels = capture_input_num_channels;
2352               auto populate_audio_frame = [](int sample_rate_hz,
2353                                              size_t num_channels,
2354                                              StreamConfig* cfg,
2355                                              std::vector<float>* channels_data,
2356                                              std::vector<float*>* frame_data) {
2357                 cfg->set_sample_rate_hz(sample_rate_hz);
2358                 cfg->set_num_channels(num_channels);
2359                 cfg->set_has_keyboard(false);
2360 
2361                 size_t max_frame_size = ceil(sample_rate_hz / 100.f);
2362                 channels_data->resize(num_channels * max_frame_size);
2363                 std::fill(channels_data->begin(), channels_data->end(), 0.5f);
2364                 frame_data->resize(num_channels);
2365                 for (size_t channel = 0; channel < num_channels; ++channel) {
2366                   (*frame_data)[channel] =
2367                       &(*channels_data)[channel * max_frame_size];
2368                 }
2369               };
2370 
2371               populate_audio_frame(
2372                   render_input_sample_rate_hz, render_input_num_channels,
2373                   &render_input_stream_config, &render_input_frame_channels,
2374                   &render_input_frame);
2375               populate_audio_frame(
2376                   render_output_sample_rate_hz, render_output_num_channels,
2377                   &render_output_stream_config, &render_output_frame_channels,
2378                   &render_output_frame);
2379               populate_audio_frame(
2380                   capture_input_sample_rate_hz, capture_input_num_channels,
2381                   &capture_input_stream_config, &capture_input_frame_channels,
2382                   &capture_input_frame);
2383               populate_audio_frame(
2384                   capture_output_sample_rate_hz, capture_output_num_channels,
2385                   &capture_output_stream_config, &capture_output_frame_channels,
2386                   &capture_output_frame);
2387 
2388               for (size_t frame = 0; frame < 2; ++frame) {
2389                 SCOPED_TRACE(ProduceDebugText(
2390                     render_input_sample_rate_hz, render_output_sample_rate_hz,
2391                     capture_input_sample_rate_hz, capture_output_sample_rate_hz,
2392                     render_input_num_channels, render_output_num_channels,
2393                     render_input_num_channels, capture_output_num_channels));
2394 
2395                 int result = apm->ProcessReverseStream(
2396                     &render_input_frame[0], render_input_stream_config,
2397                     render_output_stream_config, &render_output_frame[0]);
2398                 EXPECT_EQ(result, AudioProcessing::kNoError);
2399                 result = apm->ProcessStream(
2400                     &capture_input_frame[0], capture_input_stream_config,
2401                     capture_output_stream_config, &capture_output_frame[0]);
2402                 EXPECT_EQ(result, AudioProcessing::kNoError);
2403               }
2404             }
2405           }
2406         }
2407       }
2408     }
2409   }
2410 }
2411 
2412 }  // namespace
2413 
TEST(RuntimeSettingTest,TestDefaultCtor)2414 TEST(RuntimeSettingTest, TestDefaultCtor) {
2415   auto s = AudioProcessing::RuntimeSetting();
2416   EXPECT_EQ(AudioProcessing::RuntimeSetting::Type::kNotSpecified, s.type());
2417 }
2418 
TEST(RuntimeSettingDeathTest,TestCapturePreGain)2419 TEST(RuntimeSettingDeathTest, TestCapturePreGain) {
2420   using Type = AudioProcessing::RuntimeSetting::Type;
2421   {
2422     auto s = AudioProcessing::RuntimeSetting::CreateCapturePreGain(1.25f);
2423     EXPECT_EQ(Type::kCapturePreGain, s.type());
2424     float v;
2425     s.GetFloat(&v);
2426     EXPECT_EQ(1.25f, v);
2427   }
2428 
2429 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
2430   EXPECT_DEATH(AudioProcessing::RuntimeSetting::CreateCapturePreGain(0.1f), "");
2431 #endif
2432 }
2433 
TEST(RuntimeSettingDeathTest,TestCaptureFixedPostGain)2434 TEST(RuntimeSettingDeathTest, TestCaptureFixedPostGain) {
2435   using Type = AudioProcessing::RuntimeSetting::Type;
2436   {
2437     auto s = AudioProcessing::RuntimeSetting::CreateCaptureFixedPostGain(1.25f);
2438     EXPECT_EQ(Type::kCaptureFixedPostGain, s.type());
2439     float v;
2440     s.GetFloat(&v);
2441     EXPECT_EQ(1.25f, v);
2442   }
2443 
2444 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
2445   EXPECT_DEATH(AudioProcessing::RuntimeSetting::CreateCapturePreGain(0.1f), "");
2446 #endif
2447 }
2448 
TEST(RuntimeSettingTest,TestUsageWithSwapQueue)2449 TEST(RuntimeSettingTest, TestUsageWithSwapQueue) {
2450   SwapQueue<AudioProcessing::RuntimeSetting> q(1);
2451   auto s = AudioProcessing::RuntimeSetting();
2452   ASSERT_TRUE(q.Insert(&s));
2453   ASSERT_TRUE(q.Remove(&s));
2454   EXPECT_EQ(AudioProcessing::RuntimeSetting::Type::kNotSpecified, s.type());
2455 }
2456 
TEST(ApmConfiguration,EnablePostProcessing)2457 TEST(ApmConfiguration, EnablePostProcessing) {
2458   // Verify that apm uses a capture post processing module if one is provided.
2459   auto mock_post_processor_ptr =
2460       new ::testing::NiceMock<test::MockCustomProcessing>();
2461   auto mock_post_processor =
2462       std::unique_ptr<CustomProcessing>(mock_post_processor_ptr);
2463   rtc::scoped_refptr<AudioProcessing> apm =
2464       AudioProcessingBuilderForTesting()
2465           .SetCapturePostProcessing(std::move(mock_post_processor))
2466           .Create();
2467 
2468   Int16FrameData audio;
2469   audio.num_channels = 1;
2470   SetFrameSampleRate(&audio, AudioProcessing::NativeRate::kSampleRate16kHz);
2471 
2472   EXPECT_CALL(*mock_post_processor_ptr, Process(::testing::_)).Times(1);
2473   apm->ProcessStream(audio.data.data(),
2474                      StreamConfig(audio.sample_rate_hz, audio.num_channels),
2475                      StreamConfig(audio.sample_rate_hz, audio.num_channels),
2476                      audio.data.data());
2477 }
2478 
TEST(ApmConfiguration,EnablePreProcessing)2479 TEST(ApmConfiguration, EnablePreProcessing) {
2480   // Verify that apm uses a capture post processing module if one is provided.
2481   auto mock_pre_processor_ptr =
2482       new ::testing::NiceMock<test::MockCustomProcessing>();
2483   auto mock_pre_processor =
2484       std::unique_ptr<CustomProcessing>(mock_pre_processor_ptr);
2485   rtc::scoped_refptr<AudioProcessing> apm =
2486       AudioProcessingBuilderForTesting()
2487           .SetRenderPreProcessing(std::move(mock_pre_processor))
2488           .Create();
2489 
2490   Int16FrameData audio;
2491   audio.num_channels = 1;
2492   SetFrameSampleRate(&audio, AudioProcessing::NativeRate::kSampleRate16kHz);
2493 
2494   EXPECT_CALL(*mock_pre_processor_ptr, Process(::testing::_)).Times(1);
2495   apm->ProcessReverseStream(
2496       audio.data.data(), StreamConfig(audio.sample_rate_hz, audio.num_channels),
2497       StreamConfig(audio.sample_rate_hz, audio.num_channels),
2498       audio.data.data());
2499 }
2500 
TEST(ApmConfiguration,EnableCaptureAnalyzer)2501 TEST(ApmConfiguration, EnableCaptureAnalyzer) {
2502   // Verify that apm uses a capture analyzer if one is provided.
2503   auto mock_capture_analyzer_ptr =
2504       new ::testing::NiceMock<test::MockCustomAudioAnalyzer>();
2505   auto mock_capture_analyzer =
2506       std::unique_ptr<CustomAudioAnalyzer>(mock_capture_analyzer_ptr);
2507   rtc::scoped_refptr<AudioProcessing> apm =
2508       AudioProcessingBuilderForTesting()
2509           .SetCaptureAnalyzer(std::move(mock_capture_analyzer))
2510           .Create();
2511 
2512   Int16FrameData audio;
2513   audio.num_channels = 1;
2514   SetFrameSampleRate(&audio, AudioProcessing::NativeRate::kSampleRate16kHz);
2515 
2516   EXPECT_CALL(*mock_capture_analyzer_ptr, Analyze(::testing::_)).Times(1);
2517   apm->ProcessStream(audio.data.data(),
2518                      StreamConfig(audio.sample_rate_hz, audio.num_channels),
2519                      StreamConfig(audio.sample_rate_hz, audio.num_channels),
2520                      audio.data.data());
2521 }
2522 
TEST(ApmConfiguration,PreProcessingReceivesRuntimeSettings)2523 TEST(ApmConfiguration, PreProcessingReceivesRuntimeSettings) {
2524   auto mock_pre_processor_ptr =
2525       new ::testing::NiceMock<test::MockCustomProcessing>();
2526   auto mock_pre_processor =
2527       std::unique_ptr<CustomProcessing>(mock_pre_processor_ptr);
2528   rtc::scoped_refptr<AudioProcessing> apm =
2529       AudioProcessingBuilderForTesting()
2530           .SetRenderPreProcessing(std::move(mock_pre_processor))
2531           .Create();
2532   apm->SetRuntimeSetting(
2533       AudioProcessing::RuntimeSetting::CreateCustomRenderSetting(0));
2534 
2535   // RuntimeSettings forwarded during 'Process*Stream' calls.
2536   // Therefore we have to make one such call.
2537   Int16FrameData audio;
2538   audio.num_channels = 1;
2539   SetFrameSampleRate(&audio, AudioProcessing::NativeRate::kSampleRate16kHz);
2540 
2541   EXPECT_CALL(*mock_pre_processor_ptr, SetRuntimeSetting(::testing::_))
2542       .Times(1);
2543   apm->ProcessReverseStream(
2544       audio.data.data(), StreamConfig(audio.sample_rate_hz, audio.num_channels),
2545       StreamConfig(audio.sample_rate_hz, audio.num_channels),
2546       audio.data.data());
2547 }
2548 
2549 class MyEchoControlFactory : public EchoControlFactory {
2550  public:
Create(int sample_rate_hz)2551   std::unique_ptr<EchoControl> Create(int sample_rate_hz) {
2552     auto ec = new test::MockEchoControl();
2553     EXPECT_CALL(*ec, AnalyzeRender(::testing::_)).Times(1);
2554     EXPECT_CALL(*ec, AnalyzeCapture(::testing::_)).Times(2);
2555     EXPECT_CALL(*ec, ProcessCapture(::testing::_, ::testing::_, ::testing::_))
2556         .Times(2);
2557     return std::unique_ptr<EchoControl>(ec);
2558   }
2559 
Create(int sample_rate_hz,int num_render_channels,int num_capture_channels)2560   std::unique_ptr<EchoControl> Create(int sample_rate_hz,
2561                                       int num_render_channels,
2562                                       int num_capture_channels) {
2563     return Create(sample_rate_hz);
2564   }
2565 };
2566 
TEST(ApmConfiguration,EchoControlInjection)2567 TEST(ApmConfiguration, EchoControlInjection) {
2568   // Verify that apm uses an injected echo controller if one is provided.
2569   webrtc::Config webrtc_config;
2570   std::unique_ptr<EchoControlFactory> echo_control_factory(
2571       new MyEchoControlFactory());
2572 
2573   rtc::scoped_refptr<AudioProcessing> apm =
2574       AudioProcessingBuilderForTesting()
2575           .SetEchoControlFactory(std::move(echo_control_factory))
2576           .Create(webrtc_config);
2577 
2578   Int16FrameData audio;
2579   audio.num_channels = 1;
2580   SetFrameSampleRate(&audio, AudioProcessing::NativeRate::kSampleRate16kHz);
2581   apm->ProcessStream(audio.data.data(),
2582                      StreamConfig(audio.sample_rate_hz, audio.num_channels),
2583                      StreamConfig(audio.sample_rate_hz, audio.num_channels),
2584                      audio.data.data());
2585   apm->ProcessReverseStream(
2586       audio.data.data(), StreamConfig(audio.sample_rate_hz, audio.num_channels),
2587       StreamConfig(audio.sample_rate_hz, audio.num_channels),
2588       audio.data.data());
2589   apm->ProcessStream(audio.data.data(),
2590                      StreamConfig(audio.sample_rate_hz, audio.num_channels),
2591                      StreamConfig(audio.sample_rate_hz, audio.num_channels),
2592                      audio.data.data());
2593 }
2594 
CreateApm(bool mobile_aec)2595 std::unique_ptr<AudioProcessing> CreateApm(bool mobile_aec) {
2596   Config old_config;
2597   std::unique_ptr<AudioProcessing> apm(
2598       AudioProcessingBuilderForTesting().Create(old_config));
2599   if (!apm) {
2600     return apm;
2601   }
2602 
2603   ProcessingConfig processing_config = {
2604       {{32000, 1}, {32000, 1}, {32000, 1}, {32000, 1}}};
2605 
2606   if (apm->Initialize(processing_config) != 0) {
2607     return nullptr;
2608   }
2609 
2610   // Disable all components except for an AEC and the residual echo detector.
2611   AudioProcessing::Config apm_config;
2612   apm_config.residual_echo_detector.enabled = true;
2613   apm_config.high_pass_filter.enabled = false;
2614   apm_config.gain_controller1.enabled = false;
2615   apm_config.gain_controller2.enabled = false;
2616   apm_config.echo_canceller.enabled = true;
2617   apm_config.echo_canceller.mobile_mode = mobile_aec;
2618   apm_config.noise_suppression.enabled = false;
2619   apm_config.level_estimation.enabled = false;
2620   apm_config.voice_detection.enabled = false;
2621   apm->ApplyConfig(apm_config);
2622   return apm;
2623 }
2624 
2625 #if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS) || defined(WEBRTC_MAC)
2626 #define MAYBE_ApmStatistics DISABLED_ApmStatistics
2627 #else
2628 #define MAYBE_ApmStatistics ApmStatistics
2629 #endif
2630 
TEST(MAYBE_ApmStatistics,AECEnabledTest)2631 TEST(MAYBE_ApmStatistics, AECEnabledTest) {
2632   // Set up APM with AEC3 and process some audio.
2633   std::unique_ptr<AudioProcessing> apm = CreateApm(false);
2634   ASSERT_TRUE(apm);
2635   AudioProcessing::Config apm_config;
2636   apm_config.echo_canceller.enabled = true;
2637   apm->ApplyConfig(apm_config);
2638 
2639   // Set up an audioframe.
2640   Int16FrameData frame;
2641   frame.num_channels = 1;
2642   SetFrameSampleRate(&frame, AudioProcessing::NativeRate::kSampleRate32kHz);
2643 
2644   // Fill the audio frame with a sawtooth pattern.
2645   int16_t* ptr = frame.data.data();
2646   for (size_t i = 0; i < frame.kMaxDataSizeSamples; i++) {
2647     ptr[i] = 10000 * ((i % 3) - 1);
2648   }
2649 
2650   // Do some processing.
2651   for (int i = 0; i < 200; i++) {
2652     EXPECT_EQ(apm->ProcessReverseStream(
2653                   frame.data.data(),
2654                   StreamConfig(frame.sample_rate_hz, frame.num_channels),
2655                   StreamConfig(frame.sample_rate_hz, frame.num_channels),
2656                   frame.data.data()),
2657               0);
2658     EXPECT_EQ(apm->set_stream_delay_ms(0), 0);
2659     EXPECT_EQ(apm->ProcessStream(
2660                   frame.data.data(),
2661                   StreamConfig(frame.sample_rate_hz, frame.num_channels),
2662                   StreamConfig(frame.sample_rate_hz, frame.num_channels),
2663                   frame.data.data()),
2664               0);
2665   }
2666 
2667   // Test statistics interface.
2668   AudioProcessingStats stats = apm->GetStatistics();
2669   // We expect all statistics to be set and have a sensible value.
2670   ASSERT_TRUE(stats.residual_echo_likelihood);
2671   EXPECT_GE(*stats.residual_echo_likelihood, 0.0);
2672   EXPECT_LE(*stats.residual_echo_likelihood, 1.0);
2673   ASSERT_TRUE(stats.residual_echo_likelihood_recent_max);
2674   EXPECT_GE(*stats.residual_echo_likelihood_recent_max, 0.0);
2675   EXPECT_LE(*stats.residual_echo_likelihood_recent_max, 1.0);
2676   ASSERT_TRUE(stats.echo_return_loss);
2677   EXPECT_NE(*stats.echo_return_loss, -100.0);
2678   ASSERT_TRUE(stats.echo_return_loss_enhancement);
2679   EXPECT_NE(*stats.echo_return_loss_enhancement, -100.0);
2680 }
2681 
TEST(MAYBE_ApmStatistics,AECMEnabledTest)2682 TEST(MAYBE_ApmStatistics, AECMEnabledTest) {
2683   // Set up APM with AECM and process some audio.
2684   std::unique_ptr<AudioProcessing> apm = CreateApm(true);
2685   ASSERT_TRUE(apm);
2686 
2687   // Set up an audioframe.
2688   Int16FrameData frame;
2689   frame.num_channels = 1;
2690   SetFrameSampleRate(&frame, AudioProcessing::NativeRate::kSampleRate32kHz);
2691 
2692   // Fill the audio frame with a sawtooth pattern.
2693   int16_t* ptr = frame.data.data();
2694   for (size_t i = 0; i < frame.kMaxDataSizeSamples; i++) {
2695     ptr[i] = 10000 * ((i % 3) - 1);
2696   }
2697 
2698   // Do some processing.
2699   for (int i = 0; i < 200; i++) {
2700     EXPECT_EQ(apm->ProcessReverseStream(
2701                   frame.data.data(),
2702                   StreamConfig(frame.sample_rate_hz, frame.num_channels),
2703                   StreamConfig(frame.sample_rate_hz, frame.num_channels),
2704                   frame.data.data()),
2705               0);
2706     EXPECT_EQ(apm->set_stream_delay_ms(0), 0);
2707     EXPECT_EQ(apm->ProcessStream(
2708                   frame.data.data(),
2709                   StreamConfig(frame.sample_rate_hz, frame.num_channels),
2710                   StreamConfig(frame.sample_rate_hz, frame.num_channels),
2711                   frame.data.data()),
2712               0);
2713   }
2714 
2715   // Test statistics interface.
2716   AudioProcessingStats stats = apm->GetStatistics();
2717   // We expect only the residual echo detector statistics to be set and have a
2718   // sensible value.
2719   EXPECT_TRUE(stats.residual_echo_likelihood);
2720   if (stats.residual_echo_likelihood) {
2721     EXPECT_GE(*stats.residual_echo_likelihood, 0.0);
2722     EXPECT_LE(*stats.residual_echo_likelihood, 1.0);
2723   }
2724   EXPECT_TRUE(stats.residual_echo_likelihood_recent_max);
2725   if (stats.residual_echo_likelihood_recent_max) {
2726     EXPECT_GE(*stats.residual_echo_likelihood_recent_max, 0.0);
2727     EXPECT_LE(*stats.residual_echo_likelihood_recent_max, 1.0);
2728   }
2729   EXPECT_FALSE(stats.echo_return_loss);
2730   EXPECT_FALSE(stats.echo_return_loss_enhancement);
2731 }
2732 
TEST(ApmStatistics,ReportOutputRmsDbfs)2733 TEST(ApmStatistics, ReportOutputRmsDbfs) {
2734   ProcessingConfig processing_config = {
2735       {{32000, 1}, {32000, 1}, {32000, 1}, {32000, 1}}};
2736   AudioProcessing::Config config;
2737 
2738   // Set up an audioframe.
2739   Int16FrameData frame;
2740   frame.num_channels = 1;
2741   SetFrameSampleRate(&frame, AudioProcessing::NativeRate::kSampleRate32kHz);
2742 
2743   // Fill the audio frame with a sawtooth pattern.
2744   int16_t* ptr = frame.data.data();
2745   for (size_t i = 0; i < frame.kMaxDataSizeSamples; i++) {
2746     ptr[i] = 10000 * ((i % 3) - 1);
2747   }
2748 
2749   std::unique_ptr<AudioProcessing> apm(
2750       AudioProcessingBuilderForTesting().Create());
2751   apm->Initialize(processing_config);
2752 
2753   // If not enabled, no metric should be reported.
2754   EXPECT_EQ(
2755       apm->ProcessStream(frame.data.data(),
2756                          StreamConfig(frame.sample_rate_hz, frame.num_channels),
2757                          StreamConfig(frame.sample_rate_hz, frame.num_channels),
2758                          frame.data.data()),
2759       0);
2760   EXPECT_FALSE(apm->GetStatistics().output_rms_dbfs);
2761 
2762   // If enabled, metrics should be reported.
2763   config.level_estimation.enabled = true;
2764   apm->ApplyConfig(config);
2765   EXPECT_EQ(
2766       apm->ProcessStream(frame.data.data(),
2767                          StreamConfig(frame.sample_rate_hz, frame.num_channels),
2768                          StreamConfig(frame.sample_rate_hz, frame.num_channels),
2769                          frame.data.data()),
2770       0);
2771   auto stats = apm->GetStatistics();
2772   EXPECT_TRUE(stats.output_rms_dbfs);
2773   EXPECT_GE(*stats.output_rms_dbfs, 0);
2774 
2775   // If re-disabled, the value is again not reported.
2776   config.level_estimation.enabled = false;
2777   apm->ApplyConfig(config);
2778   EXPECT_EQ(
2779       apm->ProcessStream(frame.data.data(),
2780                          StreamConfig(frame.sample_rate_hz, frame.num_channels),
2781                          StreamConfig(frame.sample_rate_hz, frame.num_channels),
2782                          frame.data.data()),
2783       0);
2784   EXPECT_FALSE(apm->GetStatistics().output_rms_dbfs);
2785 }
2786 
TEST(ApmStatistics,ReportHasVoice)2787 TEST(ApmStatistics, ReportHasVoice) {
2788   ProcessingConfig processing_config = {
2789       {{32000, 1}, {32000, 1}, {32000, 1}, {32000, 1}}};
2790   AudioProcessing::Config config;
2791 
2792   // Set up an audioframe.
2793   Int16FrameData frame;
2794   frame.num_channels = 1;
2795   SetFrameSampleRate(&frame, AudioProcessing::NativeRate::kSampleRate32kHz);
2796 
2797   // Fill the audio frame with a sawtooth pattern.
2798   int16_t* ptr = frame.data.data();
2799   for (size_t i = 0; i < frame.kMaxDataSizeSamples; i++) {
2800     ptr[i] = 10000 * ((i % 3) - 1);
2801   }
2802 
2803   std::unique_ptr<AudioProcessing> apm(
2804       AudioProcessingBuilderForTesting().Create());
2805   apm->Initialize(processing_config);
2806 
2807   // If not enabled, no metric should be reported.
2808   EXPECT_EQ(
2809       apm->ProcessStream(frame.data.data(),
2810                          StreamConfig(frame.sample_rate_hz, frame.num_channels),
2811                          StreamConfig(frame.sample_rate_hz, frame.num_channels),
2812                          frame.data.data()),
2813       0);
2814   EXPECT_FALSE(apm->GetStatistics().voice_detected);
2815 
2816   // If enabled, metrics should be reported.
2817   config.voice_detection.enabled = true;
2818   apm->ApplyConfig(config);
2819   EXPECT_EQ(
2820       apm->ProcessStream(frame.data.data(),
2821                          StreamConfig(frame.sample_rate_hz, frame.num_channels),
2822                          StreamConfig(frame.sample_rate_hz, frame.num_channels),
2823                          frame.data.data()),
2824       0);
2825   auto stats = apm->GetStatistics();
2826   EXPECT_TRUE(stats.voice_detected);
2827 
2828   // If re-disabled, the value is again not reported.
2829   config.voice_detection.enabled = false;
2830   apm->ApplyConfig(config);
2831   EXPECT_EQ(
2832       apm->ProcessStream(frame.data.data(),
2833                          StreamConfig(frame.sample_rate_hz, frame.num_channels),
2834                          StreamConfig(frame.sample_rate_hz, frame.num_channels),
2835                          frame.data.data()),
2836       0);
2837   EXPECT_FALSE(apm->GetStatistics().voice_detected);
2838 }
2839 
TEST(ApmConfiguration,HandlingOfRateAndChannelCombinations)2840 TEST(ApmConfiguration, HandlingOfRateAndChannelCombinations) {
2841   std::array<int, 3> sample_rates_hz = {16000, 32000, 48000};
2842   std::array<int, 2> render_channel_counts = {1, 7};
2843   std::array<int, 2> capture_channel_counts = {1, 7};
2844   RunApmRateAndChannelTest(sample_rates_hz, render_channel_counts,
2845                            capture_channel_counts);
2846 }
2847 
TEST(ApmConfiguration,HandlingOfChannelCombinations)2848 TEST(ApmConfiguration, HandlingOfChannelCombinations) {
2849   std::array<int, 1> sample_rates_hz = {48000};
2850   std::array<int, 8> render_channel_counts = {1, 2, 3, 4, 5, 6, 7, 8};
2851   std::array<int, 8> capture_channel_counts = {1, 2, 3, 4, 5, 6, 7, 8};
2852   RunApmRateAndChannelTest(sample_rates_hz, render_channel_counts,
2853                            capture_channel_counts);
2854 }
2855 
TEST(ApmConfiguration,HandlingOfRateCombinations)2856 TEST(ApmConfiguration, HandlingOfRateCombinations) {
2857   std::array<int, 9> sample_rates_hz = {8000,  11025, 16000,  22050, 32000,
2858                                         48000, 96000, 192000, 384000};
2859   std::array<int, 1> render_channel_counts = {2};
2860   std::array<int, 1> capture_channel_counts = {2};
2861   RunApmRateAndChannelTest(sample_rates_hz, render_channel_counts,
2862                            capture_channel_counts);
2863 }
2864 
TEST(ApmConfiguration,SelfAssignment)2865 TEST(ApmConfiguration, SelfAssignment) {
2866   // At some point memory sanitizer was complaining about self-assigment.
2867   // Make sure we don't regress.
2868   AudioProcessing::Config config;
2869   AudioProcessing::Config* config2 = &config;
2870   *config2 = *config2;  // Workaround -Wself-assign-overloaded
2871   SUCCEED();  // Real success is absence of defects from asan/msan/ubsan.
2872 }
2873 
2874 }  // namespace webrtc
2875