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 { 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 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 69 GainControlImpl::~GainControlImpl() {} 70 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 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 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. 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 221 int GainControlImpl::stream_analog_level() { 222 // TODO(ajm): enable this assertion? 223 //assert(mode_ == kAdaptiveAnalog); 224 225 return analog_capture_level_; 226 } 227 228 int GainControlImpl::Enable(bool enable) { 229 CriticalSectionScoped crit_scoped(*apm_->crit()); 230 return EnableComponent(enable); 231 } 232 233 bool GainControlImpl::is_enabled() const { 234 return is_component_enabled(); 235 } 236 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 247 GainControl::Mode GainControlImpl::mode() const { 248 return mode_; 249 } 250 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 272 int GainControlImpl::analog_level_minimum() const { 273 return minimum_capture_level_; 274 } 275 276 int GainControlImpl::analog_level_maximum() const { 277 return maximum_capture_level_; 278 } 279 280 bool GainControlImpl::stream_is_saturated() const { 281 return stream_is_saturated_; 282 } 283 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 294 int GainControlImpl::target_level_dbfs() const { 295 return target_level_dbfs_; 296 } 297 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 308 int GainControlImpl::compression_gain_db() const { 309 return compression_gain_db_; 310 } 311 312 int GainControlImpl::enable_limiter(bool enable) { 313 CriticalSectionScoped crit_scoped(*apm_->crit()); 314 limiter_enabled_ = enable; 315 return Configure(); 316 } 317 318 bool GainControlImpl::is_limiter_enabled() const { 319 return limiter_enabled_; 320 } 321 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 336 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 344 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 355 int GainControlImpl::DestroyHandle(void* handle) const { 356 return WebRtcAgc_Free(static_cast<Handle*>(handle)); 357 } 358 359 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 367 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 381 int GainControlImpl::num_handles_required() const { 382 return apm_->num_output_channels(); 383 } 384 385 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