1 /*
2  *  Copyright (c) 2022 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "modules/audio_processing/aec3/multi_channel_content_detector.h"
12 
13 #include "system_wrappers/include/metrics.h"
14 #include "test/gtest.h"
15 
16 namespace webrtc {
17 
TEST(MultiChannelContentDetector,HandlingOfMono)18 TEST(MultiChannelContentDetector, HandlingOfMono) {
19   MultiChannelContentDetector mc(
20       /*detect_stereo_content=*/true,
21       /*num_render_input_channels=*/1,
22       /*detection_threshold=*/0.0f,
23       /*stereo_detection_timeout_threshold_seconds=*/0,
24       /*stereo_detection_hysteresis_seconds=*/0.0f);
25   EXPECT_FALSE(mc.IsProperMultiChannelContentDetected());
26 }
27 
TEST(MultiChannelContentDetector,HandlingOfMonoAndDetectionOff)28 TEST(MultiChannelContentDetector, HandlingOfMonoAndDetectionOff) {
29   MultiChannelContentDetector mc(
30       /*detect_stereo_content=*/false,
31       /*num_render_input_channels=*/1,
32       /*detection_threshold=*/0.0f,
33       /*stereo_detection_timeout_threshold_seconds=*/0,
34       /*stereo_detection_hysteresis_seconds=*/0.0f);
35   EXPECT_FALSE(mc.IsProperMultiChannelContentDetected());
36 }
37 
TEST(MultiChannelContentDetector,HandlingOfDetectionOff)38 TEST(MultiChannelContentDetector, HandlingOfDetectionOff) {
39   MultiChannelContentDetector mc(
40       /*detect_stereo_content=*/false,
41       /*num_render_input_channels=*/2,
42       /*detection_threshold=*/0.0f,
43       /*stereo_detection_timeout_threshold_seconds=*/0,
44       /*stereo_detection_hysteresis_seconds=*/0.0f);
45   EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
46 
47   std::vector<std::vector<std::vector<float>>> frame(
48       1, std::vector<std::vector<float>>(2, std::vector<float>(160, 0.0f)));
49   std::fill(frame[0][0].begin(), frame[0][0].end(), 100.0f);
50   std::fill(frame[0][1].begin(), frame[0][1].end(), 101.0f);
51 
52   EXPECT_FALSE(mc.UpdateDetection(frame));
53   EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
54 
55   EXPECT_FALSE(mc.UpdateDetection(frame));
56 }
57 
TEST(MultiChannelContentDetector,InitialDetectionOfStereo)58 TEST(MultiChannelContentDetector, InitialDetectionOfStereo) {
59   MultiChannelContentDetector mc(
60       /*detect_stereo_content=*/true,
61       /*num_render_input_channels=*/2,
62       /*detection_threshold=*/0.0f,
63       /*stereo_detection_timeout_threshold_seconds=*/0,
64       /*stereo_detection_hysteresis_seconds=*/0.0f);
65   EXPECT_FALSE(mc.IsProperMultiChannelContentDetected());
66 }
67 
TEST(MultiChannelContentDetector,DetectionWhenFakeStereo)68 TEST(MultiChannelContentDetector, DetectionWhenFakeStereo) {
69   MultiChannelContentDetector mc(
70       /*detect_stereo_content=*/true,
71       /*num_render_input_channels=*/2,
72       /*detection_threshold=*/0.0f,
73       /*stereo_detection_timeout_threshold_seconds=*/0,
74       /*stereo_detection_hysteresis_seconds=*/0.0f);
75   std::vector<std::vector<std::vector<float>>> frame(
76       1, std::vector<std::vector<float>>(2, std::vector<float>(160, 0.0f)));
77   std::fill(frame[0][0].begin(), frame[0][0].end(), 100.0f);
78   std::fill(frame[0][1].begin(), frame[0][1].end(), 100.0f);
79   EXPECT_FALSE(mc.UpdateDetection(frame));
80   EXPECT_FALSE(mc.IsProperMultiChannelContentDetected());
81 
82   EXPECT_FALSE(mc.UpdateDetection(frame));
83 }
84 
TEST(MultiChannelContentDetector,DetectionWhenStereo)85 TEST(MultiChannelContentDetector, DetectionWhenStereo) {
86   MultiChannelContentDetector mc(
87       /*detect_stereo_content=*/true,
88       /*num_render_input_channels=*/2,
89       /*detection_threshold=*/0.0f,
90       /*stereo_detection_timeout_threshold_seconds=*/0,
91       /*stereo_detection_hysteresis_seconds=*/0.0f);
92   std::vector<std::vector<std::vector<float>>> frame(
93       1, std::vector<std::vector<float>>(2, std::vector<float>(160, 0.0f)));
94   std::fill(frame[0][0].begin(), frame[0][0].end(), 100.0f);
95   std::fill(frame[0][1].begin(), frame[0][1].end(), 101.0f);
96   EXPECT_TRUE(mc.UpdateDetection(frame));
97   EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
98 
99   EXPECT_FALSE(mc.UpdateDetection(frame));
100 }
101 
TEST(MultiChannelContentDetector,DetectionWhenStereoAfterAWhile)102 TEST(MultiChannelContentDetector, DetectionWhenStereoAfterAWhile) {
103   MultiChannelContentDetector mc(
104       /*detect_stereo_content=*/true,
105       /*num_render_input_channels=*/2,
106       /*detection_threshold=*/0.0f,
107       /*stereo_detection_timeout_threshold_seconds=*/0,
108       /*stereo_detection_hysteresis_seconds=*/0.0f);
109   std::vector<std::vector<std::vector<float>>> frame(
110       1, std::vector<std::vector<float>>(2, std::vector<float>(160, 0.0f)));
111 
112   std::fill(frame[0][0].begin(), frame[0][0].end(), 100.0f);
113   std::fill(frame[0][1].begin(), frame[0][1].end(), 100.0f);
114   EXPECT_FALSE(mc.UpdateDetection(frame));
115   EXPECT_FALSE(mc.IsProperMultiChannelContentDetected());
116 
117   EXPECT_FALSE(mc.UpdateDetection(frame));
118 
119   std::fill(frame[0][0].begin(), frame[0][0].end(), 100.0f);
120   std::fill(frame[0][1].begin(), frame[0][1].end(), 101.0f);
121 
122   EXPECT_TRUE(mc.UpdateDetection(frame));
123   EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
124 
125   EXPECT_FALSE(mc.UpdateDetection(frame));
126 }
127 
TEST(MultiChannelContentDetector,DetectionWithStereoBelowThreshold)128 TEST(MultiChannelContentDetector, DetectionWithStereoBelowThreshold) {
129   constexpr float kThreshold = 1.0f;
130   MultiChannelContentDetector mc(
131       /*detect_stereo_content=*/true,
132       /*num_render_input_channels=*/2,
133       /*detection_threshold=*/kThreshold,
134       /*stereo_detection_timeout_threshold_seconds=*/0,
135       /*stereo_detection_hysteresis_seconds=*/0.0f);
136   std::vector<std::vector<std::vector<float>>> frame(
137       1, std::vector<std::vector<float>>(2, std::vector<float>(160, 0.0f)));
138   std::fill(frame[0][0].begin(), frame[0][0].end(), 100.0f);
139   std::fill(frame[0][1].begin(), frame[0][1].end(), 100.0f + kThreshold);
140 
141   EXPECT_FALSE(mc.UpdateDetection(frame));
142   EXPECT_FALSE(mc.IsProperMultiChannelContentDetected());
143 
144   EXPECT_FALSE(mc.UpdateDetection(frame));
145 }
146 
TEST(MultiChannelContentDetector,DetectionWithStereoAboveThreshold)147 TEST(MultiChannelContentDetector, DetectionWithStereoAboveThreshold) {
148   constexpr float kThreshold = 1.0f;
149   MultiChannelContentDetector mc(
150       /*detect_stereo_content=*/true,
151       /*num_render_input_channels=*/2,
152       /*detection_threshold=*/kThreshold,
153       /*stereo_detection_timeout_threshold_seconds=*/0,
154       /*stereo_detection_hysteresis_seconds=*/0.0f);
155   std::vector<std::vector<std::vector<float>>> frame(
156       1, std::vector<std::vector<float>>(2, std::vector<float>(160, 0.0f)));
157   std::fill(frame[0][0].begin(), frame[0][0].end(), 100.0f);
158   std::fill(frame[0][1].begin(), frame[0][1].end(), 100.0f + kThreshold + 0.1f);
159 
160   EXPECT_TRUE(mc.UpdateDetection(frame));
161   EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
162 
163   EXPECT_FALSE(mc.UpdateDetection(frame));
164 }
165 
166 class MultiChannelContentDetectorTimeoutBehavior
167     : public ::testing::Test,
168       public ::testing::WithParamInterface<std::tuple<bool, int>> {};
169 
170 INSTANTIATE_TEST_SUITE_P(MultiChannelContentDetector,
171                          MultiChannelContentDetectorTimeoutBehavior,
172                          ::testing::Combine(::testing::Values(false, true),
173                                             ::testing::Values(0, 1, 10)));
174 
TEST_P(MultiChannelContentDetectorTimeoutBehavior,TimeOutBehaviorForNonTrueStereo)175 TEST_P(MultiChannelContentDetectorTimeoutBehavior,
176        TimeOutBehaviorForNonTrueStereo) {
177   constexpr int kNumFramesPerSecond = 100;
178   const bool detect_stereo_content = std::get<0>(GetParam());
179   const int stereo_detection_timeout_threshold_seconds =
180       std::get<1>(GetParam());
181   const int stereo_detection_timeout_threshold_frames =
182       stereo_detection_timeout_threshold_seconds * kNumFramesPerSecond;
183 
184   MultiChannelContentDetector mc(detect_stereo_content,
185                                  /*num_render_input_channels=*/2,
186                                  /*detection_threshold=*/0.0f,
187                                  stereo_detection_timeout_threshold_seconds,
188                                  /*stereo_detection_hysteresis_seconds=*/0.0f);
189   std::vector<std::vector<std::vector<float>>> true_stereo_frame = {
190       {std::vector<float>(160, 100.0f), std::vector<float>(160, 101.0f)}};
191 
192   std::vector<std::vector<std::vector<float>>> fake_stereo_frame = {
193       {std::vector<float>(160, 100.0f), std::vector<float>(160, 100.0f)}};
194 
195   // Pass fake stereo frames and verify the content detection.
196   for (int k = 0; k < 10; ++k) {
197     EXPECT_FALSE(mc.UpdateDetection(fake_stereo_frame));
198     if (detect_stereo_content) {
199       EXPECT_FALSE(mc.IsProperMultiChannelContentDetected());
200     } else {
201       EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
202     }
203   }
204 
205   // Pass a true stereo frame and verify that it is properly detected.
206   if (detect_stereo_content) {
207     EXPECT_TRUE(mc.UpdateDetection(true_stereo_frame));
208   } else {
209     EXPECT_FALSE(mc.UpdateDetection(true_stereo_frame));
210   }
211   EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
212 
213   // Pass fake stereo frames until any timeouts are about to occur.
214   for (int k = 0; k < stereo_detection_timeout_threshold_frames - 1; ++k) {
215     EXPECT_FALSE(mc.UpdateDetection(fake_stereo_frame));
216     EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
217   }
218 
219   // Pass a fake stereo frame and verify that any timeouts properly occur.
220   if (detect_stereo_content && stereo_detection_timeout_threshold_frames > 0) {
221     EXPECT_TRUE(mc.UpdateDetection(fake_stereo_frame));
222     EXPECT_FALSE(mc.IsProperMultiChannelContentDetected());
223   } else {
224     EXPECT_FALSE(mc.UpdateDetection(fake_stereo_frame));
225     EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
226   }
227 
228   // Pass fake stereo frames and verify the behavior after any timeout.
229   for (int k = 0; k < 10; ++k) {
230     EXPECT_FALSE(mc.UpdateDetection(fake_stereo_frame));
231     if (detect_stereo_content &&
232         stereo_detection_timeout_threshold_frames > 0) {
233       EXPECT_FALSE(mc.IsProperMultiChannelContentDetected());
234     } else {
235       EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
236     }
237   }
238 }
239 
240 class MultiChannelContentDetectorHysteresisBehavior
241     : public ::testing::Test,
242       public ::testing::WithParamInterface<std::tuple<bool, float>> {};
243 
244 INSTANTIATE_TEST_SUITE_P(
245     MultiChannelContentDetector,
246     MultiChannelContentDetectorHysteresisBehavior,
247     ::testing::Combine(::testing::Values(false, true),
248                        ::testing::Values(0.0f, 0.1f, 0.2f)));
249 
TEST_P(MultiChannelContentDetectorHysteresisBehavior,PeriodBeforeStereoDetectionIsTriggered)250 TEST_P(MultiChannelContentDetectorHysteresisBehavior,
251        PeriodBeforeStereoDetectionIsTriggered) {
252   constexpr int kNumFramesPerSecond = 100;
253   const bool detect_stereo_content = std::get<0>(GetParam());
254   const int stereo_detection_hysteresis_seconds = std::get<1>(GetParam());
255   const int stereo_detection_hysteresis_frames =
256       stereo_detection_hysteresis_seconds * kNumFramesPerSecond;
257 
258   MultiChannelContentDetector mc(
259       detect_stereo_content,
260       /*num_render_input_channels=*/2,
261       /*detection_threshold=*/0.0f,
262       /*stereo_detection_timeout_threshold_seconds=*/0,
263       stereo_detection_hysteresis_seconds);
264   std::vector<std::vector<std::vector<float>>> true_stereo_frame = {
265       {std::vector<float>(160, 100.0f), std::vector<float>(160, 101.0f)}};
266 
267   std::vector<std::vector<std::vector<float>>> fake_stereo_frame = {
268       {std::vector<float>(160, 100.0f), std::vector<float>(160, 100.0f)}};
269 
270   // Pass fake stereo frames and verify the content detection.
271   for (int k = 0; k < 10; ++k) {
272     EXPECT_FALSE(mc.UpdateDetection(fake_stereo_frame));
273     if (detect_stereo_content) {
274       EXPECT_FALSE(mc.IsProperMultiChannelContentDetected());
275     } else {
276       EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
277     }
278     EXPECT_FALSE(mc.IsTemporaryMultiChannelContentDetected());
279   }
280 
281   // Pass a two true stereo frames and verify that they are properly detected.
282   ASSERT_TRUE(stereo_detection_hysteresis_frames > 2 ||
283               stereo_detection_hysteresis_frames == 0);
284   for (int k = 0; k < 2; ++k) {
285     if (detect_stereo_content) {
286       if (stereo_detection_hysteresis_seconds == 0.0f) {
287         if (k == 0) {
288           EXPECT_TRUE(mc.UpdateDetection(true_stereo_frame));
289         } else {
290           EXPECT_FALSE(mc.UpdateDetection(true_stereo_frame));
291         }
292         EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
293         EXPECT_FALSE(mc.IsTemporaryMultiChannelContentDetected());
294       } else {
295         EXPECT_FALSE(mc.UpdateDetection(true_stereo_frame));
296         EXPECT_FALSE(mc.IsProperMultiChannelContentDetected());
297         EXPECT_TRUE(mc.IsTemporaryMultiChannelContentDetected());
298       }
299     } else {
300       EXPECT_FALSE(mc.UpdateDetection(true_stereo_frame));
301       EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
302       EXPECT_FALSE(mc.IsTemporaryMultiChannelContentDetected());
303     }
304   }
305 
306   if (stereo_detection_hysteresis_seconds == 0.0f) {
307     return;
308   }
309 
310   // Pass true stereo frames until any timeouts are about to occur.
311   for (int k = 0; k < stereo_detection_hysteresis_frames - 3; ++k) {
312     if (detect_stereo_content) {
313       EXPECT_FALSE(mc.UpdateDetection(true_stereo_frame));
314       EXPECT_FALSE(mc.IsProperMultiChannelContentDetected());
315       EXPECT_TRUE(mc.IsTemporaryMultiChannelContentDetected());
316     } else {
317       EXPECT_FALSE(mc.UpdateDetection(true_stereo_frame));
318       EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
319       EXPECT_FALSE(mc.IsTemporaryMultiChannelContentDetected());
320     }
321   }
322 
323   // Pass a true stereo frame and verify that it is properly detected.
324   if (detect_stereo_content) {
325     EXPECT_TRUE(mc.UpdateDetection(true_stereo_frame));
326     EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
327     EXPECT_FALSE(mc.IsTemporaryMultiChannelContentDetected());
328   } else {
329     EXPECT_FALSE(mc.UpdateDetection(true_stereo_frame));
330     EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
331     EXPECT_FALSE(mc.IsTemporaryMultiChannelContentDetected());
332   }
333 
334   // Pass an additional true stereo frame and verify that it is properly
335   // detected.
336   if (detect_stereo_content) {
337     EXPECT_FALSE(mc.UpdateDetection(true_stereo_frame));
338     EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
339     EXPECT_FALSE(mc.IsTemporaryMultiChannelContentDetected());
340   } else {
341     EXPECT_FALSE(mc.UpdateDetection(true_stereo_frame));
342     EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
343     EXPECT_FALSE(mc.IsTemporaryMultiChannelContentDetected());
344   }
345 
346   // Pass a fake stereo frame and verify that it is properly detected.
347   if (detect_stereo_content) {
348     EXPECT_FALSE(mc.UpdateDetection(fake_stereo_frame));
349     EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
350     EXPECT_FALSE(mc.IsTemporaryMultiChannelContentDetected());
351   } else {
352     EXPECT_FALSE(mc.UpdateDetection(fake_stereo_frame));
353     EXPECT_TRUE(mc.IsProperMultiChannelContentDetected());
354     EXPECT_FALSE(mc.IsTemporaryMultiChannelContentDetected());
355   }
356 }
357 
358 class MultiChannelContentDetectorMetricsDisabled
359     : public ::testing::Test,
360       public ::testing::WithParamInterface<std::tuple<bool, int>> {};
361 
362 INSTANTIATE_TEST_SUITE_P(
363     /*no prefix*/,
364     MultiChannelContentDetectorMetricsDisabled,
365     ::testing::Values(std::tuple<bool, int>(false, 2),
366                       std::tuple<bool, int>(true, 1)));
367 
368 // Test that no metrics are logged when they are clearly uninteresting and would
369 // dilute relevant data: when the reference audio is single channel, or when
370 // dynamic detection is disabled.
TEST_P(MultiChannelContentDetectorMetricsDisabled,ReportsNoMetrics)371 TEST_P(MultiChannelContentDetectorMetricsDisabled, ReportsNoMetrics) {
372   metrics::Reset();
373   constexpr int kNumFramesPerSecond = 100;
374   const bool detect_stereo_content = std::get<0>(GetParam());
375   const int channel_count = std::get<1>(GetParam());
376   std::vector<std::vector<std::vector<float>>> audio_frame = {
377       std::vector<std::vector<float>>(channel_count,
378                                       std::vector<float>(160, 100.0f))};
379   {
380     MultiChannelContentDetector mc(
381         /*detect_stereo_content=*/detect_stereo_content,
382         /*num_render_input_channels=*/channel_count,
383         /*detection_threshold=*/0.0f,
384         /*stereo_detection_timeout_threshold_seconds=*/1,
385         /*stereo_detection_hysteresis_seconds=*/0.0f);
386     for (int k = 0; k < 20 * kNumFramesPerSecond; ++k) {
387       mc.UpdateDetection(audio_frame);
388     }
389   }
390   EXPECT_METRIC_EQ(
391       0, metrics::NumSamples("WebRTC.Audio.EchoCanceller."
392                              "ProcessingPersistentMultichannelContent"));
393   EXPECT_METRIC_EQ(
394       0, metrics::NumSamples("WebRTC.Audio.EchoCanceller."
395                              "PersistentMultichannelContentEverDetected"));
396 }
397 
398 // Tests that after 3 seconds, no metrics are reported.
TEST(MultiChannelContentDetectorMetrics,ReportsNoMetricsForShortLifetime)399 TEST(MultiChannelContentDetectorMetrics, ReportsNoMetricsForShortLifetime) {
400   metrics::Reset();
401   constexpr int kNumFramesPerSecond = 100;
402   constexpr int kTooFewFramesToLogMetrics = 3 * kNumFramesPerSecond;
403   std::vector<std::vector<std::vector<float>>> audio_frame = {
404       std::vector<std::vector<float>>(2, std::vector<float>(160, 100.0f))};
405   {
406     MultiChannelContentDetector mc(
407         /*detect_stereo_content=*/true,
408         /*num_render_input_channels=*/2,
409         /*detection_threshold=*/0.0f,
410         /*stereo_detection_timeout_threshold_seconds=*/1,
411         /*stereo_detection_hysteresis_seconds=*/0.0f);
412     for (int k = 0; k < kTooFewFramesToLogMetrics; ++k) {
413       mc.UpdateDetection(audio_frame);
414     }
415   }
416   EXPECT_METRIC_EQ(
417       0, metrics::NumSamples("WebRTC.Audio.EchoCanceller."
418                              "ProcessingPersistentMultichannelContent"));
419   EXPECT_METRIC_EQ(
420       0, metrics::NumSamples("WebRTC.Audio.EchoCanceller."
421                              "PersistentMultichannelContentEverDetected"));
422 }
423 
424 // Tests that after 25 seconds, metrics are reported.
TEST(MultiChannelContentDetectorMetrics,ReportsMetrics)425 TEST(MultiChannelContentDetectorMetrics, ReportsMetrics) {
426   metrics::Reset();
427   constexpr int kNumFramesPerSecond = 100;
428   std::vector<std::vector<std::vector<float>>> true_stereo_frame = {
429       {std::vector<float>(160, 100.0f), std::vector<float>(160, 101.0f)}};
430   std::vector<std::vector<std::vector<float>>> fake_stereo_frame = {
431       {std::vector<float>(160, 100.0f), std::vector<float>(160, 100.0f)}};
432   {
433     MultiChannelContentDetector mc(
434         /*detect_stereo_content=*/true,
435         /*num_render_input_channels=*/2,
436         /*detection_threshold=*/0.0f,
437         /*stereo_detection_timeout_threshold_seconds=*/1,
438         /*stereo_detection_hysteresis_seconds=*/0.0f);
439     for (int k = 0; k < 10 * kNumFramesPerSecond; ++k) {
440       mc.UpdateDetection(true_stereo_frame);
441     }
442     for (int k = 0; k < 15 * kNumFramesPerSecond; ++k) {
443       mc.UpdateDetection(fake_stereo_frame);
444     }
445   }
446   // After 10 seconds of true stereo and the remainder fake stereo, we expect
447   // one lifetime metric sample (multichannel detected) and two periodic samples
448   // (one multichannel, one mono).
449 
450   // Check lifetime metric.
451   EXPECT_METRIC_EQ(
452       1, metrics::NumSamples("WebRTC.Audio.EchoCanceller."
453                              "PersistentMultichannelContentEverDetected"));
454   EXPECT_METRIC_EQ(
455       1, metrics::NumEvents("WebRTC.Audio.EchoCanceller."
456                              "PersistentMultichannelContentEverDetected", 1));
457 
458   // Check periodic metric.
459   EXPECT_METRIC_EQ(
460       2, metrics::NumSamples("WebRTC.Audio.EchoCanceller."
461                              "ProcessingPersistentMultichannelContent"));
462   EXPECT_METRIC_EQ(
463       1, metrics::NumEvents("WebRTC.Audio.EchoCanceller."
464                              "ProcessingPersistentMultichannelContent", 0));
465   EXPECT_METRIC_EQ(
466       1, metrics::NumEvents("WebRTC.Audio.EchoCanceller."
467                              "ProcessingPersistentMultichannelContent", 1));
468 }
469 
470 }  // namespace webrtc
471