audio_processing_impl_locking_unittest.cc (37162B)
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 <algorithm> 12 #include <cstddef> 13 #include <cstdint> 14 #include <vector> 15 16 #include "api/array_view.h" 17 #include "api/audio/audio_processing.h" 18 #include "api/audio/builtin_audio_processing_builder.h" 19 #include "api/environment/environment_factory.h" 20 #include "api/scoped_refptr.h" 21 #include "api/units/time_delta.h" 22 #include "rtc_base/event.h" 23 #include "rtc_base/platform_thread.h" 24 #include "rtc_base/random.h" 25 #include "rtc_base/synchronization/mutex.h" 26 #include "rtc_base/thread.h" 27 #include "rtc_base/thread_annotations.h" 28 #include "test/gtest.h" 29 30 namespace webrtc { 31 namespace { 32 33 constexpr int kMaxFrameSize = 480; 34 constexpr TimeDelta kTestTimeOutLimit = TimeDelta::Minutes(10); 35 36 class AudioProcessingImplLockTest; 37 38 // Type of the render thread APM API call to use in the test. 39 enum class RenderApiImpl { 40 ProcessReverseStreamImplInteger, 41 ProcessReverseStreamImplFloat, 42 AnalyzeReverseStreamImplFloat, 43 }; 44 45 // Type of the capture thread APM API call to use in the test. 46 enum class CaptureApiImpl { ProcessStreamImplInteger, ProcessStreamImplFloat }; 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 MutexLock lock(&mutex_); 72 return rand_gen_.Rand(min, max); 73 } 74 75 int RandInt(int max) { 76 MutexLock lock(&mutex_); 77 return rand_gen_.Rand(max); 78 } 79 80 float RandFloat() { 81 MutexLock lock(&mutex_); 82 return rand_gen_.Rand<float>(); 83 } 84 85 private: 86 Mutex mutex_; 87 Random rand_gen_ RTC_GUARDED_BY(mutex_); 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 frame.resize(2 * max_frame_size); 105 } 106 107 std::vector<int16_t> frame; 108 109 std::vector<float*> output_frame; 110 std::vector<float> output_frame_channels; 111 std::vector<float*> input_frame; 112 std::vector<float> input_framechannels; 113 114 int input_sample_rate_hz = 16000; 115 int input_number_of_channels = 1; 116 int output_sample_rate_hz = 16000; 117 int output_number_of_channels = 1; 118 }; 119 120 // The configuration for the test. 121 struct TestConfig { 122 // Test case generator for the test configurations to use in the brief tests. 123 static std::vector<TestConfig> GenerateBriefTestConfigs() { 124 std::vector<TestConfig> test_configs; 125 AecType aec_types[] = {AecType::BasicWebRtcAecSettingsWithDelayAgnosticAec, 126 AecType::BasicWebRtcAecSettingsWithAecMobile}; 127 for (auto aec_type : aec_types) { 128 TestConfig test_config; 129 test_config.aec_type = aec_type; 130 131 test_config.min_number_of_calls = 300; 132 133 // Perform tests only with the extreme runtime parameter setting scheme. 134 test_config.runtime_parameter_setting_scheme = 135 RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme; 136 137 // Only test 16 kHz for this test suite. 138 test_config.initial_sample_rate_hz = 16000; 139 140 // Create test config for the Int16 processing API function set. 141 test_config.render_api_function = 142 RenderApiImpl::ProcessReverseStreamImplInteger; 143 test_config.capture_api_function = 144 CaptureApiImpl::ProcessStreamImplInteger; 145 test_configs.push_back(test_config); 146 147 // Create test config for the StreamConfig processing API function set. 148 test_config.render_api_function = 149 RenderApiImpl::ProcessReverseStreamImplFloat; 150 test_config.capture_api_function = CaptureApiImpl::ProcessStreamImplFloat; 151 test_configs.push_back(test_config); 152 } 153 154 // Return the created test configurations. 155 return test_configs; 156 } 157 158 // Test case generator for the test configurations to use in the extensive 159 // tests. 160 static std::vector<TestConfig> GenerateExtensiveTestConfigs() { 161 // Lambda functions for the test config generation. 162 auto add_processing_apis = [](TestConfig test_config) { 163 struct AllowedApiCallCombinations { 164 RenderApiImpl render_api; 165 CaptureApiImpl capture_api; 166 }; 167 168 const AllowedApiCallCombinations api_calls[] = { 169 {.render_api = RenderApiImpl::ProcessReverseStreamImplInteger, 170 .capture_api = CaptureApiImpl::ProcessStreamImplInteger}, 171 {.render_api = RenderApiImpl::ProcessReverseStreamImplFloat, 172 .capture_api = CaptureApiImpl::ProcessStreamImplFloat}, 173 {.render_api = RenderApiImpl::AnalyzeReverseStreamImplFloat, 174 .capture_api = CaptureApiImpl::ProcessStreamImplFloat}, 175 {.render_api = RenderApiImpl::ProcessReverseStreamImplInteger, 176 .capture_api = CaptureApiImpl::ProcessStreamImplFloat}, 177 {.render_api = RenderApiImpl::ProcessReverseStreamImplFloat, 178 .capture_api = CaptureApiImpl::ProcessStreamImplInteger}}; 179 std::vector<TestConfig> out; 180 for (auto api_call : api_calls) { 181 test_config.render_api_function = api_call.render_api; 182 test_config.capture_api_function = api_call.capture_api; 183 out.push_back(test_config); 184 } 185 return out; 186 }; 187 188 auto add_aec_settings = [](const std::vector<TestConfig>& in) { 189 std::vector<TestConfig> out; 190 AecType aec_types[] = { 191 AecType::BasicWebRtcAecSettings, AecType::AecTurnedOff, 192 AecType::BasicWebRtcAecSettingsWithExtentedFilter, 193 AecType::BasicWebRtcAecSettingsWithDelayAgnosticAec, 194 AecType::BasicWebRtcAecSettingsWithAecMobile}; 195 for (auto test_config : in) { 196 // Due to a VisualStudio 2015 compiler issue, the internal loop 197 // variable here cannot override a previously defined name. 198 // In other words "type" cannot be named "aec_type" here. 199 // https://connect.microsoft.com/VisualStudio/feedback/details/2291755 200 for (auto type : aec_types) { 201 test_config.aec_type = type; 202 out.push_back(test_config); 203 } 204 } 205 return out; 206 }; 207 208 auto add_settings_scheme = [](const std::vector<TestConfig>& in) { 209 std::vector<TestConfig> out; 210 RuntimeParameterSettingScheme schemes[] = { 211 RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme, 212 RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme, 213 RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme, 214 RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme}; 215 216 for (auto test_config : in) { 217 for (auto scheme : schemes) { 218 test_config.runtime_parameter_setting_scheme = scheme; 219 out.push_back(test_config); 220 } 221 } 222 return out; 223 }; 224 225 auto add_sample_rates = [](const std::vector<TestConfig>& in) { 226 const int sample_rates[] = {8000, 16000, 32000, 48000}; 227 228 std::vector<TestConfig> out; 229 for (auto test_config : in) { 230 auto available_rates = 231 (test_config.aec_type == 232 AecType::BasicWebRtcAecSettingsWithAecMobile 233 ? ArrayView<const int>(sample_rates, 2) 234 : ArrayView<const int>(sample_rates)); 235 236 for (auto rate : available_rates) { 237 test_config.initial_sample_rate_hz = rate; 238 out.push_back(test_config); 239 } 240 } 241 return out; 242 }; 243 244 // Generate test configurations of the relevant combinations of the 245 // parameters to 246 // test. 247 TestConfig test_config; 248 test_config.min_number_of_calls = 10000; 249 return add_sample_rates(add_settings_scheme( 250 add_aec_settings(add_processing_apis(test_config)))); 251 } 252 253 RenderApiImpl render_api_function = 254 RenderApiImpl::ProcessReverseStreamImplFloat; 255 CaptureApiImpl capture_api_function = CaptureApiImpl::ProcessStreamImplFloat; 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 MutexLock lock(&mutex_); 268 render_count++; 269 } 270 271 void IncreaseCaptureCounter() { 272 MutexLock lock(&mutex_); 273 capture_count++; 274 } 275 276 int GetCaptureCounter() const { 277 MutexLock lock(&mutex_); 278 return capture_count; 279 } 280 281 int GetRenderCounter() const { 282 MutexLock lock(&mutex_); 283 return render_count; 284 } 285 286 int CaptureMinusRenderCounters() const { 287 MutexLock lock(&mutex_); 288 return capture_count - render_count; 289 } 290 291 int RenderMinusCaptureCounters() const { 292 return -CaptureMinusRenderCounters(); 293 } 294 295 bool BothCountersExceedeThreshold(int threshold) { 296 MutexLock lock(&mutex_); 297 return (render_count > threshold && capture_count > threshold); 298 } 299 300 private: 301 mutable Mutex mutex_; 302 int render_count RTC_GUARDED_BY(mutex_) = 0; 303 int capture_count RTC_GUARDED_BY(mutex_) = 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 Event* render_call_event, 312 Event* capture_call_event, 313 FrameCounters* shared_counters_state, 314 const TestConfig* test_config, 315 AudioProcessing* apm); 316 void Process(); 317 318 private: 319 static constexpr int kMaxCallDifference = 10; 320 static constexpr float kCaptureInputFloatLevel = 0.03125f; 321 static constexpr int kCaptureInputFixLevel = 1024; 322 323 void PrepareFrame(); 324 void CallApmCaptureSide(); 325 void ApplyRuntimeSettingScheme(); 326 327 RandomGenerator* const rand_gen_ = nullptr; 328 Event* const render_call_event_ = nullptr; 329 Event* const capture_call_event_ = nullptr; 330 FrameCounters* const frame_counters_ = nullptr; 331 const TestConfig* const test_config_ = nullptr; 332 AudioProcessing* const apm_ = nullptr; 333 AudioFrameData frame_data_; 334 }; 335 336 // Class for handling the stats processing. 337 class StatsProcessor { 338 public: 339 StatsProcessor(RandomGenerator* rand_gen, 340 const TestConfig* test_config, 341 AudioProcessing* apm); 342 void Process(); 343 344 private: 345 RandomGenerator* rand_gen_ = nullptr; 346 const TestConfig* const test_config_ = nullptr; 347 AudioProcessing* apm_ = nullptr; 348 }; 349 350 // Class for handling the render side processing. 351 class RenderProcessor { 352 public: 353 RenderProcessor(int max_frame_size, 354 RandomGenerator* rand_gen, 355 Event* render_call_event, 356 Event* capture_call_event, 357 FrameCounters* shared_counters_state, 358 const TestConfig* test_config, 359 AudioProcessing* apm); 360 void Process(); 361 362 private: 363 static constexpr int kMaxCallDifference = 10; 364 static constexpr int kRenderInputFixLevel = 16384; 365 static constexpr float kRenderInputFloatLevel = 0.5f; 366 367 void PrepareFrame(); 368 void CallApmRenderSide(); 369 void ApplyRuntimeSettingScheme(); 370 371 RandomGenerator* const rand_gen_ = nullptr; 372 Event* const render_call_event_ = nullptr; 373 Event* const capture_call_event_ = nullptr; 374 FrameCounters* const frame_counters_ = nullptr; 375 const TestConfig* const test_config_ = nullptr; 376 AudioProcessing* const apm_ = nullptr; 377 AudioFrameData frame_data_; 378 bool first_render_call_ = true; 379 }; 380 381 class AudioProcessingImplLockTest 382 : public ::testing::TestWithParam<TestConfig> { 383 public: 384 AudioProcessingImplLockTest(); 385 bool RunTest(); 386 bool MaybeEndTest(); 387 388 private: 389 void SetUp() override; 390 void TearDown() override; 391 392 // Tests whether all the required render and capture side calls have been 393 // done. 394 bool TestDone() { 395 return frame_counters_.BothCountersExceedeThreshold( 396 test_config_.min_number_of_calls); 397 } 398 399 // Start the threads used in the test. 400 void StartThreads() { 401 const auto attributes = 402 ThreadAttributes().SetPriority(ThreadPriority::kRealtime); 403 render_thread_ = PlatformThread::SpawnJoinable( 404 [this] { 405 while (!MaybeEndTest()) 406 render_thread_state_.Process(); 407 }, 408 "render", attributes); 409 capture_thread_ = PlatformThread::SpawnJoinable( 410 [this] { 411 while (!MaybeEndTest()) { 412 capture_thread_state_.Process(); 413 } 414 }, 415 "capture", attributes); 416 417 stats_thread_ = PlatformThread::SpawnJoinable( 418 [this] { 419 while (!MaybeEndTest()) 420 stats_thread_state_.Process(); 421 }, 422 "stats", attributes); 423 } 424 425 // Event handlers for the test. 426 Event test_complete_; 427 Event render_call_event_; 428 Event capture_call_event_; 429 430 // Thread related variables. 431 mutable RandomGenerator rand_gen_; 432 433 const TestConfig test_config_; 434 scoped_refptr<AudioProcessing> apm_; 435 FrameCounters frame_counters_; 436 RenderProcessor render_thread_state_; 437 CaptureProcessor capture_thread_state_; 438 StatsProcessor stats_thread_state_; 439 PlatformThread render_thread_; 440 PlatformThread capture_thread_; 441 PlatformThread stats_thread_; 442 }; 443 444 // Sleeps a random time between 0 and max_sleep milliseconds. 445 void SleepRandomMs(int max_sleep, RandomGenerator* rand_gen) { 446 int sleeptime = rand_gen->RandInt(0, max_sleep); 447 Thread::SleepMs(sleeptime); 448 } 449 450 // Populates a float audio frame with random data. 451 void PopulateAudioFrame(float** frame, 452 float amplitude, 453 size_t num_channels, 454 size_t samples_per_channel, 455 RandomGenerator* rand_gen) { 456 for (size_t ch = 0; ch < num_channels; ch++) { 457 for (size_t k = 0; k < samples_per_channel; k++) { 458 // Store random 16 bit quantized float number between +-amplitude. 459 frame[ch][k] = amplitude * (2 * rand_gen->RandFloat() - 1); 460 } 461 } 462 } 463 464 // Populates an integer audio frame with random data. 465 void PopulateAudioFrame(float amplitude, 466 size_t num_channels, 467 size_t samples_per_channel, 468 ArrayView<int16_t> frame, 469 RandomGenerator* rand_gen) { 470 ASSERT_GT(amplitude, 0); 471 ASSERT_LE(amplitude, 32767); 472 for (size_t ch = 0; ch < num_channels; ch++) { 473 for (size_t k = 0; k < samples_per_channel; k++) { 474 // Store random 16 bit number between -(amplitude+1) and 475 // amplitude. 476 frame[k * ch] = rand_gen->RandInt(2 * amplitude + 1) - amplitude - 1; 477 } 478 } 479 } 480 481 AudioProcessing::Config GetApmTestConfig(AecType aec_type) { 482 AudioProcessing::Config apm_config; 483 apm_config.echo_canceller.enabled = aec_type != AecType::AecTurnedOff; 484 apm_config.echo_canceller.mobile_mode = 485 aec_type == AecType::BasicWebRtcAecSettingsWithAecMobile; 486 apm_config.gain_controller1.enabled = true; 487 apm_config.gain_controller1.mode = 488 AudioProcessing::Config::GainController1::kAdaptiveDigital; 489 apm_config.noise_suppression.enabled = true; 490 return apm_config; 491 } 492 493 AudioProcessingImplLockTest::AudioProcessingImplLockTest() 494 : test_config_(GetParam()), 495 apm_(BuiltinAudioProcessingBuilder() 496 .SetConfig(GetApmTestConfig(test_config_.aec_type)) 497 .Build(CreateEnvironment())), 498 render_thread_state_(kMaxFrameSize, 499 &rand_gen_, 500 &render_call_event_, 501 &capture_call_event_, 502 &frame_counters_, 503 &test_config_, 504 apm_.get()), 505 capture_thread_state_(kMaxFrameSize, 506 &rand_gen_, 507 &render_call_event_, 508 &capture_call_event_, 509 &frame_counters_, 510 &test_config_, 511 apm_.get()), 512 stats_thread_state_(&rand_gen_, &test_config_, apm_.get()) {} 513 514 // Run the test with a timeout. 515 bool AudioProcessingImplLockTest::RunTest() { 516 StartThreads(); 517 return test_complete_.Wait(kTestTimeOutLimit); 518 } 519 520 bool AudioProcessingImplLockTest::MaybeEndTest() { 521 if (HasFatalFailure() || TestDone()) { 522 test_complete_.Set(); 523 return true; 524 } 525 return false; 526 } 527 528 void AudioProcessingImplLockTest::SetUp() {} 529 530 void AudioProcessingImplLockTest::TearDown() { 531 render_call_event_.Set(); 532 capture_call_event_.Set(); 533 } 534 535 StatsProcessor::StatsProcessor(RandomGenerator* rand_gen, 536 const TestConfig* test_config, 537 AudioProcessing* apm) 538 : rand_gen_(rand_gen), test_config_(test_config), apm_(apm) {} 539 540 // Implements the callback functionality for the statistics 541 // collection thread. 542 void StatsProcessor::Process() { 543 SleepRandomMs(100, rand_gen_); 544 545 AudioProcessing::Config apm_config = apm_->GetConfig(); 546 if (test_config_->aec_type != AecType::AecTurnedOff) { 547 EXPECT_TRUE(apm_config.echo_canceller.enabled); 548 EXPECT_EQ(apm_config.echo_canceller.mobile_mode, 549 (test_config_->aec_type == 550 AecType::BasicWebRtcAecSettingsWithAecMobile)); 551 } else { 552 EXPECT_FALSE(apm_config.echo_canceller.enabled); 553 } 554 EXPECT_TRUE(apm_config.gain_controller1.enabled); 555 EXPECT_TRUE(apm_config.noise_suppression.enabled); 556 557 // The below return value is not testable. 558 apm_->GetStatistics(); 559 } 560 561 CaptureProcessor::CaptureProcessor(int max_frame_size, 562 RandomGenerator* rand_gen, 563 Event* render_call_event, 564 Event* capture_call_event, 565 FrameCounters* shared_counters_state, 566 const TestConfig* test_config, 567 AudioProcessing* apm) 568 : rand_gen_(rand_gen), 569 render_call_event_(render_call_event), 570 capture_call_event_(capture_call_event), 571 frame_counters_(shared_counters_state), 572 test_config_(test_config), 573 apm_(apm), 574 frame_data_(max_frame_size) {} 575 576 // Implements the callback functionality for the capture thread. 577 void CaptureProcessor::Process() { 578 // Sleep a random time to simulate thread jitter. 579 SleepRandomMs(3, rand_gen_); 580 581 // Ensure that the number of render and capture calls do not 582 // differ too much. 583 if (frame_counters_->CaptureMinusRenderCounters() > kMaxCallDifference) { 584 render_call_event_->Wait(Event::kForever); 585 } 586 587 // Apply any specified capture side APM non-processing runtime calls. 588 ApplyRuntimeSettingScheme(); 589 590 // Apply the capture side processing call. 591 CallApmCaptureSide(); 592 593 // Increase the number of capture-side calls. 594 frame_counters_->IncreaseCaptureCounter(); 595 596 // Flag to the render thread that another capture API call has occurred 597 // by triggering this threads call event. 598 capture_call_event_->Set(); 599 } 600 601 // Prepares a frame with relevant audio data and metadata. 602 void CaptureProcessor::PrepareFrame() { 603 // Restrict to a common fixed sample rate if the integer 604 // interface is used. 605 if (test_config_->capture_api_function == 606 CaptureApiImpl::ProcessStreamImplInteger) { 607 frame_data_.input_sample_rate_hz = test_config_->initial_sample_rate_hz; 608 frame_data_.output_sample_rate_hz = test_config_->initial_sample_rate_hz; 609 } 610 611 // Prepare the audio data. 612 StreamConfig input_stream_config(frame_data_.input_sample_rate_hz, 613 frame_data_.input_number_of_channels); 614 615 PopulateAudioFrame(kCaptureInputFixLevel, input_stream_config.num_channels(), 616 input_stream_config.num_frames(), frame_data_.frame, 617 rand_gen_); 618 619 PopulateAudioFrame(&frame_data_.input_frame[0], kCaptureInputFloatLevel, 620 input_stream_config.num_channels(), 621 input_stream_config.num_frames(), rand_gen_); 622 } 623 624 // Applies the capture side processing API call. 625 void CaptureProcessor::CallApmCaptureSide() { 626 // Prepare a proper capture side processing API call input. 627 PrepareFrame(); 628 629 // Set the stream delay. 630 apm_->set_stream_delay_ms(30); 631 632 // Set the analog level. 633 apm_->set_stream_analog_level(80); 634 635 // Call the specified capture side API processing method. 636 StreamConfig input_stream_config(frame_data_.input_sample_rate_hz, 637 frame_data_.input_number_of_channels); 638 StreamConfig output_stream_config(frame_data_.output_sample_rate_hz, 639 frame_data_.output_number_of_channels); 640 int result = AudioProcessing::kNoError; 641 switch (test_config_->capture_api_function) { 642 case CaptureApiImpl::ProcessStreamImplInteger: 643 result = 644 apm_->ProcessStream(frame_data_.frame.data(), input_stream_config, 645 output_stream_config, frame_data_.frame.data()); 646 break; 647 case CaptureApiImpl::ProcessStreamImplFloat: 648 result = apm_->ProcessStream(&frame_data_.input_frame[0], 649 input_stream_config, output_stream_config, 650 &frame_data_.output_frame[0]); 651 break; 652 default: 653 FAIL(); 654 } 655 656 // Retrieve the new analog level. 657 apm_->recommended_stream_analog_level(); 658 659 // Check the return code for error. 660 ASSERT_EQ(AudioProcessing::kNoError, result); 661 } 662 663 // Applies any runtime capture APM API calls and audio stream characteristics 664 // specified by the scheme for the test. 665 void CaptureProcessor::ApplyRuntimeSettingScheme() { 666 const int capture_count_local = frame_counters_->GetCaptureCounter(); 667 668 // Update the number of channels and sample rates for the input and output. 669 // Note that the counts frequencies for when to set parameters 670 // are set using prime numbers in order to ensure that the 671 // permutation scheme in the parameter setting changes. 672 switch (test_config_->runtime_parameter_setting_scheme) { 673 case RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme: 674 if (capture_count_local == 0) 675 frame_data_.input_sample_rate_hz = 16000; 676 else if (capture_count_local % 11 == 0) 677 frame_data_.input_sample_rate_hz = 32000; 678 else if (capture_count_local % 73 == 0) 679 frame_data_.input_sample_rate_hz = 48000; 680 else if (capture_count_local % 89 == 0) 681 frame_data_.input_sample_rate_hz = 16000; 682 else if (capture_count_local % 97 == 0) 683 frame_data_.input_sample_rate_hz = 8000; 684 685 if (capture_count_local == 0) 686 frame_data_.input_number_of_channels = 1; 687 else if (capture_count_local % 4 == 0) 688 frame_data_.input_number_of_channels = 689 (frame_data_.input_number_of_channels == 1 ? 2 : 1); 690 691 if (capture_count_local == 0) 692 frame_data_.output_sample_rate_hz = 16000; 693 else if (capture_count_local % 5 == 0) 694 frame_data_.output_sample_rate_hz = 32000; 695 else if (capture_count_local % 47 == 0) 696 frame_data_.output_sample_rate_hz = 48000; 697 else if (capture_count_local % 53 == 0) 698 frame_data_.output_sample_rate_hz = 16000; 699 else if (capture_count_local % 71 == 0) 700 frame_data_.output_sample_rate_hz = 8000; 701 702 if (capture_count_local == 0) 703 frame_data_.output_number_of_channels = 1; 704 else if (capture_count_local % 8 == 0) 705 frame_data_.output_number_of_channels = 706 (frame_data_.output_number_of_channels == 1 ? 2 : 1); 707 break; 708 case RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme: 709 if (capture_count_local % 2 == 0) { 710 frame_data_.input_number_of_channels = 1; 711 frame_data_.input_sample_rate_hz = 16000; 712 frame_data_.output_number_of_channels = 1; 713 frame_data_.output_sample_rate_hz = 16000; 714 } else { 715 frame_data_.input_number_of_channels = 716 (frame_data_.input_number_of_channels == 1 ? 2 : 1); 717 if (frame_data_.input_sample_rate_hz == 8000) 718 frame_data_.input_sample_rate_hz = 16000; 719 else if (frame_data_.input_sample_rate_hz == 16000) 720 frame_data_.input_sample_rate_hz = 32000; 721 else if (frame_data_.input_sample_rate_hz == 32000) 722 frame_data_.input_sample_rate_hz = 48000; 723 else if (frame_data_.input_sample_rate_hz == 48000) 724 frame_data_.input_sample_rate_hz = 8000; 725 726 frame_data_.output_number_of_channels = 727 (frame_data_.output_number_of_channels == 1 ? 2 : 1); 728 if (frame_data_.output_sample_rate_hz == 8000) 729 frame_data_.output_sample_rate_hz = 16000; 730 else if (frame_data_.output_sample_rate_hz == 16000) 731 frame_data_.output_sample_rate_hz = 32000; 732 else if (frame_data_.output_sample_rate_hz == 32000) 733 frame_data_.output_sample_rate_hz = 48000; 734 else if (frame_data_.output_sample_rate_hz == 48000) 735 frame_data_.output_sample_rate_hz = 8000; 736 } 737 break; 738 case RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme: 739 if (capture_count_local == 0) { 740 frame_data_.input_sample_rate_hz = 16000; 741 frame_data_.input_number_of_channels = 1; 742 frame_data_.output_sample_rate_hz = 16000; 743 frame_data_.output_number_of_channels = 1; 744 } 745 break; 746 case RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme: 747 if (capture_count_local == 0) { 748 frame_data_.input_sample_rate_hz = 16000; 749 frame_data_.input_number_of_channels = 2; 750 frame_data_.output_sample_rate_hz = 16000; 751 frame_data_.output_number_of_channels = 2; 752 } 753 break; 754 default: 755 FAIL(); 756 } 757 758 // Call any specified runtime APM setter and 759 // getter calls. 760 switch (test_config_->runtime_parameter_setting_scheme) { 761 case RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme: 762 case RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme: 763 break; 764 case RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme: 765 case RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme: 766 if (capture_count_local % 2 == 0) { 767 ASSERT_EQ(AudioProcessing::Error::kNoError, 768 apm_->set_stream_delay_ms(30)); 769 apm_->set_stream_key_pressed(true); 770 } else { 771 ASSERT_EQ(AudioProcessing::Error::kNoError, 772 apm_->set_stream_delay_ms(50)); 773 apm_->set_stream_key_pressed(false); 774 } 775 break; 776 default: 777 FAIL(); 778 } 779 780 // Restric the number of output channels not to exceed 781 // the number of input channels. 782 frame_data_.output_number_of_channels = 783 std::min(frame_data_.output_number_of_channels, 784 frame_data_.input_number_of_channels); 785 } 786 787 RenderProcessor::RenderProcessor(int max_frame_size, 788 RandomGenerator* rand_gen, 789 Event* render_call_event, 790 Event* capture_call_event, 791 FrameCounters* shared_counters_state, 792 const TestConfig* test_config, 793 AudioProcessing* apm) 794 : rand_gen_(rand_gen), 795 render_call_event_(render_call_event), 796 capture_call_event_(capture_call_event), 797 frame_counters_(shared_counters_state), 798 test_config_(test_config), 799 apm_(apm), 800 frame_data_(max_frame_size) {} 801 802 // Implements the callback functionality for the render thread. 803 void RenderProcessor::Process() { 804 // Conditional wait to ensure that a capture call has been done 805 // before the first render call is performed (implicitly 806 // required by the APM API). 807 if (first_render_call_) { 808 capture_call_event_->Wait(Event::kForever); 809 first_render_call_ = false; 810 } 811 812 // Sleep a random time to simulate thread jitter. 813 SleepRandomMs(3, rand_gen_); 814 815 // Ensure that the number of render and capture calls do not 816 // differ too much. 817 if (frame_counters_->RenderMinusCaptureCounters() > kMaxCallDifference) { 818 capture_call_event_->Wait(Event::kForever); 819 } 820 821 // Apply any specified render side APM non-processing runtime calls. 822 ApplyRuntimeSettingScheme(); 823 824 // Apply the render side processing call. 825 CallApmRenderSide(); 826 827 // Increase the number of render-side calls. 828 frame_counters_->IncreaseRenderCounter(); 829 830 // Flag to the capture thread that another render API call has occurred 831 // by triggering this threads call event. 832 render_call_event_->Set(); 833 } 834 835 // Prepares the render side frame and the accompanying metadata 836 // with the appropriate information. 837 void RenderProcessor::PrepareFrame() { 838 // Restrict to a common fixed sample rate if the integer interface is 839 // used. 840 if ((test_config_->render_api_function == 841 RenderApiImpl::ProcessReverseStreamImplInteger) || 842 (test_config_->aec_type != 843 AecType::BasicWebRtcAecSettingsWithAecMobile)) { 844 frame_data_.input_sample_rate_hz = test_config_->initial_sample_rate_hz; 845 frame_data_.output_sample_rate_hz = test_config_->initial_sample_rate_hz; 846 } 847 848 // Prepare the audio data. 849 StreamConfig input_stream_config(frame_data_.input_sample_rate_hz, 850 frame_data_.input_number_of_channels); 851 852 PopulateAudioFrame(kRenderInputFixLevel, input_stream_config.num_channels(), 853 input_stream_config.num_frames(), frame_data_.frame, 854 rand_gen_); 855 856 PopulateAudioFrame(&frame_data_.input_frame[0], kRenderInputFloatLevel, 857 input_stream_config.num_channels(), 858 input_stream_config.num_frames(), rand_gen_); 859 } 860 861 // Makes the render side processing API call. 862 void RenderProcessor::CallApmRenderSide() { 863 // Prepare a proper render side processing API call input. 864 PrepareFrame(); 865 866 // Call the specified render side API processing method. 867 StreamConfig input_stream_config(frame_data_.input_sample_rate_hz, 868 frame_data_.input_number_of_channels); 869 StreamConfig output_stream_config(frame_data_.output_sample_rate_hz, 870 frame_data_.output_number_of_channels); 871 int result = AudioProcessing::kNoError; 872 switch (test_config_->render_api_function) { 873 case RenderApiImpl::ProcessReverseStreamImplInteger: 874 result = apm_->ProcessReverseStream( 875 frame_data_.frame.data(), input_stream_config, output_stream_config, 876 frame_data_.frame.data()); 877 break; 878 case RenderApiImpl::ProcessReverseStreamImplFloat: 879 result = apm_->ProcessReverseStream( 880 &frame_data_.input_frame[0], input_stream_config, 881 output_stream_config, &frame_data_.output_frame[0]); 882 break; 883 case RenderApiImpl::AnalyzeReverseStreamImplFloat: 884 result = apm_->AnalyzeReverseStream(&frame_data_.input_frame[0], 885 input_stream_config); 886 break; 887 default: 888 FAIL(); 889 } 890 891 // Check the return code for error. 892 ASSERT_EQ(AudioProcessing::kNoError, result); 893 } 894 895 // Applies any render capture side APM API calls and audio stream 896 // characteristics 897 // specified by the scheme for the test. 898 void RenderProcessor::ApplyRuntimeSettingScheme() { 899 const int render_count_local = frame_counters_->GetRenderCounter(); 900 901 // Update the number of channels and sample rates for the input and output. 902 // Note that the counts frequencies for when to set parameters 903 // are set using prime numbers in order to ensure that the 904 // permutation scheme in the parameter setting changes. 905 switch (test_config_->runtime_parameter_setting_scheme) { 906 case RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme: 907 if (render_count_local == 0) 908 frame_data_.input_sample_rate_hz = 16000; 909 else if (render_count_local % 47 == 0) 910 frame_data_.input_sample_rate_hz = 32000; 911 else if (render_count_local % 71 == 0) 912 frame_data_.input_sample_rate_hz = 48000; 913 else if (render_count_local % 79 == 0) 914 frame_data_.input_sample_rate_hz = 16000; 915 else if (render_count_local % 83 == 0) 916 frame_data_.input_sample_rate_hz = 8000; 917 918 if (render_count_local == 0) 919 frame_data_.input_number_of_channels = 1; 920 else if (render_count_local % 4 == 0) 921 frame_data_.input_number_of_channels = 922 (frame_data_.input_number_of_channels == 1 ? 2 : 1); 923 924 if (render_count_local == 0) 925 frame_data_.output_sample_rate_hz = 16000; 926 else if (render_count_local % 17 == 0) 927 frame_data_.output_sample_rate_hz = 32000; 928 else if (render_count_local % 19 == 0) 929 frame_data_.output_sample_rate_hz = 48000; 930 else if (render_count_local % 29 == 0) 931 frame_data_.output_sample_rate_hz = 16000; 932 else if (render_count_local % 61 == 0) 933 frame_data_.output_sample_rate_hz = 8000; 934 935 if (render_count_local == 0) 936 frame_data_.output_number_of_channels = 1; 937 else if (render_count_local % 8 == 0) 938 frame_data_.output_number_of_channels = 939 (frame_data_.output_number_of_channels == 1 ? 2 : 1); 940 break; 941 case RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme: 942 if (render_count_local == 0) { 943 frame_data_.input_number_of_channels = 1; 944 frame_data_.input_sample_rate_hz = 16000; 945 frame_data_.output_number_of_channels = 1; 946 frame_data_.output_sample_rate_hz = 16000; 947 } else { 948 frame_data_.input_number_of_channels = 949 (frame_data_.input_number_of_channels == 1 ? 2 : 1); 950 if (frame_data_.input_sample_rate_hz == 8000) 951 frame_data_.input_sample_rate_hz = 16000; 952 else if (frame_data_.input_sample_rate_hz == 16000) 953 frame_data_.input_sample_rate_hz = 32000; 954 else if (frame_data_.input_sample_rate_hz == 32000) 955 frame_data_.input_sample_rate_hz = 48000; 956 else if (frame_data_.input_sample_rate_hz == 48000) 957 frame_data_.input_sample_rate_hz = 8000; 958 959 frame_data_.output_number_of_channels = 960 (frame_data_.output_number_of_channels == 1 ? 2 : 1); 961 if (frame_data_.output_sample_rate_hz == 8000) 962 frame_data_.output_sample_rate_hz = 16000; 963 else if (frame_data_.output_sample_rate_hz == 16000) 964 frame_data_.output_sample_rate_hz = 32000; 965 else if (frame_data_.output_sample_rate_hz == 32000) 966 frame_data_.output_sample_rate_hz = 48000; 967 else if (frame_data_.output_sample_rate_hz == 48000) 968 frame_data_.output_sample_rate_hz = 8000; 969 } 970 break; 971 case RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme: 972 if (render_count_local == 0) { 973 frame_data_.input_sample_rate_hz = 16000; 974 frame_data_.input_number_of_channels = 1; 975 frame_data_.output_sample_rate_hz = 16000; 976 frame_data_.output_number_of_channels = 1; 977 } 978 break; 979 case RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme: 980 if (render_count_local == 0) { 981 frame_data_.input_sample_rate_hz = 16000; 982 frame_data_.input_number_of_channels = 2; 983 frame_data_.output_sample_rate_hz = 16000; 984 frame_data_.output_number_of_channels = 2; 985 } 986 break; 987 default: 988 FAIL(); 989 } 990 991 // Restric the number of output channels not to exceed 992 // the number of input channels. 993 frame_data_.output_number_of_channels = 994 std::min(frame_data_.output_number_of_channels, 995 frame_data_.input_number_of_channels); 996 } 997 998 } // namespace 999 1000 TEST_P(AudioProcessingImplLockTest, LockTest) { 1001 // Run test and verify that it did not time out. 1002 ASSERT_TRUE(RunTest()); 1003 } 1004 1005 // Instantiate tests from the extreme test configuration set. 1006 INSTANTIATE_TEST_SUITE_P( 1007 DISABLED_AudioProcessingImplLockExtensive, 1008 AudioProcessingImplLockTest, 1009 ::testing::ValuesIn(TestConfig::GenerateExtensiveTestConfigs())); 1010 1011 INSTANTIATE_TEST_SUITE_P( 1012 AudioProcessingImplLockBrief, 1013 AudioProcessingImplLockTest, 1014 ::testing::ValuesIn(TestConfig::GenerateBriefTestConfigs())); 1015 1016 } // namespace webrtc