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