| Index: webrtc/modules/audio_processing/audio_processing_impl_locking_unittest.cc
|
| diff --git a/webrtc/modules/audio_processing/audio_processing_impl_locking_unittest.cc b/webrtc/modules/audio_processing/audio_processing_impl_locking_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d1dabee6363baca814b5727375bba0335ccb97c5
|
| --- /dev/null
|
| +++ b/webrtc/modules/audio_processing/audio_processing_impl_locking_unittest.cc
|
| @@ -0,0 +1,1118 @@
|
| +/*
|
| + * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
|
| + *
|
| + * Use of this source code is governed by a BSD-style license
|
| + * that can be found in the LICENSE file in the root of the source
|
| + * tree. An additional intellectual property rights grant can be found
|
| + * in the file PATENTS. All contributing project authors may
|
| + * be found in the AUTHORS file in the root of the source tree.
|
| + */
|
| +
|
| +#include "webrtc/modules/audio_processing/audio_processing_impl.h"
|
| +
|
| +#include <algorithm>
|
| +#include <vector>
|
| +
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +#include "webrtc/base/array_view.h"
|
| +#include "webrtc/base/criticalsection.h"
|
| +#include "webrtc/config.h"
|
| +#include "webrtc/modules/audio_processing/test/test_utils.h"
|
| +#include "webrtc/modules/include/module_common_types.h"
|
| +#include "webrtc/system_wrappers/include/event_wrapper.h"
|
| +#include "webrtc/system_wrappers/include/sleep.h"
|
| +#include "webrtc/system_wrappers/include/thread_wrapper.h"
|
| +#include "webrtc/test/random.h"
|
| +
|
| +namespace webrtc {
|
| +
|
| +namespace {
|
| +
|
| +class AudioProcessingImplLockTest;
|
| +
|
| +// Sleeps a random time between 0 and max_sleep milliseconds.
|
| +void SleepRandomMs(int max_sleep, test::Random* rand_gen) {
|
| + int sleeptime = rand_gen->Rand(0, max_sleep);
|
| + SleepMs(sleeptime);
|
| +}
|
| +
|
| +// Populates a float audio frame with random data.
|
| +void PopulateAudioFrame(float** frame,
|
| + float amplitude,
|
| + size_t num_channels,
|
| + size_t samples_per_channel,
|
| + test::Random* rand_gen) {
|
| + for (size_t ch = 0; ch < num_channels; ch++) {
|
| + for (size_t k = 0; k < samples_per_channel; k++) {
|
| + // Store random 16 bit quantized float number between +-amplitude.
|
| + frame[ch][k] = amplitude * (2 * rand_gen->Rand<float>() - 1);
|
| + }
|
| + }
|
| +}
|
| +
|
| +// Populates an audioframe frame of AudioFrame type with random data.
|
| +void PopulateAudioFrame(AudioFrame* frame,
|
| + int16_t amplitude,
|
| + test::Random* rand_gen) {
|
| + ASSERT_GT(amplitude, 0);
|
| + ASSERT_LE(amplitude, 32767);
|
| + for (int ch = 0; ch < frame->num_channels_; ch++) {
|
| + for (int k = 0; k < static_cast<int>(frame->samples_per_channel_); k++) {
|
| + // Store random 16 bit number between -(amplitude+1) and
|
| + // amplitude.
|
| + frame->data_[k * ch] = rand_gen->Rand(2 * amplitude + 1) - amplitude - 1;
|
| + }
|
| + }
|
| +}
|
| +
|
| +// Type of the render thread APM API call to use in the test.
|
| +enum class RenderApiImpl {
|
| + ProcessReverseStreamImpl1,
|
| + ProcessReverseStreamImpl2,
|
| + AnalyzeReverseStreamImpl1,
|
| + AnalyzeReverseStreamImpl2
|
| +};
|
| +
|
| +// Type of the capture thread APM API call to use in the test.
|
| +enum class CaptureApiImpl {
|
| + ProcessStreamImpl1,
|
| + ProcessStreamImpl2,
|
| + ProcessStreamImpl3
|
| +};
|
| +
|
| +// The runtime parameter setting scheme to use in the test.
|
| +enum class RuntimeParameterSettingScheme {
|
| + SparseStreamMetadataChangeScheme,
|
| + ExtremeStreamMetadataChangeScheme,
|
| + FixedMonoStreamMetadataScheme,
|
| + FixedStereoStreamMetadataScheme
|
| +};
|
| +
|
| +// Variant of echo canceller settings to use in the test.
|
| +enum class AecType {
|
| + BasicWebRtcAecSettings,
|
| + AecTurnedOff,
|
| + BasicWebRtcAecSettingsWithExtentedFilter,
|
| + BasicWebRtcAecSettingsWithDelayAgnosticAec,
|
| + BasicWebRtcAecSettingsWithAecMobile
|
| +};
|
| +
|
| +// Variables related to the audio data and formats.
|
| +struct AudioFrameData {
|
| + explicit AudioFrameData(int max_frame_size) {
|
| + // Set up the two-dimensional arrays needed for the APM API calls.
|
| + input_framechannels.resize(2 * max_frame_size);
|
| + input_frame.resize(2);
|
| + input_frame[0] = &input_framechannels[0];
|
| + input_frame[1] = &input_framechannels[max_frame_size];
|
| +
|
| + output_frame_channels.resize(2 * max_frame_size);
|
| + output_frame.resize(2);
|
| + output_frame[0] = &output_frame_channels[0];
|
| + output_frame[1] = &output_frame_channels[max_frame_size];
|
| + }
|
| +
|
| + AudioFrame frame;
|
| + std::vector<float*> output_frame;
|
| + std::vector<float> output_frame_channels;
|
| + AudioProcessing::ChannelLayout output_channel_layout =
|
| + AudioProcessing::ChannelLayout::kMono;
|
| + int input_sample_rate_hz = 16000;
|
| + int input_number_of_channels = -1;
|
| + std::vector<float*> input_frame;
|
| + std::vector<float> input_framechannels;
|
| + AudioProcessing::ChannelLayout input_channel_layout =
|
| + AudioProcessing::ChannelLayout::kMono;
|
| + int output_sample_rate_hz = 16000;
|
| + int output_number_of_channels = -1;
|
| + StreamConfig input_stream_config;
|
| + StreamConfig output_stream_config;
|
| + int input_samples_per_channel = -1;
|
| + int output_samples_per_channel = -1;
|
| +};
|
| +
|
| +// The configuration for the test.
|
| +struct TestConfig {
|
| + // Test case generator for the test configurations to use in the brief tests.
|
| + static std::vector<TestConfig> GenerateBriefTestConfigs() {
|
| + std::vector<TestConfig> test_configs;
|
| + AecType aec_types[] = {AecType::BasicWebRtcAecSettingsWithDelayAgnosticAec,
|
| + AecType::BasicWebRtcAecSettingsWithAecMobile};
|
| + for (auto aec_type : aec_types) {
|
| + TestConfig test_config;
|
| + test_config.aec_type = aec_type;
|
| +
|
| + test_config.min_number_of_calls = 300;
|
| +
|
| + // Perform tests only with the extreme runtime parameter setting scheme.
|
| + test_config.runtime_parameter_setting_scheme =
|
| + RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme;
|
| +
|
| + // Only test 16 kHz for this test suite.
|
| + test_config.initial_sample_rate_hz = 16000;
|
| +
|
| + // Create test config for the second processing API function set.
|
| + test_config.render_api_function =
|
| + RenderApiImpl::ProcessReverseStreamImpl2;
|
| + test_config.capture_api_function = CaptureApiImpl::ProcessStreamImpl2;
|
| +
|
| + // Create test config for the first processing API function set.
|
| + test_configs.push_back(test_config);
|
| + test_config.render_api_function =
|
| + RenderApiImpl::AnalyzeReverseStreamImpl2;
|
| + test_config.capture_api_function = CaptureApiImpl::ProcessStreamImpl3;
|
| + test_configs.push_back(test_config);
|
| + }
|
| +
|
| + // Return the created test configurations.
|
| + return test_configs;
|
| + }
|
| +
|
| + // Test case generator for the test configurations to use in the extensive
|
| + // tests.
|
| + static std::vector<TestConfig> GenerateExtensiveTestConfigs() {
|
| + // Lambda functions for the test config generation.
|
| + auto add_processing_apis = [](TestConfig test_config) {
|
| + struct AllowedApiCallCombinations {
|
| + RenderApiImpl render_api;
|
| + CaptureApiImpl capture_api;
|
| + };
|
| +
|
| + const AllowedApiCallCombinations api_calls[] = {
|
| + {RenderApiImpl::ProcessReverseStreamImpl1,
|
| + CaptureApiImpl::ProcessStreamImpl1},
|
| + {RenderApiImpl::AnalyzeReverseStreamImpl1,
|
| + CaptureApiImpl::ProcessStreamImpl1},
|
| + {RenderApiImpl::ProcessReverseStreamImpl2,
|
| + CaptureApiImpl::ProcessStreamImpl2},
|
| + {RenderApiImpl::ProcessReverseStreamImpl2,
|
| + CaptureApiImpl::ProcessStreamImpl3},
|
| + {RenderApiImpl::AnalyzeReverseStreamImpl2,
|
| + CaptureApiImpl::ProcessStreamImpl2},
|
| + {RenderApiImpl::AnalyzeReverseStreamImpl2,
|
| + CaptureApiImpl::ProcessStreamImpl3}};
|
| + std::vector<TestConfig> out;
|
| + for (auto api_call : api_calls) {
|
| + test_config.render_api_function = api_call.render_api;
|
| + test_config.capture_api_function = api_call.capture_api;
|
| + out.push_back(test_config);
|
| + }
|
| + return out;
|
| + };
|
| +
|
| + auto add_aec_settings = [](const std::vector<TestConfig>& in) {
|
| + std::vector<TestConfig> out;
|
| + AecType aec_types[] = {
|
| + AecType::BasicWebRtcAecSettings, AecType::AecTurnedOff,
|
| + AecType::BasicWebRtcAecSettingsWithExtentedFilter,
|
| + AecType::BasicWebRtcAecSettingsWithDelayAgnosticAec,
|
| + AecType::BasicWebRtcAecSettingsWithAecMobile};
|
| + for (auto test_config : in) {
|
| + for (auto aec_type : aec_types) {
|
| + test_config.aec_type = aec_type;
|
| + out.push_back(test_config);
|
| + }
|
| + }
|
| + return out;
|
| + };
|
| +
|
| + auto add_settings_scheme = [](const std::vector<TestConfig>& in) {
|
| + std::vector<TestConfig> out;
|
| + RuntimeParameterSettingScheme schemes[] = {
|
| + RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme,
|
| + RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme,
|
| + RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme,
|
| + RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme};
|
| +
|
| + for (auto test_config : in) {
|
| + for (auto scheme : schemes) {
|
| + test_config.runtime_parameter_setting_scheme = scheme;
|
| + out.push_back(test_config);
|
| + }
|
| + }
|
| + return out;
|
| + };
|
| +
|
| + auto add_sample_rates = [](const std::vector<TestConfig>& in) {
|
| + const int sample_rates[] = {8000, 16000, 32000, 48000};
|
| +
|
| + std::vector<TestConfig> out;
|
| + for (auto test_config : in) {
|
| + auto available_rates =
|
| + (test_config.aec_type ==
|
| + AecType::BasicWebRtcAecSettingsWithAecMobile
|
| + ? rtc::ArrayView<const int>(sample_rates, 2)
|
| + : rtc::ArrayView<const int>(sample_rates));
|
| +
|
| + for (auto rate : available_rates) {
|
| + test_config.initial_sample_rate_hz = rate;
|
| + out.push_back(test_config);
|
| + }
|
| + }
|
| + return out;
|
| + };
|
| +
|
| + // Generate test configurations of the relevant combinations of the
|
| + // parameters to
|
| + // test.
|
| + TestConfig test_config;
|
| + test_config.min_number_of_calls = 10000;
|
| + return add_sample_rates(add_settings_scheme(
|
| + add_aec_settings(add_processing_apis(test_config))));
|
| + }
|
| +
|
| + RenderApiImpl render_api_function = RenderApiImpl::ProcessReverseStreamImpl2;
|
| + CaptureApiImpl capture_api_function = CaptureApiImpl::ProcessStreamImpl2;
|
| + RuntimeParameterSettingScheme runtime_parameter_setting_scheme =
|
| + RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme;
|
| + int initial_sample_rate_hz = 16000;
|
| + AecType aec_type = AecType::BasicWebRtcAecSettingsWithDelayAgnosticAec;
|
| + int min_number_of_calls = 300;
|
| +};
|
| +
|
| +// Handler for the frame counters.
|
| +class FrameCounters {
|
| + public:
|
| + void IncreaseRenderCounter() {
|
| + rtc::CritScope cs(&crit_);
|
| + render_count++;
|
| + }
|
| +
|
| + void IncreaseCaptureCounter() {
|
| + rtc::CritScope cs(&crit_);
|
| + capture_count++;
|
| + }
|
| +
|
| + int GetCaptureCounter() {
|
| + rtc::CritScope cs(&crit_);
|
| + return capture_count;
|
| + }
|
| +
|
| + int GetRenderCounter() {
|
| + rtc::CritScope cs(&crit_);
|
| + return render_count;
|
| + }
|
| +
|
| + int CaptureMinusRenderCounters() {
|
| + rtc::CritScope cs(&crit_);
|
| + return capture_count - render_count;
|
| + }
|
| +
|
| + bool BothCountersExceedeThreshold(int threshold) {
|
| + rtc::CritScope cs(&crit_);
|
| + return (render_count > threshold && capture_count > threshold);
|
| + }
|
| +
|
| + private:
|
| + rtc::CriticalSection crit_;
|
| + int render_count GUARDED_BY(crit_) = 0;
|
| + int capture_count GUARDED_BY(crit_) = 0;
|
| +};
|
| +
|
| +// Checker for whether the capture side has been called.
|
| +class CaptureSideCalledChecker {
|
| + public:
|
| + bool CaptureSideCalled() {
|
| + rtc::CritScope cs(&crit_);
|
| + return capture_side_called_;
|
| + }
|
| +
|
| + void FlagCaptureSideCalled() {
|
| + rtc::CritScope cs(&crit_);
|
| + capture_side_called_ = true;
|
| + }
|
| +
|
| + private:
|
| + rtc::CriticalSection crit_;
|
| + bool capture_side_called_ GUARDED_BY(crit_) = false;
|
| +};
|
| +
|
| +// Class for handling the capture side processing.
|
| +class CaptureProcessor {
|
| + public:
|
| + CaptureProcessor(int max_frame_size,
|
| + test::Random* rand_gen,
|
| + FrameCounters* shared_counters_state,
|
| + CaptureSideCalledChecker* capture_call_checker,
|
| + AudioProcessingImplLockTest* test_framework,
|
| + TestConfig* test_config,
|
| + AudioProcessing* apm);
|
| + bool Process();
|
| +
|
| + private:
|
| + static const int kMaxCallDifference = 10;
|
| + static const float kCaptureInputFloatLevel;
|
| + static const int kCaptureInputFixLevel = 1024;
|
| +
|
| + void PrepareFrame();
|
| + void CallApmCaptureSide();
|
| + void ApplyRuntimeSettingScheme();
|
| +
|
| + test::Random* rand_gen_ = nullptr;
|
| + FrameCounters* frame_counters_ = nullptr;
|
| + CaptureSideCalledChecker* capture_call_checker_ = nullptr;
|
| + AudioProcessingImplLockTest* test_ = nullptr;
|
| + TestConfig* test_config_ = nullptr;
|
| + AudioProcessing* apm_ = nullptr;
|
| + AudioFrameData frame_data_;
|
| +};
|
| +
|
| +// Class for handling the stats processing.
|
| +class StatsProcessor {
|
| + public:
|
| + StatsProcessor(test::Random* rand_gen,
|
| + TestConfig* test_config,
|
| + AudioProcessing* apm);
|
| + bool Process();
|
| +
|
| + private:
|
| + test::Random* rand_gen_ = nullptr;
|
| + TestConfig* test_config_ = nullptr;
|
| + AudioProcessing* apm_ = nullptr;
|
| +};
|
| +
|
| +// Class for handling the render side processing.
|
| +class RenderProcessor {
|
| + public:
|
| + RenderProcessor(int max_frame_size,
|
| + test::Random* rand_gen,
|
| + FrameCounters* shared_counters_state,
|
| + CaptureSideCalledChecker* capture_call_checker,
|
| + AudioProcessingImplLockTest* test_framework,
|
| + TestConfig* test_config,
|
| + AudioProcessing* apm);
|
| + bool Process();
|
| +
|
| + private:
|
| + static const int kMaxCallDifference = 10;
|
| + static const int kRenderInputFixLevel = 16384;
|
| + static const float kRenderInputFloatLevel;
|
| +
|
| + void PrepareFrame();
|
| + void CallApmRenderSide();
|
| + void ApplyRuntimeSettingScheme();
|
| +
|
| + test::Random* rand_gen_ = nullptr;
|
| + FrameCounters* frame_counters_ = nullptr;
|
| + CaptureSideCalledChecker* capture_call_checker_ = nullptr;
|
| + AudioProcessingImplLockTest* test_ = nullptr;
|
| + TestConfig* test_config_ = nullptr;
|
| + AudioProcessing* apm_ = nullptr;
|
| + bool first_render_side_call_ = true;
|
| + AudioFrameData frame_data_;
|
| +};
|
| +
|
| +class AudioProcessingImplLockTest
|
| + : public ::testing::TestWithParam<TestConfig> {
|
| + public:
|
| + AudioProcessingImplLockTest();
|
| + EventTypeWrapper RunTest();
|
| + void CheckTestCompleteness();
|
| +
|
| + private:
|
| + static const int kTestTimeOutLimit = 10 * 60 * 1000;
|
| + static const int kMaxFrameSize = 480;
|
| +
|
| + // ::testing::TestWithParam<> implementation
|
| + void SetUp() override;
|
| + void TearDown() override;
|
| +
|
| + // Thread callback for the render thread
|
| + static bool RenderProcessorThreadFunc(void* context) {
|
| + return reinterpret_cast<AudioProcessingImplLockTest*>(context)
|
| + ->render_thread_state_.Process();
|
| + }
|
| +
|
| + // Thread callback for the capture thread
|
| + static bool CaptureProcessorThreadFunc(void* context) {
|
| + return reinterpret_cast<AudioProcessingImplLockTest*>(context)
|
| + ->capture_thread_state_.Process();
|
| + }
|
| +
|
| + // Thread callback for the stats thread
|
| + static bool StatsProcessorThreadFunc(void* context) {
|
| + return reinterpret_cast<AudioProcessingImplLockTest*>(context)
|
| + ->stats_thread_state_.Process();
|
| + }
|
| +
|
| + // Tests whether all the required render and capture side calls have been
|
| + // done.
|
| + bool TestDone() {
|
| + return frame_counters_.BothCountersExceedeThreshold(
|
| + test_config_.min_number_of_calls);
|
| + }
|
| +
|
| + // Start the threads used in the test.
|
| + void StartThreads() {
|
| + ASSERT_TRUE(render_thread_->Start());
|
| + render_thread_->SetPriority(kRealtimePriority);
|
| + ASSERT_TRUE(capture_thread_->Start());
|
| + capture_thread_->SetPriority(kRealtimePriority);
|
| + ASSERT_TRUE(stats_thread_->Start());
|
| + stats_thread_->SetPriority(kNormalPriority);
|
| + }
|
| +
|
| + // Event handler for the test.
|
| + const rtc::scoped_ptr<EventWrapper> test_complete_;
|
| +
|
| + // Thread related variables.
|
| + rtc::scoped_ptr<ThreadWrapper> render_thread_;
|
| + rtc::scoped_ptr<ThreadWrapper> capture_thread_;
|
| + rtc::scoped_ptr<ThreadWrapper> stats_thread_;
|
| + mutable test::Random rand_gen_;
|
| +
|
| + rtc::scoped_ptr<AudioProcessing> apm_;
|
| + TestConfig test_config_;
|
| + FrameCounters frame_counters_;
|
| + CaptureSideCalledChecker capture_call_checker_;
|
| + RenderProcessor render_thread_state_;
|
| + CaptureProcessor capture_thread_state_;
|
| + StatsProcessor stats_thread_state_;
|
| +};
|
| +
|
| +AudioProcessingImplLockTest::AudioProcessingImplLockTest()
|
| + : test_complete_(EventWrapper::Create()),
|
| + render_thread_(ThreadWrapper::CreateThread(RenderProcessorThreadFunc,
|
| + this,
|
| + "render")),
|
| + capture_thread_(ThreadWrapper::CreateThread(CaptureProcessorThreadFunc,
|
| + this,
|
| + "capture")),
|
| + stats_thread_(
|
| + ThreadWrapper::CreateThread(StatsProcessorThreadFunc, this, "stats")),
|
| + rand_gen_(42U),
|
| + apm_(AudioProcessingImpl::Create()),
|
| + render_thread_state_(kMaxFrameSize,
|
| + &rand_gen_,
|
| + &frame_counters_,
|
| + &capture_call_checker_,
|
| + this,
|
| + &test_config_,
|
| + apm_.get()),
|
| + capture_thread_state_(kMaxFrameSize,
|
| + &rand_gen_,
|
| + &frame_counters_,
|
| + &capture_call_checker_,
|
| + this,
|
| + &test_config_,
|
| + apm_.get()),
|
| + stats_thread_state_(&rand_gen_, &test_config_, apm_.get()) {}
|
| +
|
| +// Run the test with a timeout.
|
| +EventTypeWrapper AudioProcessingImplLockTest::RunTest() {
|
| + StartThreads();
|
| + return test_complete_->Wait(kTestTimeOutLimit);
|
| +}
|
| +
|
| +void AudioProcessingImplLockTest::CheckTestCompleteness() {
|
| + if (HasFatalFailure() || TestDone()) {
|
| + test_complete_->Set();
|
| + }
|
| +}
|
| +
|
| +// Setup of test and APM.
|
| +void AudioProcessingImplLockTest::SetUp() {
|
| + test_config_ = static_cast<TestConfig>(GetParam());
|
| +
|
| + ASSERT_EQ(apm_->kNoError, apm_->level_estimator()->Enable(true));
|
| + ASSERT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
|
| +
|
| + ASSERT_EQ(apm_->kNoError,
|
| + apm_->gain_control()->set_mode(GainControl::kAdaptiveAnalog));
|
| + ASSERT_EQ(apm_->kNoError, apm_->gain_control()->Enable(true));
|
| +
|
| + ASSERT_EQ(apm_->kNoError, apm_->noise_suppression()->Enable(true));
|
| + ASSERT_EQ(apm_->kNoError, apm_->voice_detection()->Enable(true));
|
| +
|
| + Config config;
|
| + if (test_config_.aec_type == AecType::AecTurnedOff) {
|
| + ASSERT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(false));
|
| + ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false));
|
| + } else if (test_config_.aec_type ==
|
| + AecType::BasicWebRtcAecSettingsWithAecMobile) {
|
| + ASSERT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(true));
|
| + ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(false));
|
| + } else {
|
| + ASSERT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(false));
|
| + ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->Enable(true));
|
| + ASSERT_EQ(apm_->kNoError, apm_->echo_cancellation()->enable_metrics(true));
|
| + ASSERT_EQ(apm_->kNoError,
|
| + apm_->echo_cancellation()->enable_delay_logging(true));
|
| +
|
| + config.Set<ExtendedFilter>(
|
| + new ExtendedFilter(test_config_.aec_type ==
|
| + AecType::BasicWebRtcAecSettingsWithExtentedFilter));
|
| +
|
| + config.Set<DelayAgnostic>(
|
| + new DelayAgnostic(test_config_.aec_type ==
|
| + AecType::BasicWebRtcAecSettingsWithDelayAgnosticAec));
|
| +
|
| + apm_->SetExtraOptions(config);
|
| + }
|
| +}
|
| +
|
| +void AudioProcessingImplLockTest::TearDown() {
|
| + render_thread_->Stop();
|
| + capture_thread_->Stop();
|
| + stats_thread_->Stop();
|
| +}
|
| +
|
| +StatsProcessor::StatsProcessor(test::Random* rand_gen,
|
| + TestConfig* test_config,
|
| + AudioProcessing* apm)
|
| + : rand_gen_(rand_gen), test_config_(test_config), apm_(apm) {}
|
| +
|
| +// Implements the callback functionality for the statistics
|
| +// collection thread.
|
| +bool StatsProcessor::Process() {
|
| + SleepRandomMs(100, rand_gen_);
|
| +
|
| + EXPECT_EQ(apm_->echo_cancellation()->is_enabled(),
|
| + ((test_config_->aec_type != AecType::AecTurnedOff) &&
|
| + (test_config_->aec_type !=
|
| + AecType::BasicWebRtcAecSettingsWithAecMobile)));
|
| + apm_->echo_cancellation()->stream_drift_samples();
|
| + EXPECT_EQ(apm_->echo_control_mobile()->is_enabled(),
|
| + (test_config_->aec_type != AecType::AecTurnedOff) &&
|
| + (test_config_->aec_type ==
|
| + AecType::BasicWebRtcAecSettingsWithAecMobile));
|
| + EXPECT_TRUE(apm_->gain_control()->is_enabled());
|
| + apm_->gain_control()->stream_analog_level();
|
| + EXPECT_TRUE(apm_->noise_suppression()->is_enabled());
|
| +
|
| + // The below return values are not testable.
|
| + apm_->noise_suppression()->speech_probability();
|
| + apm_->voice_detection()->is_enabled();
|
| +
|
| + return true;
|
| +}
|
| +
|
| +const float CaptureProcessor::kCaptureInputFloatLevel = 0.03125f;
|
| +
|
| +CaptureProcessor::CaptureProcessor(
|
| + int max_frame_size,
|
| + test::Random* rand_gen,
|
| + FrameCounters* shared_counters_state,
|
| + CaptureSideCalledChecker* capture_call_checker,
|
| + AudioProcessingImplLockTest* test_framework,
|
| + TestConfig* test_config,
|
| + AudioProcessing* apm)
|
| + : rand_gen_(rand_gen),
|
| + frame_counters_(shared_counters_state),
|
| + capture_call_checker_(capture_call_checker),
|
| + test_(test_framework),
|
| + test_config_(test_config),
|
| + apm_(apm),
|
| + frame_data_(max_frame_size) {}
|
| +
|
| +// Implements the callback functionality for the capture thread.
|
| +bool CaptureProcessor::Process() {
|
| + // Sleep a random time to simulate thread jitter.
|
| + SleepRandomMs(3, rand_gen_);
|
| +
|
| + // End the test if complete.
|
| + test_->CheckTestCompleteness();
|
| +
|
| + // Ensure that there are not more capture side calls than render side
|
| + // calls.
|
| + if (capture_call_checker_->CaptureSideCalled()) {
|
| + while (kMaxCallDifference < frame_counters_->CaptureMinusRenderCounters()) {
|
| + SleepMs(1);
|
| + }
|
| + }
|
| +
|
| + // Apply any specified capture side APM non-processing runtime calls.
|
| + ApplyRuntimeSettingScheme();
|
| +
|
| + // Apply the capture side processing call.
|
| + CallApmCaptureSide();
|
| +
|
| + // Increase the number of capture-side calls.
|
| + frame_counters_->IncreaseCaptureCounter();
|
| +
|
| + // Flag that the capture side has been called at least once
|
| + // (needed to ensure that a capture call has been done
|
| + // before the first render call is performed (implicitly
|
| + // required by the APM API).
|
| + capture_call_checker_->FlagCaptureSideCalled();
|
| +
|
| + return true;
|
| +}
|
| +
|
| +// Prepares a frame with relevant audio data and metadata.
|
| +void CaptureProcessor::PrepareFrame() {
|
| + // Restrict to a common fixed sample rate if the AudioFrame
|
| + // interface is used.
|
| + if (test_config_->capture_api_function ==
|
| + CaptureApiImpl::ProcessStreamImpl1) {
|
| + frame_data_.input_sample_rate_hz = test_config_->initial_sample_rate_hz;
|
| + frame_data_.output_sample_rate_hz = test_config_->initial_sample_rate_hz;
|
| + }
|
| +
|
| + // Prepare the audioframe data and metadata.
|
| + frame_data_.input_samples_per_channel =
|
| + frame_data_.input_sample_rate_hz * AudioProcessing::kChunkSizeMs / 1000;
|
| + frame_data_.frame.sample_rate_hz_ = frame_data_.input_sample_rate_hz;
|
| + frame_data_.frame.num_channels_ = frame_data_.input_number_of_channels;
|
| + frame_data_.frame.samples_per_channel_ =
|
| + frame_data_.input_samples_per_channel;
|
| + PopulateAudioFrame(&frame_data_.frame, kCaptureInputFixLevel, rand_gen_);
|
| +
|
| + // Prepare the float audio input data and metadata.
|
| + frame_data_.input_stream_config.set_sample_rate_hz(
|
| + frame_data_.input_sample_rate_hz);
|
| + frame_data_.input_stream_config.set_num_channels(
|
| + frame_data_.input_number_of_channels);
|
| + frame_data_.input_stream_config.set_has_keyboard(false);
|
| + PopulateAudioFrame(&frame_data_.input_frame[0], kCaptureInputFloatLevel,
|
| + frame_data_.input_number_of_channels,
|
| + frame_data_.input_samples_per_channel, rand_gen_);
|
| + frame_data_.input_channel_layout =
|
| + (frame_data_.input_number_of_channels == 1
|
| + ? AudioProcessing::ChannelLayout::kMono
|
| + : AudioProcessing::ChannelLayout::kStereo);
|
| +
|
| + // Prepare the float audio output data and metadata.
|
| + frame_data_.output_samples_per_channel =
|
| + frame_data_.output_sample_rate_hz * AudioProcessing::kChunkSizeMs / 1000;
|
| + frame_data_.output_stream_config.set_sample_rate_hz(
|
| + frame_data_.output_sample_rate_hz);
|
| + frame_data_.output_stream_config.set_num_channels(
|
| + frame_data_.output_number_of_channels);
|
| + frame_data_.output_stream_config.set_has_keyboard(false);
|
| + frame_data_.output_channel_layout =
|
| + (frame_data_.output_number_of_channels == 1
|
| + ? AudioProcessing::ChannelLayout::kMono
|
| + : AudioProcessing::ChannelLayout::kStereo);
|
| +}
|
| +
|
| +// Applies the capture side processing API call.
|
| +void CaptureProcessor::CallApmCaptureSide() {
|
| + // Prepare a proper capture side processing API call input.
|
| + PrepareFrame();
|
| +
|
| + // Set the stream delay
|
| + apm_->set_stream_delay_ms(30);
|
| +
|
| + // Call the specified capture side API processing method.
|
| + int result = AudioProcessing::kNoError;
|
| + switch (test_config_->capture_api_function) {
|
| + case CaptureApiImpl::ProcessStreamImpl1:
|
| + result = apm_->ProcessStream(&frame_data_.frame);
|
| + break;
|
| + case CaptureApiImpl::ProcessStreamImpl2:
|
| + result = apm_->ProcessStream(
|
| + &frame_data_.input_frame[0], frame_data_.input_samples_per_channel,
|
| + frame_data_.input_sample_rate_hz, frame_data_.input_channel_layout,
|
| + frame_data_.output_sample_rate_hz, frame_data_.output_channel_layout,
|
| + &frame_data_.output_frame[0]);
|
| + break;
|
| + case CaptureApiImpl::ProcessStreamImpl3:
|
| + result = apm_->ProcessStream(
|
| + &frame_data_.input_frame[0], frame_data_.input_stream_config,
|
| + frame_data_.output_stream_config, &frame_data_.output_frame[0]);
|
| + break;
|
| + default:
|
| + FAIL();
|
| + }
|
| +
|
| + // Check the return code for error.
|
| + ASSERT_EQ(AudioProcessing::kNoError, result);
|
| +}
|
| +
|
| +// Applies any runtime capture APM API calls and audio stream characteristics
|
| +// specified by the scheme for the test.
|
| +void CaptureProcessor::ApplyRuntimeSettingScheme() {
|
| + const int capture_count_local = frame_counters_->GetCaptureCounter();
|
| +
|
| + // Update the number of channels and sample rates for the input and output.
|
| + // Note that the counts frequencies for when to set parameters
|
| + // are set using prime numbers in order to ensure that the
|
| + // permutation scheme in the parameter setting changes.
|
| + switch (test_config_->runtime_parameter_setting_scheme) {
|
| + case RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme:
|
| + if (capture_count_local == 0)
|
| + frame_data_.input_sample_rate_hz = 16000;
|
| + else if (capture_count_local % 11 == 0)
|
| + frame_data_.input_sample_rate_hz = 32000;
|
| + else if (capture_count_local % 73 == 0)
|
| + frame_data_.input_sample_rate_hz = 48000;
|
| + else if (capture_count_local % 89 == 0)
|
| + frame_data_.input_sample_rate_hz = 16000;
|
| + else if (capture_count_local % 97 == 0)
|
| + frame_data_.input_sample_rate_hz = 8000;
|
| +
|
| + if (capture_count_local == 0)
|
| + frame_data_.input_number_of_channels = 1;
|
| + else if (capture_count_local % 4 == 0)
|
| + frame_data_.input_number_of_channels =
|
| + (frame_data_.input_number_of_channels == 1 ? 2 : 1);
|
| +
|
| + if (capture_count_local == 0)
|
| + frame_data_.output_sample_rate_hz = 16000;
|
| + else if (capture_count_local % 5 == 0)
|
| + frame_data_.output_sample_rate_hz = 32000;
|
| + else if (capture_count_local % 47 == 0)
|
| + frame_data_.output_sample_rate_hz = 48000;
|
| + else if (capture_count_local % 53 == 0)
|
| + frame_data_.output_sample_rate_hz = 16000;
|
| + else if (capture_count_local % 71 == 0)
|
| + frame_data_.output_sample_rate_hz = 8000;
|
| +
|
| + if (capture_count_local == 0)
|
| + frame_data_.output_number_of_channels = 1;
|
| + else if (capture_count_local % 8 == 0)
|
| + frame_data_.output_number_of_channels =
|
| + (frame_data_.output_number_of_channels == 1 ? 2 : 1);
|
| + break;
|
| + case RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme:
|
| + if (capture_count_local % 2 == 0) {
|
| + frame_data_.input_number_of_channels = 1;
|
| + frame_data_.input_sample_rate_hz = 16000;
|
| + frame_data_.output_number_of_channels = 1;
|
| + frame_data_.output_sample_rate_hz = 16000;
|
| + } else {
|
| + frame_data_.input_number_of_channels =
|
| + (frame_data_.input_number_of_channels == 1 ? 2 : 1);
|
| + if (frame_data_.input_sample_rate_hz == 8000)
|
| + frame_data_.input_sample_rate_hz = 16000;
|
| + else if (frame_data_.input_sample_rate_hz == 16000)
|
| + frame_data_.input_sample_rate_hz = 32000;
|
| + else if (frame_data_.input_sample_rate_hz == 32000)
|
| + frame_data_.input_sample_rate_hz = 48000;
|
| + else if (frame_data_.input_sample_rate_hz == 48000)
|
| + frame_data_.input_sample_rate_hz = 8000;
|
| +
|
| + frame_data_.output_number_of_channels =
|
| + (frame_data_.output_number_of_channels == 1 ? 2 : 1);
|
| + if (frame_data_.output_sample_rate_hz == 8000)
|
| + frame_data_.output_sample_rate_hz = 16000;
|
| + else if (frame_data_.output_sample_rate_hz == 16000)
|
| + frame_data_.output_sample_rate_hz = 32000;
|
| + else if (frame_data_.output_sample_rate_hz == 32000)
|
| + frame_data_.output_sample_rate_hz = 48000;
|
| + else if (frame_data_.output_sample_rate_hz == 48000)
|
| + frame_data_.output_sample_rate_hz = 8000;
|
| + }
|
| + break;
|
| + case RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme:
|
| + if (capture_count_local == 0) {
|
| + frame_data_.input_sample_rate_hz = 16000;
|
| + frame_data_.input_number_of_channels = 1;
|
| + frame_data_.output_sample_rate_hz = 16000;
|
| + frame_data_.output_number_of_channels = 1;
|
| + }
|
| + break;
|
| + case RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme:
|
| + if (capture_count_local == 0) {
|
| + frame_data_.input_sample_rate_hz = 16000;
|
| + frame_data_.input_number_of_channels = 2;
|
| + frame_data_.output_sample_rate_hz = 16000;
|
| + frame_data_.output_number_of_channels = 2;
|
| + }
|
| + break;
|
| + default:
|
| + FAIL();
|
| + }
|
| +
|
| + // Call any specified runtime APM setter and
|
| + // getter calls.
|
| + switch (test_config_->runtime_parameter_setting_scheme) {
|
| + case RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme:
|
| + case RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme:
|
| + break;
|
| + case RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme:
|
| + case RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme:
|
| + if (capture_count_local % 2 == 0) {
|
| + ASSERT_EQ(AudioProcessing::Error::kNoError,
|
| + apm_->set_stream_delay_ms(30));
|
| + apm_->set_stream_key_pressed(true);
|
| + apm_->set_output_will_be_muted(true);
|
| + apm_->set_delay_offset_ms(15);
|
| + EXPECT_EQ(apm_->delay_offset_ms(), 15);
|
| + EXPECT_GE(apm_->num_reverse_channels(), 0);
|
| + EXPECT_LE(apm_->num_reverse_channels(), 2);
|
| + } else {
|
| + ASSERT_EQ(AudioProcessing::Error::kNoError,
|
| + apm_->set_stream_delay_ms(50));
|
| + apm_->set_stream_key_pressed(false);
|
| + apm_->set_output_will_be_muted(false);
|
| + apm_->set_delay_offset_ms(20);
|
| + EXPECT_EQ(apm_->delay_offset_ms(), 20);
|
| + apm_->delay_offset_ms();
|
| + apm_->num_reverse_channels();
|
| + EXPECT_GE(apm_->num_reverse_channels(), 0);
|
| + EXPECT_LE(apm_->num_reverse_channels(), 2);
|
| + }
|
| + break;
|
| + default:
|
| + FAIL();
|
| + }
|
| +
|
| + // Restric the number of output channels not to exceed
|
| + // the number of input channels.
|
| + frame_data_.output_number_of_channels =
|
| + std::min(frame_data_.output_number_of_channels,
|
| + frame_data_.input_number_of_channels);
|
| +}
|
| +
|
| +const float RenderProcessor::kRenderInputFloatLevel = 0.5f;
|
| +
|
| +RenderProcessor::RenderProcessor(int max_frame_size,
|
| + test::Random* rand_gen,
|
| + FrameCounters* shared_counters_state,
|
| + CaptureSideCalledChecker* capture_call_checker,
|
| + AudioProcessingImplLockTest* test_framework,
|
| + TestConfig* test_config,
|
| + AudioProcessing* apm)
|
| + : rand_gen_(rand_gen),
|
| + frame_counters_(shared_counters_state),
|
| + capture_call_checker_(capture_call_checker),
|
| + test_(test_framework),
|
| + test_config_(test_config),
|
| + apm_(apm),
|
| + frame_data_(max_frame_size) {}
|
| +
|
| +// Implements the callback functionality for the render thread.
|
| +bool RenderProcessor::Process() {
|
| + // Conditional wait to ensure that a capture call has been done
|
| + // before the first render call is performed (implicitly
|
| + // required by the APM API).
|
| + if (first_render_side_call_) {
|
| + while (!capture_call_checker_->CaptureSideCalled()) {
|
| + SleepRandomMs(3, rand_gen_);
|
| + }
|
| +
|
| + first_render_side_call_ = false;
|
| + }
|
| +
|
| + // Sleep a random time to simulate thread jitter.
|
| + SleepRandomMs(3, rand_gen_);
|
| +
|
| + // End the test early if a fatal failure (ASSERT_*) has occurred.
|
| + test_->CheckTestCompleteness();
|
| +
|
| + // Ensure that the number of render and capture calls do not
|
| + // differ too much.
|
| + while (kMaxCallDifference < -frame_counters_->CaptureMinusRenderCounters()) {
|
| + SleepMs(1);
|
| + }
|
| +
|
| + // Apply any specified render side APM non-processing runtime calls.
|
| + ApplyRuntimeSettingScheme();
|
| +
|
| + // Apply the render side processing call.
|
| + CallApmRenderSide();
|
| +
|
| + // Increase the number of render-side calls.
|
| + frame_counters_->IncreaseRenderCounter();
|
| +
|
| + return true;
|
| +}
|
| +
|
| +// Prepares the render side frame and the accompanying metadata
|
| +// with the appropriate information.
|
| +void RenderProcessor::PrepareFrame() {
|
| + // Restrict to a common fixed sample rate if the AudioFrame interface is
|
| + // used.
|
| + if ((test_config_->render_api_function ==
|
| + RenderApiImpl::AnalyzeReverseStreamImpl1) ||
|
| + (test_config_->render_api_function ==
|
| + RenderApiImpl::ProcessReverseStreamImpl1) ||
|
| + (test_config_->aec_type !=
|
| + AecType::BasicWebRtcAecSettingsWithAecMobile)) {
|
| + frame_data_.input_sample_rate_hz = test_config_->initial_sample_rate_hz;
|
| + frame_data_.output_sample_rate_hz = test_config_->initial_sample_rate_hz;
|
| + }
|
| +
|
| + // Prepare the audioframe data and metadata
|
| + frame_data_.input_samples_per_channel =
|
| + frame_data_.input_sample_rate_hz * AudioProcessing::kChunkSizeMs / 1000;
|
| + frame_data_.frame.sample_rate_hz_ = frame_data_.input_sample_rate_hz;
|
| + frame_data_.frame.num_channels_ = frame_data_.input_number_of_channels;
|
| + frame_data_.frame.samples_per_channel_ =
|
| + frame_data_.input_samples_per_channel;
|
| + PopulateAudioFrame(&frame_data_.frame, kRenderInputFixLevel, rand_gen_);
|
| +
|
| + // Prepare the float audio input data and metadata.
|
| + frame_data_.input_stream_config.set_sample_rate_hz(
|
| + frame_data_.input_sample_rate_hz);
|
| + frame_data_.input_stream_config.set_num_channels(
|
| + frame_data_.input_number_of_channels);
|
| + frame_data_.input_stream_config.set_has_keyboard(false);
|
| + PopulateAudioFrame(&frame_data_.input_frame[0], kRenderInputFloatLevel,
|
| + frame_data_.input_number_of_channels,
|
| + frame_data_.input_samples_per_channel, rand_gen_);
|
| + frame_data_.input_channel_layout =
|
| + (frame_data_.input_number_of_channels == 1
|
| + ? AudioProcessing::ChannelLayout::kMono
|
| + : AudioProcessing::ChannelLayout::kStereo);
|
| +
|
| + // Prepare the float audio output data and metadata.
|
| + frame_data_.output_samples_per_channel =
|
| + frame_data_.output_sample_rate_hz * AudioProcessing::kChunkSizeMs / 1000;
|
| + frame_data_.output_stream_config.set_sample_rate_hz(
|
| + frame_data_.output_sample_rate_hz);
|
| + frame_data_.output_stream_config.set_num_channels(
|
| + frame_data_.output_number_of_channels);
|
| + frame_data_.output_stream_config.set_has_keyboard(false);
|
| + frame_data_.output_channel_layout =
|
| + (frame_data_.output_number_of_channels == 1
|
| + ? AudioProcessing::ChannelLayout::kMono
|
| + : AudioProcessing::ChannelLayout::kStereo);
|
| +}
|
| +
|
| +// Makes the render side processing API call.
|
| +void RenderProcessor::CallApmRenderSide() {
|
| + // Prepare a proper render side processing API call input.
|
| + PrepareFrame();
|
| +
|
| + // Call the specified render side API processing method.
|
| + int result = AudioProcessing::kNoError;
|
| + switch (test_config_->render_api_function) {
|
| + case RenderApiImpl::ProcessReverseStreamImpl1:
|
| + result = apm_->ProcessReverseStream(&frame_data_.frame);
|
| + break;
|
| + case RenderApiImpl::ProcessReverseStreamImpl2:
|
| + result = apm_->ProcessReverseStream(
|
| + &frame_data_.input_frame[0], frame_data_.input_stream_config,
|
| + frame_data_.output_stream_config, &frame_data_.output_frame[0]);
|
| + break;
|
| + case RenderApiImpl::AnalyzeReverseStreamImpl1:
|
| + result = apm_->AnalyzeReverseStream(&frame_data_.frame);
|
| + break;
|
| + case RenderApiImpl::AnalyzeReverseStreamImpl2:
|
| + result = apm_->AnalyzeReverseStream(
|
| + &frame_data_.input_frame[0], frame_data_.input_samples_per_channel,
|
| + frame_data_.input_sample_rate_hz, frame_data_.input_channel_layout);
|
| + break;
|
| + default:
|
| + FAIL();
|
| + }
|
| +
|
| + // Check the return code for error.
|
| + ASSERT_EQ(AudioProcessing::kNoError, result);
|
| +}
|
| +
|
| +// Applies any render capture side APM API calls and audio stream
|
| +// characteristics
|
| +// specified by the scheme for the test.
|
| +void RenderProcessor::ApplyRuntimeSettingScheme() {
|
| + const int render_count_local = frame_counters_->GetRenderCounter();
|
| +
|
| + // Update the number of channels and sample rates for the input and output.
|
| + // Note that the counts frequencies for when to set parameters
|
| + // are set using prime numbers in order to ensure that the
|
| + // permutation scheme in the parameter setting changes.
|
| + switch (test_config_->runtime_parameter_setting_scheme) {
|
| + case RuntimeParameterSettingScheme::SparseStreamMetadataChangeScheme:
|
| + if (render_count_local == 0)
|
| + frame_data_.input_sample_rate_hz = 16000;
|
| + else if (render_count_local % 47 == 0)
|
| + frame_data_.input_sample_rate_hz = 32000;
|
| + else if (render_count_local % 71 == 0)
|
| + frame_data_.input_sample_rate_hz = 48000;
|
| + else if (render_count_local % 79 == 0)
|
| + frame_data_.input_sample_rate_hz = 16000;
|
| + else if (render_count_local % 83 == 0)
|
| + frame_data_.input_sample_rate_hz = 8000;
|
| +
|
| + if (render_count_local == 0)
|
| + frame_data_.input_number_of_channels = 1;
|
| + else if (render_count_local % 4 == 0)
|
| + frame_data_.input_number_of_channels =
|
| + (frame_data_.input_number_of_channels == 1 ? 2 : 1);
|
| +
|
| + if (render_count_local == 0)
|
| + frame_data_.output_sample_rate_hz = 16000;
|
| + else if (render_count_local % 17 == 0)
|
| + frame_data_.output_sample_rate_hz = 32000;
|
| + else if (render_count_local % 19 == 0)
|
| + frame_data_.output_sample_rate_hz = 48000;
|
| + else if (render_count_local % 29 == 0)
|
| + frame_data_.output_sample_rate_hz = 16000;
|
| + else if (render_count_local % 61 == 0)
|
| + frame_data_.output_sample_rate_hz = 8000;
|
| +
|
| + if (render_count_local == 0)
|
| + frame_data_.output_number_of_channels = 1;
|
| + else if (render_count_local % 8 == 0)
|
| + frame_data_.output_number_of_channels =
|
| + (frame_data_.output_number_of_channels == 1 ? 2 : 1);
|
| + break;
|
| + case RuntimeParameterSettingScheme::ExtremeStreamMetadataChangeScheme:
|
| + if (render_count_local == 0) {
|
| + frame_data_.input_number_of_channels = 1;
|
| + frame_data_.input_sample_rate_hz = 16000;
|
| + frame_data_.output_number_of_channels = 1;
|
| + frame_data_.output_sample_rate_hz = 16000;
|
| + } else {
|
| + frame_data_.input_number_of_channels =
|
| + (frame_data_.input_number_of_channels == 1 ? 2 : 1);
|
| + if (frame_data_.input_sample_rate_hz == 8000)
|
| + frame_data_.input_sample_rate_hz = 16000;
|
| + else if (frame_data_.input_sample_rate_hz == 16000)
|
| + frame_data_.input_sample_rate_hz = 32000;
|
| + else if (frame_data_.input_sample_rate_hz == 32000)
|
| + frame_data_.input_sample_rate_hz = 48000;
|
| + else if (frame_data_.input_sample_rate_hz == 48000)
|
| + frame_data_.input_sample_rate_hz = 8000;
|
| +
|
| + frame_data_.output_number_of_channels =
|
| + (frame_data_.output_number_of_channels == 1 ? 2 : 1);
|
| + if (frame_data_.output_sample_rate_hz == 8000)
|
| + frame_data_.output_sample_rate_hz = 16000;
|
| + else if (frame_data_.output_sample_rate_hz == 16000)
|
| + frame_data_.output_sample_rate_hz = 32000;
|
| + else if (frame_data_.output_sample_rate_hz == 32000)
|
| + frame_data_.output_sample_rate_hz = 48000;
|
| + else if (frame_data_.output_sample_rate_hz == 48000)
|
| + frame_data_.output_sample_rate_hz = 8000;
|
| + }
|
| + break;
|
| + case RuntimeParameterSettingScheme::FixedMonoStreamMetadataScheme:
|
| + if (render_count_local == 0) {
|
| + frame_data_.input_sample_rate_hz = 16000;
|
| + frame_data_.input_number_of_channels = 1;
|
| + frame_data_.output_sample_rate_hz = 16000;
|
| + frame_data_.output_number_of_channels = 1;
|
| + }
|
| + break;
|
| + case RuntimeParameterSettingScheme::FixedStereoStreamMetadataScheme:
|
| + if (render_count_local == 0) {
|
| + frame_data_.input_sample_rate_hz = 16000;
|
| + frame_data_.input_number_of_channels = 2;
|
| + frame_data_.output_sample_rate_hz = 16000;
|
| + frame_data_.output_number_of_channels = 2;
|
| + }
|
| + break;
|
| + default:
|
| + FAIL();
|
| + }
|
| +
|
| + // Restric the number of output channels not to exceed
|
| + // the number of input channels.
|
| + frame_data_.output_number_of_channels =
|
| + std::min(frame_data_.output_number_of_channels,
|
| + frame_data_.input_number_of_channels);
|
| +}
|
| +
|
| +} // anonymous namespace
|
| +
|
| +TEST_P(AudioProcessingImplLockTest, LockTest) {
|
| + // Run test and verify that it did not time out.
|
| + ASSERT_EQ(kEventSignaled, RunTest());
|
| +}
|
| +
|
| +// Instantiate tests from the extreme test configuration set.
|
| +INSTANTIATE_TEST_CASE_P(
|
| + DISABLED_AudioProcessingImplLockExtensive,
|
| + AudioProcessingImplLockTest,
|
| + ::testing::ValuesIn(TestConfig::GenerateExtensiveTestConfigs()));
|
| +
|
| +INSTANTIATE_TEST_CASE_P(
|
| + DISABLED_AudioProcessingImplLockBrief,
|
| + AudioProcessingImplLockTest,
|
| + ::testing::ValuesIn(TestConfig::GenerateBriefTestConfigs()));
|
| +
|
| +} // namespace webrtc
|
|
|