blob: 87fe7a8fbbebaa28c486b3909a63655a1b8d304f [file] [log] [blame]
peah522d71b2017-02-23 05:16:26 -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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_processing/aec3/aec3_fft.h"
peah522d71b2017-02-23 05:16:26 -080012
13#include <algorithm>
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "test/gmock.h"
16#include "test/gtest.h"
peah522d71b2017-02-23 05:16:26 -080017
18namespace webrtc {
19
20#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
21
22// Verifies that the check for non-null input in Fft works.
23TEST(Aec3Fft, NullFftInput) {
24 Aec3Fft fft;
25 FftData X;
26 EXPECT_DEATH(fft.Fft(nullptr, &X), "");
27}
28
29// Verifies that the check for non-null input in Fft works.
30TEST(Aec3Fft, NullFftOutput) {
31 Aec3Fft fft;
32 std::array<float, kFftLength> x;
33 EXPECT_DEATH(fft.Fft(&x, nullptr), "");
34}
35
36// Verifies that the check for non-null output in Ifft works.
37TEST(Aec3Fft, NullIfftOutput) {
38 Aec3Fft fft;
39 FftData X;
40 EXPECT_DEATH(fft.Ifft(X, nullptr), "");
41}
42
43// Verifies that the check for non-null output in ZeroPaddedFft works.
44TEST(Aec3Fft, NullZeroPaddedFftOutput) {
45 Aec3Fft fft;
46 std::array<float, kFftLengthBy2> x;
Per Åhgrend20639f2018-01-11 10:29:49 +010047 EXPECT_DEATH(fft.ZeroPaddedFft(x, Aec3Fft::Window::kRectangular, nullptr),
48 "");
peah522d71b2017-02-23 05:16:26 -080049}
50
51// Verifies that the check for input length in ZeroPaddedFft works.
52TEST(Aec3Fft, ZeroPaddedFftWrongInputLength) {
53 Aec3Fft fft;
54 FftData X;
55 std::array<float, kFftLengthBy2 - 1> x;
Per Åhgrend20639f2018-01-11 10:29:49 +010056 EXPECT_DEATH(fft.ZeroPaddedFft(x, Aec3Fft::Window::kRectangular, &X), "");
peah522d71b2017-02-23 05:16:26 -080057}
58
59// Verifies that the check for non-null output in PaddedFft works.
60TEST(Aec3Fft, NullPaddedFftOutput) {
61 Aec3Fft fft;
62 std::array<float, kFftLengthBy2> x;
63 std::array<float, kFftLengthBy2> x_old;
64 EXPECT_DEATH(fft.PaddedFft(x, x_old, nullptr), "");
65}
66
67// Verifies that the check for input length in PaddedFft works.
68TEST(Aec3Fft, PaddedFftWrongInputLength) {
69 Aec3Fft fft;
70 FftData X;
71 std::array<float, kFftLengthBy2 - 1> x;
72 std::array<float, kFftLengthBy2> x_old;
73 EXPECT_DEATH(fft.PaddedFft(x, x_old, &X), "");
74}
75
76// Verifies that the check for length in the old value in PaddedFft works.
77TEST(Aec3Fft, PaddedFftWrongOldValuesLength) {
78 Aec3Fft fft;
79 FftData X;
80 std::array<float, kFftLengthBy2> x;
81 std::array<float, kFftLengthBy2 - 1> x_old;
82 EXPECT_DEATH(fft.PaddedFft(x, x_old, &X), "");
83}
84
85#endif
86
87// Verifies that Fft works as intended.
88TEST(Aec3Fft, Fft) {
89 Aec3Fft fft;
90 FftData X;
91 std::array<float, kFftLength> x;
92 x.fill(0.f);
93 fft.Fft(&x, &X);
94 EXPECT_THAT(X.re, ::testing::Each(0.f));
95 EXPECT_THAT(X.im, ::testing::Each(0.f));
96
97 x.fill(0.f);
98 x[0] = 1.f;
99 fft.Fft(&x, &X);
100 EXPECT_THAT(X.re, ::testing::Each(1.f));
101 EXPECT_THAT(X.im, ::testing::Each(0.f));
102
103 x.fill(1.f);
104 fft.Fft(&x, &X);
105 EXPECT_EQ(128.f, X.re[0]);
106 std::for_each(X.re.begin() + 1, X.re.end(),
107 [](float a) { EXPECT_EQ(0.f, a); });
108 EXPECT_THAT(X.im, ::testing::Each(0.f));
109}
110
111// Verifies that InverseFft works as intended.
112TEST(Aec3Fft, Ifft) {
113 Aec3Fft fft;
114 FftData X;
115 std::array<float, kFftLength> x;
116
117 X.re.fill(0.f);
118 X.im.fill(0.f);
119 fft.Ifft(X, &x);
120 EXPECT_THAT(x, ::testing::Each(0.f));
121
122 X.re.fill(1.f);
123 X.im.fill(0.f);
124 fft.Ifft(X, &x);
125 EXPECT_EQ(64.f, x[0]);
126 std::for_each(x.begin() + 1, x.end(), [](float a) { EXPECT_EQ(0.f, a); });
127
128 X.re.fill(0.f);
129 X.re[0] = 128;
130 X.im.fill(0.f);
131 fft.Ifft(X, &x);
132 EXPECT_THAT(x, ::testing::Each(64.f));
133}
134
135// Verifies that InverseFft and Fft work as intended.
136TEST(Aec3Fft, FftAndIfft) {
137 Aec3Fft fft;
138 FftData X;
139 std::array<float, kFftLength> x;
140 std::array<float, kFftLength> x_ref;
141
142 int v = 0;
143 for (int k = 0; k < 20; ++k) {
144 for (size_t j = 0; j < x.size(); ++j) {
145 x[j] = v++;
146 x_ref[j] = x[j] * 64.f;
147 }
148 fft.Fft(&x, &X);
149 fft.Ifft(X, &x);
150 for (size_t j = 0; j < x.size(); ++j) {
151 EXPECT_NEAR(x_ref[j], x[j], 0.001f);
152 }
153 }
154}
155
156// Verifies that ZeroPaddedFft work as intended.
157TEST(Aec3Fft, ZeroPaddedFft) {
158 Aec3Fft fft;
159 FftData X;
160 std::array<float, kFftLengthBy2> x_in;
161 std::array<float, kFftLength> x_ref;
162 std::array<float, kFftLength> x_out;
163
164 int v = 0;
165 x_ref.fill(0.f);
166 for (int k = 0; k < 20; ++k) {
167 for (size_t j = 0; j < x_in.size(); ++j) {
168 x_in[j] = v++;
169 x_ref[j + kFftLengthBy2] = x_in[j] * 64.f;
170 }
Per Åhgrend20639f2018-01-11 10:29:49 +0100171 fft.ZeroPaddedFft(x_in, Aec3Fft::Window::kRectangular, &X);
peah522d71b2017-02-23 05:16:26 -0800172 fft.Ifft(X, &x_out);
173 for (size_t j = 0; j < x_out.size(); ++j) {
174 EXPECT_NEAR(x_ref[j], x_out[j], 0.1f);
175 }
176 }
177}
178
179// Verifies that ZeroPaddedFft work as intended.
180TEST(Aec3Fft, PaddedFft) {
181 Aec3Fft fft;
182 FftData X;
183 std::array<float, kFftLengthBy2> x_in;
184 std::array<float, kFftLength> x_out;
185 std::array<float, kFftLengthBy2> x_old;
186 std::array<float, kFftLengthBy2> x_old_ref;
187 std::array<float, kFftLength> x_ref;
188
189 int v = 0;
190 x_old.fill(0.f);
191 for (int k = 0; k < 20; ++k) {
192 for (size_t j = 0; j < x_in.size(); ++j) {
193 x_in[j] = v++;
194 }
195
196 std::copy(x_old.begin(), x_old.end(), x_ref.begin());
197 std::copy(x_in.begin(), x_in.end(), x_ref.begin() + kFftLengthBy2);
198 std::copy(x_in.begin(), x_in.end(), x_old_ref.begin());
199 std::for_each(x_ref.begin(), x_ref.end(), [](float& a) { a *= 64.f; });
200
201 fft.PaddedFft(x_in, x_old, &X);
202 fft.Ifft(X, &x_out);
203
204 for (size_t j = 0; j < x_out.size(); ++j) {
205 EXPECT_NEAR(x_ref[j], x_out[j], 0.1f);
206 }
207
208 EXPECT_EQ(x_old_ref, x_old);
209 }
210}
211
212} // namespace webrtc