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 11dba34dd1d41e811769e6ebd085e7101e257a64d8bjornv@webrtc.org#include "webrtc/modules/audio_processing/echo_cancellation_impl.h" 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 13dba34dd1d41e811769e6ebd085e7101e257a64d8bjornv@webrtc.org#include <assert.h> 14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <string.h> 15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 168ddec2c539a1daf4dd08607561090ac163cb9a7aandrew@webrtc.orgextern "C" { 178ddec2c539a1daf4dd08607561090ac163cb9a7aandrew@webrtc.org#include "webrtc/modules/audio_processing/aec/aec_core.h" 188ddec2c539a1daf4dd08607561090ac163cb9a7aandrew@webrtc.org} 198ddec2c539a1daf4dd08607561090ac163cb9a7aandrew@webrtc.org#include "webrtc/modules/audio_processing/aec/include/echo_cancellation.h" 20dba34dd1d41e811769e6ebd085e7101e257a64d8bjornv@webrtc.org#include "webrtc/modules/audio_processing/audio_buffer.h" 21dba34dd1d41e811769e6ebd085e7101e257a64d8bjornv@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc { 24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgtypedef void Handle; 26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace { 283f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.orgint16_t MapSetting(EchoCancellation::SuppressionLevel level) { 29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org switch (level) { 30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case EchoCancellation::kLowSuppression: 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return kAecNlpConservative; 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case EchoCancellation::kModerateSuppression: 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return kAecNlpModerate; 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case EchoCancellation::kHighSuppression: 35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return kAecNlpAggressive; 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(false); 38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgAudioProcessing::Error MapError(int err) { 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org switch (err) { 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case AEC_UNSUPPORTED_FUNCTION_ERROR: 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return AudioProcessing::kUnsupportedFunctionError; 45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case AEC_BAD_PARAMETER_ERROR: 46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return AudioProcessing::kBadParameterError; 47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org case AEC_BAD_PARAMETER_WARNING: 48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return AudioProcessing::kBadStreamParameterWarning; 49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org default: 50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // AEC_UNSPECIFIED_ERROR 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // AEC_UNINITIALIZED_ERROR 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // AEC_NULL_POINTER_ERROR 53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return AudioProcessing::kUnspecifiedError; 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} // namespace 57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 58a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.orgEchoCancellationImpl::EchoCancellationImpl(const AudioProcessing* apm, 59a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org CriticalSectionWrapper* crit) 60a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org : ProcessingComponent(), 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org apm_(apm), 62a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org crit_(crit), 63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org drift_compensation_enabled_(false), 64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org metrics_enabled_(false), 65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org suppression_level_(kModerateSuppression), 66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org stream_drift_samples_(0), 67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org was_stream_drift_set_(false), 68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org stream_has_echo_(false), 698ddec2c539a1daf4dd08607561090ac163cb9a7aandrew@webrtc.org delay_logging_enabled_(false), 70376df2cf3dd5f653dd551f79021815ab3c4a02c4bjornv@webrtc.org delay_correction_enabled_(false), 71376df2cf3dd5f653dd551f79021815ab3c4a02c4bjornv@webrtc.org reported_delay_enabled_(true) {} 72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgEchoCancellationImpl::~EchoCancellationImpl() {} 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) { 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!is_component_enabled()) { 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNoError; 78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(audio->samples_per_split_channel() <= 160); 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(audio->num_channels() == apm_->num_reverse_channels()); 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int err = apm_->kNoError; 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The ordering convention must be followed to pass to the correct AEC. 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org size_t handle_index = 0; 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int i = 0; i < apm_->num_output_channels(); i++) { 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int j = 0; j < audio->num_channels(); j++) { 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Handle* my_handle = static_cast<Handle*>(handle(handle_index)); 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org err = WebRtcAec_BufferFarend( 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org my_handle, 9238a0cee9789409eebadb54bcf055a29b61767118kwiberg@webrtc.org audio->low_pass_split_data_f(j), 933f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org static_cast<int16_t>(audio->samples_per_split_channel())); 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err != apm_->kNoError) { 96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return GetHandleError(my_handle); // TODO(ajm): warning possible? 97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org handle_index++; 100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNoError; 104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) { 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!is_component_enabled()) { 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNoError; 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!apm_->was_stream_delay_set()) { 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kStreamParameterNotSetError; 113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (drift_compensation_enabled_ && !was_stream_drift_set_) { 116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kStreamParameterNotSetError; 117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(audio->samples_per_split_channel() <= 160); 120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(audio->num_channels() == apm_->num_output_channels()); 121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int err = apm_->kNoError; 123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // The ordering convention must be followed to pass to the correct AEC. 125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org size_t handle_index = 0; 126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org stream_has_echo_ = false; 127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int i = 0; i < audio->num_channels(); i++) { 128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int j = 0; j < apm_->num_reverse_channels(); j++) { 129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Handle* my_handle = handle(handle_index); 130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org err = WebRtcAec_Process( 131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org my_handle, 132e9b43402e00fc048cf93d7bb9a2cdbf97c1fed2cmflodman@webrtc.org audio->low_pass_split_data_f(i), 133e9b43402e00fc048cf93d7bb9a2cdbf97c1fed2cmflodman@webrtc.org audio->high_pass_split_data_f(i), 134e9b43402e00fc048cf93d7bb9a2cdbf97c1fed2cmflodman@webrtc.org audio->low_pass_split_data_f(i), 135e9b43402e00fc048cf93d7bb9a2cdbf97c1fed2cmflodman@webrtc.org audio->high_pass_split_data_f(i), 1363f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org static_cast<int16_t>(audio->samples_per_split_channel()), 137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org apm_->stream_delay_ms(), 138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org stream_drift_samples_); 139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err != apm_->kNoError) { 141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org err = GetHandleError(my_handle); 142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // TODO(ajm): Figure out how to return warnings properly. 143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err != apm_->kBadStreamParameterWarning) { 144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return err; 145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 148dba34dd1d41e811769e6ebd085e7101e257a64d8bjornv@webrtc.org int status = 0; 149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org err = WebRtcAec_get_echo_status(my_handle, &status); 150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err != apm_->kNoError) { 151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return GetHandleError(my_handle); 152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (status == 1) { 155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org stream_has_echo_ = true; 156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org handle_index++; 159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org was_stream_drift_set_ = false; 163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNoError; 164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint EchoCancellationImpl::Enable(bool enable) { 167a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org CriticalSectionScoped crit_scoped(crit_); 168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Ensure AEC and AECM are not both enabled. 169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (enable && apm_->echo_control_mobile()->is_enabled()) { 170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kBadParameterError; 171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return EnableComponent(enable); 174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool EchoCancellationImpl::is_enabled() const { 177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return is_component_enabled(); 178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint EchoCancellationImpl::set_suppression_level(SuppressionLevel level) { 181a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org CriticalSectionScoped crit_scoped(crit_); 182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (MapSetting(level) == -1) { 183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kBadParameterError; 184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org suppression_level_ = level; 187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return Configure(); 188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgEchoCancellation::SuppressionLevel EchoCancellationImpl::suppression_level() 191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const { 192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return suppression_level_; 193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint EchoCancellationImpl::enable_drift_compensation(bool enable) { 196a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org CriticalSectionScoped crit_scoped(crit_); 197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org drift_compensation_enabled_ = enable; 198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return Configure(); 199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool EchoCancellationImpl::is_drift_compensation_enabled() const { 202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return drift_compensation_enabled_; 203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 205b563e5e8b34fd7f0c6c02fa4176e9be83c2bf795andrew@webrtc.orgvoid EchoCancellationImpl::set_stream_drift_samples(int drift) { 206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org was_stream_drift_set_ = true; 207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org stream_drift_samples_ = drift; 208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint EchoCancellationImpl::stream_drift_samples() const { 211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return stream_drift_samples_; 212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint EchoCancellationImpl::enable_metrics(bool enable) { 215a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org CriticalSectionScoped crit_scoped(crit_); 216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org metrics_enabled_ = enable; 217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return Configure(); 218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool EchoCancellationImpl::are_metrics_enabled() const { 221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return metrics_enabled_; 222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// TODO(ajm): we currently just use the metrics from the first AEC. Think more 225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// aboue the best way to extend this to multi-channel. 226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint EchoCancellationImpl::GetMetrics(Metrics* metrics) { 227a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org CriticalSectionScoped crit_scoped(crit_); 228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (metrics == NULL) { 229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNullPointerError; 230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!is_component_enabled() || !metrics_enabled_) { 233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNotEnabledError; 234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AecMetrics my_metrics; 237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(&my_metrics, 0, sizeof(my_metrics)); 238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(metrics, 0, sizeof(Metrics)); 239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Handle* my_handle = static_cast<Handle*>(handle(0)); 241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int err = WebRtcAec_GetMetrics(my_handle, &my_metrics); 242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err != apm_->kNoError) { 243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return GetHandleError(my_handle); 244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org metrics->residual_echo_return_loss.instant = my_metrics.rerl.instant; 247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org metrics->residual_echo_return_loss.average = my_metrics.rerl.average; 248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org metrics->residual_echo_return_loss.maximum = my_metrics.rerl.max; 249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org metrics->residual_echo_return_loss.minimum = my_metrics.rerl.min; 250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org metrics->echo_return_loss.instant = my_metrics.erl.instant; 252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org metrics->echo_return_loss.average = my_metrics.erl.average; 253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org metrics->echo_return_loss.maximum = my_metrics.erl.max; 254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org metrics->echo_return_loss.minimum = my_metrics.erl.min; 255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org metrics->echo_return_loss_enhancement.instant = my_metrics.erle.instant; 257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org metrics->echo_return_loss_enhancement.average = my_metrics.erle.average; 258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org metrics->echo_return_loss_enhancement.maximum = my_metrics.erle.max; 259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org metrics->echo_return_loss_enhancement.minimum = my_metrics.erle.min; 260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org metrics->a_nlp.instant = my_metrics.aNlp.instant; 262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org metrics->a_nlp.average = my_metrics.aNlp.average; 263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org metrics->a_nlp.maximum = my_metrics.aNlp.max; 264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org metrics->a_nlp.minimum = my_metrics.aNlp.min; 265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNoError; 267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool EchoCancellationImpl::stream_has_echo() const { 270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return stream_has_echo_; 271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint EchoCancellationImpl::enable_delay_logging(bool enable) { 274a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org CriticalSectionScoped crit_scoped(crit_); 275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delay_logging_enabled_ = enable; 276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return Configure(); 277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool EchoCancellationImpl::is_delay_logging_enabled() const { 280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return delay_logging_enabled_; 281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// TODO(bjornv): How should we handle the multi-channel case? 284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint EchoCancellationImpl::GetDelayMetrics(int* median, int* std) { 285a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org CriticalSectionScoped crit_scoped(crit_); 286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (median == NULL) { 287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNullPointerError; 288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (std == NULL) { 290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNullPointerError; 291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!is_component_enabled() || !delay_logging_enabled_) { 294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNotEnabledError; 295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Handle* my_handle = static_cast<Handle*>(handle(0)); 298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (WebRtcAec_GetDelayMetrics(my_handle, median, std) != 299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org apm_->kNoError) { 300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return GetHandleError(my_handle); 301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNoError; 304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3064c2225fdfc806db5372139b6d2c3a138d4aaf10bbjornv@webrtc.orgstruct AecCore* EchoCancellationImpl::aec_core() const { 307a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org CriticalSectionScoped crit_scoped(crit_); 3084c2225fdfc806db5372139b6d2c3a138d4aaf10bbjornv@webrtc.org if (!is_component_enabled()) { 3094c2225fdfc806db5372139b6d2c3a138d4aaf10bbjornv@webrtc.org return NULL; 3104c2225fdfc806db5372139b6d2c3a138d4aaf10bbjornv@webrtc.org } 3114c2225fdfc806db5372139b6d2c3a138d4aaf10bbjornv@webrtc.org Handle* my_handle = static_cast<Handle*>(handle(0)); 3124c2225fdfc806db5372139b6d2c3a138d4aaf10bbjornv@webrtc.org return WebRtcAec_aec_core(my_handle); 3134c2225fdfc806db5372139b6d2c3a138d4aaf10bbjornv@webrtc.org} 3144c2225fdfc806db5372139b6d2c3a138d4aaf10bbjornv@webrtc.org 315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint EchoCancellationImpl::Initialize() { 316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int err = ProcessingComponent::Initialize(); 317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (err != apm_->kNoError || !is_component_enabled()) { 318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return err; 319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->kNoError; 322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3248ddec2c539a1daf4dd08607561090ac163cb9a7aandrew@webrtc.orgvoid EchoCancellationImpl::SetExtraOptions(const Config& config) { 3258ddec2c539a1daf4dd08607561090ac163cb9a7aandrew@webrtc.org delay_correction_enabled_ = config.Get<DelayCorrection>().enabled; 326b96d9c72c7286b3505e7a122e34d770377a46052bjornv@webrtc.org reported_delay_enabled_ = config.Get<ReportedDelay>().enabled; 3278ddec2c539a1daf4dd08607561090ac163cb9a7aandrew@webrtc.org Configure(); 3288ddec2c539a1daf4dd08607561090ac163cb9a7aandrew@webrtc.org} 3298ddec2c539a1daf4dd08607561090ac163cb9a7aandrew@webrtc.org 330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid* EchoCancellationImpl::CreateHandle() const { 331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Handle* handle = NULL; 332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (WebRtcAec_Create(&handle) != apm_->kNoError) { 333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org handle = NULL; 334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else { 335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(handle != NULL); 336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return handle; 339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 341ffc2de0133683fb103eef61f21134f469bc099dbbjornv@webrtc.orgvoid EchoCancellationImpl::DestroyHandle(void* handle) const { 342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(handle != NULL); 343ffc2de0133683fb103eef61f21134f469bc099dbbjornv@webrtc.org WebRtcAec_Free(static_cast<Handle*>(handle)); 344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint EchoCancellationImpl::InitializeHandle(void* handle) const { 347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(handle != NULL); 348467f7567c8befea153861e09f048f69932d6e3bdandrew@webrtc.org // TODO(ajm): Drift compensation is disabled in practice. If restored, it 349467f7567c8befea153861e09f048f69932d6e3bdandrew@webrtc.org // should be managed internally and not depend on the hardware sample rate. 350467f7567c8befea153861e09f048f69932d6e3bdandrew@webrtc.org // For now, just hardcode a 48 kHz value. 351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return WebRtcAec_Init(static_cast<Handle*>(handle), 352467f7567c8befea153861e09f048f69932d6e3bdandrew@webrtc.org apm_->proc_sample_rate_hz(), 353467f7567c8befea153861e09f048f69932d6e3bdandrew@webrtc.org 48000); 354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint EchoCancellationImpl::ConfigureHandle(void* handle) const { 357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(handle != NULL); 358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AecConfig config; 359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org config.metricsMode = metrics_enabled_; 360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org config.nlpMode = MapSetting(suppression_level_); 361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org config.skewMode = drift_compensation_enabled_; 362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org config.delay_logging = delay_logging_enabled_; 363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 3648ddec2c539a1daf4dd08607561090ac163cb9a7aandrew@webrtc.org WebRtcAec_enable_delay_correction(WebRtcAec_aec_core( 3658ddec2c539a1daf4dd08607561090ac163cb9a7aandrew@webrtc.org static_cast<Handle*>(handle)), delay_correction_enabled_ ? 1 : 0); 366376df2cf3dd5f653dd551f79021815ab3c4a02c4bjornv@webrtc.org WebRtcAec_enable_reported_delay(WebRtcAec_aec_core( 367376df2cf3dd5f653dd551f79021815ab3c4a02c4bjornv@webrtc.org static_cast<Handle*>(handle)), reported_delay_enabled_ ? 1 : 0); 368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return WebRtcAec_set_config(static_cast<Handle*>(handle), config); 369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint EchoCancellationImpl::num_handles_required() const { 372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return apm_->num_output_channels() * 373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org apm_->num_reverse_channels(); 374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint EchoCancellationImpl::GetHandleError(void* handle) const { 377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(handle != NULL); 378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return MapError(WebRtcAec_get_error_code(static_cast<Handle*>(handle))); 379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} // namespace webrtc 381