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