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 1c3ebe4abb5901ba7b44bf329b6087adc249f864..c2e69544d6f62ad0d03ecd1cfc766a4d0a615318 100644 |
--- a/webrtc/modules/audio_processing/echo_cancellation_impl.cc |
+++ b/webrtc/modules/audio_processing/echo_cancellation_impl.cc |
@@ -59,11 +59,38 @@ static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160; |
static const size_t kMaxNumFramesToBuffer = 100; |
} // namespace |
+class EchoCancellationImpl::Canceller { |
+ public: |
+ explicit Canceller(int sample_rate_hz) { |
+ state_ = WebRtcAec_Create(); |
+ RTC_CHECK(state_); |
+ } |
+ |
+ ~Canceller() { |
+ RTC_CHECK(state_); |
the sun
2016/03/03 13:13:05
DCHECK not CHECK here
peah-webrtc
2016/03/03 13:56:16
Done.
|
+ WebRtcAec_Free(state_); |
+ } |
+ |
+ Handle* state() { return state_; } |
the sun
2016/03/03 10:00:53
So removing this (either folding functions into Ca
peah-webrtc
2016/03/03 12:06:33
Yes, that is the intention. I could do it in this
the sun
2016/03/03 13:13:05
I think that is good thinking! :)
peah-webrtc
2016/03/03 13:56:16
Acknowledged.
|
+ |
+ 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) |
- : ProcessingComponent(), |
- apm_(apm), |
+ : apm_(apm), |
crit_render_(crit_render), |
crit_capture_(crit_capture), |
drift_compensation_enabled_(false), |
@@ -86,12 +113,14 @@ EchoCancellationImpl::~EchoCancellationImpl() {} |
int EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) { |
rtc::CritScope cs_render(crit_render_); |
- if (!is_component_enabled()) { |
+ if (!enabled_) { |
return AudioProcessing::kNoError; |
} |
- assert(audio->num_frames_per_band() <= 160); |
- assert(audio->num_channels() == apm_->num_reverse_channels()); |
+ RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
+ RTC_DCHECK_EQ(audio->num_channels(), apm_->num_reverse_channels()); |
+ RTC_DCHECK_EQ(cancellers_.size(), |
+ apm_->num_output_channels() * audio->num_channels()); |
int err = AudioProcessing::kNoError; |
@@ -100,9 +129,9 @@ int EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) { |
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 = static_cast<Handle*>(handle(handle_index)); |
+ Handle* my_handle = cancellers_[handle_index++]->state(); |
// 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()); |
@@ -135,7 +164,7 @@ int EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) { |
// 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 (!is_component_enabled()) { |
+ if (!enabled_) { |
return; |
} |
@@ -147,12 +176,11 @@ void EchoCancellationImpl::ReadQueuedRenderData() { |
(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 = static_cast<Handle*>(handle(handle_index)); |
+ Handle* my_handle = cancellers_[handle_index++]->state(); |
WebRtcAec_BufferFarend(my_handle, &capture_queue_buffer_[buffer_index], |
num_frames_per_band); |
buffer_index += num_frames_per_band; |
- handle_index++; |
} |
} |
} |
@@ -160,7 +188,7 @@ void EchoCancellationImpl::ReadQueuedRenderData() { |
int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) { |
rtc::CritScope cs_capture(crit_capture_); |
- if (!is_component_enabled()) { |
+ if (!enabled_) { |
return AudioProcessing::kNoError; |
} |
@@ -172,8 +200,8 @@ int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) { |
return AudioProcessing::kStreamParameterNotSetError; |
} |
- assert(audio->num_frames_per_band() <= 160); |
- assert(audio->num_channels() == apm_->num_proc_channels()); |
+ RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
+ RTC_DCHECK_EQ(audio->num_channels(), apm_->num_proc_channels()); |
int err = AudioProcessing::kNoError; |
@@ -182,7 +210,7 @@ int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) { |
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 = handle(handle_index); |
+ Handle* my_handle = cancellers_[handle_index++]->state(); |
err = WebRtcAec_Process(my_handle, audio->split_bands_const_f(i), |
audio->num_bands(), audio->split_bands_f(i), |
audio->num_frames_per_band(), |
@@ -205,8 +233,6 @@ int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) { |
if (status == 1) { |
stream_has_echo_ = true; |
} |
- |
- handle_index++; |
} |
} |
@@ -225,12 +251,18 @@ int EchoCancellationImpl::Enable(bool enable) { |
return AudioProcessing::kBadParameterError; |
} |
- return EnableComponent(enable); |
+ if (enable && !enabled_) { |
+ enabled_ = enable; // Must be set before Initialize() is called. |
+ Initialize(); |
+ } else { |
+ enabled_ = enable; |
+ } |
+ return AudioProcessing::kNoError; |
} |
bool EchoCancellationImpl::is_enabled() const { |
rtc::CritScope cs(crit_capture_); |
- return is_component_enabled(); |
+ return enabled_; |
} |
int EchoCancellationImpl::set_suppression_level(SuppressionLevel level) { |
@@ -295,7 +327,7 @@ int EchoCancellationImpl::GetMetrics(Metrics* metrics) { |
return AudioProcessing::kNullPointerError; |
} |
- if (!is_component_enabled() || !metrics_enabled_) { |
+ if (!enabled_ || !metrics_enabled_) { |
return AudioProcessing::kNotEnabledError; |
} |
@@ -303,7 +335,7 @@ int EchoCancellationImpl::GetMetrics(Metrics* metrics) { |
memset(&my_metrics, 0, sizeof(my_metrics)); |
memset(metrics, 0, sizeof(Metrics)); |
- Handle* my_handle = static_cast<Handle*>(handle(0)); |
+ Handle* my_handle = cancellers_[0]->state(); |
int err = WebRtcAec_GetMetrics(my_handle, &my_metrics); |
if (err != AudioProcessing::kNoError) { |
return MapError(err); |
@@ -382,11 +414,11 @@ int EchoCancellationImpl::GetDelayMetrics(int* median, int* std, |
return AudioProcessing::kNullPointerError; |
} |
- if (!is_component_enabled() || !delay_logging_enabled_) { |
+ if (!enabled_ || !delay_logging_enabled_) { |
return AudioProcessing::kNotEnabledError; |
} |
- Handle* my_handle = static_cast<Handle*>(handle(0)); |
+ Handle* my_handle = cancellers_[0]->state(); |
const int err = |
WebRtcAec_GetDelayMetrics(my_handle, median, std, fraction_poor_delays); |
if (err != AudioProcessing::kNoError) { |
@@ -398,25 +430,37 @@ int EchoCancellationImpl::GetDelayMetrics(int* median, int* std, |
struct AecCore* EchoCancellationImpl::aec_core() const { |
rtc::CritScope cs(crit_capture_); |
- if (!is_component_enabled()) { |
+ if (!enabled_) { |
return NULL; |
} |
- Handle* my_handle = static_cast<Handle*>(handle(0)); |
+ Handle* my_handle = cancellers_[0]->state(); |
return WebRtcAec_aec_core(my_handle); |
} |
-int EchoCancellationImpl::Initialize() { |
- int err = ProcessingComponent::Initialize(); |
- { |
- rtc::CritScope cs(crit_capture_); |
- if (err != AudioProcessing::kNoError || !is_component_enabled()) { |
- return err; |
+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)); |
} |
} |
- AllocateRenderQueue(); |
+ for (size_t i = 0; i < cancellers_.size(); ++i) { |
+ cancellers_[i]->Initialize(sample_rate_hz); |
+ } |
- return AudioProcessing::kNoError; |
+ Configure(); |
+ |
+ AllocateRenderQueue(); |
} |
void EchoCancellationImpl::AllocateRenderQueue() { |
@@ -456,45 +500,30 @@ void EchoCancellationImpl::SetExtraOptions(const Config& config) { |
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 { |
+int EchoCancellationImpl::Configure() { |
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_; |
- 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); |
+ |
+ 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; |
} |
size_t EchoCancellationImpl::num_handles_required() const { |
@@ -502,9 +531,4 @@ size_t EchoCancellationImpl::num_handles_required() const { |
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 |