xref: /aosp_15_r20/external/webrtc/modules/audio_processing/agc2/clipping_predictor_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2021 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/agc2/clipping_predictor.h"
12 
13 #include <cstdint>
14 #include <limits>
15 #include <tuple>
16 
17 #include "rtc_base/checks.h"
18 #include "test/gmock.h"
19 #include "test/gtest.h"
20 
21 namespace webrtc {
22 namespace {
23 
24 using ::testing::Eq;
25 using ::testing::Optional;
26 using ClippingPredictorConfig = AudioProcessing::Config::GainController1::
27     AnalogGainController::ClippingPredictor;
28 using ClippingPredictorMode = AudioProcessing::Config::GainController1::
29     AnalogGainController::ClippingPredictor::Mode;
30 
31 constexpr int kSampleRateHz = 32000;
32 constexpr int kNumChannels = 1;
33 constexpr int kSamplesPerChannel = kSampleRateHz / 100;
34 constexpr int kMaxMicLevel = 255;
35 constexpr int kMinMicLevel = 12;
36 constexpr int kDefaultClippedLevelStep = 15;
37 constexpr float kMaxSampleS16 =
38     static_cast<float>(std::numeric_limits<int16_t>::max());
39 
40 // Threshold in dB corresponding to a signal with an amplitude equal to 99% of
41 // the dynamic range - i.e., computed as `20*log10(0.99)`.
42 constexpr float kClippingThresholdDb = -0.08729610804900176f;
43 
CallAnalyze(int num_calls,const AudioFrameView<const float> & frame,ClippingPredictor & predictor)44 void CallAnalyze(int num_calls,
45                  const AudioFrameView<const float>& frame,
46                  ClippingPredictor& predictor) {
47   for (int i = 0; i < num_calls; ++i) {
48     predictor.Analyze(frame);
49   }
50 }
51 
52 // Creates and analyzes an audio frame with a non-zero (approx. 4.15dB) crest
53 // factor.
AnalyzeNonZeroCrestFactorAudio(int num_calls,int num_channels,float peak_ratio,ClippingPredictor & predictor)54 void AnalyzeNonZeroCrestFactorAudio(int num_calls,
55                                     int num_channels,
56                                     float peak_ratio,
57                                     ClippingPredictor& predictor) {
58   RTC_DCHECK_GT(num_calls, 0);
59   RTC_DCHECK_GT(num_channels, 0);
60   RTC_DCHECK_LE(peak_ratio, 1.0f);
61   std::vector<float*> audio(num_channels);
62   std::vector<float> audio_data(num_channels * kSamplesPerChannel, 0.0f);
63   for (int channel = 0; channel < num_channels; ++channel) {
64     audio[channel] = &audio_data[channel * kSamplesPerChannel];
65     for (int sample = 0; sample < kSamplesPerChannel; sample += 10) {
66       audio[channel][sample] = 0.1f * peak_ratio * kMaxSampleS16;
67       audio[channel][sample + 1] = 0.2f * peak_ratio * kMaxSampleS16;
68       audio[channel][sample + 2] = 0.3f * peak_ratio * kMaxSampleS16;
69       audio[channel][sample + 3] = 0.4f * peak_ratio * kMaxSampleS16;
70       audio[channel][sample + 4] = 0.5f * peak_ratio * kMaxSampleS16;
71       audio[channel][sample + 5] = 0.6f * peak_ratio * kMaxSampleS16;
72       audio[channel][sample + 6] = 0.7f * peak_ratio * kMaxSampleS16;
73       audio[channel][sample + 7] = 0.8f * peak_ratio * kMaxSampleS16;
74       audio[channel][sample + 8] = 0.9f * peak_ratio * kMaxSampleS16;
75       audio[channel][sample + 9] = 1.0f * peak_ratio * kMaxSampleS16;
76     }
77   }
78   AudioFrameView<const float> frame(audio.data(), num_channels,
79                                     kSamplesPerChannel);
80   CallAnalyze(num_calls, frame, predictor);
81 }
82 
CheckChannelEstimatesWithValue(int num_channels,int level,int default_step,int min_mic_level,int max_mic_level,const ClippingPredictor & predictor,int expected)83 void CheckChannelEstimatesWithValue(int num_channels,
84                                     int level,
85                                     int default_step,
86                                     int min_mic_level,
87                                     int max_mic_level,
88                                     const ClippingPredictor& predictor,
89                                     int expected) {
90   for (int i = 0; i < num_channels; ++i) {
91     SCOPED_TRACE(i);
92     EXPECT_THAT(predictor.EstimateClippedLevelStep(
93                     i, level, default_step, min_mic_level, max_mic_level),
94                 Optional(Eq(expected)));
95   }
96 }
97 
CheckChannelEstimatesWithoutValue(int num_channels,int level,int default_step,int min_mic_level,int max_mic_level,const ClippingPredictor & predictor)98 void CheckChannelEstimatesWithoutValue(int num_channels,
99                                        int level,
100                                        int default_step,
101                                        int min_mic_level,
102                                        int max_mic_level,
103                                        const ClippingPredictor& predictor) {
104   for (int i = 0; i < num_channels; ++i) {
105     SCOPED_TRACE(i);
106     EXPECT_EQ(predictor.EstimateClippedLevelStep(i, level, default_step,
107                                                  min_mic_level, max_mic_level),
108               absl::nullopt);
109   }
110 }
111 
112 // Creates and analyzes an audio frame with a zero crest factor.
AnalyzeZeroCrestFactorAudio(int num_calls,int num_channels,float peak_ratio,ClippingPredictor & predictor)113 void AnalyzeZeroCrestFactorAudio(int num_calls,
114                                  int num_channels,
115                                  float peak_ratio,
116                                  ClippingPredictor& predictor) {
117   RTC_DCHECK_GT(num_calls, 0);
118   RTC_DCHECK_GT(num_channels, 0);
119   RTC_DCHECK_LE(peak_ratio, 1.f);
120   std::vector<float*> audio(num_channels);
121   std::vector<float> audio_data(num_channels * kSamplesPerChannel, 0.f);
122   for (int channel = 0; channel < num_channels; ++channel) {
123     audio[channel] = &audio_data[channel * kSamplesPerChannel];
124     for (int sample = 0; sample < kSamplesPerChannel; ++sample) {
125       audio[channel][sample] = peak_ratio * kMaxSampleS16;
126     }
127   }
128   auto frame = AudioFrameView<const float>(audio.data(), num_channels,
129                                            kSamplesPerChannel);
130   CallAnalyze(num_calls, frame, predictor);
131 }
132 
TEST(ClippingPeakPredictorTest,NoPredictorCreated)133 TEST(ClippingPeakPredictorTest, NoPredictorCreated) {
134   auto predictor =
135       CreateClippingPredictor(kNumChannels, /*config=*/{/*enabled=*/false});
136   EXPECT_FALSE(predictor);
137 }
138 
TEST(ClippingPeakPredictorTest,ClippingEventPredictionCreated)139 TEST(ClippingPeakPredictorTest, ClippingEventPredictionCreated) {
140   // TODO(bugs.webrtc.org/12874): Use designated initializers one fixed.
141   auto predictor = CreateClippingPredictor(
142       kNumChannels,
143       /*config=*/{/*enabled=*/true,
144                   /*mode=*/ClippingPredictorMode::kClippingEventPrediction});
145   EXPECT_TRUE(predictor);
146 }
147 
TEST(ClippingPeakPredictorTest,AdaptiveStepClippingPeakPredictionCreated)148 TEST(ClippingPeakPredictorTest, AdaptiveStepClippingPeakPredictionCreated) {
149   // TODO(bugs.webrtc.org/12874): Use designated initializers one fixed.
150   auto predictor = CreateClippingPredictor(
151       kNumChannels, /*config=*/{
152           /*enabled=*/true,
153           /*mode=*/ClippingPredictorMode::kAdaptiveStepClippingPeakPrediction});
154   EXPECT_TRUE(predictor);
155 }
156 
TEST(ClippingPeakPredictorTest,FixedStepClippingPeakPredictionCreated)157 TEST(ClippingPeakPredictorTest, FixedStepClippingPeakPredictionCreated) {
158   // TODO(bugs.webrtc.org/12874): Use designated initializers one fixed.
159   auto predictor = CreateClippingPredictor(
160       kNumChannels, /*config=*/{
161           /*enabled=*/true,
162           /*mode=*/ClippingPredictorMode::kFixedStepClippingPeakPrediction});
163   EXPECT_TRUE(predictor);
164 }
165 
166 class ClippingPredictorParameterization
167     : public ::testing::TestWithParam<std::tuple<int, int, int, int>> {
168  protected:
num_channels() const169   int num_channels() const { return std::get<0>(GetParam()); }
GetConfig(ClippingPredictorMode mode) const170   ClippingPredictorConfig GetConfig(ClippingPredictorMode mode) const {
171     // TODO(bugs.webrtc.org/12874): Use designated initializers one fixed.
172     return {/*enabled=*/true,
173             /*mode=*/mode,
174             /*window_length=*/std::get<1>(GetParam()),
175             /*reference_window_length=*/std::get<2>(GetParam()),
176             /*reference_window_delay=*/std::get<3>(GetParam()),
177             /*clipping_threshold=*/-1.0f,
178             /*crest_factor_margin=*/0.5f};
179   }
180 };
181 
TEST_P(ClippingPredictorParameterization,CheckClippingEventPredictorEstimateAfterCrestFactorDrop)182 TEST_P(ClippingPredictorParameterization,
183        CheckClippingEventPredictorEstimateAfterCrestFactorDrop) {
184   const ClippingPredictorConfig config =
185       GetConfig(ClippingPredictorMode::kClippingEventPrediction);
186   if (config.reference_window_length + config.reference_window_delay <=
187       config.window_length) {
188     return;
189   }
190   auto predictor = CreateClippingPredictor(num_channels(), config);
191   AnalyzeNonZeroCrestFactorAudio(
192       /*num_calls=*/config.reference_window_length +
193           config.reference_window_delay - config.window_length,
194       num_channels(), /*peak_ratio=*/0.99f, *predictor);
195   CheckChannelEstimatesWithoutValue(num_channels(), /*level=*/255,
196                                     kDefaultClippedLevelStep, kMinMicLevel,
197                                     kMaxMicLevel, *predictor);
198   AnalyzeZeroCrestFactorAudio(config.window_length, num_channels(),
199                               /*peak_ratio=*/0.99f, *predictor);
200   CheckChannelEstimatesWithValue(
201       num_channels(), /*level=*/255, kDefaultClippedLevelStep, kMinMicLevel,
202       kMaxMicLevel, *predictor, kDefaultClippedLevelStep);
203 }
204 
TEST_P(ClippingPredictorParameterization,CheckClippingEventPredictorNoEstimateAfterConstantCrestFactor)205 TEST_P(ClippingPredictorParameterization,
206        CheckClippingEventPredictorNoEstimateAfterConstantCrestFactor) {
207   const ClippingPredictorConfig config =
208       GetConfig(ClippingPredictorMode::kClippingEventPrediction);
209   if (config.reference_window_length + config.reference_window_delay <=
210       config.window_length) {
211     return;
212   }
213   auto predictor = CreateClippingPredictor(num_channels(), config);
214   AnalyzeNonZeroCrestFactorAudio(
215       /*num_calls=*/config.reference_window_length +
216           config.reference_window_delay - config.window_length,
217       num_channels(), /*peak_ratio=*/0.99f, *predictor);
218   CheckChannelEstimatesWithoutValue(num_channels(), /*level=*/255,
219                                     kDefaultClippedLevelStep, kMinMicLevel,
220                                     kMaxMicLevel, *predictor);
221   AnalyzeNonZeroCrestFactorAudio(/*num_calls=*/config.window_length,
222                                  num_channels(),
223                                  /*peak_ratio=*/0.99f, *predictor);
224   CheckChannelEstimatesWithoutValue(num_channels(), /*level=*/255,
225                                     kDefaultClippedLevelStep, kMinMicLevel,
226                                     kMaxMicLevel, *predictor);
227 }
228 
TEST_P(ClippingPredictorParameterization,CheckClippingPeakPredictorEstimateAfterHighCrestFactor)229 TEST_P(ClippingPredictorParameterization,
230        CheckClippingPeakPredictorEstimateAfterHighCrestFactor) {
231   const ClippingPredictorConfig config =
232       GetConfig(ClippingPredictorMode::kAdaptiveStepClippingPeakPrediction);
233   if (config.reference_window_length + config.reference_window_delay <=
234       config.window_length) {
235     return;
236   }
237   auto predictor = CreateClippingPredictor(num_channels(), config);
238   AnalyzeNonZeroCrestFactorAudio(
239       /*num_calls=*/config.reference_window_length +
240           config.reference_window_delay - config.window_length,
241       num_channels(), /*peak_ratio=*/0.99f, *predictor);
242   CheckChannelEstimatesWithoutValue(num_channels(), /*level=*/255,
243                                     kDefaultClippedLevelStep, kMinMicLevel,
244                                     kMaxMicLevel, *predictor);
245   AnalyzeNonZeroCrestFactorAudio(/*num_calls=*/config.window_length,
246                                  num_channels(),
247                                  /*peak_ratio=*/0.99f, *predictor);
248   CheckChannelEstimatesWithValue(
249       num_channels(), /*level=*/255, kDefaultClippedLevelStep, kMinMicLevel,
250       kMaxMicLevel, *predictor, kDefaultClippedLevelStep);
251 }
252 
TEST_P(ClippingPredictorParameterization,CheckClippingPeakPredictorNoEstimateAfterLowCrestFactor)253 TEST_P(ClippingPredictorParameterization,
254        CheckClippingPeakPredictorNoEstimateAfterLowCrestFactor) {
255   const ClippingPredictorConfig config =
256       GetConfig(ClippingPredictorMode::kAdaptiveStepClippingPeakPrediction);
257   if (config.reference_window_length + config.reference_window_delay <=
258       config.window_length) {
259     return;
260   }
261   auto predictor = CreateClippingPredictor(num_channels(), config);
262   AnalyzeZeroCrestFactorAudio(
263       /*num_calls=*/config.reference_window_length +
264           config.reference_window_delay - config.window_length,
265       num_channels(), /*peak_ratio=*/0.99f, *predictor);
266   CheckChannelEstimatesWithoutValue(num_channels(), /*level=*/255,
267                                     kDefaultClippedLevelStep, kMinMicLevel,
268                                     kMaxMicLevel, *predictor);
269   AnalyzeNonZeroCrestFactorAudio(/*num_calls=*/config.window_length,
270                                  num_channels(),
271                                  /*peak_ratio=*/0.99f, *predictor);
272   CheckChannelEstimatesWithoutValue(num_channels(), /*level=*/255,
273                                     kDefaultClippedLevelStep, kMinMicLevel,
274                                     kMaxMicLevel, *predictor);
275 }
276 
277 INSTANTIATE_TEST_SUITE_P(GainController1ClippingPredictor,
278                          ClippingPredictorParameterization,
279                          ::testing::Combine(::testing::Values(1, 5),
280                                             ::testing::Values(1, 5, 10),
281                                             ::testing::Values(1, 5),
282                                             ::testing::Values(0, 1, 5)));
283 
284 class ClippingEventPredictorParameterization
285     : public ::testing::TestWithParam<std::tuple<float, float>> {
286  protected:
GetConfig() const287   ClippingPredictorConfig GetConfig() const {
288     // TODO(bugs.webrtc.org/12874): Use designated initializers one fixed.
289     return {/*enabled=*/true,
290             /*mode=*/ClippingPredictorMode::kClippingEventPrediction,
291             /*window_length=*/5,
292             /*reference_window_length=*/5,
293             /*reference_window_delay=*/5,
294             /*clipping_threshold=*/std::get<0>(GetParam()),
295             /*crest_factor_margin=*/std::get<1>(GetParam())};
296   }
297 };
298 
TEST_P(ClippingEventPredictorParameterization,CheckEstimateAfterCrestFactorDrop)299 TEST_P(ClippingEventPredictorParameterization,
300        CheckEstimateAfterCrestFactorDrop) {
301   const ClippingPredictorConfig config = GetConfig();
302   auto predictor = CreateClippingPredictor(kNumChannels, config);
303   AnalyzeNonZeroCrestFactorAudio(/*num_calls=*/config.reference_window_length,
304                                  kNumChannels, /*peak_ratio=*/0.99f,
305                                  *predictor);
306   CheckChannelEstimatesWithoutValue(kNumChannels, /*level=*/255,
307                                     kDefaultClippedLevelStep, kMinMicLevel,
308                                     kMaxMicLevel, *predictor);
309   AnalyzeZeroCrestFactorAudio(config.window_length, kNumChannels,
310                               /*peak_ratio=*/0.99f, *predictor);
311   // TODO(bugs.webrtc.org/12774): Add clarifying comment.
312   // TODO(bugs.webrtc.org/12774): Remove 4.15f threshold and split tests.
313   if (config.clipping_threshold < kClippingThresholdDb &&
314       config.crest_factor_margin < 4.15f) {
315     CheckChannelEstimatesWithValue(
316         kNumChannels, /*level=*/255, kDefaultClippedLevelStep, kMinMicLevel,
317         kMaxMicLevel, *predictor, kDefaultClippedLevelStep);
318   } else {
319     CheckChannelEstimatesWithoutValue(kNumChannels, /*level=*/255,
320                                       kDefaultClippedLevelStep, kMinMicLevel,
321                                       kMaxMicLevel, *predictor);
322   }
323 }
324 
325 INSTANTIATE_TEST_SUITE_P(GainController1ClippingPredictor,
326                          ClippingEventPredictorParameterization,
327                          ::testing::Combine(::testing::Values(-1.0f, 0.0f),
328                                             ::testing::Values(3.0f, 4.16f)));
329 
330 class ClippingPredictorModeParameterization
331     : public ::testing::TestWithParam<ClippingPredictorMode> {
332  protected:
GetConfig(float clipping_threshold_dbfs) const333   ClippingPredictorConfig GetConfig(float clipping_threshold_dbfs) const {
334     // TODO(bugs.webrtc.org/12874): Use designated initializers one fixed.
335     return {/*enabled=*/true,
336             /*mode=*/GetParam(),
337             /*window_length=*/5,
338             /*reference_window_length=*/5,
339             /*reference_window_delay=*/5,
340             /*clipping_threshold=*/clipping_threshold_dbfs,
341             /*crest_factor_margin=*/3.0f};
342   }
343 };
344 
TEST_P(ClippingPredictorModeParameterization,CheckEstimateAfterHighCrestFactorWithNoClippingMargin)345 TEST_P(ClippingPredictorModeParameterization,
346        CheckEstimateAfterHighCrestFactorWithNoClippingMargin) {
347   const ClippingPredictorConfig config = GetConfig(
348       /*clipping_threshold_dbfs=*/0.0f);
349   auto predictor = CreateClippingPredictor(kNumChannels, config);
350   AnalyzeNonZeroCrestFactorAudio(/*num_calls=*/config.reference_window_length,
351                                  kNumChannels, /*peak_ratio=*/0.99f,
352                                  *predictor);
353   CheckChannelEstimatesWithoutValue(kNumChannels, /*level=*/255,
354                                     kDefaultClippedLevelStep, kMinMicLevel,
355                                     kMaxMicLevel, *predictor);
356   AnalyzeZeroCrestFactorAudio(config.window_length, kNumChannels,
357                               /*peak_ratio=*/0.99f, *predictor);
358   // Since the clipping threshold is set to 0 dBFS, `EstimateClippedLevelStep()`
359   // is expected to return an unavailable value.
360   CheckChannelEstimatesWithoutValue(kNumChannels, /*level=*/255,
361                                     kDefaultClippedLevelStep, kMinMicLevel,
362                                     kMaxMicLevel, *predictor);
363 }
364 
TEST_P(ClippingPredictorModeParameterization,CheckEstimateAfterHighCrestFactorWithClippingMargin)365 TEST_P(ClippingPredictorModeParameterization,
366        CheckEstimateAfterHighCrestFactorWithClippingMargin) {
367   const ClippingPredictorConfig config =
368       GetConfig(/*clipping_threshold_dbfs=*/-1.0f);
369   auto predictor = CreateClippingPredictor(kNumChannels, config);
370   AnalyzeNonZeroCrestFactorAudio(/*num_calls=*/config.reference_window_length,
371                                  kNumChannels,
372                                  /*peak_ratio=*/0.99f, *predictor);
373   CheckChannelEstimatesWithoutValue(kNumChannels, /*level=*/255,
374                                     kDefaultClippedLevelStep, kMinMicLevel,
375                                     kMaxMicLevel, *predictor);
376   AnalyzeZeroCrestFactorAudio(config.window_length, kNumChannels,
377                               /*peak_ratio=*/0.99f, *predictor);
378   // TODO(bugs.webrtc.org/12774): Add clarifying comment.
379   const float expected_step =
380       config.mode == ClippingPredictorMode::kAdaptiveStepClippingPeakPrediction
381           ? 17
382           : kDefaultClippedLevelStep;
383   CheckChannelEstimatesWithValue(kNumChannels, /*level=*/255,
384                                  kDefaultClippedLevelStep, kMinMicLevel,
385                                  kMaxMicLevel, *predictor, expected_step);
386 }
387 
388 INSTANTIATE_TEST_SUITE_P(
389     GainController1ClippingPredictor,
390     ClippingPredictorModeParameterization,
391     ::testing::Values(
392         ClippingPredictorMode::kAdaptiveStepClippingPeakPrediction,
393         ClippingPredictorMode::kFixedStepClippingPeakPrediction));
394 
TEST(ClippingEventPredictorTest,CheckEstimateAfterReset)395 TEST(ClippingEventPredictorTest, CheckEstimateAfterReset) {
396   // TODO(bugs.webrtc.org/12874): Use designated initializers one fixed.
397   constexpr ClippingPredictorConfig kConfig{
398       /*enabled=*/true,
399       /*mode=*/ClippingPredictorMode::kClippingEventPrediction,
400       /*window_length=*/5,
401       /*reference_window_length=*/5,
402       /*reference_window_delay=*/5,
403       /*clipping_threshold=*/-1.0f,
404       /*crest_factor_margin=*/3.0f};
405   auto predictor = CreateClippingPredictor(kNumChannels, kConfig);
406   AnalyzeNonZeroCrestFactorAudio(/*num_calls=*/kConfig.reference_window_length,
407                                  kNumChannels,
408                                  /*peak_ratio=*/0.99f, *predictor);
409   CheckChannelEstimatesWithoutValue(kNumChannels, /*level=*/255,
410                                     kDefaultClippedLevelStep, kMinMicLevel,
411                                     kMaxMicLevel, *predictor);
412   predictor->Reset();
413   AnalyzeZeroCrestFactorAudio(kConfig.window_length, kNumChannels,
414                               /*peak_ratio=*/0.99f, *predictor);
415   CheckChannelEstimatesWithoutValue(kNumChannels, /*level=*/255,
416                                     kDefaultClippedLevelStep, kMinMicLevel,
417                                     kMaxMicLevel, *predictor);
418 }
419 
TEST(ClippingPeakPredictorTest,CheckNoEstimateAfterReset)420 TEST(ClippingPeakPredictorTest, CheckNoEstimateAfterReset) {
421   // TODO(bugs.webrtc.org/12874): Use designated initializers one fixed.
422   constexpr ClippingPredictorConfig kConfig{
423       /*enabled=*/true,
424       /*mode=*/ClippingPredictorMode::kAdaptiveStepClippingPeakPrediction,
425       /*window_length=*/5,
426       /*reference_window_length=*/5,
427       /*reference_window_delay=*/5,
428       /*clipping_threshold=*/-1.0f};
429   auto predictor = CreateClippingPredictor(kNumChannels, kConfig);
430   AnalyzeNonZeroCrestFactorAudio(/*num_calls=*/kConfig.reference_window_length,
431                                  kNumChannels,
432                                  /*peak_ratio=*/0.99f, *predictor);
433   CheckChannelEstimatesWithoutValue(kNumChannels, /*level=*/255,
434                                     kDefaultClippedLevelStep, kMinMicLevel,
435                                     kMaxMicLevel, *predictor);
436   predictor->Reset();
437   AnalyzeZeroCrestFactorAudio(kConfig.window_length, kNumChannels,
438                               /*peak_ratio=*/0.99f, *predictor);
439   CheckChannelEstimatesWithoutValue(kNumChannels, /*level=*/255,
440                                     kDefaultClippedLevelStep, kMinMicLevel,
441                                     kMaxMicLevel, *predictor);
442 }
443 
TEST(ClippingPeakPredictorTest,CheckAdaptiveStepEstimate)444 TEST(ClippingPeakPredictorTest, CheckAdaptiveStepEstimate) {
445   // TODO(bugs.webrtc.org/12874): Use designated initializers one fixed.
446   constexpr ClippingPredictorConfig kConfig{
447       /*enabled=*/true,
448       /*mode=*/ClippingPredictorMode::kAdaptiveStepClippingPeakPrediction,
449       /*window_length=*/5,
450       /*reference_window_length=*/5,
451       /*reference_window_delay=*/5,
452       /*clipping_threshold=*/-1.0f};
453   auto predictor = CreateClippingPredictor(kNumChannels, kConfig);
454   AnalyzeNonZeroCrestFactorAudio(/*num_calls=*/kConfig.reference_window_length,
455                                  kNumChannels, /*peak_ratio=*/0.99f,
456                                  *predictor);
457   CheckChannelEstimatesWithoutValue(kNumChannels, /*level=*/255,
458                                     kDefaultClippedLevelStep, kMinMicLevel,
459                                     kMaxMicLevel, *predictor);
460   AnalyzeZeroCrestFactorAudio(kConfig.window_length, kNumChannels,
461                               /*peak_ratio=*/0.99f, *predictor);
462   CheckChannelEstimatesWithValue(kNumChannels, /*level=*/255,
463                                  kDefaultClippedLevelStep, kMinMicLevel,
464                                  kMaxMicLevel, *predictor, /*expected=*/17);
465 }
466 
TEST(ClippingPeakPredictorTest,CheckFixedStepEstimate)467 TEST(ClippingPeakPredictorTest, CheckFixedStepEstimate) {
468   // TODO(bugs.webrtc.org/12874): Use designated initializers one fixed.
469   constexpr ClippingPredictorConfig kConfig{
470       /*enabled=*/true,
471       /*mode=*/ClippingPredictorMode::kFixedStepClippingPeakPrediction,
472       /*window_length=*/5,
473       /*reference_window_length=*/5,
474       /*reference_window_delay=*/5,
475       /*clipping_threshold=*/-1.0f};
476   auto predictor = CreateClippingPredictor(kNumChannels, kConfig);
477   AnalyzeNonZeroCrestFactorAudio(/*num_calls=*/kConfig.reference_window_length,
478                                  kNumChannels, /*peak_ratio=*/0.99f,
479                                  *predictor);
480   CheckChannelEstimatesWithoutValue(kNumChannels, /*level=*/255,
481                                     kDefaultClippedLevelStep, kMinMicLevel,
482                                     kMaxMicLevel, *predictor);
483   AnalyzeZeroCrestFactorAudio(kConfig.window_length, kNumChannels,
484                               /*peak_ratio=*/0.99f, *predictor);
485   CheckChannelEstimatesWithValue(
486       kNumChannels, /*level=*/255, kDefaultClippedLevelStep, kMinMicLevel,
487       kMaxMicLevel, *predictor, kDefaultClippedLevelStep);
488 }
489 
490 }  // namespace
491 }  // namespace webrtc
492