blob: b5454c05ed4545b486bd0579991b6cbcd4c95505 [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 }
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
Per Åhgren77dc1992019-11-23 00:14:31 +010042// Checks whether the legacy digital gain application should be used.
43bool UseLegacyDigitalGainApplier() {
44 return field_trial::IsEnabled("WebRTC-UseLegacyDigitalGainApplier");
45}
46
47// Floating point variant of WebRtcAgc_Process.
48void ApplyDigitalGain(const int32_t gains[11],
49 size_t num_bands,
50 float* const* out) {
51 constexpr float kScaling = 1.f / 65536.f;
52 constexpr int kNumSubSections = 16;
53 constexpr float kOneByNumSubSections = 1.f / kNumSubSections;
54
55 float gains_scaled[11];
56 for (int k = 0; k < 11; ++k) {
57 gains_scaled[k] = gains[k] * kScaling;
58 }
59
60 for (size_t b = 0; b < num_bands; ++b) {
61 float* out_band = out[b];
62 for (int k = 0, sample = 0; k < 10; ++k) {
63 const float delta =
64 (gains_scaled[k + 1] - gains_scaled[k]) * kOneByNumSubSections;
65 float gain = gains_scaled[k];
66 for (int n = 0; n < kNumSubSections; ++n, ++sample) {
67 RTC_DCHECK_EQ(k * kNumSubSections + n, sample);
68 out_band[sample] *= gain;
69 out_band[sample] =
70 std::min(32767.f, std::max(-32768.f, out_band[sample]));
71 gain += delta;
72 }
73 }
74 }
75}
76
peah2446e5a2015-11-18 06:11:13 -080077} // namespace
peah4d291f72015-11-16 23:52:25 -080078
Per Åhgren77dc1992019-11-23 00:14:31 +010079struct GainControlImpl::MonoAgcState {
80 MonoAgcState() {
81 state = WebRtcAgc_Create();
82 RTC_CHECK(state);
peahbfa97112016-03-10 21:09:04 -080083 }
84
Per Åhgren77dc1992019-11-23 00:14:31 +010085 ~MonoAgcState() {
86 RTC_DCHECK(state);
87 WebRtcAgc_Free(state);
peahbfa97112016-03-10 21:09:04 -080088 }
89
Per Åhgren77dc1992019-11-23 00:14:31 +010090 MonoAgcState(const MonoAgcState&) = delete;
91 MonoAgcState& operator=(const MonoAgcState&) = delete;
92 int32_t gains[11];
93 Handle* state;
peahbfa97112016-03-10 21:09:04 -080094};
95
peah135259a2016-10-28 03:12:11 -070096int GainControlImpl::instance_counter_ = 0;
97
Sam Zackrissonf0d1c032019-03-27 13:28:08 +010098GainControlImpl::GainControlImpl()
99 : data_dumper_(new ApmDataDumper(instance_counter_)),
Per Åhgren77dc1992019-11-23 00:14:31 +0100100 use_legacy_gain_applier_(UseLegacyDigitalGainApplier()),
peah4d291f72015-11-16 23:52:25 -0800101 mode_(kAdaptiveAnalog),
102 minimum_capture_level_(0),
103 maximum_capture_level_(255),
104 limiter_enabled_(true),
105 target_level_dbfs_(3),
106 compression_gain_db_(9),
107 analog_capture_level_(0),
108 was_analog_level_set_(false),
Sam Zackrissonf0d1c032019-03-27 13:28:08 +0100109 stream_is_saturated_(false) {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000110
Per Åhgren77dc1992019-11-23 00:14:31 +0100111GainControlImpl::~GainControlImpl() = default;
niklase@google.com470e71d2011-07-07 08:21:25 +0000112
peah701d6282016-10-25 05:42:20 -0700113void GainControlImpl::ProcessRenderAudio(
114 rtc::ArrayView<const int16_t> packed_render_audio) {
Per Åhgren77dc1992019-11-23 00:14:31 +0100115 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
116 WebRtcAgc_AddFarend(mono_agcs_[ch]->state, packed_render_audio.data(),
peah701d6282016-10-25 05:42:20 -0700117 packed_render_audio.size());
peah4d291f72015-11-16 23:52:25 -0800118 }
119}
120
peah701d6282016-10-25 05:42:20 -0700121void GainControlImpl::PackRenderAudioBuffer(
Per Åhgrene35b32c2019-11-22 18:22:04 +0100122 const AudioBuffer& audio,
peah701d6282016-10-25 05:42:20 -0700123 std::vector<int16_t>* packed_buffer) {
Per Åhgrene35b32c2019-11-22 18:22:04 +0100124 RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength, audio.num_frames_per_band());
Per Åhgren77dc1992019-11-23 00:14:31 +0100125 std::array<int16_t, AudioBuffer::kMaxSplitFrameLength>
126 mixed_16_kHz_render_data;
127 rtc::ArrayView<const int16_t> mixed_16_kHz_render(
128 mixed_16_kHz_render_data.data(), audio.num_frames_per_band());
Per Åhgrene35b32c2019-11-22 18:22:04 +0100129 if (audio.num_channels() == 1) {
130 FloatS16ToS16(audio.split_bands_const(0)[kBand0To8kHz],
Per Åhgren77dc1992019-11-23 00:14:31 +0100131 audio.num_frames_per_band(), mixed_16_kHz_render_data.data());
Per Åhgrena1351272019-08-15 12:15:46 +0200132 } else {
Per Åhgrene35b32c2019-11-22 18:22:04 +0100133 const int num_channels = static_cast<int>(audio.num_channels());
134 for (size_t i = 0; i < audio.num_frames_per_band(); ++i) {
Per Åhgren77dc1992019-11-23 00:14:31 +0100135 int32_t sum = 0;
136 for (int ch = 0; ch < num_channels; ++ch) {
137 sum += FloatS16ToS16(audio.split_channels_const(kBand0To8kHz)[ch][i]);
Per Åhgrena1351272019-08-15 12:15:46 +0200138 }
Per Åhgren77dc1992019-11-23 00:14:31 +0100139 mixed_16_kHz_render_data[i] = sum / num_channels;
Per Åhgrena1351272019-08-15 12:15:46 +0200140 }
Per Åhgrena1351272019-08-15 12:15:46 +0200141 }
142
peah701d6282016-10-25 05:42:20 -0700143 packed_buffer->clear();
Per Åhgren77dc1992019-11-23 00:14:31 +0100144 packed_buffer->insert(
145 packed_buffer->end(), mixed_16_kHz_render.data(),
146 (mixed_16_kHz_render.data() + audio.num_frames_per_band()));
peah701d6282016-10-25 05:42:20 -0700147}
148
Per Åhgrene35b32c2019-11-22 18:22:04 +0100149int GainControlImpl::AnalyzeCaptureAudio(const AudioBuffer& audio) {
peahb8fbb542016-03-15 02:28:08 -0700150 RTC_DCHECK(num_proc_channels_);
Per Åhgrene35b32c2019-11-22 18:22:04 +0100151 RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength, audio.num_frames_per_band());
152 RTC_DCHECK_EQ(audio.num_channels(), *num_proc_channels_);
Per Åhgren77dc1992019-11-23 00:14:31 +0100153 RTC_DCHECK_LE(*num_proc_channels_, mono_agcs_.size());
niklase@google.com470e71d2011-07-07 08:21:25 +0000154
Per Åhgren928146f2019-08-20 09:19:21 +0200155 int16_t split_band_data[AudioBuffer::kMaxNumBands]
156 [AudioBuffer::kMaxSplitFrameLength];
157 int16_t* split_bands[AudioBuffer::kMaxNumBands] = {
158 split_band_data[0], split_band_data[1], split_band_data[2]};
159
niklase@google.com470e71d2011-07-07 08:21:25 +0000160 if (mode_ == kAdaptiveAnalog) {
Per Åhgren77dc1992019-11-23 00:14:31 +0100161 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
162 capture_levels_[ch] = analog_capture_level_;
Per Åhgren928146f2019-08-20 09:19:21 +0200163
Per Åhgren77dc1992019-11-23 00:14:31 +0100164 audio.ExportSplitChannelData(ch, split_bands);
Per Åhgren928146f2019-08-20 09:19:21 +0200165
166 int err =
Per Åhgren77dc1992019-11-23 00:14:31 +0100167 WebRtcAgc_AddMic(mono_agcs_[ch]->state, split_bands,
Per Åhgrene35b32c2019-11-22 18:22:04 +0100168 audio.num_bands(), audio.num_frames_per_band());
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 }
173 }
174 } else if (mode_ == kAdaptiveDigital) {
Per Åhgren77dc1992019-11-23 00:14:31 +0100175 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000176 int32_t capture_level_out = 0;
Per Åhgren928146f2019-08-20 09:19:21 +0200177
Per Åhgren77dc1992019-11-23 00:14:31 +0100178 audio.ExportSplitChannelData(ch, split_bands);
Per Åhgren928146f2019-08-20 09:19:21 +0200179
180 int err =
Per Åhgren77dc1992019-11-23 00:14:31 +0100181 WebRtcAgc_VirtualMic(mono_agcs_[ch]->state, split_bands,
Per Åhgrene35b32c2019-11-22 18:22:04 +0100182 audio.num_bands(), audio.num_frames_per_band(),
Per Åhgren928146f2019-08-20 09:19:21 +0200183 analog_capture_level_, &capture_level_out);
184
Per Åhgren77dc1992019-11-23 00:14:31 +0100185 capture_levels_[ch] = capture_level_out;
niklase@google.com470e71d2011-07-07 08:21:25 +0000186
peahdf3efa82015-11-28 12:35:15 -0800187 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800188 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000189 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000190 }
191 }
192
peahdf3efa82015-11-28 12:35:15 -0800193 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000194}
195
peahb8fbb542016-03-15 02:28:08 -0700196int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio,
197 bool stream_has_echo) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000198 if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) {
peahdf3efa82015-11-28 12:35:15 -0800199 return AudioProcessing::kStreamParameterNotSetError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000200 }
201
peahb8fbb542016-03-15 02:28:08 -0700202 RTC_DCHECK(num_proc_channels_);
Per Åhgren928146f2019-08-20 09:19:21 +0200203 RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength,
204 audio->num_frames_per_band());
peahb8fbb542016-03-15 02:28:08 -0700205 RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000206
207 stream_is_saturated_ = false;
Per Åhgren77dc1992019-11-23 00:14:31 +0100208 bool error_reported = false;
209 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
Per Åhgren928146f2019-08-20 09:19:21 +0200210 int16_t split_band_data[AudioBuffer::kMaxNumBands]
211 [AudioBuffer::kMaxSplitFrameLength];
212 int16_t* split_bands[AudioBuffer::kMaxNumBands] = {
213 split_band_data[0], split_band_data[1], split_band_data[2]};
Per Åhgren77dc1992019-11-23 00:14:31 +0100214 audio->ExportSplitChannelData(ch, split_bands);
Per Åhgren928146f2019-08-20 09:19:21 +0200215
peahdf3efa82015-11-28 12:35:15 -0800216 // The call to stream_has_echo() is ok from a deadlock perspective
217 // as the capture lock is allready held.
Per Åhgren77dc1992019-11-23 00:14:31 +0100218 int32_t new_capture_level = 0;
219 uint8_t saturation_warning = 0;
220 int err_analyze = WebRtcAgc_Analyze(
221 mono_agcs_[ch]->state, split_bands, audio->num_bands(),
222 audio->num_frames_per_band(), capture_levels_[ch], &new_capture_level,
223 stream_has_echo, &saturation_warning, mono_agcs_[ch]->gains);
224 capture_levels_[ch] = new_capture_level;
niklase@google.com470e71d2011-07-07 08:21:25 +0000225
Per Åhgren77dc1992019-11-23 00:14:31 +0100226 error_reported = error_reported || err_analyze != AudioProcessing::kNoError;
Per Åhgren928146f2019-08-20 09:19:21 +0200227
Per Åhgren77dc1992019-11-23 00:14:31 +0100228 stream_is_saturated_ = stream_is_saturated_ || saturation_warning == 1;
229 }
230
231 // Choose the minimun gain for application
232 size_t index_to_apply = 0;
233 for (size_t ch = 1; ch < mono_agcs_.size(); ++ch) {
234 if (mono_agcs_[index_to_apply]->gains[10] < mono_agcs_[ch]->gains[10]) {
235 index_to_apply = ch;
niklase@google.com470e71d2011-07-07 08:21:25 +0000236 }
Per Åhgren77dc1992019-11-23 00:14:31 +0100237 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000238
Per Åhgren77dc1992019-11-23 00:14:31 +0100239 if (use_legacy_gain_applier_) {
240 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
241 int16_t split_band_data[AudioBuffer::kMaxNumBands]
242 [AudioBuffer::kMaxSplitFrameLength];
243 int16_t* split_bands[AudioBuffer::kMaxNumBands] = {
244 split_band_data[0], split_band_data[1], split_band_data[2]};
245 audio->ExportSplitChannelData(ch, split_bands);
246
247 int err_process = WebRtcAgc_Process(
248 mono_agcs_[ch]->state, mono_agcs_[index_to_apply]->gains, split_bands,
249 audio->num_bands(), split_bands);
250 RTC_DCHECK_EQ(err_process, 0);
251
252 audio->ImportSplitChannelData(ch, split_bands);
niklase@google.com470e71d2011-07-07 08:21:25 +0000253 }
Per Åhgren77dc1992019-11-23 00:14:31 +0100254 } else {
255 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
256 ApplyDigitalGain(mono_agcs_[index_to_apply]->gains, audio->num_bands(),
257 audio->split_bands(ch));
258 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000259 }
260
peahb8fbb542016-03-15 02:28:08 -0700261 RTC_DCHECK_LT(0ul, *num_proc_channels_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000262 if (mode_ == kAdaptiveAnalog) {
Per Åhgren77dc1992019-11-23 00:14:31 +0100263 // Take the analog level to be the minimum accross all channels.
264 analog_capture_level_ = capture_levels_[0];
265 for (size_t ch = 1; ch < mono_agcs_.size(); ++ch) {
266 analog_capture_level_ =
267 std::min(analog_capture_level_, capture_levels_[ch]);
niklase@google.com470e71d2011-07-07 08:21:25 +0000268 }
Per Åhgren77dc1992019-11-23 00:14:31 +0100269 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000270
Per Åhgren77dc1992019-11-23 00:14:31 +0100271 if (error_reported) {
272 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000273 }
274
275 was_analog_level_set_ = false;
Per Åhgren77dc1992019-11-23 00:14:31 +0100276
peahdf3efa82015-11-28 12:35:15 -0800277 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000278}
279
aluebs11d4a422016-04-28 14:58:32 -0700280
niklase@google.com470e71d2011-07-07 08:21:25 +0000281// TODO(ajm): ensure this is called under kAdaptiveAnalog.
282int GainControlImpl::set_stream_analog_level(int level) {
peah135259a2016-10-28 03:12:11 -0700283 data_dumper_->DumpRaw("gain_control_set_stream_analog_level", 1, &level);
peahdf3efa82015-11-28 12:35:15 -0800284
niklase@google.com470e71d2011-07-07 08:21:25 +0000285 was_analog_level_set_ = true;
286 if (level < minimum_capture_level_ || level > maximum_capture_level_) {
peahdf3efa82015-11-28 12:35:15 -0800287 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000288 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000289 analog_capture_level_ = level;
290
peahdf3efa82015-11-28 12:35:15 -0800291 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000292}
293
Sam Zackrissonf0d1c032019-03-27 13:28:08 +0100294int GainControlImpl::stream_analog_level() const {
peah135259a2016-10-28 03:12:11 -0700295 data_dumper_->DumpRaw("gain_control_stream_analog_level", 1,
296 &analog_capture_level_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000297 return analog_capture_level_;
298}
299
niklase@google.com470e71d2011-07-07 08:21:25 +0000300int GainControlImpl::set_mode(Mode mode) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000301 if (MapSetting(mode) == -1) {
peahdf3efa82015-11-28 12:35:15 -0800302 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000303 }
304
305 mode_ = mode;
peahb8fbb542016-03-15 02:28:08 -0700306 RTC_DCHECK(num_proc_channels_);
307 RTC_DCHECK(sample_rate_hz_);
308 Initialize(*num_proc_channels_, *sample_rate_hz_);
peahbfa97112016-03-10 21:09:04 -0800309 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000310}
311
niklase@google.com470e71d2011-07-07 08:21:25 +0000312
Yves Gerey665174f2018-06-19 15:03:05 +0200313int GainControlImpl::set_analog_level_limits(int minimum, int maximum) {
Per Åhgren77dc1992019-11-23 00:14:31 +0100314 if (minimum < 0 || maximum > 65535 || maximum < minimum) {
peahdf3efa82015-11-28 12:35:15 -0800315 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000316 }
317
Per Åhgren77dc1992019-11-23 00:14:31 +0100318 minimum_capture_level_ = minimum;
319 maximum_capture_level_ = maximum;
niklase@google.com470e71d2011-07-07 08:21:25 +0000320
Per Åhgren77dc1992019-11-23 00:14:31 +0100321 RTC_DCHECK(num_proc_channels_);
322 RTC_DCHECK(sample_rate_hz_);
323 Initialize(*num_proc_channels_, *sample_rate_hz_);
peahbfa97112016-03-10 21:09:04 -0800324 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000325}
326
niklase@google.com470e71d2011-07-07 08:21:25 +0000327
328int GainControlImpl::set_target_level_dbfs(int level) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000329 if (level > 31 || level < 0) {
peahdf3efa82015-11-28 12:35:15 -0800330 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000331 }
Sam Zackrisson421c8592019-02-11 13:39:46 +0100332 target_level_dbfs_ = level;
niklase@google.com470e71d2011-07-07 08:21:25 +0000333 return Configure();
334}
335
niklase@google.com470e71d2011-07-07 08:21:25 +0000336int GainControlImpl::set_compression_gain_db(int gain) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000337 if (gain < 0 || gain > 90) {
Per Åhgren3daedb62019-11-22 12:11:40 +0100338 RTC_LOG(LS_ERROR) << "set_compression_gain_db(" << gain << ") failed.";
peahdf3efa82015-11-28 12:35:15 -0800339 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000340 }
Sam Zackrisson421c8592019-02-11 13:39:46 +0100341 compression_gain_db_ = gain;
niklase@google.com470e71d2011-07-07 08:21:25 +0000342 return Configure();
343}
344
niklase@google.com470e71d2011-07-07 08:21:25 +0000345int GainControlImpl::enable_limiter(bool enable) {
Sam Zackrisson421c8592019-02-11 13:39:46 +0100346 limiter_enabled_ = enable;
niklase@google.com470e71d2011-07-07 08:21:25 +0000347 return Configure();
348}
349
peahb8fbb542016-03-15 02:28:08 -0700350void GainControlImpl::Initialize(size_t num_proc_channels, int sample_rate_hz) {
peah135259a2016-10-28 03:12:11 -0700351 data_dumper_->InitiateNewSetOfRecordings();
peahb8fbb542016-03-15 02:28:08 -0700352
Per Åhgren27bd76b2019-11-26 09:23:45 +0100353 RTC_DCHECK(sample_rate_hz == 16000 || sample_rate_hz == 32000 ||
354 sample_rate_hz == 48000);
355
Oskar Sundbomaa8b67d2017-11-17 14:34:48 +0100356 num_proc_channels_ = num_proc_channels;
357 sample_rate_hz_ = sample_rate_hz;
peahb8fbb542016-03-15 02:28:08 -0700358
Per Åhgren77dc1992019-11-23 00:14:31 +0100359 mono_agcs_.resize(*num_proc_channels_);
360 capture_levels_.resize(*num_proc_channels_);
361 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
362 if (!mono_agcs_[ch]) {
363 mono_agcs_[ch].reset(new MonoAgcState());
peahbfa97112016-03-10 21:09:04 -0800364 }
Per Åhgren77dc1992019-11-23 00:14:31 +0100365
366 int error = WebRtcAgc_Init(mono_agcs_[ch]->state, minimum_capture_level_,
367 maximum_capture_level_, MapSetting(mode_),
368 *sample_rate_hz_);
369 RTC_DCHECK_EQ(error, 0);
370 capture_levels_[ch] = analog_capture_level_;
peahbfa97112016-03-10 21:09:04 -0800371 }
372
373 Configure();
peah4d291f72015-11-16 23:52:25 -0800374}
375
peahbfa97112016-03-10 21:09:04 -0800376int GainControlImpl::Configure() {
pbos@webrtc.orge468bc92014-12-18 09:11:33 +0000377 WebRtcAgcConfig config;
niklase@google.com470e71d2011-07-07 08:21:25 +0000378 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we
379 // change the interface.
Yves Gerey665174f2018-06-19 15:03:05 +0200380 // RTC_DCHECK_LE(target_level_dbfs_, 0);
381 // config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_);
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000382 config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_);
Yves Gerey665174f2018-06-19 15:03:05 +0200383 config.compressionGaindB = static_cast<int16_t>(compression_gain_db_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000384 config.limiterEnable = limiter_enabled_;
385
peahbfa97112016-03-10 21:09:04 -0800386 int error = AudioProcessing::kNoError;
Per Åhgren77dc1992019-11-23 00:14:31 +0100387 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
388 int error_ch = WebRtcAgc_set_config(mono_agcs_[ch]->state, config);
389 if (error_ch != AudioProcessing::kNoError) {
390 error = error_ch;
peahbfa97112016-03-10 21:09:04 -0800391 }
392 }
393 return error;
niklase@google.com470e71d2011-07-07 08:21:25 +0000394}
niklase@google.com470e71d2011-07-07 08:21:25 +0000395} // namespace webrtc