blob: cd21e4c93e68c6d7c8850d5b9b215810bc2cb0a7 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
bjornv@webrtc.org0c6f9312012-01-30 09:39:08 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_processing/gain_control_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
Yves Gerey988cc082018-10-23 12:03:01 +020013#include <cstdint>
14
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +020015#include "absl/types/optional.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "modules/audio_processing/agc/legacy/gain_control.h"
17#include "modules/audio_processing/audio_buffer.h"
Yves Gerey988cc082018-10-23 12:03:01 +020018#include "modules/audio_processing/include/audio_processing.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "modules/audio_processing/logging/apm_data_dumper.h"
Yves Gerey988cc082018-10-23 12:03:01 +020020#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 09:11:00 -080021#include "rtc_base/constructor_magic.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000022
niklase@google.com470e71d2011-07-07 08:21:25 +000023namespace webrtc {
24
25typedef void Handle;
26
niklase@google.com470e71d2011-07-07 08:21:25 +000027namespace {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +000028int16_t MapSetting(GainControl::Mode mode) {
niklase@google.com470e71d2011-07-07 08:21:25 +000029 switch (mode) {
30 case GainControl::kAdaptiveAnalog:
31 return kAgcModeAdaptiveAnalog;
niklase@google.com470e71d2011-07-07 08:21:25 +000032 case GainControl::kAdaptiveDigital:
33 return kAgcModeAdaptiveDigital;
niklase@google.com470e71d2011-07-07 08:21:25 +000034 case GainControl::kFixedDigital:
35 return kAgcModeFixedDigital;
niklase@google.com470e71d2011-07-07 08:21:25 +000036 }
nisseeb4ca4e2017-01-12 02:24:27 -080037 RTC_NOTREACHED();
mflodman@webrtc.org657b2a42012-02-06 11:06:01 +000038 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +000039}
niklase@google.com470e71d2011-07-07 08:21:25 +000040
peah2446e5a2015-11-18 06:11:13 -080041} // namespace
peah4d291f72015-11-16 23:52:25 -080042
peahbfa97112016-03-10 21:09:04 -080043class GainControlImpl::GainController {
44 public:
45 explicit GainController() {
46 state_ = WebRtcAgc_Create();
47 RTC_CHECK(state_);
48 }
49
50 ~GainController() {
51 RTC_DCHECK(state_);
52 WebRtcAgc_Free(state_);
53 }
54
55 Handle* state() {
56 RTC_DCHECK(state_);
57 return state_;
58 }
59
60 void Initialize(int minimum_capture_level,
61 int maximum_capture_level,
62 Mode mode,
63 int sample_rate_hz,
64 int capture_level) {
65 RTC_DCHECK(state_);
66 int error =
67 WebRtcAgc_Init(state_, minimum_capture_level, maximum_capture_level,
68 MapSetting(mode), sample_rate_hz);
69 RTC_DCHECK_EQ(0, error);
70
71 set_capture_level(capture_level);
72 }
73
Yves Gerey665174f2018-06-19 15:03:05 +020074 void set_capture_level(int capture_level) { capture_level_ = capture_level; }
peahbfa97112016-03-10 21:09:04 -080075
76 int get_capture_level() {
77 RTC_DCHECK(capture_level_);
78 return *capture_level_;
79 }
80
81 private:
82 Handle* state_;
83 // TODO(peah): Remove the optional once the initialization is moved into the
84 // ctor.
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +020085 absl::optional<int> capture_level_;
peahbfa97112016-03-10 21:09:04 -080086
87 RTC_DISALLOW_COPY_AND_ASSIGN(GainController);
88};
89
peah135259a2016-10-28 03:12:11 -070090int GainControlImpl::instance_counter_ = 0;
91
Sam Zackrisson421c8592019-02-11 13:39:46 +010092GainControlImpl::GainControlImpl(rtc::CriticalSection* crit_capture)
93 : crit_capture_(crit_capture),
peah135259a2016-10-28 03:12:11 -070094 data_dumper_(new ApmDataDumper(instance_counter_)),
peah4d291f72015-11-16 23:52:25 -080095 mode_(kAdaptiveAnalog),
96 minimum_capture_level_(0),
97 maximum_capture_level_(255),
98 limiter_enabled_(true),
99 target_level_dbfs_(3),
100 compression_gain_db_(9),
101 analog_capture_level_(0),
102 was_analog_level_set_(false),
peah701d6282016-10-25 05:42:20 -0700103 stream_is_saturated_(false) {
peahdf3efa82015-11-28 12:35:15 -0800104 RTC_DCHECK(crit_capture);
105}
niklase@google.com470e71d2011-07-07 08:21:25 +0000106
107GainControlImpl::~GainControlImpl() {}
108
peah701d6282016-10-25 05:42:20 -0700109void GainControlImpl::ProcessRenderAudio(
110 rtc::ArrayView<const int16_t> packed_render_audio) {
111 rtc::CritScope cs_capture(crit_capture_);
peahbfa97112016-03-10 21:09:04 -0800112 if (!enabled_) {
peah4d291f72015-11-16 23:52:25 -0800113 return;
114 }
115
peah701d6282016-10-25 05:42:20 -0700116 for (auto& gain_controller : gain_controllers_) {
117 WebRtcAgc_AddFarend(gain_controller->state(), packed_render_audio.data(),
118 packed_render_audio.size());
peah4d291f72015-11-16 23:52:25 -0800119 }
120}
121
peah701d6282016-10-25 05:42:20 -0700122void GainControlImpl::PackRenderAudioBuffer(
123 AudioBuffer* audio,
124 std::vector<int16_t>* packed_buffer) {
kwibergaf476c72016-11-28 15:21:39 -0800125 RTC_DCHECK_GE(160, audio->num_frames_per_band());
peah701d6282016-10-25 05:42:20 -0700126
127 packed_buffer->clear();
128 packed_buffer->insert(
129 packed_buffer->end(), audio->mixed_low_pass_data(),
130 (audio->mixed_low_pass_data() + audio->num_frames_per_band()));
131}
132
niklase@google.com470e71d2011-07-07 08:21:25 +0000133int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
peahdf3efa82015-11-28 12:35:15 -0800134 rtc::CritScope cs(crit_capture_);
135
peahbfa97112016-03-10 21:09:04 -0800136 if (!enabled_) {
peahdf3efa82015-11-28 12:35:15 -0800137 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000138 }
139
peahb8fbb542016-03-15 02:28:08 -0700140 RTC_DCHECK(num_proc_channels_);
kwibergaf476c72016-11-28 15:21:39 -0800141 RTC_DCHECK_GE(160, audio->num_frames_per_band());
peahb8fbb542016-03-15 02:28:08 -0700142 RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_);
143 RTC_DCHECK_LE(*num_proc_channels_, gain_controllers_.size());
niklase@google.com470e71d2011-07-07 08:21:25 +0000144
145 if (mode_ == kAdaptiveAnalog) {
peahbfa97112016-03-10 21:09:04 -0800146 int capture_channel = 0;
147 for (auto& gain_controller : gain_controllers_) {
148 gain_controller->set_capture_level(analog_capture_level_);
149 int err = WebRtcAgc_AddMic(
150 gain_controller->state(), audio->split_bands(capture_channel),
151 audio->num_bands(), audio->num_frames_per_band());
niklase@google.com470e71d2011-07-07 08:21:25 +0000152
peahdf3efa82015-11-28 12:35:15 -0800153 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800154 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000155 }
peahbfa97112016-03-10 21:09:04 -0800156 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000157 }
158 } else if (mode_ == kAdaptiveDigital) {
peahbfa97112016-03-10 21:09:04 -0800159 int capture_channel = 0;
160 for (auto& gain_controller : gain_controllers_) {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000161 int32_t capture_level_out = 0;
peahbfa97112016-03-10 21:09:04 -0800162 int err = WebRtcAgc_VirtualMic(
163 gain_controller->state(), audio->split_bands(capture_channel),
164 audio->num_bands(), audio->num_frames_per_band(),
165 analog_capture_level_, &capture_level_out);
niklase@google.com470e71d2011-07-07 08:21:25 +0000166
peahbfa97112016-03-10 21:09:04 -0800167 gain_controller->set_capture_level(capture_level_out);
niklase@google.com470e71d2011-07-07 08:21:25 +0000168
peahdf3efa82015-11-28 12:35:15 -0800169 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800170 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000171 }
peahbfa97112016-03-10 21:09:04 -0800172 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000173 }
174 }
175
peahdf3efa82015-11-28 12:35:15 -0800176 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000177}
178
peahb8fbb542016-03-15 02:28:08 -0700179int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio,
180 bool stream_has_echo) {
peahdf3efa82015-11-28 12:35:15 -0800181 rtc::CritScope cs(crit_capture_);
182
peahbfa97112016-03-10 21:09:04 -0800183 if (!enabled_) {
peahdf3efa82015-11-28 12:35:15 -0800184 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000185 }
186
187 if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) {
peahdf3efa82015-11-28 12:35:15 -0800188 return AudioProcessing::kStreamParameterNotSetError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000189 }
190
peahb8fbb542016-03-15 02:28:08 -0700191 RTC_DCHECK(num_proc_channels_);
kwibergaf476c72016-11-28 15:21:39 -0800192 RTC_DCHECK_GE(160, audio->num_frames_per_band());
peahb8fbb542016-03-15 02:28:08 -0700193 RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000194
195 stream_is_saturated_ = false;
peahbfa97112016-03-10 21:09:04 -0800196 int capture_channel = 0;
197 for (auto& gain_controller : gain_controllers_) {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000198 int32_t capture_level_out = 0;
199 uint8_t saturation_warning = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000200
peahdf3efa82015-11-28 12:35:15 -0800201 // The call to stream_has_echo() is ok from a deadlock perspective
202 // as the capture lock is allready held.
niklase@google.com470e71d2011-07-07 08:21:25 +0000203 int err = WebRtcAgc_Process(
peahbfa97112016-03-10 21:09:04 -0800204 gain_controller->state(), audio->split_bands_const(capture_channel),
205 audio->num_bands(), audio->num_frames_per_band(),
206 audio->split_bands(capture_channel),
207 gain_controller->get_capture_level(), &capture_level_out,
peahb8fbb542016-03-15 02:28:08 -0700208 stream_has_echo, &saturation_warning);
niklase@google.com470e71d2011-07-07 08:21:25 +0000209
peahdf3efa82015-11-28 12:35:15 -0800210 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800211 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000212 }
213
peahbfa97112016-03-10 21:09:04 -0800214 gain_controller->set_capture_level(capture_level_out);
niklase@google.com470e71d2011-07-07 08:21:25 +0000215 if (saturation_warning == 1) {
216 stream_is_saturated_ = true;
217 }
peahbfa97112016-03-10 21:09:04 -0800218
219 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000220 }
221
peahb8fbb542016-03-15 02:28:08 -0700222 RTC_DCHECK_LT(0ul, *num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000223 if (mode_ == kAdaptiveAnalog) {
224 // Take the analog level to be the average across the handles.
225 analog_capture_level_ = 0;
peahbfa97112016-03-10 21:09:04 -0800226 for (auto& gain_controller : gain_controllers_) {
227 analog_capture_level_ += gain_controller->get_capture_level();
niklase@google.com470e71d2011-07-07 08:21:25 +0000228 }
229
peahb8fbb542016-03-15 02:28:08 -0700230 analog_capture_level_ /= (*num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000231 }
232
233 was_analog_level_set_ = false;
peahdf3efa82015-11-28 12:35:15 -0800234 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000235}
236
aluebs11d4a422016-04-28 14:58:32 -0700237int GainControlImpl::compression_gain_db() const {
238 rtc::CritScope cs(crit_capture_);
239 return compression_gain_db_;
240}
241
niklase@google.com470e71d2011-07-07 08:21:25 +0000242// TODO(ajm): ensure this is called under kAdaptiveAnalog.
243int GainControlImpl::set_stream_analog_level(int level) {
peahdf3efa82015-11-28 12:35:15 -0800244 rtc::CritScope cs(crit_capture_);
peah135259a2016-10-28 03:12:11 -0700245 data_dumper_->DumpRaw("gain_control_set_stream_analog_level", 1, &level);
peahdf3efa82015-11-28 12:35:15 -0800246
niklase@google.com470e71d2011-07-07 08:21:25 +0000247 was_analog_level_set_ = true;
248 if (level < minimum_capture_level_ || level > maximum_capture_level_) {
peahdf3efa82015-11-28 12:35:15 -0800249 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000250 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000251 analog_capture_level_ = level;
252
peahdf3efa82015-11-28 12:35:15 -0800253 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000254}
255
256int GainControlImpl::stream_analog_level() {
peahdf3efa82015-11-28 12:35:15 -0800257 rtc::CritScope cs(crit_capture_);
peah135259a2016-10-28 03:12:11 -0700258 data_dumper_->DumpRaw("gain_control_stream_analog_level", 1,
259 &analog_capture_level_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000260 // TODO(ajm): enable this assertion?
Yves Gerey665174f2018-06-19 15:03:05 +0200261 // RTC_DCHECK_EQ(kAdaptiveAnalog, mode_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000262
263 return analog_capture_level_;
264}
265
266int GainControlImpl::Enable(bool enable) {
peahdf3efa82015-11-28 12:35:15 -0800267 rtc::CritScope cs_capture(crit_capture_);
peahbfa97112016-03-10 21:09:04 -0800268 if (enable && !enabled_) {
269 enabled_ = enable; // Must be set before Initialize() is called.
peahb8fbb542016-03-15 02:28:08 -0700270
271 RTC_DCHECK(num_proc_channels_);
272 RTC_DCHECK(sample_rate_hz_);
273 Initialize(*num_proc_channels_, *sample_rate_hz_);
peahbfa97112016-03-10 21:09:04 -0800274 } else {
275 enabled_ = enable;
276 }
277 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000278}
279
280bool GainControlImpl::is_enabled() const {
peahdf3efa82015-11-28 12:35:15 -0800281 rtc::CritScope cs(crit_capture_);
peahbfa97112016-03-10 21:09:04 -0800282 return enabled_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000283}
284
285int GainControlImpl::set_mode(Mode mode) {
peahdf3efa82015-11-28 12:35:15 -0800286 rtc::CritScope cs_capture(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000287 if (MapSetting(mode) == -1) {
peahdf3efa82015-11-28 12:35:15 -0800288 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000289 }
290
291 mode_ = mode;
peahb8fbb542016-03-15 02:28:08 -0700292 RTC_DCHECK(num_proc_channels_);
293 RTC_DCHECK(sample_rate_hz_);
294 Initialize(*num_proc_channels_, *sample_rate_hz_);
peahbfa97112016-03-10 21:09:04 -0800295 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000296}
297
298GainControl::Mode GainControlImpl::mode() const {
peahdf3efa82015-11-28 12:35:15 -0800299 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000300 return mode_;
301}
302
Yves Gerey665174f2018-06-19 15:03:05 +0200303int GainControlImpl::set_analog_level_limits(int minimum, int maximum) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000304 if (minimum < 0) {
peahdf3efa82015-11-28 12:35:15 -0800305 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000306 }
307
308 if (maximum > 65535) {
peahdf3efa82015-11-28 12:35:15 -0800309 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000310 }
311
312 if (maximum < minimum) {
peahdf3efa82015-11-28 12:35:15 -0800313 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000314 }
315
peah7c931ad2016-03-24 12:52:02 -0700316 size_t num_proc_channels_local = 0u;
317 int sample_rate_hz_local = 0;
318 {
319 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000320
peah7c931ad2016-03-24 12:52:02 -0700321 minimum_capture_level_ = minimum;
322 maximum_capture_level_ = maximum;
323
324 RTC_DCHECK(num_proc_channels_);
325 RTC_DCHECK(sample_rate_hz_);
326 num_proc_channels_local = *num_proc_channels_;
327 sample_rate_hz_local = *sample_rate_hz_;
328 }
329 Initialize(num_proc_channels_local, sample_rate_hz_local);
peahbfa97112016-03-10 21:09:04 -0800330 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000331}
332
333int GainControlImpl::analog_level_minimum() const {
peahdf3efa82015-11-28 12:35:15 -0800334 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000335 return minimum_capture_level_;
336}
337
338int GainControlImpl::analog_level_maximum() const {
peahdf3efa82015-11-28 12:35:15 -0800339 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000340 return maximum_capture_level_;
341}
342
343bool GainControlImpl::stream_is_saturated() const {
peahdf3efa82015-11-28 12:35:15 -0800344 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000345 return stream_is_saturated_;
346}
347
348int GainControlImpl::set_target_level_dbfs(int level) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000349 if (level > 31 || level < 0) {
peahdf3efa82015-11-28 12:35:15 -0800350 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000351 }
Sam Zackrisson421c8592019-02-11 13:39:46 +0100352 rtc::CritScope cs(crit_capture_);
353 target_level_dbfs_ = level;
niklase@google.com470e71d2011-07-07 08:21:25 +0000354 return Configure();
355}
356
357int GainControlImpl::target_level_dbfs() const {
peahdf3efa82015-11-28 12:35:15 -0800358 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000359 return target_level_dbfs_;
360}
361
362int GainControlImpl::set_compression_gain_db(int gain) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000363 if (gain < 0 || gain > 90) {
peahdf3efa82015-11-28 12:35:15 -0800364 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000365 }
Sam Zackrisson421c8592019-02-11 13:39:46 +0100366 rtc::CritScope cs(crit_capture_);
367 compression_gain_db_ = gain;
niklase@google.com470e71d2011-07-07 08:21:25 +0000368 return Configure();
369}
370
niklase@google.com470e71d2011-07-07 08:21:25 +0000371int GainControlImpl::enable_limiter(bool enable) {
Sam Zackrisson421c8592019-02-11 13:39:46 +0100372 rtc::CritScope cs(crit_capture_);
373 limiter_enabled_ = enable;
niklase@google.com470e71d2011-07-07 08:21:25 +0000374 return Configure();
375}
376
377bool GainControlImpl::is_limiter_enabled() const {
peahdf3efa82015-11-28 12:35:15 -0800378 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000379 return limiter_enabled_;
380}
381
peahb8fbb542016-03-15 02:28:08 -0700382void GainControlImpl::Initialize(size_t num_proc_channels, int sample_rate_hz) {
peahbfa97112016-03-10 21:09:04 -0800383 rtc::CritScope cs_capture(crit_capture_);
peah135259a2016-10-28 03:12:11 -0700384 data_dumper_->InitiateNewSetOfRecordings();
peahb8fbb542016-03-15 02:28:08 -0700385
Oskar Sundbomaa8b67d2017-11-17 14:34:48 +0100386 num_proc_channels_ = num_proc_channels;
387 sample_rate_hz_ = sample_rate_hz;
peahb8fbb542016-03-15 02:28:08 -0700388
peahbfa97112016-03-10 21:09:04 -0800389 if (!enabled_) {
390 return;
niklase@google.com470e71d2011-07-07 08:21:25 +0000391 }
392
peahb8fbb542016-03-15 02:28:08 -0700393 gain_controllers_.resize(*num_proc_channels_);
peahbfa97112016-03-10 21:09:04 -0800394 for (auto& gain_controller : gain_controllers_) {
395 if (!gain_controller) {
396 gain_controller.reset(new GainController());
397 }
398 gain_controller->Initialize(minimum_capture_level_, maximum_capture_level_,
peahb8fbb542016-03-15 02:28:08 -0700399 mode_, *sample_rate_hz_, analog_capture_level_);
peahbfa97112016-03-10 21:09:04 -0800400 }
401
402 Configure();
peah4d291f72015-11-16 23:52:25 -0800403}
404
peahbfa97112016-03-10 21:09:04 -0800405int GainControlImpl::Configure() {
pbos@webrtc.orge468bc92014-12-18 09:11:33 +0000406 WebRtcAgcConfig config;
niklase@google.com470e71d2011-07-07 08:21:25 +0000407 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we
408 // change the interface.
Yves Gerey665174f2018-06-19 15:03:05 +0200409 // RTC_DCHECK_LE(target_level_dbfs_, 0);
410 // config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_);
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000411 config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_);
Yves Gerey665174f2018-06-19 15:03:05 +0200412 config.compressionGaindB = static_cast<int16_t>(compression_gain_db_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000413 config.limiterEnable = limiter_enabled_;
414
peahbfa97112016-03-10 21:09:04 -0800415 int error = AudioProcessing::kNoError;
416 for (auto& gain_controller : gain_controllers_) {
417 const int handle_error =
418 WebRtcAgc_set_config(gain_controller->state(), config);
419 if (handle_error != AudioProcessing::kNoError) {
420 error = handle_error;
421 }
422 }
423 return error;
niklase@google.com470e71d2011-07-07 08:21:25 +0000424}
niklase@google.com470e71d2011-07-07 08:21:25 +0000425} // namespace webrtc