blob: 08dc4286669e61d4ad49c1d912a104738540ac8a [file] [log] [blame]
peah21920892017-02-08 05:08:56 -08001/*
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
Per Åhgren38e2d952017-11-17 14:54:28 +010011#include "modules/audio_processing/aec3/decimator.h"
peah21920892017-02-08 05:08:56 -080012
13#include <math.h>
14#include <algorithm>
15#include <array>
16#include <numeric>
peah21920892017-02-08 05:08:56 -080017#include <string>
18#include <vector>
19
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "modules/audio_processing/aec3/aec3_common.h"
Jonas Olsson366a50c2018-09-06 13:41:30 +020021#include "rtc_base/strings/string_builder.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "test/gtest.h"
peah21920892017-02-08 05:08:56 -080023
24namespace webrtc {
25
26namespace {
27
28std::string ProduceDebugText(int sample_rate_hz) {
Jonas Olsson366a50c2018-09-06 13:41:30 +020029 rtc::StringBuilder ss;
peah21920892017-02-08 05:08:56 -080030 ss << "Sample rate: " << sample_rate_hz;
Jonas Olsson84df1c72018-09-14 16:59:32 +020031 return ss.Release();
peah21920892017-02-08 05:08:56 -080032}
33
Per Åhgren38e2d952017-11-17 14:54:28 +010034constexpr size_t kDownSamplingFactors[] = {2, 4, 8};
peah21920892017-02-08 05:08:56 -080035constexpr float kPi = 3.141592f;
36constexpr size_t kNumStartupBlocks = 50;
37constexpr size_t kNumBlocks = 1000;
38
39void ProduceDecimatedSinusoidalOutputPower(int sample_rate_hz,
Per Åhgren38e2d952017-11-17 14:54:28 +010040 size_t down_sampling_factor,
peah21920892017-02-08 05:08:56 -080041 float sinusoidal_frequency_hz,
42 float* input_power,
43 float* output_power) {
44 float input[kBlockSize * kNumBlocks];
Per Åhgren38e2d952017-11-17 14:54:28 +010045 const size_t sub_block_size = kBlockSize / down_sampling_factor;
peah21920892017-02-08 05:08:56 -080046
47 // Produce a sinusoid of the specified frequency.
48 for (size_t k = 0; k < kBlockSize * kNumBlocks; ++k) {
49 input[k] =
50 32767.f * sin(2.f * kPi * sinusoidal_frequency_hz * k / sample_rate_hz);
51 }
52
Per Åhgren38e2d952017-11-17 14:54:28 +010053 Decimator decimator(down_sampling_factor);
54 std::vector<float> output(sub_block_size * kNumBlocks);
peah21920892017-02-08 05:08:56 -080055
56 for (size_t k = 0; k < kNumBlocks; ++k) {
Per Åhgren38e2d952017-11-17 14:54:28 +010057 std::vector<float> sub_block(sub_block_size);
peah21920892017-02-08 05:08:56 -080058
59 decimator.Decimate(
60 rtc::ArrayView<const float>(&input[k * kBlockSize], kBlockSize),
peahcf02cf12017-04-05 14:18:07 -070061 sub_block);
peah21920892017-02-08 05:08:56 -080062
63 std::copy(sub_block.begin(), sub_block.end(),
Per Åhgren38e2d952017-11-17 14:54:28 +010064 output.begin() + k * sub_block_size);
peah21920892017-02-08 05:08:56 -080065 }
66
67 ASSERT_GT(kNumBlocks, kNumStartupBlocks);
68 rtc::ArrayView<const float> input_to_evaluate(
69 &input[kNumStartupBlocks * kBlockSize],
70 (kNumBlocks - kNumStartupBlocks) * kBlockSize);
71 rtc::ArrayView<const float> output_to_evaluate(
Per Åhgren38e2d952017-11-17 14:54:28 +010072 &output[kNumStartupBlocks * sub_block_size],
73 (kNumBlocks - kNumStartupBlocks) * sub_block_size);
peah21920892017-02-08 05:08:56 -080074 *input_power =
75 std::inner_product(input_to_evaluate.begin(), input_to_evaluate.end(),
76 input_to_evaluate.begin(), 0.f) /
77 input_to_evaluate.size();
78 *output_power =
79 std::inner_product(output_to_evaluate.begin(), output_to_evaluate.end(),
80 output_to_evaluate.begin(), 0.f) /
81 output_to_evaluate.size();
82}
83
84} // namespace
85
86// Verifies that there is little aliasing from upper frequencies in the
87// downsampling.
Per Åhgren38e2d952017-11-17 14:54:28 +010088TEST(Decimator, NoLeakageFromUpperFrequencies) {
peah21920892017-02-08 05:08:56 -080089 float input_power;
90 float output_power;
91 for (auto rate : {8000, 16000, 32000, 48000}) {
Per Åhgren38e2d952017-11-17 14:54:28 +010092 for (auto down_sampling_factor : kDownSamplingFactors) {
93 ProduceDebugText(rate);
94 ProduceDecimatedSinusoidalOutputPower(rate, down_sampling_factor,
95 3.f / 8.f * rate, &input_power,
96 &output_power);
97 EXPECT_GT(0.0001f * input_power, output_power);
98 }
peah21920892017-02-08 05:08:56 -080099 }
100}
101
peah21920892017-02-08 05:08:56 -0800102#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
103// Verifies the check for the input size.
Per Åhgren38e2d952017-11-17 14:54:28 +0100104TEST(Decimator, WrongInputSize) {
105 Decimator decimator(4);
peah21920892017-02-08 05:08:56 -0800106 std::vector<float> x(std::vector<float>(kBlockSize - 1, 0.f));
Per Åhgren38e2d952017-11-17 14:54:28 +0100107 std::array<float, kBlockSize / 4> x_downsampled;
peahcf02cf12017-04-05 14:18:07 -0700108 EXPECT_DEATH(decimator.Decimate(x, x_downsampled), "");
peah21920892017-02-08 05:08:56 -0800109}
110
111// Verifies the check for non-null output parameter.
Per Åhgren38e2d952017-11-17 14:54:28 +0100112TEST(Decimator, NullOutput) {
113 Decimator decimator(4);
peah21920892017-02-08 05:08:56 -0800114 std::vector<float> x(std::vector<float>(kBlockSize, 0.f));
115 EXPECT_DEATH(decimator.Decimate(x, nullptr), "");
116}
117
Per Åhgren38e2d952017-11-17 14:54:28 +0100118// Verifies the check for the output size.
119TEST(Decimator, WrongOutputSize) {
120 Decimator decimator(4);
121 std::vector<float> x(std::vector<float>(kBlockSize, 0.f));
122 std::array<float, kBlockSize / 4 - 1> x_downsampled;
123 EXPECT_DEATH(decimator.Decimate(x, x_downsampled), "");
124}
125
126// Verifies the check for the correct downsampling factor.
127TEST(Decimator, CorrectDownSamplingFactor) {
128 EXPECT_DEATH(Decimator(3), "");
129}
130
peah21920892017-02-08 05:08:56 -0800131#endif
132
133} // namespace webrtc