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