blob: 936a286cdbcb8309041748c548ac67b5606ef721 [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
pbos@webrtc.org7fad4b82013-05-28 08:11:59 +000011#include "webrtc/modules/audio_processing/gain_control_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
peahbfa97112016-03-10 21:09:04 -080013#include "webrtc/base/optional.h"
andrew@webrtc.org56e4a052014-02-27 22:23:17 +000014#include "webrtc/modules/audio_processing/audio_buffer.h"
bjornv@webrtc.orgb395a5e2014-12-16 10:38:10 +000015#include "webrtc/modules/audio_processing/agc/legacy/gain_control.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000016
niklase@google.com470e71d2011-07-07 08:21:25 +000017namespace webrtc {
18
19typedef void Handle;
20
niklase@google.com470e71d2011-07-07 08:21:25 +000021namespace {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +000022int16_t MapSetting(GainControl::Mode mode) {
niklase@google.com470e71d2011-07-07 08:21:25 +000023 switch (mode) {
24 case GainControl::kAdaptiveAnalog:
25 return kAgcModeAdaptiveAnalog;
niklase@google.com470e71d2011-07-07 08:21:25 +000026 case GainControl::kAdaptiveDigital:
27 return kAgcModeAdaptiveDigital;
niklase@google.com470e71d2011-07-07 08:21:25 +000028 case GainControl::kFixedDigital:
29 return kAgcModeFixedDigital;
niklase@google.com470e71d2011-07-07 08:21:25 +000030 }
peahbfa97112016-03-10 21:09:04 -080031 RTC_DCHECK(false);
mflodman@webrtc.org657b2a42012-02-06 11:06:01 +000032 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +000033}
niklase@google.com470e71d2011-07-07 08:21:25 +000034
peah2446e5a2015-11-18 06:11:13 -080035// Maximum length that a frame of samples can have.
36static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160;
37// Maximum number of frames to buffer in the render queue.
38// TODO(peah): Decrease this once we properly handle hugely unbalanced
39// reverse and forward call numbers.
40static const size_t kMaxNumFramesToBuffer = 100;
41
42} // 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
75 void set_capture_level(int capture_level) {
76 capture_level_ = rtc::Optional<int>(capture_level);
77 }
78
79 int get_capture_level() {
80 RTC_DCHECK(capture_level_);
81 return *capture_level_;
82 }
83
84 private:
85 Handle* state_;
86 // TODO(peah): Remove the optional once the initialization is moved into the
87 // ctor.
88 rtc::Optional<int> capture_level_;
89
90 RTC_DISALLOW_COPY_AND_ASSIGN(GainController);
91};
92
andrew@webrtc.org56e4a052014-02-27 22:23:17 +000093GainControlImpl::GainControlImpl(const AudioProcessing* apm,
peahdf3efa82015-11-28 12:35:15 -080094 rtc::CriticalSection* crit_render,
95 rtc::CriticalSection* crit_capture)
peahbfa97112016-03-10 21:09:04 -080096 : apm_(apm),
peahdf3efa82015-11-28 12:35:15 -080097 crit_render_(crit_render),
98 crit_capture_(crit_capture),
peah4d291f72015-11-16 23:52:25 -080099 mode_(kAdaptiveAnalog),
100 minimum_capture_level_(0),
101 maximum_capture_level_(255),
102 limiter_enabled_(true),
103 target_level_dbfs_(3),
104 compression_gain_db_(9),
105 analog_capture_level_(0),
106 was_analog_level_set_(false),
107 stream_is_saturated_(false),
peahdf3efa82015-11-28 12:35:15 -0800108 render_queue_element_max_size_(0) {
109 RTC_DCHECK(apm);
110 RTC_DCHECK(crit_render);
111 RTC_DCHECK(crit_capture);
112}
niklase@google.com470e71d2011-07-07 08:21:25 +0000113
114GainControlImpl::~GainControlImpl() {}
115
116int GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) {
peahdf3efa82015-11-28 12:35:15 -0800117 rtc::CritScope cs(crit_render_);
peahbfa97112016-03-10 21:09:04 -0800118 if (!enabled_) {
peahdf3efa82015-11-28 12:35:15 -0800119 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000120 }
121
peahbfa97112016-03-10 21:09:04 -0800122 RTC_DCHECK_GE(160u, audio->num_frames_per_band());
niklase@google.com470e71d2011-07-07 08:21:25 +0000123
peah4d291f72015-11-16 23:52:25 -0800124 render_queue_buffer_.resize(0);
peahbfa97112016-03-10 21:09:04 -0800125 for (auto& gain_controller : gain_controllers_) {
126 int err = WebRtcAgc_GetAddFarendError(gain_controller->state(),
127 audio->num_frames_per_band());
niklase@google.com470e71d2011-07-07 08:21:25 +0000128
peahbfa97112016-03-10 21:09:04 -0800129 if (err != AudioProcessing::kNoError) {
130 return AudioProcessing::kUnspecifiedError;
131 }
peah4d291f72015-11-16 23:52:25 -0800132
133 // Buffer the samples in the render queue.
134 render_queue_buffer_.insert(
135 render_queue_buffer_.end(), audio->mixed_low_pass_data(),
136 (audio->mixed_low_pass_data() + audio->num_frames_per_band()));
137 }
138
139 // Insert the samples into the queue.
140 if (!render_signal_queue_->Insert(&render_queue_buffer_)) {
peahdf3efa82015-11-28 12:35:15 -0800141 // The data queue is full and needs to be emptied.
peah4d291f72015-11-16 23:52:25 -0800142 ReadQueuedRenderData();
143
144 // Retry the insert (should always work).
145 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000146 }
147
peahdf3efa82015-11-28 12:35:15 -0800148 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000149}
150
peah4d291f72015-11-16 23:52:25 -0800151// Read chunks of data that were received and queued on the render side from
152// a queue. All the data chunks are buffered into the farend signal of the AGC.
153void GainControlImpl::ReadQueuedRenderData() {
peahdf3efa82015-11-28 12:35:15 -0800154 rtc::CritScope cs(crit_capture_);
155
peahbfa97112016-03-10 21:09:04 -0800156 if (!enabled_) {
peah4d291f72015-11-16 23:52:25 -0800157 return;
158 }
159
160 while (render_signal_queue_->Remove(&capture_queue_buffer_)) {
pkasting25702cb2016-01-08 13:50:27 -0800161 size_t buffer_index = 0;
162 const size_t num_frames_per_band =
peahbfa97112016-03-10 21:09:04 -0800163 capture_queue_buffer_.size() / num_handles_required();
164 for (auto& gain_controller : gain_controllers_) {
165 WebRtcAgc_AddFarend(gain_controller->state(),
166 &capture_queue_buffer_[buffer_index],
peah4d291f72015-11-16 23:52:25 -0800167 num_frames_per_band);
168
169 buffer_index += num_frames_per_band;
170 }
171 }
172}
173
niklase@google.com470e71d2011-07-07 08:21:25 +0000174int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
peahdf3efa82015-11-28 12:35:15 -0800175 rtc::CritScope cs(crit_capture_);
176
peahbfa97112016-03-10 21:09:04 -0800177 if (!enabled_) {
peahdf3efa82015-11-28 12:35:15 -0800178 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000179 }
180
peahbfa97112016-03-10 21:09:04 -0800181 RTC_DCHECK_GE(160u, audio->num_frames_per_band());
182 RTC_DCHECK_EQ(audio->num_channels(), num_handles_required());
183 RTC_DCHECK_LE(num_handles_required(), gain_controllers_.size());
niklase@google.com470e71d2011-07-07 08:21:25 +0000184
185 if (mode_ == kAdaptiveAnalog) {
peahbfa97112016-03-10 21:09:04 -0800186 int capture_channel = 0;
187 for (auto& gain_controller : gain_controllers_) {
188 gain_controller->set_capture_level(analog_capture_level_);
189 int err = WebRtcAgc_AddMic(
190 gain_controller->state(), audio->split_bands(capture_channel),
191 audio->num_bands(), audio->num_frames_per_band());
niklase@google.com470e71d2011-07-07 08:21:25 +0000192
peahdf3efa82015-11-28 12:35:15 -0800193 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800194 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000195 }
peahbfa97112016-03-10 21:09:04 -0800196 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000197 }
198 } else if (mode_ == kAdaptiveDigital) {
peahbfa97112016-03-10 21:09:04 -0800199 int capture_channel = 0;
200 for (auto& gain_controller : gain_controllers_) {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000201 int32_t capture_level_out = 0;
peahbfa97112016-03-10 21:09:04 -0800202 int err = WebRtcAgc_VirtualMic(
203 gain_controller->state(), audio->split_bands(capture_channel),
204 audio->num_bands(), audio->num_frames_per_band(),
205 analog_capture_level_, &capture_level_out);
niklase@google.com470e71d2011-07-07 08:21:25 +0000206
peahbfa97112016-03-10 21:09:04 -0800207 gain_controller->set_capture_level(capture_level_out);
niklase@google.com470e71d2011-07-07 08:21:25 +0000208
peahdf3efa82015-11-28 12:35:15 -0800209 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800210 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000211 }
peahbfa97112016-03-10 21:09:04 -0800212 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000213 }
214 }
215
peahdf3efa82015-11-28 12:35:15 -0800216 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000217}
218
219int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) {
peahdf3efa82015-11-28 12:35:15 -0800220 rtc::CritScope cs(crit_capture_);
221
peahbfa97112016-03-10 21:09:04 -0800222 if (!enabled_) {
peahdf3efa82015-11-28 12:35:15 -0800223 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000224 }
225
226 if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) {
peahdf3efa82015-11-28 12:35:15 -0800227 return AudioProcessing::kStreamParameterNotSetError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000228 }
229
peahbfa97112016-03-10 21:09:04 -0800230 RTC_DCHECK_GE(160u, audio->num_frames_per_band());
231 RTC_DCHECK_EQ(audio->num_channels(), num_handles_required());
niklase@google.com470e71d2011-07-07 08:21:25 +0000232
233 stream_is_saturated_ = false;
peahbfa97112016-03-10 21:09:04 -0800234 int capture_channel = 0;
235 for (auto& gain_controller : gain_controllers_) {
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000236 int32_t capture_level_out = 0;
237 uint8_t saturation_warning = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000238
peahdf3efa82015-11-28 12:35:15 -0800239 // The call to stream_has_echo() is ok from a deadlock perspective
240 // as the capture lock is allready held.
niklase@google.com470e71d2011-07-07 08:21:25 +0000241 int err = WebRtcAgc_Process(
peahbfa97112016-03-10 21:09:04 -0800242 gain_controller->state(), audio->split_bands_const(capture_channel),
243 audio->num_bands(), audio->num_frames_per_band(),
244 audio->split_bands(capture_channel),
245 gain_controller->get_capture_level(), &capture_level_out,
246 apm_->echo_cancellation()->stream_has_echo(), &saturation_warning);
niklase@google.com470e71d2011-07-07 08:21:25 +0000247
peahdf3efa82015-11-28 12:35:15 -0800248 if (err != AudioProcessing::kNoError) {
peahbfa97112016-03-10 21:09:04 -0800249 return AudioProcessing::kUnspecifiedError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000250 }
251
peahbfa97112016-03-10 21:09:04 -0800252 gain_controller->set_capture_level(capture_level_out);
niklase@google.com470e71d2011-07-07 08:21:25 +0000253 if (saturation_warning == 1) {
254 stream_is_saturated_ = true;
255 }
peahbfa97112016-03-10 21:09:04 -0800256
257 ++capture_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000258 }
259
260 if (mode_ == kAdaptiveAnalog) {
261 // Take the analog level to be the average across the handles.
262 analog_capture_level_ = 0;
peahbfa97112016-03-10 21:09:04 -0800263 for (auto& gain_controller : gain_controllers_) {
264 analog_capture_level_ += gain_controller->get_capture_level();
niklase@google.com470e71d2011-07-07 08:21:25 +0000265 }
266
peahbfa97112016-03-10 21:09:04 -0800267 analog_capture_level_ /= num_handles_required();
niklase@google.com470e71d2011-07-07 08:21:25 +0000268 }
269
270 was_analog_level_set_ = false;
peahdf3efa82015-11-28 12:35:15 -0800271 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000272}
273
274// TODO(ajm): ensure this is called under kAdaptiveAnalog.
275int GainControlImpl::set_stream_analog_level(int level) {
peahdf3efa82015-11-28 12:35:15 -0800276 rtc::CritScope cs(crit_capture_);
277
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
287int GainControlImpl::stream_analog_level() {
peahdf3efa82015-11-28 12:35:15 -0800288 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000289 // TODO(ajm): enable this assertion?
290 //assert(mode_ == kAdaptiveAnalog);
291
292 return analog_capture_level_;
293}
294
295int GainControlImpl::Enable(bool enable) {
peahdf3efa82015-11-28 12:35:15 -0800296 rtc::CritScope cs_render(crit_render_);
297 rtc::CritScope cs_capture(crit_capture_);
peahbfa97112016-03-10 21:09:04 -0800298 if (enable && !enabled_) {
299 enabled_ = enable; // Must be set before Initialize() is called.
300 Initialize();
301 } else {
302 enabled_ = enable;
303 }
304 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000305}
306
307bool GainControlImpl::is_enabled() const {
peahdf3efa82015-11-28 12:35:15 -0800308 rtc::CritScope cs(crit_capture_);
peahbfa97112016-03-10 21:09:04 -0800309 return enabled_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000310}
311
312int GainControlImpl::set_mode(Mode mode) {
peahdf3efa82015-11-28 12:35:15 -0800313 rtc::CritScope cs_render(crit_render_);
314 rtc::CritScope cs_capture(crit_capture_);
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;
peahbfa97112016-03-10 21:09:04 -0800320 Initialize();
321 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000322}
323
324GainControl::Mode GainControlImpl::mode() const {
peahdf3efa82015-11-28 12:35:15 -0800325 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000326 return mode_;
327}
328
329int GainControlImpl::set_analog_level_limits(int minimum,
330 int maximum) {
peahdf3efa82015-11-28 12:35:15 -0800331 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000332 if (minimum < 0) {
peahdf3efa82015-11-28 12:35:15 -0800333 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000334 }
335
336 if (maximum > 65535) {
peahdf3efa82015-11-28 12:35:15 -0800337 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000338 }
339
340 if (maximum < minimum) {
peahdf3efa82015-11-28 12:35:15 -0800341 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000342 }
343
344 minimum_capture_level_ = minimum;
345 maximum_capture_level_ = maximum;
346
peahbfa97112016-03-10 21:09:04 -0800347 Initialize();
348 return AudioProcessing::kNoError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000349}
350
351int GainControlImpl::analog_level_minimum() const {
peahdf3efa82015-11-28 12:35:15 -0800352 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000353 return minimum_capture_level_;
354}
355
356int GainControlImpl::analog_level_maximum() const {
peahdf3efa82015-11-28 12:35:15 -0800357 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000358 return maximum_capture_level_;
359}
360
361bool GainControlImpl::stream_is_saturated() const {
peahdf3efa82015-11-28 12:35:15 -0800362 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000363 return stream_is_saturated_;
364}
365
366int GainControlImpl::set_target_level_dbfs(int level) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000367 if (level > 31 || level < 0) {
peahdf3efa82015-11-28 12:35:15 -0800368 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000369 }
peahbfa97112016-03-10 21:09:04 -0800370 {
371 rtc::CritScope cs(crit_capture_);
372 target_level_dbfs_ = level;
373 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000374 return Configure();
375}
376
377int GainControlImpl::target_level_dbfs() const {
peahdf3efa82015-11-28 12:35:15 -0800378 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000379 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) {
peahdf3efa82015-11-28 12:35:15 -0800384 return AudioProcessing::kBadParameterError;
niklase@google.com470e71d2011-07-07 08:21:25 +0000385 }
peahbfa97112016-03-10 21:09:04 -0800386 {
387 rtc::CritScope cs(crit_capture_);
388 compression_gain_db_ = gain;
389 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000390 return Configure();
391}
392
393int GainControlImpl::compression_gain_db() const {
peahdf3efa82015-11-28 12:35:15 -0800394 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000395 return compression_gain_db_;
396}
397
398int GainControlImpl::enable_limiter(bool enable) {
peahbfa97112016-03-10 21:09:04 -0800399 {
400 rtc::CritScope cs(crit_capture_);
401 limiter_enabled_ = enable;
402 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000403 return Configure();
404}
405
406bool GainControlImpl::is_limiter_enabled() const {
peahdf3efa82015-11-28 12:35:15 -0800407 rtc::CritScope cs(crit_capture_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000408 return limiter_enabled_;
409}
410
peahbfa97112016-03-10 21:09:04 -0800411void GainControlImpl::Initialize() {
412 rtc::CritScope cs_render(crit_render_);
413 rtc::CritScope cs_capture(crit_capture_);
414 if (!enabled_) {
415 return;
niklase@google.com470e71d2011-07-07 08:21:25 +0000416 }
417
peahbfa97112016-03-10 21:09:04 -0800418 int sample_rate_hz = apm_->proc_sample_rate_hz();
419 gain_controllers_.resize(num_handles_required());
420 for (auto& gain_controller : gain_controllers_) {
421 if (!gain_controller) {
422 gain_controller.reset(new GainController());
423 }
424 gain_controller->Initialize(minimum_capture_level_, maximum_capture_level_,
425 mode_, sample_rate_hz, analog_capture_level_);
426 }
427
428 Configure();
429
peah4d291f72015-11-16 23:52:25 -0800430 AllocateRenderQueue();
niklase@google.com470e71d2011-07-07 08:21:25 +0000431}
432
peah4d291f72015-11-16 23:52:25 -0800433void GainControlImpl::AllocateRenderQueue() {
peahbfa97112016-03-10 21:09:04 -0800434 const size_t new_render_queue_element_max_size = std::max<size_t>(
435 static_cast<size_t>(1),
436 kMaxAllowedValuesOfSamplesPerFrame * num_handles_required());
peah4d291f72015-11-16 23:52:25 -0800437
peahdf3efa82015-11-28 12:35:15 -0800438 rtc::CritScope cs_render(crit_render_);
439 rtc::CritScope cs_capture(crit_capture_);
440
peah2446e5a2015-11-18 06:11:13 -0800441 if (render_queue_element_max_size_ < new_render_queue_element_max_size) {
442 render_queue_element_max_size_ = new_render_queue_element_max_size;
peah4d291f72015-11-16 23:52:25 -0800443 std::vector<int16_t> template_queue_element(render_queue_element_max_size_);
444
445 render_signal_queue_.reset(
446 new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>(
447 kMaxNumFramesToBuffer, template_queue_element,
448 RenderQueueItemVerifier<int16_t>(render_queue_element_max_size_)));
peah2446e5a2015-11-18 06:11:13 -0800449
450 render_queue_buffer_.resize(render_queue_element_max_size_);
451 capture_queue_buffer_.resize(render_queue_element_max_size_);
peah4d291f72015-11-16 23:52:25 -0800452 } else {
453 render_signal_queue_->Clear();
454 }
peah4d291f72015-11-16 23:52:25 -0800455}
456
peahbfa97112016-03-10 21:09:04 -0800457int GainControlImpl::Configure() {
peahdf3efa82015-11-28 12:35:15 -0800458 rtc::CritScope cs_render(crit_render_);
459 rtc::CritScope cs_capture(crit_capture_);
pbos@webrtc.orge468bc92014-12-18 09:11:33 +0000460 WebRtcAgcConfig config;
niklase@google.com470e71d2011-07-07 08:21:25 +0000461 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we
462 // change the interface.
463 //assert(target_level_dbfs_ <= 0);
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000464 //config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_);
465 config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000466 config.compressionGaindB =
pbos@webrtc.orgb7192b82013-04-10 07:50:54 +0000467 static_cast<int16_t>(compression_gain_db_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000468 config.limiterEnable = limiter_enabled_;
469
peahbfa97112016-03-10 21:09:04 -0800470 int error = AudioProcessing::kNoError;
471 for (auto& gain_controller : gain_controllers_) {
472 const int handle_error =
473 WebRtcAgc_set_config(gain_controller->state(), config);
474 if (handle_error != AudioProcessing::kNoError) {
475 error = handle_error;
476 }
477 }
478 return error;
niklase@google.com470e71d2011-07-07 08:21:25 +0000479}
480
Peter Kasting69558702016-01-12 16:26:35 -0800481size_t GainControlImpl::num_handles_required() const {
peahdf3efa82015-11-28 12:35:15 -0800482 // Not locked as it only relies on APM public API which is threadsafe.
aluebsb2328d12016-01-11 20:32:29 -0800483 return apm_->num_proc_channels();
niklase@google.com470e71d2011-07-07 08:21:25 +0000484}
niklase@google.com470e71d2011-07-07 08:21:25 +0000485} // namespace webrtc