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