Chromium Code Reviews| Index: webrtc/modules/audio_processing/gain_control_impl.cc |
| diff --git a/webrtc/modules/audio_processing/gain_control_impl.cc b/webrtc/modules/audio_processing/gain_control_impl.cc |
| index 8a3612dce5a7b7ea9c2b5a6c128329a3168b2da9..7205bf1934e9c504b828bdb7786f338d9fc62f7a 100644 |
| --- a/webrtc/modules/audio_processing/gain_control_impl.cc |
| +++ b/webrtc/modules/audio_processing/gain_control_impl.cc |
| @@ -35,20 +35,26 @@ int16_t MapSetting(GainControl::Mode mode) { |
| } |
| } // namespace |
| +const size_t GainControlImpl::kAllowedValuesOfSamplesPerFrame1; |
| +const size_t GainControlImpl::kAllowedValuesOfSamplesPerFrame2; |
| + |
| GainControlImpl::GainControlImpl(const AudioProcessing* apm, |
| CriticalSectionWrapper* crit) |
| - : ProcessingComponent(), |
| - apm_(apm), |
| - crit_(crit), |
| - mode_(kAdaptiveAnalog), |
| - minimum_capture_level_(0), |
| - maximum_capture_level_(255), |
| - limiter_enabled_(true), |
| - target_level_dbfs_(3), |
| - compression_gain_db_(9), |
| - analog_capture_level_(0), |
| - was_analog_level_set_(false), |
| - stream_is_saturated_(false) {} |
| + : ProcessingComponent(), |
| + apm_(apm), |
| + crit_(crit), |
| + mode_(kAdaptiveAnalog), |
| + minimum_capture_level_(0), |
| + maximum_capture_level_(255), |
| + limiter_enabled_(true), |
| + target_level_dbfs_(3), |
| + compression_gain_db_(9), |
| + analog_capture_level_(0), |
| + was_analog_level_set_(false), |
| + stream_is_saturated_(false), |
| + render_queue_element_max_size_(0) { |
| + AllocateRenderQueue(); |
| +} |
| GainControlImpl::~GainControlImpl() {} |
| @@ -59,21 +65,55 @@ int GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) { |
| assert(audio->num_frames_per_band() <= 160); |
| + int buffer_index = 0; |
| for (int i = 0; i < num_handles(); i++) { |
| Handle* my_handle = static_cast<Handle*>(handle(i)); |
| - int err = WebRtcAgc_AddFarend( |
| - my_handle, |
| - audio->mixed_low_pass_data(), |
| - audio->num_frames_per_band()); |
| + int err = |
| + WebRtcAgc_GetAddFarendError(my_handle, audio->num_frames_per_band()); |
| - if (err != apm_->kNoError) { |
| + if (err != apm_->kNoError) |
| return GetHandleError(my_handle); |
| - } |
| + |
| + // Buffer the samples in the render queue. |
| + RTC_DCHECK((buffer_index + audio->num_frames_per_band()) <= |
| + render_queue_element_max_size_); |
| + |
| + memcpy(&render_queue_buffer_[buffer_index], audio->mixed_low_pass_data(), |
| + (audio->num_frames_per_band() * |
| + sizeof(audio->mixed_low_pass_data()[0]))); |
| + |
| + buffer_index += audio->num_frames_per_band(); |
| } |
| + render_queue_buffer_.resize(buffer_index); |
| + render_signal_queue_->Insert(&render_queue_buffer_); |
| + |
| return apm_->kNoError; |
| } |
| +// Read chunks of data that were received and queued on the render side from |
| +// a queue. All the data chunks are buffered into the farend signal of the AGC. |
| +void GainControlImpl::ReadQueuedRenderData() { |
|
the sun
2015/10/27 16:42:49
Why do you need this extra function? Why not pop t
peah-webrtc
2015/10/29 14:05:23
Not fully sure what you mean? Do you mean that it
|
| + if (!is_component_enabled()) { |
| + return; |
| + } |
| + |
| + bool samples_read = render_signal_queue_->Remove(&capture_queue_buffer_); |
| + while (samples_read) { |
| + int buffer_index = 0; |
| + const int num_frames_per_band = |
| + capture_queue_buffer_.size() / num_handles(); |
| + for (int i = 0; i < num_handles(); i++) { |
| + Handle* my_handle = static_cast<Handle*>(handle(i)); |
| + (void)WebRtcAgc_AddFarend(my_handle, &capture_queue_buffer_[buffer_index], |
| + num_frames_per_band); |
| + |
| + buffer_index += num_frames_per_band; |
| + } |
| + samples_read = render_signal_queue_->Remove(&capture_queue_buffer_); |
| + } |
| +} |
| + |
| int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) { |
| if (!is_component_enabled()) { |
| return apm_->kNoError; |
| @@ -179,6 +219,12 @@ int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) { |
| // TODO(ajm): ensure this is called under kAdaptiveAnalog. |
| int GainControlImpl::set_stream_analog_level(int level) { |
| + // TODO(peah): Verify that this is really needed to do the reading. |
| + // here as well as in ProcessStream. It works since these functions |
| + // are called from the same thread, but it is not nice to do it in two |
| + // places if not needed. |
| + ReadQueuedRenderData(); |
| + |
| CriticalSectionScoped crit_scoped(crit_); |
| was_analog_level_set_ = true; |
| if (level < minimum_capture_level_ || level > maximum_capture_level_) { |
| @@ -296,10 +342,37 @@ int GainControlImpl::Initialize() { |
| return err; |
| } |
| + AllocateRenderQueue(); |
| + |
| capture_levels_.assign(num_handles(), analog_capture_level_); |
| return apm_->kNoError; |
| } |
| +void GainControlImpl::AllocateRenderQueue() { |
| + const size_t max_frame_size = std::max(kAllowedValuesOfSamplesPerFrame1, |
| + kAllowedValuesOfSamplesPerFrame2); |
| + const size_t min_frame_size = std::min(kAllowedValuesOfSamplesPerFrame1, |
| + kAllowedValuesOfSamplesPerFrame2); |
| + |
| + render_queue_element_max_size_ = |
| + (max_frame_size * num_handles()); |
| + |
| + const size_t render_queue_element_min_size = |
| + (min_frame_size * num_handles()); |
| + |
| + std::vector<int16_t> template_queue_element(render_queue_element_max_size_); |
| + |
| + render_signal_queue_.reset( |
| + new SwapQueue<std::vector<int16_t>, AgcRenderQueueItemVerifier>( |
| + kMaxNumFramesToBuffer, |
| + AgcRenderQueueItemVerifier(render_queue_element_min_size, |
| + render_queue_element_max_size_), |
| + template_queue_element)); |
| + |
| + render_queue_buffer_.resize(render_queue_element_max_size_); |
| + capture_queue_buffer_.resize(render_queue_element_max_size_); |
| +} |
| + |
| void* GainControlImpl::CreateHandle() const { |
| return WebRtcAgc_Create(); |
| } |