tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

saturation_protector_unittest.cc (6318B)


      1 /*
      2 *  Copyright (c) 2018 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/saturation_protector.h"
     12 
     13 #include <algorithm>
     14 #include <cmath>
     15 
     16 #include "modules/audio_processing/agc2/agc2_common.h"
     17 #include "modules/audio_processing/logging/apm_data_dumper.h"
     18 #include "test/gtest.h"
     19 
     20 namespace webrtc {
     21 namespace {
     22 
     23 constexpr float kInitialHeadroomDb = 20.0f;
     24 constexpr int kNoAdjacentSpeechFramesRequired = 1;
     25 constexpr float kMaxSpeechProbability = 1.0f;
     26 
     27 // Calls `Analyze(speech_probability, peak_dbfs, speech_level_dbfs)`
     28 // `num_iterations` times on `saturation_protector` and return the largest
     29 // headroom difference between two consecutive calls.
     30 float RunOnConstantLevel(int num_iterations,
     31                         float speech_probability,
     32                         float peak_dbfs,
     33                         float speech_level_dbfs,
     34                         SaturationProtector& saturation_protector) {
     35  float last_headroom = saturation_protector.HeadroomDb();
     36  float max_difference = 0.0f;
     37  for (int i = 0; i < num_iterations; ++i) {
     38    saturation_protector.Analyze(speech_probability, peak_dbfs,
     39                                 speech_level_dbfs);
     40    const float new_headroom = saturation_protector.HeadroomDb();
     41    max_difference =
     42        std::max(max_difference, std::fabs(new_headroom - last_headroom));
     43    last_headroom = new_headroom;
     44  }
     45  return max_difference;
     46 }
     47 
     48 // Checks that the returned headroom value is correctly reset.
     49 TEST(GainController2SaturationProtector, Reset) {
     50  ApmDataDumper apm_data_dumper(0);
     51  auto saturation_protector = CreateSaturationProtector(
     52      kInitialHeadroomDb, kNoAdjacentSpeechFramesRequired, &apm_data_dumper);
     53  const float initial_headroom_db = saturation_protector->HeadroomDb();
     54  RunOnConstantLevel(/*num_iterations=*/10, kMaxSpeechProbability,
     55                     /*peak_dbfs=*/0.0f,
     56                     /*speech_level_dbfs=*/-10.0f, *saturation_protector);
     57  // Make sure that there are side-effects.
     58  ASSERT_NE(initial_headroom_db, saturation_protector->HeadroomDb());
     59  saturation_protector->Reset();
     60  EXPECT_EQ(initial_headroom_db, saturation_protector->HeadroomDb());
     61 }
     62 
     63 // Checks that the estimate converges to the ratio between peaks and level
     64 // estimator values after a while.
     65 TEST(GainController2SaturationProtector, EstimatesCrestRatio) {
     66  constexpr int kNumIterations = 2000;
     67  constexpr float kPeakLevelDbfs = -20.0f;
     68  constexpr float kCrestFactorDb = kInitialHeadroomDb + 1.0f;
     69  constexpr float kSpeechLevelDbfs = kPeakLevelDbfs - kCrestFactorDb;
     70  const float kMaxDifferenceDb =
     71      0.5f * std::fabs(kInitialHeadroomDb - kCrestFactorDb);
     72 
     73  ApmDataDumper apm_data_dumper(0);
     74  auto saturation_protector = CreateSaturationProtector(
     75      kInitialHeadroomDb, kNoAdjacentSpeechFramesRequired, &apm_data_dumper);
     76  RunOnConstantLevel(kNumIterations, kMaxSpeechProbability, kPeakLevelDbfs,
     77                     kSpeechLevelDbfs, *saturation_protector);
     78  EXPECT_NEAR(saturation_protector->HeadroomDb(), kCrestFactorDb,
     79              kMaxDifferenceDb);
     80 }
     81 
     82 // Checks that the headroom does not change too quickly.
     83 TEST(GainController2SaturationProtector, ChangeSlowly) {
     84  constexpr int kNumIterations = 1000;
     85  constexpr float kPeakLevelDbfs = -20.f;
     86  constexpr float kCrestFactorDb = kInitialHeadroomDb - 5.f;
     87  constexpr float kOtherCrestFactorDb = kInitialHeadroomDb;
     88  constexpr float kSpeechLevelDbfs = kPeakLevelDbfs - kCrestFactorDb;
     89  constexpr float kOtherSpeechLevelDbfs = kPeakLevelDbfs - kOtherCrestFactorDb;
     90 
     91  ApmDataDumper apm_data_dumper(0);
     92  auto saturation_protector = CreateSaturationProtector(
     93      kInitialHeadroomDb, kNoAdjacentSpeechFramesRequired, &apm_data_dumper);
     94  float max_difference_db =
     95      RunOnConstantLevel(kNumIterations, kMaxSpeechProbability, kPeakLevelDbfs,
     96                         kSpeechLevelDbfs, *saturation_protector);
     97  max_difference_db = std::max(
     98      RunOnConstantLevel(kNumIterations, kMaxSpeechProbability, kPeakLevelDbfs,
     99                         kOtherSpeechLevelDbfs, *saturation_protector),
    100      max_difference_db);
    101  constexpr float kMaxChangeSpeedDbPerSecond = 0.5f;  // 1 db / 2 seconds.
    102  EXPECT_LE(max_difference_db,
    103            kMaxChangeSpeedDbPerSecond / 1000 * kFrameDurationMs);
    104 }
    105 
    106 class SaturationProtectorParametrization
    107    : public ::testing::TestWithParam<int> {
    108 protected:
    109  int adjacent_speech_frames_threshold() const { return GetParam(); }
    110 };
    111 
    112 TEST_P(SaturationProtectorParametrization, DoNotAdaptToShortSpeechSegments) {
    113  ApmDataDumper apm_data_dumper(0);
    114  auto saturation_protector = CreateSaturationProtector(
    115      kInitialHeadroomDb, adjacent_speech_frames_threshold(), &apm_data_dumper);
    116  const float initial_headroom_db = saturation_protector->HeadroomDb();
    117  RunOnConstantLevel(/*num_iterations=*/adjacent_speech_frames_threshold() - 1,
    118                     kMaxSpeechProbability,
    119                     /*peak_dbfs=*/0.0f,
    120                     /*speech_level_dbfs=*/-10.0f, *saturation_protector);
    121  // No adaptation expected.
    122  EXPECT_EQ(initial_headroom_db, saturation_protector->HeadroomDb());
    123 }
    124 
    125 TEST_P(SaturationProtectorParametrization, AdaptToEnoughSpeechSegments) {
    126  ApmDataDumper apm_data_dumper(0);
    127  auto saturation_protector = CreateSaturationProtector(
    128      kInitialHeadroomDb, adjacent_speech_frames_threshold(), &apm_data_dumper);
    129  const float initial_headroom_db = saturation_protector->HeadroomDb();
    130  RunOnConstantLevel(/*num_iterations=*/adjacent_speech_frames_threshold() + 1,
    131                     kMaxSpeechProbability,
    132                     /*peak_dbfs=*/0.0f,
    133                     /*speech_level_dbfs=*/-10.0f, *saturation_protector);
    134  // Adaptation expected.
    135  EXPECT_NE(initial_headroom_db, saturation_protector->HeadroomDb());
    136 }
    137 
    138 INSTANTIATE_TEST_SUITE_P(GainController2,
    139                         SaturationProtectorParametrization,
    140                         ::testing::Values(2, 9, 17));
    141 
    142 }  // namespace
    143 }  // namespace webrtc