blob: 296efab15b8d94c5088f5ca26c4d556a609e11ec [file] [log] [blame]
andrew@webrtc.org325cff02014-10-01 17:42:181/*
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
kwibergc2b785d2016-02-24 13:22:3211#include <memory>
12
Mirko Bonadei92ea95e2017-09-15 04:47:3113#include "common_audio/blocker.h"
andrew@webrtc.org325cff02014-10-01 17:42:1814
Mirko Bonadei92ea95e2017-09-15 04:47:3115#include "rtc_base/arraysize.h"
16#include "test/gtest.h"
andrew@webrtc.org325cff02014-10-01 17:42:1817
18namespace {
19
20// Callback Function to add 3 to every sample in the signal.
aluebs@webrtc.orgc0da63c2015-01-13 22:28:3521class PlusThreeBlockerCallback : public webrtc::BlockerCallback {
andrew@webrtc.org325cff02014-10-01 17:42:1822 public:
kjellander@webrtc.org14665ff2015-03-04 12:58:3523 void ProcessBlock(const float* const* input,
Peter Kastingdce40cf2015-08-24 21:52:2324 size_t num_frames,
Peter Kasting69558702016-01-13 00:26:3525 size_t num_input_channels,
26 size_t num_output_channels,
kjellander@webrtc.org14665ff2015-03-04 12:58:3527 float* const* output) override {
Peter Kasting69558702016-01-13 00:26:3528 for (size_t i = 0; i < num_output_channels; ++i) {
Peter Kastingdce40cf2015-08-24 21:52:2329 for (size_t j = 0; j < num_frames; ++j) {
andrew@webrtc.org325cff02014-10-01 17:42:1830 output[i][j] = input[i][j] + 3;
31 }
32 }
33 }
34};
35
aluebs@webrtc.orgc0da63c2015-01-13 22:28:3536// No-op Callback Function.
37class CopyBlockerCallback : public webrtc::BlockerCallback {
38 public:
kjellander@webrtc.org14665ff2015-03-04 12:58:3539 void ProcessBlock(const float* const* input,
Peter Kastingdce40cf2015-08-24 21:52:2340 size_t num_frames,
Peter Kasting69558702016-01-13 00:26:3541 size_t num_input_channels,
42 size_t num_output_channels,
kjellander@webrtc.org14665ff2015-03-04 12:58:3543 float* const* output) override {
Peter Kasting69558702016-01-13 00:26:3544 for (size_t i = 0; i < num_output_channels; ++i) {
Peter Kastingdce40cf2015-08-24 21:52:2345 for (size_t j = 0; j < num_frames; ++j) {
aluebs@webrtc.orgc0da63c2015-01-13 22:28:3546 output[i][j] = input[i][j];
47 }
48 }
49 }
50};
51
andrew@webrtc.org325cff02014-10-01 17:42:1852} // namespace
53
54namespace webrtc {
55
56// Tests blocking with a window that multiplies the signal by 2, a callback
57// that adds 3 to each sample in the signal, and different combinations of chunk
58// size, block size, and shift amount.
59class BlockerTest : public ::testing::Test {
60 protected:
61 void RunTest(Blocker* blocker,
pkasting25702cb2016-01-08 21:50:2762 size_t chunk_size,
63 size_t num_frames,
andrew@webrtc.org325cff02014-10-01 17:42:1864 const float* const* input,
65 float* const* input_chunk,
66 float* const* output,
67 float* const* output_chunk,
Peter Kasting69558702016-01-13 00:26:3568 size_t num_input_channels,
69 size_t num_output_channels) {
pkasting25702cb2016-01-08 21:50:2770 size_t start = 0;
71 size_t end = chunk_size - 1;
andrew@webrtc.org325cff02014-10-01 17:42:1872 while (end < num_frames) {
73 CopyTo(input_chunk, 0, start, num_input_channels, chunk_size, input);
74 blocker->ProcessChunk(input_chunk,
75 chunk_size,
76 num_input_channels,
77 num_output_channels,
78 output_chunk);
79 CopyTo(output, start, 0, num_output_channels, chunk_size, output_chunk);
80
pkasting25702cb2016-01-08 21:50:2781 start += chunk_size;
82 end += chunk_size;
andrew@webrtc.org325cff02014-10-01 17:42:1883 }
84 }
85
86 void ValidateSignalEquality(const float* const* expected,
87 const float* const* actual,
Peter Kasting69558702016-01-13 00:26:3588 size_t num_channels,
pkasting25702cb2016-01-08 21:50:2789 size_t num_frames) {
Peter Kasting69558702016-01-13 00:26:3590 for (size_t i = 0; i < num_channels; ++i) {
pkasting25702cb2016-01-08 21:50:2791 for (size_t j = 0; j < num_frames; ++j) {
andrew@webrtc.org325cff02014-10-01 17:42:1892 EXPECT_FLOAT_EQ(expected[i][j], actual[i][j]);
93 }
94 }
95 }
96
aluebs@webrtc.orgc0da63c2015-01-13 22:28:3597 void ValidateInitialDelay(const float* const* output,
Peter Kasting69558702016-01-13 00:26:3598 size_t num_channels,
pkasting25702cb2016-01-08 21:50:2799 size_t num_frames,
100 size_t initial_delay) {
Peter Kasting69558702016-01-13 00:26:35101 for (size_t i = 0; i < num_channels; ++i) {
pkasting25702cb2016-01-08 21:50:27102 for (size_t j = 0; j < num_frames; ++j) {
aluebs@webrtc.orgc0da63c2015-01-13 22:28:35103 if (j < initial_delay) {
104 EXPECT_FLOAT_EQ(output[i][j], 0.f);
105 } else {
106 EXPECT_GT(output[i][j], 0.f);
107 }
108 }
109 }
110 }
111
andrew@webrtc.org325cff02014-10-01 17:42:18112 static void CopyTo(float* const* dst,
pkasting25702cb2016-01-08 21:50:27113 size_t start_index_dst,
114 size_t start_index_src,
Peter Kasting69558702016-01-13 00:26:35115 size_t num_channels,
pkasting25702cb2016-01-08 21:50:27116 size_t num_frames,
andrew@webrtc.org325cff02014-10-01 17:42:18117 const float* const* src) {
Peter Kasting69558702016-01-13 00:26:35118 for (size_t i = 0; i < num_channels; ++i) {
andrew@webrtc.org325cff02014-10-01 17:42:18119 memcpy(&dst[i][start_index_dst],
120 &src[i][start_index_src],
121 num_frames * sizeof(float));
122 }
123 }
124};
125
126TEST_F(BlockerTest, TestBlockerMutuallyPrimeChunkandBlockSize) {
Peter Kasting69558702016-01-13 00:26:35127 const size_t kNumInputChannels = 3;
128 const size_t kNumOutputChannels = 2;
pkasting25702cb2016-01-08 21:50:27129 const size_t kNumFrames = 10;
130 const size_t kBlockSize = 4;
131 const size_t kChunkSize = 5;
132 const size_t kShiftAmount = 2;
andrew@webrtc.org325cff02014-10-01 17:42:18133
134 const float kInput[kNumInputChannels][kNumFrames] = {
135 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
136 {2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
137 {3, 3, 3, 3, 3, 3, 3, 3, 3, 3}};
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15138 ChannelBuffer<float> input_cb(kNumFrames, kNumInputChannels);
139 input_cb.SetDataForTesting(kInput[0], sizeof(kInput) / sizeof(**kInput));
andrew@webrtc.org325cff02014-10-01 17:42:18140
141 const float kExpectedOutput[kNumInputChannels][kNumFrames] = {
aluebs@webrtc.orgc0da63c2015-01-13 22:28:35142 {6, 6, 12, 20, 20, 20, 20, 20, 20, 20},
143 {6, 6, 12, 28, 28, 28, 28, 28, 28, 28}};
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15144 ChannelBuffer<float> expected_output_cb(kNumFrames, kNumInputChannels);
145 expected_output_cb.SetDataForTesting(
146 kExpectedOutput[0], sizeof(kExpectedOutput) / sizeof(**kExpectedOutput));
andrew@webrtc.org325cff02014-10-01 17:42:18147
148 const float kWindow[kBlockSize] = {2.f, 2.f, 2.f, 2.f};
149
150 ChannelBuffer<float> actual_output_cb(kNumFrames, kNumOutputChannels);
151 ChannelBuffer<float> input_chunk_cb(kChunkSize, kNumInputChannels);
152 ChannelBuffer<float> output_chunk_cb(kChunkSize, kNumOutputChannels);
153
aluebs@webrtc.orgc0da63c2015-01-13 22:28:35154 PlusThreeBlockerCallback callback;
andrew@webrtc.org325cff02014-10-01 17:42:18155 Blocker blocker(kChunkSize,
156 kBlockSize,
157 kNumInputChannels,
158 kNumOutputChannels,
159 kWindow,
160 kShiftAmount,
161 &callback);
162
163 RunTest(&blocker,
164 kChunkSize,
165 kNumFrames,
166 input_cb.channels(),
167 input_chunk_cb.channels(),
168 actual_output_cb.channels(),
169 output_chunk_cb.channels(),
170 kNumInputChannels,
171 kNumOutputChannels);
172
173 ValidateSignalEquality(expected_output_cb.channels(),
174 actual_output_cb.channels(),
175 kNumOutputChannels,
176 kNumFrames);
177}
178
179TEST_F(BlockerTest, TestBlockerMutuallyPrimeShiftAndBlockSize) {
Peter Kasting69558702016-01-13 00:26:35180 const size_t kNumInputChannels = 3;
181 const size_t kNumOutputChannels = 2;
pkasting25702cb2016-01-08 21:50:27182 const size_t kNumFrames = 12;
183 const size_t kBlockSize = 4;
184 const size_t kChunkSize = 6;
185 const size_t kShiftAmount = 3;
andrew@webrtc.org325cff02014-10-01 17:42:18186
187 const float kInput[kNumInputChannels][kNumFrames] = {
188 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
189 {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
190 {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}};
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15191 ChannelBuffer<float> input_cb(kNumFrames, kNumInputChannels);
192 input_cb.SetDataForTesting(kInput[0], sizeof(kInput) / sizeof(**kInput));
andrew@webrtc.org325cff02014-10-01 17:42:18193
aluebs@webrtc.orgc0da63c2015-01-13 22:28:35194 const float kExpectedOutput[kNumOutputChannels][kNumFrames] = {
195 {6, 10, 10, 20, 10, 10, 20, 10, 10, 20, 10, 10},
196 {6, 14, 14, 28, 14, 14, 28, 14, 14, 28, 14, 14}};
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15197 ChannelBuffer<float> expected_output_cb(kNumFrames, kNumOutputChannels);
198 expected_output_cb.SetDataForTesting(
199 kExpectedOutput[0], sizeof(kExpectedOutput) / sizeof(**kExpectedOutput));
andrew@webrtc.org325cff02014-10-01 17:42:18200
201 const float kWindow[kBlockSize] = {2.f, 2.f, 2.f, 2.f};
202
203 ChannelBuffer<float> actual_output_cb(kNumFrames, kNumOutputChannels);
204 ChannelBuffer<float> input_chunk_cb(kChunkSize, kNumInputChannels);
205 ChannelBuffer<float> output_chunk_cb(kChunkSize, kNumOutputChannels);
206
aluebs@webrtc.orgc0da63c2015-01-13 22:28:35207 PlusThreeBlockerCallback callback;
andrew@webrtc.org325cff02014-10-01 17:42:18208 Blocker blocker(kChunkSize,
209 kBlockSize,
210 kNumInputChannels,
211 kNumOutputChannels,
212 kWindow,
213 kShiftAmount,
214 &callback);
215
216 RunTest(&blocker,
217 kChunkSize,
218 kNumFrames,
219 input_cb.channels(),
220 input_chunk_cb.channels(),
221 actual_output_cb.channels(),
222 output_chunk_cb.channels(),
223 kNumInputChannels,
224 kNumOutputChannels);
225
226 ValidateSignalEquality(expected_output_cb.channels(),
227 actual_output_cb.channels(),
228 kNumOutputChannels,
229 kNumFrames);
230}
231
232TEST_F(BlockerTest, TestBlockerNoOverlap) {
Peter Kasting69558702016-01-13 00:26:35233 const size_t kNumInputChannels = 3;
234 const size_t kNumOutputChannels = 2;
pkasting25702cb2016-01-08 21:50:27235 const size_t kNumFrames = 12;
236 const size_t kBlockSize = 4;
237 const size_t kChunkSize = 4;
238 const size_t kShiftAmount = 4;
andrew@webrtc.org325cff02014-10-01 17:42:18239
240 const float kInput[kNumInputChannels][kNumFrames] = {
241 {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
242 {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
243 {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}};
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15244 ChannelBuffer<float> input_cb(kNumFrames, kNumInputChannels);
245 input_cb.SetDataForTesting(kInput[0], sizeof(kInput) / sizeof(**kInput));
andrew@webrtc.org325cff02014-10-01 17:42:18246
aluebs@webrtc.orgc0da63c2015-01-13 22:28:35247 const float kExpectedOutput[kNumOutputChannels][kNumFrames] = {
248 {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
249 {14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}};
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15250 ChannelBuffer<float> expected_output_cb(kNumFrames, kNumOutputChannels);
251 expected_output_cb.SetDataForTesting(
252 kExpectedOutput[0], sizeof(kExpectedOutput) / sizeof(**kExpectedOutput));
andrew@webrtc.org325cff02014-10-01 17:42:18253
254 const float kWindow[kBlockSize] = {2.f, 2.f, 2.f, 2.f};
255
256 ChannelBuffer<float> actual_output_cb(kNumFrames, kNumOutputChannels);
257 ChannelBuffer<float> input_chunk_cb(kChunkSize, kNumInputChannels);
258 ChannelBuffer<float> output_chunk_cb(kChunkSize, kNumOutputChannels);
259
aluebs@webrtc.orgc0da63c2015-01-13 22:28:35260 PlusThreeBlockerCallback callback;
andrew@webrtc.org325cff02014-10-01 17:42:18261 Blocker blocker(kChunkSize,
262 kBlockSize,
263 kNumInputChannels,
264 kNumOutputChannels,
265 kWindow,
266 kShiftAmount,
267 &callback);
268
269 RunTest(&blocker,
270 kChunkSize,
271 kNumFrames,
272 input_cb.channels(),
273 input_chunk_cb.channels(),
274 actual_output_cb.channels(),
275 output_chunk_cb.channels(),
276 kNumInputChannels,
277 kNumOutputChannels);
278
279 ValidateSignalEquality(expected_output_cb.channels(),
280 actual_output_cb.channels(),
281 kNumOutputChannels,
282 kNumFrames);
283}
284
aluebs@webrtc.orgc0da63c2015-01-13 22:28:35285TEST_F(BlockerTest, InitialDelaysAreMinimum) {
Peter Kasting69558702016-01-13 00:26:35286 const size_t kNumInputChannels = 3;
287 const size_t kNumOutputChannels = 2;
pkasting25702cb2016-01-08 21:50:27288 const size_t kNumFrames = 1280;
289 const size_t kChunkSize[] =
aluebs@webrtc.orgc0da63c2015-01-13 22:28:35290 {80, 80, 80, 80, 80, 80, 160, 160, 160, 160, 160, 160};
pkasting25702cb2016-01-08 21:50:27291 const size_t kBlockSize[] =
aluebs@webrtc.orgc0da63c2015-01-13 22:28:35292 {64, 64, 64, 128, 128, 128, 128, 128, 128, 256, 256, 256};
pkasting25702cb2016-01-08 21:50:27293 const size_t kShiftAmount[] =
aluebs@webrtc.orgc0da63c2015-01-13 22:28:35294 {16, 32, 64, 32, 64, 128, 32, 64, 128, 64, 128, 256};
pkasting25702cb2016-01-08 21:50:27295 const size_t kInitialDelay[] =
aluebs@webrtc.orgc0da63c2015-01-13 22:28:35296 {48, 48, 48, 112, 112, 112, 96, 96, 96, 224, 224, 224};
297
298 float input[kNumInputChannels][kNumFrames];
Peter Kasting69558702016-01-13 00:26:35299 for (size_t i = 0; i < kNumInputChannels; ++i) {
pkasting25702cb2016-01-08 21:50:27300 for (size_t j = 0; j < kNumFrames; ++j) {
aluebs@webrtc.orgc0da63c2015-01-13 22:28:35301 input[i][j] = i + 1;
302 }
303 }
aluebs@webrtc.orgd35a5c32015-02-10 22:52:15304 ChannelBuffer<float> input_cb(kNumFrames, kNumInputChannels);
305 input_cb.SetDataForTesting(input[0], sizeof(input) / sizeof(**input));
aluebs@webrtc.orgc0da63c2015-01-13 22:28:35306
307 ChannelBuffer<float> output_cb(kNumFrames, kNumOutputChannels);
308
309 CopyBlockerCallback callback;
310
pkasting25702cb2016-01-08 21:50:27311 for (size_t i = 0; i < arraysize(kChunkSize); ++i) {
kwibergc2b785d2016-02-24 13:22:32312 std::unique_ptr<float[]> window(new float[kBlockSize[i]]);
pkasting25702cb2016-01-08 21:50:27313 for (size_t j = 0; j < kBlockSize[i]; ++j) {
aluebs@webrtc.orgc0da63c2015-01-13 22:28:35314 window[j] = 1.f;
315 }
316
317 ChannelBuffer<float> input_chunk_cb(kChunkSize[i], kNumInputChannels);
318 ChannelBuffer<float> output_chunk_cb(kChunkSize[i], kNumOutputChannels);
319
320 Blocker blocker(kChunkSize[i],
321 kBlockSize[i],
322 kNumInputChannels,
323 kNumOutputChannels,
324 window.get(),
325 kShiftAmount[i],
326 &callback);
327
328 RunTest(&blocker,
329 kChunkSize[i],
330 kNumFrames,
331 input_cb.channels(),
332 input_chunk_cb.channels(),
333 output_cb.channels(),
334 output_chunk_cb.channels(),
335 kNumInputChannels,
336 kNumOutputChannels);
337
338 ValidateInitialDelay(output_cb.channels(),
339 kNumOutputChannels,
340 kNumFrames,
341 kInitialDelay[i]);
342 }
343}
344
andrew@webrtc.org325cff02014-10-01 17:42:18345} // namespace webrtc