• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/fixed_gain_controller.h"
12 
13 #include "api/array_view.h"
14 #include "common_audio/include/audio_util.h"
15 #include "modules/audio_processing/agc2/agc2_common.h"
16 #include "modules/audio_processing/logging/apm_data_dumper.h"
17 #include "rtc_base/checks.h"
18 #include "rtc_base/logging.h"
19 #include "rtc_base/numerics/safe_minmax.h"
20 
21 namespace webrtc {
22 namespace {
23 
24 // Returns true when the gain factor is so close to 1 that it would
25 // not affect int16 samples.
CloseToOne(float gain_factor)26 bool CloseToOne(float gain_factor) {
27   return 1.f - 1.f / kMaxFloatS16Value <= gain_factor &&
28          gain_factor <= 1.f + 1.f / kMaxFloatS16Value;
29 }
30 }  // namespace
31 
FixedGainController(ApmDataDumper * apm_data_dumper)32 FixedGainController::FixedGainController(ApmDataDumper* apm_data_dumper)
33     : FixedGainController(apm_data_dumper, "Agc2") {}
34 
FixedGainController(ApmDataDumper * apm_data_dumper,std::string histogram_name_prefix)35 FixedGainController::FixedGainController(ApmDataDumper* apm_data_dumper,
36                                          std::string histogram_name_prefix)
37     : apm_data_dumper_(apm_data_dumper),
38       limiter_(48000, apm_data_dumper_, histogram_name_prefix) {
39   // Do update histograms.xml when adding name prefixes.
40   RTC_DCHECK(histogram_name_prefix == "" || histogram_name_prefix == "Test" ||
41              histogram_name_prefix == "AudioMixer" ||
42              histogram_name_prefix == "Agc2");
43 }
44 
SetGain(float gain_to_apply_db)45 void FixedGainController::SetGain(float gain_to_apply_db) {
46   // Changes in gain_to_apply_ cause discontinuities. We assume
47   // gain_to_apply_ is set in the beginning of the call. If it is
48   // frequently changed, we should add interpolation between the
49   // values.
50   // The gain
51   RTC_DCHECK_LE(-50.f, gain_to_apply_db);
52   RTC_DCHECK_LE(gain_to_apply_db, 50.f);
53   const float previous_applied_gained = gain_to_apply_;
54   gain_to_apply_ = DbToRatio(gain_to_apply_db);
55   RTC_DCHECK_LT(0.f, gain_to_apply_);
56   RTC_DLOG(LS_INFO) << "Gain to apply: " << gain_to_apply_db << " db.";
57   // Reset the gain curve applier to quickly react on abrupt level changes
58   // caused by large changes of the applied gain.
59   if (previous_applied_gained != gain_to_apply_) {
60     limiter_.Reset();
61   }
62 }
63 
SetSampleRate(size_t sample_rate_hz)64 void FixedGainController::SetSampleRate(size_t sample_rate_hz) {
65   limiter_.SetSampleRate(sample_rate_hz);
66 }
67 
Process(AudioFrameView<float> signal)68 void FixedGainController::Process(AudioFrameView<float> signal) {
69   // Apply fixed digital gain. One of the
70   // planned usages of the FGC is to only use the limiter. In that
71   // case, the gain would be 1.0. Not doing the multiplications speeds
72   // it up considerably. Hence the check.
73   if (!CloseToOne(gain_to_apply_)) {
74     for (size_t k = 0; k < signal.num_channels(); ++k) {
75       rtc::ArrayView<float> channel_view = signal.channel(k);
76       for (auto& sample : channel_view) {
77         sample *= gain_to_apply_;
78       }
79     }
80   }
81 
82   // Use the limiter.
83   limiter_.Process(signal);
84 
85   // Dump data for debug.
86   const auto channel_view = signal.channel(0);
87   apm_data_dumper_->DumpRaw("agc2_fixed_digital_gain_curve_applier",
88                             channel_view.size(), channel_view.data());
89   // Hard-clipping.
90   for (size_t k = 0; k < signal.num_channels(); ++k) {
91     rtc::ArrayView<float> channel_view = signal.channel(k);
92     for (auto& sample : channel_view) {
93       sample = rtc::SafeClamp(sample, kMinFloatS16Value, kMaxFloatS16Value);
94     }
95   }
96 }
97 
LastAudioLevel() const98 float FixedGainController::LastAudioLevel() const {
99   return limiter_.LastAudioLevel();
100 }
101 }  // namespace webrtc
102