| Index: webrtc/modules/audio_processing/echo_control_mobile_impl.cc
|
| diff --git a/webrtc/modules/audio_processing/echo_control_mobile_impl.cc b/webrtc/modules/audio_processing/echo_control_mobile_impl.cc
|
| index 0c62648e70015249214ae3a463aec6ae8d45bac0..cfc42498043551ac9f4b505e12a8b1f577b960d0 100644
|
| --- a/webrtc/modules/audio_processing/echo_control_mobile_impl.cc
|
| +++ b/webrtc/modules/audio_processing/echo_control_mobile_impl.cc
|
| @@ -53,12 +53,6 @@ AudioProcessing::Error MapError(int err) {
|
| return AudioProcessing::kUnspecifiedError;
|
| }
|
| }
|
| -// Maximum length that a frame of samples can have.
|
| -static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160;
|
| -// Maximum number of frames to buffer in the render queue.
|
| -// TODO(peah): Decrease this once we properly handle hugely unbalanced
|
| -// reverse and forward call numbers.
|
| -static const size_t kMaxNumFramesToBuffer = 100;
|
| } // namespace
|
|
|
| size_t EchoControlMobile::echo_path_size_bytes() {
|
| @@ -120,8 +114,7 @@ EchoControlMobileImpl::EchoControlMobileImpl(rtc::CriticalSection* crit_render,
|
| crit_capture_(crit_capture),
|
| routing_mode_(kSpeakerphone),
|
| comfort_noise_enabled_(true),
|
| - external_echo_path_(NULL),
|
| - render_queue_element_max_size_(0) {
|
| + external_echo_path_(NULL) {
|
| RTC_DCHECK(crit_render);
|
| RTC_DCHECK(crit_capture);
|
| }
|
| @@ -133,80 +126,59 @@ EchoControlMobileImpl::~EchoControlMobileImpl() {
|
| }
|
| }
|
|
|
| -int EchoControlMobileImpl::ProcessRenderAudio(const AudioBuffer* audio) {
|
| - rtc::CritScope cs_render(crit_render_);
|
| +void EchoControlMobileImpl::ProcessRenderAudio(
|
| + rtc::ArrayView<const int16_t> packed_render_audio) {
|
| + rtc::CritScope cs_capture(crit_capture_);
|
| if (!enabled_) {
|
| - return AudioProcessing::kNoError;
|
| + return;
|
| }
|
|
|
| RTC_DCHECK(stream_properties_);
|
| - RTC_DCHECK_GE(160u, audio->num_frames_per_band());
|
| - RTC_DCHECK_EQ(audio->num_channels(),
|
| - stream_properties_->num_reverse_channels);
|
| - RTC_DCHECK_GE(cancellers_.size(), stream_properties_->num_output_channels *
|
| - audio->num_channels());
|
|
|
| - int err = AudioProcessing::kNoError;
|
| - // The ordering convention must be followed to pass to the correct AECM.
|
| - render_queue_buffer_.clear();
|
| - int render_channel = 0;
|
| - for (auto& canceller : cancellers_) {
|
| - err = WebRtcAecm_GetBufferFarendError(
|
| - canceller->state(),
|
| - audio->split_bands_const(render_channel)[kBand0To8kHz],
|
| - audio->num_frames_per_band());
|
| -
|
| - if (err != AudioProcessing::kNoError)
|
| - return MapError(err); // TODO(ajm): warning possible?);
|
| -
|
| - // Buffer the samples in the render queue.
|
| - render_queue_buffer_.insert(
|
| - render_queue_buffer_.end(),
|
| - audio->split_bands_const(render_channel)[kBand0To8kHz],
|
| - (audio->split_bands_const(render_channel)[kBand0To8kHz] +
|
| - audio->num_frames_per_band()));
|
| - render_channel = (render_channel + 1) % audio->num_channels();
|
| - }
|
| + size_t buffer_index = 0;
|
| + size_t num_frames_per_band =
|
| + packed_render_audio.size() / (stream_properties_->num_output_channels *
|
| + stream_properties_->num_reverse_channels);
|
|
|
| - // Insert the samples into the queue.
|
| - if (!render_signal_queue_->Insert(&render_queue_buffer_)) {
|
| - // The data queue is full and needs to be emptied.
|
| - ReadQueuedRenderData();
|
| + for (auto& canceller : cancellers_) {
|
| + WebRtcAecm_BufferFarend(canceller->state(),
|
| + &packed_render_audio[buffer_index],
|
| + num_frames_per_band);
|
|
|
| - // Retry the insert (should always work).
|
| - bool result = render_signal_queue_->Insert(&render_queue_buffer_);
|
| - RTC_DCHECK(result);
|
| + buffer_index += num_frames_per_band;
|
| }
|
| -
|
| - return AudioProcessing::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 AEC.
|
| -void EchoControlMobileImpl::ReadQueuedRenderData() {
|
| - rtc::CritScope cs_capture(crit_capture_);
|
| - RTC_DCHECK(stream_properties_);
|
| -
|
| - if (!enabled_) {
|
| - return;
|
| - }
|
| -
|
| - while (render_signal_queue_->Remove(&capture_queue_buffer_)) {
|
| - size_t buffer_index = 0;
|
| - size_t num_frames_per_band = capture_queue_buffer_.size() /
|
| - (stream_properties_->num_output_channels *
|
| - stream_properties_->num_reverse_channels);
|
| -
|
| - for (auto& canceller : cancellers_) {
|
| - WebRtcAecm_BufferFarend(canceller->state(),
|
| - &capture_queue_buffer_[buffer_index],
|
| - num_frames_per_band);
|
| +void EchoControlMobileImpl::PackRenderAudioBuffer(
|
| + const AudioBuffer* audio,
|
| + size_t num_output_channels,
|
| + size_t num_channels,
|
| + std::vector<int16_t>* packed_buffer) {
|
| + RTC_DCHECK_GE(160u, audio->num_frames_per_band());
|
| + RTC_DCHECK_EQ(num_channels, audio->num_channels());
|
|
|
| - buffer_index += num_frames_per_band;
|
| + // The ordering convention must be followed to pass to the correct AECM.
|
| + packed_buffer->clear();
|
| + int render_channel = 0;
|
| + for (size_t i = 0; i < num_output_channels; i++) {
|
| + for (size_t j = 0; j < audio->num_channels(); j++) {
|
| + // Buffer the samples in the render queue.
|
| + packed_buffer->insert(
|
| + packed_buffer->end(),
|
| + audio->split_bands_const(render_channel)[kBand0To8kHz],
|
| + (audio->split_bands_const(render_channel)[kBand0To8kHz] +
|
| + audio->num_frames_per_band()));
|
| + render_channel = (render_channel + 1) % audio->num_channels();
|
| }
|
| }
|
| }
|
|
|
| +size_t EchoControlMobileImpl::NumCancellersRequired(
|
| + size_t num_output_channels,
|
| + size_t num_reverse_channels) {
|
| + return num_output_channels * num_reverse_channels;
|
| +}
|
| +
|
| int EchoControlMobileImpl::ProcessCaptureAudio(AudioBuffer* audio,
|
| int stream_delay_ms) {
|
| rtc::CritScope cs_capture(crit_capture_);
|
| @@ -385,7 +357,10 @@ void EchoControlMobileImpl::Initialize(int sample_rate_hz,
|
| LOG(LS_ERROR) << "AECM only supports 16 kHz or lower sample rates";
|
| }
|
|
|
| - cancellers_.resize(num_handles_required());
|
| + cancellers_.resize(
|
| + NumCancellersRequired(stream_properties_->num_output_channels,
|
| + stream_properties_->num_reverse_channels));
|
| +
|
| for (auto& canceller : cancellers_) {
|
| if (!canceller) {
|
| canceller.reset(new Canceller());
|
| @@ -395,35 +370,6 @@ void EchoControlMobileImpl::Initialize(int sample_rate_hz,
|
| }
|
|
|
| Configure();
|
| -
|
| - AllocateRenderQueue();
|
| -}
|
| -
|
| -void EchoControlMobileImpl::AllocateRenderQueue() {
|
| - const size_t new_render_queue_element_max_size = std::max<size_t>(
|
| - static_cast<size_t>(1),
|
| - kMaxAllowedValuesOfSamplesPerFrame * num_handles_required());
|
| -
|
| - rtc::CritScope cs_render(crit_render_);
|
| - rtc::CritScope cs_capture(crit_capture_);
|
| -
|
| - // Reallocate the queue if the queue item size is too small to fit the
|
| - // data to put in the queue.
|
| - if (render_queue_element_max_size_ < new_render_queue_element_max_size) {
|
| - render_queue_element_max_size_ = new_render_queue_element_max_size;
|
| -
|
| - std::vector<int16_t> template_queue_element(render_queue_element_max_size_);
|
| -
|
| - render_signal_queue_.reset(
|
| - new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>(
|
| - kMaxNumFramesToBuffer, template_queue_element,
|
| - RenderQueueItemVerifier<int16_t>(render_queue_element_max_size_)));
|
| -
|
| - render_queue_buffer_.resize(render_queue_element_max_size_);
|
| - capture_queue_buffer_.resize(render_queue_element_max_size_);
|
| - } else {
|
| - render_signal_queue_->Clear();
|
| - }
|
| }
|
|
|
| int EchoControlMobileImpl::Configure() {
|
| @@ -442,9 +388,4 @@ int EchoControlMobileImpl::Configure() {
|
| return error;
|
| }
|
|
|
| -size_t EchoControlMobileImpl::num_handles_required() const {
|
| - RTC_DCHECK(stream_properties_);
|
| - return stream_properties_->num_output_channels *
|
| - stream_properties_->num_reverse_channels;
|
| -}
|
| } // namespace webrtc
|
|
|