1 /* 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 * 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 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/modules/audio_processing/audio_processing_impl.h" 12 13 #include <algorithm> 14 #include <vector> 15 16 #include "testing/gtest/include/gtest/gtest.h" 17 #include "webrtc/base/array_view.h" 18 #include "webrtc/base/criticalsection.h" 19 #include "webrtc/base/event.h" 20 #include "webrtc/base/platform_thread.h" 21 #include "webrtc/base/random.h" 22 #include "webrtc/config.h" 23 #include "webrtc/modules/audio_processing/test/test_utils.h" 24 #include "webrtc/modules/include/module_common_types.h" 25 #include "webrtc/system_wrappers/include/sleep.h" 26 27 namespace webrtc { 28 29 namespace { 30 31 class AudioProcessingImplLockTest; 32 33 // Type of the render thread APM API call to use in the test. 34 enum class RenderApiImpl { 35 ProcessReverseStreamImpl1, 36 ProcessReverseStreamImpl2, 37 AnalyzeReverseStreamImpl1, 38 AnalyzeReverseStreamImpl2 39 }; 40 41 // Type of the capture thread APM API call to use in the test. 42 enum class CaptureApiImpl { 43 ProcessStreamImpl1, 44 ProcessStreamImpl2, 45 ProcessStreamImpl3 46 }; 47 48 // The runtime parameter setting scheme to use in the test. 49 enum class RuntimeParameterSettingScheme { 50 SparseStreamMetadataChangeScheme, 51 ExtremeStreamMetadataChangeScheme, 52 FixedMonoStreamMetadataScheme, 53 FixedStereoStreamMetadataScheme 54 }; 55 56 // Variant of echo canceller settings to use in the test. 57 enum class AecType { 58 BasicWebRtcAecSettings, 59 AecTurnedOff, 60 BasicWebRtcAecSettingsWithExtentedFilter, 61 BasicWebRtcAecSettingsWithDelayAgnosticAec, 62 BasicWebRtcAecSettingsWithAecMobile 63 }; 64 65 // Thread-safe random number generator wrapper. 66 class RandomGenerator { 67 public: 68 RandomGenerator() : rand_gen_(42U) {} 69 70 int RandInt(int min, int max) { 71 rtc::CritScope cs(&crit_); 72 return rand_gen_.Rand(min, max); 73 } 74 75 int RandInt(int max) { 76 rtc::CritScope cs(&crit_); 77 return rand_gen_.Rand(max); 78 } 79 80 float RandFloat() { 81 rtc::CritScope cs(&crit_); 82 return rand_gen_.Rand<float>(); 83 } 84 85 private: 86 rtc::CriticalSection crit_; 87 Random rand_gen_ GUARDED_BY(crit_); 88 }; 89 90 // Variables related to the audio data and formats. 91 struct AudioFrameData { 92 explicit AudioFrameData(int max_frame_size) { 93 // Set up the two-dimensional arrays needed for the APM API calls. 94 input_framechannels.resize(2 * max_frame_size); 95 input_frame.resize(2); 96 input_frame[0] = &input_framechannels[0]; 97 input_frame[1] = &input_framechannels[max_frame_size]; 98 99 output_frame_channels.resize(2 * max_frame_size); 100 output_frame.resize(2); 101 output_frame[0] = &output_frame_channels[0]; 102 output_frame[1] = &output_frame_channels[max_frame_size]; 103 } 104 105 AudioFrame frame; 106 std::vector<float*> output_frame; 107 std::vector<float> output_frame_channels; 108 AudioProcessing::ChannelLayout output_channel_layout = 109 AudioProcessing::ChannelLayout::kMono; 110 int input_sample_rate_hz = 16000; 111 int input_number_of_channels = -1; 112 std::vector<float*> input_frame; 113 std::vector<float> input_framechannels; 114 AudioProcessing::ChannelLayout input_channel_layout = 115 AudioProcessing::ChannelLayout::kMono; 116 int output_sample_rate_hz = 16000; 117 int output_number_of_channels = -1; 118 StreamConfig input_stream_config; 119 StreamConfig output_stream_config; 120 int input_samples_per_channel = -1; 121 int output_samples_per_channel = -1; 122 }; 123 124 // The configuration for the test. 125 struct TestConfig { 126 // Test case generator for the test configurations to use in the brief tests. 127 static std::vector<TestConfig> GenerateBriefTestConfigs() { 128 std::vector<TestConfig> test_configs; 129 AecType aec_types[] = {AecType::BasicWebRtcAecSettingsWithDelayAgnosticAec, 130 AecType::BasicWebRtcAecSettingsWithAecMobile}; 131 for (auto aec_type : aec_types) { 132 TestConfig test_config; 133 test_config.aec_type = aec_type; 134 135 test_config.min_number_of_calls = 300; 136 137 // Perform tests only with the extreme runtime parameter setting scheme. 138 test_config.runtime_parameter_setting_scheme = 139 RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme; 140 141 // Only test 16 kHz for this test suite. 142 test_config.initial_sample_rate_hz = 16000; 143 144 // Create test config for the second processing API function set. 145 test_config.render_api_function = 146 RenderApiImpl::ProcessReverseStreamImpl2; 147 test_config.capture_api_function = CaptureApiImpl::ProcessStreamImpl2; 148 149 // Create test config for the first processing API function set. 150 test_configs.push_back(test_config); 151 test_config.render_api_function = 152 RenderApiImpl::AnalyzeReverseStreamImpl2; 153 test_config.capture_api_function = CaptureApiImpl::ProcessStreamImpl3; 154 test_configs.push_back(test_config); 155 } 156 157 // Return the created test configurations. 158 return test_configs; 159 } 160 161 // Test case generator for the test configurations to use in the extensive 162 // tests. 163 static std::vector<TestConfig> GenerateExtensiveTestConfigs() { 164 // Lambda functions for the test config generation. 165 auto add_processing_apis = [](TestConfig test_config) { 166 struct AllowedApiCallCombinations { 167 RenderApiImpl render_api; 168 CaptureApiImpl capture_api; 169 }; 170 171 const AllowedApiCallCombinations api_calls[] = { 172 {RenderApiImpl::ProcessReverseStreamImpl1, 173 CaptureApiImpl::ProcessStreamImpl1}, 174 {RenderApiImpl::AnalyzeReverseStreamImpl1, 175 CaptureApiImpl::ProcessStreamImpl1}, 176 {RenderApiImpl::ProcessReverseStreamImpl2, 177 CaptureApiImpl::ProcessStreamImpl2}, 178 {RenderApiImpl::ProcessReverseStreamImpl2, 179 CaptureApiImpl::ProcessStreamImpl3}, 180 {RenderApiImpl::AnalyzeReverseStreamImpl2, 181 CaptureApiImpl::ProcessStreamImpl2}, 182 {RenderApiImpl::AnalyzeReverseStreamImpl2, 183 CaptureApiImpl::ProcessStreamImpl3}}; 184 std::vector<TestConfig> out; 185 for (auto api_call : api_calls) { 186 test_config.render_api_function = api_call.render_api; 187 test_config.capture_api_function = api_call.capture_api; 188 out.push_back(test_config); 189 } 190 return out; 191 }; 192 193 auto add_aec_settings = [](const std::vector<TestConfig>& in) { 194 std::vector<TestConfig> out; 195 AecType aec_types[] = { 196 AecType::BasicWebRtcAecSettings, AecType::AecTurnedOff, 197 AecType::BasicWebRtcAecSettingsWithExtentedFilter, 198 AecType::BasicWebRtcAecSettingsWithDelayAgnosticAec, 199 AecType::BasicWebRtcAecSettingsWithAecMobile}; 200 for (auto test_config : in) { 201 for (auto aec_type : aec_types) { 202 test_config.aec_type = aec_type; 203 out.push_back(test_config); 204 } 205 } 206 return out; 207 }; 208 209 auto add_settings_scheme = [](const std::vector<TestConfig>& in) { 210 std::vector<TestConfig> out; 211 RuntimeParameterSettingScheme schemes[] = { 212 RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme, 213 RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme, 214 RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme, 215 RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme}; 216 217 for (auto test_config : in) { 218 for (auto scheme : schemes) { 219 test_config.runtime_parameter_setting_scheme = scheme; 220 out.push_back(test_config); 221 } 222 } 223 return out; 224 }; 225 226 auto add_sample_rates = [](const std::vector<TestConfig>& in) { 227 const int sample_rates[] = {8000, 16000, 32000, 48000}; 228 229 std::vector<TestConfig> out; 230 for (auto test_config : in) { 231 auto available_rates = 232 (test_config.aec_type == 233 AecType::BasicWebRtcAecSettingsWithAecMobile 234 ? rtc::ArrayView<const int>(sample_rates, 2) 235 : rtc::ArrayView<const int>(sample_rates)); 236 237 for (auto rate : available_rates) { 238 test_config.initial_sample_rate_hz = rate; 239 out.push_back(test_config); 240 } 241 } 242 return out; 243 }; 244 245 // Generate test configurations of the relevant combinations of the 246 // parameters to 247 // test. 248 TestConfig test_config; 249 test_config.min_number_of_calls = 10000; 250 return add_sample_rates(add_settings_scheme( 251 add_aec_settings(add_processing_apis(test_config)))); 252 } 253 254 RenderApiImpl render_api_function = RenderApiImpl::ProcessReverseStreamImpl2; 255 CaptureApiImpl capture_api_function = CaptureApiImpl::ProcessStreamImpl2; 256 RuntimeParameterSettingScheme runtime_parameter_setting_scheme = 257 RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme; 258 int initial_sample_rate_hz = 16000; 259 AecType aec_type = AecType::BasicWebRtcAecSettingsWithDelayAgnosticAec; 260 int min_number_of_calls = 300; 261 }; 262 263 // Handler for the frame counters. 264 class FrameCounters { 265 public: 266 void IncreaseRenderCounter() { 267 rtc::CritScope cs(&crit_); 268 render_count++; 269 } 270 271 void IncreaseCaptureCounter() { 272 rtc::CritScope cs(&crit_); 273 capture_count++; 274 } 275 276 int GetCaptureCounter() const { 277 rtc::CritScope cs(&crit_); 278 return capture_count; 279 } 280 281 int GetRenderCounter() const { 282 rtc::CritScope cs(&crit_); 283 return render_count; 284 } 285 286 int CaptureMinusRenderCounters() const { 287 rtc::CritScope cs(&crit_); 288 return capture_count - render_count; 289 } 290 291 int RenderMinusCaptureCounters() const { 292 return -CaptureMinusRenderCounters(); 293 } 294 295 bool BothCountersExceedeThreshold(int threshold) { 296 rtc::CritScope cs(&crit_); 297 return (render_count > threshold && capture_count > threshold); 298 } 299 300 private: 301 mutable rtc::CriticalSection crit_; 302 int render_count GUARDED_BY(crit_) = 0; 303 int capture_count GUARDED_BY(crit_) = 0; 304 }; 305 306 // Class for handling the capture side processing. 307 class CaptureProcessor { 308 public: 309 CaptureProcessor(int max_frame_size, 310 RandomGenerator* rand_gen, 311 rtc::Event* render_call_event, 312 rtc::Event* capture_call_event, 313 FrameCounters* shared_counters_state, 314 AudioProcessingImplLockTest* test_framework, 315 TestConfig* test_config, 316 AudioProcessing* apm); 317 bool Process(); 318 319 private: 320 static const int kMaxCallDifference = 10; 321 static const float kCaptureInputFloatLevel; 322 static const int kCaptureInputFixLevel = 1024; 323 324 void PrepareFrame(); 325 void CallApmCaptureSide(); 326 void ApplyRuntimeSettingScheme(); 327 328 RandomGenerator* const rand_gen_ = nullptr; 329 rtc::Event* const render_call_event_ = nullptr; 330 rtc::Event* const capture_call_event_ = nullptr; 331 FrameCounters* const frame_counters_ = nullptr; 332 AudioProcessingImplLockTest* const test_ = nullptr; 333 const TestConfig* const test_config_ = nullptr; 334 AudioProcessing* const apm_ = nullptr; 335 AudioFrameData frame_data_; 336 }; 337 338 // Class for handling the stats processing. 339 class StatsProcessor { 340 public: 341 StatsProcessor(RandomGenerator* rand_gen, 342 TestConfig* test_config, 343 AudioProcessing* apm); 344 bool Process(); 345 346 private: 347 RandomGenerator* rand_gen_ = nullptr; 348 TestConfig* test_config_ = nullptr; 349 AudioProcessing* apm_ = nullptr; 350 }; 351 352 // Class for handling the render side processing. 353 class RenderProcessor { 354 public: 355 RenderProcessor(int max_frame_size, 356 RandomGenerator* rand_gen, 357 rtc::Event* render_call_event, 358 rtc::Event* capture_call_event, 359 FrameCounters* shared_counters_state, 360 AudioProcessingImplLockTest* test_framework, 361 TestConfig* test_config, 362 AudioProcessing* apm); 363 bool Process(); 364 365 private: 366 static const int kMaxCallDifference = 10; 367 static const int kRenderInputFixLevel = 16384; 368 static const float kRenderInputFloatLevel; 369 370 void PrepareFrame(); 371 void CallApmRenderSide(); 372 void ApplyRuntimeSettingScheme(); 373 374 RandomGenerator* const rand_gen_ = nullptr; 375 rtc::Event* const render_call_event_ = nullptr; 376 rtc::Event* const capture_call_event_ = nullptr; 377 FrameCounters* const frame_counters_ = nullptr; 378 AudioProcessingImplLockTest* const test_ = nullptr; 379 const TestConfig* const test_config_ = nullptr; 380 AudioProcessing* const apm_ = nullptr; 381 AudioFrameData frame_data_; 382 bool first_render_call_ = true; 383 }; 384 385 class AudioProcessingImplLockTest 386 : public ::testing::TestWithParam<TestConfig> { 387 public: 388 AudioProcessingImplLockTest(); 389 bool RunTest(); 390 bool MaybeEndTest(); 391 392 private: 393 static const int kTestTimeOutLimit = 10 * 60 * 1000; 394 static const int kMaxFrameSize = 480; 395 396 // ::testing::TestWithParam<> implementation 397 void SetUp() override; 398 void TearDown() override; 399 400 // Thread callback for the render thread 401 static bool RenderProcessorThreadFunc(void* context) { 402 return reinterpret_cast<AudioProcessingImplLockTest*>(context) 403 ->render_thread_state_.Process(); 404 } 405 406 // Thread callback for the capture thread 407 static bool CaptureProcessorThreadFunc(void* context) { 408 return reinterpret_cast<AudioProcessingImplLockTest*>(context) 409 ->capture_thread_state_.Process(); 410 } 411 412 // Thread callback for the stats thread 413 static bool StatsProcessorThreadFunc(void* context) { 414 return reinterpret_cast<AudioProcessingImplLockTest*>(context) 415 ->stats_thread_state_.Process(); 416 } 417 418 // Tests whether all the required render and capture side calls have been 419 // done. 420 bool TestDone() { 421 return frame_counters_.BothCountersExceedeThreshold( 422 test_config_.min_number_of_calls); 423 } 424 425 // Start the threads used in the test. 426 void StartThreads() { 427 render_thread_.Start(); 428 render_thread_.SetPriority(rtc::kRealtimePriority); 429 capture_thread_.Start(); 430 capture_thread_.SetPriority(rtc::kRealtimePriority); 431 stats_thread_.Start(); 432 stats_thread_.SetPriority(rtc::kNormalPriority); 433 } 434 435 // Event handlers for the test. 436 rtc::Event test_complete_; 437 rtc::Event render_call_event_; 438 rtc::Event capture_call_event_; 439 440 // Thread related variables. 441 rtc::PlatformThread render_thread_; 442 rtc::PlatformThread capture_thread_; 443 rtc::PlatformThread stats_thread_; 444 mutable RandomGenerator rand_gen_; 445 446 rtc::scoped_ptr<AudioProcessing> apm_; 447 TestConfig test_config_; 448 FrameCounters frame_counters_; 449 RenderProcessor render_thread_state_; 450 CaptureProcessor capture_thread_state_; 451 StatsProcessor stats_thread_state_; 452 }; 453 454 // Sleeps a random time between 0 and max_sleep milliseconds. 455 void SleepRandomMs(int max_sleep, RandomGenerator* rand_gen) { 456 int sleeptime = rand_gen->RandInt(0, max_sleep); 457 SleepMs(sleeptime); 458 } 459 460 // Populates a float audio frame with random data. 461 void PopulateAudioFrame(float** frame, 462 float amplitude, 463 size_t num_channels, 464 size_t samples_per_channel, 465 RandomGenerator* rand_gen) { 466 for (size_t ch = 0; ch < num_channels; ch++) { 467 for (size_t k = 0; k < samples_per_channel; k++) { 468 // Store random 16 bit quantized float number between +-amplitude. 469 frame[ch][k] = amplitude * (2 * rand_gen->RandFloat() - 1); 470 } 471 } 472 } 473 474 // Populates an audioframe frame of AudioFrame type with random data. 475 void PopulateAudioFrame(AudioFrame* frame, 476 int16_t amplitude, 477 RandomGenerator* rand_gen) { 478 ASSERT_GT(amplitude, 0); 479 ASSERT_LE(amplitude, 32767); 480 for (size_t ch = 0; ch < frame->num_channels_; ch++) { 481 for (size_t k = 0; k < frame->samples_per_channel_; k++) { 482 // Store random 16 bit number between -(amplitude+1) and 483 // amplitude. 484 frame->data_[k * ch] = 485 rand_gen->RandInt(2 * amplitude + 1) - amplitude - 1; 486 } 487 } 488 } 489 490 AudioProcessingImplLockTest::AudioProcessingImplLockTest() 491 : test_complete_(false, false), 492 render_call_event_(false, false), 493 capture_call_event_(false, false), 494 render_thread_(RenderProcessorThreadFunc, this, "render"), 495 capture_thread_(CaptureProcessorThreadFunc, this, "capture"), 496 stats_thread_(StatsProcessorThreadFunc, this, "stats"), 497 apm_(AudioProcessingImpl::Create()), 498 render_thread_state_(kMaxFrameSize, 499 &rand_gen_, 500 &render_call_event_, 501 &capture_call_event_, 502 &frame_counters_, 503 this, 504 &test_config_, 505 apm_.get()), 506 capture_thread_state_(kMaxFrameSize, 507 &rand_gen_, 508 &render_call_event_, 509 &capture_call_event_, 510 &frame_counters_, 511 this, 512 &test_config_, 513 apm_.get()), 514 stats_thread_state_(&rand_gen_, &test_config_, apm_.get()) {} 515 516 // Run the test with a timeout. 517 bool AudioProcessingImplLockTest::RunTest() { 518 StartThreads(); 519 return test_complete_.Wait(kTestTimeOutLimit); 520 } 521 522 bool AudioProcessingImplLockTest::MaybeEndTest() { 523 if (HasFatalFailure() || TestDone()) { 524 test_complete_.Set(); 525 return true; 526 } 527 return false; 528 } 529 530 // Setup of test and APM. 531 void AudioProcessingImplLockTest::SetUp() { 532 test_config_ = static_cast<TestConfig>(GetParam()); 533 534 ASSERT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true)); 535 ASSERT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true)); 536 537 ASSERT_EQ(apm_->kNoError, 538 apm_->gain_control()->set_mode(GainControl::kAdaptiveDigital)); 539 ASSERT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true)); 540 541 ASSERT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(true)); 542 ASSERT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true)); 543 544 Config config; 545 if (test_config_.aec_type == AecType::AecTurnedOff) { 546 ASSERT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(false)); 547 ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false)); 548 } else if (test_config_.aec_type == 549 AecType::BasicWebRtcAecSettingsWithAecMobile) { 550 ASSERT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(true)); 551 ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false)); 552 } else { 553 ASSERT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(false)); 554 ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true)); 555 ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->enable_metrics(true)); 556 ASSERT_EQ(apm_->kNoError, 557 apm_->echo_cancellation()->enable_delay_logging(true)); 558 559 config.Set<ExtendedFilter>( 560 new ExtendedFilter(test_config_.aec_type == 561 AecType::BasicWebRtcAecSettingsWithExtentedFilter)); 562 563 config.Set<DelayAgnostic>( 564 new DelayAgnostic(test_config_.aec_type == 565 AecType::BasicWebRtcAecSettingsWithDelayAgnosticAec)); 566 567 apm_->SetExtraOptions(config); 568 } 569 } 570 571 void AudioProcessingImplLockTest::TearDown() { 572 render_call_event_.Set(); 573 capture_call_event_.Set(); 574 render_thread_.Stop(); 575 capture_thread_.Stop(); 576 stats_thread_.Stop(); 577 } 578 579 StatsProcessor::StatsProcessor(RandomGenerator* rand_gen, 580 TestConfig* test_config, 581 AudioProcessing* apm) 582 : rand_gen_(rand_gen), test_config_(test_config), apm_(apm) {} 583 584 // Implements the callback functionality for the statistics 585 // collection thread. 586 bool StatsProcessor::Process() { 587 SleepRandomMs(100, rand_gen_); 588 589 EXPECT_EQ(apm_->echo_cancellation()->is_enabled(), 590 ((test_config_->aec_type != AecType::AecTurnedOff) && 591 (test_config_->aec_type != 592 AecType::BasicWebRtcAecSettingsWithAecMobile))); 593 apm_->echo_cancellation()->stream_drift_samples(); 594 EXPECT_EQ(apm_->echo_control_mobile()->is_enabled(), 595 (test_config_->aec_type != AecType::AecTurnedOff) && 596 (test_config_->aec_type == 597 AecType::BasicWebRtcAecSettingsWithAecMobile)); 598 EXPECT_TRUE(apm_->gain_control()->is_enabled()); 599 apm_->gain_control()->stream_analog_level(); 600 EXPECT_TRUE(apm_->noise_suppression()->is_enabled()); 601 602 // The below return values are not testable. 603 apm_->noise_suppression()->speech_probability(); 604 apm_->voice_detection()->is_enabled(); 605 606 return true; 607 } 608 609 const float CaptureProcessor::kCaptureInputFloatLevel = 0.03125f; 610 611 CaptureProcessor::CaptureProcessor(int max_frame_size, 612 RandomGenerator* rand_gen, 613 rtc::Event* render_call_event, 614 rtc::Event* capture_call_event, 615 FrameCounters* shared_counters_state, 616 AudioProcessingImplLockTest* test_framework, 617 TestConfig* test_config, 618 AudioProcessing* apm) 619 : rand_gen_(rand_gen), 620 render_call_event_(render_call_event), 621 capture_call_event_(capture_call_event), 622 frame_counters_(shared_counters_state), 623 test_(test_framework), 624 test_config_(test_config), 625 apm_(apm), 626 frame_data_(max_frame_size) {} 627 628 // Implements the callback functionality for the capture thread. 629 bool CaptureProcessor::Process() { 630 // Sleep a random time to simulate thread jitter. 631 SleepRandomMs(3, rand_gen_); 632 633 // Check whether the test is done. 634 if (test_->MaybeEndTest()) { 635 return false; 636 } 637 638 // Ensure that the number of render and capture calls do not 639 // differ too much. 640 if (frame_counters_->CaptureMinusRenderCounters() > kMaxCallDifference) { 641 render_call_event_->Wait(rtc::Event::kForever); 642 } 643 644 // Apply any specified capture side APM non-processing runtime calls. 645 ApplyRuntimeSettingScheme(); 646 647 // Apply the capture side processing call. 648 CallApmCaptureSide(); 649 650 // Increase the number of capture-side calls. 651 frame_counters_->IncreaseCaptureCounter(); 652 653 // Flag to the render thread that another capture API call has occurred 654 // by triggering this threads call event. 655 capture_call_event_->Set(); 656 657 return true; 658 } 659 660 // Prepares a frame with relevant audio data and metadata. 661 void CaptureProcessor::PrepareFrame() { 662 // Restrict to a common fixed sample rate if the AudioFrame 663 // interface is used. 664 if (test_config_->capture_api_function == 665 CaptureApiImpl::ProcessStreamImpl1) { 666 frame_data_.input_sample_rate_hz = test_config_->initial_sample_rate_hz; 667 frame_data_.output_sample_rate_hz = test_config_->initial_sample_rate_hz; 668 } 669 670 // Prepare the audioframe data and metadata. 671 frame_data_.input_samples_per_channel = 672 frame_data_.input_sample_rate_hz * AudioProcessing::kChunkSizeMs / 1000; 673 frame_data_.frame.sample_rate_hz_ = frame_data_.input_sample_rate_hz; 674 frame_data_.frame.num_channels_ = frame_data_.input_number_of_channels; 675 frame_data_.frame.samples_per_channel_ = 676 frame_data_.input_samples_per_channel; 677 PopulateAudioFrame(&frame_data_.frame, kCaptureInputFixLevel, rand_gen_); 678 679 // Prepare the float audio input data and metadata. 680 frame_data_.input_stream_config.set_sample_rate_hz( 681 frame_data_.input_sample_rate_hz); 682 frame_data_.input_stream_config.set_num_channels( 683 frame_data_.input_number_of_channels); 684 frame_data_.input_stream_config.set_has_keyboard(false); 685 PopulateAudioFrame(&frame_data_.input_frame[0], kCaptureInputFloatLevel, 686 frame_data_.input_number_of_channels, 687 frame_data_.input_samples_per_channel, rand_gen_); 688 frame_data_.input_channel_layout = 689 (frame_data_.input_number_of_channels == 1 690 ? AudioProcessing::ChannelLayout::kMono 691 : AudioProcessing::ChannelLayout::kStereo); 692 693 // Prepare the float audio output data and metadata. 694 frame_data_.output_samples_per_channel = 695 frame_data_.output_sample_rate_hz * AudioProcessing::kChunkSizeMs / 1000; 696 frame_data_.output_stream_config.set_sample_rate_hz( 697 frame_data_.output_sample_rate_hz); 698 frame_data_.output_stream_config.set_num_channels( 699 frame_data_.output_number_of_channels); 700 frame_data_.output_stream_config.set_has_keyboard(false); 701 frame_data_.output_channel_layout = 702 (frame_data_.output_number_of_channels == 1 703 ? AudioProcessing::ChannelLayout::kMono 704 : AudioProcessing::ChannelLayout::kStereo); 705 } 706 707 // Applies the capture side processing API call. 708 void CaptureProcessor::CallApmCaptureSide() { 709 // Prepare a proper capture side processing API call input. 710 PrepareFrame(); 711 712 // Set the stream delay 713 apm_->set_stream_delay_ms(30); 714 715 // Call the specified capture side API processing method. 716 int result = AudioProcessing::kNoError; 717 switch (test_config_->capture_api_function) { 718 case CaptureApiImpl::ProcessStreamImpl1: 719 result = apm_->ProcessStream(&frame_data_.frame); 720 break; 721 case CaptureApiImpl::ProcessStreamImpl2: 722 result = apm_->ProcessStream( 723 &frame_data_.input_frame[0], frame_data_.input_samples_per_channel, 724 frame_data_.input_sample_rate_hz, frame_data_.input_channel_layout, 725 frame_data_.output_sample_rate_hz, frame_data_.output_channel_layout, 726 &frame_data_.output_frame[0]); 727 break; 728 case CaptureApiImpl::ProcessStreamImpl3: 729 result = apm_->ProcessStream( 730 &frame_data_.input_frame[0], frame_data_.input_stream_config, 731 frame_data_.output_stream_config, &frame_data_.output_frame[0]); 732 break; 733 default: 734 FAIL(); 735 } 736 737 // Check the return code for error. 738 ASSERT_EQ(AudioProcessing::kNoError, result); 739 } 740 741 // Applies any runtime capture APM API calls and audio stream characteristics 742 // specified by the scheme for the test. 743 void CaptureProcessor::ApplyRuntimeSettingScheme() { 744 const int capture_count_local = frame_counters_->GetCaptureCounter(); 745 746 // Update the number of channels and sample rates for the input and output. 747 // Note that the counts frequencies for when to set parameters 748 // are set using prime numbers in order to ensure that the 749 // permutation scheme in the parameter setting changes. 750 switch (test_config_->runtime_parameter_setting_scheme) { 751 case RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme: 752 if (capture_count_local == 0) 753 frame_data_.input_sample_rate_hz = 16000; 754 else if (capture_count_local % 11 == 0) 755 frame_data_.input_sample_rate_hz = 32000; 756 else if (capture_count_local % 73 == 0) 757 frame_data_.input_sample_rate_hz = 48000; 758 else if (capture_count_local % 89 == 0) 759 frame_data_.input_sample_rate_hz = 16000; 760 else if (capture_count_local % 97 == 0) 761 frame_data_.input_sample_rate_hz = 8000; 762 763 if (capture_count_local == 0) 764 frame_data_.input_number_of_channels = 1; 765 else if (capture_count_local % 4 == 0) 766 frame_data_.input_number_of_channels = 767 (frame_data_.input_number_of_channels == 1 ? 2 : 1); 768 769 if (capture_count_local == 0) 770 frame_data_.output_sample_rate_hz = 16000; 771 else if (capture_count_local % 5 == 0) 772 frame_data_.output_sample_rate_hz = 32000; 773 else if (capture_count_local % 47 == 0) 774 frame_data_.output_sample_rate_hz = 48000; 775 else if (capture_count_local % 53 == 0) 776 frame_data_.output_sample_rate_hz = 16000; 777 else if (capture_count_local % 71 == 0) 778 frame_data_.output_sample_rate_hz = 8000; 779 780 if (capture_count_local == 0) 781 frame_data_.output_number_of_channels = 1; 782 else if (capture_count_local % 8 == 0) 783 frame_data_.output_number_of_channels = 784 (frame_data_.output_number_of_channels == 1 ? 2 : 1); 785 break; 786 case RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme: 787 if (capture_count_local % 2 == 0) { 788 frame_data_.input_number_of_channels = 1; 789 frame_data_.input_sample_rate_hz = 16000; 790 frame_data_.output_number_of_channels = 1; 791 frame_data_.output_sample_rate_hz = 16000; 792 } else { 793 frame_data_.input_number_of_channels = 794 (frame_data_.input_number_of_channels == 1 ? 2 : 1); 795 if (frame_data_.input_sample_rate_hz == 8000) 796 frame_data_.input_sample_rate_hz = 16000; 797 else if (frame_data_.input_sample_rate_hz == 16000) 798 frame_data_.input_sample_rate_hz = 32000; 799 else if (frame_data_.input_sample_rate_hz == 32000) 800 frame_data_.input_sample_rate_hz = 48000; 801 else if (frame_data_.input_sample_rate_hz == 48000) 802 frame_data_.input_sample_rate_hz = 8000; 803 804 frame_data_.output_number_of_channels = 805 (frame_data_.output_number_of_channels == 1 ? 2 : 1); 806 if (frame_data_.output_sample_rate_hz == 8000) 807 frame_data_.output_sample_rate_hz = 16000; 808 else if (frame_data_.output_sample_rate_hz == 16000) 809 frame_data_.output_sample_rate_hz = 32000; 810 else if (frame_data_.output_sample_rate_hz == 32000) 811 frame_data_.output_sample_rate_hz = 48000; 812 else if (frame_data_.output_sample_rate_hz == 48000) 813 frame_data_.output_sample_rate_hz = 8000; 814 } 815 break; 816 case RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme: 817 if (capture_count_local == 0) { 818 frame_data_.input_sample_rate_hz = 16000; 819 frame_data_.input_number_of_channels = 1; 820 frame_data_.output_sample_rate_hz = 16000; 821 frame_data_.output_number_of_channels = 1; 822 } 823 break; 824 case RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme: 825 if (capture_count_local == 0) { 826 frame_data_.input_sample_rate_hz = 16000; 827 frame_data_.input_number_of_channels = 2; 828 frame_data_.output_sample_rate_hz = 16000; 829 frame_data_.output_number_of_channels = 2; 830 } 831 break; 832 default: 833 FAIL(); 834 } 835 836 // Call any specified runtime APM setter and 837 // getter calls. 838 switch (test_config_->runtime_parameter_setting_scheme) { 839 case RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme: 840 case RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme: 841 break; 842 case RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme: 843 case RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme: 844 if (capture_count_local % 2 == 0) { 845 ASSERT_EQ(AudioProcessing::Error::kNoError, 846 apm_->set_stream_delay_ms(30)); 847 apm_->set_stream_key_pressed(true); 848 apm_->set_delay_offset_ms(15); 849 EXPECT_EQ(apm_->delay_offset_ms(), 15); 850 } else { 851 ASSERT_EQ(AudioProcessing::Error::kNoError, 852 apm_->set_stream_delay_ms(50)); 853 apm_->set_stream_key_pressed(false); 854 apm_->set_delay_offset_ms(20); 855 EXPECT_EQ(apm_->delay_offset_ms(), 20); 856 apm_->delay_offset_ms(); 857 } 858 break; 859 default: 860 FAIL(); 861 } 862 863 // Restric the number of output channels not to exceed 864 // the number of input channels. 865 frame_data_.output_number_of_channels = 866 std::min(frame_data_.output_number_of_channels, 867 frame_data_.input_number_of_channels); 868 } 869 870 const float RenderProcessor::kRenderInputFloatLevel = 0.5f; 871 872 RenderProcessor::RenderProcessor(int max_frame_size, 873 RandomGenerator* rand_gen, 874 rtc::Event* render_call_event, 875 rtc::Event* capture_call_event, 876 FrameCounters* shared_counters_state, 877 AudioProcessingImplLockTest* test_framework, 878 TestConfig* test_config, 879 AudioProcessing* apm) 880 : rand_gen_(rand_gen), 881 render_call_event_(render_call_event), 882 capture_call_event_(capture_call_event), 883 frame_counters_(shared_counters_state), 884 test_(test_framework), 885 test_config_(test_config), 886 apm_(apm), 887 frame_data_(max_frame_size) {} 888 889 // Implements the callback functionality for the render thread. 890 bool RenderProcessor::Process() { 891 // Conditional wait to ensure that a capture call has been done 892 // before the first render call is performed (implicitly 893 // required by the APM API). 894 if (first_render_call_) { 895 capture_call_event_->Wait(rtc::Event::kForever); 896 first_render_call_ = false; 897 } 898 899 // Sleep a random time to simulate thread jitter. 900 SleepRandomMs(3, rand_gen_); 901 902 // Check whether the test is done. 903 if (test_->MaybeEndTest()) { 904 return false; 905 } 906 907 // Ensure that the number of render and capture calls do not 908 // differ too much. 909 if (frame_counters_->RenderMinusCaptureCounters() > kMaxCallDifference) { 910 capture_call_event_->Wait(rtc::Event::kForever); 911 } 912 913 // Apply any specified render side APM non-processing runtime calls. 914 ApplyRuntimeSettingScheme(); 915 916 // Apply the render side processing call. 917 CallApmRenderSide(); 918 919 // Increase the number of render-side calls. 920 frame_counters_->IncreaseRenderCounter(); 921 922 // Flag to the capture thread that another render API call has occurred 923 // by triggering this threads call event. 924 render_call_event_->Set(); 925 return true; 926 } 927 928 // Prepares the render side frame and the accompanying metadata 929 // with the appropriate information. 930 void RenderProcessor::PrepareFrame() { 931 // Restrict to a common fixed sample rate if the AudioFrame interface is 932 // used. 933 if ((test_config_->render_api_function == 934 RenderApiImpl::AnalyzeReverseStreamImpl1) || 935 (test_config_->render_api_function == 936 RenderApiImpl::ProcessReverseStreamImpl1) || 937 (test_config_->aec_type != 938 AecType::BasicWebRtcAecSettingsWithAecMobile)) { 939 frame_data_.input_sample_rate_hz = test_config_->initial_sample_rate_hz; 940 frame_data_.output_sample_rate_hz = test_config_->initial_sample_rate_hz; 941 } 942 943 // Prepare the audioframe data and metadata 944 frame_data_.input_samples_per_channel = 945 frame_data_.input_sample_rate_hz * AudioProcessing::kChunkSizeMs / 1000; 946 frame_data_.frame.sample_rate_hz_ = frame_data_.input_sample_rate_hz; 947 frame_data_.frame.num_channels_ = frame_data_.input_number_of_channels; 948 frame_data_.frame.samples_per_channel_ = 949 frame_data_.input_samples_per_channel; 950 PopulateAudioFrame(&frame_data_.frame, kRenderInputFixLevel, rand_gen_); 951 952 // Prepare the float audio input data and metadata. 953 frame_data_.input_stream_config.set_sample_rate_hz( 954 frame_data_.input_sample_rate_hz); 955 frame_data_.input_stream_config.set_num_channels( 956 frame_data_.input_number_of_channels); 957 frame_data_.input_stream_config.set_has_keyboard(false); 958 PopulateAudioFrame(&frame_data_.input_frame[0], kRenderInputFloatLevel, 959 frame_data_.input_number_of_channels, 960 frame_data_.input_samples_per_channel, rand_gen_); 961 frame_data_.input_channel_layout = 962 (frame_data_.input_number_of_channels == 1 963 ? AudioProcessing::ChannelLayout::kMono 964 : AudioProcessing::ChannelLayout::kStereo); 965 966 // Prepare the float audio output data and metadata. 967 frame_data_.output_samples_per_channel = 968 frame_data_.output_sample_rate_hz * AudioProcessing::kChunkSizeMs / 1000; 969 frame_data_.output_stream_config.set_sample_rate_hz( 970 frame_data_.output_sample_rate_hz); 971 frame_data_.output_stream_config.set_num_channels( 972 frame_data_.output_number_of_channels); 973 frame_data_.output_stream_config.set_has_keyboard(false); 974 frame_data_.output_channel_layout = 975 (frame_data_.output_number_of_channels == 1 976 ? AudioProcessing::ChannelLayout::kMono 977 : AudioProcessing::ChannelLayout::kStereo); 978 } 979 980 // Makes the render side processing API call. 981 void RenderProcessor::CallApmRenderSide() { 982 // Prepare a proper render side processing API call input. 983 PrepareFrame(); 984 985 // Call the specified render side API processing method. 986 int result = AudioProcessing::kNoError; 987 switch (test_config_->render_api_function) { 988 case RenderApiImpl::ProcessReverseStreamImpl1: 989 result = apm_->ProcessReverseStream(&frame_data_.frame); 990 break; 991 case RenderApiImpl::ProcessReverseStreamImpl2: 992 result = apm_->ProcessReverseStream( 993 &frame_data_.input_frame[0], frame_data_.input_stream_config, 994 frame_data_.output_stream_config, &frame_data_.output_frame[0]); 995 break; 996 case RenderApiImpl::AnalyzeReverseStreamImpl1: 997 result = apm_->AnalyzeReverseStream(&frame_data_.frame); 998 break; 999 case RenderApiImpl::AnalyzeReverseStreamImpl2: 1000 result = apm_->AnalyzeReverseStream( 1001 &frame_data_.input_frame[0], frame_data_.input_samples_per_channel, 1002 frame_data_.input_sample_rate_hz, frame_data_.input_channel_layout); 1003 break; 1004 default: 1005 FAIL(); 1006 } 1007 1008 // Check the return code for error. 1009 ASSERT_EQ(AudioProcessing::kNoError, result); 1010 } 1011 1012 // Applies any render capture side APM API calls and audio stream 1013 // characteristics 1014 // specified by the scheme for the test. 1015 void RenderProcessor::ApplyRuntimeSettingScheme() { 1016 const int render_count_local = frame_counters_->GetRenderCounter(); 1017 1018 // Update the number of channels and sample rates for the input and output. 1019 // Note that the counts frequencies for when to set parameters 1020 // are set using prime numbers in order to ensure that the 1021 // permutation scheme in the parameter setting changes. 1022 switch (test_config_->runtime_parameter_setting_scheme) { 1023 case RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme: 1024 if (render_count_local == 0) 1025 frame_data_.input_sample_rate_hz = 16000; 1026 else if (render_count_local % 47 == 0) 1027 frame_data_.input_sample_rate_hz = 32000; 1028 else if (render_count_local % 71 == 0) 1029 frame_data_.input_sample_rate_hz = 48000; 1030 else if (render_count_local % 79 == 0) 1031 frame_data_.input_sample_rate_hz = 16000; 1032 else if (render_count_local % 83 == 0) 1033 frame_data_.input_sample_rate_hz = 8000; 1034 1035 if (render_count_local == 0) 1036 frame_data_.input_number_of_channels = 1; 1037 else if (render_count_local % 4 == 0) 1038 frame_data_.input_number_of_channels = 1039 (frame_data_.input_number_of_channels == 1 ? 2 : 1); 1040 1041 if (render_count_local == 0) 1042 frame_data_.output_sample_rate_hz = 16000; 1043 else if (render_count_local % 17 == 0) 1044 frame_data_.output_sample_rate_hz = 32000; 1045 else if (render_count_local % 19 == 0) 1046 frame_data_.output_sample_rate_hz = 48000; 1047 else if (render_count_local % 29 == 0) 1048 frame_data_.output_sample_rate_hz = 16000; 1049 else if (render_count_local % 61 == 0) 1050 frame_data_.output_sample_rate_hz = 8000; 1051 1052 if (render_count_local == 0) 1053 frame_data_.output_number_of_channels = 1; 1054 else if (render_count_local % 8 == 0) 1055 frame_data_.output_number_of_channels = 1056 (frame_data_.output_number_of_channels == 1 ? 2 : 1); 1057 break; 1058 case RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme: 1059 if (render_count_local == 0) { 1060 frame_data_.input_number_of_channels = 1; 1061 frame_data_.input_sample_rate_hz = 16000; 1062 frame_data_.output_number_of_channels = 1; 1063 frame_data_.output_sample_rate_hz = 16000; 1064 } else { 1065 frame_data_.input_number_of_channels = 1066 (frame_data_.input_number_of_channels == 1 ? 2 : 1); 1067 if (frame_data_.input_sample_rate_hz == 8000) 1068 frame_data_.input_sample_rate_hz = 16000; 1069 else if (frame_data_.input_sample_rate_hz == 16000) 1070 frame_data_.input_sample_rate_hz = 32000; 1071 else if (frame_data_.input_sample_rate_hz == 32000) 1072 frame_data_.input_sample_rate_hz = 48000; 1073 else if (frame_data_.input_sample_rate_hz == 48000) 1074 frame_data_.input_sample_rate_hz = 8000; 1075 1076 frame_data_.output_number_of_channels = 1077 (frame_data_.output_number_of_channels == 1 ? 2 : 1); 1078 if (frame_data_.output_sample_rate_hz == 8000) 1079 frame_data_.output_sample_rate_hz = 16000; 1080 else if (frame_data_.output_sample_rate_hz == 16000) 1081 frame_data_.output_sample_rate_hz = 32000; 1082 else if (frame_data_.output_sample_rate_hz == 32000) 1083 frame_data_.output_sample_rate_hz = 48000; 1084 else if (frame_data_.output_sample_rate_hz == 48000) 1085 frame_data_.output_sample_rate_hz = 8000; 1086 } 1087 break; 1088 case RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme: 1089 if (render_count_local == 0) { 1090 frame_data_.input_sample_rate_hz = 16000; 1091 frame_data_.input_number_of_channels = 1; 1092 frame_data_.output_sample_rate_hz = 16000; 1093 frame_data_.output_number_of_channels = 1; 1094 } 1095 break; 1096 case RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme: 1097 if (render_count_local == 0) { 1098 frame_data_.input_sample_rate_hz = 16000; 1099 frame_data_.input_number_of_channels = 2; 1100 frame_data_.output_sample_rate_hz = 16000; 1101 frame_data_.output_number_of_channels = 2; 1102 } 1103 break; 1104 default: 1105 FAIL(); 1106 } 1107 1108 // Restric the number of output channels not to exceed 1109 // the number of input channels. 1110 frame_data_.output_number_of_channels = 1111 std::min(frame_data_.output_number_of_channels, 1112 frame_data_.input_number_of_channels); 1113 } 1114 1115 } // anonymous namespace 1116 1117 TEST_P(AudioProcessingImplLockTest, LockTest) { 1118 // Run test and verify that it did not time out. 1119 ASSERT_TRUE(RunTest()); 1120 } 1121 1122 // Instantiate tests from the extreme test configuration set. 1123 INSTANTIATE_TEST_CASE_P( 1124 DISABLED_AudioProcessingImplLockExtensive, 1125 AudioProcessingImplLockTest, 1126 ::testing::ValuesIn(TestConfig::GenerateExtensiveTestConfigs())); 1127 1128 INSTANTIATE_TEST_CASE_P( 1129 AudioProcessingImplLockBrief, 1130 AudioProcessingImplLockTest, 1131 ::testing::ValuesIn(TestConfig::GenerateBriefTestConfigs())); 1132 1133 } // namespace webrtc 1134