Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include "webrtc/modules/audio_processing/echo_cancellation_impl.h" | 11 #include "webrtc/modules/audio_processing/echo_cancellation_impl.h" |
| 12 | 12 |
| 13 #include <assert.h> | 13 #include <assert.h> |
| 14 #include <string.h> | 14 #include <string.h> |
| 15 | 15 |
| 16 extern "C" { | 16 extern "C" { |
| 17 #include "webrtc/modules/audio_processing/aec/aec_core.h" | 17 #include "webrtc/modules/audio_processing/aec/aec_core.h" |
| 18 } | 18 } |
| 19 #include "webrtc/base/criticalsection.h" | |
| 19 #include "webrtc/modules/audio_processing/aec/include/echo_cancellation.h" | 20 #include "webrtc/modules/audio_processing/aec/include/echo_cancellation.h" |
| 20 #include "webrtc/modules/audio_processing/audio_buffer.h" | 21 #include "webrtc/modules/audio_processing/audio_buffer.h" |
| 21 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" | |
| 22 | 22 |
| 23 namespace webrtc { | 23 namespace webrtc { |
| 24 | 24 |
| 25 typedef void Handle; | 25 typedef void Handle; |
| 26 | 26 |
| 27 namespace { | 27 namespace { |
| 28 int16_t MapSetting(EchoCancellation::SuppressionLevel level) { | 28 int16_t MapSetting(EchoCancellation::SuppressionLevel level) { |
| 29 switch (level) { | 29 switch (level) { |
| 30 case EchoCancellation::kLowSuppression: | 30 case EchoCancellation::kLowSuppression: |
| 31 return kAecNlpConservative; | 31 return kAecNlpConservative; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 53 return AudioProcessing::kUnspecifiedError; | 53 return AudioProcessing::kUnspecifiedError; |
| 54 } | 54 } |
| 55 } | 55 } |
| 56 } // namespace | 56 } // namespace |
| 57 | 57 |
| 58 const size_t EchoCancellationImpl::kAllowedValuesOfSamplesPerFrame1; | 58 const size_t EchoCancellationImpl::kAllowedValuesOfSamplesPerFrame1; |
| 59 const size_t EchoCancellationImpl::kAllowedValuesOfSamplesPerFrame2; | 59 const size_t EchoCancellationImpl::kAllowedValuesOfSamplesPerFrame2; |
| 60 | 60 |
| 61 EchoCancellationImpl::EchoCancellationImpl( | 61 EchoCancellationImpl::EchoCancellationImpl( |
| 62 const AudioProcessing* apm, | 62 const AudioProcessing* apm, |
| 63 CriticalSectionWrapper* crit, | 63 rtc::CriticalSection* crit_render, |
| 64 rtc::CriticalSection* crit_capture, | |
| 64 rtc::ThreadChecker* render_thread_checker) | 65 rtc::ThreadChecker* render_thread_checker) |
| 65 : ProcessingComponent(), | 66 : ProcessingComponent(), |
| 66 apm_(apm), | 67 apm_(apm), |
| 67 crit_(crit), | 68 crit_render_(crit_render), |
| 69 crit_capture_(crit_capture), | |
| 68 render_thread_checker_(render_thread_checker), | 70 render_thread_checker_(render_thread_checker), |
| 69 drift_compensation_enabled_(false), | 71 drift_compensation_enabled_(false), |
| 70 metrics_enabled_(false), | 72 metrics_enabled_(false), |
| 71 suppression_level_(kModerateSuppression), | 73 suppression_level_(kModerateSuppression), |
| 72 stream_drift_samples_(0), | 74 stream_drift_samples_(0), |
| 73 was_stream_drift_set_(false), | 75 was_stream_drift_set_(false), |
| 74 stream_has_echo_(false), | 76 stream_has_echo_(false), |
| 75 delay_logging_enabled_(false), | 77 delay_logging_enabled_(false), |
| 76 extended_filter_enabled_(false), | 78 extended_filter_enabled_(false), |
| 77 delay_agnostic_enabled_(false), | 79 delay_agnostic_enabled_(false), |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 109 } | 111 } |
| 110 | 112 |
| 111 // Buffer the samples in the render queue. | 113 // Buffer the samples in the render queue. |
| 112 render_queue_buffer_.insert(render_queue_buffer_.end(), | 114 render_queue_buffer_.insert(render_queue_buffer_.end(), |
| 113 audio->split_bands_const_f(j)[kBand0To8kHz], | 115 audio->split_bands_const_f(j)[kBand0To8kHz], |
| 114 (audio->split_bands_const_f(j)[kBand0To8kHz] + | 116 (audio->split_bands_const_f(j)[kBand0To8kHz] + |
| 115 audio->num_frames_per_band())); | 117 audio->num_frames_per_band())); |
| 116 } | 118 } |
| 117 } | 119 } |
| 118 | 120 |
| 119 // Check of success is temporarily disabled as it breaks a unit test. | 121 // Insert the samples into the queue. |
| 120 // TODO(peah): Will be fixed in the next CL. | 122 bool success = render_signal_queue_->Insert(&render_queue_buffer_); |
|
hlundin-webrtc
2015/11/05 16:11:22
You don't need success.
if (!render_signal_queue_-
peah-webrtc
2015/11/06 09:54:32
Done.
| |
| 121 (void)render_signal_queue_->Insert(&render_queue_buffer_); | 123 if (!success) { |
| 124 // The data queue is full and needs to be emptied. | |
| 125 { | |
| 126 rtc::CritScope cs_capture(crit_capture_); | |
| 127 ReadQueuedRenderData(); | |
| 128 } | |
| 129 | |
| 130 // Retry the insert (should always work). | |
| 131 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true); | |
| 132 } | |
| 122 | 133 |
| 123 return apm_->kNoError; | 134 return apm_->kNoError; |
| 124 } | 135 } |
| 125 | 136 |
| 126 // Read chunks of data that were received and queued on the render side from | 137 // Read chunks of data that were received and queued on the render side from |
| 127 // a queue. All the data chunks are buffered into the farend signal of the AEC. | 138 // a queue. All the data chunks are buffered into the farend signal of the AEC. |
| 128 void EchoCancellationImpl::ReadQueuedRenderData() { | 139 void EchoCancellationImpl::ReadQueuedRenderData() { |
| 129 if (!is_component_enabled()) { | 140 if (!is_component_enabled()) { |
| 130 return; | 141 return; |
| 131 } | 142 } |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 203 | 214 |
| 204 handle_index++; | 215 handle_index++; |
| 205 } | 216 } |
| 206 } | 217 } |
| 207 | 218 |
| 208 was_stream_drift_set_ = false; | 219 was_stream_drift_set_ = false; |
| 209 return apm_->kNoError; | 220 return apm_->kNoError; |
| 210 } | 221 } |
| 211 | 222 |
| 212 int EchoCancellationImpl::Enable(bool enable) { | 223 int EchoCancellationImpl::Enable(bool enable) { |
| 213 CriticalSectionScoped crit_scoped(crit_); | 224 // Run in a single-threaded manner. |
| 225 rtc::CritScope cs_render(crit_render_); | |
| 226 rtc::CritScope cs_capture(crit_capture_); | |
| 214 // Ensure AEC and AECM are not both enabled. | 227 // Ensure AEC and AECM are not both enabled. |
| 215 if (enable && apm_->echo_control_mobile()->is_enabled()) { | 228 if (enable && apm_->echo_control_mobile()->is_enabled()) { |
| 216 return apm_->kBadParameterError; | 229 return apm_->kBadParameterError; |
| 217 } | 230 } |
| 218 | 231 |
| 219 return EnableComponent(enable); | 232 return EnableComponent(enable); |
| 220 } | 233 } |
| 221 | 234 |
| 222 bool EchoCancellationImpl::is_enabled() const { | 235 bool EchoCancellationImpl::is_enabled() const { |
| 236 rtc::CritScope cs(crit_capture_); | |
| 223 return is_component_enabled(); | 237 return is_component_enabled(); |
| 224 } | 238 } |
| 225 | 239 |
| 226 int EchoCancellationImpl::set_suppression_level(SuppressionLevel level) { | 240 int EchoCancellationImpl::set_suppression_level(SuppressionLevel level) { |
| 227 CriticalSectionScoped crit_scoped(crit_); | 241 rtc::CritScope cs(crit_capture_); |
| 228 if (MapSetting(level) == -1) { | 242 if (MapSetting(level) == -1) { |
| 229 return apm_->kBadParameterError; | 243 return apm_->kBadParameterError; |
| 230 } | 244 } |
| 231 | 245 |
| 232 suppression_level_ = level; | 246 suppression_level_ = level; |
| 233 return Configure(); | 247 return Configure(); |
| 234 } | 248 } |
| 235 | 249 |
| 236 EchoCancellation::SuppressionLevel EchoCancellationImpl::suppression_level() | 250 EchoCancellation::SuppressionLevel EchoCancellationImpl::suppression_level() |
| 237 const { | 251 const { |
| 252 rtc::CritScope cs(crit_capture_); | |
| 238 return suppression_level_; | 253 return suppression_level_; |
| 239 } | 254 } |
| 240 | 255 |
| 241 int EchoCancellationImpl::enable_drift_compensation(bool enable) { | 256 int EchoCancellationImpl::enable_drift_compensation(bool enable) { |
| 242 CriticalSectionScoped crit_scoped(crit_); | 257 rtc::CritScope cs(crit_capture_); |
| 243 drift_compensation_enabled_ = enable; | 258 drift_compensation_enabled_ = enable; |
| 244 return Configure(); | 259 return Configure(); |
| 245 } | 260 } |
| 246 | 261 |
| 247 bool EchoCancellationImpl::is_drift_compensation_enabled() const { | 262 bool EchoCancellationImpl::is_drift_compensation_enabled() const { |
| 263 rtc::CritScope cs(crit_capture_); | |
| 248 return drift_compensation_enabled_; | 264 return drift_compensation_enabled_; |
| 249 } | 265 } |
| 250 | 266 |
| 251 void EchoCancellationImpl::set_stream_drift_samples(int drift) { | 267 void EchoCancellationImpl::set_stream_drift_samples(int drift) { |
| 268 rtc::CritScope cs(crit_capture_); | |
| 252 was_stream_drift_set_ = true; | 269 was_stream_drift_set_ = true; |
| 253 stream_drift_samples_ = drift; | 270 stream_drift_samples_ = drift; |
| 254 } | 271 } |
| 255 | 272 |
| 256 int EchoCancellationImpl::stream_drift_samples() const { | 273 int EchoCancellationImpl::stream_drift_samples() const { |
| 274 rtc::CritScope cs(crit_capture_); | |
| 257 return stream_drift_samples_; | 275 return stream_drift_samples_; |
| 258 } | 276 } |
| 259 | 277 |
| 260 int EchoCancellationImpl::enable_metrics(bool enable) { | 278 int EchoCancellationImpl::enable_metrics(bool enable) { |
| 261 CriticalSectionScoped crit_scoped(crit_); | 279 rtc::CritScope cs(crit_capture_); |
| 262 metrics_enabled_ = enable; | 280 metrics_enabled_ = enable; |
| 263 return Configure(); | 281 return Configure(); |
| 264 } | 282 } |
| 265 | 283 |
| 266 bool EchoCancellationImpl::are_metrics_enabled() const { | 284 bool EchoCancellationImpl::are_metrics_enabled() const { |
| 285 rtc::CritScope cs(crit_capture_); | |
| 267 return metrics_enabled_; | 286 return metrics_enabled_; |
| 268 } | 287 } |
| 269 | 288 |
| 270 // TODO(ajm): we currently just use the metrics from the first AEC. Think more | 289 // TODO(ajm): we currently just use the metrics from the first AEC. Think more |
| 271 // aboue the best way to extend this to multi-channel. | 290 // aboue the best way to extend this to multi-channel. |
| 272 int EchoCancellationImpl::GetMetrics(Metrics* metrics) { | 291 int EchoCancellationImpl::GetMetrics(Metrics* metrics) { |
| 273 CriticalSectionScoped crit_scoped(crit_); | 292 rtc::CritScope cs(crit_capture_); |
| 274 if (metrics == NULL) { | 293 if (metrics == NULL) { |
| 275 return apm_->kNullPointerError; | 294 return apm_->kNullPointerError; |
| 276 } | 295 } |
| 277 | 296 |
| 278 if (!is_component_enabled() || !metrics_enabled_) { | 297 if (!is_component_enabled() || !metrics_enabled_) { |
| 279 return apm_->kNotEnabledError; | 298 return apm_->kNotEnabledError; |
| 280 } | 299 } |
| 281 | 300 |
| 282 AecMetrics my_metrics; | 301 AecMetrics my_metrics; |
| 283 memset(&my_metrics, 0, sizeof(my_metrics)); | 302 memset(&my_metrics, 0, sizeof(my_metrics)); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 306 | 325 |
| 307 metrics->a_nlp.instant = my_metrics.aNlp.instant; | 326 metrics->a_nlp.instant = my_metrics.aNlp.instant; |
| 308 metrics->a_nlp.average = my_metrics.aNlp.average; | 327 metrics->a_nlp.average = my_metrics.aNlp.average; |
| 309 metrics->a_nlp.maximum = my_metrics.aNlp.max; | 328 metrics->a_nlp.maximum = my_metrics.aNlp.max; |
| 310 metrics->a_nlp.minimum = my_metrics.aNlp.min; | 329 metrics->a_nlp.minimum = my_metrics.aNlp.min; |
| 311 | 330 |
| 312 return apm_->kNoError; | 331 return apm_->kNoError; |
| 313 } | 332 } |
| 314 | 333 |
| 315 bool EchoCancellationImpl::stream_has_echo() const { | 334 bool EchoCancellationImpl::stream_has_echo() const { |
| 316 return stream_has_echo_; | 335 // This is called both from within and from outside of APM, with and |
| 336 // without locks set. Hence the conditional lock handling below. | |
| 337 bool stream_has_echo; | |
| 338 if (crit_capture_->TryEnter()) { | |
|
hlundin-webrtc
2015/11/05 16:11:22
I don't understand this code, but I wonder if rtc:
peah-webrtc
2015/11/06 09:54:32
Sounds like that! Thanks!
Done.
| |
| 339 stream_has_echo = stream_has_echo_; | |
| 340 crit_capture_->Leave(); | |
| 341 } else { | |
| 342 stream_has_echo = stream_has_echo_; | |
| 343 } | |
| 344 return stream_has_echo; | |
| 317 } | 345 } |
| 318 | 346 |
| 319 int EchoCancellationImpl::enable_delay_logging(bool enable) { | 347 int EchoCancellationImpl::enable_delay_logging(bool enable) { |
| 320 CriticalSectionScoped crit_scoped(crit_); | 348 rtc::CritScope cs(crit_capture_); |
| 321 delay_logging_enabled_ = enable; | 349 delay_logging_enabled_ = enable; |
| 322 return Configure(); | 350 return Configure(); |
| 323 } | 351 } |
| 324 | 352 |
| 325 bool EchoCancellationImpl::is_delay_logging_enabled() const { | 353 bool EchoCancellationImpl::is_delay_logging_enabled() const { |
| 354 rtc::CritScope cs(crit_capture_); | |
| 326 return delay_logging_enabled_; | 355 return delay_logging_enabled_; |
| 327 } | 356 } |
| 328 | 357 |
| 329 bool EchoCancellationImpl::is_delay_agnostic_enabled() const { | 358 bool EchoCancellationImpl::is_delay_agnostic_enabled() const { |
| 359 // Only called from within APM, hence no locking is needed. | |
| 330 return delay_agnostic_enabled_; | 360 return delay_agnostic_enabled_; |
| 331 } | 361 } |
| 332 | 362 |
| 333 bool EchoCancellationImpl::is_extended_filter_enabled() const { | 363 bool EchoCancellationImpl::is_extended_filter_enabled() const { |
| 364 // Only called from within APM, hence no locking is needed. | |
| 334 return extended_filter_enabled_; | 365 return extended_filter_enabled_; |
| 335 } | 366 } |
| 336 | 367 |
| 337 // TODO(bjornv): How should we handle the multi-channel case? | 368 // TODO(bjornv): How should we handle the multi-channel case? |
| 338 int EchoCancellationImpl::GetDelayMetrics(int* median, int* std) { | 369 int EchoCancellationImpl::GetDelayMetrics(int* median, int* std) { |
| 370 rtc::CritScope cs(crit_capture_); | |
| 339 float fraction_poor_delays = 0; | 371 float fraction_poor_delays = 0; |
| 340 return GetDelayMetrics(median, std, &fraction_poor_delays); | 372 return GetDelayMetrics(median, std, &fraction_poor_delays); |
| 341 } | 373 } |
| 342 | 374 |
| 343 int EchoCancellationImpl::GetDelayMetrics(int* median, int* std, | 375 int EchoCancellationImpl::GetDelayMetrics(int* median, int* std, |
| 344 float* fraction_poor_delays) { | 376 float* fraction_poor_delays) { |
| 345 CriticalSectionScoped crit_scoped(crit_); | 377 rtc::CritScope cs(crit_capture_); |
| 346 if (median == NULL) { | 378 if (median == NULL) { |
| 347 return apm_->kNullPointerError; | 379 return apm_->kNullPointerError; |
| 348 } | 380 } |
| 349 if (std == NULL) { | 381 if (std == NULL) { |
| 350 return apm_->kNullPointerError; | 382 return apm_->kNullPointerError; |
| 351 } | 383 } |
| 352 | 384 |
| 353 if (!is_component_enabled() || !delay_logging_enabled_) { | 385 if (!is_component_enabled() || !delay_logging_enabled_) { |
| 354 return apm_->kNotEnabledError; | 386 return apm_->kNotEnabledError; |
| 355 } | 387 } |
| 356 | 388 |
| 357 Handle* my_handle = static_cast<Handle*>(handle(0)); | 389 Handle* my_handle = static_cast<Handle*>(handle(0)); |
| 358 const int err = | 390 const int err = |
| 359 WebRtcAec_GetDelayMetrics(my_handle, median, std, fraction_poor_delays); | 391 WebRtcAec_GetDelayMetrics(my_handle, median, std, fraction_poor_delays); |
| 360 if (err != apm_->kNoError) { | 392 if (err != apm_->kNoError) { |
| 361 return MapError(err); | 393 return MapError(err); |
| 362 } | 394 } |
| 363 | 395 |
| 364 return apm_->kNoError; | 396 return apm_->kNoError; |
| 365 } | 397 } |
| 366 | 398 |
| 367 struct AecCore* EchoCancellationImpl::aec_core() const { | 399 struct AecCore* EchoCancellationImpl::aec_core() const { |
| 368 CriticalSectionScoped crit_scoped(crit_); | 400 // Only called from within APM, hence no locking is needed. |
| 369 if (!is_component_enabled()) { | 401 if (!is_component_enabled()) { |
| 370 return NULL; | 402 return NULL; |
| 371 } | 403 } |
| 372 Handle* my_handle = static_cast<Handle*>(handle(0)); | 404 Handle* my_handle = static_cast<Handle*>(handle(0)); |
| 373 return WebRtcAec_aec_core(my_handle); | 405 return WebRtcAec_aec_core(my_handle); |
| 374 } | 406 } |
| 375 | 407 |
| 376 int EchoCancellationImpl::Initialize() { | 408 int EchoCancellationImpl::Initialize() { |
| 409 // Only called from within APM, hence no locking is needed. | |
| 377 int err = ProcessingComponent::Initialize(); | 410 int err = ProcessingComponent::Initialize(); |
| 378 if (err != apm_->kNoError || !is_component_enabled()) { | 411 if (err != apm_->kNoError || !is_component_enabled()) { |
| 379 return err; | 412 return err; |
| 380 } | 413 } |
| 381 | 414 |
| 382 AllocateRenderQueue(); | 415 AllocateRenderQueue(); |
| 383 | 416 |
| 384 return apm_->kNoError; | 417 return apm_->kNoError; |
| 385 } | 418 } |
| 386 | 419 |
| 387 void EchoCancellationImpl::AllocateRenderQueue() { | 420 void EchoCancellationImpl::AllocateRenderQueue() { |
| 421 // Only called from within APM, hence no locking is needed. | |
| 388 const size_t max_frame_size = std::max(kAllowedValuesOfSamplesPerFrame1, | 422 const size_t max_frame_size = std::max(kAllowedValuesOfSamplesPerFrame1, |
| 389 kAllowedValuesOfSamplesPerFrame2); | 423 kAllowedValuesOfSamplesPerFrame2); |
| 390 | 424 |
| 391 const size_t new_render_queue_element_max_size = | 425 const size_t new_render_queue_element_max_size = |
| 392 std::max(1UL, max_frame_size * num_handles_required()); | 426 std::max(1UL, max_frame_size * num_handles_required()); |
| 393 | 427 |
| 394 // Reallocate the queue if the queue item size is too small to fit the | 428 // Reallocate the queue if the queue item size is too small to fit the |
| 395 // data to put in the queue. | 429 // data to put in the queue. |
| 396 if (new_render_queue_element_max_size > render_queue_element_max_size_) { | 430 if (new_render_queue_element_max_size > render_queue_element_max_size_) { |
| 397 render_queue_element_max_size_ = new_render_queue_element_max_size; | 431 render_queue_element_max_size_ = new_render_queue_element_max_size; |
| 398 | 432 |
| 399 std::vector<float> template_queue_element(render_queue_element_max_size_); | 433 std::vector<float> template_queue_element(render_queue_element_max_size_); |
| 400 | 434 |
| 401 render_signal_queue_.reset( | 435 render_signal_queue_.reset( |
| 402 new SwapQueue<std::vector<float>, AecRenderQueueItemVerifier>( | 436 new SwapQueue<std::vector<float>, AecRenderQueueItemVerifier>( |
| 403 kMaxNumFramesToBuffer, | 437 kMaxNumFramesToBuffer, |
| 404 AecRenderQueueItemVerifier(render_queue_element_max_size_), | 438 AecRenderQueueItemVerifier(render_queue_element_max_size_), |
| 405 template_queue_element)); | 439 template_queue_element)); |
| 406 } else { | 440 } else { |
| 407 render_signal_queue_->Clear(); | 441 render_signal_queue_->Clear(); |
| 408 } | 442 } |
| 409 | 443 |
| 410 render_queue_buffer_.resize(new_render_queue_element_max_size); | 444 render_queue_buffer_.resize(new_render_queue_element_max_size); |
| 411 capture_queue_buffer_.resize(new_render_queue_element_max_size); | 445 capture_queue_buffer_.resize(new_render_queue_element_max_size); |
| 412 } | 446 } |
| 413 | 447 |
| 414 void EchoCancellationImpl::SetExtraOptions(const Config& config) { | 448 void EchoCancellationImpl::SetExtraOptions(const Config& config) { |
| 449 // This is called both from within and from outside of APM, with and | |
| 450 // without locks set. Hence the conditional lock handling below. | |
| 451 bool locked_locally = crit_capture_->TryEnter(); | |
| 415 extended_filter_enabled_ = config.Get<ExtendedFilter>().enabled; | 452 extended_filter_enabled_ = config.Get<ExtendedFilter>().enabled; |
| 416 delay_agnostic_enabled_ = config.Get<DelayAgnostic>().enabled; | 453 delay_agnostic_enabled_ = config.Get<DelayAgnostic>().enabled; |
| 417 Configure(); | 454 Configure(); |
| 455 if (locked_locally) { | |
| 456 crit_capture_->Leave(); | |
| 457 } | |
| 418 } | 458 } |
| 419 | 459 |
| 420 void* EchoCancellationImpl::CreateHandle() const { | 460 void* EchoCancellationImpl::CreateHandle() const { |
| 461 // Only called from within APM, hence no locking is needed. | |
| 421 return WebRtcAec_Create(); | 462 return WebRtcAec_Create(); |
| 422 } | 463 } |
| 423 | 464 |
| 424 void EchoCancellationImpl::DestroyHandle(void* handle) const { | 465 void EchoCancellationImpl::DestroyHandle(void* handle) const { |
| 466 // Only called from within APM, hence no locking is needed. | |
| 425 assert(handle != NULL); | 467 assert(handle != NULL); |
| 426 WebRtcAec_Free(static_cast<Handle*>(handle)); | 468 WebRtcAec_Free(static_cast<Handle*>(handle)); |
| 427 } | 469 } |
| 428 | 470 |
| 429 int EchoCancellationImpl::InitializeHandle(void* handle) const { | 471 int EchoCancellationImpl::InitializeHandle(void* handle) const { |
| 472 // Only called from within APM, hence no locking is needed. | |
| 430 assert(handle != NULL); | 473 assert(handle != NULL); |
| 431 // TODO(ajm): Drift compensation is disabled in practice. If restored, it | 474 // TODO(ajm): Drift compensation is disabled in practice. If restored, it |
| 432 // should be managed internally and not depend on the hardware sample rate. | 475 // should be managed internally and not depend on the hardware sample rate. |
| 433 // For now, just hardcode a 48 kHz value. | 476 // For now, just hardcode a 48 kHz value. |
| 434 return WebRtcAec_Init(static_cast<Handle*>(handle), | 477 return WebRtcAec_Init(static_cast<Handle*>(handle), |
| 435 apm_->proc_sample_rate_hz(), | 478 apm_->proc_sample_rate_hz(), |
| 436 48000); | 479 48000); |
| 437 } | 480 } |
| 438 | 481 |
| 439 int EchoCancellationImpl::ConfigureHandle(void* handle) const { | 482 int EchoCancellationImpl::ConfigureHandle(void* handle) const { |
| 483 // Only called from within APM, hence no locking is needed. | |
| 440 assert(handle != NULL); | 484 assert(handle != NULL); |
| 441 AecConfig config; | 485 AecConfig config; |
| 442 config.metricsMode = metrics_enabled_; | 486 config.metricsMode = metrics_enabled_; |
| 443 config.nlpMode = MapSetting(suppression_level_); | 487 config.nlpMode = MapSetting(suppression_level_); |
| 444 config.skewMode = drift_compensation_enabled_; | 488 config.skewMode = drift_compensation_enabled_; |
| 445 config.delay_logging = delay_logging_enabled_; | 489 config.delay_logging = delay_logging_enabled_; |
| 446 | 490 |
| 447 WebRtcAec_enable_extended_filter( | 491 WebRtcAec_enable_extended_filter( |
| 448 WebRtcAec_aec_core(static_cast<Handle*>(handle)), | 492 WebRtcAec_aec_core(static_cast<Handle*>(handle)), |
| 449 extended_filter_enabled_ ? 1 : 0); | 493 extended_filter_enabled_ ? 1 : 0); |
| 450 WebRtcAec_enable_delay_agnostic( | 494 WebRtcAec_enable_delay_agnostic( |
| 451 WebRtcAec_aec_core(static_cast<Handle*>(handle)), | 495 WebRtcAec_aec_core(static_cast<Handle*>(handle)), |
| 452 delay_agnostic_enabled_ ? 1 : 0); | 496 delay_agnostic_enabled_ ? 1 : 0); |
| 453 return WebRtcAec_set_config(static_cast<Handle*>(handle), config); | 497 return WebRtcAec_set_config(static_cast<Handle*>(handle), config); |
| 454 } | 498 } |
| 455 | 499 |
| 456 int EchoCancellationImpl::num_handles_required() const { | 500 int EchoCancellationImpl::num_handles_required() const { |
| 501 // Only called from within APM, hence no locking is needed. | |
| 457 return apm_->num_output_channels() * | 502 return apm_->num_output_channels() * |
| 458 apm_->num_reverse_channels(); | 503 apm_->num_reverse_channels(); |
| 459 } | 504 } |
| 460 | 505 |
| 461 int EchoCancellationImpl::GetHandleError(void* handle) const { | 506 int EchoCancellationImpl::GetHandleError(void* handle) const { |
| 507 // Only called from within APM, hence no locking is needed. | |
| 462 assert(handle != NULL); | 508 assert(handle != NULL); |
| 463 return AudioProcessing::kUnspecifiedError; | 509 return AudioProcessing::kUnspecifiedError; |
| 464 } | 510 } |
| 465 | 511 |
| 466 } // namespace webrtc | 512 } // namespace webrtc |
| OLD | NEW |