/* * Copyright (c) 2017 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 "modules/audio_processing/aec3/decimator_by_4.h" #include #include #include #include #include #include #include #include "modules/audio_processing/aec3/aec3_common.h" #include "test/gtest.h" namespace webrtc { namespace { std::string ProduceDebugText(int sample_rate_hz) { std::ostringstream ss; ss << "Sample rate: " << sample_rate_hz; return ss.str(); } constexpr float kPi = 3.141592f; constexpr size_t kNumStartupBlocks = 50; constexpr size_t kNumBlocks = 1000; void ProduceDecimatedSinusoidalOutputPower(int sample_rate_hz, float sinusoidal_frequency_hz, float* input_power, float* output_power) { float input[kBlockSize * kNumBlocks]; // Produce a sinusoid of the specified frequency. for (size_t k = 0; k < kBlockSize * kNumBlocks; ++k) { input[k] = 32767.f * sin(2.f * kPi * sinusoidal_frequency_hz * k / sample_rate_hz); } DecimatorBy4 decimator; std::array output; for (size_t k = 0; k < kNumBlocks; ++k) { std::array sub_block; decimator.Decimate( rtc::ArrayView(&input[k * kBlockSize], kBlockSize), sub_block); std::copy(sub_block.begin(), sub_block.end(), output.begin() + k * kSubBlockSize); } ASSERT_GT(kNumBlocks, kNumStartupBlocks); rtc::ArrayView input_to_evaluate( &input[kNumStartupBlocks * kBlockSize], (kNumBlocks - kNumStartupBlocks) * kBlockSize); rtc::ArrayView output_to_evaluate( &output[kNumStartupBlocks * kSubBlockSize], (kNumBlocks - kNumStartupBlocks) * kSubBlockSize); *input_power = std::inner_product(input_to_evaluate.begin(), input_to_evaluate.end(), input_to_evaluate.begin(), 0.f) / input_to_evaluate.size(); *output_power = std::inner_product(output_to_evaluate.begin(), output_to_evaluate.end(), output_to_evaluate.begin(), 0.f) / output_to_evaluate.size(); } } // namespace // Verifies that there is little aliasing from upper frequencies in the // downsampling. TEST(DecimatorBy4, NoLeakageFromUpperFrequencies) { float input_power; float output_power; for (auto rate : {8000, 16000, 32000, 48000}) { ProduceDebugText(rate); ProduceDecimatedSinusoidalOutputPower(rate, 3.f / 8.f * rate, &input_power, &output_power); EXPECT_GT(0.0001f * input_power, output_power); } } // Verifies that the impact of low-frequency content is small during the // downsampling. TEST(DecimatorBy4, NoImpactOnLowerFrequencies) { float input_power; float output_power; for (auto rate : {8000, 16000, 32000, 48000}) { ProduceDebugText(rate); ProduceDecimatedSinusoidalOutputPower(rate, 200.f, &input_power, &output_power); EXPECT_LT(0.7f * input_power, output_power); } } #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) // Verifies the check for the input size. TEST(DecimatorBy4, WrongInputSize) { DecimatorBy4 decimator; std::vector x(std::vector(kBlockSize - 1, 0.f)); std::array x_downsampled; EXPECT_DEATH(decimator.Decimate(x, x_downsampled), ""); } // Verifies the check for non-null output parameter. TEST(DecimatorBy4, NullOutput) { DecimatorBy4 decimator; std::vector x(std::vector(kBlockSize, 0.f)); EXPECT_DEATH(decimator.Decimate(x, nullptr), ""); } #endif } // namespace webrtc