Index: webrtc/modules/audio_processing/echo_cancellation_impl.cc |
diff --git a/webrtc/modules/audio_processing/echo_cancellation_impl.cc b/webrtc/modules/audio_processing/echo_cancellation_impl.cc |
index 1cc66eccf4ff73f81342fae54dcf3c56016b745e..1bac629c9e752f1597b75231e73cbacb2520b542 100644 |
--- a/webrtc/modules/audio_processing/echo_cancellation_impl.cc |
+++ b/webrtc/modules/audio_processing/echo_cancellation_impl.cc |
@@ -59,38 +59,11 @@ |
static const size_t kMaxNumFramesToBuffer = 100; |
} // namespace |
-class EchoCancellationImpl::Canceller { |
- public: |
- explicit Canceller(int sample_rate_hz) { |
- state_ = WebRtcAec_Create(); |
- RTC_DCHECK(state_); |
- } |
- |
- ~Canceller() { |
- RTC_CHECK(state_); |
- WebRtcAec_Free(state_); |
- } |
- |
- Handle* state() { return state_; } |
- |
- void Initialize(int sample_rate_hz) { |
- // TODO(ajm): Drift compensation is disabled in practice. If restored, it |
- // should be managed internally and not depend on the hardware sample rate. |
- // For now, just hardcode a 48 kHz value. |
- const int error = WebRtcAec_Init(state_, sample_rate_hz, 48000); |
- RTC_DCHECK_EQ(0, error); |
- } |
- |
- private: |
- Handle* state_; |
- |
- RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Canceller); |
-}; |
- |
EchoCancellationImpl::EchoCancellationImpl(const AudioProcessing* apm, |
rtc::CriticalSection* crit_render, |
rtc::CriticalSection* crit_capture) |
- : apm_(apm), |
+ : ProcessingComponent(), |
+ apm_(apm), |
crit_render_(crit_render), |
crit_capture_(crit_capture), |
drift_compensation_enabled_(false), |
@@ -113,14 +86,12 @@ |
int EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) { |
rtc::CritScope cs_render(crit_render_); |
- if (!enabled_) { |
+ if (!is_component_enabled()) { |
return AudioProcessing::kNoError; |
} |
- RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
- RTC_DCHECK_EQ(audio->num_channels(), apm_->num_reverse_channels()); |
- RTC_DCHECK_GE(cancellers_.size(), |
- apm_->num_output_channels() * audio->num_channels()); |
+ assert(audio->num_frames_per_band() <= 160); |
+ assert(audio->num_channels() == apm_->num_reverse_channels()); |
int err = AudioProcessing::kNoError; |
@@ -129,9 +100,9 @@ |
render_queue_buffer_.clear(); |
for (size_t i = 0; i < apm_->num_output_channels(); i++) { |
for (size_t j = 0; j < audio->num_channels(); j++) { |
- Handle* my_handle = cancellers_[handle_index++]->state(); |
+ Handle* my_handle = static_cast<Handle*>(handle(handle_index)); |
// Retrieve any error code produced by the buffering of the farend |
- // signal. |
+ // signal |
err = WebRtcAec_GetBufferFarendError( |
my_handle, audio->split_bands_const_f(j)[kBand0To8kHz], |
audio->num_frames_per_band()); |
@@ -145,6 +116,8 @@ |
audio->split_bands_const_f(j)[kBand0To8kHz], |
(audio->split_bands_const_f(j)[kBand0To8kHz] + |
audio->num_frames_per_band())); |
+ |
+ handle_index++; |
} |
} |
@@ -164,7 +137,7 @@ |
// a queue. All the data chunks are buffered into the farend signal of the AEC. |
void EchoCancellationImpl::ReadQueuedRenderData() { |
rtc::CritScope cs_capture(crit_capture_); |
- if (!enabled_) { |
+ if (!is_component_enabled()) { |
return; |
} |
@@ -176,11 +149,12 @@ |
(apm_->num_output_channels() * apm_->num_reverse_channels()); |
for (size_t i = 0; i < apm_->num_output_channels(); i++) { |
for (size_t j = 0; j < apm_->num_reverse_channels(); j++) { |
- Handle* my_handle = cancellers_[handle_index++]->state(); |
+ Handle* my_handle = static_cast<Handle*>(handle(handle_index)); |
WebRtcAec_BufferFarend(my_handle, &capture_queue_buffer_[buffer_index], |
num_frames_per_band); |
buffer_index += num_frames_per_band; |
+ handle_index++; |
} |
} |
} |
@@ -188,7 +162,7 @@ |
int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) { |
rtc::CritScope cs_capture(crit_capture_); |
- if (!enabled_) { |
+ if (!is_component_enabled()) { |
return AudioProcessing::kNoError; |
} |
@@ -200,8 +174,8 @@ |
return AudioProcessing::kStreamParameterNotSetError; |
} |
- RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
- RTC_DCHECK_EQ(audio->num_channels(), apm_->num_proc_channels()); |
+ assert(audio->num_frames_per_band() <= 160); |
+ assert(audio->num_channels() == apm_->num_proc_channels()); |
int err = AudioProcessing::kNoError; |
@@ -210,7 +184,7 @@ |
stream_has_echo_ = false; |
for (size_t i = 0; i < audio->num_channels(); i++) { |
for (size_t j = 0; j < apm_->num_reverse_channels(); j++) { |
- Handle* my_handle = cancellers_[handle_index++]->state(); |
+ Handle* my_handle = handle(handle_index); |
err = WebRtcAec_Process(my_handle, audio->split_bands_const_f(i), |
audio->num_bands(), audio->split_bands_f(i), |
audio->num_frames_per_band(), |
@@ -233,6 +207,8 @@ |
if (status == 1) { |
stream_has_echo_ = true; |
} |
+ |
+ handle_index++; |
} |
} |
@@ -251,18 +227,12 @@ |
return AudioProcessing::kBadParameterError; |
} |
- if (enable && !enabled_) { |
- enabled_ = enable; // Must be set before Initialize() is called. |
- Initialize(); |
- } else { |
- enabled_ = enable; |
- } |
- return AudioProcessing::kNoError; |
+ return EnableComponent(enable); |
} |
bool EchoCancellationImpl::is_enabled() const { |
rtc::CritScope cs(crit_capture_); |
- return enabled_; |
+ return is_component_enabled(); |
} |
int EchoCancellationImpl::set_suppression_level(SuppressionLevel level) { |
@@ -327,7 +297,7 @@ |
return AudioProcessing::kNullPointerError; |
} |
- if (!enabled_ || !metrics_enabled_) { |
+ if (!is_component_enabled() || !metrics_enabled_) { |
return AudioProcessing::kNotEnabledError; |
} |
@@ -335,7 +305,7 @@ |
memset(&my_metrics, 0, sizeof(my_metrics)); |
memset(metrics, 0, sizeof(Metrics)); |
- Handle* my_handle = cancellers_[0]->state(); |
+ Handle* my_handle = static_cast<Handle*>(handle(0)); |
int err = WebRtcAec_GetMetrics(my_handle, &my_metrics); |
if (err != AudioProcessing::kNoError) { |
return MapError(err); |
@@ -414,11 +384,11 @@ |
return AudioProcessing::kNullPointerError; |
} |
- if (!enabled_ || !delay_logging_enabled_) { |
+ if (!is_component_enabled() || !delay_logging_enabled_) { |
return AudioProcessing::kNotEnabledError; |
} |
- Handle* my_handle = cancellers_[0]->state(); |
+ Handle* my_handle = static_cast<Handle*>(handle(0)); |
const int err = |
WebRtcAec_GetDelayMetrics(my_handle, median, std, fraction_poor_delays); |
if (err != AudioProcessing::kNoError) { |
@@ -430,37 +400,25 @@ |
struct AecCore* EchoCancellationImpl::aec_core() const { |
rtc::CritScope cs(crit_capture_); |
- if (!enabled_) { |
+ if (!is_component_enabled()) { |
return NULL; |
} |
- Handle* my_handle = cancellers_[0]->state(); |
+ Handle* my_handle = static_cast<Handle*>(handle(0)); |
return WebRtcAec_aec_core(my_handle); |
} |
-void EchoCancellationImpl::Initialize() { |
- rtc::CritScope cs_render(crit_render_); |
- rtc::CritScope cs_capture(crit_capture_); |
- if (!enabled_) { |
- return; |
- } |
- const int sample_rate_hz = apm_->proc_sample_rate_hz(); |
- |
- if (num_handles_required() > cancellers_.size()) { |
- const size_t cancellers_old_size = cancellers_.size(); |
- cancellers_.resize(num_handles_required()); |
- |
- for (size_t i = cancellers_old_size; i < cancellers_.size(); ++i) { |
- cancellers_[i].reset(new Canceller(sample_rate_hz)); |
+int EchoCancellationImpl::Initialize() { |
+ int err = ProcessingComponent::Initialize(); |
+ { |
+ rtc::CritScope cs(crit_capture_); |
+ if (err != AudioProcessing::kNoError || !is_component_enabled()) { |
+ return err; |
} |
} |
- for (size_t i = 0; i < cancellers_.size(); ++i) { |
- cancellers_[i]->Initialize(sample_rate_hz); |
- } |
- |
- Configure(); |
- |
AllocateRenderQueue(); |
+ |
+ return AudioProcessing::kNoError; |
} |
void EchoCancellationImpl::AllocateRenderQueue() { |
@@ -500,30 +458,45 @@ |
Configure(); |
} |
-int EchoCancellationImpl::Configure() { |
+void* EchoCancellationImpl::CreateHandle() const { |
+ return WebRtcAec_Create(); |
+} |
+ |
+void EchoCancellationImpl::DestroyHandle(void* handle) const { |
+ assert(handle != NULL); |
+ WebRtcAec_Free(static_cast<Handle*>(handle)); |
+} |
+ |
+int EchoCancellationImpl::InitializeHandle(void* handle) const { |
+ // Not locked as it only relies on APM public API which is threadsafe. |
+ |
+ assert(handle != NULL); |
+ // TODO(ajm): Drift compensation is disabled in practice. If restored, it |
+ // should be managed internally and not depend on the hardware sample rate. |
+ // For now, just hardcode a 48 kHz value. |
+ return WebRtcAec_Init(static_cast<Handle*>(handle), |
+ apm_->proc_sample_rate_hz(), 48000); |
+} |
+ |
+int EchoCancellationImpl::ConfigureHandle(void* handle) const { |
rtc::CritScope cs_render(crit_render_); |
rtc::CritScope cs_capture(crit_capture_); |
+ assert(handle != NULL); |
AecConfig config; |
config.metricsMode = metrics_enabled_; |
config.nlpMode = MapSetting(suppression_level_); |
config.skewMode = drift_compensation_enabled_; |
config.delay_logging = delay_logging_enabled_; |
- |
- int error = AudioProcessing::kNoError; |
- for (size_t i = 0; i < cancellers_.size(); i++) { |
- Handle* my_handle = cancellers_[i]->state(); |
- WebRtcAec_enable_extended_filter(WebRtcAec_aec_core(my_handle), |
- extended_filter_enabled_ ? 1 : 0); |
- WebRtcAec_enable_delay_agnostic(WebRtcAec_aec_core(my_handle), |
- delay_agnostic_enabled_ ? 1 : 0); |
- WebRtcAec_enable_next_generation_aec(WebRtcAec_aec_core(my_handle), |
- next_generation_aec_enabled_ ? 1 : 0); |
- const int handle_error = WebRtcAec_set_config(my_handle, config); |
- if (handle_error != AudioProcessing::kNoError) { |
- error = AudioProcessing::kNoError; |
- } |
- } |
- return error; |
+ WebRtcAec_enable_extended_filter( |
+ WebRtcAec_aec_core(static_cast<Handle*>(handle)), |
+ extended_filter_enabled_ ? 1 : 0); |
+ WebRtcAec_enable_delay_agnostic( |
+ WebRtcAec_aec_core(static_cast<Handle*>(handle)), |
+ delay_agnostic_enabled_ ? 1 : 0); |
+ WebRtcAec_enable_next_generation_aec( |
+ WebRtcAec_aec_core(static_cast<Handle*>(handle)), |
+ next_generation_aec_enabled_ ? 1 : 0); |
+ return WebRtcAec_set_config(static_cast<Handle*>(handle), config); |
} |
size_t EchoCancellationImpl::num_handles_required() const { |
@@ -531,4 +504,9 @@ |
return apm_->num_output_channels() * apm_->num_reverse_channels(); |
} |
+int EchoCancellationImpl::GetHandleError(void* handle) const { |
+ // Not locked as it does not rely on anything in the state. |
+ assert(handle != NULL); |
+ return AudioProcessing::kUnspecifiedError; |
+} |
} // namespace webrtc |