blob: 7265d7b0f10bd76feedfebcf0ba9190ed3a5038c [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"
Per Åhgren3daedb62019-11-22 12:11:40 +010022#include "rtc_base/logging.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000023
niklase@google.com470e71d2011-07-07 08:21:25 +000024namespace webrtc {
25
26typedef void Handle;
27
niklase@google.com470e71d2011-07-07 08:21:25 +000028namespace {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +000029int16_t MapSetting(GainControl::Mode mode) {
niklase@google.com470e71d2011-07-07 08:21:25 +000030 switch (mode) {
31 case GainControl::kAdaptiveAnalog:
32 return kAgcModeAdaptiveAnalog;
niklase@google.com470e71d2011-07-07 08:21:25 +000033 case GainControl::kAdaptiveDigital:
34 return kAgcModeAdaptiveDigital;
niklase@google.com470e71d2011-07-07 08:21:25 +000035 case GainControl::kFixedDigital:
36 return kAgcModeFixedDigital;
niklase@google.com470e71d2011-07-07 08:21:25 +000037 }
nisseeb4ca4e2017-01-12 02:24:27 -080038 RTC_NOTREACHED();
mflodman@webrtc.org657b2a42012-02-06 11:06:01 +000039 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +000040}
niklase@google.com470e71d2011-07-07 08:21:25 +000041
peah2446e5a2015-11-18 06:11:13 -080042} // namespace
peah4d291f72015-11-16 23:52:25 -080043
peahbfa97112016-03-10 21:09:04 -080044class GainControlImpl::GainController {
45 public:
46 explicit GainController() {
47 state_ = WebRtcAgc_Create();
48 RTC_CHECK(state_);
49 }
50
51 ~GainController() {
52 RTC_DCHECK(state_);
53 WebRtcAgc_Free(state_);
54 }
55
56 Handle* state() {
57 RTC_DCHECK(state_);
58 return state_;
59 }
60
61 void Initialize(int minimum_capture_level,
62 int maximum_capture_level,
63 Mode mode,
64 int sample_rate_hz,
65 int capture_level) {
66 RTC_DCHECK(state_);
67 int error =
68 WebRtcAgc_Init(state_, minimum_capture_level, maximum_capture_level,
69 MapSetting(mode), sample_rate_hz);
70 RTC_DCHECK_EQ(0, error);
71
72 set_capture_level(capture_level);
73 }
74
Yves Gerey665174f2018-06-19 15:03:05 +020075 void set_capture_level(int capture_level) { capture_level_ = capture_level; }
peahbfa97112016-03-10 21:09:04 -080076
77 int get_capture_level() {
78 RTC_DCHECK(capture_level_);
79 return *capture_level_;
80 }
81
82 private:
83 Handle* state_;
84 // TODO(peah): Remove the optional once the initialization is moved into the
85 // ctor.
Danil Chapovalovdb9f7ab2018-06-19 10:50:11 +020086 absl::optional<int> capture_level_;
peahbfa97112016-03-10 21:09:04 -080087
88 RTC_DISALLOW_COPY_AND_ASSIGN(GainController);
89};
90
peah135259a2016-10-28 03:12:11 -070091int GainControlImpl::instance_counter_ = 0;
92
Sam Zackrissonf0d1c032019-03-27 13:28:08 +010093GainControlImpl::GainControlImpl()
94 : 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),
Sam Zackrissonf0d1c032019-03-27 13:28:08 +0100103 stream_is_saturated_(false) {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000104
105GainControlImpl::~GainControlImpl() {}
106
peah701d6282016-10-25 05:42:20 -0700107void GainControlImpl::ProcessRenderAudio(
108 rtc::ArrayView<const int16_t> packed_render_audio) {
peahbfa97112016-03-10 21:09:04 -0800109 if (!enabled_) {
peah4d291f72015-11-16 23:52:25 -0800110 return;
111 }
112
peah701d6282016-10-25 05:42:20 -0700113 for (auto& gain_controller : gain_controllers_) {
114 WebRtcAgc_AddFarend(gain_controller->state(), packed_render_audio.data(),
115 packed_render_audio.size());
peah4d291f72015-11-16 23:52:25 -0800116 }
117}
118
peah701d6282016-10-25 05:42:20 -0700119void GainControlImpl::PackRenderAudioBuffer(
Per Åhgrene35b32c2019-11-22 18:22:04 +0100120 const AudioBuffer& audio,
peah701d6282016-10-25 05:42:20 -0700121 std::vector<int16_t>* packed_buffer) {
Per Åhgrene35b32c2019-11-22 18:22:04 +0100122 RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength, audio.num_frames_per_band());
Per Åhgren928146f2019-08-20 09:19:21 +0200123 std::array<int16_t, AudioBuffer::kMaxSplitFrameLength> mixed_low_pass_data;
124 rtc::ArrayView<const int16_t> mixed_low_pass(mixed_low_pass_data.data(),
Per Åhgrene35b32c2019-11-22 18:22:04 +0100125 audio.num_frames_per_band());
126 if (audio.num_channels() == 1) {
127 FloatS16ToS16(audio.split_bands_const(0)[kBand0To8kHz],
128 audio.num_frames_per_band(), mixed_low_pass_data.data());
Per Åhgrena1351272019-08-15 12:15:46 +0200129 } else {
Per Åhgrene35b32c2019-11-22 18:22:04 +0100130 const int num_channels = static_cast<int>(audio.num_channels());
131 for (size_t i = 0; i < audio.num_frames_per_band(); ++i) {
Per Åhgren928146f2019-08-20 09:19:21 +0200132 int32_t value =
Per Åhgrene35b32c2019-11-22 18:22:04 +0100133 FloatS16ToS16(audio.split_channels_const(kBand0To8kHz)[0][i]);
Per Åhgrena1351272019-08-15 12:15:46 +0200134 for (int j = 1; j < num_channels; ++j) {
Per Åhgrene35b32c2019-11-22 18:22:04 +0100135 value += FloatS16ToS16(audio.split_channels_const(kBand0To8kHz)[j][i]);
Per Åhgrena1351272019-08-15 12:15:46 +0200136 }
137 mixed_low_pass_data[i] = value / num_channels;
138 }
Per Åhgrena1351272019-08-15 12:15:46 +0200139 }
140
peah701d6282016-10-25 05:42:20 -0700141 packed_buffer->clear();
Per Åhgrena1351272019-08-15 12:15:46 +0200142 packed_buffer->insert(packed_buffer->end(), mixed_low_pass.data(),
Per Åhgrene35b32c2019-11-22 18:22:04 +0100143 (mixed_low_pass.data() + audio.num_frames_per_band()));
peah701d6282016-10-25 05:42:20 -0700144}
145
Per Åhgrene35b32c2019-11-22 18:22:04 +0100146int GainControlImpl::AnalyzeCaptureAudio(const AudioBuffer& audio) {
peahbfa97112016-03-10 21:09:04 -0800147 if (!enabled_) {
peahdf3efa82015-11-28 12:35:15 -0800148 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000149 }
150
peahb8fbb542016-03-15 02:28:08 -0700151 RTC_DCHECK(num_proc_channels_);
Per Åhgrene35b32c2019-11-22 18:22:04 +0100152 RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength, audio.num_frames_per_band());
153 RTC_DCHECK_EQ(audio.num_channels(), *num_proc_channels_);
peahb8fbb542016-03-15 02:28:08 -0700154 RTC_DCHECK_LE(*num_proc_channels_, gain_controllers_.size());
niklase@google.com470e71d2011-07-07 08:21:25 +0000155
Per Åhgren928146f2019-08-20 09:19:21 +0200156 int16_t split_band_data[AudioBuffer::kMaxNumBands]
157 [AudioBuffer::kMaxSplitFrameLength];
158 int16_t* split_bands[AudioBuffer::kMaxNumBands] = {
159 split_band_data[0], split_band_data[1], split_band_data[2]};
160
niklase@google.com470e71d2011-07-07 08:21:25 +0000161 if (mode_ == kAdaptiveAnalog) {
peahbfa97112016-03-10 21:09:04 -0800162 int capture_channel = 0;
163 for (auto& gain_controller : gain_controllers_) {
164 gain_controller->set_capture_level(analog_capture_level_);
Per Åhgren928146f2019-08-20 09:19:21 +0200165
Per Åhgrene35b32c2019-11-22 18:22:04 +0100166 audio.ExportSplitChannelData(capture_channel, split_bands);
Per Åhgren928146f2019-08-20 09:19:21 +0200167
168 int err =
169 WebRtcAgc_AddMic(gain_controller->state(), split_bands,
Per Åhgrene35b32c2019-11-22 18:22:04 +0100170 audio.num_bands(), audio.num_frames_per_band());
niklase@google.com470e71d2011-07-07 08:21:25 +0000171
peahdf3efa82015-11-28 12:35:15 -0800172 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800173 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000174 }
peahbfa97112016-03-10 21:09:04 -0800175 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000176 }
177 } else if (mode_ == kAdaptiveDigital) {
peahbfa97112016-03-10 21:09:04 -0800178 int capture_channel = 0;
179 for (auto& gain_controller : gain_controllers_) {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000180 int32_t capture_level_out = 0;
Per Åhgren928146f2019-08-20 09:19:21 +0200181
Per Åhgrene35b32c2019-11-22 18:22:04 +0100182 audio.ExportSplitChannelData(capture_channel, split_bands);
Per Åhgren928146f2019-08-20 09:19:21 +0200183
184 int err =
185 WebRtcAgc_VirtualMic(gain_controller->state(), split_bands,
Per Åhgrene35b32c2019-11-22 18:22:04 +0100186 audio.num_bands(), audio.num_frames_per_band(),
Per Åhgren928146f2019-08-20 09:19:21 +0200187 analog_capture_level_, &capture_level_out);
188
peahbfa97112016-03-10 21:09:04 -0800189 gain_controller->set_capture_level(capture_level_out);
niklase@google.com470e71d2011-07-07 08:21:25 +0000190
peahdf3efa82015-11-28 12:35:15 -0800191 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800192 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000193 }
peahbfa97112016-03-10 21:09:04 -0800194 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000195 }
196 }
197
peahdf3efa82015-11-28 12:35:15 -0800198 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000199}
200
peahb8fbb542016-03-15 02:28:08 -0700201int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio,
202 bool stream_has_echo) {
peahbfa97112016-03-10 21:09:04 -0800203 if (!enabled_) {
peahdf3efa82015-11-28 12:35:15 -0800204 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000205 }
206
207 if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) {
peahdf3efa82015-11-28 12:35:15 -0800208 return AudioProcessing::kStreamParameterNotSetError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000209 }
210
peahb8fbb542016-03-15 02:28:08 -0700211 RTC_DCHECK(num_proc_channels_);
Per Åhgren928146f2019-08-20 09:19:21 +0200212 RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength,
213 audio->num_frames_per_band());
peahb8fbb542016-03-15 02:28:08 -0700214 RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000215
216 stream_is_saturated_ = false;
peahbfa97112016-03-10 21:09:04 -0800217 int capture_channel = 0;
218 for (auto& gain_controller : gain_controllers_) {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000219 int32_t capture_level_out = 0;
220 uint8_t saturation_warning = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000221
Per Åhgren928146f2019-08-20 09:19:21 +0200222 int16_t split_band_data[AudioBuffer::kMaxNumBands]
223 [AudioBuffer::kMaxSplitFrameLength];
224 int16_t* split_bands[AudioBuffer::kMaxNumBands] = {
225 split_band_data[0], split_band_data[1], split_band_data[2]};
Per Åhgrend47941e2019-08-22 11:51:13 +0200226 audio->ExportSplitChannelData(capture_channel, split_bands);
Per Åhgren928146f2019-08-20 09:19:21 +0200227
peahdf3efa82015-11-28 12:35:15 -0800228 // The call to stream_has_echo() is ok from a deadlock perspective
229 // as the capture lock is allready held.
niklase@google.com470e71d2011-07-07 08:21:25 +0000230 int err = WebRtcAgc_Process(
Per Åhgren928146f2019-08-20 09:19:21 +0200231 gain_controller->state(), split_bands, audio->num_bands(),
232 audio->num_frames_per_band(), split_bands,
peahbfa97112016-03-10 21:09:04 -0800233 gain_controller->get_capture_level(), &capture_level_out,
peahb8fbb542016-03-15 02:28:08 -0700234 stream_has_echo, &saturation_warning);
niklase@google.com470e71d2011-07-07 08:21:25 +0000235
Per Åhgrend47941e2019-08-22 11:51:13 +0200236 audio->ImportSplitChannelData(capture_channel, split_bands);
Per Åhgren928146f2019-08-20 09:19:21 +0200237
peahdf3efa82015-11-28 12:35:15 -0800238 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800239 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000240 }
241
peahbfa97112016-03-10 21:09:04 -0800242 gain_controller->set_capture_level(capture_level_out);
niklase@google.com470e71d2011-07-07 08:21:25 +0000243 if (saturation_warning == 1) {
244 stream_is_saturated_ = true;
245 }
peahbfa97112016-03-10 21:09:04 -0800246
247 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000248 }
249
peahb8fbb542016-03-15 02:28:08 -0700250 RTC_DCHECK_LT(0ul, *num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000251 if (mode_ == kAdaptiveAnalog) {
252 // Take the analog level to be the average across the handles.
253 analog_capture_level_ = 0;
peahbfa97112016-03-10 21:09:04 -0800254 for (auto& gain_controller : gain_controllers_) {
255 analog_capture_level_ += gain_controller->get_capture_level();
niklase@google.com470e71d2011-07-07 08:21:25 +0000256 }
257
peahb8fbb542016-03-15 02:28:08 -0700258 analog_capture_level_ /= (*num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000259 }
260
261 was_analog_level_set_ = false;
peahdf3efa82015-11-28 12:35:15 -0800262 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000263}
264
aluebs11d4a422016-04-28 14:58:32 -0700265int GainControlImpl::compression_gain_db() const {
aluebs11d4a422016-04-28 14:58:32 -0700266 return compression_gain_db_;
267}
268
niklase@google.com470e71d2011-07-07 08:21:25 +0000269// TODO(ajm): ensure this is called under kAdaptiveAnalog.
270int GainControlImpl::set_stream_analog_level(int level) {
peah135259a2016-10-28 03:12:11 -0700271 data_dumper_->DumpRaw("gain_control_set_stream_analog_level", 1, &level);
peahdf3efa82015-11-28 12:35:15 -0800272
niklase@google.com470e71d2011-07-07 08:21:25 +0000273 was_analog_level_set_ = true;
274 if (level < minimum_capture_level_ || level > maximum_capture_level_) {
peahdf3efa82015-11-28 12:35:15 -0800275 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000276 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000277 analog_capture_level_ = level;
278
peahdf3efa82015-11-28 12:35:15 -0800279 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000280}
281
Sam Zackrissonf0d1c032019-03-27 13:28:08 +0100282int GainControlImpl::stream_analog_level() const {
peah135259a2016-10-28 03:12:11 -0700283 data_dumper_->DumpRaw("gain_control_stream_analog_level", 1,
284 &analog_capture_level_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000285 // TODO(ajm): enable this assertion?
Yves Gerey665174f2018-06-19 15:03:05 +0200286 // RTC_DCHECK_EQ(kAdaptiveAnalog, mode_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000287
288 return analog_capture_level_;
289}
290
291int GainControlImpl::Enable(bool enable) {
peahbfa97112016-03-10 21:09:04 -0800292 if (enable && !enabled_) {
293 enabled_ = enable; // Must be set before Initialize() is called.
peahb8fbb542016-03-15 02:28:08 -0700294
295 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 } else {
299 enabled_ = enable;
300 }
301 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000302}
303
304bool GainControlImpl::is_enabled() const {
peahbfa97112016-03-10 21:09:04 -0800305 return enabled_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000306}
307
308int GainControlImpl::set_mode(Mode mode) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000309 if (MapSetting(mode) == -1) {
peahdf3efa82015-11-28 12:35:15 -0800310 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000311 }
312
313 mode_ = mode;
peahb8fbb542016-03-15 02:28:08 -0700314 RTC_DCHECK(num_proc_channels_);
315 RTC_DCHECK(sample_rate_hz_);
316 Initialize(*num_proc_channels_, *sample_rate_hz_);
peahbfa97112016-03-10 21:09:04 -0800317 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000318}
319
320GainControl::Mode GainControlImpl::mode() const {
321 return mode_;
322}
323
Yves Gerey665174f2018-06-19 15:03:05 +0200324int GainControlImpl::set_analog_level_limits(int minimum, int maximum) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000325 if (minimum < 0) {
peahdf3efa82015-11-28 12:35:15 -0800326 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000327 }
328
329 if (maximum > 65535) {
peahdf3efa82015-11-28 12:35:15 -0800330 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000331 }
332
333 if (maximum < minimum) {
peahdf3efa82015-11-28 12:35:15 -0800334 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000335 }
336
peah7c931ad2016-03-24 12:52:02 -0700337 size_t num_proc_channels_local = 0u;
338 int sample_rate_hz_local = 0;
339 {
peah7c931ad2016-03-24 12:52:02 -0700340 minimum_capture_level_ = minimum;
341 maximum_capture_level_ = maximum;
342
343 RTC_DCHECK(num_proc_channels_);
344 RTC_DCHECK(sample_rate_hz_);
345 num_proc_channels_local = *num_proc_channels_;
346 sample_rate_hz_local = *sample_rate_hz_;
347 }
348 Initialize(num_proc_channels_local, sample_rate_hz_local);
peahbfa97112016-03-10 21:09:04 -0800349 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000350}
351
352int GainControlImpl::analog_level_minimum() const {
353 return minimum_capture_level_;
354}
355
356int GainControlImpl::analog_level_maximum() const {
357 return maximum_capture_level_;
358}
359
360bool GainControlImpl::stream_is_saturated() const {
361 return stream_is_saturated_;
362}
363
364int GainControlImpl::set_target_level_dbfs(int level) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000365 if (level > 31 || level < 0) {
peahdf3efa82015-11-28 12:35:15 -0800366 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000367 }
Sam Zackrisson421c8592019-02-11 13:39:46 +0100368 target_level_dbfs_ = level;
niklase@google.com470e71d2011-07-07 08:21:25 +0000369 return Configure();
370}
371
372int GainControlImpl::target_level_dbfs() const {
373 return target_level_dbfs_;
374}
375
376int GainControlImpl::set_compression_gain_db(int gain) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000377 if (gain < 0 || gain > 90) {
Per Åhgren3daedb62019-11-22 12:11:40 +0100378 RTC_LOG(LS_ERROR) << "set_compression_gain_db(" << gain << ") failed.";
peahdf3efa82015-11-28 12:35:15 -0800379 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000380 }
Sam Zackrisson421c8592019-02-11 13:39:46 +0100381 compression_gain_db_ = gain;
niklase@google.com470e71d2011-07-07 08:21:25 +0000382 return Configure();
383}
384
niklase@google.com470e71d2011-07-07 08:21:25 +0000385int GainControlImpl::enable_limiter(bool enable) {
Sam Zackrisson421c8592019-02-11 13:39:46 +0100386 limiter_enabled_ = enable;
niklase@google.com470e71d2011-07-07 08:21:25 +0000387 return Configure();
388}
389
390bool GainControlImpl::is_limiter_enabled() const {
391 return limiter_enabled_;
392}
393
peahb8fbb542016-03-15 02:28:08 -0700394void GainControlImpl::Initialize(size_t num_proc_channels, int sample_rate_hz) {
peah135259a2016-10-28 03:12:11 -0700395 data_dumper_->InitiateNewSetOfRecordings();
peahb8fbb542016-03-15 02:28:08 -0700396
Oskar Sundbomaa8b67d2017-11-17 14:34:48 +0100397 num_proc_channels_ = num_proc_channels;
398 sample_rate_hz_ = sample_rate_hz;
peahb8fbb542016-03-15 02:28:08 -0700399
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() {
pbos@webrtc.orge468bc92014-12-18 09:11:33 +0000417 WebRtcAgcConfig config;
niklase@google.com470e71d2011-07-07 08:21:25 +0000418 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we
419 // change the interface.
Yves Gerey665174f2018-06-19 15:03:05 +0200420 // RTC_DCHECK_LE(target_level_dbfs_, 0);
421 // config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_);
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000422 config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_);
Yves Gerey665174f2018-06-19 15:03:05 +0200423 config.compressionGaindB = static_cast<int16_t>(compression_gain_db_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000424 config.limiterEnable = limiter_enabled_;
425
peahbfa97112016-03-10 21:09:04 -0800426 int error = AudioProcessing::kNoError;
427 for (auto& gain_controller : gain_controllers_) {
428 const int handle_error =
429 WebRtcAgc_set_config(gain_controller->state(), config);
430 if (handle_error != AudioProcessing::kNoError) {
431 error = handle_error;
432 }
433 }
434 return error;
niklase@google.com470e71d2011-07-07 08:21:25 +0000435}
niklase@google.com470e71d2011-07-07 08:21:25 +0000436} // namespace webrtc