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/gain_control_impl.h" | 11 #include "webrtc/modules/audio_processing/gain_control_impl.h" |
12 | 12 |
13 #include <assert.h> | 13 #include <assert.h> |
14 | 14 |
15 #include "webrtc/base/criticalsection.h" | |
15 #include "webrtc/modules/audio_processing/audio_buffer.h" | 16 #include "webrtc/modules/audio_processing/audio_buffer.h" |
16 #include "webrtc/modules/audio_processing/agc/legacy/gain_control.h" | 17 #include "webrtc/modules/audio_processing/agc/legacy/gain_control.h" |
17 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" | |
18 | 18 |
19 namespace webrtc { | 19 namespace webrtc { |
20 | 20 |
21 typedef void Handle; | 21 typedef void Handle; |
22 | 22 |
23 namespace { | 23 namespace { |
24 int16_t MapSetting(GainControl::Mode mode) { | 24 int16_t MapSetting(GainControl::Mode mode) { |
25 switch (mode) { | 25 switch (mode) { |
26 case GainControl::kAdaptiveAnalog: | 26 case GainControl::kAdaptiveAnalog: |
27 return kAgcModeAdaptiveAnalog; | 27 return kAgcModeAdaptiveAnalog; |
28 case GainControl::kAdaptiveDigital: | 28 case GainControl::kAdaptiveDigital: |
29 return kAgcModeAdaptiveDigital; | 29 return kAgcModeAdaptiveDigital; |
30 case GainControl::kFixedDigital: | 30 case GainControl::kFixedDigital: |
31 return kAgcModeFixedDigital; | 31 return kAgcModeFixedDigital; |
32 } | 32 } |
33 assert(false); | 33 assert(false); |
34 return -1; | 34 return -1; |
35 } | 35 } |
36 } // namespace | 36 } // namespace |
37 | 37 |
38 const size_t GainControlImpl::kAllowedValuesOfSamplesPerFrame1; | 38 const size_t GainControlImpl::kAllowedValuesOfSamplesPerFrame1; |
39 const size_t GainControlImpl::kAllowedValuesOfSamplesPerFrame2; | 39 const size_t GainControlImpl::kAllowedValuesOfSamplesPerFrame2; |
40 | 40 |
41 GainControlImpl::GainControlImpl(const AudioProcessing* apm, | 41 GainControlImpl::GainControlImpl(const AudioProcessing* apm, |
42 CriticalSectionWrapper* crit, | 42 rtc::CriticalSection* crit_render, |
43 rtc::CriticalSection* crit_capture, | |
43 rtc::ThreadChecker* render_thread_checker, | 44 rtc::ThreadChecker* render_thread_checker, |
44 rtc::ThreadChecker* capture_thread_checker) | 45 rtc::ThreadChecker* capture_thread_checker) |
45 : ProcessingComponent(), | 46 : ProcessingComponent(), |
46 apm_(apm), | 47 apm_(apm), |
47 crit_(crit), | 48 crit_render_(crit_render), |
49 crit_capture_(crit_capture), | |
48 render_thread_checker_(render_thread_checker), | 50 render_thread_checker_(render_thread_checker), |
49 capture_thread_checker_(capture_thread_checker), | 51 capture_thread_checker_(capture_thread_checker), |
50 mode_(kAdaptiveAnalog), | 52 mode_(kAdaptiveAnalog), |
51 minimum_capture_level_(0), | 53 minimum_capture_level_(0), |
52 maximum_capture_level_(255), | 54 maximum_capture_level_(255), |
53 limiter_enabled_(true), | 55 limiter_enabled_(true), |
54 target_level_dbfs_(3), | 56 target_level_dbfs_(3), |
55 compression_gain_db_(9), | 57 compression_gain_db_(9), |
56 analog_capture_level_(0), | 58 analog_capture_level_(0), |
57 was_analog_level_set_(false), | 59 was_analog_level_set_(false), |
(...skipping 20 matching lines...) Expand all Loading... | |
78 | 80 |
79 if (err != apm_->kNoError) | 81 if (err != apm_->kNoError) |
80 return GetHandleError(my_handle); | 82 return GetHandleError(my_handle); |
81 | 83 |
82 // Buffer the samples in the render queue. | 84 // Buffer the samples in the render queue. |
83 render_queue_buffer_.insert( | 85 render_queue_buffer_.insert( |
84 render_queue_buffer_.end(), audio->mixed_low_pass_data(), | 86 render_queue_buffer_.end(), audio->mixed_low_pass_data(), |
85 (audio->mixed_low_pass_data() + audio->num_frames_per_band())); | 87 (audio->mixed_low_pass_data() + audio->num_frames_per_band())); |
86 } | 88 } |
87 | 89 |
88 // Check of success is temporarily disabled as it breaks a unit test. | 90 // Insert the samples into the queue. |
89 // TODO(peah): Will be fixed in the next CL. | 91 bool success = render_signal_queue_->Insert(&render_queue_buffer_); |
hlundin-webrtc
2015/11/05 16:11:22
if (!render_signal_queue_->Insert(&render_queue_bu
peah-webrtc
2015/11/06 09:54:32
Done.
| |
90 (void)render_signal_queue_->Insert(&render_queue_buffer_); | 92 if (!success) { |
93 // The data queue is full and needs to be emptied. | |
94 { | |
95 rtc::CritScope cs_capture(crit_capture_); | |
96 ReadQueuedRenderData(); | |
97 } | |
98 | |
99 // Retry the insert (should always work). | |
100 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true); | |
101 } | |
91 | 102 |
92 return apm_->kNoError; | 103 return apm_->kNoError; |
93 } | 104 } |
94 | 105 |
95 // Read chunks of data that were received and queued on the render side from | 106 // Read chunks of data that were received and queued on the render side from |
96 // a queue. All the data chunks are buffered into the farend signal of the AGC. | 107 // a queue. All the data chunks are buffered into the farend signal of the AGC. |
97 void GainControlImpl::ReadQueuedRenderData() { | 108 void GainControlImpl::ReadQueuedRenderData() { |
98 if (!is_component_enabled()) { | 109 if (!is_component_enabled()) { |
99 return; | 110 return; |
100 } | 111 } |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
218 | 229 |
219 // TODO(ajm): ensure this is called under kAdaptiveAnalog. | 230 // TODO(ajm): ensure this is called under kAdaptiveAnalog. |
220 int GainControlImpl::set_stream_analog_level(int level) { | 231 int GainControlImpl::set_stream_analog_level(int level) { |
221 RTC_DCHECK(capture_thread_checker_->CalledOnValidThread()); | 232 RTC_DCHECK(capture_thread_checker_->CalledOnValidThread()); |
222 // TODO(peah): Verify that this is really needed to do the reading. | 233 // TODO(peah): Verify that this is really needed to do the reading. |
223 // here as well as in ProcessStream. It works since these functions | 234 // here as well as in ProcessStream. It works since these functions |
224 // are called from the same thread, but it is not nice to do it in two | 235 // are called from the same thread, but it is not nice to do it in two |
225 // places if not needed. | 236 // places if not needed. |
226 ReadQueuedRenderData(); | 237 ReadQueuedRenderData(); |
227 | 238 |
228 CriticalSectionScoped crit_scoped(crit_); | 239 rtc::CritScope cs(crit_capture_); |
229 was_analog_level_set_ = true; | 240 was_analog_level_set_ = true; |
230 if (level < minimum_capture_level_ || level > maximum_capture_level_) { | 241 if (level < minimum_capture_level_ || level > maximum_capture_level_) { |
231 return apm_->kBadParameterError; | 242 return apm_->kBadParameterError; |
232 } | 243 } |
233 analog_capture_level_ = level; | 244 analog_capture_level_ = level; |
234 | 245 |
235 return apm_->kNoError; | 246 return apm_->kNoError; |
236 } | 247 } |
237 | 248 |
238 int GainControlImpl::stream_analog_level() { | 249 int GainControlImpl::stream_analog_level() { |
250 rtc::CritScope cs(crit_capture_); | |
239 RTC_DCHECK(capture_thread_checker_->CalledOnValidThread()); | 251 RTC_DCHECK(capture_thread_checker_->CalledOnValidThread()); |
240 // TODO(ajm): enable this assertion? | 252 // TODO(ajm): enable this assertion? |
241 //assert(mode_ == kAdaptiveAnalog); | 253 //assert(mode_ == kAdaptiveAnalog); |
242 | 254 |
243 return analog_capture_level_; | 255 return analog_capture_level_; |
244 } | 256 } |
245 | 257 |
246 int GainControlImpl::Enable(bool enable) { | 258 int GainControlImpl::Enable(bool enable) { |
247 CriticalSectionScoped crit_scoped(crit_); | 259 rtc::CritScope cs_render(crit_render_); |
260 rtc::CritScope cs(crit_capture_); | |
248 return EnableComponent(enable); | 261 return EnableComponent(enable); |
249 } | 262 } |
250 | 263 |
251 bool GainControlImpl::is_enabled() const { | 264 bool GainControlImpl::is_enabled() const { |
265 rtc::CritScope cs(crit_capture_); | |
252 return is_component_enabled(); | 266 return is_component_enabled(); |
253 } | 267 } |
254 | 268 |
255 int GainControlImpl::set_mode(Mode mode) { | 269 int GainControlImpl::set_mode(Mode mode) { |
256 CriticalSectionScoped crit_scoped(crit_); | 270 rtc::CritScope cs_render(crit_render_); |
271 rtc::CritScope cs_capture(crit_capture_); | |
257 if (MapSetting(mode) == -1) { | 272 if (MapSetting(mode) == -1) { |
258 return apm_->kBadParameterError; | 273 return apm_->kBadParameterError; |
259 } | 274 } |
260 | 275 |
261 mode_ = mode; | 276 mode_ = mode; |
262 return Initialize(); | 277 return Initialize(); |
263 } | 278 } |
264 | 279 |
265 GainControl::Mode GainControlImpl::mode() const { | 280 GainControl::Mode GainControlImpl::mode() const { |
281 rtc::CritScope cs(crit_capture_); | |
266 return mode_; | 282 return mode_; |
267 } | 283 } |
268 | 284 |
269 int GainControlImpl::set_analog_level_limits(int minimum, | 285 int GainControlImpl::set_analog_level_limits(int minimum, |
270 int maximum) { | 286 int maximum) { |
271 CriticalSectionScoped crit_scoped(crit_); | 287 rtc::CritScope cs(crit_capture_); |
272 if (minimum < 0) { | 288 if (minimum < 0) { |
273 return apm_->kBadParameterError; | 289 return apm_->kBadParameterError; |
274 } | 290 } |
275 | 291 |
276 if (maximum > 65535) { | 292 if (maximum > 65535) { |
277 return apm_->kBadParameterError; | 293 return apm_->kBadParameterError; |
278 } | 294 } |
279 | 295 |
280 if (maximum < minimum) { | 296 if (maximum < minimum) { |
281 return apm_->kBadParameterError; | 297 return apm_->kBadParameterError; |
282 } | 298 } |
283 | 299 |
284 minimum_capture_level_ = minimum; | 300 minimum_capture_level_ = minimum; |
285 maximum_capture_level_ = maximum; | 301 maximum_capture_level_ = maximum; |
286 | 302 |
287 return Initialize(); | 303 return Initialize(); |
288 } | 304 } |
289 | 305 |
290 int GainControlImpl::analog_level_minimum() const { | 306 int GainControlImpl::analog_level_minimum() const { |
307 rtc::CritScope cs(crit_capture_); | |
291 return minimum_capture_level_; | 308 return minimum_capture_level_; |
292 } | 309 } |
293 | 310 |
294 int GainControlImpl::analog_level_maximum() const { | 311 int GainControlImpl::analog_level_maximum() const { |
312 rtc::CritScope cs(crit_capture_); | |
295 return maximum_capture_level_; | 313 return maximum_capture_level_; |
296 } | 314 } |
297 | 315 |
298 bool GainControlImpl::stream_is_saturated() const { | 316 bool GainControlImpl::stream_is_saturated() const { |
317 rtc::CritScope cs(crit_capture_); | |
299 return stream_is_saturated_; | 318 return stream_is_saturated_; |
300 } | 319 } |
301 | 320 |
302 int GainControlImpl::set_target_level_dbfs(int level) { | 321 int GainControlImpl::set_target_level_dbfs(int level) { |
303 CriticalSectionScoped crit_scoped(crit_); | 322 rtc::CritScope cs(crit_capture_); |
304 if (level > 31 || level < 0) { | 323 if (level > 31 || level < 0) { |
305 return apm_->kBadParameterError; | 324 return apm_->kBadParameterError; |
306 } | 325 } |
307 | 326 |
308 target_level_dbfs_ = level; | 327 target_level_dbfs_ = level; |
309 return Configure(); | 328 return Configure(); |
310 } | 329 } |
311 | 330 |
312 int GainControlImpl::target_level_dbfs() const { | 331 int GainControlImpl::target_level_dbfs() const { |
332 rtc::CritScope cs(crit_capture_); | |
313 return target_level_dbfs_; | 333 return target_level_dbfs_; |
314 } | 334 } |
315 | 335 |
316 int GainControlImpl::set_compression_gain_db(int gain) { | 336 int GainControlImpl::set_compression_gain_db(int gain) { |
317 CriticalSectionScoped crit_scoped(crit_); | 337 rtc::CritScope cs(crit_capture_); |
318 if (gain < 0 || gain > 90) { | 338 if (gain < 0 || gain > 90) { |
319 return apm_->kBadParameterError; | 339 return apm_->kBadParameterError; |
320 } | 340 } |
321 | 341 |
322 compression_gain_db_ = gain; | 342 compression_gain_db_ = gain; |
323 return Configure(); | 343 return Configure(); |
324 } | 344 } |
325 | 345 |
326 int GainControlImpl::compression_gain_db() const { | 346 int GainControlImpl::compression_gain_db() const { |
347 rtc::CritScope cs(crit_capture_); | |
327 return compression_gain_db_; | 348 return compression_gain_db_; |
328 } | 349 } |
329 | 350 |
330 int GainControlImpl::enable_limiter(bool enable) { | 351 int GainControlImpl::enable_limiter(bool enable) { |
331 CriticalSectionScoped crit_scoped(crit_); | 352 rtc::CritScope cs(crit_capture_); |
332 limiter_enabled_ = enable; | 353 limiter_enabled_ = enable; |
333 return Configure(); | 354 return Configure(); |
334 } | 355 } |
335 | 356 |
336 bool GainControlImpl::is_limiter_enabled() const { | 357 bool GainControlImpl::is_limiter_enabled() const { |
358 rtc::CritScope cs(crit_capture_); | |
337 return limiter_enabled_; | 359 return limiter_enabled_; |
338 } | 360 } |
339 | 361 |
340 int GainControlImpl::Initialize() { | 362 int GainControlImpl::Initialize() { |
341 int err = ProcessingComponent::Initialize(); | 363 int err = ProcessingComponent::Initialize(); |
342 if (err != apm_->kNoError || !is_component_enabled()) { | 364 if (err != apm_->kNoError || !is_component_enabled()) { |
343 return err; | 365 return err; |
344 } | 366 } |
345 | 367 |
346 AllocateRenderQueue(); | 368 AllocateRenderQueue(); |
347 | 369 |
348 capture_levels_.assign(num_handles(), analog_capture_level_); | 370 capture_levels_.assign(num_handles(), analog_capture_level_); |
349 return apm_->kNoError; | 371 return apm_->kNoError; |
350 } | 372 } |
351 | 373 |
352 void GainControlImpl::AllocateRenderQueue() { | 374 void GainControlImpl::AllocateRenderQueue() { |
375 // Only called from within APM, hence no locking is needed. | |
353 const size_t max_frame_size = std::max(kAllowedValuesOfSamplesPerFrame1, | 376 const size_t max_frame_size = std::max(kAllowedValuesOfSamplesPerFrame1, |
354 kAllowedValuesOfSamplesPerFrame2); | 377 kAllowedValuesOfSamplesPerFrame2); |
355 | 378 |
356 const size_t new_render_queue_element_max_size = | 379 const size_t new_render_queue_element_max_size = |
357 std::max(1UL, (max_frame_size * num_handles())); | 380 std::max(1UL, (max_frame_size * num_handles())); |
358 | 381 |
359 if (new_render_queue_element_max_size > render_queue_element_max_size_) { | 382 if (new_render_queue_element_max_size > render_queue_element_max_size_) { |
360 std::vector<int16_t> template_queue_element(render_queue_element_max_size_); | 383 std::vector<int16_t> template_queue_element(render_queue_element_max_size_); |
361 | 384 |
362 render_signal_queue_.reset( | 385 render_signal_queue_.reset( |
363 new SwapQueue<std::vector<int16_t>, AgcRenderQueueItemVerifier>( | 386 new SwapQueue<std::vector<int16_t>, AgcRenderQueueItemVerifier>( |
364 kMaxNumFramesToBuffer, | 387 kMaxNumFramesToBuffer, |
365 AgcRenderQueueItemVerifier(render_queue_element_max_size_), | 388 AgcRenderQueueItemVerifier(render_queue_element_max_size_), |
366 template_queue_element)); | 389 template_queue_element)); |
367 } else { | 390 } else { |
368 render_signal_queue_->Clear(); | 391 render_signal_queue_->Clear(); |
369 } | 392 } |
370 | 393 |
371 render_queue_buffer_.resize(new_render_queue_element_max_size); | 394 render_queue_buffer_.resize(new_render_queue_element_max_size); |
372 capture_queue_buffer_.resize(new_render_queue_element_max_size); | 395 capture_queue_buffer_.resize(new_render_queue_element_max_size); |
373 } | 396 } |
374 | 397 |
375 void* GainControlImpl::CreateHandle() const { | 398 void* GainControlImpl::CreateHandle() const { |
399 // Only called from within APM, hence no locking is needed. | |
376 return WebRtcAgc_Create(); | 400 return WebRtcAgc_Create(); |
377 } | 401 } |
378 | 402 |
379 void GainControlImpl::DestroyHandle(void* handle) const { | 403 void GainControlImpl::DestroyHandle(void* handle) const { |
404 // Only called from within APM, hence no locking is needed. | |
380 WebRtcAgc_Free(static_cast<Handle*>(handle)); | 405 WebRtcAgc_Free(static_cast<Handle*>(handle)); |
381 } | 406 } |
382 | 407 |
383 int GainControlImpl::InitializeHandle(void* handle) const { | 408 int GainControlImpl::InitializeHandle(void* handle) const { |
409 // Only called from within APM, hence no locking is needed. | |
384 return WebRtcAgc_Init(static_cast<Handle*>(handle), | 410 return WebRtcAgc_Init(static_cast<Handle*>(handle), |
385 minimum_capture_level_, | 411 minimum_capture_level_, |
386 maximum_capture_level_, | 412 maximum_capture_level_, |
387 MapSetting(mode_), | 413 MapSetting(mode_), |
388 apm_->proc_sample_rate_hz()); | 414 apm_->proc_sample_rate_hz()); |
389 } | 415 } |
390 | 416 |
391 int GainControlImpl::ConfigureHandle(void* handle) const { | 417 int GainControlImpl::ConfigureHandle(void* handle) const { |
418 // Only called from within APM, hence no locking is needed. | |
392 WebRtcAgcConfig config; | 419 WebRtcAgcConfig config; |
393 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we | 420 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we |
394 // change the interface. | 421 // change the interface. |
395 //assert(target_level_dbfs_ <= 0); | 422 //assert(target_level_dbfs_ <= 0); |
396 //config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_); | 423 //config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_); |
397 config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_); | 424 config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_); |
398 config.compressionGaindB = | 425 config.compressionGaindB = |
399 static_cast<int16_t>(compression_gain_db_); | 426 static_cast<int16_t>(compression_gain_db_); |
400 config.limiterEnable = limiter_enabled_; | 427 config.limiterEnable = limiter_enabled_; |
401 | 428 |
402 return WebRtcAgc_set_config(static_cast<Handle*>(handle), config); | 429 return WebRtcAgc_set_config(static_cast<Handle*>(handle), config); |
403 } | 430 } |
404 | 431 |
405 int GainControlImpl::num_handles_required() const { | 432 int GainControlImpl::num_handles_required() const { |
433 // Only called from within APM, hence no locking is needed. | |
406 return apm_->num_output_channels(); | 434 return apm_->num_output_channels(); |
407 } | 435 } |
408 | 436 |
409 int GainControlImpl::GetHandleError(void* handle) const { | 437 int GainControlImpl::GetHandleError(void* handle) const { |
438 // Only called from within APM, hence no locking is needed. | |
410 // The AGC has no get_error() function. | 439 // The AGC has no get_error() function. |
411 // (Despite listing errors in its interface...) | 440 // (Despite listing errors in its interface...) |
412 assert(handle != NULL); | 441 assert(handle != NULL); |
413 return apm_->kUnspecifiedError; | 442 return apm_->kUnspecifiedError; |
414 } | 443 } |
415 } // namespace webrtc | 444 } // namespace webrtc |
OLD | NEW |