blob: e5760183f0e13514f682e2b2c6ece264ee96f30f [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
pbos@webrtc.org7fad4b82013-05-28 08:11:59 +000011#include "webrtc/modules/audio_processing/gain_control_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
bjornv@webrtc.orgb395a5e2014-12-16 10:38:10 +000013#include "webrtc/modules/audio_processing/agc/legacy/gain_control.h"
kjellanderc8fa6922017-06-30 14:02:00 -070014#include "webrtc/modules/audio_processing/audio_buffer.h"
peah135259a2016-10-28 03:12:11 -070015#include "webrtc/modules/audio_processing/logging/apm_data_dumper.h"
kjellanderc8fa6922017-06-30 14:02:00 -070016#include "webrtc/rtc_base/constructormagic.h"
17#include "webrtc/rtc_base/optional.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
70 void set_capture_level(int capture_level) {
71 capture_level_ = rtc::Optional<int>(capture_level);
72 }
73
74 int get_capture_level() {
75 RTC_DCHECK(capture_level_);
76 return *capture_level_;
77 }
78
79 private:
80 Handle* state_;
81 // TODO(peah): Remove the optional once the initialization is moved into the
82 // ctor.
83 rtc::Optional<int> capture_level_;
84
85 RTC_DISALLOW_COPY_AND_ASSIGN(GainController);
86};
87
peah135259a2016-10-28 03:12:11 -070088int GainControlImpl::instance_counter_ = 0;
89
peahb8fbb542016-03-15 02:28:08 -070090GainControlImpl::GainControlImpl(rtc::CriticalSection* crit_render,
peahdf3efa82015-11-28 12:35:15 -080091 rtc::CriticalSection* crit_capture)
peahb8fbb542016-03-15 02:28:08 -070092 : crit_render_(crit_render),
peahdf3efa82015-11-28 12:35:15 -080093 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_render);
105 RTC_DCHECK(crit_capture);
106}
niklase@google.com470e71d2011-07-07 08:21:25 +0000107
108GainControlImpl::~GainControlImpl() {}
109
peah701d6282016-10-25 05:42:20 -0700110void GainControlImpl::ProcessRenderAudio(
111 rtc::ArrayView<const int16_t> packed_render_audio) {
112 rtc::CritScope cs_capture(crit_capture_);
peahbfa97112016-03-10 21:09:04 -0800113 if (!enabled_) {
peah4d291f72015-11-16 23:52:25 -0800114 return;
115 }
116
peah701d6282016-10-25 05:42:20 -0700117 for (auto& gain_controller : gain_controllers_) {
118 WebRtcAgc_AddFarend(gain_controller->state(), packed_render_audio.data(),
119 packed_render_audio.size());
peah4d291f72015-11-16 23:52:25 -0800120 }
121}
122
peah701d6282016-10-25 05:42:20 -0700123void GainControlImpl::PackRenderAudioBuffer(
124 AudioBuffer* audio,
125 std::vector<int16_t>* packed_buffer) {
kwibergaf476c72016-11-28 15:21:39 -0800126 RTC_DCHECK_GE(160, audio->num_frames_per_band());
peah701d6282016-10-25 05:42:20 -0700127
128 packed_buffer->clear();
129 packed_buffer->insert(
130 packed_buffer->end(), audio->mixed_low_pass_data(),
131 (audio->mixed_low_pass_data() + audio->num_frames_per_band()));
132}
133
niklase@google.com470e71d2011-07-07 08:21:25 +0000134int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
peahdf3efa82015-11-28 12:35:15 -0800135 rtc::CritScope cs(crit_capture_);
136
peahbfa97112016-03-10 21:09:04 -0800137 if (!enabled_) {
peahdf3efa82015-11-28 12:35:15 -0800138 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000139 }
140
peahb8fbb542016-03-15 02:28:08 -0700141 RTC_DCHECK(num_proc_channels_);
kwibergaf476c72016-11-28 15:21:39 -0800142 RTC_DCHECK_GE(160, audio->num_frames_per_band());
peahb8fbb542016-03-15 02:28:08 -0700143 RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_);
144 RTC_DCHECK_LE(*num_proc_channels_, gain_controllers_.size());
niklase@google.com470e71d2011-07-07 08:21:25 +0000145
146 if (mode_ == kAdaptiveAnalog) {
peahbfa97112016-03-10 21:09:04 -0800147 int capture_channel = 0;
148 for (auto& gain_controller : gain_controllers_) {
149 gain_controller->set_capture_level(analog_capture_level_);
150 int err = WebRtcAgc_AddMic(
151 gain_controller->state(), audio->split_bands(capture_channel),
152 audio->num_bands(), audio->num_frames_per_band());
niklase@google.com470e71d2011-07-07 08:21:25 +0000153
peahdf3efa82015-11-28 12:35:15 -0800154 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800155 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000156 }
peahbfa97112016-03-10 21:09:04 -0800157 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000158 }
159 } else if (mode_ == kAdaptiveDigital) {
peahbfa97112016-03-10 21:09:04 -0800160 int capture_channel = 0;
161 for (auto& gain_controller : gain_controllers_) {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000162 int32_t capture_level_out = 0;
peahbfa97112016-03-10 21:09:04 -0800163 int err = WebRtcAgc_VirtualMic(
164 gain_controller->state(), audio->split_bands(capture_channel),
165 audio->num_bands(), audio->num_frames_per_band(),
166 analog_capture_level_, &capture_level_out);
niklase@google.com470e71d2011-07-07 08:21:25 +0000167
peahbfa97112016-03-10 21:09:04 -0800168 gain_controller->set_capture_level(capture_level_out);
niklase@google.com470e71d2011-07-07 08:21:25 +0000169
peahdf3efa82015-11-28 12:35:15 -0800170 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800171 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000172 }
peahbfa97112016-03-10 21:09:04 -0800173 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000174 }
175 }
176
peahdf3efa82015-11-28 12:35:15 -0800177 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000178}
179
peahb8fbb542016-03-15 02:28:08 -0700180int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio,
181 bool stream_has_echo) {
peahdf3efa82015-11-28 12:35:15 -0800182 rtc::CritScope cs(crit_capture_);
183
peahbfa97112016-03-10 21:09:04 -0800184 if (!enabled_) {
peahdf3efa82015-11-28 12:35:15 -0800185 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000186 }
187
188 if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) {
peahdf3efa82015-11-28 12:35:15 -0800189 return AudioProcessing::kStreamParameterNotSetError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000190 }
191
peahb8fbb542016-03-15 02:28:08 -0700192 RTC_DCHECK(num_proc_channels_);
kwibergaf476c72016-11-28 15:21:39 -0800193 RTC_DCHECK_GE(160, audio->num_frames_per_band());
peahb8fbb542016-03-15 02:28:08 -0700194 RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000195
196 stream_is_saturated_ = false;
peahbfa97112016-03-10 21:09:04 -0800197 int capture_channel = 0;
198 for (auto& gain_controller : gain_controllers_) {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000199 int32_t capture_level_out = 0;
200 uint8_t saturation_warning = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000201
peahdf3efa82015-11-28 12:35:15 -0800202 // The call to stream_has_echo() is ok from a deadlock perspective
203 // as the capture lock is allready held.
niklase@google.com470e71d2011-07-07 08:21:25 +0000204 int err = WebRtcAgc_Process(
peahbfa97112016-03-10 21:09:04 -0800205 gain_controller->state(), audio->split_bands_const(capture_channel),
206 audio->num_bands(), audio->num_frames_per_band(),
207 audio->split_bands(capture_channel),
208 gain_controller->get_capture_level(), &capture_level_out,
peahb8fbb542016-03-15 02:28:08 -0700209 stream_has_echo, &saturation_warning);
niklase@google.com470e71d2011-07-07 08:21:25 +0000210
peahdf3efa82015-11-28 12:35:15 -0800211 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800212 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000213 }
214
peahbfa97112016-03-10 21:09:04 -0800215 gain_controller->set_capture_level(capture_level_out);
niklase@google.com470e71d2011-07-07 08:21:25 +0000216 if (saturation_warning == 1) {
217 stream_is_saturated_ = true;
218 }
peahbfa97112016-03-10 21:09:04 -0800219
220 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000221 }
222
peahb8fbb542016-03-15 02:28:08 -0700223 RTC_DCHECK_LT(0ul, *num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000224 if (mode_ == kAdaptiveAnalog) {
225 // Take the analog level to be the average across the handles.
226 analog_capture_level_ = 0;
peahbfa97112016-03-10 21:09:04 -0800227 for (auto& gain_controller : gain_controllers_) {
228 analog_capture_level_ += gain_controller->get_capture_level();
niklase@google.com470e71d2011-07-07 08:21:25 +0000229 }
230
peahb8fbb542016-03-15 02:28:08 -0700231 analog_capture_level_ /= (*num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000232 }
233
234 was_analog_level_set_ = false;
peahdf3efa82015-11-28 12:35:15 -0800235 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000236}
237
aluebs11d4a422016-04-28 14:58:32 -0700238int GainControlImpl::compression_gain_db() const {
239 rtc::CritScope cs(crit_capture_);
240 return compression_gain_db_;
241}
242
niklase@google.com470e71d2011-07-07 08:21:25 +0000243// TODO(ajm): ensure this is called under kAdaptiveAnalog.
244int GainControlImpl::set_stream_analog_level(int level) {
peahdf3efa82015-11-28 12:35:15 -0800245 rtc::CritScope cs(crit_capture_);
peah135259a2016-10-28 03:12:11 -0700246 data_dumper_->DumpRaw("gain_control_set_stream_analog_level", 1, &level);
peahdf3efa82015-11-28 12:35:15 -0800247
niklase@google.com470e71d2011-07-07 08:21:25 +0000248 was_analog_level_set_ = true;
249 if (level < minimum_capture_level_ || level > maximum_capture_level_) {
peahdf3efa82015-11-28 12:35:15 -0800250 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000251 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000252 analog_capture_level_ = level;
253
peahdf3efa82015-11-28 12:35:15 -0800254 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000255}
256
257int GainControlImpl::stream_analog_level() {
peahdf3efa82015-11-28 12:35:15 -0800258 rtc::CritScope cs(crit_capture_);
peah135259a2016-10-28 03:12:11 -0700259 data_dumper_->DumpRaw("gain_control_stream_analog_level", 1,
260 &analog_capture_level_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000261 // TODO(ajm): enable this assertion?
kwiberg9e2be5f2016-09-14 05:23:22 -0700262 //RTC_DCHECK_EQ(kAdaptiveAnalog, mode_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000263
264 return analog_capture_level_;
265}
266
267int GainControlImpl::Enable(bool enable) {
peahdf3efa82015-11-28 12:35:15 -0800268 rtc::CritScope cs_render(crit_render_);
269 rtc::CritScope cs_capture(crit_capture_);
peahbfa97112016-03-10 21:09:04 -0800270 if (enable && !enabled_) {
271 enabled_ = enable; // Must be set before Initialize() is called.
peahb8fbb542016-03-15 02:28:08 -0700272
273 RTC_DCHECK(num_proc_channels_);
274 RTC_DCHECK(sample_rate_hz_);
275 Initialize(*num_proc_channels_, *sample_rate_hz_);
peahbfa97112016-03-10 21:09:04 -0800276 } else {
277 enabled_ = enable;
278 }
279 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000280}
281
282bool GainControlImpl::is_enabled() const {
peahdf3efa82015-11-28 12:35:15 -0800283 rtc::CritScope cs(crit_capture_);
peahbfa97112016-03-10 21:09:04 -0800284 return enabled_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000285}
286
287int GainControlImpl::set_mode(Mode mode) {
peahdf3efa82015-11-28 12:35:15 -0800288 rtc::CritScope cs_render(crit_render_);
289 rtc::CritScope cs_capture(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000290 if (MapSetting(mode) == -1) {
peahdf3efa82015-11-28 12:35:15 -0800291 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000292 }
293
294 mode_ = mode;
peahb8fbb542016-03-15 02:28:08 -0700295 RTC_DCHECK(num_proc_channels_);
296 RTC_DCHECK(sample_rate_hz_);
297 Initialize(*num_proc_channels_, *sample_rate_hz_);
peahbfa97112016-03-10 21:09:04 -0800298 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000299}
300
301GainControl::Mode GainControlImpl::mode() const {
peahdf3efa82015-11-28 12:35:15 -0800302 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000303 return mode_;
304}
305
306int GainControlImpl::set_analog_level_limits(int minimum,
307 int maximum) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000308 if (minimum < 0) {
peahdf3efa82015-11-28 12:35:15 -0800309 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000310 }
311
312 if (maximum > 65535) {
peahdf3efa82015-11-28 12:35:15 -0800313 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000314 }
315
316 if (maximum < minimum) {
peahdf3efa82015-11-28 12:35:15 -0800317 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000318 }
319
peah7c931ad2016-03-24 12:52:02 -0700320 size_t num_proc_channels_local = 0u;
321 int sample_rate_hz_local = 0;
322 {
323 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000324
peah7c931ad2016-03-24 12:52:02 -0700325 minimum_capture_level_ = minimum;
326 maximum_capture_level_ = maximum;
327
328 RTC_DCHECK(num_proc_channels_);
329 RTC_DCHECK(sample_rate_hz_);
330 num_proc_channels_local = *num_proc_channels_;
331 sample_rate_hz_local = *sample_rate_hz_;
332 }
333 Initialize(num_proc_channels_local, sample_rate_hz_local);
peahbfa97112016-03-10 21:09:04 -0800334 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000335}
336
337int GainControlImpl::analog_level_minimum() const {
peahdf3efa82015-11-28 12:35:15 -0800338 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000339 return minimum_capture_level_;
340}
341
342int GainControlImpl::analog_level_maximum() const {
peahdf3efa82015-11-28 12:35:15 -0800343 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000344 return maximum_capture_level_;
345}
346
347bool GainControlImpl::stream_is_saturated() const {
peahdf3efa82015-11-28 12:35:15 -0800348 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000349 return stream_is_saturated_;
350}
351
352int GainControlImpl::set_target_level_dbfs(int level) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000353 if (level > 31 || level < 0) {
peahdf3efa82015-11-28 12:35:15 -0800354 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000355 }
peahbfa97112016-03-10 21:09:04 -0800356 {
357 rtc::CritScope cs(crit_capture_);
358 target_level_dbfs_ = level;
359 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000360 return Configure();
361}
362
363int GainControlImpl::target_level_dbfs() const {
peahdf3efa82015-11-28 12:35:15 -0800364 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000365 return target_level_dbfs_;
366}
367
368int GainControlImpl::set_compression_gain_db(int gain) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000369 if (gain < 0 || gain > 90) {
peahdf3efa82015-11-28 12:35:15 -0800370 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000371 }
peahbfa97112016-03-10 21:09:04 -0800372 {
373 rtc::CritScope cs(crit_capture_);
374 compression_gain_db_ = gain;
375 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000376 return Configure();
377}
378
niklase@google.com470e71d2011-07-07 08:21:25 +0000379int GainControlImpl::enable_limiter(bool enable) {
peahbfa97112016-03-10 21:09:04 -0800380 {
381 rtc::CritScope cs(crit_capture_);
382 limiter_enabled_ = enable;
383 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000384 return Configure();
385}
386
387bool GainControlImpl::is_limiter_enabled() const {
peahdf3efa82015-11-28 12:35:15 -0800388 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000389 return limiter_enabled_;
390}
391
peahb8fbb542016-03-15 02:28:08 -0700392void GainControlImpl::Initialize(size_t num_proc_channels, int sample_rate_hz) {
peahbfa97112016-03-10 21:09:04 -0800393 rtc::CritScope cs_render(crit_render_);
394 rtc::CritScope cs_capture(crit_capture_);
peah135259a2016-10-28 03:12:11 -0700395 data_dumper_->InitiateNewSetOfRecordings();
peahb8fbb542016-03-15 02:28:08 -0700396
397 num_proc_channels_ = rtc::Optional<size_t>(num_proc_channels);
398 sample_rate_hz_ = rtc::Optional<int>(sample_rate_hz);
399
peahbfa97112016-03-10 21:09:04 -0800400 if (!enabled_) {
401 return;
niklase@google.com470e71d2011-07-07 08:21:25 +0000402 }
403
peahb8fbb542016-03-15 02:28:08 -0700404 gain_controllers_.resize(*num_proc_channels_);
peahbfa97112016-03-10 21:09:04 -0800405 for (auto& gain_controller : gain_controllers_) {
406 if (!gain_controller) {
407 gain_controller.reset(new GainController());
408 }
409 gain_controller->Initialize(minimum_capture_level_, maximum_capture_level_,
peahb8fbb542016-03-15 02:28:08 -0700410 mode_, *sample_rate_hz_, analog_capture_level_);
peahbfa97112016-03-10 21:09:04 -0800411 }
412
413 Configure();
peah4d291f72015-11-16 23:52:25 -0800414}
415
peahbfa97112016-03-10 21:09:04 -0800416int GainControlImpl::Configure() {
peahdf3efa82015-11-28 12:35:15 -0800417 rtc::CritScope cs_render(crit_render_);
418 rtc::CritScope cs_capture(crit_capture_);
pbos@webrtc.orge468bc92014-12-18 09:11:33 +0000419 WebRtcAgcConfig config;
niklase@google.com470e71d2011-07-07 08:21:25 +0000420 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we
421 // change the interface.
kwiberg9e2be5f2016-09-14 05:23:22 -0700422 //RTC_DCHECK_LE(target_level_dbfs_, 0);
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000423 //config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_);
424 config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000425 config.compressionGaindB =
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000426 static_cast<int16_t>(compression_gain_db_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000427 config.limiterEnable = limiter_enabled_;
428
peahbfa97112016-03-10 21:09:04 -0800429 int error = AudioProcessing::kNoError;
430 for (auto& gain_controller : gain_controllers_) {
431 const int handle_error =
432 WebRtcAgc_set_config(gain_controller->state(), config);
433 if (handle_error != AudioProcessing::kNoError) {
434 error = handle_error;
435 }
436 }
437 return error;
niklase@google.com470e71d2011-07-07 08:21:25 +0000438}
niklase@google.com470e71d2011-07-07 08:21:25 +0000439} // namespace webrtc