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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 } | 52 } |
53 | 53 |
54 // Maximum length that a frame of samples can have. | 54 // Maximum length that a frame of samples can have. |
55 static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160; | 55 static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160; |
56 // Maximum number of frames to buffer in the render queue. | 56 // Maximum number of frames to buffer in the render queue. |
57 // TODO(peah): Decrease this once we properly handle hugely unbalanced | 57 // TODO(peah): Decrease this once we properly handle hugely unbalanced |
58 // reverse and forward call numbers. | 58 // reverse and forward call numbers. |
59 static const size_t kMaxNumFramesToBuffer = 100; | 59 static const size_t kMaxNumFramesToBuffer = 100; |
60 } // namespace | 60 } // namespace |
61 | 61 |
| 62 class EchoCancellationImpl::Canceller { |
| 63 public: |
| 64 explicit Canceller(int sample_rate_hz) { |
| 65 state_ = WebRtcAec_Create(); |
| 66 RTC_DCHECK(state_); |
| 67 } |
| 68 |
| 69 ~Canceller() { |
| 70 RTC_CHECK(state_); |
| 71 WebRtcAec_Free(state_); |
| 72 } |
| 73 |
| 74 Handle* state() { return state_; } |
| 75 |
| 76 void Initialize(int sample_rate_hz) { |
| 77 // TODO(ajm): Drift compensation is disabled in practice. If restored, it |
| 78 // should be managed internally and not depend on the hardware sample rate. |
| 79 // For now, just hardcode a 48 kHz value. |
| 80 const int error = WebRtcAec_Init(state_, sample_rate_hz, 48000); |
| 81 RTC_DCHECK_EQ(0, error); |
| 82 } |
| 83 |
| 84 private: |
| 85 Handle* state_; |
| 86 |
| 87 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Canceller); |
| 88 }; |
| 89 |
62 EchoCancellationImpl::EchoCancellationImpl(const AudioProcessing* apm, | 90 EchoCancellationImpl::EchoCancellationImpl(const AudioProcessing* apm, |
63 rtc::CriticalSection* crit_render, | 91 rtc::CriticalSection* crit_render, |
64 rtc::CriticalSection* crit_capture) | 92 rtc::CriticalSection* crit_capture) |
65 : ProcessingComponent(), | 93 : apm_(apm), |
66 apm_(apm), | |
67 crit_render_(crit_render), | 94 crit_render_(crit_render), |
68 crit_capture_(crit_capture), | 95 crit_capture_(crit_capture), |
69 drift_compensation_enabled_(false), | 96 drift_compensation_enabled_(false), |
70 metrics_enabled_(false), | 97 metrics_enabled_(false), |
71 suppression_level_(kModerateSuppression), | 98 suppression_level_(kModerateSuppression), |
72 stream_drift_samples_(0), | 99 stream_drift_samples_(0), |
73 was_stream_drift_set_(false), | 100 was_stream_drift_set_(false), |
74 stream_has_echo_(false), | 101 stream_has_echo_(false), |
75 delay_logging_enabled_(false), | 102 delay_logging_enabled_(false), |
76 extended_filter_enabled_(false), | 103 extended_filter_enabled_(false), |
77 delay_agnostic_enabled_(false), | 104 delay_agnostic_enabled_(false), |
78 next_generation_aec_enabled_(false), | 105 next_generation_aec_enabled_(false), |
79 render_queue_element_max_size_(0) { | 106 render_queue_element_max_size_(0) { |
80 RTC_DCHECK(apm); | 107 RTC_DCHECK(apm); |
81 RTC_DCHECK(crit_render); | 108 RTC_DCHECK(crit_render); |
82 RTC_DCHECK(crit_capture); | 109 RTC_DCHECK(crit_capture); |
83 } | 110 } |
84 | 111 |
85 EchoCancellationImpl::~EchoCancellationImpl() {} | 112 EchoCancellationImpl::~EchoCancellationImpl() {} |
86 | 113 |
87 int EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) { | 114 int EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) { |
88 rtc::CritScope cs_render(crit_render_); | 115 rtc::CritScope cs_render(crit_render_); |
89 if (!is_component_enabled()) { | 116 if (!enabled_) { |
90 return AudioProcessing::kNoError; | 117 return AudioProcessing::kNoError; |
91 } | 118 } |
92 | 119 |
93 assert(audio->num_frames_per_band() <= 160); | 120 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
94 assert(audio->num_channels() == apm_->num_reverse_channels()); | 121 RTC_DCHECK_EQ(audio->num_channels(), apm_->num_reverse_channels()); |
| 122 RTC_DCHECK_GE(cancellers_.size(), |
| 123 apm_->num_output_channels() * audio->num_channels()); |
95 | 124 |
96 int err = AudioProcessing::kNoError; | 125 int err = AudioProcessing::kNoError; |
97 | 126 |
98 // The ordering convention must be followed to pass to the correct AEC. | 127 // The ordering convention must be followed to pass to the correct AEC. |
99 size_t handle_index = 0; | 128 size_t handle_index = 0; |
100 render_queue_buffer_.clear(); | 129 render_queue_buffer_.clear(); |
101 for (size_t i = 0; i < apm_->num_output_channels(); i++) { | 130 for (size_t i = 0; i < apm_->num_output_channels(); i++) { |
102 for (size_t j = 0; j < audio->num_channels(); j++) { | 131 for (size_t j = 0; j < audio->num_channels(); j++) { |
103 Handle* my_handle = static_cast<Handle*>(handle(handle_index)); | 132 Handle* my_handle = cancellers_[handle_index++]->state(); |
104 // Retrieve any error code produced by the buffering of the farend | 133 // Retrieve any error code produced by the buffering of the farend |
105 // signal | 134 // signal. |
106 err = WebRtcAec_GetBufferFarendError( | 135 err = WebRtcAec_GetBufferFarendError( |
107 my_handle, audio->split_bands_const_f(j)[kBand0To8kHz], | 136 my_handle, audio->split_bands_const_f(j)[kBand0To8kHz], |
108 audio->num_frames_per_band()); | 137 audio->num_frames_per_band()); |
109 | 138 |
110 if (err != AudioProcessing::kNoError) { | 139 if (err != AudioProcessing::kNoError) { |
111 return MapError(err); // TODO(ajm): warning possible? | 140 return MapError(err); // TODO(ajm): warning possible? |
112 } | 141 } |
113 | 142 |
114 // Buffer the samples in the render queue. | 143 // Buffer the samples in the render queue. |
115 render_queue_buffer_.insert(render_queue_buffer_.end(), | 144 render_queue_buffer_.insert(render_queue_buffer_.end(), |
116 audio->split_bands_const_f(j)[kBand0To8kHz], | 145 audio->split_bands_const_f(j)[kBand0To8kHz], |
117 (audio->split_bands_const_f(j)[kBand0To8kHz] + | 146 (audio->split_bands_const_f(j)[kBand0To8kHz] + |
118 audio->num_frames_per_band())); | 147 audio->num_frames_per_band())); |
119 | |
120 handle_index++; | |
121 } | 148 } |
122 } | 149 } |
123 | 150 |
124 // Insert the samples into the queue. | 151 // Insert the samples into the queue. |
125 if (!render_signal_queue_->Insert(&render_queue_buffer_)) { | 152 if (!render_signal_queue_->Insert(&render_queue_buffer_)) { |
126 // The data queue is full and needs to be emptied. | 153 // The data queue is full and needs to be emptied. |
127 ReadQueuedRenderData(); | 154 ReadQueuedRenderData(); |
128 | 155 |
129 // Retry the insert (should always work). | 156 // Retry the insert (should always work). |
130 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true); | 157 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true); |
131 } | 158 } |
132 | 159 |
133 return AudioProcessing::kNoError; | 160 return AudioProcessing::kNoError; |
134 } | 161 } |
135 | 162 |
136 // Read chunks of data that were received and queued on the render side from | 163 // Read chunks of data that were received and queued on the render side from |
137 // a queue. All the data chunks are buffered into the farend signal of the AEC. | 164 // a queue. All the data chunks are buffered into the farend signal of the AEC. |
138 void EchoCancellationImpl::ReadQueuedRenderData() { | 165 void EchoCancellationImpl::ReadQueuedRenderData() { |
139 rtc::CritScope cs_capture(crit_capture_); | 166 rtc::CritScope cs_capture(crit_capture_); |
140 if (!is_component_enabled()) { | 167 if (!enabled_) { |
141 return; | 168 return; |
142 } | 169 } |
143 | 170 |
144 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { | 171 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { |
145 size_t handle_index = 0; | 172 size_t handle_index = 0; |
146 size_t buffer_index = 0; | 173 size_t buffer_index = 0; |
147 const size_t num_frames_per_band = | 174 const size_t num_frames_per_band = |
148 capture_queue_buffer_.size() / | 175 capture_queue_buffer_.size() / |
149 (apm_->num_output_channels() * apm_->num_reverse_channels()); | 176 (apm_->num_output_channels() * apm_->num_reverse_channels()); |
150 for (size_t i = 0; i < apm_->num_output_channels(); i++) { | 177 for (size_t i = 0; i < apm_->num_output_channels(); i++) { |
151 for (size_t j = 0; j < apm_->num_reverse_channels(); j++) { | 178 for (size_t j = 0; j < apm_->num_reverse_channels(); j++) { |
152 Handle* my_handle = static_cast<Handle*>(handle(handle_index)); | 179 Handle* my_handle = cancellers_[handle_index++]->state(); |
153 WebRtcAec_BufferFarend(my_handle, &capture_queue_buffer_[buffer_index], | 180 WebRtcAec_BufferFarend(my_handle, &capture_queue_buffer_[buffer_index], |
154 num_frames_per_band); | 181 num_frames_per_band); |
155 | 182 |
156 buffer_index += num_frames_per_band; | 183 buffer_index += num_frames_per_band; |
157 handle_index++; | |
158 } | 184 } |
159 } | 185 } |
160 } | 186 } |
161 } | 187 } |
162 | 188 |
163 int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) { | 189 int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) { |
164 rtc::CritScope cs_capture(crit_capture_); | 190 rtc::CritScope cs_capture(crit_capture_); |
165 if (!is_component_enabled()) { | 191 if (!enabled_) { |
166 return AudioProcessing::kNoError; | 192 return AudioProcessing::kNoError; |
167 } | 193 } |
168 | 194 |
169 if (!apm_->was_stream_delay_set()) { | 195 if (!apm_->was_stream_delay_set()) { |
170 return AudioProcessing::kStreamParameterNotSetError; | 196 return AudioProcessing::kStreamParameterNotSetError; |
171 } | 197 } |
172 | 198 |
173 if (drift_compensation_enabled_ && !was_stream_drift_set_) { | 199 if (drift_compensation_enabled_ && !was_stream_drift_set_) { |
174 return AudioProcessing::kStreamParameterNotSetError; | 200 return AudioProcessing::kStreamParameterNotSetError; |
175 } | 201 } |
176 | 202 |
177 assert(audio->num_frames_per_band() <= 160); | 203 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
178 assert(audio->num_channels() == apm_->num_proc_channels()); | 204 RTC_DCHECK_EQ(audio->num_channels(), apm_->num_proc_channels()); |
179 | 205 |
180 int err = AudioProcessing::kNoError; | 206 int err = AudioProcessing::kNoError; |
181 | 207 |
182 // The ordering convention must be followed to pass to the correct AEC. | 208 // The ordering convention must be followed to pass to the correct AEC. |
183 size_t handle_index = 0; | 209 size_t handle_index = 0; |
184 stream_has_echo_ = false; | 210 stream_has_echo_ = false; |
185 for (size_t i = 0; i < audio->num_channels(); i++) { | 211 for (size_t i = 0; i < audio->num_channels(); i++) { |
186 for (size_t j = 0; j < apm_->num_reverse_channels(); j++) { | 212 for (size_t j = 0; j < apm_->num_reverse_channels(); j++) { |
187 Handle* my_handle = handle(handle_index); | 213 Handle* my_handle = cancellers_[handle_index++]->state(); |
188 err = WebRtcAec_Process(my_handle, audio->split_bands_const_f(i), | 214 err = WebRtcAec_Process(my_handle, audio->split_bands_const_f(i), |
189 audio->num_bands(), audio->split_bands_f(i), | 215 audio->num_bands(), audio->split_bands_f(i), |
190 audio->num_frames_per_band(), | 216 audio->num_frames_per_band(), |
191 apm_->stream_delay_ms(), stream_drift_samples_); | 217 apm_->stream_delay_ms(), stream_drift_samples_); |
192 | 218 |
193 if (err != AudioProcessing::kNoError) { | 219 if (err != AudioProcessing::kNoError) { |
194 err = MapError(err); | 220 err = MapError(err); |
195 // TODO(ajm): Figure out how to return warnings properly. | 221 // TODO(ajm): Figure out how to return warnings properly. |
196 if (err != AudioProcessing::kBadStreamParameterWarning) { | 222 if (err != AudioProcessing::kBadStreamParameterWarning) { |
197 return err; | 223 return err; |
198 } | 224 } |
199 } | 225 } |
200 | 226 |
201 int status = 0; | 227 int status = 0; |
202 err = WebRtcAec_get_echo_status(my_handle, &status); | 228 err = WebRtcAec_get_echo_status(my_handle, &status); |
203 if (err != AudioProcessing::kNoError) { | 229 if (err != AudioProcessing::kNoError) { |
204 return MapError(err); | 230 return MapError(err); |
205 } | 231 } |
206 | 232 |
207 if (status == 1) { | 233 if (status == 1) { |
208 stream_has_echo_ = true; | 234 stream_has_echo_ = true; |
209 } | 235 } |
210 | |
211 handle_index++; | |
212 } | 236 } |
213 } | 237 } |
214 | 238 |
215 was_stream_drift_set_ = false; | 239 was_stream_drift_set_ = false; |
216 return AudioProcessing::kNoError; | 240 return AudioProcessing::kNoError; |
217 } | 241 } |
218 | 242 |
219 int EchoCancellationImpl::Enable(bool enable) { | 243 int EchoCancellationImpl::Enable(bool enable) { |
220 // Run in a single-threaded manner. | 244 // Run in a single-threaded manner. |
221 rtc::CritScope cs_render(crit_render_); | 245 rtc::CritScope cs_render(crit_render_); |
222 rtc::CritScope cs_capture(crit_capture_); | 246 rtc::CritScope cs_capture(crit_capture_); |
223 // Ensure AEC and AECM are not both enabled. | 247 // Ensure AEC and AECM are not both enabled. |
224 // The is_enabled call is safe from a deadlock perspective | 248 // The is_enabled call is safe from a deadlock perspective |
225 // as both locks are already held in the correct order. | 249 // as both locks are already held in the correct order. |
226 if (enable && apm_->echo_control_mobile()->is_enabled()) { | 250 if (enable && apm_->echo_control_mobile()->is_enabled()) { |
227 return AudioProcessing::kBadParameterError; | 251 return AudioProcessing::kBadParameterError; |
228 } | 252 } |
229 | 253 |
230 return EnableComponent(enable); | 254 if (enable && !enabled_) { |
| 255 enabled_ = enable; // Must be set before Initialize() is called. |
| 256 Initialize(); |
| 257 } else { |
| 258 enabled_ = enable; |
| 259 } |
| 260 return AudioProcessing::kNoError; |
231 } | 261 } |
232 | 262 |
233 bool EchoCancellationImpl::is_enabled() const { | 263 bool EchoCancellationImpl::is_enabled() const { |
234 rtc::CritScope cs(crit_capture_); | 264 rtc::CritScope cs(crit_capture_); |
235 return is_component_enabled(); | 265 return enabled_; |
236 } | 266 } |
237 | 267 |
238 int EchoCancellationImpl::set_suppression_level(SuppressionLevel level) { | 268 int EchoCancellationImpl::set_suppression_level(SuppressionLevel level) { |
239 { | 269 { |
240 if (MapSetting(level) == -1) { | 270 if (MapSetting(level) == -1) { |
241 return AudioProcessing::kBadParameterError; | 271 return AudioProcessing::kBadParameterError; |
242 } | 272 } |
243 rtc::CritScope cs(crit_capture_); | 273 rtc::CritScope cs(crit_capture_); |
244 suppression_level_ = level; | 274 suppression_level_ = level; |
245 } | 275 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 } | 320 } |
291 | 321 |
292 // TODO(ajm): we currently just use the metrics from the first AEC. Think more | 322 // TODO(ajm): we currently just use the metrics from the first AEC. Think more |
293 // aboue the best way to extend this to multi-channel. | 323 // aboue the best way to extend this to multi-channel. |
294 int EchoCancellationImpl::GetMetrics(Metrics* metrics) { | 324 int EchoCancellationImpl::GetMetrics(Metrics* metrics) { |
295 rtc::CritScope cs(crit_capture_); | 325 rtc::CritScope cs(crit_capture_); |
296 if (metrics == NULL) { | 326 if (metrics == NULL) { |
297 return AudioProcessing::kNullPointerError; | 327 return AudioProcessing::kNullPointerError; |
298 } | 328 } |
299 | 329 |
300 if (!is_component_enabled() || !metrics_enabled_) { | 330 if (!enabled_ || !metrics_enabled_) { |
301 return AudioProcessing::kNotEnabledError; | 331 return AudioProcessing::kNotEnabledError; |
302 } | 332 } |
303 | 333 |
304 AecMetrics my_metrics; | 334 AecMetrics my_metrics; |
305 memset(&my_metrics, 0, sizeof(my_metrics)); | 335 memset(&my_metrics, 0, sizeof(my_metrics)); |
306 memset(metrics, 0, sizeof(Metrics)); | 336 memset(metrics, 0, sizeof(Metrics)); |
307 | 337 |
308 Handle* my_handle = static_cast<Handle*>(handle(0)); | 338 Handle* my_handle = cancellers_[0]->state(); |
309 int err = WebRtcAec_GetMetrics(my_handle, &my_metrics); | 339 int err = WebRtcAec_GetMetrics(my_handle, &my_metrics); |
310 if (err != AudioProcessing::kNoError) { | 340 if (err != AudioProcessing::kNoError) { |
311 return MapError(err); | 341 return MapError(err); |
312 } | 342 } |
313 | 343 |
314 metrics->residual_echo_return_loss.instant = my_metrics.rerl.instant; | 344 metrics->residual_echo_return_loss.instant = my_metrics.rerl.instant; |
315 metrics->residual_echo_return_loss.average = my_metrics.rerl.average; | 345 metrics->residual_echo_return_loss.average = my_metrics.rerl.average; |
316 metrics->residual_echo_return_loss.maximum = my_metrics.rerl.max; | 346 metrics->residual_echo_return_loss.maximum = my_metrics.rerl.max; |
317 metrics->residual_echo_return_loss.minimum = my_metrics.rerl.min; | 347 metrics->residual_echo_return_loss.minimum = my_metrics.rerl.min; |
318 | 348 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 int EchoCancellationImpl::GetDelayMetrics(int* median, int* std, | 407 int EchoCancellationImpl::GetDelayMetrics(int* median, int* std, |
378 float* fraction_poor_delays) { | 408 float* fraction_poor_delays) { |
379 rtc::CritScope cs(crit_capture_); | 409 rtc::CritScope cs(crit_capture_); |
380 if (median == NULL) { | 410 if (median == NULL) { |
381 return AudioProcessing::kNullPointerError; | 411 return AudioProcessing::kNullPointerError; |
382 } | 412 } |
383 if (std == NULL) { | 413 if (std == NULL) { |
384 return AudioProcessing::kNullPointerError; | 414 return AudioProcessing::kNullPointerError; |
385 } | 415 } |
386 | 416 |
387 if (!is_component_enabled() || !delay_logging_enabled_) { | 417 if (!enabled_ || !delay_logging_enabled_) { |
388 return AudioProcessing::kNotEnabledError; | 418 return AudioProcessing::kNotEnabledError; |
389 } | 419 } |
390 | 420 |
391 Handle* my_handle = static_cast<Handle*>(handle(0)); | 421 Handle* my_handle = cancellers_[0]->state(); |
392 const int err = | 422 const int err = |
393 WebRtcAec_GetDelayMetrics(my_handle, median, std, fraction_poor_delays); | 423 WebRtcAec_GetDelayMetrics(my_handle, median, std, fraction_poor_delays); |
394 if (err != AudioProcessing::kNoError) { | 424 if (err != AudioProcessing::kNoError) { |
395 return MapError(err); | 425 return MapError(err); |
396 } | 426 } |
397 | 427 |
398 return AudioProcessing::kNoError; | 428 return AudioProcessing::kNoError; |
399 } | 429 } |
400 | 430 |
401 struct AecCore* EchoCancellationImpl::aec_core() const { | 431 struct AecCore* EchoCancellationImpl::aec_core() const { |
402 rtc::CritScope cs(crit_capture_); | 432 rtc::CritScope cs(crit_capture_); |
403 if (!is_component_enabled()) { | 433 if (!enabled_) { |
404 return NULL; | 434 return NULL; |
405 } | 435 } |
406 Handle* my_handle = static_cast<Handle*>(handle(0)); | 436 Handle* my_handle = cancellers_[0]->state(); |
407 return WebRtcAec_aec_core(my_handle); | 437 return WebRtcAec_aec_core(my_handle); |
408 } | 438 } |
409 | 439 |
410 int EchoCancellationImpl::Initialize() { | 440 void EchoCancellationImpl::Initialize() { |
411 int err = ProcessingComponent::Initialize(); | 441 rtc::CritScope cs_render(crit_render_); |
412 { | 442 rtc::CritScope cs_capture(crit_capture_); |
413 rtc::CritScope cs(crit_capture_); | 443 if (!enabled_) { |
414 if (err != AudioProcessing::kNoError || !is_component_enabled()) { | 444 return; |
415 return err; | 445 } |
| 446 const int sample_rate_hz = apm_->proc_sample_rate_hz(); |
| 447 |
| 448 if (num_handles_required() > cancellers_.size()) { |
| 449 const size_t cancellers_old_size = cancellers_.size(); |
| 450 cancellers_.resize(num_handles_required()); |
| 451 |
| 452 for (size_t i = cancellers_old_size; i < cancellers_.size(); ++i) { |
| 453 cancellers_[i].reset(new Canceller(sample_rate_hz)); |
416 } | 454 } |
417 } | 455 } |
418 | 456 |
| 457 for (size_t i = 0; i < cancellers_.size(); ++i) { |
| 458 cancellers_[i]->Initialize(sample_rate_hz); |
| 459 } |
| 460 |
| 461 Configure(); |
| 462 |
419 AllocateRenderQueue(); | 463 AllocateRenderQueue(); |
420 | |
421 return AudioProcessing::kNoError; | |
422 } | 464 } |
423 | 465 |
424 int EchoCancellationImpl::GetSystemDelayInSamples() const { | 466 int EchoCancellationImpl::GetSystemDelayInSamples() const { |
425 rtc::CritScope cs(crit_capture_); | 467 rtc::CritScope cs(crit_capture_); |
426 RTC_DCHECK(is_component_enabled()); | 468 RTC_DCHECK(enabled_); |
427 // Report the delay for the first AEC component. | 469 // Report the delay for the first AEC component. |
428 return WebRtcAec_system_delay( | 470 return WebRtcAec_system_delay( |
429 WebRtcAec_aec_core(static_cast<Handle*>(handle(0)))); | 471 WebRtcAec_aec_core(cancellers_[0]->state())); |
430 } | 472 } |
431 | 473 |
432 void EchoCancellationImpl::AllocateRenderQueue() { | 474 void EchoCancellationImpl::AllocateRenderQueue() { |
433 const size_t new_render_queue_element_max_size = std::max<size_t>( | 475 const size_t new_render_queue_element_max_size = std::max<size_t>( |
434 static_cast<size_t>(1), | 476 static_cast<size_t>(1), |
435 kMaxAllowedValuesOfSamplesPerFrame * num_handles_required()); | 477 kMaxAllowedValuesOfSamplesPerFrame * num_handles_required()); |
436 | 478 |
437 rtc::CritScope cs_render(crit_render_); | 479 rtc::CritScope cs_render(crit_render_); |
438 rtc::CritScope cs_capture(crit_capture_); | 480 rtc::CritScope cs_capture(crit_capture_); |
439 | 481 |
(...skipping 19 matching lines...) Expand all Loading... |
459 void EchoCancellationImpl::SetExtraOptions(const Config& config) { | 501 void EchoCancellationImpl::SetExtraOptions(const Config& config) { |
460 { | 502 { |
461 rtc::CritScope cs(crit_capture_); | 503 rtc::CritScope cs(crit_capture_); |
462 extended_filter_enabled_ = config.Get<ExtendedFilter>().enabled; | 504 extended_filter_enabled_ = config.Get<ExtendedFilter>().enabled; |
463 delay_agnostic_enabled_ = config.Get<DelayAgnostic>().enabled; | 505 delay_agnostic_enabled_ = config.Get<DelayAgnostic>().enabled; |
464 next_generation_aec_enabled_ = config.Get<NextGenerationAec>().enabled; | 506 next_generation_aec_enabled_ = config.Get<NextGenerationAec>().enabled; |
465 } | 507 } |
466 Configure(); | 508 Configure(); |
467 } | 509 } |
468 | 510 |
469 void* EchoCancellationImpl::CreateHandle() const { | 511 int EchoCancellationImpl::Configure() { |
470 return WebRtcAec_Create(); | |
471 } | |
472 | |
473 void EchoCancellationImpl::DestroyHandle(void* handle) const { | |
474 assert(handle != NULL); | |
475 WebRtcAec_Free(static_cast<Handle*>(handle)); | |
476 } | |
477 | |
478 int EchoCancellationImpl::InitializeHandle(void* handle) const { | |
479 // Not locked as it only relies on APM public API which is threadsafe. | |
480 | |
481 assert(handle != NULL); | |
482 // TODO(ajm): Drift compensation is disabled in practice. If restored, it | |
483 // should be managed internally and not depend on the hardware sample rate. | |
484 // For now, just hardcode a 48 kHz value. | |
485 return WebRtcAec_Init(static_cast<Handle*>(handle), | |
486 apm_->proc_sample_rate_hz(), 48000); | |
487 } | |
488 | |
489 int EchoCancellationImpl::ConfigureHandle(void* handle) const { | |
490 rtc::CritScope cs_render(crit_render_); | 512 rtc::CritScope cs_render(crit_render_); |
491 rtc::CritScope cs_capture(crit_capture_); | 513 rtc::CritScope cs_capture(crit_capture_); |
492 assert(handle != NULL); | |
493 AecConfig config; | 514 AecConfig config; |
494 config.metricsMode = metrics_enabled_; | 515 config.metricsMode = metrics_enabled_; |
495 config.nlpMode = MapSetting(suppression_level_); | 516 config.nlpMode = MapSetting(suppression_level_); |
496 config.skewMode = drift_compensation_enabled_; | 517 config.skewMode = drift_compensation_enabled_; |
497 config.delay_logging = delay_logging_enabled_; | 518 config.delay_logging = delay_logging_enabled_; |
498 WebRtcAec_enable_extended_filter( | 519 |
499 WebRtcAec_aec_core(static_cast<Handle*>(handle)), | 520 int error = AudioProcessing::kNoError; |
500 extended_filter_enabled_ ? 1 : 0); | 521 for (size_t i = 0; i < cancellers_.size(); i++) { |
501 WebRtcAec_enable_delay_agnostic( | 522 Handle* my_handle = cancellers_[i]->state(); |
502 WebRtcAec_aec_core(static_cast<Handle*>(handle)), | 523 WebRtcAec_enable_extended_filter(WebRtcAec_aec_core(my_handle), |
503 delay_agnostic_enabled_ ? 1 : 0); | 524 extended_filter_enabled_ ? 1 : 0); |
504 WebRtcAec_enable_next_generation_aec( | 525 WebRtcAec_enable_delay_agnostic(WebRtcAec_aec_core(my_handle), |
505 WebRtcAec_aec_core(static_cast<Handle*>(handle)), | 526 delay_agnostic_enabled_ ? 1 : 0); |
506 next_generation_aec_enabled_ ? 1 : 0); | 527 WebRtcAec_enable_next_generation_aec(WebRtcAec_aec_core(my_handle), |
507 return WebRtcAec_set_config(static_cast<Handle*>(handle), config); | 528 next_generation_aec_enabled_ ? 1 : 0); |
| 529 const int handle_error = WebRtcAec_set_config(my_handle, config); |
| 530 if (handle_error != AudioProcessing::kNoError) { |
| 531 error = AudioProcessing::kNoError; |
| 532 } |
| 533 } |
| 534 return error; |
508 } | 535 } |
509 | 536 |
510 size_t EchoCancellationImpl::num_handles_required() const { | 537 size_t EchoCancellationImpl::num_handles_required() const { |
511 // Not locked as it only relies on APM public API which is threadsafe. | 538 // Not locked as it only relies on APM public API which is threadsafe. |
512 return apm_->num_output_channels() * apm_->num_reverse_channels(); | 539 return apm_->num_output_channels() * apm_->num_reverse_channels(); |
513 } | 540 } |
514 | 541 |
515 int EchoCancellationImpl::GetHandleError(void* handle) const { | |
516 // Not locked as it does not rely on anything in the state. | |
517 assert(handle != NULL); | |
518 return AudioProcessing::kUnspecifiedError; | |
519 } | |
520 } // namespace webrtc | 542 } // namespace webrtc |
OLD | NEW |