1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 119fb16139d917ba32720e031d3c871987d418668fpbos@webrtc.org#include "webrtc/modules/audio_processing/gain_control_impl.h" 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 133f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org#include <assert.h> 14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 15a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org#include "webrtc/modules/audio_processing/audio_buffer.h" 169fb16139d917ba32720e031d3c871987d418668fpbos@webrtc.org#include "webrtc/modules/audio_processing/agc/include/gain_control.h" 179fb16139d917ba32720e031d3c871987d418668fpbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc { 20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgtypedef void Handle; 22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace { 243f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.orgint16_t MapSetting(GainControl::Mode mode) { 25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org switch (mode) { 26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case GainControl::kAdaptiveAnalog: 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return kAgcModeAdaptiveAnalog; 28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case GainControl::kAdaptiveDigital: 29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return kAgcModeAdaptiveDigital; 30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case GainControl::kFixedDigital: 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return kAgcModeFixedDigital; 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(false); 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} // namespace 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 38a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.orgGainControlImpl::GainControlImpl(const AudioProcessing* apm, 39a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org CriticalSectionWrapper* crit) 40a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org : ProcessingComponent(), 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org apm_(apm), 42a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org crit_(crit), 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org mode_(kAdaptiveAnalog), 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org minimum_capture_level_(0), 45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org maximum_capture_level_(255), 46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org limiter_enabled_(true), 47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org target_level_dbfs_(3), 48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org compression_gain_db_(9), 49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org analog_capture_level_(0), 50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org was_analog_level_set_(false), 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org stream_is_saturated_(false) {} 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgGainControlImpl::~GainControlImpl() {} 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) { 56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!is_component_enabled()) { 57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNoError; 58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(audio->samples_per_split_channel() <= 160); 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int i = 0; i < num_handles(); i++) { 63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Handle* my_handle = static_cast<Handle*>(handle(i)); 64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int err = WebRtcAgc_AddFarend( 65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org my_handle, 66eb15100c9bdb4c97ffda2c05a934aab270795c27aluebs@webrtc.org audio->mixed_low_pass_data(), 673f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org static_cast<int16_t>(audio->samples_per_split_channel())); 68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err != apm_->kNoError) { 70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return GetHandleError(my_handle); 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNoError; 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) { 78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!is_component_enabled()) { 79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNoError; 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(audio->samples_per_split_channel() <= 160); 83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(audio->num_channels() == num_handles()); 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int err = apm_->kNoError; 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (mode_ == kAdaptiveAnalog) { 88e95dc25b14845cbf00ae363e88459c44e2341c47andrew@webrtc.org capture_levels_.assign(num_handles(), analog_capture_level_); 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int i = 0; i < num_handles(); i++) { 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Handle* my_handle = static_cast<Handle*>(handle(i)); 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org err = WebRtcAgc_AddMic( 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org my_handle, 93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org audio->low_pass_split_data(i), 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org audio->high_pass_split_data(i), 953f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org static_cast<int16_t>(audio->samples_per_split_channel())); 96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err != apm_->kNoError) { 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return GetHandleError(my_handle); 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else if (mode_ == kAdaptiveDigital) { 102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int i = 0; i < num_handles(); i++) { 104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Handle* my_handle = static_cast<Handle*>(handle(i)); 1053f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int32_t capture_level_out = 0; 106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org err = WebRtcAgc_VirtualMic( 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org my_handle, 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org audio->low_pass_split_data(i), 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org audio->high_pass_split_data(i), 1113f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org static_cast<int16_t>(audio->samples_per_split_channel()), 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org analog_capture_level_, 113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &capture_level_out); 114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org capture_levels_[i] = capture_level_out; 116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err != apm_->kNoError) { 118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return GetHandleError(my_handle); 119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNoError; 125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) { 128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!is_component_enabled()) { 129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNoError; 130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) { 133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kStreamParameterNotSetError; 134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(audio->samples_per_split_channel() <= 160); 137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(audio->num_channels() == num_handles()); 138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org stream_is_saturated_ = false; 140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int i = 0; i < num_handles(); i++) { 141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Handle* my_handle = static_cast<Handle*>(handle(i)); 1423f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org int32_t capture_level_out = 0; 1433f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org uint8_t saturation_warning = 0; 144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int err = WebRtcAgc_Process( 146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org my_handle, 147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org audio->low_pass_split_data(i), 148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org audio->high_pass_split_data(i), 1493f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org static_cast<int16_t>(audio->samples_per_split_channel()), 150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org audio->low_pass_split_data(i), 151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org audio->high_pass_split_data(i), 152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org capture_levels_[i], 153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &capture_level_out, 154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org apm_->echo_cancellation()->stream_has_echo(), 155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &saturation_warning); 156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err != apm_->kNoError) { 158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return GetHandleError(my_handle); 159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org capture_levels_[i] = capture_level_out; 162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (saturation_warning == 1) { 163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org stream_is_saturated_ = true; 164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (mode_ == kAdaptiveAnalog) { 168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Take the analog level to be the average across the handles. 169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org analog_capture_level_ = 0; 170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int i = 0; i < num_handles(); i++) { 171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org analog_capture_level_ += capture_levels_[i]; 172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org analog_capture_level_ /= num_handles(); 175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org was_analog_level_set_ = false; 178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNoError; 179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// TODO(ajm): ensure this is called under kAdaptiveAnalog. 182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::set_stream_analog_level(int level) { 183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org was_analog_level_set_ = true; 184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (level < minimum_capture_level_ || level > maximum_capture_level_) { 185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kBadParameterError; 186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org analog_capture_level_ = level; 188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNoError; 190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::stream_analog_level() { 193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(ajm): enable this assertion? 194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org //assert(mode_ == kAdaptiveAnalog); 195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return analog_capture_level_; 197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::Enable(bool enable) { 200a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org CriticalSectionScoped crit_scoped(crit_); 201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return EnableComponent(enable); 202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool GainControlImpl::is_enabled() const { 205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return is_component_enabled(); 206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::set_mode(Mode mode) { 209a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org CriticalSectionScoped crit_scoped(crit_); 210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (MapSetting(mode) == -1) { 211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kBadParameterError; 212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org mode_ = mode; 215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return Initialize(); 216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgGainControl::Mode GainControlImpl::mode() const { 219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return mode_; 220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::set_analog_level_limits(int minimum, 223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int maximum) { 224a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org CriticalSectionScoped crit_scoped(crit_); 225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (minimum < 0) { 226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kBadParameterError; 227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (maximum > 65535) { 230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kBadParameterError; 231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (maximum < minimum) { 234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kBadParameterError; 235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org minimum_capture_level_ = minimum; 238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org maximum_capture_level_ = maximum; 239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return Initialize(); 241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::analog_level_minimum() const { 244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return minimum_capture_level_; 245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::analog_level_maximum() const { 248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return maximum_capture_level_; 249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool GainControlImpl::stream_is_saturated() const { 252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return stream_is_saturated_; 253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::set_target_level_dbfs(int level) { 256a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org CriticalSectionScoped crit_scoped(crit_); 257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (level > 31 || level < 0) { 258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kBadParameterError; 259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org target_level_dbfs_ = level; 262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return Configure(); 263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::target_level_dbfs() const { 266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return target_level_dbfs_; 267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::set_compression_gain_db(int gain) { 270a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org CriticalSectionScoped crit_scoped(crit_); 271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (gain < 0 || gain > 90) { 272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kBadParameterError; 273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org compression_gain_db_ = gain; 276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return Configure(); 277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::compression_gain_db() const { 280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return compression_gain_db_; 281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::enable_limiter(bool enable) { 284a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org CriticalSectionScoped crit_scoped(crit_); 285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org limiter_enabled_ = enable; 286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return Configure(); 287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool GainControlImpl::is_limiter_enabled() const { 290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return limiter_enabled_; 291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::Initialize() { 294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int err = ProcessingComponent::Initialize(); 295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err != apm_->kNoError || !is_component_enabled()) { 296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return err; 297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 29948b9892684682b60b8c4fbc01f1998ace1d32663andrew@webrtc.org capture_levels_.assign(num_handles(), analog_capture_level_); 300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNoError; 301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid* GainControlImpl::CreateHandle() const { 304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Handle* handle = NULL; 305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (WebRtcAgc_Create(&handle) != apm_->kNoError) { 306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org handle = NULL; 307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else { 308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(handle != NULL); 309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return handle; 312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 314ffc2de0133683fb103eef61f21134f469bc099dbbjornv@webrtc.orgvoid GainControlImpl::DestroyHandle(void* handle) const { 315ffc2de0133683fb103eef61f21134f469bc099dbbjornv@webrtc.org WebRtcAgc_Free(static_cast<Handle*>(handle)); 316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::InitializeHandle(void* handle) const { 319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return WebRtcAgc_Init(static_cast<Handle*>(handle), 320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org minimum_capture_level_, 321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org maximum_capture_level_, 322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org MapSetting(mode_), 323467f7567c8befea153861e09f048f69932d6e3bdandrew@webrtc.org apm_->proc_sample_rate_hz()); 324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::ConfigureHandle(void* handle) const { 327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WebRtcAgc_config_t config; 328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we 329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // change the interface. 330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org //assert(target_level_dbfs_ <= 0); 3313f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org //config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_); 3323f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_); 333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org config.compressionGaindB = 3343f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org static_cast<int16_t>(compression_gain_db_); 335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org config.limiterEnable = limiter_enabled_; 336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return WebRtcAgc_set_config(static_cast<Handle*>(handle), config); 338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::num_handles_required() const { 341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->num_output_channels(); 342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::GetHandleError(void* handle) const { 345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The AGC has no get_error() function. 346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // (Despite listing errors in its interface...) 347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(handle != NULL); 348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kUnspecifiedError; 349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} // namespace webrtc 351