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_CHECK(state_); | |
67 } | |
68 | |
69 ~Canceller() { | |
70 RTC_CHECK(state_); | |
the sun
2016/03/03 13:13:05
DCHECK not CHECK here
peah-webrtc
2016/03/03 13:56:16
Done.
| |
71 WebRtcAec_Free(state_); | |
72 } | |
73 | |
74 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.
| |
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_EQ(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(), |
(...skipping 12 matching lines...) Expand all Loading... | |
128 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true); | 157 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true); |
129 } | 158 } |
130 | 159 |
131 return AudioProcessing::kNoError; | 160 return AudioProcessing::kNoError; |
132 } | 161 } |
133 | 162 |
134 // 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 |
135 // 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. |
136 void EchoCancellationImpl::ReadQueuedRenderData() { | 165 void EchoCancellationImpl::ReadQueuedRenderData() { |
137 rtc::CritScope cs_capture(crit_capture_); | 166 rtc::CritScope cs_capture(crit_capture_); |
138 if (!is_component_enabled()) { | 167 if (!enabled_) { |
139 return; | 168 return; |
140 } | 169 } |
141 | 170 |
142 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { | 171 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { |
143 size_t handle_index = 0; | 172 size_t handle_index = 0; |
144 size_t buffer_index = 0; | 173 size_t buffer_index = 0; |
145 const size_t num_frames_per_band = | 174 const size_t num_frames_per_band = |
146 capture_queue_buffer_.size() / | 175 capture_queue_buffer_.size() / |
147 (apm_->num_output_channels() * apm_->num_reverse_channels()); | 176 (apm_->num_output_channels() * apm_->num_reverse_channels()); |
148 for (size_t i = 0; i < apm_->num_output_channels(); i++) { | 177 for (size_t i = 0; i < apm_->num_output_channels(); i++) { |
149 for (size_t j = 0; j < apm_->num_reverse_channels(); j++) { | 178 for (size_t j = 0; j < apm_->num_reverse_channels(); j++) { |
150 Handle* my_handle = static_cast<Handle*>(handle(handle_index)); | 179 Handle* my_handle = cancellers_[handle_index++]->state(); |
151 WebRtcAec_BufferFarend(my_handle, &capture_queue_buffer_[buffer_index], | 180 WebRtcAec_BufferFarend(my_handle, &capture_queue_buffer_[buffer_index], |
152 num_frames_per_band); | 181 num_frames_per_band); |
153 | 182 |
154 buffer_index += num_frames_per_band; | 183 buffer_index += num_frames_per_band; |
155 handle_index++; | |
156 } | 184 } |
157 } | 185 } |
158 } | 186 } |
159 } | 187 } |
160 | 188 |
161 int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) { | 189 int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) { |
162 rtc::CritScope cs_capture(crit_capture_); | 190 rtc::CritScope cs_capture(crit_capture_); |
163 if (!is_component_enabled()) { | 191 if (!enabled_) { |
164 return AudioProcessing::kNoError; | 192 return AudioProcessing::kNoError; |
165 } | 193 } |
166 | 194 |
167 if (!apm_->was_stream_delay_set()) { | 195 if (!apm_->was_stream_delay_set()) { |
168 return AudioProcessing::kStreamParameterNotSetError; | 196 return AudioProcessing::kStreamParameterNotSetError; |
169 } | 197 } |
170 | 198 |
171 if (drift_compensation_enabled_ && !was_stream_drift_set_) { | 199 if (drift_compensation_enabled_ && !was_stream_drift_set_) { |
172 return AudioProcessing::kStreamParameterNotSetError; | 200 return AudioProcessing::kStreamParameterNotSetError; |
173 } | 201 } |
174 | 202 |
175 assert(audio->num_frames_per_band() <= 160); | 203 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
176 assert(audio->num_channels() == apm_->num_proc_channels()); | 204 RTC_DCHECK_EQ(audio->num_channels(), apm_->num_proc_channels()); |
177 | 205 |
178 int err = AudioProcessing::kNoError; | 206 int err = AudioProcessing::kNoError; |
179 | 207 |
180 // 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. |
181 size_t handle_index = 0; | 209 size_t handle_index = 0; |
182 stream_has_echo_ = false; | 210 stream_has_echo_ = false; |
183 for (size_t i = 0; i < audio->num_channels(); i++) { | 211 for (size_t i = 0; i < audio->num_channels(); i++) { |
184 for (size_t j = 0; j < apm_->num_reverse_channels(); j++) { | 212 for (size_t j = 0; j < apm_->num_reverse_channels(); j++) { |
185 Handle* my_handle = handle(handle_index); | 213 Handle* my_handle = cancellers_[handle_index++]->state(); |
186 err = WebRtcAec_Process(my_handle, audio->split_bands_const_f(i), | 214 err = WebRtcAec_Process(my_handle, audio->split_bands_const_f(i), |
187 audio->num_bands(), audio->split_bands_f(i), | 215 audio->num_bands(), audio->split_bands_f(i), |
188 audio->num_frames_per_band(), | 216 audio->num_frames_per_band(), |
189 apm_->stream_delay_ms(), stream_drift_samples_); | 217 apm_->stream_delay_ms(), stream_drift_samples_); |
190 | 218 |
191 if (err != AudioProcessing::kNoError) { | 219 if (err != AudioProcessing::kNoError) { |
192 err = MapError(err); | 220 err = MapError(err); |
193 // TODO(ajm): Figure out how to return warnings properly. | 221 // TODO(ajm): Figure out how to return warnings properly. |
194 if (err != AudioProcessing::kBadStreamParameterWarning) { | 222 if (err != AudioProcessing::kBadStreamParameterWarning) { |
195 return err; | 223 return err; |
196 } | 224 } |
197 } | 225 } |
198 | 226 |
199 int status = 0; | 227 int status = 0; |
200 err = WebRtcAec_get_echo_status(my_handle, &status); | 228 err = WebRtcAec_get_echo_status(my_handle, &status); |
201 if (err != AudioProcessing::kNoError) { | 229 if (err != AudioProcessing::kNoError) { |
202 return MapError(err); | 230 return MapError(err); |
203 } | 231 } |
204 | 232 |
205 if (status == 1) { | 233 if (status == 1) { |
206 stream_has_echo_ = true; | 234 stream_has_echo_ = true; |
207 } | 235 } |
208 | |
209 handle_index++; | |
210 } | 236 } |
211 } | 237 } |
212 | 238 |
213 was_stream_drift_set_ = false; | 239 was_stream_drift_set_ = false; |
214 return AudioProcessing::kNoError; | 240 return AudioProcessing::kNoError; |
215 } | 241 } |
216 | 242 |
217 int EchoCancellationImpl::Enable(bool enable) { | 243 int EchoCancellationImpl::Enable(bool enable) { |
218 // Run in a single-threaded manner. | 244 // Run in a single-threaded manner. |
219 rtc::CritScope cs_render(crit_render_); | 245 rtc::CritScope cs_render(crit_render_); |
220 rtc::CritScope cs_capture(crit_capture_); | 246 rtc::CritScope cs_capture(crit_capture_); |
221 // Ensure AEC and AECM are not both enabled. | 247 // Ensure AEC and AECM are not both enabled. |
222 // The is_enabled call is safe from a deadlock perspective | 248 // The is_enabled call is safe from a deadlock perspective |
223 // as both locks are already held in the correct order. | 249 // as both locks are already held in the correct order. |
224 if (enable && apm_->echo_control_mobile()->is_enabled()) { | 250 if (enable && apm_->echo_control_mobile()->is_enabled()) { |
225 return AudioProcessing::kBadParameterError; | 251 return AudioProcessing::kBadParameterError; |
226 } | 252 } |
227 | 253 |
228 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; | |
229 } | 261 } |
230 | 262 |
231 bool EchoCancellationImpl::is_enabled() const { | 263 bool EchoCancellationImpl::is_enabled() const { |
232 rtc::CritScope cs(crit_capture_); | 264 rtc::CritScope cs(crit_capture_); |
233 return is_component_enabled(); | 265 return enabled_; |
234 } | 266 } |
235 | 267 |
236 int EchoCancellationImpl::set_suppression_level(SuppressionLevel level) { | 268 int EchoCancellationImpl::set_suppression_level(SuppressionLevel level) { |
237 { | 269 { |
238 if (MapSetting(level) == -1) { | 270 if (MapSetting(level) == -1) { |
239 return AudioProcessing::kBadParameterError; | 271 return AudioProcessing::kBadParameterError; |
240 } | 272 } |
241 rtc::CritScope cs(crit_capture_); | 273 rtc::CritScope cs(crit_capture_); |
242 suppression_level_ = level; | 274 suppression_level_ = level; |
243 } | 275 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
288 } | 320 } |
289 | 321 |
290 // 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 |
291 // aboue the best way to extend this to multi-channel. | 323 // aboue the best way to extend this to multi-channel. |
292 int EchoCancellationImpl::GetMetrics(Metrics* metrics) { | 324 int EchoCancellationImpl::GetMetrics(Metrics* metrics) { |
293 rtc::CritScope cs(crit_capture_); | 325 rtc::CritScope cs(crit_capture_); |
294 if (metrics == NULL) { | 326 if (metrics == NULL) { |
295 return AudioProcessing::kNullPointerError; | 327 return AudioProcessing::kNullPointerError; |
296 } | 328 } |
297 | 329 |
298 if (!is_component_enabled() || !metrics_enabled_) { | 330 if (!enabled_ || !metrics_enabled_) { |
299 return AudioProcessing::kNotEnabledError; | 331 return AudioProcessing::kNotEnabledError; |
300 } | 332 } |
301 | 333 |
302 AecMetrics my_metrics; | 334 AecMetrics my_metrics; |
303 memset(&my_metrics, 0, sizeof(my_metrics)); | 335 memset(&my_metrics, 0, sizeof(my_metrics)); |
304 memset(metrics, 0, sizeof(Metrics)); | 336 memset(metrics, 0, sizeof(Metrics)); |
305 | 337 |
306 Handle* my_handle = static_cast<Handle*>(handle(0)); | 338 Handle* my_handle = cancellers_[0]->state(); |
307 int err = WebRtcAec_GetMetrics(my_handle, &my_metrics); | 339 int err = WebRtcAec_GetMetrics(my_handle, &my_metrics); |
308 if (err != AudioProcessing::kNoError) { | 340 if (err != AudioProcessing::kNoError) { |
309 return MapError(err); | 341 return MapError(err); |
310 } | 342 } |
311 | 343 |
312 metrics->residual_echo_return_loss.instant = my_metrics.rerl.instant; | 344 metrics->residual_echo_return_loss.instant = my_metrics.rerl.instant; |
313 metrics->residual_echo_return_loss.average = my_metrics.rerl.average; | 345 metrics->residual_echo_return_loss.average = my_metrics.rerl.average; |
314 metrics->residual_echo_return_loss.maximum = my_metrics.rerl.max; | 346 metrics->residual_echo_return_loss.maximum = my_metrics.rerl.max; |
315 metrics->residual_echo_return_loss.minimum = my_metrics.rerl.min; | 347 metrics->residual_echo_return_loss.minimum = my_metrics.rerl.min; |
316 | 348 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
375 int EchoCancellationImpl::GetDelayMetrics(int* median, int* std, | 407 int EchoCancellationImpl::GetDelayMetrics(int* median, int* std, |
376 float* fraction_poor_delays) { | 408 float* fraction_poor_delays) { |
377 rtc::CritScope cs(crit_capture_); | 409 rtc::CritScope cs(crit_capture_); |
378 if (median == NULL) { | 410 if (median == NULL) { |
379 return AudioProcessing::kNullPointerError; | 411 return AudioProcessing::kNullPointerError; |
380 } | 412 } |
381 if (std == NULL) { | 413 if (std == NULL) { |
382 return AudioProcessing::kNullPointerError; | 414 return AudioProcessing::kNullPointerError; |
383 } | 415 } |
384 | 416 |
385 if (!is_component_enabled() || !delay_logging_enabled_) { | 417 if (!enabled_ || !delay_logging_enabled_) { |
386 return AudioProcessing::kNotEnabledError; | 418 return AudioProcessing::kNotEnabledError; |
387 } | 419 } |
388 | 420 |
389 Handle* my_handle = static_cast<Handle*>(handle(0)); | 421 Handle* my_handle = cancellers_[0]->state(); |
390 const int err = | 422 const int err = |
391 WebRtcAec_GetDelayMetrics(my_handle, median, std, fraction_poor_delays); | 423 WebRtcAec_GetDelayMetrics(my_handle, median, std, fraction_poor_delays); |
392 if (err != AudioProcessing::kNoError) { | 424 if (err != AudioProcessing::kNoError) { |
393 return MapError(err); | 425 return MapError(err); |
394 } | 426 } |
395 | 427 |
396 return AudioProcessing::kNoError; | 428 return AudioProcessing::kNoError; |
397 } | 429 } |
398 | 430 |
399 struct AecCore* EchoCancellationImpl::aec_core() const { | 431 struct AecCore* EchoCancellationImpl::aec_core() const { |
400 rtc::CritScope cs(crit_capture_); | 432 rtc::CritScope cs(crit_capture_); |
401 if (!is_component_enabled()) { | 433 if (!enabled_) { |
402 return NULL; | 434 return NULL; |
403 } | 435 } |
404 Handle* my_handle = static_cast<Handle*>(handle(0)); | 436 Handle* my_handle = cancellers_[0]->state(); |
405 return WebRtcAec_aec_core(my_handle); | 437 return WebRtcAec_aec_core(my_handle); |
406 } | 438 } |
407 | 439 |
408 int EchoCancellationImpl::Initialize() { | 440 void EchoCancellationImpl::Initialize() { |
409 int err = ProcessingComponent::Initialize(); | 441 rtc::CritScope cs_render(crit_render_); |
410 { | 442 rtc::CritScope cs_capture(crit_capture_); |
411 rtc::CritScope cs(crit_capture_); | 443 if (!enabled_) { |
412 if (err != AudioProcessing::kNoError || !is_component_enabled()) { | 444 return; |
413 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)); | |
414 } | 454 } |
415 } | 455 } |
416 | 456 |
457 for (size_t i = 0; i < cancellers_.size(); ++i) { | |
458 cancellers_[i]->Initialize(sample_rate_hz); | |
459 } | |
460 | |
461 Configure(); | |
462 | |
417 AllocateRenderQueue(); | 463 AllocateRenderQueue(); |
418 | |
419 return AudioProcessing::kNoError; | |
420 } | 464 } |
421 | 465 |
422 void EchoCancellationImpl::AllocateRenderQueue() { | 466 void EchoCancellationImpl::AllocateRenderQueue() { |
423 const size_t new_render_queue_element_max_size = std::max<size_t>( | 467 const size_t new_render_queue_element_max_size = std::max<size_t>( |
424 static_cast<size_t>(1), | 468 static_cast<size_t>(1), |
425 kMaxAllowedValuesOfSamplesPerFrame * num_handles_required()); | 469 kMaxAllowedValuesOfSamplesPerFrame * num_handles_required()); |
426 | 470 |
427 rtc::CritScope cs_render(crit_render_); | 471 rtc::CritScope cs_render(crit_render_); |
428 rtc::CritScope cs_capture(crit_capture_); | 472 rtc::CritScope cs_capture(crit_capture_); |
429 | 473 |
(...skipping 19 matching lines...) Expand all Loading... | |
449 void EchoCancellationImpl::SetExtraOptions(const Config& config) { | 493 void EchoCancellationImpl::SetExtraOptions(const Config& config) { |
450 { | 494 { |
451 rtc::CritScope cs(crit_capture_); | 495 rtc::CritScope cs(crit_capture_); |
452 extended_filter_enabled_ = config.Get<ExtendedFilter>().enabled; | 496 extended_filter_enabled_ = config.Get<ExtendedFilter>().enabled; |
453 delay_agnostic_enabled_ = config.Get<DelayAgnostic>().enabled; | 497 delay_agnostic_enabled_ = config.Get<DelayAgnostic>().enabled; |
454 next_generation_aec_enabled_ = config.Get<NextGenerationAec>().enabled; | 498 next_generation_aec_enabled_ = config.Get<NextGenerationAec>().enabled; |
455 } | 499 } |
456 Configure(); | 500 Configure(); |
457 } | 501 } |
458 | 502 |
459 void* EchoCancellationImpl::CreateHandle() const { | 503 int EchoCancellationImpl::Configure() { |
460 return WebRtcAec_Create(); | |
461 } | |
462 | |
463 void EchoCancellationImpl::DestroyHandle(void* handle) const { | |
464 assert(handle != NULL); | |
465 WebRtcAec_Free(static_cast<Handle*>(handle)); | |
466 } | |
467 | |
468 int EchoCancellationImpl::InitializeHandle(void* handle) const { | |
469 // Not locked as it only relies on APM public API which is threadsafe. | |
470 | |
471 assert(handle != NULL); | |
472 // TODO(ajm): Drift compensation is disabled in practice. If restored, it | |
473 // should be managed internally and not depend on the hardware sample rate. | |
474 // For now, just hardcode a 48 kHz value. | |
475 return WebRtcAec_Init(static_cast<Handle*>(handle), | |
476 apm_->proc_sample_rate_hz(), 48000); | |
477 } | |
478 | |
479 int EchoCancellationImpl::ConfigureHandle(void* handle) const { | |
480 rtc::CritScope cs_render(crit_render_); | 504 rtc::CritScope cs_render(crit_render_); |
481 rtc::CritScope cs_capture(crit_capture_); | 505 rtc::CritScope cs_capture(crit_capture_); |
482 assert(handle != NULL); | |
483 AecConfig config; | 506 AecConfig config; |
484 config.metricsMode = metrics_enabled_; | 507 config.metricsMode = metrics_enabled_; |
485 config.nlpMode = MapSetting(suppression_level_); | 508 config.nlpMode = MapSetting(suppression_level_); |
486 config.skewMode = drift_compensation_enabled_; | 509 config.skewMode = drift_compensation_enabled_; |
487 config.delay_logging = delay_logging_enabled_; | 510 config.delay_logging = delay_logging_enabled_; |
488 WebRtcAec_enable_extended_filter( | 511 |
489 WebRtcAec_aec_core(static_cast<Handle*>(handle)), | 512 int error = AudioProcessing::kNoError; |
490 extended_filter_enabled_ ? 1 : 0); | 513 for (size_t i = 0; i < cancellers_.size(); i++) { |
491 WebRtcAec_enable_delay_agnostic( | 514 Handle* my_handle = cancellers_[i]->state(); |
492 WebRtcAec_aec_core(static_cast<Handle*>(handle)), | 515 WebRtcAec_enable_extended_filter(WebRtcAec_aec_core(my_handle), |
493 delay_agnostic_enabled_ ? 1 : 0); | 516 extended_filter_enabled_ ? 1 : 0); |
494 WebRtcAec_enable_next_generation_aec( | 517 WebRtcAec_enable_delay_agnostic(WebRtcAec_aec_core(my_handle), |
495 WebRtcAec_aec_core(static_cast<Handle*>(handle)), | 518 delay_agnostic_enabled_ ? 1 : 0); |
496 next_generation_aec_enabled_ ? 1 : 0); | 519 WebRtcAec_enable_next_generation_aec(WebRtcAec_aec_core(my_handle), |
497 return WebRtcAec_set_config(static_cast<Handle*>(handle), config); | 520 next_generation_aec_enabled_ ? 1 : 0); |
521 const int handle_error = WebRtcAec_set_config(my_handle, config); | |
522 if (handle_error != AudioProcessing::kNoError) { | |
523 error = AudioProcessing::kNoError; | |
524 } | |
525 } | |
526 return error; | |
498 } | 527 } |
499 | 528 |
500 size_t EchoCancellationImpl::num_handles_required() const { | 529 size_t EchoCancellationImpl::num_handles_required() const { |
501 // Not locked as it only relies on APM public API which is threadsafe. | 530 // Not locked as it only relies on APM public API which is threadsafe. |
502 return apm_->num_output_channels() * apm_->num_reverse_channels(); | 531 return apm_->num_output_channels() * apm_->num_reverse_channels(); |
503 } | 532 } |
504 | 533 |
505 int EchoCancellationImpl::GetHandleError(void* handle) const { | |
506 // Not locked as it does not rely on anything in the state. | |
507 assert(handle != NULL); | |
508 return AudioProcessing::kUnspecifiedError; | |
509 } | |
510 } // namespace webrtc | 534 } // namespace webrtc |
OLD | NEW |