decimator_unittest.cc (4580B)
1 /* 2 * Copyright (c) 2017 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 "modules/audio_processing/aec3/decimator.h" 12 13 #include <algorithm> 14 #include <array> 15 #include <cmath> 16 #include <cstring> 17 #include <numbers> 18 #include <numeric> 19 #include <string> 20 #include <vector> 21 22 #include "api/array_view.h" 23 #include "modules/audio_processing/aec3/aec3_common.h" 24 #include "rtc_base/checks.h" 25 #include "rtc_base/strings/string_builder.h" 26 #include "test/gtest.h" 27 28 namespace webrtc { 29 30 namespace { 31 32 std::string ProduceDebugText(int sample_rate_hz) { 33 StringBuilder ss; 34 ss << "Sample rate: " << sample_rate_hz; 35 return ss.Release(); 36 } 37 38 constexpr size_t kDownSamplingFactors[] = {4, 8}; 39 constexpr float kPi = std::numbers::pi_v<float>; 40 constexpr size_t kNumStartupBlocks = 50; 41 constexpr size_t kNumBlocks = 1000; 42 43 void ProduceDecimatedSinusoidalOutputPower(int sample_rate_hz, 44 size_t down_sampling_factor, 45 float sinusoidal_frequency_hz, 46 float* input_power, 47 float* output_power) { 48 float input[kBlockSize * kNumBlocks]; 49 const size_t sub_block_size = kBlockSize / down_sampling_factor; 50 51 // Produce a sinusoid of the specified frequency. 52 for (size_t k = 0; k < kBlockSize * kNumBlocks; ++k) { 53 input[k] = 32767.f * std::sin(2.f * kPi * sinusoidal_frequency_hz * k / 54 sample_rate_hz); 55 } 56 57 Decimator decimator(down_sampling_factor); 58 std::vector<float> output(sub_block_size * kNumBlocks); 59 60 for (size_t k = 0; k < kNumBlocks; ++k) { 61 std::vector<float> sub_block(sub_block_size); 62 decimator.Decimate( 63 ArrayView<const float>(&input[k * kBlockSize], kBlockSize), sub_block); 64 65 std::copy(sub_block.begin(), sub_block.end(), 66 output.begin() + k * sub_block_size); 67 } 68 69 ASSERT_GT(kNumBlocks, kNumStartupBlocks); 70 ArrayView<const float> input_to_evaluate( 71 &input[kNumStartupBlocks * kBlockSize], 72 (kNumBlocks - kNumStartupBlocks) * kBlockSize); 73 ArrayView<const float> output_to_evaluate( 74 &output[kNumStartupBlocks * sub_block_size], 75 (kNumBlocks - kNumStartupBlocks) * sub_block_size); 76 *input_power = 77 std::inner_product(input_to_evaluate.begin(), input_to_evaluate.end(), 78 input_to_evaluate.begin(), 0.f) / 79 input_to_evaluate.size(); 80 *output_power = 81 std::inner_product(output_to_evaluate.begin(), output_to_evaluate.end(), 82 output_to_evaluate.begin(), 0.f) / 83 output_to_evaluate.size(); 84 } 85 86 } // namespace 87 88 // Verifies that there is little aliasing from upper frequencies in the 89 // downsampling. 90 TEST(Decimator, NoLeakageFromUpperFrequencies) { 91 float input_power; 92 float output_power; 93 for (auto rate : {16000, 32000, 48000}) { 94 for (auto down_sampling_factor : kDownSamplingFactors) { 95 ProduceDebugText(rate); 96 ProduceDecimatedSinusoidalOutputPower(rate, down_sampling_factor, 97 3.f / 8.f * rate, &input_power, 98 &output_power); 99 EXPECT_GT(0.0001f * input_power, output_power); 100 } 101 } 102 } 103 104 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) 105 // Verifies the check for the input size. 106 TEST(DecimatorDeathTest, WrongInputSize) { 107 Decimator decimator(4); 108 std::vector<float> x(kBlockSize - 1, 0.f); 109 std::array<float, kBlockSize / 4> x_downsampled; 110 EXPECT_DEATH(decimator.Decimate(x, x_downsampled), ""); 111 } 112 113 // Verifies the check for non-null output parameter. 114 TEST(DecimatorDeathTest, NullOutput) { 115 Decimator decimator(4); 116 std::vector<float> x(kBlockSize, 0.f); 117 EXPECT_DEATH(decimator.Decimate(x, nullptr), ""); 118 } 119 120 // Verifies the check for the output size. 121 TEST(DecimatorDeathTest, WrongOutputSize) { 122 Decimator decimator(4); 123 std::vector<float> x(kBlockSize, 0.f); 124 std::array<float, kBlockSize / 4 - 1> x_downsampled; 125 EXPECT_DEATH(decimator.Decimate(x, x_downsampled), ""); 126 } 127 128 // Verifies the check for the correct downsampling factor. 129 TEST(DecimatorDeathTest, CorrectDownSamplingFactor) { 130 EXPECT_DEATH(Decimator(3), ""); 131 } 132 133 #endif 134 135 } // namespace webrtc