1 /*
2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
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
11 #include "gain_control_impl.h"
12
13 #include <cassert>
14
15 #include "critical_section_wrapper.h"
16 #include "gain_control.h"
17
18 #include "audio_processing_impl.h"
19 #include "audio_buffer.h"
20
21 namespace webrtc {
22
23 typedef void Handle;
24
25 /*template <class T>
26 class GainControlHandle : public ComponentHandle<T> {
27 public:
28 GainControlHandle();
29 virtual ~GainControlHandle();
30
31 virtual int Create();
32 virtual T* ptr() const;
33
34 private:
35 T* handle;
36 };*/
37
38 namespace {
MapSetting(GainControl::Mode mode)39 WebRtc_Word16 MapSetting(GainControl::Mode mode) {
40 switch (mode) {
41 case GainControl::kAdaptiveAnalog:
42 return kAgcModeAdaptiveAnalog;
43 break;
44 case GainControl::kAdaptiveDigital:
45 return kAgcModeAdaptiveDigital;
46 break;
47 case GainControl::kFixedDigital:
48 return kAgcModeFixedDigital;
49 break;
50 default:
51 return -1;
52 }
53 }
54 } // namespace
55
GainControlImpl(const AudioProcessingImpl * apm)56 GainControlImpl::GainControlImpl(const AudioProcessingImpl* apm)
57 : ProcessingComponent(apm),
58 apm_(apm),
59 mode_(kAdaptiveAnalog),
60 minimum_capture_level_(0),
61 maximum_capture_level_(255),
62 limiter_enabled_(true),
63 target_level_dbfs_(3),
64 compression_gain_db_(9),
65 analog_capture_level_(0),
66 was_analog_level_set_(false),
67 stream_is_saturated_(false) {}
68
~GainControlImpl()69 GainControlImpl::~GainControlImpl() {}
70
ProcessRenderAudio(AudioBuffer * audio)71 int GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) {
72 if (!is_component_enabled()) {
73 return apm_->kNoError;
74 }
75
76 assert(audio->samples_per_split_channel() <= 160);
77
78 WebRtc_Word16* mixed_data = audio->low_pass_split_data(0);
79 if (audio->num_channels() > 1) {
80 audio->CopyAndMixLowPass(1);
81 mixed_data = audio->mixed_low_pass_data(0);
82 }
83
84 for (int i = 0; i < num_handles(); i++) {
85 Handle* my_handle = static_cast<Handle*>(handle(i));
86 int err = WebRtcAgc_AddFarend(
87 my_handle,
88 mixed_data,
89 static_cast<WebRtc_Word16>(audio->samples_per_split_channel()));
90
91 if (err != apm_->kNoError) {
92 return GetHandleError(my_handle);
93 }
94 }
95
96 return apm_->kNoError;
97 }
98
AnalyzeCaptureAudio(AudioBuffer * audio)99 int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
100 if (!is_component_enabled()) {
101 return apm_->kNoError;
102 }
103
104 assert(audio->samples_per_split_channel() <= 160);
105 assert(audio->num_channels() == num_handles());
106
107 int err = apm_->kNoError;
108
109 if (mode_ == kAdaptiveAnalog) {
110 for (int i = 0; i < num_handles(); i++) {
111 Handle* my_handle = static_cast<Handle*>(handle(i));
112 err = WebRtcAgc_AddMic(
113 my_handle,
114 audio->low_pass_split_data(i),
115 audio->high_pass_split_data(i),
116 static_cast<WebRtc_Word16>(audio->samples_per_split_channel()));
117
118 if (err != apm_->kNoError) {
119 return GetHandleError(my_handle);
120 }
121 }
122 } else if (mode_ == kAdaptiveDigital) {
123
124 for (int i = 0; i < num_handles(); i++) {
125 Handle* my_handle = static_cast<Handle*>(handle(i));
126 WebRtc_Word32 capture_level_out = 0;
127
128 err = WebRtcAgc_VirtualMic(
129 my_handle,
130 audio->low_pass_split_data(i),
131 audio->high_pass_split_data(i),
132 static_cast<WebRtc_Word16>(audio->samples_per_split_channel()),
133 //capture_levels_[i],
134 analog_capture_level_,
135 &capture_level_out);
136
137 capture_levels_[i] = capture_level_out;
138
139 if (err != apm_->kNoError) {
140 return GetHandleError(my_handle);
141 }
142
143 }
144 }
145
146 return apm_->kNoError;
147 }
148
ProcessCaptureAudio(AudioBuffer * audio)149 int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) {
150 if (!is_component_enabled()) {
151 return apm_->kNoError;
152 }
153
154 if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) {
155 return apm_->kStreamParameterNotSetError;
156 }
157
158 assert(audio->samples_per_split_channel() <= 160);
159 assert(audio->num_channels() == num_handles());
160
161 stream_is_saturated_ = false;
162 for (int i = 0; i < num_handles(); i++) {
163 Handle* my_handle = static_cast<Handle*>(handle(i));
164 WebRtc_Word32 capture_level_out = 0;
165 WebRtc_UWord8 saturation_warning = 0;
166
167 int err = WebRtcAgc_Process(
168 my_handle,
169 audio->low_pass_split_data(i),
170 audio->high_pass_split_data(i),
171 static_cast<WebRtc_Word16>(audio->samples_per_split_channel()),
172 audio->low_pass_split_data(i),
173 audio->high_pass_split_data(i),
174 capture_levels_[i],
175 &capture_level_out,
176 apm_->echo_cancellation()->stream_has_echo(),
177 &saturation_warning);
178
179 if (err != apm_->kNoError) {
180 return GetHandleError(my_handle);
181 }
182
183 capture_levels_[i] = capture_level_out;
184 if (saturation_warning == 1) {
185 stream_is_saturated_ = true;
186 }
187 }
188
189 if (mode_ == kAdaptiveAnalog) {
190 // Take the analog level to be the average across the handles.
191 analog_capture_level_ = 0;
192 for (int i = 0; i < num_handles(); i++) {
193 analog_capture_level_ += capture_levels_[i];
194 }
195
196 analog_capture_level_ /= num_handles();
197 }
198
199 was_analog_level_set_ = false;
200 return apm_->kNoError;
201 }
202
203 // TODO(ajm): ensure this is called under kAdaptiveAnalog.
set_stream_analog_level(int level)204 int GainControlImpl::set_stream_analog_level(int level) {
205 was_analog_level_set_ = true;
206 if (level < minimum_capture_level_ || level > maximum_capture_level_) {
207 return apm_->kBadParameterError;
208 }
209
210 if (mode_ == kAdaptiveAnalog) {
211 if (level != analog_capture_level_) {
212 // The analog level has been changed; update our internal levels.
213 capture_levels_.assign(num_handles(), level);
214 }
215 }
216 analog_capture_level_ = level;
217
218 return apm_->kNoError;
219 }
220
stream_analog_level()221 int GainControlImpl::stream_analog_level() {
222 // TODO(ajm): enable this assertion?
223 //assert(mode_ == kAdaptiveAnalog);
224
225 return analog_capture_level_;
226 }
227
Enable(bool enable)228 int GainControlImpl::Enable(bool enable) {
229 CriticalSectionScoped crit_scoped(*apm_->crit());
230 return EnableComponent(enable);
231 }
232
is_enabled() const233 bool GainControlImpl::is_enabled() const {
234 return is_component_enabled();
235 }
236
set_mode(Mode mode)237 int GainControlImpl::set_mode(Mode mode) {
238 CriticalSectionScoped crit_scoped(*apm_->crit());
239 if (MapSetting(mode) == -1) {
240 return apm_->kBadParameterError;
241 }
242
243 mode_ = mode;
244 return Initialize();
245 }
246
mode() const247 GainControl::Mode GainControlImpl::mode() const {
248 return mode_;
249 }
250
set_analog_level_limits(int minimum,int maximum)251 int GainControlImpl::set_analog_level_limits(int minimum,
252 int maximum) {
253 CriticalSectionScoped crit_scoped(*apm_->crit());
254 if (minimum < 0) {
255 return apm_->kBadParameterError;
256 }
257
258 if (maximum > 65535) {
259 return apm_->kBadParameterError;
260 }
261
262 if (maximum < minimum) {
263 return apm_->kBadParameterError;
264 }
265
266 minimum_capture_level_ = minimum;
267 maximum_capture_level_ = maximum;
268
269 return Initialize();
270 }
271
analog_level_minimum() const272 int GainControlImpl::analog_level_minimum() const {
273 return minimum_capture_level_;
274 }
275
analog_level_maximum() const276 int GainControlImpl::analog_level_maximum() const {
277 return maximum_capture_level_;
278 }
279
stream_is_saturated() const280 bool GainControlImpl::stream_is_saturated() const {
281 return stream_is_saturated_;
282 }
283
set_target_level_dbfs(int level)284 int GainControlImpl::set_target_level_dbfs(int level) {
285 CriticalSectionScoped crit_scoped(*apm_->crit());
286 if (level > 31 || level < 0) {
287 return apm_->kBadParameterError;
288 }
289
290 target_level_dbfs_ = level;
291 return Configure();
292 }
293
target_level_dbfs() const294 int GainControlImpl::target_level_dbfs() const {
295 return target_level_dbfs_;
296 }
297
set_compression_gain_db(int gain)298 int GainControlImpl::set_compression_gain_db(int gain) {
299 CriticalSectionScoped crit_scoped(*apm_->crit());
300 if (gain < 0 || gain > 90) {
301 return apm_->kBadParameterError;
302 }
303
304 compression_gain_db_ = gain;
305 return Configure();
306 }
307
compression_gain_db() const308 int GainControlImpl::compression_gain_db() const {
309 return compression_gain_db_;
310 }
311
enable_limiter(bool enable)312 int GainControlImpl::enable_limiter(bool enable) {
313 CriticalSectionScoped crit_scoped(*apm_->crit());
314 limiter_enabled_ = enable;
315 return Configure();
316 }
317
is_limiter_enabled() const318 bool GainControlImpl::is_limiter_enabled() const {
319 return limiter_enabled_;
320 }
321
Initialize()322 int GainControlImpl::Initialize() {
323 int err = ProcessingComponent::Initialize();
324 if (err != apm_->kNoError || !is_component_enabled()) {
325 return err;
326 }
327
328 analog_capture_level_ =
329 (maximum_capture_level_ - minimum_capture_level_) >> 1;
330 capture_levels_.assign(num_handles(), analog_capture_level_);
331 was_analog_level_set_ = false;
332
333 return apm_->kNoError;
334 }
335
get_version(char * version,int version_len_bytes) const336 int GainControlImpl::get_version(char* version, int version_len_bytes) const {
337 if (WebRtcAgc_Version(version, version_len_bytes) != 0) {
338 return apm_->kBadParameterError;
339 }
340
341 return apm_->kNoError;
342 }
343
CreateHandle() const344 void* GainControlImpl::CreateHandle() const {
345 Handle* handle = NULL;
346 if (WebRtcAgc_Create(&handle) != apm_->kNoError) {
347 handle = NULL;
348 } else {
349 assert(handle != NULL);
350 }
351
352 return handle;
353 }
354
DestroyHandle(void * handle) const355 int GainControlImpl::DestroyHandle(void* handle) const {
356 return WebRtcAgc_Free(static_cast<Handle*>(handle));
357 }
358
InitializeHandle(void * handle) const359 int GainControlImpl::InitializeHandle(void* handle) const {
360 return WebRtcAgc_Init(static_cast<Handle*>(handle),
361 minimum_capture_level_,
362 maximum_capture_level_,
363 MapSetting(mode_),
364 apm_->sample_rate_hz());
365 }
366
ConfigureHandle(void * handle) const367 int GainControlImpl::ConfigureHandle(void* handle) const {
368 WebRtcAgc_config_t config;
369 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we
370 // change the interface.
371 //assert(target_level_dbfs_ <= 0);
372 //config.targetLevelDbfs = static_cast<WebRtc_Word16>(-target_level_dbfs_);
373 config.targetLevelDbfs = static_cast<WebRtc_Word16>(target_level_dbfs_);
374 config.compressionGaindB =
375 static_cast<WebRtc_Word16>(compression_gain_db_);
376 config.limiterEnable = limiter_enabled_;
377
378 return WebRtcAgc_set_config(static_cast<Handle*>(handle), config);
379 }
380
num_handles_required() const381 int GainControlImpl::num_handles_required() const {
382 return apm_->num_output_channels();
383 }
384
GetHandleError(void * handle) const385 int GainControlImpl::GetHandleError(void* handle) const {
386 // The AGC has no get_error() function.
387 // (Despite listing errors in its interface...)
388 assert(handle != NULL);
389 return apm_->kUnspecifiedError;
390 }
391 } // namespace webrtc
392