blob: edc49d14011e1c36cbac3adb0ef9944a99c177cb [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"
Per Åhgren3daedb62019-11-22 12:11:40 +010021#include "rtc_base/logging.h"
Per Åhgren77dc1992019-11-23 00:14:31 +010022#include "system_wrappers/include/field_trial.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 }
Artem Titovd3251962021-11-15 16:57:07 +010038 RTC_DCHECK_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
Alessio Bazzica78b466a2022-11-18 20:58:02 +010042// Applies the sub-frame `gains` to all the bands in `out` and clamps the output
43// in the signed 16 bit range.
Per Åhgren77dc1992019-11-23 00:14:31 +010044void ApplyDigitalGain(const int32_t gains[11],
45 size_t num_bands,
46 float* const* out) {
47 constexpr float kScaling = 1.f / 65536.f;
48 constexpr int kNumSubSections = 16;
49 constexpr float kOneByNumSubSections = 1.f / kNumSubSections;
50
51 float gains_scaled[11];
52 for (int k = 0; k < 11; ++k) {
53 gains_scaled[k] = gains[k] * kScaling;
54 }
55
56 for (size_t b = 0; b < num_bands; ++b) {
57 float* out_band = out[b];
58 for (int k = 0, sample = 0; k < 10; ++k) {
59 const float delta =
60 (gains_scaled[k + 1] - gains_scaled[k]) * kOneByNumSubSections;
61 float gain = gains_scaled[k];
62 for (int n = 0; n < kNumSubSections; ++n, ++sample) {
63 RTC_DCHECK_EQ(k * kNumSubSections + n, sample);
64 out_band[sample] *= gain;
65 out_band[sample] =
66 std::min(32767.f, std::max(-32768.f, out_band[sample]));
67 gain += delta;
68 }
69 }
70 }
71}
72
peah2446e5a2015-11-18 06:11:13 -080073} // namespace
peah4d291f72015-11-16 23:52:25 -080074
Per Åhgren77dc1992019-11-23 00:14:31 +010075struct GainControlImpl::MonoAgcState {
76 MonoAgcState() {
77 state = WebRtcAgc_Create();
78 RTC_CHECK(state);
peahbfa97112016-03-10 21:09:04 -080079 }
80
Per Åhgren77dc1992019-11-23 00:14:31 +010081 ~MonoAgcState() {
82 RTC_DCHECK(state);
83 WebRtcAgc_Free(state);
peahbfa97112016-03-10 21:09:04 -080084 }
85
Per Åhgren77dc1992019-11-23 00:14:31 +010086 MonoAgcState(const MonoAgcState&) = delete;
87 MonoAgcState& operator=(const MonoAgcState&) = delete;
88 int32_t gains[11];
89 Handle* state;
peahbfa97112016-03-10 21:09:04 -080090};
91
peah135259a2016-10-28 03:12:11 -070092int GainControlImpl::instance_counter_ = 0;
93
Sam Zackrissonf0d1c032019-03-27 13:28:08 +010094GainControlImpl::GainControlImpl()
95 : data_dumper_(new ApmDataDumper(instance_counter_)),
peah4d291f72015-11-16 23:52:25 -080096 mode_(kAdaptiveAnalog),
97 minimum_capture_level_(0),
98 maximum_capture_level_(255),
99 limiter_enabled_(true),
100 target_level_dbfs_(3),
101 compression_gain_db_(9),
102 analog_capture_level_(0),
103 was_analog_level_set_(false),
Sam Zackrissonf0d1c032019-03-27 13:28:08 +0100104 stream_is_saturated_(false) {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000105
Per Åhgren77dc1992019-11-23 00:14:31 +0100106GainControlImpl::~GainControlImpl() = default;
niklase@google.com470e71d2011-07-07 08:21:25 +0000107
peah701d6282016-10-25 05:42:20 -0700108void GainControlImpl::ProcessRenderAudio(
109 rtc::ArrayView<const int16_t> packed_render_audio) {
Per Åhgren77dc1992019-11-23 00:14:31 +0100110 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
111 WebRtcAgc_AddFarend(mono_agcs_[ch]->state, packed_render_audio.data(),
peah701d6282016-10-25 05:42:20 -0700112 packed_render_audio.size());
peah4d291f72015-11-16 23:52:25 -0800113 }
114}
115
peah701d6282016-10-25 05:42:20 -0700116void GainControlImpl::PackRenderAudioBuffer(
Per Åhgrene35b32c2019-11-22 18:22:04 +0100117 const AudioBuffer& audio,
peah701d6282016-10-25 05:42:20 -0700118 std::vector<int16_t>* packed_buffer) {
Per Åhgrene35b32c2019-11-22 18:22:04 +0100119 RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength, audio.num_frames_per_band());
Per Åhgren77dc1992019-11-23 00:14:31 +0100120 std::array<int16_t, AudioBuffer::kMaxSplitFrameLength>
121 mixed_16_kHz_render_data;
122 rtc::ArrayView<const int16_t> mixed_16_kHz_render(
123 mixed_16_kHz_render_data.data(), audio.num_frames_per_band());
Per Åhgrene35b32c2019-11-22 18:22:04 +0100124 if (audio.num_channels() == 1) {
125 FloatS16ToS16(audio.split_bands_const(0)[kBand0To8kHz],
Per Åhgren77dc1992019-11-23 00:14:31 +0100126 audio.num_frames_per_band(), mixed_16_kHz_render_data.data());
Per Åhgrena1351272019-08-15 12:15:46 +0200127 } else {
Per Åhgrene35b32c2019-11-22 18:22:04 +0100128 const int num_channels = static_cast<int>(audio.num_channels());
129 for (size_t i = 0; i < audio.num_frames_per_band(); ++i) {
Per Åhgren77dc1992019-11-23 00:14:31 +0100130 int32_t sum = 0;
131 for (int ch = 0; ch < num_channels; ++ch) {
132 sum += FloatS16ToS16(audio.split_channels_const(kBand0To8kHz)[ch][i]);
Per Åhgrena1351272019-08-15 12:15:46 +0200133 }
Per Åhgren77dc1992019-11-23 00:14:31 +0100134 mixed_16_kHz_render_data[i] = sum / num_channels;
Per Åhgrena1351272019-08-15 12:15:46 +0200135 }
Per Åhgrena1351272019-08-15 12:15:46 +0200136 }
137
peah701d6282016-10-25 05:42:20 -0700138 packed_buffer->clear();
Per Åhgren77dc1992019-11-23 00:14:31 +0100139 packed_buffer->insert(
140 packed_buffer->end(), mixed_16_kHz_render.data(),
141 (mixed_16_kHz_render.data() + audio.num_frames_per_band()));
peah701d6282016-10-25 05:42:20 -0700142}
143
Per Åhgrene35b32c2019-11-22 18:22:04 +0100144int GainControlImpl::AnalyzeCaptureAudio(const AudioBuffer& audio) {
peahb8fbb542016-03-15 02:28:08 -0700145 RTC_DCHECK(num_proc_channels_);
Per Åhgrene35b32c2019-11-22 18:22:04 +0100146 RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength, audio.num_frames_per_band());
147 RTC_DCHECK_EQ(audio.num_channels(), *num_proc_channels_);
Per Åhgren77dc1992019-11-23 00:14:31 +0100148 RTC_DCHECK_LE(*num_proc_channels_, mono_agcs_.size());
niklase@google.com470e71d2011-07-07 08:21:25 +0000149
Per Åhgren928146f2019-08-20 09:19:21 +0200150 int16_t split_band_data[AudioBuffer::kMaxNumBands]
151 [AudioBuffer::kMaxSplitFrameLength];
152 int16_t* split_bands[AudioBuffer::kMaxNumBands] = {
153 split_band_data[0], split_band_data[1], split_band_data[2]};
154
niklase@google.com470e71d2011-07-07 08:21:25 +0000155 if (mode_ == kAdaptiveAnalog) {
Per Åhgren77dc1992019-11-23 00:14:31 +0100156 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
157 capture_levels_[ch] = analog_capture_level_;
Per Åhgren928146f2019-08-20 09:19:21 +0200158
Per Åhgren77dc1992019-11-23 00:14:31 +0100159 audio.ExportSplitChannelData(ch, split_bands);
Per Åhgren928146f2019-08-20 09:19:21 +0200160
161 int err =
Per Åhgren77dc1992019-11-23 00:14:31 +0100162 WebRtcAgc_AddMic(mono_agcs_[ch]->state, split_bands,
Per Åhgrene35b32c2019-11-22 18:22:04 +0100163 audio.num_bands(), audio.num_frames_per_band());
niklase@google.com470e71d2011-07-07 08:21:25 +0000164
peahdf3efa82015-11-28 12:35:15 -0800165 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800166 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000167 }
168 }
169 } else if (mode_ == kAdaptiveDigital) {
Per Åhgren77dc1992019-11-23 00:14:31 +0100170 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000171 int32_t capture_level_out = 0;
Per Åhgren928146f2019-08-20 09:19:21 +0200172
Per Åhgren77dc1992019-11-23 00:14:31 +0100173 audio.ExportSplitChannelData(ch, split_bands);
Per Åhgren928146f2019-08-20 09:19:21 +0200174
175 int err =
Per Åhgren77dc1992019-11-23 00:14:31 +0100176 WebRtcAgc_VirtualMic(mono_agcs_[ch]->state, split_bands,
Per Åhgrene35b32c2019-11-22 18:22:04 +0100177 audio.num_bands(), audio.num_frames_per_band(),
Per Åhgren928146f2019-08-20 09:19:21 +0200178 analog_capture_level_, &capture_level_out);
179
Per Åhgren77dc1992019-11-23 00:14:31 +0100180 capture_levels_[ch] = capture_level_out;
niklase@google.com470e71d2011-07-07 08:21:25 +0000181
peahdf3efa82015-11-28 12:35:15 -0800182 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800183 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000184 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000185 }
186 }
187
peahdf3efa82015-11-28 12:35:15 -0800188 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000189}
190
peahb8fbb542016-03-15 02:28:08 -0700191int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio,
192 bool stream_has_echo) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000193 if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) {
peahdf3efa82015-11-28 12:35:15 -0800194 return AudioProcessing::kStreamParameterNotSetError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000195 }
196
peahb8fbb542016-03-15 02:28:08 -0700197 RTC_DCHECK(num_proc_channels_);
Per Åhgren928146f2019-08-20 09:19:21 +0200198 RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength,
199 audio->num_frames_per_band());
peahb8fbb542016-03-15 02:28:08 -0700200 RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000201
202 stream_is_saturated_ = false;
Per Åhgren77dc1992019-11-23 00:14:31 +0100203 bool error_reported = false;
204 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
Per Åhgren928146f2019-08-20 09:19:21 +0200205 int16_t split_band_data[AudioBuffer::kMaxNumBands]
206 [AudioBuffer::kMaxSplitFrameLength];
207 int16_t* split_bands[AudioBuffer::kMaxNumBands] = {
208 split_band_data[0], split_band_data[1], split_band_data[2]};
Per Åhgren77dc1992019-11-23 00:14:31 +0100209 audio->ExportSplitChannelData(ch, split_bands);
Per Åhgren928146f2019-08-20 09:19:21 +0200210
peahdf3efa82015-11-28 12:35:15 -0800211 // The call to stream_has_echo() is ok from a deadlock perspective
212 // as the capture lock is allready held.
Per Åhgren77dc1992019-11-23 00:14:31 +0100213 int32_t new_capture_level = 0;
214 uint8_t saturation_warning = 0;
215 int err_analyze = WebRtcAgc_Analyze(
216 mono_agcs_[ch]->state, split_bands, audio->num_bands(),
217 audio->num_frames_per_band(), capture_levels_[ch], &new_capture_level,
218 stream_has_echo, &saturation_warning, mono_agcs_[ch]->gains);
219 capture_levels_[ch] = new_capture_level;
niklase@google.com470e71d2011-07-07 08:21:25 +0000220
Per Åhgren77dc1992019-11-23 00:14:31 +0100221 error_reported = error_reported || err_analyze != AudioProcessing::kNoError;
Per Åhgren928146f2019-08-20 09:19:21 +0200222
Per Åhgren77dc1992019-11-23 00:14:31 +0100223 stream_is_saturated_ = stream_is_saturated_ || saturation_warning == 1;
224 }
225
226 // Choose the minimun gain for application
227 size_t index_to_apply = 0;
228 for (size_t ch = 1; ch < mono_agcs_.size(); ++ch) {
229 if (mono_agcs_[index_to_apply]->gains[10] < mono_agcs_[ch]->gains[10]) {
230 index_to_apply = ch;
niklase@google.com470e71d2011-07-07 08:21:25 +0000231 }
Per Åhgren77dc1992019-11-23 00:14:31 +0100232 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000233
Alessio Bazzica78b466a2022-11-18 20:58:02 +0100234 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
235 ApplyDigitalGain(mono_agcs_[index_to_apply]->gains, audio->num_bands(),
236 audio->split_bands(ch));
niklase@google.com470e71d2011-07-07 08:21:25 +0000237 }
238
peahb8fbb542016-03-15 02:28:08 -0700239 RTC_DCHECK_LT(0ul, *num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000240 if (mode_ == kAdaptiveAnalog) {
Per Åhgren77dc1992019-11-23 00:14:31 +0100241 // Take the analog level to be the minimum accross all channels.
242 analog_capture_level_ = capture_levels_[0];
243 for (size_t ch = 1; ch < mono_agcs_.size(); ++ch) {
244 analog_capture_level_ =
245 std::min(analog_capture_level_, capture_levels_[ch]);
niklase@google.com470e71d2011-07-07 08:21:25 +0000246 }
Per Åhgren77dc1992019-11-23 00:14:31 +0100247 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000248
Per Åhgren77dc1992019-11-23 00:14:31 +0100249 if (error_reported) {
250 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000251 }
252
253 was_analog_level_set_ = false;
Per Åhgren77dc1992019-11-23 00:14:31 +0100254
peahdf3efa82015-11-28 12:35:15 -0800255 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000256}
257
aluebs11d4a422016-04-28 14:58:32 -0700258
niklase@google.com470e71d2011-07-07 08:21:25 +0000259// TODO(ajm): ensure this is called under kAdaptiveAnalog.
260int GainControlImpl::set_stream_analog_level(int level) {
peah135259a2016-10-28 03:12:11 -0700261 data_dumper_->DumpRaw("gain_control_set_stream_analog_level", 1, &level);
peahdf3efa82015-11-28 12:35:15 -0800262
niklase@google.com470e71d2011-07-07 08:21:25 +0000263 was_analog_level_set_ = true;
264 if (level < minimum_capture_level_ || level > maximum_capture_level_) {
peahdf3efa82015-11-28 12:35:15 -0800265 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000266 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000267 analog_capture_level_ = level;
268
peahdf3efa82015-11-28 12:35:15 -0800269 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000270}
271
Sam Zackrissonf0d1c032019-03-27 13:28:08 +0100272int GainControlImpl::stream_analog_level() const {
peah135259a2016-10-28 03:12:11 -0700273 data_dumper_->DumpRaw("gain_control_stream_analog_level", 1,
274 &analog_capture_level_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000275 return analog_capture_level_;
276}
277
niklase@google.com470e71d2011-07-07 08:21:25 +0000278int GainControlImpl::set_mode(Mode mode) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000279 if (MapSetting(mode) == -1) {
peahdf3efa82015-11-28 12:35:15 -0800280 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000281 }
282
283 mode_ = mode;
peahb8fbb542016-03-15 02:28:08 -0700284 RTC_DCHECK(num_proc_channels_);
285 RTC_DCHECK(sample_rate_hz_);
286 Initialize(*num_proc_channels_, *sample_rate_hz_);
peahbfa97112016-03-10 21:09:04 -0800287 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000288}
289
niklase@google.com470e71d2011-07-07 08:21:25 +0000290
Yves Gerey665174f2018-06-19 15:03:05 +0200291int GainControlImpl::set_analog_level_limits(int minimum, int maximum) {
Per Åhgren77dc1992019-11-23 00:14:31 +0100292 if (minimum < 0 || maximum > 65535 || maximum < minimum) {
peahdf3efa82015-11-28 12:35:15 -0800293 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000294 }
295
Per Åhgren77dc1992019-11-23 00:14:31 +0100296 minimum_capture_level_ = minimum;
297 maximum_capture_level_ = maximum;
niklase@google.com470e71d2011-07-07 08:21:25 +0000298
Per Åhgren77dc1992019-11-23 00:14:31 +0100299 RTC_DCHECK(num_proc_channels_);
300 RTC_DCHECK(sample_rate_hz_);
301 Initialize(*num_proc_channels_, *sample_rate_hz_);
peahbfa97112016-03-10 21:09:04 -0800302 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000303}
304
niklase@google.com470e71d2011-07-07 08:21:25 +0000305
306int GainControlImpl::set_target_level_dbfs(int level) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000307 if (level > 31 || level < 0) {
peahdf3efa82015-11-28 12:35:15 -0800308 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000309 }
Sam Zackrisson421c8592019-02-11 13:39:46 +0100310 target_level_dbfs_ = level;
niklase@google.com470e71d2011-07-07 08:21:25 +0000311 return Configure();
312}
313
niklase@google.com470e71d2011-07-07 08:21:25 +0000314int GainControlImpl::set_compression_gain_db(int gain) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000315 if (gain < 0 || gain > 90) {
Per Åhgren3daedb62019-11-22 12:11:40 +0100316 RTC_LOG(LS_ERROR) << "set_compression_gain_db(" << gain << ") failed.";
peahdf3efa82015-11-28 12:35:15 -0800317 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000318 }
Sam Zackrisson421c8592019-02-11 13:39:46 +0100319 compression_gain_db_ = gain;
niklase@google.com470e71d2011-07-07 08:21:25 +0000320 return Configure();
321}
322
niklase@google.com470e71d2011-07-07 08:21:25 +0000323int GainControlImpl::enable_limiter(bool enable) {
Sam Zackrisson421c8592019-02-11 13:39:46 +0100324 limiter_enabled_ = enable;
niklase@google.com470e71d2011-07-07 08:21:25 +0000325 return Configure();
326}
327
peahb8fbb542016-03-15 02:28:08 -0700328void GainControlImpl::Initialize(size_t num_proc_channels, int sample_rate_hz) {
peah135259a2016-10-28 03:12:11 -0700329 data_dumper_->InitiateNewSetOfRecordings();
peahb8fbb542016-03-15 02:28:08 -0700330
Per Åhgren27bd76b2019-11-26 09:23:45 +0100331 RTC_DCHECK(sample_rate_hz == 16000 || sample_rate_hz == 32000 ||
332 sample_rate_hz == 48000);
333
Oskar Sundbomaa8b67d2017-11-17 14:34:48 +0100334 num_proc_channels_ = num_proc_channels;
335 sample_rate_hz_ = sample_rate_hz;
peahb8fbb542016-03-15 02:28:08 -0700336
Per Åhgren77dc1992019-11-23 00:14:31 +0100337 mono_agcs_.resize(*num_proc_channels_);
338 capture_levels_.resize(*num_proc_channels_);
339 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
340 if (!mono_agcs_[ch]) {
341 mono_agcs_[ch].reset(new MonoAgcState());
peahbfa97112016-03-10 21:09:04 -0800342 }
Per Åhgren77dc1992019-11-23 00:14:31 +0100343
344 int error = WebRtcAgc_Init(mono_agcs_[ch]->state, minimum_capture_level_,
345 maximum_capture_level_, MapSetting(mode_),
346 *sample_rate_hz_);
347 RTC_DCHECK_EQ(error, 0);
348 capture_levels_[ch] = analog_capture_level_;
peahbfa97112016-03-10 21:09:04 -0800349 }
350
351 Configure();
peah4d291f72015-11-16 23:52:25 -0800352}
353
peahbfa97112016-03-10 21:09:04 -0800354int GainControlImpl::Configure() {
pbos@webrtc.orge468bc92014-12-18 09:11:33 +0000355 WebRtcAgcConfig config;
niklase@google.com470e71d2011-07-07 08:21:25 +0000356 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we
357 // change the interface.
Yves Gerey665174f2018-06-19 15:03:05 +0200358 // RTC_DCHECK_LE(target_level_dbfs_, 0);
359 // config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_);
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000360 config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_);
Yves Gerey665174f2018-06-19 15:03:05 +0200361 config.compressionGaindB = static_cast<int16_t>(compression_gain_db_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000362 config.limiterEnable = limiter_enabled_;
363
peahbfa97112016-03-10 21:09:04 -0800364 int error = AudioProcessing::kNoError;
Per Åhgren77dc1992019-11-23 00:14:31 +0100365 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
366 int error_ch = WebRtcAgc_set_config(mono_agcs_[ch]->state, config);
367 if (error_ch != AudioProcessing::kNoError) {
368 error = error_ch;
peahbfa97112016-03-10 21:09:04 -0800369 }
370 }
371 return error;
niklase@google.com470e71d2011-07-07 08:21:25 +0000372}
niklase@google.com470e71d2011-07-07 08:21:25 +0000373} // namespace webrtc