| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 return kAgcModeAdaptiveAnalog; | 26 return kAgcModeAdaptiveAnalog; |
| 27 case GainControl::kAdaptiveDigital: | 27 case GainControl::kAdaptiveDigital: |
| 28 return kAgcModeAdaptiveDigital; | 28 return kAgcModeAdaptiveDigital; |
| 29 case GainControl::kFixedDigital: | 29 case GainControl::kFixedDigital: |
| 30 return kAgcModeFixedDigital; | 30 return kAgcModeFixedDigital; |
| 31 } | 31 } |
| 32 RTC_DCHECK(false); | 32 RTC_DCHECK(false); |
| 33 return -1; | 33 return -1; |
| 34 } | 34 } |
| 35 | 35 |
| 36 // Maximum length that a frame of samples can have. | |
| 37 static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160; | |
| 38 // Maximum number of frames to buffer in the render queue. | |
| 39 // TODO(peah): Decrease this once we properly handle hugely unbalanced | |
| 40 // reverse and forward call numbers. | |
| 41 static const size_t kMaxNumFramesToBuffer = 100; | |
| 42 | |
| 43 } // namespace | 36 } // namespace |
| 44 | 37 |
| 45 class GainControlImpl::GainController { | 38 class GainControlImpl::GainController { |
| 46 public: | 39 public: |
| 47 explicit GainController() { | 40 explicit GainController() { |
| 48 state_ = WebRtcAgc_Create(); | 41 state_ = WebRtcAgc_Create(); |
| 49 RTC_CHECK(state_); | 42 RTC_CHECK(state_); |
| 50 } | 43 } |
| 51 | 44 |
| 52 ~GainController() { | 45 ~GainController() { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 : crit_render_(crit_render), | 89 : crit_render_(crit_render), |
| 97 crit_capture_(crit_capture), | 90 crit_capture_(crit_capture), |
| 98 mode_(kAdaptiveAnalog), | 91 mode_(kAdaptiveAnalog), |
| 99 minimum_capture_level_(0), | 92 minimum_capture_level_(0), |
| 100 maximum_capture_level_(255), | 93 maximum_capture_level_(255), |
| 101 limiter_enabled_(true), | 94 limiter_enabled_(true), |
| 102 target_level_dbfs_(3), | 95 target_level_dbfs_(3), |
| 103 compression_gain_db_(9), | 96 compression_gain_db_(9), |
| 104 analog_capture_level_(0), | 97 analog_capture_level_(0), |
| 105 was_analog_level_set_(false), | 98 was_analog_level_set_(false), |
| 106 stream_is_saturated_(false), | 99 stream_is_saturated_(false) { |
| 107 render_queue_element_max_size_(0) { | |
| 108 RTC_DCHECK(crit_render); | 100 RTC_DCHECK(crit_render); |
| 109 RTC_DCHECK(crit_capture); | 101 RTC_DCHECK(crit_capture); |
| 110 } | 102 } |
| 111 | 103 |
| 112 GainControlImpl::~GainControlImpl() {} | 104 GainControlImpl::~GainControlImpl() {} |
| 113 | 105 |
| 114 int GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) { | 106 void GainControlImpl::ProcessRenderAudio( |
| 115 rtc::CritScope cs(crit_render_); | 107 rtc::ArrayView<const int16_t> packed_render_audio) { |
| 116 if (!enabled_) { | 108 rtc::CritScope cs_capture(crit_capture_); |
| 117 return AudioProcessing::kNoError; | |
| 118 } | |
| 119 | |
| 120 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); | |
| 121 | |
| 122 render_queue_buffer_.resize(0); | |
| 123 for (auto& gain_controller : gain_controllers_) { | |
| 124 int err = WebRtcAgc_GetAddFarendError(gain_controller->state(), | |
| 125 audio->num_frames_per_band()); | |
| 126 | |
| 127 if (err != AudioProcessing::kNoError) { | |
| 128 return AudioProcessing::kUnspecifiedError; | |
| 129 } | |
| 130 | |
| 131 // Buffer the samples in the render queue. | |
| 132 render_queue_buffer_.insert( | |
| 133 render_queue_buffer_.end(), audio->mixed_low_pass_data(), | |
| 134 (audio->mixed_low_pass_data() + audio->num_frames_per_band())); | |
| 135 } | |
| 136 | |
| 137 // Insert the samples into the queue. | |
| 138 if (!render_signal_queue_->Insert(&render_queue_buffer_)) { | |
| 139 // The data queue is full and needs to be emptied. | |
| 140 ReadQueuedRenderData(); | |
| 141 | |
| 142 // Retry the insert (should always work). | |
| 143 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true); | |
| 144 } | |
| 145 | |
| 146 return AudioProcessing::kNoError; | |
| 147 } | |
| 148 | |
| 149 // Read chunks of data that were received and queued on the render side from | |
| 150 // a queue. All the data chunks are buffered into the farend signal of the AGC. | |
| 151 void GainControlImpl::ReadQueuedRenderData() { | |
| 152 rtc::CritScope cs(crit_capture_); | |
| 153 | |
| 154 if (!enabled_) { | 109 if (!enabled_) { |
| 155 return; | 110 return; |
| 156 } | 111 } |
| 157 | 112 |
| 158 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { | 113 for (auto& gain_controller : gain_controllers_) { |
| 159 size_t buffer_index = 0; | 114 WebRtcAgc_AddFarend(gain_controller->state(), packed_render_audio.data(), |
| 160 RTC_DCHECK(num_proc_channels_); | 115 packed_render_audio.size()); |
| 161 RTC_DCHECK_LT(0ul, *num_proc_channels_); | |
| 162 const size_t num_frames_per_band = | |
| 163 capture_queue_buffer_.size() / (*num_proc_channels_); | |
| 164 for (auto& gain_controller : gain_controllers_) { | |
| 165 WebRtcAgc_AddFarend(gain_controller->state(), | |
| 166 &capture_queue_buffer_[buffer_index], | |
| 167 num_frames_per_band); | |
| 168 | |
| 169 buffer_index += num_frames_per_band; | |
| 170 } | |
| 171 } | 116 } |
| 172 } | 117 } |
| 173 | 118 |
| 119 void GainControlImpl::PackRenderAudioBuffer( |
| 120 AudioBuffer* audio, |
| 121 std::vector<int16_t>* packed_buffer) { |
| 122 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
| 123 |
| 124 packed_buffer->clear(); |
| 125 packed_buffer->insert( |
| 126 packed_buffer->end(), audio->mixed_low_pass_data(), |
| 127 (audio->mixed_low_pass_data() + audio->num_frames_per_band())); |
| 128 } |
| 129 |
| 174 int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) { | 130 int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) { |
| 175 rtc::CritScope cs(crit_capture_); | 131 rtc::CritScope cs(crit_capture_); |
| 176 | 132 |
| 177 if (!enabled_) { | 133 if (!enabled_) { |
| 178 return AudioProcessing::kNoError; | 134 return AudioProcessing::kNoError; |
| 179 } | 135 } |
| 180 | 136 |
| 181 RTC_DCHECK(num_proc_channels_); | 137 RTC_DCHECK(num_proc_channels_); |
| 182 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); | 138 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
| 183 RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_); | 139 RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_); |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 gain_controllers_.resize(*num_proc_channels_); | 396 gain_controllers_.resize(*num_proc_channels_); |
| 441 for (auto& gain_controller : gain_controllers_) { | 397 for (auto& gain_controller : gain_controllers_) { |
| 442 if (!gain_controller) { | 398 if (!gain_controller) { |
| 443 gain_controller.reset(new GainController()); | 399 gain_controller.reset(new GainController()); |
| 444 } | 400 } |
| 445 gain_controller->Initialize(minimum_capture_level_, maximum_capture_level_, | 401 gain_controller->Initialize(minimum_capture_level_, maximum_capture_level_, |
| 446 mode_, *sample_rate_hz_, analog_capture_level_); | 402 mode_, *sample_rate_hz_, analog_capture_level_); |
| 447 } | 403 } |
| 448 | 404 |
| 449 Configure(); | 405 Configure(); |
| 450 | |
| 451 AllocateRenderQueue(); | |
| 452 } | |
| 453 | |
| 454 void GainControlImpl::AllocateRenderQueue() { | |
| 455 rtc::CritScope cs_render(crit_render_); | |
| 456 rtc::CritScope cs_capture(crit_capture_); | |
| 457 | |
| 458 RTC_DCHECK(num_proc_channels_); | |
| 459 const size_t new_render_queue_element_max_size = std::max<size_t>( | |
| 460 static_cast<size_t>(1), | |
| 461 kMaxAllowedValuesOfSamplesPerFrame * (*num_proc_channels_)); | |
| 462 | |
| 463 if (render_queue_element_max_size_ < new_render_queue_element_max_size) { | |
| 464 render_queue_element_max_size_ = new_render_queue_element_max_size; | |
| 465 std::vector<int16_t> template_queue_element(render_queue_element_max_size_); | |
| 466 | |
| 467 render_signal_queue_.reset( | |
| 468 new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>( | |
| 469 kMaxNumFramesToBuffer, template_queue_element, | |
| 470 RenderQueueItemVerifier<int16_t>(render_queue_element_max_size_))); | |
| 471 | |
| 472 render_queue_buffer_.resize(render_queue_element_max_size_); | |
| 473 capture_queue_buffer_.resize(render_queue_element_max_size_); | |
| 474 } else { | |
| 475 render_signal_queue_->Clear(); | |
| 476 } | |
| 477 } | 406 } |
| 478 | 407 |
| 479 int GainControlImpl::Configure() { | 408 int GainControlImpl::Configure() { |
| 480 rtc::CritScope cs_render(crit_render_); | 409 rtc::CritScope cs_render(crit_render_); |
| 481 rtc::CritScope cs_capture(crit_capture_); | 410 rtc::CritScope cs_capture(crit_capture_); |
| 482 WebRtcAgcConfig config; | 411 WebRtcAgcConfig config; |
| 483 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we | 412 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we |
| 484 // change the interface. | 413 // change the interface. |
| 485 //RTC_DCHECK_LE(target_level_dbfs_, 0); | 414 //RTC_DCHECK_LE(target_level_dbfs_, 0); |
| 486 //config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_); | 415 //config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_); |
| 487 config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_); | 416 config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_); |
| 488 config.compressionGaindB = | 417 config.compressionGaindB = |
| 489 static_cast<int16_t>(compression_gain_db_); | 418 static_cast<int16_t>(compression_gain_db_); |
| 490 config.limiterEnable = limiter_enabled_; | 419 config.limiterEnable = limiter_enabled_; |
| 491 | 420 |
| 492 int error = AudioProcessing::kNoError; | 421 int error = AudioProcessing::kNoError; |
| 493 for (auto& gain_controller : gain_controllers_) { | 422 for (auto& gain_controller : gain_controllers_) { |
| 494 const int handle_error = | 423 const int handle_error = |
| 495 WebRtcAgc_set_config(gain_controller->state(), config); | 424 WebRtcAgc_set_config(gain_controller->state(), config); |
| 496 if (handle_error != AudioProcessing::kNoError) { | 425 if (handle_error != AudioProcessing::kNoError) { |
| 497 error = handle_error; | 426 error = handle_error; |
| 498 } | 427 } |
| 499 } | 428 } |
| 500 return error; | 429 return error; |
| 501 } | 430 } |
| 502 } // namespace webrtc | 431 } // namespace webrtc |
| OLD | NEW |