blob: 685a27ff6681209ab2a4b842bc712e2b494dbb90 [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
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +020013#include "absl/types/optional.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "modules/audio_processing/agc/legacy/gain_control.h"
15#include "modules/audio_processing/audio_buffer.h"
16#include "modules/audio_processing/logging/apm_data_dumper.h"
17#include "rtc_base/constructormagic.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000018
niklase@google.com470e71d2011-07-07 08:21:25 +000019namespace webrtc {
20
21typedef void Handle;
22
niklase@google.com470e71d2011-07-07 08:21:25 +000023namespace {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +000024int16_t MapSetting(GainControl::Mode mode) {
niklase@google.com470e71d2011-07-07 08:21:25 +000025 switch (mode) {
26 case GainControl::kAdaptiveAnalog:
27 return kAgcModeAdaptiveAnalog;
niklase@google.com470e71d2011-07-07 08:21:25 +000028 case GainControl::kAdaptiveDigital:
29 return kAgcModeAdaptiveDigital;
niklase@google.com470e71d2011-07-07 08:21:25 +000030 case GainControl::kFixedDigital:
31 return kAgcModeFixedDigital;
niklase@google.com470e71d2011-07-07 08:21:25 +000032 }
nisseeb4ca4e2017-01-12 02:24:27 -080033 RTC_NOTREACHED();
mflodman@webrtc.org657b2a42012-02-06 11:06:01 +000034 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +000035}
niklase@google.com470e71d2011-07-07 08:21:25 +000036
peah2446e5a2015-11-18 06:11:13 -080037} // namespace
peah4d291f72015-11-16 23:52:25 -080038
peahbfa97112016-03-10 21:09:04 -080039class GainControlImpl::GainController {
40 public:
41 explicit GainController() {
42 state_ = WebRtcAgc_Create();
43 RTC_CHECK(state_);
44 }
45
46 ~GainController() {
47 RTC_DCHECK(state_);
48 WebRtcAgc_Free(state_);
49 }
50
51 Handle* state() {
52 RTC_DCHECK(state_);
53 return state_;
54 }
55
56 void Initialize(int minimum_capture_level,
57 int maximum_capture_level,
58 Mode mode,
59 int sample_rate_hz,
60 int capture_level) {
61 RTC_DCHECK(state_);
62 int error =
63 WebRtcAgc_Init(state_, minimum_capture_level, maximum_capture_level,
64 MapSetting(mode), sample_rate_hz);
65 RTC_DCHECK_EQ(0, error);
66
67 set_capture_level(capture_level);
68 }
69
Yves Gerey665174f2018-06-19 15:03:05 +020070 void set_capture_level(int capture_level) { capture_level_ = capture_level; }
peahbfa97112016-03-10 21:09:04 -080071
72 int get_capture_level() {
73 RTC_DCHECK(capture_level_);
74 return *capture_level_;
75 }
76
77 private:
78 Handle* state_;
79 // TODO(peah): Remove the optional once the initialization is moved into the
80 // ctor.
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +020081 absl::optional<int> capture_level_;
peahbfa97112016-03-10 21:09:04 -080082
83 RTC_DISALLOW_COPY_AND_ASSIGN(GainController);
84};
85
peah135259a2016-10-28 03:12:11 -070086int GainControlImpl::instance_counter_ = 0;
87
peahb8fbb542016-03-15 02:28:08 -070088GainControlImpl::GainControlImpl(rtc::CriticalSection* crit_render,
peahdf3efa82015-11-28 12:35:15 -080089 rtc::CriticalSection* crit_capture)
peahb8fbb542016-03-15 02:28:08 -070090 : crit_render_(crit_render),
peahdf3efa82015-11-28 12:35:15 -080091 crit_capture_(crit_capture),
peah135259a2016-10-28 03:12:11 -070092 data_dumper_(new ApmDataDumper(instance_counter_)),
peah4d291f72015-11-16 23:52:25 -080093 mode_(kAdaptiveAnalog),
94 minimum_capture_level_(0),
95 maximum_capture_level_(255),
96 limiter_enabled_(true),
97 target_level_dbfs_(3),
98 compression_gain_db_(9),
99 analog_capture_level_(0),
100 was_analog_level_set_(false),
peah701d6282016-10-25 05:42:20 -0700101 stream_is_saturated_(false) {
peahdf3efa82015-11-28 12:35:15 -0800102 RTC_DCHECK(crit_render);
103 RTC_DCHECK(crit_capture);
104}
niklase@google.com470e71d2011-07-07 08:21:25 +0000105
106GainControlImpl::~GainControlImpl() {}
107
peah701d6282016-10-25 05:42:20 -0700108void GainControlImpl::ProcessRenderAudio(
109 rtc::ArrayView<const int16_t> packed_render_audio) {
110 rtc::CritScope cs_capture(crit_capture_);
peahbfa97112016-03-10 21:09:04 -0800111 if (!enabled_) {
peah4d291f72015-11-16 23:52:25 -0800112 return;
113 }
114
peah701d6282016-10-25 05:42:20 -0700115 for (auto& gain_controller : gain_controllers_) {
116 WebRtcAgc_AddFarend(gain_controller->state(), packed_render_audio.data(),
117 packed_render_audio.size());
peah4d291f72015-11-16 23:52:25 -0800118 }
119}
120
peah701d6282016-10-25 05:42:20 -0700121void GainControlImpl::PackRenderAudioBuffer(
122 AudioBuffer* audio,
123 std::vector<int16_t>* packed_buffer) {
kwibergaf476c72016-11-28 15:21:39 -0800124 RTC_DCHECK_GE(160, audio->num_frames_per_band());
peah701d6282016-10-25 05:42:20 -0700125
126 packed_buffer->clear();
127 packed_buffer->insert(
128 packed_buffer->end(), audio->mixed_low_pass_data(),
129 (audio->mixed_low_pass_data() + audio->num_frames_per_band()));
130}
131
niklase@google.com470e71d2011-07-07 08:21:25 +0000132int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
peahdf3efa82015-11-28 12:35:15 -0800133 rtc::CritScope cs(crit_capture_);
134
peahbfa97112016-03-10 21:09:04 -0800135 if (!enabled_) {
peahdf3efa82015-11-28 12:35:15 -0800136 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000137 }
138
peahb8fbb542016-03-15 02:28:08 -0700139 RTC_DCHECK(num_proc_channels_);
kwibergaf476c72016-11-28 15:21:39 -0800140 RTC_DCHECK_GE(160, audio->num_frames_per_band());
peahb8fbb542016-03-15 02:28:08 -0700141 RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_);
142 RTC_DCHECK_LE(*num_proc_channels_, gain_controllers_.size());
niklase@google.com470e71d2011-07-07 08:21:25 +0000143
144 if (mode_ == kAdaptiveAnalog) {
peahbfa97112016-03-10 21:09:04 -0800145 int capture_channel = 0;
146 for (auto& gain_controller : gain_controllers_) {
147 gain_controller->set_capture_level(analog_capture_level_);
148 int err = WebRtcAgc_AddMic(
149 gain_controller->state(), audio->split_bands(capture_channel),
150 audio->num_bands(), audio->num_frames_per_band());
niklase@google.com470e71d2011-07-07 08:21:25 +0000151
peahdf3efa82015-11-28 12:35:15 -0800152 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800153 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000154 }
peahbfa97112016-03-10 21:09:04 -0800155 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000156 }
157 } else if (mode_ == kAdaptiveDigital) {
peahbfa97112016-03-10 21:09:04 -0800158 int capture_channel = 0;
159 for (auto& gain_controller : gain_controllers_) {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000160 int32_t capture_level_out = 0;
peahbfa97112016-03-10 21:09:04 -0800161 int err = WebRtcAgc_VirtualMic(
162 gain_controller->state(), audio->split_bands(capture_channel),
163 audio->num_bands(), audio->num_frames_per_band(),
164 analog_capture_level_, &capture_level_out);
niklase@google.com470e71d2011-07-07 08:21:25 +0000165
peahbfa97112016-03-10 21:09:04 -0800166 gain_controller->set_capture_level(capture_level_out);
niklase@google.com470e71d2011-07-07 08:21:25 +0000167
peahdf3efa82015-11-28 12:35:15 -0800168 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800169 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000170 }
peahbfa97112016-03-10 21:09:04 -0800171 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000172 }
173 }
174
peahdf3efa82015-11-28 12:35:15 -0800175 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000176}
177
peahb8fbb542016-03-15 02:28:08 -0700178int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio,
179 bool stream_has_echo) {
peahdf3efa82015-11-28 12:35:15 -0800180 rtc::CritScope cs(crit_capture_);
181
peahbfa97112016-03-10 21:09:04 -0800182 if (!enabled_) {
peahdf3efa82015-11-28 12:35:15 -0800183 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000184 }
185
186 if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) {
peahdf3efa82015-11-28 12:35:15 -0800187 return AudioProcessing::kStreamParameterNotSetError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000188 }
189
peahb8fbb542016-03-15 02:28:08 -0700190 RTC_DCHECK(num_proc_channels_);
kwibergaf476c72016-11-28 15:21:39 -0800191 RTC_DCHECK_GE(160, audio->num_frames_per_band());
peahb8fbb542016-03-15 02:28:08 -0700192 RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000193
194 stream_is_saturated_ = false;
peahbfa97112016-03-10 21:09:04 -0800195 int capture_channel = 0;
196 for (auto& gain_controller : gain_controllers_) {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000197 int32_t capture_level_out = 0;
198 uint8_t saturation_warning = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000199
peahdf3efa82015-11-28 12:35:15 -0800200 // The call to stream_has_echo() is ok from a deadlock perspective
201 // as the capture lock is allready held.
niklase@google.com470e71d2011-07-07 08:21:25 +0000202 int err = WebRtcAgc_Process(
peahbfa97112016-03-10 21:09:04 -0800203 gain_controller->state(), audio->split_bands_const(capture_channel),
204 audio->num_bands(), audio->num_frames_per_band(),
205 audio->split_bands(capture_channel),
206 gain_controller->get_capture_level(), &capture_level_out,
peahb8fbb542016-03-15 02:28:08 -0700207 stream_has_echo, &saturation_warning);
niklase@google.com470e71d2011-07-07 08:21:25 +0000208
peahdf3efa82015-11-28 12:35:15 -0800209 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800210 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000211 }
212
peahbfa97112016-03-10 21:09:04 -0800213 gain_controller->set_capture_level(capture_level_out);
niklase@google.com470e71d2011-07-07 08:21:25 +0000214 if (saturation_warning == 1) {
215 stream_is_saturated_ = true;
216 }
peahbfa97112016-03-10 21:09:04 -0800217
218 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000219 }
220
peahb8fbb542016-03-15 02:28:08 -0700221 RTC_DCHECK_LT(0ul, *num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000222 if (mode_ == kAdaptiveAnalog) {
223 // Take the analog level to be the average across the handles.
224 analog_capture_level_ = 0;
peahbfa97112016-03-10 21:09:04 -0800225 for (auto& gain_controller : gain_controllers_) {
226 analog_capture_level_ += gain_controller->get_capture_level();
niklase@google.com470e71d2011-07-07 08:21:25 +0000227 }
228
peahb8fbb542016-03-15 02:28:08 -0700229 analog_capture_level_ /= (*num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000230 }
231
232 was_analog_level_set_ = false;
peahdf3efa82015-11-28 12:35:15 -0800233 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000234}
235
aluebs11d4a422016-04-28 14:58:32 -0700236int GainControlImpl::compression_gain_db() const {
237 rtc::CritScope cs(crit_capture_);
238 return compression_gain_db_;
239}
240
niklase@google.com470e71d2011-07-07 08:21:25 +0000241// TODO(ajm): ensure this is called under kAdaptiveAnalog.
242int GainControlImpl::set_stream_analog_level(int level) {
peahdf3efa82015-11-28 12:35:15 -0800243 rtc::CritScope cs(crit_capture_);
peah135259a2016-10-28 03:12:11 -0700244 data_dumper_->DumpRaw("gain_control_set_stream_analog_level", 1, &level);
peahdf3efa82015-11-28 12:35:15 -0800245
niklase@google.com470e71d2011-07-07 08:21:25 +0000246 was_analog_level_set_ = true;
247 if (level < minimum_capture_level_ || level > maximum_capture_level_) {
peahdf3efa82015-11-28 12:35:15 -0800248 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000249 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000250 analog_capture_level_ = level;
251
peahdf3efa82015-11-28 12:35:15 -0800252 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000253}
254
255int GainControlImpl::stream_analog_level() {
peahdf3efa82015-11-28 12:35:15 -0800256 rtc::CritScope cs(crit_capture_);
peah135259a2016-10-28 03:12:11 -0700257 data_dumper_->DumpRaw("gain_control_stream_analog_level", 1,
258 &analog_capture_level_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000259 // TODO(ajm): enable this assertion?
Yves Gerey665174f2018-06-19 15:03:05 +0200260 // RTC_DCHECK_EQ(kAdaptiveAnalog, mode_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000261
262 return analog_capture_level_;
263}
264
265int GainControlImpl::Enable(bool enable) {
peahdf3efa82015-11-28 12:35:15 -0800266 rtc::CritScope cs_render(crit_render_);
267 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_render(crit_render_);
287 rtc::CritScope cs_capture(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000288 if (MapSetting(mode) == -1) {
peahdf3efa82015-11-28 12:35:15 -0800289 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000290 }
291
292 mode_ = mode;
peahb8fbb542016-03-15 02:28:08 -0700293 RTC_DCHECK(num_proc_channels_);
294 RTC_DCHECK(sample_rate_hz_);
295 Initialize(*num_proc_channels_, *sample_rate_hz_);
peahbfa97112016-03-10 21:09:04 -0800296 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000297}
298
299GainControl::Mode GainControlImpl::mode() const {
peahdf3efa82015-11-28 12:35:15 -0800300 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000301 return mode_;
302}
303
Yves Gerey665174f2018-06-19 15:03:05 +0200304int GainControlImpl::set_analog_level_limits(int minimum, int maximum) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000305 if (minimum < 0) {
peahdf3efa82015-11-28 12:35:15 -0800306 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000307 }
308
309 if (maximum > 65535) {
peahdf3efa82015-11-28 12:35:15 -0800310 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000311 }
312
313 if (maximum < minimum) {
peahdf3efa82015-11-28 12:35:15 -0800314 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000315 }
316
peah7c931ad2016-03-24 12:52:02 -0700317 size_t num_proc_channels_local = 0u;
318 int sample_rate_hz_local = 0;
319 {
320 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000321
peah7c931ad2016-03-24 12:52:02 -0700322 minimum_capture_level_ = minimum;
323 maximum_capture_level_ = maximum;
324
325 RTC_DCHECK(num_proc_channels_);
326 RTC_DCHECK(sample_rate_hz_);
327 num_proc_channels_local = *num_proc_channels_;
328 sample_rate_hz_local = *sample_rate_hz_;
329 }
330 Initialize(num_proc_channels_local, sample_rate_hz_local);
peahbfa97112016-03-10 21:09:04 -0800331 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000332}
333
334int GainControlImpl::analog_level_minimum() const {
peahdf3efa82015-11-28 12:35:15 -0800335 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000336 return minimum_capture_level_;
337}
338
339int GainControlImpl::analog_level_maximum() const {
peahdf3efa82015-11-28 12:35:15 -0800340 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000341 return maximum_capture_level_;
342}
343
344bool GainControlImpl::stream_is_saturated() const {
peahdf3efa82015-11-28 12:35:15 -0800345 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000346 return stream_is_saturated_;
347}
348
349int GainControlImpl::set_target_level_dbfs(int level) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000350 if (level > 31 || level < 0) {
peahdf3efa82015-11-28 12:35:15 -0800351 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000352 }
peahbfa97112016-03-10 21:09:04 -0800353 {
354 rtc::CritScope cs(crit_capture_);
355 target_level_dbfs_ = level;
356 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000357 return Configure();
358}
359
360int GainControlImpl::target_level_dbfs() const {
peahdf3efa82015-11-28 12:35:15 -0800361 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000362 return target_level_dbfs_;
363}
364
365int GainControlImpl::set_compression_gain_db(int gain) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000366 if (gain < 0 || gain > 90) {
peahdf3efa82015-11-28 12:35:15 -0800367 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000368 }
peahbfa97112016-03-10 21:09:04 -0800369 {
370 rtc::CritScope cs(crit_capture_);
371 compression_gain_db_ = gain;
372 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000373 return Configure();
374}
375
niklase@google.com470e71d2011-07-07 08:21:25 +0000376int GainControlImpl::enable_limiter(bool enable) {
peahbfa97112016-03-10 21:09:04 -0800377 {
378 rtc::CritScope cs(crit_capture_);
379 limiter_enabled_ = enable;
380 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000381 return Configure();
382}
383
384bool GainControlImpl::is_limiter_enabled() const {
peahdf3efa82015-11-28 12:35:15 -0800385 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000386 return limiter_enabled_;
387}
388
peahb8fbb542016-03-15 02:28:08 -0700389void GainControlImpl::Initialize(size_t num_proc_channels, int sample_rate_hz) {
peahbfa97112016-03-10 21:09:04 -0800390 rtc::CritScope cs_render(crit_render_);
391 rtc::CritScope cs_capture(crit_capture_);
peah135259a2016-10-28 03:12:11 -0700392 data_dumper_->InitiateNewSetOfRecordings();
peahb8fbb542016-03-15 02:28:08 -0700393
Oskar Sundbomaa8b67d2017-11-17 14:34:48 +0100394 num_proc_channels_ = num_proc_channels;
395 sample_rate_hz_ = sample_rate_hz;
peahb8fbb542016-03-15 02:28:08 -0700396
peahbfa97112016-03-10 21:09:04 -0800397 if (!enabled_) {
398 return;
niklase@google.com470e71d2011-07-07 08:21:25 +0000399 }
400
peahb8fbb542016-03-15 02:28:08 -0700401 gain_controllers_.resize(*num_proc_channels_);
peahbfa97112016-03-10 21:09:04 -0800402 for (auto& gain_controller : gain_controllers_) {
403 if (!gain_controller) {
404 gain_controller.reset(new GainController());
405 }
406 gain_controller->Initialize(minimum_capture_level_, maximum_capture_level_,
peahb8fbb542016-03-15 02:28:08 -0700407 mode_, *sample_rate_hz_, analog_capture_level_);
peahbfa97112016-03-10 21:09:04 -0800408 }
409
410 Configure();
peah4d291f72015-11-16 23:52:25 -0800411}
412
peahbfa97112016-03-10 21:09:04 -0800413int GainControlImpl::Configure() {
peahdf3efa82015-11-28 12:35:15 -0800414 rtc::CritScope cs_render(crit_render_);
415 rtc::CritScope cs_capture(crit_capture_);
pbos@webrtc.orge468bc92014-12-18 09:11:33 +0000416 WebRtcAgcConfig config;
niklase@google.com470e71d2011-07-07 08:21:25 +0000417 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we
418 // change the interface.
Yves Gerey665174f2018-06-19 15:03:05 +0200419 // RTC_DCHECK_LE(target_level_dbfs_, 0);
420 // config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_);
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000421 config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_);
Yves Gerey665174f2018-06-19 15:03:05 +0200422 config.compressionGaindB = static_cast<int16_t>(compression_gain_db_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000423 config.limiterEnable = limiter_enabled_;
424
peahbfa97112016-03-10 21:09:04 -0800425 int error = AudioProcessing::kNoError;
426 for (auto& gain_controller : gain_controllers_) {
427 const int handle_error =
428 WebRtcAgc_set_config(gain_controller->state(), config);
429 if (handle_error != AudioProcessing::kNoError) {
430 error = handle_error;
431 }
432 }
433 return error;
niklase@google.com470e71d2011-07-07 08:21:25 +0000434}
niklase@google.com470e71d2011-07-07 08:21:25 +0000435} // namespace webrtc