tor-browser

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

interpolated_gain_curve_unittest.cc (7431B)


      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/interpolated_gain_curve.h"
     12 
     13 #include <array>
     14 #include <cmath>
     15 #include <cstddef>
     16 #include <string>
     17 #include <type_traits>
     18 #include <vector>
     19 
     20 #include "common_audio/include/audio_util.h"
     21 #include "modules/audio_processing/agc2/agc2_common.h"
     22 #include "modules/audio_processing/agc2/agc2_testing_common.h"
     23 #include "modules/audio_processing/agc2/compute_interpolated_gain_curve.h"
     24 #include "modules/audio_processing/agc2/limiter_db_gain_curve.h"
     25 #include "modules/audio_processing/logging/apm_data_dumper.h"
     26 #include "test/gtest.h"
     27 
     28 namespace webrtc {
     29 namespace {
     30 
     31 constexpr double kLevelEpsilon = 1e-2 * kMaxAbsFloatS16Value;
     32 constexpr float kInterpolatedGainCurveTolerance = 1.f / 32768.f;
     33 ApmDataDumper apm_data_dumper(0);
     34 static_assert(std::is_trivially_destructible<LimiterDbGainCurve>::value, "");
     35 const LimiterDbGainCurve limiter;
     36 
     37 }  // namespace
     38 
     39 TEST(GainController2InterpolatedGainCurve, CreateUse) {
     40  InterpolatedGainCurve igc(&apm_data_dumper, "");
     41 
     42  const auto levels = test::LinSpace(
     43      kLevelEpsilon, DbfsToFloatS16(limiter.max_input_level_db() + 1), 500);
     44  for (const auto level : levels) {
     45    EXPECT_GE(igc.LookUpGainToApply(level), 0.0f);
     46  }
     47 }
     48 
     49 TEST(GainController2InterpolatedGainCurve, CheckValidOutput) {
     50  InterpolatedGainCurve igc(&apm_data_dumper, "");
     51 
     52  const auto levels = test::LinSpace(
     53      kLevelEpsilon, limiter.max_input_level_linear() * 2.0, 500);
     54  for (const auto level : levels) {
     55    SCOPED_TRACE(std::to_string(level));
     56    const float gain = igc.LookUpGainToApply(level);
     57    EXPECT_LE(0.0f, gain);
     58    EXPECT_LE(gain, 1.0f);
     59  }
     60 }
     61 
     62 TEST(GainController2InterpolatedGainCurve, CheckMonotonicity) {
     63  InterpolatedGainCurve igc(&apm_data_dumper, "");
     64 
     65  const auto levels = test::LinSpace(
     66      kLevelEpsilon, limiter.max_input_level_linear() + kLevelEpsilon + 0.5,
     67      500);
     68  float prev_gain = igc.LookUpGainToApply(0.0f);
     69  for (const auto level : levels) {
     70    const float gain = igc.LookUpGainToApply(level);
     71    EXPECT_GE(prev_gain, gain);
     72    prev_gain = gain;
     73  }
     74 }
     75 
     76 TEST(GainController2InterpolatedGainCurve, CheckApproximation) {
     77  InterpolatedGainCurve igc(&apm_data_dumper, "");
     78 
     79  const auto levels = test::LinSpace(
     80      kLevelEpsilon, limiter.max_input_level_linear() - kLevelEpsilon, 500);
     81  for (const auto level : levels) {
     82    SCOPED_TRACE(std::to_string(level));
     83    EXPECT_LT(
     84        std::fabs(limiter.GetGainLinear(level) - igc.LookUpGainToApply(level)),
     85        kInterpolatedGainCurveTolerance);
     86  }
     87 }
     88 
     89 TEST(GainController2InterpolatedGainCurve, CheckRegionBoundaries) {
     90  InterpolatedGainCurve igc(&apm_data_dumper, "");
     91 
     92  const std::vector<double> levels{
     93      {kLevelEpsilon, limiter.knee_start_linear() + kLevelEpsilon,
     94       limiter.limiter_start_linear() + kLevelEpsilon,
     95       limiter.max_input_level_linear() + kLevelEpsilon}};
     96  for (const auto level : levels) {
     97    igc.LookUpGainToApply(level);
     98  }
     99 
    100  const auto stats = igc.get_stats();
    101  EXPECT_EQ(1ul, stats.look_ups_identity_region);
    102  EXPECT_EQ(1ul, stats.look_ups_knee_region);
    103  EXPECT_EQ(1ul, stats.look_ups_limiter_region);
    104  EXPECT_EQ(1ul, stats.look_ups_saturation_region);
    105 }
    106 
    107 TEST(GainController2InterpolatedGainCurve, CheckIdentityRegion) {
    108  constexpr size_t kNumSteps = 10;
    109  InterpolatedGainCurve igc(&apm_data_dumper, "");
    110 
    111  const auto levels =
    112      test::LinSpace(kLevelEpsilon, limiter.knee_start_linear(), kNumSteps);
    113  for (const auto level : levels) {
    114    SCOPED_TRACE(std::to_string(level));
    115    EXPECT_EQ(1.0f, igc.LookUpGainToApply(level));
    116  }
    117 
    118  const auto stats = igc.get_stats();
    119  EXPECT_EQ(kNumSteps - 1, stats.look_ups_identity_region);
    120  EXPECT_EQ(1ul, stats.look_ups_knee_region);
    121  EXPECT_EQ(0ul, stats.look_ups_limiter_region);
    122  EXPECT_EQ(0ul, stats.look_ups_saturation_region);
    123 }
    124 
    125 TEST(GainController2InterpolatedGainCurve, CheckNoOverApproximationKnee) {
    126  constexpr size_t kNumSteps = 10;
    127  InterpolatedGainCurve igc(&apm_data_dumper, "");
    128 
    129  const auto levels =
    130      test::LinSpace(limiter.knee_start_linear() + kLevelEpsilon,
    131                     limiter.limiter_start_linear(), kNumSteps);
    132  for (const auto level : levels) {
    133    SCOPED_TRACE(std::to_string(level));
    134    // Small tolerance added (needed because comparing a float with a double).
    135    EXPECT_LE(igc.LookUpGainToApply(level),
    136              limiter.GetGainLinear(level) + 1e-7);
    137  }
    138 
    139  const auto stats = igc.get_stats();
    140  EXPECT_EQ(0ul, stats.look_ups_identity_region);
    141  EXPECT_EQ(kNumSteps - 1, stats.look_ups_knee_region);
    142  EXPECT_EQ(1ul, stats.look_ups_limiter_region);
    143  EXPECT_EQ(0ul, stats.look_ups_saturation_region);
    144 }
    145 
    146 TEST(GainController2InterpolatedGainCurve, CheckNoOverApproximationBeyondKnee) {
    147  constexpr size_t kNumSteps = 10;
    148  InterpolatedGainCurve igc(&apm_data_dumper, "");
    149 
    150  const auto levels = test::LinSpace(
    151      limiter.limiter_start_linear() + kLevelEpsilon,
    152      limiter.max_input_level_linear() - kLevelEpsilon, kNumSteps);
    153  for (const auto level : levels) {
    154    SCOPED_TRACE(std::to_string(level));
    155    // Small tolerance added (needed because comparing a float with a double).
    156    EXPECT_LE(igc.LookUpGainToApply(level),
    157              limiter.GetGainLinear(level) + 1e-7);
    158  }
    159 
    160  const auto stats = igc.get_stats();
    161  EXPECT_EQ(0ul, stats.look_ups_identity_region);
    162  EXPECT_EQ(0ul, stats.look_ups_knee_region);
    163  EXPECT_EQ(kNumSteps, stats.look_ups_limiter_region);
    164  EXPECT_EQ(0ul, stats.look_ups_saturation_region);
    165 }
    166 
    167 TEST(GainController2InterpolatedGainCurve,
    168     CheckNoOverApproximationWithSaturation) {
    169  constexpr size_t kNumSteps = 3;
    170  InterpolatedGainCurve igc(&apm_data_dumper, "");
    171 
    172  const auto levels = test::LinSpace(
    173      limiter.max_input_level_linear() + kLevelEpsilon,
    174      limiter.max_input_level_linear() + kLevelEpsilon + 0.5, kNumSteps);
    175  for (const auto level : levels) {
    176    SCOPED_TRACE(std::to_string(level));
    177    EXPECT_LE(igc.LookUpGainToApply(level), limiter.GetGainLinear(level));
    178  }
    179 
    180  const auto stats = igc.get_stats();
    181  EXPECT_EQ(0ul, stats.look_ups_identity_region);
    182  EXPECT_EQ(0ul, stats.look_ups_knee_region);
    183  EXPECT_EQ(0ul, stats.look_ups_limiter_region);
    184  EXPECT_EQ(kNumSteps, stats.look_ups_saturation_region);
    185 }
    186 
    187 TEST(GainController2InterpolatedGainCurve, CheckApproximationParams) {
    188  test::InterpolatedParameters parameters =
    189      test::ComputeInterpolatedGainCurveApproximationParams();
    190 
    191  InterpolatedGainCurve igc(&apm_data_dumper, "");
    192 
    193  for (size_t i = 0; i < kInterpolatedGainCurveTotalPoints; ++i) {
    194    // The tolerance levels are chosen to account for deviations due
    195    // to computing with single precision floating point numbers.
    196    EXPECT_NEAR(igc.approximation_params_x_[i],
    197                parameters.computed_approximation_params_x[i], 0.9f);
    198    EXPECT_NEAR(igc.approximation_params_m_[i],
    199                parameters.computed_approximation_params_m[i], 0.00001f);
    200    EXPECT_NEAR(igc.approximation_params_q_[i],
    201                parameters.computed_approximation_params_q[i], 0.001f);
    202  }
    203 }
    204 
    205 }  // namespace webrtc