blob: f2ac6644048fb363ff41f3388a50ca4852a90547 [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>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
peah21920892017-02-08 05:08:56 -080015#include <algorithm>
16#include <array>
Mirko Bonadeidbce0902019-03-15 07:39:02 +010017#include <cmath>
Gustaf Ullbergee84d392019-09-10 09:36:43 +020018#include <cstring>
peah21920892017-02-08 05:08:56 -080019#include <numeric>
peah21920892017-02-08 05:08:56 -080020#include <string>
21#include <vector>
22
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "modules/audio_processing/aec3/aec3_common.h"
Jonas Olsson366a50c2018-09-06 13:41:30 +020024#include "rtc_base/strings/string_builder.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "test/gtest.h"
peah21920892017-02-08 05:08:56 -080026
27namespace webrtc {
28
29namespace {
30
31std::string ProduceDebugText(int sample_rate_hz) {
Jonas Olsson366a50c2018-09-06 13:41:30 +020032 rtc::StringBuilder ss;
peah21920892017-02-08 05:08:56 -080033 ss << "Sample rate: " << sample_rate_hz;
Jonas Olsson84df1c72018-09-14 16:59:32 +020034 return ss.Release();
peah21920892017-02-08 05:08:56 -080035}
36
Per Åhgren38e2d952017-11-17 14:54:28 +010037constexpr size_t kDownSamplingFactors[] = {2, 4, 8};
peah21920892017-02-08 05:08:56 -080038constexpr float kPi = 3.141592f;
39constexpr size_t kNumStartupBlocks = 50;
40constexpr size_t kNumBlocks = 1000;
41
42void ProduceDecimatedSinusoidalOutputPower(int sample_rate_hz,
Per Åhgren38e2d952017-11-17 14:54:28 +010043 size_t down_sampling_factor,
peah21920892017-02-08 05:08:56 -080044 float sinusoidal_frequency_hz,
45 float* input_power,
46 float* output_power) {
47 float input[kBlockSize * kNumBlocks];
Per Åhgren38e2d952017-11-17 14:54:28 +010048 const size_t sub_block_size = kBlockSize / down_sampling_factor;
peah21920892017-02-08 05:08:56 -080049
50 // Produce a sinusoid of the specified frequency.
51 for (size_t k = 0; k < kBlockSize * kNumBlocks; ++k) {
Mirko Bonadeidbce0902019-03-15 07:39:02 +010052 input[k] = 32767.f * std::sin(2.f * kPi * sinusoidal_frequency_hz * k /
53 sample_rate_hz);
peah21920892017-02-08 05:08:56 -080054 }
55
Per Åhgren38e2d952017-11-17 14:54:28 +010056 Decimator decimator(down_sampling_factor);
57 std::vector<float> output(sub_block_size * kNumBlocks);
peah21920892017-02-08 05:08:56 -080058
59 for (size_t k = 0; k < kNumBlocks; ++k) {
Per Åhgren38e2d952017-11-17 14:54:28 +010060 std::vector<float> sub_block(sub_block_size);
Gustaf Ullbergee84d392019-09-10 09:36:43 +020061 std::vector<std::vector<float>> input_multichannel(
62 1, std::vector<float>(kBlockSize));
63 memcpy(input_multichannel[0].data(), &input[k * kBlockSize],
64 kBlockSize * sizeof(float));
65 decimator.Decimate(input_multichannel, true, sub_block);
peah21920892017-02-08 05:08:56 -080066
67 std::copy(sub_block.begin(), sub_block.end(),
Per Åhgren38e2d952017-11-17 14:54:28 +010068 output.begin() + k * sub_block_size);
peah21920892017-02-08 05:08:56 -080069 }
70
71 ASSERT_GT(kNumBlocks, kNumStartupBlocks);
72 rtc::ArrayView<const float> input_to_evaluate(
73 &input[kNumStartupBlocks * kBlockSize],
74 (kNumBlocks - kNumStartupBlocks) * kBlockSize);
75 rtc::ArrayView<const float> output_to_evaluate(
Per Åhgren38e2d952017-11-17 14:54:28 +010076 &output[kNumStartupBlocks * sub_block_size],
77 (kNumBlocks - kNumStartupBlocks) * sub_block_size);
peah21920892017-02-08 05:08:56 -080078 *input_power =
79 std::inner_product(input_to_evaluate.begin(), input_to_evaluate.end(),
80 input_to_evaluate.begin(), 0.f) /
81 input_to_evaluate.size();
82 *output_power =
83 std::inner_product(output_to_evaluate.begin(), output_to_evaluate.end(),
84 output_to_evaluate.begin(), 0.f) /
85 output_to_evaluate.size();
86}
87
88} // namespace
89
90// Verifies that there is little aliasing from upper frequencies in the
91// downsampling.
Per Åhgren38e2d952017-11-17 14:54:28 +010092TEST(Decimator, NoLeakageFromUpperFrequencies) {
peah21920892017-02-08 05:08:56 -080093 float input_power;
94 float output_power;
Per Åhgrence202a02019-09-02 17:01:19 +020095 for (auto rate : {16000, 32000, 48000}) {
Per Åhgren38e2d952017-11-17 14:54:28 +010096 for (auto down_sampling_factor : kDownSamplingFactors) {
97 ProduceDebugText(rate);
98 ProduceDecimatedSinusoidalOutputPower(rate, down_sampling_factor,
99 3.f / 8.f * rate, &input_power,
100 &output_power);
101 EXPECT_GT(0.0001f * input_power, output_power);
102 }
peah21920892017-02-08 05:08:56 -0800103 }
104}
105
peah21920892017-02-08 05:08:56 -0800106#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
107// Verifies the check for the input size.
Per Åhgren38e2d952017-11-17 14:54:28 +0100108TEST(Decimator, WrongInputSize) {
109 Decimator decimator(4);
Gustaf Ullbergee84d392019-09-10 09:36:43 +0200110 std::vector<std::vector<float>> x(1, std::vector<float>(kBlockSize - 1, 0.f));
Per Åhgren38e2d952017-11-17 14:54:28 +0100111 std::array<float, kBlockSize / 4> x_downsampled;
Gustaf Ullbergee84d392019-09-10 09:36:43 +0200112 EXPECT_DEATH(decimator.Decimate(x, true, x_downsampled), "");
peah21920892017-02-08 05:08:56 -0800113}
114
115// Verifies the check for non-null output parameter.
Per Åhgren38e2d952017-11-17 14:54:28 +0100116TEST(Decimator, NullOutput) {
117 Decimator decimator(4);
Gustaf Ullbergee84d392019-09-10 09:36:43 +0200118 std::vector<std::vector<float>> x(1, std::vector<float>(kBlockSize, 0.f));
119 EXPECT_DEATH(decimator.Decimate(x, true, nullptr), "");
peah21920892017-02-08 05:08:56 -0800120}
121
Per Åhgren38e2d952017-11-17 14:54:28 +0100122// Verifies the check for the output size.
123TEST(Decimator, WrongOutputSize) {
124 Decimator decimator(4);
Gustaf Ullbergee84d392019-09-10 09:36:43 +0200125 std::vector<std::vector<float>> x(1, std::vector<float>(kBlockSize, 0.f));
Per Åhgren38e2d952017-11-17 14:54:28 +0100126 std::array<float, kBlockSize / 4 - 1> x_downsampled;
Gustaf Ullbergee84d392019-09-10 09:36:43 +0200127 EXPECT_DEATH(decimator.Decimate(x, true, x_downsampled), "");
Per Åhgren38e2d952017-11-17 14:54:28 +0100128}
129
130// Verifies the check for the correct downsampling factor.
131TEST(Decimator, CorrectDownSamplingFactor) {
132 EXPECT_DEATH(Decimator(3), "");
133}
134
peah21920892017-02-08 05:08:56 -0800135#endif
136
137} // namespace webrtc