blob: 95e6a3af902f2ca76239fc0b0b42dbc7b1bf212b [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 Zackrissonf0d1c032019-03-27 13:28:08 +010092GainControlImpl::GainControlImpl()
93 : data_dumper_(new ApmDataDumper(instance_counter_)),
peah4d291f72015-11-16 23:52:25 -080094 mode_(kAdaptiveAnalog),
95 minimum_capture_level_(0),
96 maximum_capture_level_(255),
97 limiter_enabled_(true),
98 target_level_dbfs_(3),
99 compression_gain_db_(9),
100 analog_capture_level_(0),
101 was_analog_level_set_(false),
Sam Zackrissonf0d1c032019-03-27 13:28:08 +0100102 stream_is_saturated_(false) {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000103
104GainControlImpl::~GainControlImpl() {}
105
peah701d6282016-10-25 05:42:20 -0700106void GainControlImpl::ProcessRenderAudio(
107 rtc::ArrayView<const int16_t> packed_render_audio) {
peahbfa97112016-03-10 21:09:04 -0800108 if (!enabled_) {
peah4d291f72015-11-16 23:52:25 -0800109 return;
110 }
111
peah701d6282016-10-25 05:42:20 -0700112 for (auto& gain_controller : gain_controllers_) {
113 WebRtcAgc_AddFarend(gain_controller->state(), packed_render_audio.data(),
114 packed_render_audio.size());
peah4d291f72015-11-16 23:52:25 -0800115 }
116}
117
peah701d6282016-10-25 05:42:20 -0700118void GainControlImpl::PackRenderAudioBuffer(
119 AudioBuffer* audio,
120 std::vector<int16_t>* packed_buffer) {
Per Ã…hgren928146f2019-08-20 09:19:21 +0200121 RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength,
122 audio->num_frames_per_band());
123 std::array<int16_t, AudioBuffer::kMaxSplitFrameLength> mixed_low_pass_data;
124 rtc::ArrayView<const int16_t> mixed_low_pass(mixed_low_pass_data.data(),
125 audio->num_frames_per_band());
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200126 if (audio->num_channels() == 1) {
127 FloatS16ToS16(audio->split_bands_const(0)[kBand0To8kHz],
Per Ã…hgren928146f2019-08-20 09:19:21 +0200128 audio->num_frames_per_band(), mixed_low_pass_data.data());
Per Ã…hgrena1351272019-08-15 12:15:46 +0200129 } else {
130 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 Ã…hgrend47941e2019-08-22 11:51:13 +0200133 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 Ã…hgrend47941e2019-08-22 11:51:13 +0200135 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(),
143 (mixed_low_pass.data() + audio->num_frames_per_band()));
peah701d6282016-10-25 05:42:20 -0700144}
145
niklase@google.com470e71d2011-07-07 08:21:25 +0000146int GainControlImpl::AnalyzeCaptureAudio(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 Ã…hgren928146f2019-08-20 09:19:21 +0200152 RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength,
153 audio->num_frames_per_band());
peahb8fbb542016-03-15 02:28:08 -0700154 RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_);
155 RTC_DCHECK_LE(*num_proc_channels_, gain_controllers_.size());
niklase@google.com470e71d2011-07-07 08:21:25 +0000156
Per Ã…hgren928146f2019-08-20 09:19:21 +0200157 int16_t split_band_data[AudioBuffer::kMaxNumBands]
158 [AudioBuffer::kMaxSplitFrameLength];
159 int16_t* split_bands[AudioBuffer::kMaxNumBands] = {
160 split_band_data[0], split_band_data[1], split_band_data[2]};
161
niklase@google.com470e71d2011-07-07 08:21:25 +0000162 if (mode_ == kAdaptiveAnalog) {
peahbfa97112016-03-10 21:09:04 -0800163 int capture_channel = 0;
164 for (auto& gain_controller : gain_controllers_) {
165 gain_controller->set_capture_level(analog_capture_level_);
Per Ã…hgren928146f2019-08-20 09:19:21 +0200166
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200167 audio->ExportSplitChannelData(capture_channel, split_bands);
Per Ã…hgren928146f2019-08-20 09:19:21 +0200168
169 int err =
170 WebRtcAgc_AddMic(gain_controller->state(), split_bands,
171 audio->num_bands(), audio->num_frames_per_band());
172
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200173 audio->ImportSplitChannelData(capture_channel, split_bands);
niklase@google.com470e71d2011-07-07 08:21:25 +0000174
peahdf3efa82015-11-28 12:35:15 -0800175 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800176 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000177 }
peahbfa97112016-03-10 21:09:04 -0800178 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000179 }
180 } else if (mode_ == kAdaptiveDigital) {
peahbfa97112016-03-10 21:09:04 -0800181 int capture_channel = 0;
182 for (auto& gain_controller : gain_controllers_) {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000183 int32_t capture_level_out = 0;
Per Ã…hgren928146f2019-08-20 09:19:21 +0200184
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200185 audio->ExportSplitChannelData(capture_channel, split_bands);
Per Ã…hgren928146f2019-08-20 09:19:21 +0200186
187 int err =
188 WebRtcAgc_VirtualMic(gain_controller->state(), split_bands,
189 audio->num_bands(), audio->num_frames_per_band(),
190 analog_capture_level_, &capture_level_out);
191
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200192 audio->ImportSplitChannelData(capture_channel, split_bands);
niklase@google.com470e71d2011-07-07 08:21:25 +0000193
peahbfa97112016-03-10 21:09:04 -0800194 gain_controller->set_capture_level(capture_level_out);
niklase@google.com470e71d2011-07-07 08:21:25 +0000195
peahdf3efa82015-11-28 12:35:15 -0800196 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800197 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000198 }
peahbfa97112016-03-10 21:09:04 -0800199 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000200 }
201 }
202
peahdf3efa82015-11-28 12:35:15 -0800203 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000204}
205
peahb8fbb542016-03-15 02:28:08 -0700206int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio,
207 bool stream_has_echo) {
peahbfa97112016-03-10 21:09:04 -0800208 if (!enabled_) {
peahdf3efa82015-11-28 12:35:15 -0800209 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000210 }
211
212 if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) {
peahdf3efa82015-11-28 12:35:15 -0800213 return AudioProcessing::kStreamParameterNotSetError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000214 }
215
peahb8fbb542016-03-15 02:28:08 -0700216 RTC_DCHECK(num_proc_channels_);
Per Ã…hgren928146f2019-08-20 09:19:21 +0200217 RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength,
218 audio->num_frames_per_band());
peahb8fbb542016-03-15 02:28:08 -0700219 RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000220
221 stream_is_saturated_ = false;
peahbfa97112016-03-10 21:09:04 -0800222 int capture_channel = 0;
223 for (auto& gain_controller : gain_controllers_) {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000224 int32_t capture_level_out = 0;
225 uint8_t saturation_warning = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000226
Per Ã…hgren928146f2019-08-20 09:19:21 +0200227 int16_t split_band_data[AudioBuffer::kMaxNumBands]
228 [AudioBuffer::kMaxSplitFrameLength];
229 int16_t* split_bands[AudioBuffer::kMaxNumBands] = {
230 split_band_data[0], split_band_data[1], split_band_data[2]};
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200231 audio->ExportSplitChannelData(capture_channel, split_bands);
Per Ã…hgren928146f2019-08-20 09:19:21 +0200232
peahdf3efa82015-11-28 12:35:15 -0800233 // The call to stream_has_echo() is ok from a deadlock perspective
234 // as the capture lock is allready held.
niklase@google.com470e71d2011-07-07 08:21:25 +0000235 int err = WebRtcAgc_Process(
Per Ã…hgren928146f2019-08-20 09:19:21 +0200236 gain_controller->state(), split_bands, audio->num_bands(),
237 audio->num_frames_per_band(), split_bands,
peahbfa97112016-03-10 21:09:04 -0800238 gain_controller->get_capture_level(), &capture_level_out,
peahb8fbb542016-03-15 02:28:08 -0700239 stream_has_echo, &saturation_warning);
niklase@google.com470e71d2011-07-07 08:21:25 +0000240
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200241 audio->ImportSplitChannelData(capture_channel, split_bands);
Per Ã…hgren928146f2019-08-20 09:19:21 +0200242
peahdf3efa82015-11-28 12:35:15 -0800243 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800244 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000245 }
246
peahbfa97112016-03-10 21:09:04 -0800247 gain_controller->set_capture_level(capture_level_out);
niklase@google.com470e71d2011-07-07 08:21:25 +0000248 if (saturation_warning == 1) {
249 stream_is_saturated_ = true;
250 }
peahbfa97112016-03-10 21:09:04 -0800251
252 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000253 }
254
peahb8fbb542016-03-15 02:28:08 -0700255 RTC_DCHECK_LT(0ul, *num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000256 if (mode_ == kAdaptiveAnalog) {
257 // Take the analog level to be the average across the handles.
258 analog_capture_level_ = 0;
peahbfa97112016-03-10 21:09:04 -0800259 for (auto& gain_controller : gain_controllers_) {
260 analog_capture_level_ += gain_controller->get_capture_level();
niklase@google.com470e71d2011-07-07 08:21:25 +0000261 }
262
peahb8fbb542016-03-15 02:28:08 -0700263 analog_capture_level_ /= (*num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000264 }
265
266 was_analog_level_set_ = false;
peahdf3efa82015-11-28 12:35:15 -0800267 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000268}
269
aluebs11d4a422016-04-28 14:58:32 -0700270int GainControlImpl::compression_gain_db() const {
aluebs11d4a422016-04-28 14:58:32 -0700271 return compression_gain_db_;
272}
273
niklase@google.com470e71d2011-07-07 08:21:25 +0000274// TODO(ajm): ensure this is called under kAdaptiveAnalog.
275int GainControlImpl::set_stream_analog_level(int level) {
peah135259a2016-10-28 03:12:11 -0700276 data_dumper_->DumpRaw("gain_control_set_stream_analog_level", 1, &level);
peahdf3efa82015-11-28 12:35:15 -0800277
niklase@google.com470e71d2011-07-07 08:21:25 +0000278 was_analog_level_set_ = true;
279 if (level < minimum_capture_level_ || level > maximum_capture_level_) {
peahdf3efa82015-11-28 12:35:15 -0800280 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000281 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000282 analog_capture_level_ = level;
283
peahdf3efa82015-11-28 12:35:15 -0800284 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000285}
286
Sam Zackrissonf0d1c032019-03-27 13:28:08 +0100287int GainControlImpl::stream_analog_level() const {
peah135259a2016-10-28 03:12:11 -0700288 data_dumper_->DumpRaw("gain_control_stream_analog_level", 1,
289 &analog_capture_level_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000290 // TODO(ajm): enable this assertion?
Yves Gerey665174f2018-06-19 15:03:05 +0200291 // RTC_DCHECK_EQ(kAdaptiveAnalog, mode_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000292
293 return analog_capture_level_;
294}
295
296int GainControlImpl::Enable(bool enable) {
peahbfa97112016-03-10 21:09:04 -0800297 if (enable && !enabled_) {
298 enabled_ = enable; // Must be set before Initialize() is called.
peahb8fbb542016-03-15 02:28:08 -0700299
300 RTC_DCHECK(num_proc_channels_);
301 RTC_DCHECK(sample_rate_hz_);
302 Initialize(*num_proc_channels_, *sample_rate_hz_);
peahbfa97112016-03-10 21:09:04 -0800303 } else {
304 enabled_ = enable;
305 }
306 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000307}
308
309bool GainControlImpl::is_enabled() const {
peahbfa97112016-03-10 21:09:04 -0800310 return enabled_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000311}
312
313int GainControlImpl::set_mode(Mode mode) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000314 if (MapSetting(mode) == -1) {
peahdf3efa82015-11-28 12:35:15 -0800315 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000316 }
317
318 mode_ = mode;
peahb8fbb542016-03-15 02:28:08 -0700319 RTC_DCHECK(num_proc_channels_);
320 RTC_DCHECK(sample_rate_hz_);
321 Initialize(*num_proc_channels_, *sample_rate_hz_);
peahbfa97112016-03-10 21:09:04 -0800322 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000323}
324
325GainControl::Mode GainControlImpl::mode() const {
326 return mode_;
327}
328
Yves Gerey665174f2018-06-19 15:03:05 +0200329int GainControlImpl::set_analog_level_limits(int minimum, int maximum) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000330 if (minimum < 0) {
peahdf3efa82015-11-28 12:35:15 -0800331 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000332 }
333
334 if (maximum > 65535) {
peahdf3efa82015-11-28 12:35:15 -0800335 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000336 }
337
338 if (maximum < minimum) {
peahdf3efa82015-11-28 12:35:15 -0800339 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000340 }
341
peah7c931ad2016-03-24 12:52:02 -0700342 size_t num_proc_channels_local = 0u;
343 int sample_rate_hz_local = 0;
344 {
peah7c931ad2016-03-24 12:52:02 -0700345 minimum_capture_level_ = minimum;
346 maximum_capture_level_ = maximum;
347
348 RTC_DCHECK(num_proc_channels_);
349 RTC_DCHECK(sample_rate_hz_);
350 num_proc_channels_local = *num_proc_channels_;
351 sample_rate_hz_local = *sample_rate_hz_;
352 }
353 Initialize(num_proc_channels_local, sample_rate_hz_local);
peahbfa97112016-03-10 21:09:04 -0800354 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000355}
356
357int GainControlImpl::analog_level_minimum() const {
358 return minimum_capture_level_;
359}
360
361int GainControlImpl::analog_level_maximum() const {
362 return maximum_capture_level_;
363}
364
365bool GainControlImpl::stream_is_saturated() const {
366 return stream_is_saturated_;
367}
368
369int GainControlImpl::set_target_level_dbfs(int level) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000370 if (level > 31 || level < 0) {
peahdf3efa82015-11-28 12:35:15 -0800371 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000372 }
Sam Zackrisson421c8592019-02-11 13:39:46 +0100373 target_level_dbfs_ = level;
niklase@google.com470e71d2011-07-07 08:21:25 +0000374 return Configure();
375}
376
377int GainControlImpl::target_level_dbfs() const {
378 return target_level_dbfs_;
379}
380
381int GainControlImpl::set_compression_gain_db(int gain) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000382 if (gain < 0 || gain > 90) {
peahdf3efa82015-11-28 12:35:15 -0800383 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000384 }
Sam Zackrisson421c8592019-02-11 13:39:46 +0100385 compression_gain_db_ = gain;
niklase@google.com470e71d2011-07-07 08:21:25 +0000386 return Configure();
387}
388
niklase@google.com470e71d2011-07-07 08:21:25 +0000389int GainControlImpl::enable_limiter(bool enable) {
Sam Zackrisson421c8592019-02-11 13:39:46 +0100390 limiter_enabled_ = enable;
niklase@google.com470e71d2011-07-07 08:21:25 +0000391 return Configure();
392}
393
394bool GainControlImpl::is_limiter_enabled() const {
395 return limiter_enabled_;
396}
397
peahb8fbb542016-03-15 02:28:08 -0700398void GainControlImpl::Initialize(size_t num_proc_channels, int sample_rate_hz) {
peah135259a2016-10-28 03:12:11 -0700399 data_dumper_->InitiateNewSetOfRecordings();
peahb8fbb542016-03-15 02:28:08 -0700400
Oskar Sundbomaa8b67d2017-11-17 14:34:48 +0100401 num_proc_channels_ = num_proc_channels;
402 sample_rate_hz_ = sample_rate_hz;
peahb8fbb542016-03-15 02:28:08 -0700403
peahbfa97112016-03-10 21:09:04 -0800404 if (!enabled_) {
405 return;
niklase@google.com470e71d2011-07-07 08:21:25 +0000406 }
407
peahb8fbb542016-03-15 02:28:08 -0700408 gain_controllers_.resize(*num_proc_channels_);
peahbfa97112016-03-10 21:09:04 -0800409 for (auto& gain_controller : gain_controllers_) {
410 if (!gain_controller) {
411 gain_controller.reset(new GainController());
412 }
413 gain_controller->Initialize(minimum_capture_level_, maximum_capture_level_,
peahb8fbb542016-03-15 02:28:08 -0700414 mode_, *sample_rate_hz_, analog_capture_level_);
peahbfa97112016-03-10 21:09:04 -0800415 }
416
417 Configure();
peah4d291f72015-11-16 23:52:25 -0800418}
419
peahbfa97112016-03-10 21:09:04 -0800420int GainControlImpl::Configure() {
pbos@webrtc.orge468bc92014-12-18 09:11:33 +0000421 WebRtcAgcConfig config;
niklase@google.com470e71d2011-07-07 08:21:25 +0000422 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we
423 // change the interface.
Yves Gerey665174f2018-06-19 15:03:05 +0200424 // RTC_DCHECK_LE(target_level_dbfs_, 0);
425 // config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_);
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000426 config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_);
Yves Gerey665174f2018-06-19 15:03:05 +0200427 config.compressionGaindB = static_cast<int16_t>(compression_gain_db_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000428 config.limiterEnable = limiter_enabled_;
429
peahbfa97112016-03-10 21:09:04 -0800430 int error = AudioProcessing::kNoError;
431 for (auto& gain_controller : gain_controllers_) {
432 const int handle_error =
433 WebRtcAgc_set_config(gain_controller->state(), config);
434 if (handle_error != AudioProcessing::kNoError) {
435 error = handle_error;
436 }
437 }
438 return error;
niklase@google.com470e71d2011-07-07 08:21:25 +0000439}
niklase@google.com470e71d2011-07-07 08:21:25 +0000440} // namespace webrtc