tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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