blob: d67967bc02a5f28fc09313c4d37310bce4abb45d [file] [log] [blame]
peahd0263542017-01-03 04:20:34 -08001/*
2 * Copyright (c) 2016 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/block_framer.h"
peahd0263542017-01-03 04:20:34 -080012
peahd0263542017-01-03 04:20:34 -080013#include <string>
14#include <vector>
15
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "modules/audio_processing/aec3/aec3_common.h"
Jonas Olsson366a50c2018-09-06 13:41:30 +020017#include "rtc_base/strings/string_builder.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "test/gtest.h"
peahd0263542017-01-03 04:20:34 -080019
20namespace webrtc {
21namespace {
22
Per Åhgrence202a02019-09-02 17:01:19 +020023void SetupSubFrameView(
24 std::vector<std::vector<std::vector<float>>>* sub_frame,
25 std::vector<std::vector<rtc::ArrayView<float>>>* sub_frame_view) {
26 for (size_t band = 0; band < sub_frame_view->size(); ++band) {
27 for (size_t channel = 0; channel < (*sub_frame_view)[band].size();
28 ++channel) {
29 (*sub_frame_view)[band][channel] =
30 rtc::ArrayView<float>((*sub_frame)[band][channel].data(),
31 (*sub_frame)[band][channel].size());
32 }
peahd0263542017-01-03 04:20:34 -080033 }
34}
35
36float ComputeSampleValue(size_t chunk_counter,
37 size_t chunk_size,
38 size_t band,
Per Åhgrence202a02019-09-02 17:01:19 +020039 size_t channel,
peahd0263542017-01-03 04:20:34 -080040 size_t sample_index,
41 int offset) {
Per Åhgrence202a02019-09-02 17:01:19 +020042 float value = static_cast<int>(100 + chunk_counter * chunk_size +
43 sample_index + channel) +
44 offset;
45 return 5000 * band + value;
peahd0263542017-01-03 04:20:34 -080046}
47
Per Åhgrence202a02019-09-02 17:01:19 +020048bool VerifySubFrame(
49 size_t sub_frame_counter,
50 int offset,
51 const std::vector<std::vector<rtc::ArrayView<float>>>& sub_frame_view) {
52 for (size_t band = 0; band < sub_frame_view.size(); ++band) {
53 for (size_t channel = 0; channel < sub_frame_view[band].size(); ++channel) {
54 for (size_t sample = 0; sample < sub_frame_view[band][channel].size();
55 ++sample) {
56 const float reference_value = ComputeSampleValue(
57 sub_frame_counter, kSubFrameLength, band, channel, sample, offset);
58 if (reference_value != sub_frame_view[band][channel][sample]) {
59 return false;
60 }
peahd0263542017-01-03 04:20:34 -080061 }
62 }
63 }
64 return true;
65}
66
Per Åhgrence202a02019-09-02 17:01:19 +020067void FillBlock(size_t block_counter,
68 std::vector<std::vector<std::vector<float>>>* block) {
69 for (size_t band = 0; band < block->size(); ++band) {
70 for (size_t channel = 0; channel < (*block)[band].size(); ++channel) {
71 for (size_t sample = 0; sample < (*block)[band][channel].size();
72 ++sample) {
73 (*block)[band][channel][sample] = ComputeSampleValue(
74 block_counter, kBlockSize, band, channel, sample, 0);
75 }
peahd0263542017-01-03 04:20:34 -080076 }
77 }
78}
79
80// Verifies that the BlockFramer is able to produce the expected frame content.
Per Åhgrence202a02019-09-02 17:01:19 +020081void RunFramerTest(int sample_rate_hz, size_t num_channels) {
82 constexpr size_t kNumSubFramesToProcess = 10;
peahd0263542017-01-03 04:20:34 -080083 const size_t num_bands = NumBandsForRate(sample_rate_hz);
84
Per Åhgrence202a02019-09-02 17:01:19 +020085 std::vector<std::vector<std::vector<float>>> block(
86 num_bands, std::vector<std::vector<float>>(
87 num_channels, std::vector<float>(kBlockSize, 0.f)));
88 std::vector<std::vector<std::vector<float>>> output_sub_frame(
89 num_bands, std::vector<std::vector<float>>(
90 num_channels, std::vector<float>(kSubFrameLength, 0.f)));
91 std::vector<std::vector<rtc::ArrayView<float>>> output_sub_frame_view(
92 num_bands, std::vector<rtc::ArrayView<float>>(num_channels));
peahd0263542017-01-03 04:20:34 -080093 SetupSubFrameView(&output_sub_frame, &output_sub_frame_view);
Per Åhgrence202a02019-09-02 17:01:19 +020094 BlockFramer framer(num_bands, num_channels);
peahd0263542017-01-03 04:20:34 -080095
96 size_t block_index = 0;
97 for (size_t sub_frame_index = 0; sub_frame_index < kNumSubFramesToProcess;
98 ++sub_frame_index) {
99 FillBlock(block_index++, &block);
100 framer.InsertBlockAndExtractSubFrame(block, &output_sub_frame_view);
Per Åhgrence202a02019-09-02 17:01:19 +0200101 if (sub_frame_index > 1) {
102 EXPECT_TRUE(VerifySubFrame(sub_frame_index, -64, output_sub_frame_view));
103 }
peahd0263542017-01-03 04:20:34 -0800104
105 if ((sub_frame_index + 1) % 4 == 0) {
106 FillBlock(block_index++, &block);
107 framer.InsertBlock(block);
108 }
109 }
110}
111
112#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
113// Verifies that the BlockFramer crashes if the InsertBlockAndExtractSubFrame
114// method is called for inputs with the wrong number of bands or band lengths.
Per Åhgrence202a02019-09-02 17:01:19 +0200115void RunWronglySizedInsertAndExtractParametersTest(
116 int sample_rate_hz,
117 size_t correct_num_channels,
118 size_t num_block_bands,
119 size_t num_block_channels,
120 size_t block_length,
121 size_t num_sub_frame_bands,
122 size_t num_sub_frame_channels,
123 size_t sub_frame_length) {
peahd0263542017-01-03 04:20:34 -0800124 const size_t correct_num_bands = NumBandsForRate(sample_rate_hz);
125
Per Åhgrence202a02019-09-02 17:01:19 +0200126 std::vector<std::vector<std::vector<float>>> block(
127 num_block_bands,
128 std::vector<std::vector<float>>(num_block_channels,
129 std::vector<float>(block_length, 0.f)));
130 std::vector<std::vector<std::vector<float>>> output_sub_frame(
131 num_sub_frame_bands,
132 std::vector<std::vector<float>>(
133 num_sub_frame_channels, std::vector<float>(sub_frame_length, 0.f)));
134 std::vector<std::vector<rtc::ArrayView<float>>> output_sub_frame_view(
135 output_sub_frame.size(),
136 std::vector<rtc::ArrayView<float>>(num_sub_frame_channels));
peahd0263542017-01-03 04:20:34 -0800137 SetupSubFrameView(&output_sub_frame, &output_sub_frame_view);
Per Åhgrence202a02019-09-02 17:01:19 +0200138 BlockFramer framer(correct_num_bands, correct_num_channels);
peahd0263542017-01-03 04:20:34 -0800139 EXPECT_DEATH(
140 framer.InsertBlockAndExtractSubFrame(block, &output_sub_frame_view), "");
141}
142
143// Verifies that the BlockFramer crashes if the InsertBlock method is called for
144// inputs with the wrong number of bands or band lengths.
145void RunWronglySizedInsertParameterTest(int sample_rate_hz,
Per Åhgrence202a02019-09-02 17:01:19 +0200146 size_t correct_num_channels,
peahd0263542017-01-03 04:20:34 -0800147 size_t num_block_bands,
Per Åhgrence202a02019-09-02 17:01:19 +0200148 size_t num_block_channels,
peahd0263542017-01-03 04:20:34 -0800149 size_t block_length) {
150 const size_t correct_num_bands = NumBandsForRate(sample_rate_hz);
151
Per Åhgrence202a02019-09-02 17:01:19 +0200152 std::vector<std::vector<std::vector<float>>> correct_block(
153 correct_num_bands,
154 std::vector<std::vector<float>>(correct_num_channels,
155 std::vector<float>(kBlockSize, 0.f)));
156 std::vector<std::vector<std::vector<float>>> wrong_block(
157 num_block_bands,
158 std::vector<std::vector<float>>(num_block_channels,
159 std::vector<float>(block_length, 0.f)));
160 std::vector<std::vector<std::vector<float>>> output_sub_frame(
161 correct_num_bands,
162 std::vector<std::vector<float>>(
163 correct_num_channels, std::vector<float>(kSubFrameLength, 0.f)));
164 std::vector<std::vector<rtc::ArrayView<float>>> output_sub_frame_view(
165 output_sub_frame.size(),
166 std::vector<rtc::ArrayView<float>>(correct_num_channels));
peahd0263542017-01-03 04:20:34 -0800167 SetupSubFrameView(&output_sub_frame, &output_sub_frame_view);
Per Åhgrence202a02019-09-02 17:01:19 +0200168 BlockFramer framer(correct_num_bands, correct_num_channels);
peahd0263542017-01-03 04:20:34 -0800169 framer.InsertBlockAndExtractSubFrame(correct_block, &output_sub_frame_view);
170 framer.InsertBlockAndExtractSubFrame(correct_block, &output_sub_frame_view);
171 framer.InsertBlockAndExtractSubFrame(correct_block, &output_sub_frame_view);
172 framer.InsertBlockAndExtractSubFrame(correct_block, &output_sub_frame_view);
173
174 EXPECT_DEATH(framer.InsertBlock(wrong_block), "");
175}
176
177// Verifies that the BlockFramer crashes if the InsertBlock method is called
178// after a wrong number of previous InsertBlockAndExtractSubFrame method calls
179// have been made.
Per Åhgrence202a02019-09-02 17:01:19 +0200180
peahd0263542017-01-03 04:20:34 -0800181void RunWronglyInsertOrderTest(int sample_rate_hz,
Per Åhgrence202a02019-09-02 17:01:19 +0200182 size_t num_channels,
peahd0263542017-01-03 04:20:34 -0800183 size_t num_preceeding_api_calls) {
184 const size_t correct_num_bands = NumBandsForRate(sample_rate_hz);
185
Per Åhgrence202a02019-09-02 17:01:19 +0200186 std::vector<std::vector<std::vector<float>>> block(
187 correct_num_bands,
188 std::vector<std::vector<float>>(num_channels,
189 std::vector<float>(kBlockSize, 0.f)));
190 std::vector<std::vector<std::vector<float>>> output_sub_frame(
191 correct_num_bands,
192 std::vector<std::vector<float>>(
193 num_channels, std::vector<float>(kSubFrameLength, 0.f)));
194 std::vector<std::vector<rtc::ArrayView<float>>> output_sub_frame_view(
195 output_sub_frame.size(),
196 std::vector<rtc::ArrayView<float>>(num_channels));
peahd0263542017-01-03 04:20:34 -0800197 SetupSubFrameView(&output_sub_frame, &output_sub_frame_view);
Per Åhgrence202a02019-09-02 17:01:19 +0200198 BlockFramer framer(correct_num_bands, num_channels);
peahd0263542017-01-03 04:20:34 -0800199 for (size_t k = 0; k < num_preceeding_api_calls; ++k) {
200 framer.InsertBlockAndExtractSubFrame(block, &output_sub_frame_view);
201 }
202
203 EXPECT_DEATH(framer.InsertBlock(block), "");
204}
205#endif
206
Per Åhgrence202a02019-09-02 17:01:19 +0200207std::string ProduceDebugText(int sample_rate_hz, size_t num_channels) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200208 rtc::StringBuilder ss;
peahd0263542017-01-03 04:20:34 -0800209 ss << "Sample rate: " << sample_rate_hz;
Per Åhgrence202a02019-09-02 17:01:19 +0200210 ss << ", number of channels: " << num_channels;
Jonas Olsson84df1c72018-09-14 16:59:32 +0200211 return ss.Release();
peahd0263542017-01-03 04:20:34 -0800212}
213
214} // namespace
215
216#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
Tommi909f3a52020-05-18 16:47:56 +0200217TEST(BlockFramerDeathTest,
218 WrongNumberOfBandsInBlockForInsertBlockAndExtractSubFrame) {
Per Åhgrence202a02019-09-02 17:01:19 +0200219 for (auto rate : {16000, 32000, 48000}) {
220 for (auto correct_num_channels : {1, 2, 8}) {
221 SCOPED_TRACE(ProduceDebugText(rate, correct_num_channels));
222 const size_t correct_num_bands = NumBandsForRate(rate);
223 const size_t wrong_num_bands = (correct_num_bands % 3) + 1;
224 RunWronglySizedInsertAndExtractParametersTest(
225 rate, correct_num_channels, wrong_num_bands, correct_num_channels,
226 kBlockSize, correct_num_bands, correct_num_channels, kSubFrameLength);
227 }
228 }
229}
230
Tommi909f3a52020-05-18 16:47:56 +0200231TEST(BlockFramerDeathTest,
Per Åhgrence202a02019-09-02 17:01:19 +0200232 WrongNumberOfChannelsInBlockForInsertBlockAndExtractSubFrame) {
233 for (auto rate : {16000, 32000, 48000}) {
234 for (auto correct_num_channels : {1, 2, 8}) {
235 SCOPED_TRACE(ProduceDebugText(rate, correct_num_channels));
236 const size_t correct_num_bands = NumBandsForRate(rate);
237 const size_t wrong_num_channels = correct_num_channels + 1;
238 RunWronglySizedInsertAndExtractParametersTest(
239 rate, correct_num_channels, correct_num_bands, wrong_num_channels,
240 kBlockSize, correct_num_bands, correct_num_channels, kSubFrameLength);
241 }
peahd0263542017-01-03 04:20:34 -0800242 }
243}
244
Tommi909f3a52020-05-18 16:47:56 +0200245TEST(BlockFramerDeathTest,
peahd0263542017-01-03 04:20:34 -0800246 WrongNumberOfBandsInSubFrameForInsertBlockAndExtractSubFrame) {
Per Åhgrence202a02019-09-02 17:01:19 +0200247 for (auto rate : {16000, 32000, 48000}) {
248 for (auto correct_num_channels : {1, 2, 8}) {
249 SCOPED_TRACE(ProduceDebugText(rate, correct_num_channels));
250 const size_t correct_num_bands = NumBandsForRate(rate);
251 const size_t wrong_num_bands = (correct_num_bands % 3) + 1;
252 RunWronglySizedInsertAndExtractParametersTest(
253 rate, correct_num_channels, correct_num_bands, correct_num_channels,
254 kBlockSize, wrong_num_bands, correct_num_channels, kSubFrameLength);
255 }
256 }
257}
258
Tommi909f3a52020-05-18 16:47:56 +0200259TEST(BlockFramerDeathTest,
Per Åhgrence202a02019-09-02 17:01:19 +0200260 WrongNumberOfChannelsInSubFrameForInsertBlockAndExtractSubFrame) {
261 for (auto rate : {16000, 32000, 48000}) {
262 for (auto correct_num_channels : {1, 2, 8}) {
263 SCOPED_TRACE(ProduceDebugText(rate, correct_num_channels));
264 const size_t correct_num_bands = NumBandsForRate(rate);
265 const size_t wrong_num_channels = correct_num_channels + 1;
266 RunWronglySizedInsertAndExtractParametersTest(
267 rate, correct_num_channels, correct_num_bands, correct_num_channels,
268 kBlockSize, correct_num_bands, wrong_num_channels, kSubFrameLength);
269 }
peahd0263542017-01-03 04:20:34 -0800270 }
271}
272
Tommi909f3a52020-05-18 16:47:56 +0200273TEST(BlockFramerDeathTest,
274 WrongNumberOfSamplesInBlockForInsertBlockAndExtractSubFrame) {
Per Åhgrence202a02019-09-02 17:01:19 +0200275 for (auto rate : {16000, 32000, 48000}) {
276 for (auto correct_num_channels : {1, 2, 8}) {
277 SCOPED_TRACE(ProduceDebugText(rate, correct_num_channels));
278 const size_t correct_num_bands = NumBandsForRate(rate);
279 RunWronglySizedInsertAndExtractParametersTest(
280 rate, correct_num_channels, correct_num_bands, correct_num_channels,
281 kBlockSize - 1, correct_num_bands, correct_num_channels,
282 kSubFrameLength);
283 }
peahd0263542017-01-03 04:20:34 -0800284 }
285}
286
Tommi909f3a52020-05-18 16:47:56 +0200287TEST(BlockFramerDeathTest,
peahd0263542017-01-03 04:20:34 -0800288 WrongNumberOfSamplesInSubFrameForInsertBlockAndExtractSubFrame) {
Per Åhgrence202a02019-09-02 17:01:19 +0200289 const size_t correct_num_channels = 1;
290 for (auto rate : {16000, 32000, 48000}) {
291 SCOPED_TRACE(ProduceDebugText(rate, correct_num_channels));
peahd0263542017-01-03 04:20:34 -0800292 const size_t correct_num_bands = NumBandsForRate(rate);
Per Åhgrence202a02019-09-02 17:01:19 +0200293 RunWronglySizedInsertAndExtractParametersTest(
294 rate, correct_num_channels, correct_num_bands, correct_num_channels,
295 kBlockSize, correct_num_bands, correct_num_channels,
296 kSubFrameLength - 1);
peahd0263542017-01-03 04:20:34 -0800297 }
298}
299
Tommi909f3a52020-05-18 16:47:56 +0200300TEST(BlockFramerDeathTest, WrongNumberOfBandsInBlockForInsertBlock) {
Per Åhgrence202a02019-09-02 17:01:19 +0200301 for (auto rate : {16000, 32000, 48000}) {
302 for (auto correct_num_channels : {1, 2, 8}) {
303 SCOPED_TRACE(ProduceDebugText(rate, correct_num_channels));
304 const size_t correct_num_bands = NumBandsForRate(rate);
305 const size_t wrong_num_bands = (correct_num_bands % 3) + 1;
306 RunWronglySizedInsertParameterTest(rate, correct_num_channels,
307 wrong_num_bands, correct_num_channels,
308 kBlockSize);
Per Åhgrena66395e2019-08-30 08:54:09 +0200309 }
310 }
311}
312
Tommi909f3a52020-05-18 16:47:56 +0200313TEST(BlockFramerDeathTest, WrongNumberOfChannelsInBlockForInsertBlock) {
Per Åhgrence202a02019-09-02 17:01:19 +0200314 for (auto rate : {16000, 32000, 48000}) {
315 for (auto correct_num_channels : {1, 2, 8}) {
316 SCOPED_TRACE(ProduceDebugText(rate, correct_num_channels));
317 const size_t correct_num_bands = NumBandsForRate(rate);
318 const size_t wrong_num_channels = correct_num_channels + 1;
319 RunWronglySizedInsertParameterTest(rate, correct_num_channels,
320 correct_num_bands, wrong_num_channels,
321 kBlockSize);
322 }
323 }
324}
325
Tommi909f3a52020-05-18 16:47:56 +0200326TEST(BlockFramerDeathTest, WrongNumberOfSamplesInBlockForInsertBlock) {
Per Åhgrence202a02019-09-02 17:01:19 +0200327 for (auto rate : {16000, 32000, 48000}) {
328 for (auto correct_num_channels : {1, 2, 8}) {
329 SCOPED_TRACE(ProduceDebugText(rate, correct_num_channels));
330 const size_t correct_num_bands = NumBandsForRate(rate);
331 RunWronglySizedInsertParameterTest(rate, correct_num_channels,
332 correct_num_bands,
333 correct_num_channels, kBlockSize - 1);
334 }
335 }
336}
337
Tommi909f3a52020-05-18 16:47:56 +0200338TEST(BlockFramerDeathTest, WrongNumberOfPreceedingApiCallsForInsertBlock) {
Per Åhgrence202a02019-09-02 17:01:19 +0200339 for (size_t num_channels : {1, 2, 8}) {
340 for (auto rate : {16000, 32000, 48000}) {
341 for (size_t num_calls = 0; num_calls < 4; ++num_calls) {
342 rtc::StringBuilder ss;
343 ss << "Sample rate: " << rate;
344 ss << ", Num channels: " << num_channels;
345 ss << ", Num preceeding InsertBlockAndExtractSubFrame calls: "
346 << num_calls;
347
348 SCOPED_TRACE(ss.str());
349 RunWronglyInsertOrderTest(rate, num_channels, num_calls);
350 }
351 }
352 }
353}
354
355// Verifies that the verification for 0 number of channels works.
Tommi909f3a52020-05-18 16:47:56 +0200356TEST(BlockFramerDeathTest, ZeroNumberOfChannelsParameter) {
Per Åhgrence202a02019-09-02 17:01:19 +0200357 EXPECT_DEATH(BlockFramer(16000, 0), "");
358}
359
360// Verifies that the verification for 0 number of bands works.
Tommi909f3a52020-05-18 16:47:56 +0200361TEST(BlockFramerDeathTest, ZeroNumberOfBandsParameter) {
Per Åhgrence202a02019-09-02 17:01:19 +0200362 EXPECT_DEATH(BlockFramer(0, 1), "");
363}
364
365// Verifies that the verification for null sub_frame pointer works.
Tommi909f3a52020-05-18 16:47:56 +0200366TEST(BlockFramerDeathTest, NullSubFrameParameter) {
Per Åhgrence202a02019-09-02 17:01:19 +0200367 EXPECT_DEATH(BlockFramer(1, 1).InsertBlockAndExtractSubFrame(
368 std::vector<std::vector<std::vector<float>>>(
369 1, std::vector<std::vector<float>>(
370 1, std::vector<float>(kBlockSize, 0.f))),
peahd0263542017-01-03 04:20:34 -0800371 nullptr),
372 "");
373}
374
375#endif
376
377TEST(BlockFramer, FrameBitexactness) {
Per Åhgrence202a02019-09-02 17:01:19 +0200378 for (auto rate : {16000, 32000, 48000}) {
379 for (auto num_channels : {1, 2, 4, 8}) {
380 SCOPED_TRACE(ProduceDebugText(rate, num_channels));
381 RunFramerTest(rate, num_channels);
382 }
peahd0263542017-01-03 04:20:34 -0800383 }
384}
385
386} // namespace webrtc