interpolated_gain_curve.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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. #ifndef MODULES_AUDIO_PROCESSING_AGC2_INTERPOLATED_GAIN_CURVE_H_
  11. #define MODULES_AUDIO_PROCESSING_AGC2_INTERPOLATED_GAIN_CURVE_H_
  12. #include <array>
  13. #include <string>
  14. #include "modules/audio_processing/agc2/agc2_common.h"
  15. #include "rtc_base/constructor_magic.h"
  16. #include "rtc_base/gtest_prod_util.h"
  17. #include "system_wrappers/include/metrics.h"
  18. namespace webrtc {
  19. class ApmDataDumper;
  20. constexpr float kInputLevelScalingFactor = 32768.0f;
  21. // Defined as DbfsToLinear(kLimiterMaxInputLevelDbFs)
  22. constexpr float kMaxInputLevelLinear = static_cast<float>(36766.300710566735);
  23. // Interpolated gain curve using under-approximation to avoid saturation.
  24. //
  25. // The goal of this class is allowing fast look ups to get an accurate
  26. // estimates of the gain to apply given an estimated input level.
  27. class InterpolatedGainCurve {
  28. public:
  29. enum class GainCurveRegion {
  30. kIdentity = 0,
  31. kKnee = 1,
  32. kLimiter = 2,
  33. kSaturation = 3
  34. };
  35. struct Stats {
  36. // Region in which the output level equals the input one.
  37. size_t look_ups_identity_region = 0;
  38. // Smoothing between the identity and the limiter regions.
  39. size_t look_ups_knee_region = 0;
  40. // Limiter region in which the output and input levels are linearly related.
  41. size_t look_ups_limiter_region = 0;
  42. // Region in which saturation may occur since the input level is beyond the
  43. // maximum expected by the limiter.
  44. size_t look_ups_saturation_region = 0;
  45. // True if stats have been populated.
  46. bool available = false;
  47. // The current region, and for how many frames the level has been
  48. // in that region.
  49. GainCurveRegion region = GainCurveRegion::kIdentity;
  50. int64_t region_duration_frames = 0;
  51. };
  52. InterpolatedGainCurve(ApmDataDumper* apm_data_dumper,
  53. std::string histogram_name_prefix);
  54. ~InterpolatedGainCurve();
  55. Stats get_stats() const { return stats_; }
  56. // Given a non-negative input level (linear scale), a scalar factor to apply
  57. // to a sub-frame is returned.
  58. // Levels above kLimiterMaxInputLevelDbFs will be reduced to 0 dBFS
  59. // after applying this gain
  60. float LookUpGainToApply(float input_level) const;
  61. private:
  62. // For comparing 'approximation_params_*_' with ones computed by
  63. // ComputeInterpolatedGainCurve.
  64. FRIEND_TEST_ALL_PREFIXES(AutomaticGainController2InterpolatedGainCurve,
  65. CheckApproximationParams);
  66. struct RegionLogger {
  67. metrics::Histogram* identity_histogram;
  68. metrics::Histogram* knee_histogram;
  69. metrics::Histogram* limiter_histogram;
  70. metrics::Histogram* saturation_histogram;
  71. RegionLogger(std::string identity_histogram_name,
  72. std::string knee_histogram_name,
  73. std::string limiter_histogram_name,
  74. std::string saturation_histogram_name);
  75. ~RegionLogger();
  76. void LogRegionStats(const InterpolatedGainCurve::Stats& stats) const;
  77. } region_logger_;
  78. void UpdateStats(float input_level) const;
  79. ApmDataDumper* const apm_data_dumper_;
  80. static constexpr std::array<float, kInterpolatedGainCurveTotalPoints>
  81. approximation_params_x_ = {
  82. {30057.296875, 30148.986328125, 30240.67578125, 30424.052734375,
  83. 30607.4296875, 30790.806640625, 30974.18359375, 31157.560546875,
  84. 31340.939453125, 31524.31640625, 31707.693359375, 31891.0703125,
  85. 32074.447265625, 32257.82421875, 32441.201171875, 32624.580078125,
  86. 32807.95703125, 32991.33203125, 33174.7109375, 33358.08984375,
  87. 33541.46484375, 33724.84375, 33819.53515625, 34009.5390625,
  88. 34200.05859375, 34389.81640625, 34674.48828125, 35054.375,
  89. 35434.86328125, 35814.81640625, 36195.16796875, 36575.03125}};
  90. static constexpr std::array<float, kInterpolatedGainCurveTotalPoints>
  91. approximation_params_m_ = {
  92. {-3.515235675877192989e-07, -1.050251626111275982e-06,
  93. -2.085213736791047268e-06, -3.443004743530764244e-06,
  94. -4.773849468620028347e-06, -6.077375928725814447e-06,
  95. -7.353257842623861507e-06, -8.601219633419532329e-06,
  96. -9.821013009059242904e-06, -1.101243378798244521e-05,
  97. -1.217532644659513608e-05, -1.330956911260727793e-05,
  98. -1.441507538402220234e-05, -1.549179251014720649e-05,
  99. -1.653970684856176376e-05, -1.755882840370759368e-05,
  100. -1.854918446042574942e-05, -1.951086778717581183e-05,
  101. -2.044398024736437947e-05, -2.1348627342376858e-05,
  102. -2.222496914328075945e-05, -2.265374678245279938e-05,
  103. -2.242570917587727308e-05, -2.220122041762806475e-05,
  104. -2.19802095671184361e-05, -2.176260204578284174e-05,
  105. -2.133731686626560986e-05, -2.092481918225530535e-05,
  106. -2.052459603874012828e-05, -2.013615448959171772e-05,
  107. -1.975903069251216948e-05, -1.939277899509761482e-05}};
  108. static constexpr std::array<float, kInterpolatedGainCurveTotalPoints>
  109. approximation_params_q_ = {
  110. {1.010565876960754395, 1.031631827354431152, 1.062929749488830566,
  111. 1.104239225387573242, 1.144973039627075195, 1.185109615325927734,
  112. 1.224629044532775879, 1.263512492179870605, 1.301741957664489746,
  113. 1.339300632476806641, 1.376173257827758789, 1.412345528602600098,
  114. 1.447803974151611328, 1.482536554336547852, 1.516532182693481445,
  115. 1.549780607223510742, 1.582272171974182129, 1.613999366760253906,
  116. 1.644955039024353027, 1.675132393836975098, 1.704526185989379883,
  117. 1.718986630439758301, 1.711274504661560059, 1.703639745712280273,
  118. 1.696081161499023438, 1.688597679138183594, 1.673851132392883301,
  119. 1.659391283988952637, 1.645209431648254395, 1.631297469139099121,
  120. 1.617647409439086914, 1.604251742362976074}};
  121. // Stats.
  122. mutable Stats stats_;
  123. RTC_DISALLOW_COPY_AND_ASSIGN(InterpolatedGainCurve);
  124. };
  125. } // namespace webrtc
  126. #endif // MODULES_AUDIO_PROCESSING_AGC2_INTERPOLATED_GAIN_CURVE_H_