2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/modules/audio_processing/gain_control_impl.h"
15 #include "webrtc/modules/audio_processing/audio_buffer.h"
16 #include "webrtc/modules/audio_processing/agc/include/gain_control.h"
17 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
24 int16_t MapSetting(GainControl::Mode mode) {
26 case GainControl::kAdaptiveAnalog:
27 return kAgcModeAdaptiveAnalog;
28 case GainControl::kAdaptiveDigital:
29 return kAgcModeAdaptiveDigital;
30 case GainControl::kFixedDigital:
31 return kAgcModeFixedDigital;
38 GainControlImpl::GainControlImpl(const AudioProcessing* apm,
39 CriticalSectionWrapper* crit)
40 : ProcessingComponent(),
43 mode_(kAdaptiveAnalog),
44 minimum_capture_level_(0),
45 maximum_capture_level_(255),
46 limiter_enabled_(true),
47 target_level_dbfs_(3),
48 compression_gain_db_(9),
49 analog_capture_level_(0),
50 was_analog_level_set_(false),
51 stream_is_saturated_(false) {}
53 GainControlImpl::~GainControlImpl() {}
55 int GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) {
56 if (!is_component_enabled()) {
57 return apm_->kNoError;
60 assert(audio->samples_per_split_channel() <= 160);
62 const int16_t* mixed_data = audio->low_pass_split_data(0);
63 if (audio->num_channels() > 1) {
64 audio->CopyAndMixLowPass(1);
65 mixed_data = audio->mixed_low_pass_data(0);
68 for (int i = 0; i < num_handles(); i++) {
69 Handle* my_handle = static_cast<Handle*>(handle(i));
70 int err = WebRtcAgc_AddFarend(
73 static_cast<int16_t>(audio->samples_per_split_channel()));
75 if (err != apm_->kNoError) {
76 return GetHandleError(my_handle);
80 return apm_->kNoError;
83 int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
84 if (!is_component_enabled()) {
85 return apm_->kNoError;
88 assert(audio->samples_per_split_channel() <= 160);
89 assert(audio->num_channels() == num_handles());
91 int err = apm_->kNoError;
93 if (mode_ == kAdaptiveAnalog) {
94 capture_levels_.assign(num_handles(), analog_capture_level_);
95 for (int i = 0; i < num_handles(); i++) {
96 Handle* my_handle = static_cast<Handle*>(handle(i));
97 err = WebRtcAgc_AddMic(
99 audio->low_pass_split_data(i),
100 audio->high_pass_split_data(i),
101 static_cast<int16_t>(audio->samples_per_split_channel()));
103 if (err != apm_->kNoError) {
104 return GetHandleError(my_handle);
107 } else if (mode_ == kAdaptiveDigital) {
109 for (int i = 0; i < num_handles(); i++) {
110 Handle* my_handle = static_cast<Handle*>(handle(i));
111 int32_t capture_level_out = 0;
113 err = WebRtcAgc_VirtualMic(
115 audio->low_pass_split_data(i),
116 audio->high_pass_split_data(i),
117 static_cast<int16_t>(audio->samples_per_split_channel()),
118 analog_capture_level_,
121 capture_levels_[i] = capture_level_out;
123 if (err != apm_->kNoError) {
124 return GetHandleError(my_handle);
130 return apm_->kNoError;
133 int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) {
134 if (!is_component_enabled()) {
135 return apm_->kNoError;
138 if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) {
139 return apm_->kStreamParameterNotSetError;
142 assert(audio->samples_per_split_channel() <= 160);
143 assert(audio->num_channels() == num_handles());
145 stream_is_saturated_ = false;
146 for (int i = 0; i < num_handles(); i++) {
147 Handle* my_handle = static_cast<Handle*>(handle(i));
148 int32_t capture_level_out = 0;
149 uint8_t saturation_warning = 0;
151 int err = WebRtcAgc_Process(
153 audio->low_pass_split_data(i),
154 audio->high_pass_split_data(i),
155 static_cast<int16_t>(audio->samples_per_split_channel()),
156 audio->low_pass_split_data(i),
157 audio->high_pass_split_data(i),
160 apm_->echo_cancellation()->stream_has_echo(),
161 &saturation_warning);
163 if (err != apm_->kNoError) {
164 return GetHandleError(my_handle);
167 capture_levels_[i] = capture_level_out;
168 if (saturation_warning == 1) {
169 stream_is_saturated_ = true;
173 if (mode_ == kAdaptiveAnalog) {
174 // Take the analog level to be the average across the handles.
175 analog_capture_level_ = 0;
176 for (int i = 0; i < num_handles(); i++) {
177 analog_capture_level_ += capture_levels_[i];
180 analog_capture_level_ /= num_handles();
183 was_analog_level_set_ = false;
184 return apm_->kNoError;
187 // TODO(ajm): ensure this is called under kAdaptiveAnalog.
188 int GainControlImpl::set_stream_analog_level(int level) {
189 was_analog_level_set_ = true;
190 if (level < minimum_capture_level_ || level > maximum_capture_level_) {
191 return apm_->kBadParameterError;
193 analog_capture_level_ = level;
195 return apm_->kNoError;
198 int GainControlImpl::stream_analog_level() {
199 // TODO(ajm): enable this assertion?
200 //assert(mode_ == kAdaptiveAnalog);
202 return analog_capture_level_;
205 int GainControlImpl::Enable(bool enable) {
206 CriticalSectionScoped crit_scoped(crit_);
207 return EnableComponent(enable);
210 bool GainControlImpl::is_enabled() const {
211 return is_component_enabled();
214 int GainControlImpl::set_mode(Mode mode) {
215 CriticalSectionScoped crit_scoped(crit_);
216 if (MapSetting(mode) == -1) {
217 return apm_->kBadParameterError;
224 GainControl::Mode GainControlImpl::mode() const {
228 int GainControlImpl::set_analog_level_limits(int minimum,
230 CriticalSectionScoped crit_scoped(crit_);
232 return apm_->kBadParameterError;
235 if (maximum > 65535) {
236 return apm_->kBadParameterError;
239 if (maximum < minimum) {
240 return apm_->kBadParameterError;
243 minimum_capture_level_ = minimum;
244 maximum_capture_level_ = maximum;
249 int GainControlImpl::analog_level_minimum() const {
250 return minimum_capture_level_;
253 int GainControlImpl::analog_level_maximum() const {
254 return maximum_capture_level_;
257 bool GainControlImpl::stream_is_saturated() const {
258 return stream_is_saturated_;
261 int GainControlImpl::set_target_level_dbfs(int level) {
262 CriticalSectionScoped crit_scoped(crit_);
263 if (level > 31 || level < 0) {
264 return apm_->kBadParameterError;
267 target_level_dbfs_ = level;
271 int GainControlImpl::target_level_dbfs() const {
272 return target_level_dbfs_;
275 int GainControlImpl::set_compression_gain_db(int gain) {
276 CriticalSectionScoped crit_scoped(crit_);
277 if (gain < 0 || gain > 90) {
278 return apm_->kBadParameterError;
281 compression_gain_db_ = gain;
285 int GainControlImpl::compression_gain_db() const {
286 return compression_gain_db_;
289 int GainControlImpl::enable_limiter(bool enable) {
290 CriticalSectionScoped crit_scoped(crit_);
291 limiter_enabled_ = enable;
295 bool GainControlImpl::is_limiter_enabled() const {
296 return limiter_enabled_;
299 int GainControlImpl::Initialize() {
300 int err = ProcessingComponent::Initialize();
301 if (err != apm_->kNoError || !is_component_enabled()) {
305 capture_levels_.assign(num_handles(), analog_capture_level_);
306 return apm_->kNoError;
309 void* GainControlImpl::CreateHandle() const {
310 Handle* handle = NULL;
311 if (WebRtcAgc_Create(&handle) != apm_->kNoError) {
314 assert(handle != NULL);
320 void GainControlImpl::DestroyHandle(void* handle) const {
321 WebRtcAgc_Free(static_cast<Handle*>(handle));
324 int GainControlImpl::InitializeHandle(void* handle) const {
325 return WebRtcAgc_Init(static_cast<Handle*>(handle),
326 minimum_capture_level_,
327 maximum_capture_level_,
329 apm_->proc_sample_rate_hz());
332 int GainControlImpl::ConfigureHandle(void* handle) const {
333 WebRtcAgc_config_t config;
334 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we
335 // change the interface.
336 //assert(target_level_dbfs_ <= 0);
337 //config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_);
338 config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_);
339 config.compressionGaindB =
340 static_cast<int16_t>(compression_gain_db_);
341 config.limiterEnable = limiter_enabled_;
343 return WebRtcAgc_set_config(static_cast<Handle*>(handle), config);
346 int GainControlImpl::num_handles_required() const {
347 return apm_->num_output_channels();
350 int GainControlImpl::GetHandleError(void* handle) const {
351 // The AGC has no get_error() function.
352 // (Despite listing errors in its interface...)
353 assert(handle != NULL);
354 return apm_->kUnspecifiedError;
356 } // namespace webrtc