1e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* 2e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * 4e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * Use of this source code is governed by a BSD-style license 5e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * that can be found in the LICENSE file in the root of the source 6e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * tree. An additional intellectual property rights grant can be found 7e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * in the file PATENTS. All contributing project authors may 8e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * be found in the AUTHORS file in the root of the source tree. 9e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 10e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 11e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "echo_control_mobile_impl.h" 12e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 13e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <cassert> 14c55a96383497a772a307b346368133960b02ad03Eric Laurent#include <cstring> 15e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 16e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "critical_section_wrapper.h" 17e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "echo_control_mobile.h" 18e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 19e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "audio_processing_impl.h" 20e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "audio_buffer.h" 21e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 22e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentnamespace webrtc { 23e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 24e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurenttypedef void Handle; 25e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 26e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentnamespace { 27e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentWebRtc_Word16 MapSetting(EchoControlMobile::RoutingMode mode) { 28e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent switch (mode) { 29e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent case EchoControlMobile::kQuietEarpieceOrHeadset: 30e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return 0; 31e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent case EchoControlMobile::kEarpiece: 32e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return 1; 33e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent case EchoControlMobile::kLoudEarpiece: 34e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return 2; 35e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent case EchoControlMobile::kSpeakerphone: 36e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return 3; 37e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent case EchoControlMobile::kLoudSpeakerphone: 38e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return 4; 39e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent default: 40e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 41e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 42e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 43e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 44e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint MapError(int err) { 45e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent switch (err) { 46e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent case AECM_UNSUPPORTED_FUNCTION_ERROR: 47e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return AudioProcessing::kUnsupportedFunctionError; 48c55a96383497a772a307b346368133960b02ad03Eric Laurent case AECM_NULL_POINTER_ERROR: 49c55a96383497a772a307b346368133960b02ad03Eric Laurent return AudioProcessing::kNullPointerError; 50e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent case AECM_BAD_PARAMETER_ERROR: 51e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return AudioProcessing::kBadParameterError; 52e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent case AECM_BAD_PARAMETER_WARNING: 53e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return AudioProcessing::kBadStreamParameterWarning; 54e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent default: 55c55a96383497a772a307b346368133960b02ad03Eric Laurent // AECM_UNSPECIFIED_ERROR 56c55a96383497a772a307b346368133960b02ad03Eric Laurent // AECM_UNINITIALIZED_ERROR 57e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return AudioProcessing::kUnspecifiedError; 58e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 59e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 60e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} // namespace 61e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 62c55a96383497a772a307b346368133960b02ad03Eric Laurentsize_t EchoControlMobile::echo_path_size_bytes() { 63c55a96383497a772a307b346368133960b02ad03Eric Laurent return WebRtcAecm_echo_path_size_bytes(); 64c55a96383497a772a307b346368133960b02ad03Eric Laurent} 65c55a96383497a772a307b346368133960b02ad03Eric Laurent 66e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentEchoControlMobileImpl::EchoControlMobileImpl(const AudioProcessingImpl* apm) 67e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent : ProcessingComponent(apm), 68e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent apm_(apm), 69e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent routing_mode_(kSpeakerphone), 70c55a96383497a772a307b346368133960b02ad03Eric Laurent comfort_noise_enabled_(true), 71c55a96383497a772a307b346368133960b02ad03Eric Laurent external_echo_path_(NULL) {} 72e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 73c55a96383497a772a307b346368133960b02ad03Eric LaurentEchoControlMobileImpl::~EchoControlMobileImpl() { 74c55a96383497a772a307b346368133960b02ad03Eric Laurent if (external_echo_path_ != NULL) { 75c55a96383497a772a307b346368133960b02ad03Eric Laurent delete [] external_echo_path_; 76c55a96383497a772a307b346368133960b02ad03Eric Laurent external_echo_path_ = NULL; 77c55a96383497a772a307b346368133960b02ad03Eric Laurent } 78c55a96383497a772a307b346368133960b02ad03Eric Laurent} 79e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 80e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoControlMobileImpl::ProcessRenderAudio(const AudioBuffer* audio) { 81e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (!is_component_enabled()) { 82e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNoError; 83e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 84e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 85e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(audio->samples_per_split_channel() <= 160); 86e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(audio->num_channels() == apm_->num_reverse_channels()); 87e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 88e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent int err = apm_->kNoError; 89e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 90e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // The ordering convention must be followed to pass to the correct AECM. 91e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent size_t handle_index = 0; 92e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (int i = 0; i < apm_->num_output_channels(); i++) { 93e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (int j = 0; j < audio->num_channels(); j++) { 94e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent Handle* my_handle = static_cast<Handle*>(handle(handle_index)); 95e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent err = WebRtcAecm_BufferFarend( 96e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent my_handle, 97e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent audio->low_pass_split_data(j), 98e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent static_cast<WebRtc_Word16>(audio->samples_per_split_channel())); 99e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 100e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (err != apm_->kNoError) { 101e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return GetHandleError(my_handle); // TODO(ajm): warning possible? 102e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 103e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 104e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent handle_index++; 105e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 106e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 107e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 108e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNoError; 109e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 110e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 111e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoControlMobileImpl::ProcessCaptureAudio(AudioBuffer* audio) { 112e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (!is_component_enabled()) { 113e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNoError; 114e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 115e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 116e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (!apm_->was_stream_delay_set()) { 117e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kStreamParameterNotSetError; 118e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 119e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 120e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(audio->samples_per_split_channel() <= 160); 121e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(audio->num_channels() == apm_->num_output_channels()); 122e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 123e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent int err = apm_->kNoError; 124e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 125e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // The ordering convention must be followed to pass to the correct AECM. 126e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent size_t handle_index = 0; 127e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (int i = 0; i < audio->num_channels(); i++) { 128e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // TODO(ajm): improve how this works, possibly inside AECM. 129e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // This is kind of hacked up. 130e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16* noisy = audio->low_pass_reference(i); 131e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16* clean = audio->low_pass_split_data(i); 132e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (noisy == NULL) { 133e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent noisy = clean; 134e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent clean = NULL; 135e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 136e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (int j = 0; j < apm_->num_reverse_channels(); j++) { 137e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent Handle* my_handle = static_cast<Handle*>(handle(handle_index)); 138e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent err = WebRtcAecm_Process( 139e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent my_handle, 140e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent noisy, 141e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent clean, 142e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent audio->low_pass_split_data(i), 143e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent static_cast<WebRtc_Word16>(audio->samples_per_split_channel()), 144e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent apm_->stream_delay_ms()); 145e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 146e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (err != apm_->kNoError) { 147e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return GetHandleError(my_handle); // TODO(ajm): warning possible? 148e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 149e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 150e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent handle_index++; 151e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 152e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 153e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 154e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNoError; 155e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 156e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 157e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoControlMobileImpl::Enable(bool enable) { 158e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent CriticalSectionScoped crit_scoped(*apm_->crit()); 159e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Ensure AEC and AECM are not both enabled. 160e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (enable && apm_->echo_cancellation()->is_enabled()) { 161e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kBadParameterError; 162e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 163e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 164e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return EnableComponent(enable); 165e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 166e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 167e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentbool EchoControlMobileImpl::is_enabled() const { 168e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return is_component_enabled(); 169e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 170e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 171e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoControlMobileImpl::set_routing_mode(RoutingMode mode) { 172e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent CriticalSectionScoped crit_scoped(*apm_->crit()); 173e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (MapSetting(mode) == -1) { 174e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kBadParameterError; 175e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 176e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 177e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent routing_mode_ = mode; 178e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return Configure(); 179e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 180e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 181e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentEchoControlMobile::RoutingMode EchoControlMobileImpl::routing_mode() 182e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent const { 183e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return routing_mode_; 184e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 185e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 186e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoControlMobileImpl::enable_comfort_noise(bool enable) { 187e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent CriticalSectionScoped crit_scoped(*apm_->crit()); 188e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent comfort_noise_enabled_ = enable; 189e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return Configure(); 190e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 191e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 192e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentbool EchoControlMobileImpl::is_comfort_noise_enabled() const { 193e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return comfort_noise_enabled_; 194e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 195e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 196c55a96383497a772a307b346368133960b02ad03Eric Laurentint EchoControlMobileImpl::SetEchoPath(const void* echo_path, 197c55a96383497a772a307b346368133960b02ad03Eric Laurent size_t size_bytes) { 198c55a96383497a772a307b346368133960b02ad03Eric Laurent CriticalSectionScoped crit_scoped(*apm_->crit()); 199c55a96383497a772a307b346368133960b02ad03Eric Laurent if (echo_path == NULL) { 200c55a96383497a772a307b346368133960b02ad03Eric Laurent return apm_->kNullPointerError; 201c55a96383497a772a307b346368133960b02ad03Eric Laurent } 202c55a96383497a772a307b346368133960b02ad03Eric Laurent if (size_bytes != echo_path_size_bytes()) { 203c55a96383497a772a307b346368133960b02ad03Eric Laurent // Size mismatch 204c55a96383497a772a307b346368133960b02ad03Eric Laurent return apm_->kBadParameterError; 205c55a96383497a772a307b346368133960b02ad03Eric Laurent } 206c55a96383497a772a307b346368133960b02ad03Eric Laurent 207c55a96383497a772a307b346368133960b02ad03Eric Laurent if (external_echo_path_ == NULL) { 208c55a96383497a772a307b346368133960b02ad03Eric Laurent external_echo_path_ = new unsigned char[size_bytes]; 209c55a96383497a772a307b346368133960b02ad03Eric Laurent } 210c55a96383497a772a307b346368133960b02ad03Eric Laurent memcpy(external_echo_path_, echo_path, size_bytes); 211c55a96383497a772a307b346368133960b02ad03Eric Laurent 212c55a96383497a772a307b346368133960b02ad03Eric Laurent return Initialize(); 213c55a96383497a772a307b346368133960b02ad03Eric Laurent} 214c55a96383497a772a307b346368133960b02ad03Eric Laurent 215c55a96383497a772a307b346368133960b02ad03Eric Laurentint EchoControlMobileImpl::GetEchoPath(void* echo_path, 216c55a96383497a772a307b346368133960b02ad03Eric Laurent size_t size_bytes) const { 217c55a96383497a772a307b346368133960b02ad03Eric Laurent CriticalSectionScoped crit_scoped(*apm_->crit()); 218c55a96383497a772a307b346368133960b02ad03Eric Laurent if (echo_path == NULL) { 219c55a96383497a772a307b346368133960b02ad03Eric Laurent return apm_->kNullPointerError; 220c55a96383497a772a307b346368133960b02ad03Eric Laurent } 221c55a96383497a772a307b346368133960b02ad03Eric Laurent if (size_bytes != echo_path_size_bytes()) { 222c55a96383497a772a307b346368133960b02ad03Eric Laurent // Size mismatch 223c55a96383497a772a307b346368133960b02ad03Eric Laurent return apm_->kBadParameterError; 224c55a96383497a772a307b346368133960b02ad03Eric Laurent } 225c55a96383497a772a307b346368133960b02ad03Eric Laurent if (!is_component_enabled()) { 226c55a96383497a772a307b346368133960b02ad03Eric Laurent return apm_->kNotEnabledError; 227c55a96383497a772a307b346368133960b02ad03Eric Laurent } 228c55a96383497a772a307b346368133960b02ad03Eric Laurent 229c55a96383497a772a307b346368133960b02ad03Eric Laurent // Get the echo path from the first channel 230c55a96383497a772a307b346368133960b02ad03Eric Laurent Handle* my_handle = static_cast<Handle*>(handle(0)); 231c55a96383497a772a307b346368133960b02ad03Eric Laurent if (WebRtcAecm_GetEchoPath(my_handle, echo_path, size_bytes) != 0) { 232c55a96383497a772a307b346368133960b02ad03Eric Laurent return GetHandleError(my_handle); 233c55a96383497a772a307b346368133960b02ad03Eric Laurent } 234c55a96383497a772a307b346368133960b02ad03Eric Laurent 235c55a96383497a772a307b346368133960b02ad03Eric Laurent return apm_->kNoError; 236c55a96383497a772a307b346368133960b02ad03Eric Laurent} 237c55a96383497a772a307b346368133960b02ad03Eric Laurent 238e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoControlMobileImpl::Initialize() { 239e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (!is_component_enabled()) { 240e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNoError; 241e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 242e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 243e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (apm_->sample_rate_hz() == apm_->kSampleRate32kHz) { 244e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // AECM doesn't support super-wideband. 245e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kBadSampleRateError; 246e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 247e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 248e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return ProcessingComponent::Initialize(); 249e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 250e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 251e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoControlMobileImpl::get_version(char* version, 252e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent int version_len_bytes) const { 253e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (WebRtcAecm_get_version(version, version_len_bytes) != 0) { 254c55a96383497a772a307b346368133960b02ad03Eric Laurent return apm_->kBadParameterError; 255e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 256e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 257e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNoError; 258e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 259e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 260e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid* EchoControlMobileImpl::CreateHandle() const { 261e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent Handle* handle = NULL; 262e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (WebRtcAecm_Create(&handle) != apm_->kNoError) { 263e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent handle = NULL; 264e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else { 265e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(handle != NULL); 266e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 267e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 268e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return handle; 269e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 270e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 271e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoControlMobileImpl::DestroyHandle(void* handle) const { 272e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return WebRtcAecm_Free(static_cast<Handle*>(handle)); 273e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 274e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 275e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoControlMobileImpl::InitializeHandle(void* handle) const { 276c55a96383497a772a307b346368133960b02ad03Eric Laurent assert(handle != NULL); 277c55a96383497a772a307b346368133960b02ad03Eric Laurent Handle* my_handle = static_cast<Handle*>(handle); 278c55a96383497a772a307b346368133960b02ad03Eric Laurent if (WebRtcAecm_Init(my_handle, apm_->sample_rate_hz()) != 0) { 279c55a96383497a772a307b346368133960b02ad03Eric Laurent return GetHandleError(my_handle); 280c55a96383497a772a307b346368133960b02ad03Eric Laurent } 281c55a96383497a772a307b346368133960b02ad03Eric Laurent if (external_echo_path_ != NULL) { 282c55a96383497a772a307b346368133960b02ad03Eric Laurent if (WebRtcAecm_InitEchoPath(my_handle, 283c55a96383497a772a307b346368133960b02ad03Eric Laurent external_echo_path_, 284c55a96383497a772a307b346368133960b02ad03Eric Laurent echo_path_size_bytes()) != 0) { 285c55a96383497a772a307b346368133960b02ad03Eric Laurent return GetHandleError(my_handle); 286c55a96383497a772a307b346368133960b02ad03Eric Laurent } 287c55a96383497a772a307b346368133960b02ad03Eric Laurent } 288c55a96383497a772a307b346368133960b02ad03Eric Laurent 289c55a96383497a772a307b346368133960b02ad03Eric Laurent return apm_->kNoError; 290e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 291e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 292e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoControlMobileImpl::ConfigureHandle(void* handle) const { 293e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent AecmConfig config; 294e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent config.cngMode = comfort_noise_enabled_; 295e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent config.echoMode = MapSetting(routing_mode_); 296e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 297e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return WebRtcAecm_set_config(static_cast<Handle*>(handle), config); 298e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 299e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 300e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoControlMobileImpl::num_handles_required() const { 301e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->num_output_channels() * 302e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent apm_->num_reverse_channels(); 303e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 304e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 305e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoControlMobileImpl::GetHandleError(void* handle) const { 306e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(handle != NULL); 307e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return MapError(WebRtcAecm_get_error_code(static_cast<Handle*>(handle))); 308e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 309e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} // namespace webrtc 310