blob: 5c5880b5eb2901d9549b46350722158fa3231f50 [file] [log] [blame]
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +00001/*
2 * Copyright (c) 2014 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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "common_audio/fir_filter.h"
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +000012
13#include <string.h>
14
kwibergc2b785d2016-02-24 05:22:32 -080015#include <memory>
16
Jonas Olssona4d87372019-07-05 19:08:33 +020017#include "common_audio/fir_filter_factory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "test/gtest.h"
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +000019
20namespace webrtc {
Alejandro Luebsa9c0ae22015-04-14 15:51:28 -070021namespace {
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +000022
23static const float kCoefficients[] = {0.2f, 0.3f, 0.5f, 0.7f, 0.11f};
Yves Gerey665174f2018-06-19 15:03:05 +020024static const size_t kCoefficientsLength =
25 sizeof(kCoefficients) / sizeof(kCoefficients[0]);
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +000026
Yves Gerey665174f2018-06-19 15:03:05 +020027static const float kInput[] = {1.f, 2.f, 3.f, 4.f, 5.f,
28 6.f, 7.f, 8.f, 9.f, 10.f};
29static const size_t kInputLength = sizeof(kInput) / sizeof(kInput[0]);
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +000030
31void VerifyOutput(const float* expected_output,
32 const float* output,
33 size_t length) {
Yves Gerey665174f2018-06-19 15:03:05 +020034 EXPECT_EQ(
35 0, memcmp(expected_output, output, length * sizeof(expected_output[0])));
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +000036}
37
Alejandro Luebsa9c0ae22015-04-14 15:51:28 -070038} // namespace
39
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +000040TEST(FIRFilterTest, FilterAsIdentity) {
41 const float kCoefficients[] = {1.f, 0.f, 0.f, 0.f, 0.f};
42 float output[kInputLength];
kwibergc2b785d2016-02-24 05:22:32 -080043 std::unique_ptr<FIRFilter> filter(
Patrik Höglundf715c532017-11-17 11:04:15 +010044 CreateFirFilter(kCoefficients, kCoefficientsLength, kInputLength));
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +000045 filter->Filter(kInput, kInputLength, output);
46
47 VerifyOutput(kInput, output, kInputLength);
48}
49
50TEST(FIRFilterTest, FilterUsedAsScalarMultiplication) {
51 const float kCoefficients[] = {5.f, 0.f, 0.f, 0.f, 0.f};
52 float output[kInputLength];
kwibergc2b785d2016-02-24 05:22:32 -080053 std::unique_ptr<FIRFilter> filter(
Patrik Höglundf715c532017-11-17 11:04:15 +010054 CreateFirFilter(kCoefficients, kCoefficientsLength, kInputLength));
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +000055 filter->Filter(kInput, kInputLength, output);
56
57 EXPECT_FLOAT_EQ(5.f, output[0]);
58 EXPECT_FLOAT_EQ(20.f, output[3]);
59 EXPECT_FLOAT_EQ(25.f, output[4]);
60 EXPECT_FLOAT_EQ(50.f, output[kInputLength - 1]);
61}
62
63TEST(FIRFilterTest, FilterUsedAsInputShifting) {
64 const float kCoefficients[] = {0.f, 0.f, 0.f, 0.f, 1.f};
65 float output[kInputLength];
kwibergc2b785d2016-02-24 05:22:32 -080066 std::unique_ptr<FIRFilter> filter(
Patrik Höglundf715c532017-11-17 11:04:15 +010067 CreateFirFilter(kCoefficients, kCoefficientsLength, kInputLength));
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +000068 filter->Filter(kInput, kInputLength, output);
69
70 EXPECT_FLOAT_EQ(0.f, output[0]);
71 EXPECT_FLOAT_EQ(0.f, output[3]);
72 EXPECT_FLOAT_EQ(1.f, output[4]);
73 EXPECT_FLOAT_EQ(2.f, output[5]);
74 EXPECT_FLOAT_EQ(6.f, output[kInputLength - 1]);
75}
76
77TEST(FIRFilterTest, FilterUsedAsArbitraryWeighting) {
78 float output[kInputLength];
kwibergc2b785d2016-02-24 05:22:32 -080079 std::unique_ptr<FIRFilter> filter(
Patrik Höglundf715c532017-11-17 11:04:15 +010080 CreateFirFilter(kCoefficients, kCoefficientsLength, kInputLength));
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +000081 filter->Filter(kInput, kInputLength, output);
82
83 EXPECT_FLOAT_EQ(0.2f, output[0]);
84 EXPECT_FLOAT_EQ(3.4f, output[3]);
85 EXPECT_FLOAT_EQ(5.21f, output[4]);
86 EXPECT_FLOAT_EQ(7.02f, output[5]);
87 EXPECT_FLOAT_EQ(14.26f, output[kInputLength - 1]);
88}
89
90TEST(FIRFilterTest, FilterInLengthLesserOrEqualToCoefficientsLength) {
91 float output[kInputLength];
kwibergc2b785d2016-02-24 05:22:32 -080092 std::unique_ptr<FIRFilter> filter(
Patrik Höglundf715c532017-11-17 11:04:15 +010093 CreateFirFilter(kCoefficients, kCoefficientsLength, 2));
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +000094 filter->Filter(kInput, 2, output);
95
96 EXPECT_FLOAT_EQ(0.2f, output[0]);
97 EXPECT_FLOAT_EQ(0.7f, output[1]);
Yves Gerey665174f2018-06-19 15:03:05 +020098 filter.reset(
99 CreateFirFilter(kCoefficients, kCoefficientsLength, kCoefficientsLength));
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +0000100 filter->Filter(kInput, kCoefficientsLength, output);
101
102 EXPECT_FLOAT_EQ(0.2f, output[0]);
103 EXPECT_FLOAT_EQ(3.4f, output[3]);
104 EXPECT_FLOAT_EQ(5.21f, output[4]);
105}
106
107TEST(FIRFilterTest, MultipleFilterCalls) {
108 float output[kInputLength];
kwibergc2b785d2016-02-24 05:22:32 -0800109 std::unique_ptr<FIRFilter> filter(
Patrik Höglundf715c532017-11-17 11:04:15 +0100110 CreateFirFilter(kCoefficients, kCoefficientsLength, 3));
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +0000111 filter->Filter(kInput, 2, output);
112 EXPECT_FLOAT_EQ(0.2f, output[0]);
113 EXPECT_FLOAT_EQ(0.7f, output[1]);
114
115 filter->Filter(kInput, 2, output);
116 EXPECT_FLOAT_EQ(1.3f, output[0]);
117 EXPECT_FLOAT_EQ(2.4f, output[1]);
118
119 filter->Filter(kInput, 2, output);
120 EXPECT_FLOAT_EQ(2.81f, output[0]);
121 EXPECT_FLOAT_EQ(2.62f, output[1]);
122
123 filter->Filter(kInput, 2, output);
124 EXPECT_FLOAT_EQ(2.81f, output[0]);
125 EXPECT_FLOAT_EQ(2.62f, output[1]);
126
127 filter->Filter(&kInput[3], 3, output);
128 EXPECT_FLOAT_EQ(3.41f, output[0]);
129 EXPECT_FLOAT_EQ(4.12f, output[1]);
130 EXPECT_FLOAT_EQ(6.21f, output[2]);
131
132 filter->Filter(&kInput[3], 3, output);
133 EXPECT_FLOAT_EQ(8.12f, output[0]);
134 EXPECT_FLOAT_EQ(9.14f, output[1]);
135 EXPECT_FLOAT_EQ(9.45f, output[2]);
136}
137
138TEST(FIRFilterTest, VerifySampleBasedVsBlockBasedFiltering) {
139 float output_block_based[kInputLength];
kwibergc2b785d2016-02-24 05:22:32 -0800140 std::unique_ptr<FIRFilter> filter(
Patrik Höglundf715c532017-11-17 11:04:15 +0100141 CreateFirFilter(kCoefficients, kCoefficientsLength, kInputLength));
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +0000142 filter->Filter(kInput, kInputLength, output_block_based);
143
144 float output_sample_based[kInputLength];
Patrik Höglundf715c532017-11-17 11:04:15 +0100145 filter.reset(CreateFirFilter(kCoefficients, kCoefficientsLength, 1));
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +0000146 for (size_t i = 0; i < kInputLength; ++i) {
147 filter->Filter(&kInput[i], 1, &output_sample_based[i]);
148 }
149
Yves Gerey665174f2018-06-19 15:03:05 +0200150 EXPECT_EQ(0, memcmp(output_sample_based, output_block_based, kInputLength));
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +0000151}
152
153TEST(FIRFilterTest, SimplestHighPassFilter) {
154 const float kCoefficients[] = {1.f, -1.f};
Yves Gerey665174f2018-06-19 15:03:05 +0200155 const size_t kCoefficientsLength =
156 sizeof(kCoefficients) / sizeof(kCoefficients[0]);
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +0000157
158 float kConstantInput[] = {1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f};
Yves Gerey665174f2018-06-19 15:03:05 +0200159 const size_t kConstantInputLength =
160 sizeof(kConstantInput) / sizeof(kConstantInput[0]);
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +0000161
162 float output[kConstantInputLength];
Patrik Höglundf715c532017-11-17 11:04:15 +0100163 std::unique_ptr<FIRFilter> filter(CreateFirFilter(
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +0000164 kCoefficients, kCoefficientsLength, kConstantInputLength));
165 filter->Filter(kConstantInput, kConstantInputLength, output);
166 EXPECT_FLOAT_EQ(1.f, output[0]);
167 for (size_t i = kCoefficientsLength - 1; i < kConstantInputLength; ++i) {
168 EXPECT_FLOAT_EQ(0.f, output[i]);
169 }
170}
171
172TEST(FIRFilterTest, SimplestLowPassFilter) {
173 const float kCoefficients[] = {1.f, 1.f};
Yves Gerey665174f2018-06-19 15:03:05 +0200174 const size_t kCoefficientsLength =
175 sizeof(kCoefficients) / sizeof(kCoefficients[0]);
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +0000176
177 float kHighFrequencyInput[] = {-1.f, 1.f, -1.f, 1.f, -1.f, 1.f, -1.f, 1.f};
Yves Gerey665174f2018-06-19 15:03:05 +0200178 const size_t kHighFrequencyInputLength =
179 sizeof(kHighFrequencyInput) / sizeof(kHighFrequencyInput[0]);
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +0000180
181 float output[kHighFrequencyInputLength];
Patrik Höglundf715c532017-11-17 11:04:15 +0100182 std::unique_ptr<FIRFilter> filter(CreateFirFilter(
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +0000183 kCoefficients, kCoefficientsLength, kHighFrequencyInputLength));
184 filter->Filter(kHighFrequencyInput, kHighFrequencyInputLength, output);
185 EXPECT_FLOAT_EQ(-1.f, output[0]);
186 for (size_t i = kCoefficientsLength - 1; i < kHighFrequencyInputLength; ++i) {
187 EXPECT_FLOAT_EQ(0.f, output[i]);
188 }
189}
190
191TEST(FIRFilterTest, SameOutputWhenSwapedCoefficientsAndInput) {
192 float output[kCoefficientsLength];
193 float output_swaped[kCoefficientsLength];
Yves Gerey665174f2018-06-19 15:03:05 +0200194 std::unique_ptr<FIRFilter> filter(
195 CreateFirFilter(kCoefficients, kCoefficientsLength, kCoefficientsLength));
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +0000196 // Use kCoefficientsLength for in_length to get same-length outputs.
197 filter->Filter(kInput, kCoefficientsLength, output);
198
Yves Gerey665174f2018-06-19 15:03:05 +0200199 filter.reset(
200 CreateFirFilter(kInput, kCoefficientsLength, kCoefficientsLength));
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +0000201 filter->Filter(kCoefficients, kCoefficientsLength, output_swaped);
202
Yves Gerey665174f2018-06-19 15:03:05 +0200203 for (size_t i = 0; i < kCoefficientsLength; ++i) {
aluebs@webrtc.org37ca7652014-03-24 10:16:11 +0000204 EXPECT_FLOAT_EQ(output[i], output_swaped[i]);
205 }
206}
207
208} // namespace webrtc