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