blob: f0d48b29d6cec234820371406752205519848704 [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(
120 AudioBuffer* audio,
121 std::vector<int16_t>* packed_buffer) {
Per Åhgren928146f2019-08-20 09:19:21 +0200122 RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength,
123 audio->num_frames_per_band());
124 std::array<int16_t, AudioBuffer::kMaxSplitFrameLength> mixed_low_pass_data;
125 rtc::ArrayView<const int16_t> mixed_low_pass(mixed_low_pass_data.data(),
126 audio->num_frames_per_band());
Per Åhgrend47941e2019-08-22 11:51:13 +0200127 if (audio->num_channels() == 1) {
128 FloatS16ToS16(audio->split_bands_const(0)[kBand0To8kHz],
Per Åhgren928146f2019-08-20 09:19:21 +0200129 audio->num_frames_per_band(), mixed_low_pass_data.data());
Per Åhgrena1351272019-08-15 12:15:46 +0200130 } else {
131 const int num_channels = static_cast<int>(audio->num_channels());
132 for (size_t i = 0; i < audio->num_frames_per_band(); ++i) {
Per Åhgren928146f2019-08-20 09:19:21 +0200133 int32_t value =
Per Åhgrend47941e2019-08-22 11:51:13 +0200134 FloatS16ToS16(audio->split_channels_const(kBand0To8kHz)[0][i]);
Per Åhgrena1351272019-08-15 12:15:46 +0200135 for (int j = 1; j < num_channels; ++j) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200136 value += FloatS16ToS16(audio->split_channels_const(kBand0To8kHz)[j][i]);
Per Åhgrena1351272019-08-15 12:15:46 +0200137 }
138 mixed_low_pass_data[i] = value / num_channels;
139 }
Per Åhgrena1351272019-08-15 12:15:46 +0200140 }
141
peah701d6282016-10-25 05:42:20 -0700142 packed_buffer->clear();
Per Åhgrena1351272019-08-15 12:15:46 +0200143 packed_buffer->insert(packed_buffer->end(), mixed_low_pass.data(),
144 (mixed_low_pass.data() + audio->num_frames_per_band()));
peah701d6282016-10-25 05:42:20 -0700145}
146
niklase@google.com470e71d2011-07-07 08:21:25 +0000147int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
peahbfa97112016-03-10 21:09:04 -0800148 if (!enabled_) {
peahdf3efa82015-11-28 12:35:15 -0800149 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000150 }
151
peahb8fbb542016-03-15 02:28:08 -0700152 RTC_DCHECK(num_proc_channels_);
Per Åhgren928146f2019-08-20 09:19:21 +0200153 RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength,
154 audio->num_frames_per_band());
peahb8fbb542016-03-15 02:28:08 -0700155 RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_);
156 RTC_DCHECK_LE(*num_proc_channels_, gain_controllers_.size());
niklase@google.com470e71d2011-07-07 08:21:25 +0000157
Per Åhgren928146f2019-08-20 09:19:21 +0200158 int16_t split_band_data[AudioBuffer::kMaxNumBands]
159 [AudioBuffer::kMaxSplitFrameLength];
160 int16_t* split_bands[AudioBuffer::kMaxNumBands] = {
161 split_band_data[0], split_band_data[1], split_band_data[2]};
162
niklase@google.com470e71d2011-07-07 08:21:25 +0000163 if (mode_ == kAdaptiveAnalog) {
peahbfa97112016-03-10 21:09:04 -0800164 int capture_channel = 0;
165 for (auto& gain_controller : gain_controllers_) {
166 gain_controller->set_capture_level(analog_capture_level_);
Per Åhgren928146f2019-08-20 09:19:21 +0200167
Per Åhgrend47941e2019-08-22 11:51:13 +0200168 audio->ExportSplitChannelData(capture_channel, split_bands);
Per Åhgren928146f2019-08-20 09:19:21 +0200169
170 int err =
171 WebRtcAgc_AddMic(gain_controller->state(), split_bands,
172 audio->num_bands(), audio->num_frames_per_band());
173
Per Åhgrend47941e2019-08-22 11:51:13 +0200174 audio->ImportSplitChannelData(capture_channel, split_bands);
niklase@google.com470e71d2011-07-07 08:21:25 +0000175
peahdf3efa82015-11-28 12:35:15 -0800176 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800177 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000178 }
peahbfa97112016-03-10 21:09:04 -0800179 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000180 }
181 } else if (mode_ == kAdaptiveDigital) {
peahbfa97112016-03-10 21:09:04 -0800182 int capture_channel = 0;
183 for (auto& gain_controller : gain_controllers_) {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000184 int32_t capture_level_out = 0;
Per Åhgren928146f2019-08-20 09:19:21 +0200185
Per Åhgrend47941e2019-08-22 11:51:13 +0200186 audio->ExportSplitChannelData(capture_channel, split_bands);
Per Åhgren928146f2019-08-20 09:19:21 +0200187
188 int err =
189 WebRtcAgc_VirtualMic(gain_controller->state(), split_bands,
190 audio->num_bands(), audio->num_frames_per_band(),
191 analog_capture_level_, &capture_level_out);
192
Per Åhgrend47941e2019-08-22 11:51:13 +0200193 audio->ImportSplitChannelData(capture_channel, split_bands);
niklase@google.com470e71d2011-07-07 08:21:25 +0000194
peahbfa97112016-03-10 21:09:04 -0800195 gain_controller->set_capture_level(capture_level_out);
niklase@google.com470e71d2011-07-07 08:21:25 +0000196
peahdf3efa82015-11-28 12:35:15 -0800197 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800198 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000199 }
peahbfa97112016-03-10 21:09:04 -0800200 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000201 }
202 }
203
peahdf3efa82015-11-28 12:35:15 -0800204 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000205}
206
peahb8fbb542016-03-15 02:28:08 -0700207int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio,
208 bool stream_has_echo) {
peahbfa97112016-03-10 21:09:04 -0800209 if (!enabled_) {
peahdf3efa82015-11-28 12:35:15 -0800210 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000211 }
212
213 if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) {
peahdf3efa82015-11-28 12:35:15 -0800214 return AudioProcessing::kStreamParameterNotSetError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000215 }
216
peahb8fbb542016-03-15 02:28:08 -0700217 RTC_DCHECK(num_proc_channels_);
Per Åhgren928146f2019-08-20 09:19:21 +0200218 RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength,
219 audio->num_frames_per_band());
peahb8fbb542016-03-15 02:28:08 -0700220 RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000221
222 stream_is_saturated_ = false;
peahbfa97112016-03-10 21:09:04 -0800223 int capture_channel = 0;
224 for (auto& gain_controller : gain_controllers_) {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000225 int32_t capture_level_out = 0;
226 uint8_t saturation_warning = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000227
Per Åhgren928146f2019-08-20 09:19:21 +0200228 int16_t split_band_data[AudioBuffer::kMaxNumBands]
229 [AudioBuffer::kMaxSplitFrameLength];
230 int16_t* split_bands[AudioBuffer::kMaxNumBands] = {
231 split_band_data[0], split_band_data[1], split_band_data[2]};
Per Åhgrend47941e2019-08-22 11:51:13 +0200232 audio->ExportSplitChannelData(capture_channel, split_bands);
Per Åhgren928146f2019-08-20 09:19:21 +0200233
peahdf3efa82015-11-28 12:35:15 -0800234 // The call to stream_has_echo() is ok from a deadlock perspective
235 // as the capture lock is allready held.
niklase@google.com470e71d2011-07-07 08:21:25 +0000236 int err = WebRtcAgc_Process(
Per Åhgren928146f2019-08-20 09:19:21 +0200237 gain_controller->state(), split_bands, audio->num_bands(),
238 audio->num_frames_per_band(), split_bands,
peahbfa97112016-03-10 21:09:04 -0800239 gain_controller->get_capture_level(), &capture_level_out,
peahb8fbb542016-03-15 02:28:08 -0700240 stream_has_echo, &saturation_warning);
niklase@google.com470e71d2011-07-07 08:21:25 +0000241
Per Åhgrend47941e2019-08-22 11:51:13 +0200242 audio->ImportSplitChannelData(capture_channel, split_bands);
Per Åhgren928146f2019-08-20 09:19:21 +0200243
peahdf3efa82015-11-28 12:35:15 -0800244 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800245 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000246 }
247
peahbfa97112016-03-10 21:09:04 -0800248 gain_controller->set_capture_level(capture_level_out);
niklase@google.com470e71d2011-07-07 08:21:25 +0000249 if (saturation_warning == 1) {
250 stream_is_saturated_ = true;
251 }
peahbfa97112016-03-10 21:09:04 -0800252
253 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000254 }
255
peahb8fbb542016-03-15 02:28:08 -0700256 RTC_DCHECK_LT(0ul, *num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000257 if (mode_ == kAdaptiveAnalog) {
258 // Take the analog level to be the average across the handles.
259 analog_capture_level_ = 0;
peahbfa97112016-03-10 21:09:04 -0800260 for (auto& gain_controller : gain_controllers_) {
261 analog_capture_level_ += gain_controller->get_capture_level();
niklase@google.com470e71d2011-07-07 08:21:25 +0000262 }
263
peahb8fbb542016-03-15 02:28:08 -0700264 analog_capture_level_ /= (*num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000265 }
266
267 was_analog_level_set_ = false;
peahdf3efa82015-11-28 12:35:15 -0800268 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000269}
270
aluebs11d4a422016-04-28 14:58:32 -0700271int GainControlImpl::compression_gain_db() const {
aluebs11d4a422016-04-28 14:58:32 -0700272 return compression_gain_db_;
273}
274
niklase@google.com470e71d2011-07-07 08:21:25 +0000275// TODO(ajm): ensure this is called under kAdaptiveAnalog.
276int GainControlImpl::set_stream_analog_level(int level) {
peah135259a2016-10-28 03:12:11 -0700277 data_dumper_->DumpRaw("gain_control_set_stream_analog_level", 1, &level);
peahdf3efa82015-11-28 12:35:15 -0800278
niklase@google.com470e71d2011-07-07 08:21:25 +0000279 was_analog_level_set_ = true;
280 if (level < minimum_capture_level_ || level > maximum_capture_level_) {
peahdf3efa82015-11-28 12:35:15 -0800281 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000282 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000283 analog_capture_level_ = level;
284
peahdf3efa82015-11-28 12:35:15 -0800285 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000286}
287
Sam Zackrissonf0d1c032019-03-27 13:28:08 +0100288int GainControlImpl::stream_analog_level() const {
peah135259a2016-10-28 03:12:11 -0700289 data_dumper_->DumpRaw("gain_control_stream_analog_level", 1,
290 &analog_capture_level_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000291 // TODO(ajm): enable this assertion?
Yves Gerey665174f2018-06-19 15:03:05 +0200292 // RTC_DCHECK_EQ(kAdaptiveAnalog, mode_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000293
294 return analog_capture_level_;
295}
296
297int GainControlImpl::Enable(bool enable) {
peahbfa97112016-03-10 21:09:04 -0800298 if (enable && !enabled_) {
299 enabled_ = enable; // Must be set before Initialize() is called.
peahb8fbb542016-03-15 02:28:08 -0700300
301 RTC_DCHECK(num_proc_channels_);
302 RTC_DCHECK(sample_rate_hz_);
303 Initialize(*num_proc_channels_, *sample_rate_hz_);
peahbfa97112016-03-10 21:09:04 -0800304 } else {
305 enabled_ = enable;
306 }
307 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000308}
309
310bool GainControlImpl::is_enabled() const {
peahbfa97112016-03-10 21:09:04 -0800311 return enabled_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000312}
313
314int GainControlImpl::set_mode(Mode mode) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000315 if (MapSetting(mode) == -1) {
peahdf3efa82015-11-28 12:35:15 -0800316 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000317 }
318
319 mode_ = mode;
peahb8fbb542016-03-15 02:28:08 -0700320 RTC_DCHECK(num_proc_channels_);
321 RTC_DCHECK(sample_rate_hz_);
322 Initialize(*num_proc_channels_, *sample_rate_hz_);
peahbfa97112016-03-10 21:09:04 -0800323 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000324}
325
326GainControl::Mode GainControlImpl::mode() const {
327 return mode_;
328}
329
Yves Gerey665174f2018-06-19 15:03:05 +0200330int GainControlImpl::set_analog_level_limits(int minimum, int maximum) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000331 if (minimum < 0) {
peahdf3efa82015-11-28 12:35:15 -0800332 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000333 }
334
335 if (maximum > 65535) {
peahdf3efa82015-11-28 12:35:15 -0800336 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000337 }
338
339 if (maximum < minimum) {
peahdf3efa82015-11-28 12:35:15 -0800340 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000341 }
342
peah7c931ad2016-03-24 12:52:02 -0700343 size_t num_proc_channels_local = 0u;
344 int sample_rate_hz_local = 0;
345 {
peah7c931ad2016-03-24 12:52:02 -0700346 minimum_capture_level_ = minimum;
347 maximum_capture_level_ = maximum;
348
349 RTC_DCHECK(num_proc_channels_);
350 RTC_DCHECK(sample_rate_hz_);
351 num_proc_channels_local = *num_proc_channels_;
352 sample_rate_hz_local = *sample_rate_hz_;
353 }
354 Initialize(num_proc_channels_local, sample_rate_hz_local);
peahbfa97112016-03-10 21:09:04 -0800355 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000356}
357
358int GainControlImpl::analog_level_minimum() const {
359 return minimum_capture_level_;
360}
361
362int GainControlImpl::analog_level_maximum() const {
363 return maximum_capture_level_;
364}
365
366bool GainControlImpl::stream_is_saturated() const {
367 return stream_is_saturated_;
368}
369
370int GainControlImpl::set_target_level_dbfs(int level) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000371 if (level > 31 || level < 0) {
peahdf3efa82015-11-28 12:35:15 -0800372 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000373 }
Sam Zackrisson421c8592019-02-11 13:39:46 +0100374 target_level_dbfs_ = level;
niklase@google.com470e71d2011-07-07 08:21:25 +0000375 return Configure();
376}
377
378int GainControlImpl::target_level_dbfs() const {
379 return target_level_dbfs_;
380}
381
382int GainControlImpl::set_compression_gain_db(int gain) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000383 if (gain < 0 || gain > 90) {
Per Åhgren3daedb62019-11-22 12:11:40 +0100384 RTC_LOG(LS_ERROR) << "set_compression_gain_db(" << gain << ") failed.";
peahdf3efa82015-11-28 12:35:15 -0800385 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000386 }
Sam Zackrisson421c8592019-02-11 13:39:46 +0100387 compression_gain_db_ = gain;
niklase@google.com470e71d2011-07-07 08:21:25 +0000388 return Configure();
389}
390
niklase@google.com470e71d2011-07-07 08:21:25 +0000391int GainControlImpl::enable_limiter(bool enable) {
Sam Zackrisson421c8592019-02-11 13:39:46 +0100392 limiter_enabled_ = enable;
niklase@google.com470e71d2011-07-07 08:21:25 +0000393 return Configure();
394}
395
396bool GainControlImpl::is_limiter_enabled() const {
397 return limiter_enabled_;
398}
399
peahb8fbb542016-03-15 02:28:08 -0700400void GainControlImpl::Initialize(size_t num_proc_channels, int sample_rate_hz) {
peah135259a2016-10-28 03:12:11 -0700401 data_dumper_->InitiateNewSetOfRecordings();
peahb8fbb542016-03-15 02:28:08 -0700402
Oskar Sundbomaa8b67d2017-11-17 14:34:48 +0100403 num_proc_channels_ = num_proc_channels;
404 sample_rate_hz_ = sample_rate_hz;
peahb8fbb542016-03-15 02:28:08 -0700405
peahbfa97112016-03-10 21:09:04 -0800406 if (!enabled_) {
407 return;
niklase@google.com470e71d2011-07-07 08:21:25 +0000408 }
409
peahb8fbb542016-03-15 02:28:08 -0700410 gain_controllers_.resize(*num_proc_channels_);
peahbfa97112016-03-10 21:09:04 -0800411 for (auto& gain_controller : gain_controllers_) {
412 if (!gain_controller) {
413 gain_controller.reset(new GainController());
414 }
415 gain_controller->Initialize(minimum_capture_level_, maximum_capture_level_,
peahb8fbb542016-03-15 02:28:08 -0700416 mode_, *sample_rate_hz_, analog_capture_level_);
peahbfa97112016-03-10 21:09:04 -0800417 }
418
419 Configure();
peah4d291f72015-11-16 23:52:25 -0800420}
421
peahbfa97112016-03-10 21:09:04 -0800422int GainControlImpl::Configure() {
pbos@webrtc.orge468bc92014-12-18 09:11:33 +0000423 WebRtcAgcConfig config;
niklase@google.com470e71d2011-07-07 08:21:25 +0000424 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we
425 // change the interface.
Yves Gerey665174f2018-06-19 15:03:05 +0200426 // RTC_DCHECK_LE(target_level_dbfs_, 0);
427 // config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_);
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000428 config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_);
Yves Gerey665174f2018-06-19 15:03:05 +0200429 config.compressionGaindB = static_cast<int16_t>(compression_gain_db_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000430 config.limiterEnable = limiter_enabled_;
431
peahbfa97112016-03-10 21:09:04 -0800432 int error = AudioProcessing::kNoError;
433 for (auto& gain_controller : gain_controllers_) {
434 const int handle_error =
435 WebRtcAgc_set_config(gain_controller->state(), config);
436 if (handle_error != AudioProcessing::kNoError) {
437 error = handle_error;
438 }
439 }
440 return error;
niklase@google.com470e71d2011-07-07 08:21:25 +0000441}
niklase@google.com470e71d2011-07-07 08:21:25 +0000442} // namespace webrtc