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 public: | |
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 int sample_rate_hz; | |
72 size_t num_reverse_channels; | |
73 size_t num_output_channels; | |
74 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_); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 } | 123 } |
107 | 124 |
108 EchoCancellationImpl::~EchoCancellationImpl() {} | 125 EchoCancellationImpl::~EchoCancellationImpl() {} |
109 | 126 |
110 int EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) { | 127 int EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) { |
111 rtc::CritScope cs_render(crit_render_); | 128 rtc::CritScope cs_render(crit_render_); |
112 if (!enabled_) { | 129 if (!enabled_) { |
113 return AudioProcessing::kNoError; | 130 return AudioProcessing::kNoError; |
114 } | 131 } |
115 | 132 |
133 RTC_DCHECK(!!stream_properties_); | |
116 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); | 134 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
117 RTC_DCHECK_EQ(audio->num_channels(), apm_->num_reverse_channels()); | 135 RTC_DCHECK_EQ(audio->num_channels(), |
118 RTC_DCHECK_GE(cancellers_.size(), | 136 stream_properties_->num_reverse_channels); |
119 apm_->num_output_channels() * audio->num_channels()); | 137 RTC_DCHECK_GE(cancellers_.size(), stream_properties_->num_output_channels * |
138 audio->num_channels()); | |
120 | 139 |
121 int err = AudioProcessing::kNoError; | 140 int err = AudioProcessing::kNoError; |
122 | 141 |
123 // The ordering convention must be followed to pass to the correct AEC. | 142 // The ordering convention must be followed to pass to the correct AEC. |
124 size_t handle_index = 0; | 143 size_t handle_index = 0; |
125 render_queue_buffer_.clear(); | 144 render_queue_buffer_.clear(); |
126 for (size_t i = 0; i < apm_->num_output_channels(); i++) { | 145 for (size_t i = 0; i < stream_properties_->num_output_channels; i++) { |
127 for (size_t j = 0; j < audio->num_channels(); j++) { | 146 for (size_t j = 0; j < audio->num_channels(); j++) { |
128 // Retrieve any error code produced by the buffering of the farend | 147 // Retrieve any error code produced by the buffering of the farend |
129 // signal. | 148 // signal. |
130 err = WebRtcAec_GetBufferFarendError( | 149 err = WebRtcAec_GetBufferFarendError( |
131 cancellers_[handle_index++]->state(), | 150 cancellers_[handle_index++]->state(), |
132 audio->split_bands_const_f(j)[kBand0To8kHz], | 151 audio->split_bands_const_f(j)[kBand0To8kHz], |
133 audio->num_frames_per_band()); | 152 audio->num_frames_per_band()); |
134 | 153 |
135 if (err != AudioProcessing::kNoError) { | 154 if (err != AudioProcessing::kNoError) { |
136 return MapError(err); // TODO(ajm): warning possible? | 155 return MapError(err); // TODO(ajm): warning possible? |
(...skipping 20 matching lines...) Expand all Loading... | |
157 } | 176 } |
158 | 177 |
159 // Read chunks of data that were received and queued on the render side from | 178 // 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. | 179 // a queue. All the data chunks are buffered into the farend signal of the AEC. |
161 void EchoCancellationImpl::ReadQueuedRenderData() { | 180 void EchoCancellationImpl::ReadQueuedRenderData() { |
162 rtc::CritScope cs_capture(crit_capture_); | 181 rtc::CritScope cs_capture(crit_capture_); |
163 if (!enabled_) { | 182 if (!enabled_) { |
164 return; | 183 return; |
165 } | 184 } |
166 | 185 |
186 RTC_DCHECK(!!stream_properties_); | |
167 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { | 187 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { |
168 size_t handle_index = 0; | 188 size_t handle_index = 0; |
169 size_t buffer_index = 0; | 189 size_t buffer_index = 0; |
170 const size_t num_frames_per_band = | 190 const size_t num_frames_per_band = |
171 capture_queue_buffer_.size() / | 191 capture_queue_buffer_.size() / |
172 (apm_->num_output_channels() * apm_->num_reverse_channels()); | 192 (stream_properties_->num_output_channels * |
173 for (size_t i = 0; i < apm_->num_output_channels(); i++) { | 193 stream_properties_->num_reverse_channels); |
174 for (size_t j = 0; j < apm_->num_reverse_channels(); j++) { | 194 for (size_t i = 0; i < stream_properties_->num_output_channels; i++) { |
195 for (size_t j = 0; j < stream_properties_->num_reverse_channels; j++) { | |
175 WebRtcAec_BufferFarend(cancellers_[handle_index++]->state(), | 196 WebRtcAec_BufferFarend(cancellers_[handle_index++]->state(), |
176 &capture_queue_buffer_[buffer_index], | 197 &capture_queue_buffer_[buffer_index], |
177 num_frames_per_band); | 198 num_frames_per_band); |
178 | 199 |
179 buffer_index += num_frames_per_band; | 200 buffer_index += num_frames_per_band; |
180 } | 201 } |
181 } | 202 } |
182 } | 203 } |
183 } | 204 } |
184 | 205 |
185 int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) { | 206 int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio, |
207 int stream_delay_ms) { | |
186 rtc::CritScope cs_capture(crit_capture_); | 208 rtc::CritScope cs_capture(crit_capture_); |
187 if (!enabled_) { | 209 if (!enabled_) { |
188 return AudioProcessing::kNoError; | 210 return AudioProcessing::kNoError; |
189 } | 211 } |
190 | 212 |
191 if (!apm_->was_stream_delay_set()) { | |
192 return AudioProcessing::kStreamParameterNotSetError; | |
193 } | |
194 | |
195 if (drift_compensation_enabled_ && !was_stream_drift_set_) { | 213 if (drift_compensation_enabled_ && !was_stream_drift_set_) { |
196 return AudioProcessing::kStreamParameterNotSetError; | 214 return AudioProcessing::kStreamParameterNotSetError; |
197 } | 215 } |
198 | 216 |
217 RTC_DCHECK(!!stream_properties_); | |
199 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); | 218 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
200 RTC_DCHECK_EQ(audio->num_channels(), apm_->num_proc_channels()); | 219 RTC_DCHECK_EQ(audio->num_channels(), stream_properties_->num_proc_channels); |
201 | 220 |
202 int err = AudioProcessing::kNoError; | 221 int err = AudioProcessing::kNoError; |
203 | 222 |
204 // The ordering convention must be followed to pass to the correct AEC. | 223 // The ordering convention must be followed to pass to the correct AEC. |
205 size_t handle_index = 0; | 224 size_t handle_index = 0; |
206 stream_has_echo_ = false; | 225 stream_has_echo_ = false; |
207 for (size_t i = 0; i < audio->num_channels(); i++) { | 226 for (size_t i = 0; i < audio->num_channels(); i++) { |
208 for (size_t j = 0; j < apm_->num_reverse_channels(); j++) { | 227 for (size_t j = 0; j < stream_properties_->num_reverse_channels; j++) { |
209 err = WebRtcAec_Process(cancellers_[handle_index]->state(), | 228 err = WebRtcAec_Process( |
210 audio->split_bands_const_f(i), audio->num_bands(), | 229 cancellers_[handle_index]->state(), audio->split_bands_const_f(i), |
211 audio->split_bands_f(i), | 230 audio->num_bands(), audio->split_bands_f(i), |
212 audio->num_frames_per_band(), | 231 audio->num_frames_per_band(), stream_delay_ms, stream_drift_samples_); |
213 apm_->stream_delay_ms(), stream_drift_samples_); | |
214 | 232 |
215 if (err != AudioProcessing::kNoError) { | 233 if (err != AudioProcessing::kNoError) { |
216 err = MapError(err); | 234 err = MapError(err); |
217 // TODO(ajm): Figure out how to return warnings properly. | 235 // TODO(ajm): Figure out how to return warnings properly. |
218 if (err != AudioProcessing::kBadStreamParameterWarning) { | 236 if (err != AudioProcessing::kBadStreamParameterWarning) { |
219 return err; | 237 return err; |
220 } | 238 } |
221 } | 239 } |
222 | 240 |
223 int status = 0; | 241 int status = 0; |
(...skipping 12 matching lines...) Expand all Loading... | |
236 } | 254 } |
237 | 255 |
238 was_stream_drift_set_ = false; | 256 was_stream_drift_set_ = false; |
239 return AudioProcessing::kNoError; | 257 return AudioProcessing::kNoError; |
240 } | 258 } |
241 | 259 |
242 int EchoCancellationImpl::Enable(bool enable) { | 260 int EchoCancellationImpl::Enable(bool enable) { |
243 // Run in a single-threaded manner. | 261 // Run in a single-threaded manner. |
244 rtc::CritScope cs_render(crit_render_); | 262 rtc::CritScope cs_render(crit_render_); |
245 rtc::CritScope cs_capture(crit_capture_); | 263 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()) { | |
peah-webrtc
2016/03/07 13:12:40
Please examine this change carefully as it is actu
| |
250 return AudioProcessing::kBadParameterError; | |
251 } | |
252 | 264 |
253 if (enable && !enabled_) { | 265 if (enable && !enabled_) { |
254 enabled_ = enable; // Must be set before Initialize() is called. | 266 enabled_ = enable; // Must be set before Initialize() is called. |
255 Initialize(); | 267 |
268 // TODO(peah): Simplify once the Enable function has been removed from | |
269 // the public APM API. | |
270 RTC_DCHECK(!!stream_properties_); | |
271 Initialize(stream_properties_->sample_rate_hz, | |
272 stream_properties_->num_reverse_channels, | |
273 stream_properties_->num_output_channels, | |
274 stream_properties_->num_proc_channels); | |
256 } else { | 275 } else { |
257 enabled_ = enable; | 276 enabled_ = enable; |
258 } | 277 } |
259 return AudioProcessing::kNoError; | 278 return AudioProcessing::kNoError; |
260 } | 279 } |
261 | 280 |
262 bool EchoCancellationImpl::is_enabled() const { | 281 bool EchoCancellationImpl::is_enabled() const { |
263 rtc::CritScope cs(crit_capture_); | 282 rtc::CritScope cs(crit_capture_); |
264 return enabled_; | 283 return enabled_; |
265 } | 284 } |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
426 } | 445 } |
427 | 446 |
428 struct AecCore* EchoCancellationImpl::aec_core() const { | 447 struct AecCore* EchoCancellationImpl::aec_core() const { |
429 rtc::CritScope cs(crit_capture_); | 448 rtc::CritScope cs(crit_capture_); |
430 if (!enabled_) { | 449 if (!enabled_) { |
431 return NULL; | 450 return NULL; |
432 } | 451 } |
433 return WebRtcAec_aec_core(cancellers_[0]->state()); | 452 return WebRtcAec_aec_core(cancellers_[0]->state()); |
434 } | 453 } |
435 | 454 |
436 void EchoCancellationImpl::Initialize() { | 455 void EchoCancellationImpl::Initialize(int sample_rate_hz, |
456 size_t num_reverse_channels, | |
457 size_t num_output_channels, | |
458 size_t num_proc_channels) { | |
437 rtc::CritScope cs_render(crit_render_); | 459 rtc::CritScope cs_render(crit_render_); |
438 rtc::CritScope cs_capture(crit_capture_); | 460 rtc::CritScope cs_capture(crit_capture_); |
461 | |
462 stream_properties_.reset( | |
463 new StreamProperties(sample_rate_hz, num_reverse_channels, | |
464 num_output_channels, num_proc_channels)); | |
465 | |
439 if (!enabled_) { | 466 if (!enabled_) { |
440 return; | 467 return; |
441 } | 468 } |
442 | 469 |
443 if (num_handles_required() > cancellers_.size()) { | 470 if (NumCancellersRequired() > cancellers_.size()) { |
444 const size_t cancellers_old_size = cancellers_.size(); | 471 const size_t cancellers_old_size = cancellers_.size(); |
445 cancellers_.resize(num_handles_required()); | 472 cancellers_.resize(NumCancellersRequired()); |
446 | 473 |
447 for (size_t i = cancellers_old_size; i < cancellers_.size(); ++i) { | 474 for (size_t i = cancellers_old_size; i < cancellers_.size(); ++i) { |
448 cancellers_[i].reset(new Canceller()); | 475 cancellers_[i].reset(new Canceller()); |
449 } | 476 } |
450 } | 477 } |
451 | 478 |
452 const int sample_rate_hz = apm_->proc_sample_rate_hz(); | |
453 for (auto& canceller : cancellers_) { | 479 for (auto& canceller : cancellers_) { |
454 canceller->Initialize(sample_rate_hz); | 480 canceller->Initialize(sample_rate_hz); |
455 } | 481 } |
456 | 482 |
457 Configure(); | 483 Configure(); |
458 | 484 |
459 AllocateRenderQueue(); | 485 AllocateRenderQueue(); |
460 } | 486 } |
461 | 487 |
462 int EchoCancellationImpl::GetSystemDelayInSamples() const { | 488 int EchoCancellationImpl::GetSystemDelayInSamples() const { |
463 rtc::CritScope cs(crit_capture_); | 489 rtc::CritScope cs(crit_capture_); |
464 RTC_DCHECK(enabled_); | 490 RTC_DCHECK(enabled_); |
465 // Report the delay for the first AEC component. | 491 // Report the delay for the first AEC component. |
466 return WebRtcAec_system_delay( | 492 return WebRtcAec_system_delay( |
467 WebRtcAec_aec_core(cancellers_[0]->state())); | 493 WebRtcAec_aec_core(cancellers_[0]->state())); |
468 } | 494 } |
469 | 495 |
470 void EchoCancellationImpl::AllocateRenderQueue() { | 496 void EchoCancellationImpl::AllocateRenderQueue() { |
471 const size_t new_render_queue_element_max_size = std::max<size_t>( | 497 const size_t new_render_queue_element_max_size = std::max<size_t>( |
472 static_cast<size_t>(1), | 498 static_cast<size_t>(1), |
473 kMaxAllowedValuesOfSamplesPerFrame * num_handles_required()); | 499 kMaxAllowedValuesOfSamplesPerFrame * NumCancellersRequired()); |
474 | 500 |
475 rtc::CritScope cs_render(crit_render_); | 501 rtc::CritScope cs_render(crit_render_); |
476 rtc::CritScope cs_capture(crit_capture_); | 502 rtc::CritScope cs_capture(crit_capture_); |
477 | 503 |
478 // Reallocate the queue if the queue item size is too small to fit the | 504 // Reallocate the queue if the queue item size is too small to fit the |
479 // data to put in the queue. | 505 // data to put in the queue. |
480 if (render_queue_element_max_size_ < new_render_queue_element_max_size) { | 506 if (render_queue_element_max_size_ < new_render_queue_element_max_size) { |
481 render_queue_element_max_size_ = new_render_queue_element_max_size; | 507 render_queue_element_max_size_ = new_render_queue_element_max_size; |
482 | 508 |
483 std::vector<float> template_queue_element(render_queue_element_max_size_); | 509 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_next_generation_aec(WebRtcAec_aec_core(canceller->state()), | 548 WebRtcAec_enable_next_generation_aec(WebRtcAec_aec_core(canceller->state()), |
523 next_generation_aec_enabled_ ? 1 : 0); | 549 next_generation_aec_enabled_ ? 1 : 0); |
524 const int handle_error = WebRtcAec_set_config(canceller->state(), config); | 550 const int handle_error = WebRtcAec_set_config(canceller->state(), config); |
525 if (handle_error != AudioProcessing::kNoError) { | 551 if (handle_error != AudioProcessing::kNoError) { |
526 error = AudioProcessing::kNoError; | 552 error = AudioProcessing::kNoError; |
527 } | 553 } |
528 } | 554 } |
529 return error; | 555 return error; |
530 } | 556 } |
531 | 557 |
532 size_t EchoCancellationImpl::num_handles_required() const { | 558 size_t EchoCancellationImpl::NumCancellersRequired() const { |
533 // Not locked as it only relies on APM public API which is threadsafe. | 559 RTC_DCHECK(!!stream_properties_); |
534 return apm_->num_output_channels() * apm_->num_reverse_channels(); | 560 return stream_properties_->num_output_channels * |
561 stream_properties_->num_reverse_channels; | |
535 } | 562 } |
536 | 563 |
537 } // namespace webrtc | 564 } // namespace webrtc |
OLD | NEW |