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