| 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 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 } | 50 } |
| 51 | 51 |
| 52 // Maximum length that a frame of samples can have. | 52 // Maximum length that a frame of samples can have. |
| 53 static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160; | 53 static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160; |
| 54 // Maximum number of frames to buffer in the render queue. | 54 // Maximum number of frames to buffer in the render queue. |
| 55 // TODO(peah): Decrease this once we properly handle hugely unbalanced | 55 // TODO(peah): Decrease this once we properly handle hugely unbalanced |
| 56 // reverse and forward call numbers. | 56 // reverse and forward call numbers. |
| 57 static const size_t kMaxNumFramesToBuffer = 100; | 57 static const size_t kMaxNumFramesToBuffer = 100; |
| 58 } // namespace | 58 } // namespace |
| 59 | 59 |
| 60 struct EchoCancellationImpl::StreamProperties { |
| 61 StreamProperties() = delete; |
| 62 StreamProperties(int sample_rate_hz, |
| 63 size_t num_reverse_channels, |
| 64 size_t num_output_channels, |
| 65 size_t num_proc_channels) |
| 66 : sample_rate_hz(sample_rate_hz), |
| 67 num_reverse_channels(num_reverse_channels), |
| 68 num_output_channels(num_output_channels), |
| 69 num_proc_channels(num_proc_channels) {} |
| 70 |
| 71 const int sample_rate_hz; |
| 72 const size_t num_reverse_channels; |
| 73 const size_t num_output_channels; |
| 74 const size_t num_proc_channels; |
| 75 }; |
| 76 |
| 60 class EchoCancellationImpl::Canceller { | 77 class EchoCancellationImpl::Canceller { |
| 61 public: | 78 public: |
| 62 Canceller() { | 79 Canceller() { |
| 63 state_ = WebRtcAec_Create(); | 80 state_ = WebRtcAec_Create(); |
| 64 RTC_DCHECK(state_); | 81 RTC_DCHECK(state_); |
| 65 } | 82 } |
| 66 | 83 |
| 67 ~Canceller() { | 84 ~Canceller() { |
| 68 RTC_CHECK(state_); | 85 RTC_CHECK(state_); |
| 69 WebRtcAec_Free(state_); | 86 WebRtcAec_Free(state_); |
| 70 } | 87 } |
| 71 | 88 |
| 72 void* state() { return state_; } | 89 void* state() { return state_; } |
| 73 | 90 |
| 74 void Initialize(int sample_rate_hz) { | 91 void Initialize(int sample_rate_hz) { |
| 75 // TODO(ajm): Drift compensation is disabled in practice. If restored, it | 92 // TODO(ajm): Drift compensation is disabled in practice. If restored, it |
| 76 // should be managed internally and not depend on the hardware sample rate. | 93 // should be managed internally and not depend on the hardware sample rate. |
| 77 // For now, just hardcode a 48 kHz value. | 94 // For now, just hardcode a 48 kHz value. |
| 78 const int error = WebRtcAec_Init(state_, sample_rate_hz, 48000); | 95 const int error = WebRtcAec_Init(state_, sample_rate_hz, 48000); |
| 79 RTC_DCHECK_EQ(0, error); | 96 RTC_DCHECK_EQ(0, error); |
| 80 } | 97 } |
| 81 | 98 |
| 82 private: | 99 private: |
| 83 void* state_; | 100 void* state_; |
| 84 }; | 101 }; |
| 85 | 102 |
| 86 EchoCancellationImpl::EchoCancellationImpl(const AudioProcessing* apm, | 103 EchoCancellationImpl::EchoCancellationImpl(rtc::CriticalSection* crit_render, |
| 87 rtc::CriticalSection* crit_render, | |
| 88 rtc::CriticalSection* crit_capture) | 104 rtc::CriticalSection* crit_capture) |
| 89 : apm_(apm), | 105 : crit_render_(crit_render), |
| 90 crit_render_(crit_render), | |
| 91 crit_capture_(crit_capture), | 106 crit_capture_(crit_capture), |
| 92 drift_compensation_enabled_(false), | 107 drift_compensation_enabled_(false), |
| 93 metrics_enabled_(false), | 108 metrics_enabled_(false), |
| 94 suppression_level_(kModerateSuppression), | 109 suppression_level_(kModerateSuppression), |
| 95 stream_drift_samples_(0), | 110 stream_drift_samples_(0), |
| 96 was_stream_drift_set_(false), | 111 was_stream_drift_set_(false), |
| 97 stream_has_echo_(false), | 112 stream_has_echo_(false), |
| 98 delay_logging_enabled_(false), | 113 delay_logging_enabled_(false), |
| 99 extended_filter_enabled_(false), | 114 extended_filter_enabled_(false), |
| 100 delay_agnostic_enabled_(false), | 115 delay_agnostic_enabled_(false), |
| 101 aec3_enabled_(false), | 116 aec3_enabled_(false), |
| 102 render_queue_element_max_size_(0) { | 117 render_queue_element_max_size_(0) { |
| 103 RTC_DCHECK(apm); | |
| 104 RTC_DCHECK(crit_render); | 118 RTC_DCHECK(crit_render); |
| 105 RTC_DCHECK(crit_capture); | 119 RTC_DCHECK(crit_capture); |
| 106 } | 120 } |
| 107 | 121 |
| 108 EchoCancellationImpl::~EchoCancellationImpl() {} | 122 EchoCancellationImpl::~EchoCancellationImpl() {} |
| 109 | 123 |
| 110 int EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) { | 124 int EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) { |
| 111 rtc::CritScope cs_render(crit_render_); | 125 rtc::CritScope cs_render(crit_render_); |
| 112 if (!enabled_) { | 126 if (!enabled_) { |
| 113 return AudioProcessing::kNoError; | 127 return AudioProcessing::kNoError; |
| 114 } | 128 } |
| 115 | 129 |
| 130 RTC_DCHECK(stream_properties_); |
| 116 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); | 131 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
| 117 RTC_DCHECK_EQ(audio->num_channels(), apm_->num_reverse_channels()); | 132 RTC_DCHECK_EQ(audio->num_channels(), |
| 118 RTC_DCHECK_GE(cancellers_.size(), | 133 stream_properties_->num_reverse_channels); |
| 119 apm_->num_output_channels() * audio->num_channels()); | 134 RTC_DCHECK_GE(cancellers_.size(), stream_properties_->num_output_channels * |
| 135 audio->num_channels()); |
| 120 | 136 |
| 121 int err = AudioProcessing::kNoError; | 137 int err = AudioProcessing::kNoError; |
| 122 | 138 |
| 123 // The ordering convention must be followed to pass to the correct AEC. | 139 // The ordering convention must be followed to pass to the correct AEC. |
| 124 size_t handle_index = 0; | 140 size_t handle_index = 0; |
| 125 render_queue_buffer_.clear(); | 141 render_queue_buffer_.clear(); |
| 126 for (size_t i = 0; i < apm_->num_output_channels(); i++) { | 142 for (size_t i = 0; i < stream_properties_->num_output_channels; i++) { |
| 127 for (size_t j = 0; j < audio->num_channels(); j++) { | 143 for (size_t j = 0; j < audio->num_channels(); j++) { |
| 128 // Retrieve any error code produced by the buffering of the farend | 144 // Retrieve any error code produced by the buffering of the farend |
| 129 // signal. | 145 // signal. |
| 130 err = WebRtcAec_GetBufferFarendError( | 146 err = WebRtcAec_GetBufferFarendError( |
| 131 cancellers_[handle_index++]->state(), | 147 cancellers_[handle_index++]->state(), |
| 132 audio->split_bands_const_f(j)[kBand0To8kHz], | 148 audio->split_bands_const_f(j)[kBand0To8kHz], |
| 133 audio->num_frames_per_band()); | 149 audio->num_frames_per_band()); |
| 134 | 150 |
| 135 if (err != AudioProcessing::kNoError) { | 151 if (err != AudioProcessing::kNoError) { |
| 136 return MapError(err); // TODO(ajm): warning possible? | 152 return MapError(err); // TODO(ajm): warning possible? |
| (...skipping 20 matching lines...) Expand all Loading... |
| 157 } | 173 } |
| 158 | 174 |
| 159 // Read chunks of data that were received and queued on the render side from | 175 // Read chunks of data that were received and queued on the render side from |
| 160 // a queue. All the data chunks are buffered into the farend signal of the AEC. | 176 // a queue. All the data chunks are buffered into the farend signal of the AEC. |
| 161 void EchoCancellationImpl::ReadQueuedRenderData() { | 177 void EchoCancellationImpl::ReadQueuedRenderData() { |
| 162 rtc::CritScope cs_capture(crit_capture_); | 178 rtc::CritScope cs_capture(crit_capture_); |
| 163 if (!enabled_) { | 179 if (!enabled_) { |
| 164 return; | 180 return; |
| 165 } | 181 } |
| 166 | 182 |
| 183 RTC_DCHECK(stream_properties_); |
| 167 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { | 184 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { |
| 168 size_t handle_index = 0; | 185 size_t handle_index = 0; |
| 169 size_t buffer_index = 0; | 186 size_t buffer_index = 0; |
| 170 const size_t num_frames_per_band = | 187 const size_t num_frames_per_band = |
| 171 capture_queue_buffer_.size() / | 188 capture_queue_buffer_.size() / |
| 172 (apm_->num_output_channels() * apm_->num_reverse_channels()); | 189 (stream_properties_->num_output_channels * |
| 173 for (size_t i = 0; i < apm_->num_output_channels(); i++) { | 190 stream_properties_->num_reverse_channels); |
| 174 for (size_t j = 0; j < apm_->num_reverse_channels(); j++) { | 191 for (size_t i = 0; i < stream_properties_->num_output_channels; i++) { |
| 192 for (size_t j = 0; j < stream_properties_->num_reverse_channels; j++) { |
| 175 WebRtcAec_BufferFarend(cancellers_[handle_index++]->state(), | 193 WebRtcAec_BufferFarend(cancellers_[handle_index++]->state(), |
| 176 &capture_queue_buffer_[buffer_index], | 194 &capture_queue_buffer_[buffer_index], |
| 177 num_frames_per_band); | 195 num_frames_per_band); |
| 178 | 196 |
| 179 buffer_index += num_frames_per_band; | 197 buffer_index += num_frames_per_band; |
| 180 } | 198 } |
| 181 } | 199 } |
| 182 } | 200 } |
| 183 } | 201 } |
| 184 | 202 |
| 185 int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) { | 203 int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio, |
| 204 int stream_delay_ms) { |
| 186 rtc::CritScope cs_capture(crit_capture_); | 205 rtc::CritScope cs_capture(crit_capture_); |
| 187 if (!enabled_) { | 206 if (!enabled_) { |
| 188 return AudioProcessing::kNoError; | 207 return AudioProcessing::kNoError; |
| 189 } | 208 } |
| 190 | 209 |
| 191 if (!apm_->was_stream_delay_set()) { | |
| 192 return AudioProcessing::kStreamParameterNotSetError; | |
| 193 } | |
| 194 | |
| 195 if (drift_compensation_enabled_ && !was_stream_drift_set_) { | 210 if (drift_compensation_enabled_ && !was_stream_drift_set_) { |
| 196 return AudioProcessing::kStreamParameterNotSetError; | 211 return AudioProcessing::kStreamParameterNotSetError; |
| 197 } | 212 } |
| 198 | 213 |
| 214 RTC_DCHECK(stream_properties_); |
| 199 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); | 215 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
| 200 RTC_DCHECK_EQ(audio->num_channels(), apm_->num_proc_channels()); | 216 RTC_DCHECK_EQ(audio->num_channels(), stream_properties_->num_proc_channels); |
| 201 | 217 |
| 202 int err = AudioProcessing::kNoError; | 218 int err = AudioProcessing::kNoError; |
| 203 | 219 |
| 204 // The ordering convention must be followed to pass to the correct AEC. | 220 // The ordering convention must be followed to pass to the correct AEC. |
| 205 size_t handle_index = 0; | 221 size_t handle_index = 0; |
| 206 stream_has_echo_ = false; | 222 stream_has_echo_ = false; |
| 207 for (size_t i = 0; i < audio->num_channels(); i++) { | 223 for (size_t i = 0; i < audio->num_channels(); i++) { |
| 208 for (size_t j = 0; j < apm_->num_reverse_channels(); j++) { | 224 for (size_t j = 0; j < stream_properties_->num_reverse_channels; j++) { |
| 209 err = WebRtcAec_Process(cancellers_[handle_index]->state(), | 225 err = WebRtcAec_Process( |
| 210 audio->split_bands_const_f(i), audio->num_bands(), | 226 cancellers_[handle_index]->state(), audio->split_bands_const_f(i), |
| 211 audio->split_bands_f(i), | 227 audio->num_bands(), audio->split_bands_f(i), |
| 212 audio->num_frames_per_band(), | 228 audio->num_frames_per_band(), stream_delay_ms, stream_drift_samples_); |
| 213 apm_->stream_delay_ms(), stream_drift_samples_); | |
| 214 | 229 |
| 215 if (err != AudioProcessing::kNoError) { | 230 if (err != AudioProcessing::kNoError) { |
| 216 err = MapError(err); | 231 err = MapError(err); |
| 217 // TODO(ajm): Figure out how to return warnings properly. | 232 // TODO(ajm): Figure out how to return warnings properly. |
| 218 if (err != AudioProcessing::kBadStreamParameterWarning) { | 233 if (err != AudioProcessing::kBadStreamParameterWarning) { |
| 219 return err; | 234 return err; |
| 220 } | 235 } |
| 221 } | 236 } |
| 222 | 237 |
| 223 int status = 0; | 238 int status = 0; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 236 } | 251 } |
| 237 | 252 |
| 238 was_stream_drift_set_ = false; | 253 was_stream_drift_set_ = false; |
| 239 return AudioProcessing::kNoError; | 254 return AudioProcessing::kNoError; |
| 240 } | 255 } |
| 241 | 256 |
| 242 int EchoCancellationImpl::Enable(bool enable) { | 257 int EchoCancellationImpl::Enable(bool enable) { |
| 243 // Run in a single-threaded manner. | 258 // Run in a single-threaded manner. |
| 244 rtc::CritScope cs_render(crit_render_); | 259 rtc::CritScope cs_render(crit_render_); |
| 245 rtc::CritScope cs_capture(crit_capture_); | 260 rtc::CritScope cs_capture(crit_capture_); |
| 246 // Ensure AEC and AECM are not both enabled. | |
| 247 // The is_enabled call is safe from a deadlock perspective | |
| 248 // as both locks are already held in the correct order. | |
| 249 if (enable && apm_->echo_control_mobile()->is_enabled()) { | |
| 250 return AudioProcessing::kBadParameterError; | |
| 251 } | |
| 252 | 261 |
| 253 if (enable && !enabled_) { | 262 if (enable && !enabled_) { |
| 254 enabled_ = enable; // Must be set before Initialize() is called. | 263 enabled_ = enable; // Must be set before Initialize() is called. |
| 255 Initialize(); | 264 |
| 265 // TODO(peah): Simplify once the Enable function has been removed from |
| 266 // the public APM API. |
| 267 RTC_DCHECK(stream_properties_); |
| 268 Initialize(stream_properties_->sample_rate_hz, |
| 269 stream_properties_->num_reverse_channels, |
| 270 stream_properties_->num_output_channels, |
| 271 stream_properties_->num_proc_channels); |
| 256 } else { | 272 } else { |
| 257 enabled_ = enable; | 273 enabled_ = enable; |
| 258 } | 274 } |
| 259 return AudioProcessing::kNoError; | 275 return AudioProcessing::kNoError; |
| 260 } | 276 } |
| 261 | 277 |
| 262 bool EchoCancellationImpl::is_enabled() const { | 278 bool EchoCancellationImpl::is_enabled() const { |
| 263 rtc::CritScope cs(crit_capture_); | 279 rtc::CritScope cs(crit_capture_); |
| 264 return enabled_; | 280 return enabled_; |
| 265 } | 281 } |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 } | 442 } |
| 427 | 443 |
| 428 struct AecCore* EchoCancellationImpl::aec_core() const { | 444 struct AecCore* EchoCancellationImpl::aec_core() const { |
| 429 rtc::CritScope cs(crit_capture_); | 445 rtc::CritScope cs(crit_capture_); |
| 430 if (!enabled_) { | 446 if (!enabled_) { |
| 431 return NULL; | 447 return NULL; |
| 432 } | 448 } |
| 433 return WebRtcAec_aec_core(cancellers_[0]->state()); | 449 return WebRtcAec_aec_core(cancellers_[0]->state()); |
| 434 } | 450 } |
| 435 | 451 |
| 436 void EchoCancellationImpl::Initialize() { | 452 void EchoCancellationImpl::Initialize(int sample_rate_hz, |
| 453 size_t num_reverse_channels, |
| 454 size_t num_output_channels, |
| 455 size_t num_proc_channels) { |
| 437 rtc::CritScope cs_render(crit_render_); | 456 rtc::CritScope cs_render(crit_render_); |
| 438 rtc::CritScope cs_capture(crit_capture_); | 457 rtc::CritScope cs_capture(crit_capture_); |
| 458 |
| 459 stream_properties_.reset( |
| 460 new StreamProperties(sample_rate_hz, num_reverse_channels, |
| 461 num_output_channels, num_proc_channels)); |
| 462 |
| 439 if (!enabled_) { | 463 if (!enabled_) { |
| 440 return; | 464 return; |
| 441 } | 465 } |
| 442 | 466 |
| 443 if (num_handles_required() > cancellers_.size()) { | 467 if (NumCancellersRequired() > cancellers_.size()) { |
| 444 const size_t cancellers_old_size = cancellers_.size(); | 468 const size_t cancellers_old_size = cancellers_.size(); |
| 445 cancellers_.resize(num_handles_required()); | 469 cancellers_.resize(NumCancellersRequired()); |
| 446 | 470 |
| 447 for (size_t i = cancellers_old_size; i < cancellers_.size(); ++i) { | 471 for (size_t i = cancellers_old_size; i < cancellers_.size(); ++i) { |
| 448 cancellers_[i].reset(new Canceller()); | 472 cancellers_[i].reset(new Canceller()); |
| 449 } | 473 } |
| 450 } | 474 } |
| 451 | 475 |
| 452 const int sample_rate_hz = apm_->proc_sample_rate_hz(); | |
| 453 for (auto& canceller : cancellers_) { | 476 for (auto& canceller : cancellers_) { |
| 454 canceller->Initialize(sample_rate_hz); | 477 canceller->Initialize(sample_rate_hz); |
| 455 } | 478 } |
| 456 | 479 |
| 457 Configure(); | 480 Configure(); |
| 458 | 481 |
| 459 AllocateRenderQueue(); | 482 AllocateRenderQueue(); |
| 460 } | 483 } |
| 461 | 484 |
| 462 int EchoCancellationImpl::GetSystemDelayInSamples() const { | 485 int EchoCancellationImpl::GetSystemDelayInSamples() const { |
| 463 rtc::CritScope cs(crit_capture_); | 486 rtc::CritScope cs(crit_capture_); |
| 464 RTC_DCHECK(enabled_); | 487 RTC_DCHECK(enabled_); |
| 465 // Report the delay for the first AEC component. | 488 // Report the delay for the first AEC component. |
| 466 return WebRtcAec_system_delay( | 489 return WebRtcAec_system_delay( |
| 467 WebRtcAec_aec_core(cancellers_[0]->state())); | 490 WebRtcAec_aec_core(cancellers_[0]->state())); |
| 468 } | 491 } |
| 469 | 492 |
| 470 void EchoCancellationImpl::AllocateRenderQueue() { | 493 void EchoCancellationImpl::AllocateRenderQueue() { |
| 471 const size_t new_render_queue_element_max_size = std::max<size_t>( | 494 const size_t new_render_queue_element_max_size = std::max<size_t>( |
| 472 static_cast<size_t>(1), | 495 static_cast<size_t>(1), |
| 473 kMaxAllowedValuesOfSamplesPerFrame * num_handles_required()); | 496 kMaxAllowedValuesOfSamplesPerFrame * NumCancellersRequired()); |
| 474 | 497 |
| 475 rtc::CritScope cs_render(crit_render_); | 498 rtc::CritScope cs_render(crit_render_); |
| 476 rtc::CritScope cs_capture(crit_capture_); | 499 rtc::CritScope cs_capture(crit_capture_); |
| 477 | 500 |
| 478 // Reallocate the queue if the queue item size is too small to fit the | 501 // Reallocate the queue if the queue item size is too small to fit the |
| 479 // data to put in the queue. | 502 // data to put in the queue. |
| 480 if (render_queue_element_max_size_ < new_render_queue_element_max_size) { | 503 if (render_queue_element_max_size_ < new_render_queue_element_max_size) { |
| 481 render_queue_element_max_size_ = new_render_queue_element_max_size; | 504 render_queue_element_max_size_ = new_render_queue_element_max_size; |
| 482 | 505 |
| 483 std::vector<float> template_queue_element(render_queue_element_max_size_); | 506 std::vector<float> template_queue_element(render_queue_element_max_size_); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 WebRtcAec_enable_aec3(WebRtcAec_aec_core(canceller->state()), | 545 WebRtcAec_enable_aec3(WebRtcAec_aec_core(canceller->state()), |
| 523 aec3_enabled_ ? 1 : 0); | 546 aec3_enabled_ ? 1 : 0); |
| 524 const int handle_error = WebRtcAec_set_config(canceller->state(), config); | 547 const int handle_error = WebRtcAec_set_config(canceller->state(), config); |
| 525 if (handle_error != AudioProcessing::kNoError) { | 548 if (handle_error != AudioProcessing::kNoError) { |
| 526 error = AudioProcessing::kNoError; | 549 error = AudioProcessing::kNoError; |
| 527 } | 550 } |
| 528 } | 551 } |
| 529 return error; | 552 return error; |
| 530 } | 553 } |
| 531 | 554 |
| 532 size_t EchoCancellationImpl::num_handles_required() const { | 555 size_t EchoCancellationImpl::NumCancellersRequired() const { |
| 533 // Not locked as it only relies on APM public API which is threadsafe. | 556 RTC_DCHECK(stream_properties_); |
| 534 return apm_->num_output_channels() * apm_->num_reverse_channels(); | 557 return stream_properties_->num_output_channels * |
| 558 stream_properties_->num_reverse_channels; |
| 535 } | 559 } |
| 536 | 560 |
| 537 } // namespace webrtc | 561 } // namespace webrtc |
| OLD | NEW |