| 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 d0161e0b4644fa91911b338835e915e5aa6f7d11..7068df27d9d7e3dd498529faa9ab43fe17b9a7ba 100644
|
| --- a/webrtc/modules/audio_processing/echo_control_mobile_impl.cc
|
| +++ b/webrtc/modules/audio_processing/echo_control_mobile_impl.cc
|
| @@ -40,6 +40,22 @@ int16_t MapSetting(EchoControlMobile::RoutingMode mode) {
|
| return -1;
|
| }
|
|
|
| +AudioProcessing::Error MapError(int err) {
|
| + switch (err) {
|
| + case AECM_UNSUPPORTED_FUNCTION_ERROR:
|
| + return AudioProcessing::kUnsupportedFunctionError;
|
| + case AECM_NULL_POINTER_ERROR:
|
| + return AudioProcessing::kNullPointerError;
|
| + case AECM_BAD_PARAMETER_ERROR:
|
| + return AudioProcessing::kBadParameterError;
|
| + case AECM_BAD_PARAMETER_WARNING:
|
| + return AudioProcessing::kBadStreamParameterWarning;
|
| + default:
|
| + // AECM_UNSPECIFIED_ERROR
|
| + // AECM_UNINITIALIZED_ERROR
|
| + return AudioProcessing::kUnspecifiedError;
|
| + }
|
| +}
|
| } // namespace
|
|
|
| size_t EchoControlMobile::echo_path_size_bytes() {
|
| @@ -48,12 +64,21 @@ size_t EchoControlMobile::echo_path_size_bytes() {
|
|
|
| EchoControlMobileImpl::EchoControlMobileImpl(const AudioProcessing* apm,
|
| CriticalSectionWrapper* crit)
|
| - : ProcessingComponent(),
|
| - apm_(apm),
|
| - crit_(crit),
|
| - routing_mode_(kSpeakerphone),
|
| - comfort_noise_enabled_(true),
|
| - external_echo_path_(NULL) {}
|
| + : ProcessingComponent(),
|
| + apm_(apm),
|
| + crit_(crit),
|
| + routing_mode_(kSpeakerphone),
|
| + comfort_noise_enabled_(true),
|
| + external_echo_path_(NULL),
|
| + render_queue_buffer_(kMaxNumSamplesPerFrameToBuffer),
|
| + capture_queue_buffer_(kMaxNumSamplesPerFrameToBuffer) {
|
| + std::vector<int16_t> template_queue_element(kMaxNumSamplesPerFrameToBuffer);
|
| +
|
| + render_signal_queue_.reset(
|
| + new SwapQueue<std::vector<int16_t>, &RenderQueueItemVerifier>(
|
| + (kMaxNumFramesToBuffer * kMaxNumChannelsPerFrameToBuffer),
|
| + template_queue_element));
|
| +}
|
|
|
| EchoControlMobileImpl::~EchoControlMobileImpl() {
|
| if (external_echo_path_ != NULL) {
|
| @@ -77,14 +102,25 @@ int EchoControlMobileImpl::ProcessRenderAudio(const AudioBuffer* audio) {
|
| for (int i = 0; i < apm_->num_output_channels(); i++) {
|
| for (int j = 0; j < audio->num_channels(); j++) {
|
| Handle* my_handle = static_cast<Handle*>(handle(handle_index));
|
| - err = WebRtcAecm_BufferFarend(
|
| - my_handle,
|
| - audio->split_bands_const(j)[kBand0To8kHz],
|
| + err = WebRtcAecm_GetBufferFarendError(
|
| + my_handle, audio->split_bands_const(j)[kBand0To8kHz],
|
| audio->num_frames_per_band());
|
|
|
| - if (err != apm_->kNoError) {
|
| - return GetHandleError(my_handle); // TODO(ajm): warning possible?
|
| - }
|
| + if (err != apm_->kNoError)
|
| + return MapError(err); // TODO(ajm): warning possible?);
|
| +
|
| + // Buffer the samples in the render queue.
|
| + // TODO(peah): Do a proper size check agains the actual sample size
|
| + // once the APM properly checks the sample type passed to AECM.
|
| + memcpy(&render_queue_buffer_[0],
|
| + audio->split_bands_const_f(j)[kBand0To8kHz],
|
| + (audio->num_frames_per_band() * sizeof(int16_t)));
|
| + render_queue_buffer_.resize(audio->num_frames_per_band());
|
| + // TODO(peah): Refactor so that it is possible to check the
|
| + // return value of Insert. Currently, that is not possible
|
| + // due to the code design when the capture thread is never
|
| + // started.
|
| + render_signal_queue_->Insert(&render_queue_buffer_);
|
|
|
| handle_index++;
|
| }
|
| @@ -93,6 +129,25 @@ int EchoControlMobileImpl::ProcessRenderAudio(const AudioBuffer* audio) {
|
| 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 AEC.
|
| +void EchoControlMobileImpl::ReadQueuedRenderData() {
|
| + if (!is_component_enabled()) {
|
| + return;
|
| + }
|
| +
|
| + while (render_signal_queue_->Remove(&capture_queue_buffer_)) {
|
| + size_t handle_index = 0;
|
| + for (int i = 0; i < apm_->num_output_channels(); i++) {
|
| + for (int j = 0; j < apm_->num_reverse_channels(); j++) {
|
| + Handle* my_handle = static_cast<Handle*>(handle(handle_index));
|
| + (void)WebRtcAecm_BufferFarend(my_handle, &capture_queue_buffer_[0],
|
| + capture_queue_buffer_.size());
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| int EchoControlMobileImpl::ProcessCaptureAudio(AudioBuffer* audio) {
|
| if (!is_component_enabled()) {
|
| return apm_->kNoError;
|
| @@ -128,9 +183,8 @@ int EchoControlMobileImpl::ProcessCaptureAudio(AudioBuffer* audio) {
|
| audio->num_frames_per_band(),
|
| apm_->stream_delay_ms());
|
|
|
| - if (err != apm_->kNoError) {
|
| - return GetHandleError(my_handle); // TODO(ajm): warning possible?
|
| - }
|
| + if (err != apm_->kNoError)
|
| + return MapError(err);
|
|
|
| handle_index++;
|
| }
|
| @@ -213,9 +267,9 @@ int EchoControlMobileImpl::GetEchoPath(void* echo_path,
|
|
|
| // Get the echo path from the first channel
|
| Handle* my_handle = static_cast<Handle*>(handle(0));
|
| - if (WebRtcAecm_GetEchoPath(my_handle, echo_path, size_bytes) != 0) {
|
| - return GetHandleError(my_handle);
|
| - }
|
| + int32_t err = WebRtcAecm_GetEchoPath(my_handle, echo_path, size_bytes);
|
| + if (err != 0)
|
| + return MapError(err);
|
|
|
| return apm_->kNoError;
|
| }
|
| @@ -225,6 +279,8 @@ int EchoControlMobileImpl::Initialize() {
|
| return apm_->kNoError;
|
| }
|
|
|
| + render_signal_queue_->Clear();
|
| +
|
| if (apm_->proc_sample_rate_hz() > apm_->kSampleRate16kHz) {
|
| LOG(LS_ERROR) << "AECM only supports 16 kHz or lower sample rates";
|
| return apm_->kBadSampleRateError;
|
| @@ -275,4 +331,11 @@ int EchoControlMobileImpl::GetHandleError(void* handle) const {
|
| assert(handle != NULL);
|
| return AudioProcessing::kUnspecifiedError;
|
| }
|
| +
|
| +bool EchoControlMobileImpl::RenderQueueItemVerifier(
|
| + const std::vector<int16_t>& v) {
|
| + return ((v.size() == kMinNumSamplesPerFrameToBuffer) ||
|
| + (v.size() == kMaxNumSamplesPerFrameToBuffer));
|
| +}
|
| +
|
| } // namespace webrtc
|
|
|