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_cancellation_impl.h" 12e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 13e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <cassert> 14e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <string.h> 15e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 16e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "critical_section_wrapper.h" 17e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "echo_cancellation.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(EchoCancellation::SuppressionLevel level) { 28e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent switch (level) { 29e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent case EchoCancellation::kLowSuppression: 30e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return kAecNlpConservative; 31e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent case EchoCancellation::kModerateSuppression: 32e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return kAecNlpModerate; 33e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent case EchoCancellation::kHighSuppression: 34e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return kAecNlpAggressive; 35e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent default: 36e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return -1; 37e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 38e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 39e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 40e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint MapError(int err) { 41e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent switch (err) { 42e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent case AEC_UNSUPPORTED_FUNCTION_ERROR: 43e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return AudioProcessing::kUnsupportedFunctionError; 44e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent break; 45e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent case AEC_BAD_PARAMETER_ERROR: 46e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return AudioProcessing::kBadParameterError; 47e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent break; 48e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent case AEC_BAD_PARAMETER_WARNING: 49e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return AudioProcessing::kBadStreamParameterWarning; 50e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent break; 51e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent default: 52e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // AEC_UNSPECIFIED_ERROR 53e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // AEC_UNINITIALIZED_ERROR 54e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // AEC_NULL_POINTER_ERROR 55e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return AudioProcessing::kUnspecifiedError; 56e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 57e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 58e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} // namespace 59e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 60e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentEchoCancellationImpl::EchoCancellationImpl(const AudioProcessingImpl* apm) 61e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent : ProcessingComponent(apm), 62e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent apm_(apm), 63e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent drift_compensation_enabled_(false), 64e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent metrics_enabled_(false), 65e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent suppression_level_(kModerateSuppression), 66e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent device_sample_rate_hz_(48000), 67e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stream_drift_samples_(0), 68e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent was_stream_drift_set_(false), 69c55a96383497a772a307b346368133960b02ad03Eric Laurent stream_has_echo_(false), 70c55a96383497a772a307b346368133960b02ad03Eric Laurent delay_logging_enabled_(false) {} 71e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 72e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentEchoCancellationImpl::~EchoCancellationImpl() {} 73e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 74e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) { 75e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (!is_component_enabled()) { 76e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNoError; 77e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 78e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 79e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(audio->samples_per_split_channel() <= 160); 80e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(audio->num_channels() == apm_->num_reverse_channels()); 81e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 82e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent int err = apm_->kNoError; 83e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 84e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // The ordering convention must be followed to pass to the correct AEC. 85e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent size_t handle_index = 0; 86e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (int i = 0; i < apm_->num_output_channels(); i++) { 87e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (int j = 0; j < audio->num_channels(); j++) { 88e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent Handle* my_handle = static_cast<Handle*>(handle(handle_index)); 89e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent err = WebRtcAec_BufferFarend( 90e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent my_handle, 91e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent audio->low_pass_split_data(j), 92e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent static_cast<WebRtc_Word16>(audio->samples_per_split_channel())); 93e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 94e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (err != apm_->kNoError) { 95e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return GetHandleError(my_handle); // TODO(ajm): warning possible? 96e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 97e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 98e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent handle_index++; 99e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 100e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 101e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 102e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNoError; 103e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 104e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 105e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) { 106e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (!is_component_enabled()) { 107e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNoError; 108e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 109e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 110e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (!apm_->was_stream_delay_set()) { 111e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kStreamParameterNotSetError; 112e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 113e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 114e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (drift_compensation_enabled_ && !was_stream_drift_set_) { 115e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kStreamParameterNotSetError; 116e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 117e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 118e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(audio->samples_per_split_channel() <= 160); 119e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(audio->num_channels() == apm_->num_output_channels()); 120e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 121e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent int err = apm_->kNoError; 122e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 123e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // The ordering convention must be followed to pass to the correct AEC. 124e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent size_t handle_index = 0; 125e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stream_has_echo_ = false; 126e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (int i = 0; i < audio->num_channels(); i++) { 127e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent for (int j = 0; j < apm_->num_reverse_channels(); j++) { 128e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent Handle* my_handle = handle(handle_index); 129e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent err = WebRtcAec_Process( 130e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent my_handle, 131e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent audio->low_pass_split_data(i), 132e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent audio->high_pass_split_data(i), 133e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent audio->low_pass_split_data(i), 134e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent audio->high_pass_split_data(i), 135e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent static_cast<WebRtc_Word16>(audio->samples_per_split_channel()), 136e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent apm_->stream_delay_ms(), 137e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stream_drift_samples_); 138e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 139e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (err != apm_->kNoError) { 140e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent err = GetHandleError(my_handle); 141e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // TODO(ajm): Figure out how to return warnings properly. 142e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (err != apm_->kBadStreamParameterWarning) { 143e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return err; 144e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 145e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 146e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 147e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 status = 0; 148e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent err = WebRtcAec_get_echo_status(my_handle, &status); 149e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (err != apm_->kNoError) { 150e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return GetHandleError(my_handle); 151e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 152e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 153e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (status == 1) { 154e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stream_has_echo_ = true; 155e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 156e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 157e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent handle_index++; 158e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 159e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 160e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 161e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent was_stream_drift_set_ = false; 162e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNoError; 163e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 164e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 165e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoCancellationImpl::Enable(bool enable) { 166e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent CriticalSectionScoped crit_scoped(*apm_->crit()); 167e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Ensure AEC and AECM are not both enabled. 168e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (enable && apm_->echo_control_mobile()->is_enabled()) { 169e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kBadParameterError; 170e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 171e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 172e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return EnableComponent(enable); 173e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 174e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 175e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentbool EchoCancellationImpl::is_enabled() const { 176e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return is_component_enabled(); 177e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 178e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 179e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoCancellationImpl::set_suppression_level(SuppressionLevel level) { 180e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent CriticalSectionScoped crit_scoped(*apm_->crit()); 181e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (MapSetting(level) == -1) { 182e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kBadParameterError; 183e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 184e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 185e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent suppression_level_ = level; 186e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return Configure(); 187e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 188e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 189e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentEchoCancellation::SuppressionLevel EchoCancellationImpl::suppression_level() 190e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent const { 191e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return suppression_level_; 192e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 193e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 194e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoCancellationImpl::enable_drift_compensation(bool enable) { 195e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent CriticalSectionScoped crit_scoped(*apm_->crit()); 196e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent drift_compensation_enabled_ = enable; 197e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return Configure(); 198e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 199e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 200e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentbool EchoCancellationImpl::is_drift_compensation_enabled() const { 201e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return drift_compensation_enabled_; 202e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 203e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 204e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoCancellationImpl::set_device_sample_rate_hz(int rate) { 205e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent CriticalSectionScoped crit_scoped(*apm_->crit()); 206e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (rate < 8000 || rate > 96000) { 207e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kBadParameterError; 208e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 209e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 210e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent device_sample_rate_hz_ = rate; 211e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return Initialize(); 212e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 213e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 214e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoCancellationImpl::device_sample_rate_hz() const { 215e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return device_sample_rate_hz_; 216e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 217e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 218e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoCancellationImpl::set_stream_drift_samples(int drift) { 219e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent was_stream_drift_set_ = true; 220e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent stream_drift_samples_ = drift; 221e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNoError; 222e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 223e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 224e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoCancellationImpl::stream_drift_samples() const { 225e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return stream_drift_samples_; 226e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 227e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 228e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoCancellationImpl::enable_metrics(bool enable) { 229e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent CriticalSectionScoped crit_scoped(*apm_->crit()); 230e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent metrics_enabled_ = enable; 231e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return Configure(); 232e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 233e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 234e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentbool EchoCancellationImpl::are_metrics_enabled() const { 235e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return metrics_enabled_; 236e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 237e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 238e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent// TODO(ajm): we currently just use the metrics from the first AEC. Think more 239e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent// aboue the best way to extend this to multi-channel. 240e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoCancellationImpl::GetMetrics(Metrics* metrics) { 241e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent CriticalSectionScoped crit_scoped(*apm_->crit()); 242e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (metrics == NULL) { 243e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNullPointerError; 244e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 245e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 246e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (!is_component_enabled() || !metrics_enabled_) { 247e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNotEnabledError; 248e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 249e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 250e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent AecMetrics my_metrics; 251e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent memset(&my_metrics, 0, sizeof(my_metrics)); 252e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent memset(metrics, 0, sizeof(Metrics)); 253e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 254e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent Handle* my_handle = static_cast<Handle*>(handle(0)); 255e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent int err = WebRtcAec_GetMetrics(my_handle, &my_metrics); 256e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (err != apm_->kNoError) { 257e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return GetHandleError(my_handle); 258e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 259e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 260e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent metrics->residual_echo_return_loss.instant = my_metrics.rerl.instant; 261e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent metrics->residual_echo_return_loss.average = my_metrics.rerl.average; 262e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent metrics->residual_echo_return_loss.maximum = my_metrics.rerl.max; 263e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent metrics->residual_echo_return_loss.minimum = my_metrics.rerl.min; 264e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 265e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent metrics->echo_return_loss.instant = my_metrics.erl.instant; 266e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent metrics->echo_return_loss.average = my_metrics.erl.average; 267e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent metrics->echo_return_loss.maximum = my_metrics.erl.max; 268e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent metrics->echo_return_loss.minimum = my_metrics.erl.min; 269e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 270e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent metrics->echo_return_loss_enhancement.instant = my_metrics.erle.instant; 271e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent metrics->echo_return_loss_enhancement.average = my_metrics.erle.average; 272e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent metrics->echo_return_loss_enhancement.maximum = my_metrics.erle.max; 273e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent metrics->echo_return_loss_enhancement.minimum = my_metrics.erle.min; 274e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 275e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent metrics->a_nlp.instant = my_metrics.aNlp.instant; 276e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent metrics->a_nlp.average = my_metrics.aNlp.average; 277e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent metrics->a_nlp.maximum = my_metrics.aNlp.max; 278e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent metrics->a_nlp.minimum = my_metrics.aNlp.min; 279e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 280e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNoError; 281e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 282e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 283e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentbool EchoCancellationImpl::stream_has_echo() const { 284e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return stream_has_echo_; 285e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 286e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 287c55a96383497a772a307b346368133960b02ad03Eric Laurentint EchoCancellationImpl::enable_delay_logging(bool enable) { 288c55a96383497a772a307b346368133960b02ad03Eric Laurent CriticalSectionScoped crit_scoped(*apm_->crit()); 289c55a96383497a772a307b346368133960b02ad03Eric Laurent delay_logging_enabled_ = enable; 290c55a96383497a772a307b346368133960b02ad03Eric Laurent return Configure(); 291c55a96383497a772a307b346368133960b02ad03Eric Laurent} 292c55a96383497a772a307b346368133960b02ad03Eric Laurent 293c55a96383497a772a307b346368133960b02ad03Eric Laurentbool EchoCancellationImpl::is_delay_logging_enabled() const { 294c55a96383497a772a307b346368133960b02ad03Eric Laurent return delay_logging_enabled_; 295c55a96383497a772a307b346368133960b02ad03Eric Laurent} 296c55a96383497a772a307b346368133960b02ad03Eric Laurent 297c55a96383497a772a307b346368133960b02ad03Eric Laurent// TODO(bjornv): How should we handle the multi-channel case? 298c55a96383497a772a307b346368133960b02ad03Eric Laurentint EchoCancellationImpl::GetDelayMetrics(int* median, int* std) { 299c55a96383497a772a307b346368133960b02ad03Eric Laurent CriticalSectionScoped crit_scoped(*apm_->crit()); 300c55a96383497a772a307b346368133960b02ad03Eric Laurent if (median == NULL) { 301c55a96383497a772a307b346368133960b02ad03Eric Laurent return apm_->kNullPointerError; 302c55a96383497a772a307b346368133960b02ad03Eric Laurent } 303c55a96383497a772a307b346368133960b02ad03Eric Laurent if (std == NULL) { 304c55a96383497a772a307b346368133960b02ad03Eric Laurent return apm_->kNullPointerError; 305c55a96383497a772a307b346368133960b02ad03Eric Laurent } 306c55a96383497a772a307b346368133960b02ad03Eric Laurent 307c55a96383497a772a307b346368133960b02ad03Eric Laurent if (!is_component_enabled() || !delay_logging_enabled_) { 308c55a96383497a772a307b346368133960b02ad03Eric Laurent return apm_->kNotEnabledError; 309c55a96383497a772a307b346368133960b02ad03Eric Laurent } 310c55a96383497a772a307b346368133960b02ad03Eric Laurent 311c55a96383497a772a307b346368133960b02ad03Eric Laurent Handle* my_handle = static_cast<Handle*>(handle(0)); 312c55a96383497a772a307b346368133960b02ad03Eric Laurent if (WebRtcAec_GetDelayMetrics(my_handle, median, std) != 313c55a96383497a772a307b346368133960b02ad03Eric Laurent apm_->kNoError) { 314c55a96383497a772a307b346368133960b02ad03Eric Laurent return GetHandleError(my_handle); 315c55a96383497a772a307b346368133960b02ad03Eric Laurent } 316c55a96383497a772a307b346368133960b02ad03Eric Laurent 317c55a96383497a772a307b346368133960b02ad03Eric Laurent return apm_->kNoError; 318c55a96383497a772a307b346368133960b02ad03Eric Laurent} 319c55a96383497a772a307b346368133960b02ad03Eric Laurent 320e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoCancellationImpl::Initialize() { 321e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent int err = ProcessingComponent::Initialize(); 322e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (err != apm_->kNoError || !is_component_enabled()) { 323e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return err; 324e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 325e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 326e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent was_stream_drift_set_ = false; 327e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 328e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNoError; 329e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 330e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 331e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoCancellationImpl::get_version(char* version, 332e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent int version_len_bytes) const { 333e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (WebRtcAec_get_version(version, version_len_bytes) != 0) { 334e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kBadParameterError; 335e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 336e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 337e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->kNoError; 338e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 339e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 340e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid* EchoCancellationImpl::CreateHandle() const { 341e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent Handle* handle = NULL; 342e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (WebRtcAec_Create(&handle) != apm_->kNoError) { 343e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent handle = NULL; 344e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else { 345e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(handle != NULL); 346e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 347e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 348e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return handle; 349e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 350e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 351e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoCancellationImpl::DestroyHandle(void* handle) const { 352e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(handle != NULL); 353e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return WebRtcAec_Free(static_cast<Handle*>(handle)); 354e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 355e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 356e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoCancellationImpl::InitializeHandle(void* handle) const { 357e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(handle != NULL); 358e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return WebRtcAec_Init(static_cast<Handle*>(handle), 359e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent apm_->sample_rate_hz(), 360e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent device_sample_rate_hz_); 361e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 362e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 363e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoCancellationImpl::ConfigureHandle(void* handle) const { 364e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(handle != NULL); 365e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent AecConfig config; 366e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent config.metricsMode = metrics_enabled_; 367e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent config.nlpMode = MapSetting(suppression_level_); 368e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent config.skewMode = drift_compensation_enabled_; 369c55a96383497a772a307b346368133960b02ad03Eric Laurent config.delay_logging = delay_logging_enabled_; 370e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 371e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return WebRtcAec_set_config(static_cast<Handle*>(handle), config); 372e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 373e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 374e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoCancellationImpl::num_handles_required() const { 375e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return apm_->num_output_channels() * 376e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent apm_->num_reverse_channels(); 377e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 378e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 379e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint EchoCancellationImpl::GetHandleError(void* handle) const { 380e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent assert(handle != NULL); 381e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return MapError(WebRtcAec_get_error_code(static_cast<Handle*>(handle))); 382e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 383e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} // namespace webrtc 384