1 /*
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
11 #include "modules/audio_processing/aec3/block_framer.h"
12
13 #include <string>
14 #include <vector>
15
16 #include "modules/audio_processing/aec3/aec3_common.h"
17 #include "rtc_base/strings/string_builder.h"
18 #include "test/gtest.h"
19
20 namespace webrtc {
21 namespace {
22
SetupSubFrameView(std::vector<std::vector<std::vector<float>>> * sub_frame,std::vector<std::vector<rtc::ArrayView<float>>> * sub_frame_view)23 void 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 }
33 }
34 }
35
ComputeSampleValue(size_t chunk_counter,size_t chunk_size,size_t band,size_t channel,size_t sample_index,int offset)36 float ComputeSampleValue(size_t chunk_counter,
37 size_t chunk_size,
38 size_t band,
39 size_t channel,
40 size_t sample_index,
41 int offset) {
42 float value = static_cast<int>(100 + chunk_counter * chunk_size +
43 sample_index + channel) +
44 offset;
45 return 5000 * band + value;
46 }
47
VerifySubFrame(size_t sub_frame_counter,int offset,const std::vector<std::vector<rtc::ArrayView<float>>> & sub_frame_view)48 bool 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 }
61 }
62 }
63 }
64 return true;
65 }
66
FillBlock(size_t block_counter,Block * block)67 void FillBlock(size_t block_counter, Block* block) {
68 for (int band = 0; band < block->NumBands(); ++band) {
69 for (int channel = 0; channel < block->NumChannels(); ++channel) {
70 auto b = block->View(band, channel);
71 for (size_t sample = 0; sample < kBlockSize; ++sample) {
72 b[sample] = ComputeSampleValue(block_counter, kBlockSize, band, channel,
73 sample, 0);
74 }
75 }
76 }
77 }
78
79 // Verifies that the BlockFramer is able to produce the expected frame content.
RunFramerTest(int sample_rate_hz,size_t num_channels)80 void RunFramerTest(int sample_rate_hz, size_t num_channels) {
81 constexpr size_t kNumSubFramesToProcess = 10;
82 const size_t num_bands = NumBandsForRate(sample_rate_hz);
83
84 Block block(num_bands, num_channels);
85 std::vector<std::vector<std::vector<float>>> output_sub_frame(
86 num_bands, std::vector<std::vector<float>>(
87 num_channels, std::vector<float>(kSubFrameLength, 0.f)));
88 std::vector<std::vector<rtc::ArrayView<float>>> output_sub_frame_view(
89 num_bands, std::vector<rtc::ArrayView<float>>(num_channels));
90 SetupSubFrameView(&output_sub_frame, &output_sub_frame_view);
91 BlockFramer framer(num_bands, num_channels);
92
93 size_t block_index = 0;
94 for (size_t sub_frame_index = 0; sub_frame_index < kNumSubFramesToProcess;
95 ++sub_frame_index) {
96 FillBlock(block_index++, &block);
97 framer.InsertBlockAndExtractSubFrame(block, &output_sub_frame_view);
98 if (sub_frame_index > 1) {
99 EXPECT_TRUE(VerifySubFrame(sub_frame_index, -64, output_sub_frame_view));
100 }
101
102 if ((sub_frame_index + 1) % 4 == 0) {
103 FillBlock(block_index++, &block);
104 framer.InsertBlock(block);
105 }
106 }
107 }
108
109 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
110 // Verifies that the BlockFramer crashes if the InsertBlockAndExtractSubFrame
111 // method is called for inputs with the wrong number of bands or band lengths.
RunWronglySizedInsertAndExtractParametersTest(int sample_rate_hz,size_t correct_num_channels,size_t num_block_bands,size_t num_block_channels,size_t num_sub_frame_bands,size_t num_sub_frame_channels,size_t sub_frame_length)112 void RunWronglySizedInsertAndExtractParametersTest(
113 int sample_rate_hz,
114 size_t correct_num_channels,
115 size_t num_block_bands,
116 size_t num_block_channels,
117 size_t num_sub_frame_bands,
118 size_t num_sub_frame_channels,
119 size_t sub_frame_length) {
120 const size_t correct_num_bands = NumBandsForRate(sample_rate_hz);
121
122 Block block(num_block_bands, num_block_channels);
123 std::vector<std::vector<std::vector<float>>> output_sub_frame(
124 num_sub_frame_bands,
125 std::vector<std::vector<float>>(
126 num_sub_frame_channels, std::vector<float>(sub_frame_length, 0.f)));
127 std::vector<std::vector<rtc::ArrayView<float>>> output_sub_frame_view(
128 output_sub_frame.size(),
129 std::vector<rtc::ArrayView<float>>(num_sub_frame_channels));
130 SetupSubFrameView(&output_sub_frame, &output_sub_frame_view);
131 BlockFramer framer(correct_num_bands, correct_num_channels);
132 EXPECT_DEATH(
133 framer.InsertBlockAndExtractSubFrame(block, &output_sub_frame_view), "");
134 }
135
136 // Verifies that the BlockFramer crashes if the InsertBlock method is called for
137 // inputs with the wrong number of bands or band lengths.
RunWronglySizedInsertParameterTest(int sample_rate_hz,size_t correct_num_channels,size_t num_block_bands,size_t num_block_channels)138 void RunWronglySizedInsertParameterTest(int sample_rate_hz,
139 size_t correct_num_channels,
140 size_t num_block_bands,
141 size_t num_block_channels) {
142 const size_t correct_num_bands = NumBandsForRate(sample_rate_hz);
143
144 Block correct_block(correct_num_bands, correct_num_channels);
145 Block wrong_block(num_block_bands, num_block_channels);
146 std::vector<std::vector<std::vector<float>>> output_sub_frame(
147 correct_num_bands,
148 std::vector<std::vector<float>>(
149 correct_num_channels, std::vector<float>(kSubFrameLength, 0.f)));
150 std::vector<std::vector<rtc::ArrayView<float>>> output_sub_frame_view(
151 output_sub_frame.size(),
152 std::vector<rtc::ArrayView<float>>(correct_num_channels));
153 SetupSubFrameView(&output_sub_frame, &output_sub_frame_view);
154 BlockFramer framer(correct_num_bands, correct_num_channels);
155 framer.InsertBlockAndExtractSubFrame(correct_block, &output_sub_frame_view);
156 framer.InsertBlockAndExtractSubFrame(correct_block, &output_sub_frame_view);
157 framer.InsertBlockAndExtractSubFrame(correct_block, &output_sub_frame_view);
158 framer.InsertBlockAndExtractSubFrame(correct_block, &output_sub_frame_view);
159
160 EXPECT_DEATH(framer.InsertBlock(wrong_block), "");
161 }
162
163 // Verifies that the BlockFramer crashes if the InsertBlock method is called
164 // after a wrong number of previous InsertBlockAndExtractSubFrame method calls
165 // have been made.
166
RunWronglyInsertOrderTest(int sample_rate_hz,size_t num_channels,size_t num_preceeding_api_calls)167 void RunWronglyInsertOrderTest(int sample_rate_hz,
168 size_t num_channels,
169 size_t num_preceeding_api_calls) {
170 const size_t correct_num_bands = NumBandsForRate(sample_rate_hz);
171
172 Block block(correct_num_bands, num_channels);
173 std::vector<std::vector<std::vector<float>>> output_sub_frame(
174 correct_num_bands,
175 std::vector<std::vector<float>>(
176 num_channels, std::vector<float>(kSubFrameLength, 0.f)));
177 std::vector<std::vector<rtc::ArrayView<float>>> output_sub_frame_view(
178 output_sub_frame.size(),
179 std::vector<rtc::ArrayView<float>>(num_channels));
180 SetupSubFrameView(&output_sub_frame, &output_sub_frame_view);
181 BlockFramer framer(correct_num_bands, num_channels);
182 for (size_t k = 0; k < num_preceeding_api_calls; ++k) {
183 framer.InsertBlockAndExtractSubFrame(block, &output_sub_frame_view);
184 }
185
186 EXPECT_DEATH(framer.InsertBlock(block), "");
187 }
188 #endif
189
ProduceDebugText(int sample_rate_hz,size_t num_channels)190 std::string ProduceDebugText(int sample_rate_hz, size_t num_channels) {
191 rtc::StringBuilder ss;
192 ss << "Sample rate: " << sample_rate_hz;
193 ss << ", number of channels: " << num_channels;
194 return ss.Release();
195 }
196
197 } // namespace
198
199 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
TEST(BlockFramerDeathTest,WrongNumberOfBandsInBlockForInsertBlockAndExtractSubFrame)200 TEST(BlockFramerDeathTest,
201 WrongNumberOfBandsInBlockForInsertBlockAndExtractSubFrame) {
202 for (auto rate : {16000, 32000, 48000}) {
203 for (auto correct_num_channels : {1, 2, 8}) {
204 SCOPED_TRACE(ProduceDebugText(rate, correct_num_channels));
205 const size_t correct_num_bands = NumBandsForRate(rate);
206 const size_t wrong_num_bands = (correct_num_bands % 3) + 1;
207 RunWronglySizedInsertAndExtractParametersTest(
208 rate, correct_num_channels, wrong_num_bands, correct_num_channels,
209 correct_num_bands, correct_num_channels, kSubFrameLength);
210 }
211 }
212 }
213
TEST(BlockFramerDeathTest,WrongNumberOfChannelsInBlockForInsertBlockAndExtractSubFrame)214 TEST(BlockFramerDeathTest,
215 WrongNumberOfChannelsInBlockForInsertBlockAndExtractSubFrame) {
216 for (auto rate : {16000, 32000, 48000}) {
217 for (auto correct_num_channels : {1, 2, 8}) {
218 SCOPED_TRACE(ProduceDebugText(rate, correct_num_channels));
219 const size_t correct_num_bands = NumBandsForRate(rate);
220 const size_t wrong_num_channels = correct_num_channels + 1;
221 RunWronglySizedInsertAndExtractParametersTest(
222 rate, correct_num_channels, correct_num_bands, wrong_num_channels,
223 correct_num_bands, correct_num_channels, kSubFrameLength);
224 }
225 }
226 }
227
TEST(BlockFramerDeathTest,WrongNumberOfBandsInSubFrameForInsertBlockAndExtractSubFrame)228 TEST(BlockFramerDeathTest,
229 WrongNumberOfBandsInSubFrameForInsertBlockAndExtractSubFrame) {
230 for (auto rate : {16000, 32000, 48000}) {
231 for (auto correct_num_channels : {1, 2, 8}) {
232 SCOPED_TRACE(ProduceDebugText(rate, correct_num_channels));
233 const size_t correct_num_bands = NumBandsForRate(rate);
234 const size_t wrong_num_bands = (correct_num_bands % 3) + 1;
235 RunWronglySizedInsertAndExtractParametersTest(
236 rate, correct_num_channels, correct_num_bands, correct_num_channels,
237 wrong_num_bands, correct_num_channels, kSubFrameLength);
238 }
239 }
240 }
241
TEST(BlockFramerDeathTest,WrongNumberOfChannelsInSubFrameForInsertBlockAndExtractSubFrame)242 TEST(BlockFramerDeathTest,
243 WrongNumberOfChannelsInSubFrameForInsertBlockAndExtractSubFrame) {
244 for (auto rate : {16000, 32000, 48000}) {
245 for (auto correct_num_channels : {1, 2, 8}) {
246 SCOPED_TRACE(ProduceDebugText(rate, correct_num_channels));
247 const size_t correct_num_bands = NumBandsForRate(rate);
248 const size_t wrong_num_channels = correct_num_channels + 1;
249 RunWronglySizedInsertAndExtractParametersTest(
250 rate, correct_num_channels, correct_num_bands, correct_num_channels,
251 correct_num_bands, wrong_num_channels, kSubFrameLength);
252 }
253 }
254 }
255
TEST(BlockFramerDeathTest,WrongNumberOfSamplesInSubFrameForInsertBlockAndExtractSubFrame)256 TEST(BlockFramerDeathTest,
257 WrongNumberOfSamplesInSubFrameForInsertBlockAndExtractSubFrame) {
258 const size_t correct_num_channels = 1;
259 for (auto rate : {16000, 32000, 48000}) {
260 SCOPED_TRACE(ProduceDebugText(rate, correct_num_channels));
261 const size_t correct_num_bands = NumBandsForRate(rate);
262 RunWronglySizedInsertAndExtractParametersTest(
263 rate, correct_num_channels, correct_num_bands, correct_num_channels,
264 correct_num_bands, correct_num_channels, kSubFrameLength - 1);
265 }
266 }
267
TEST(BlockFramerDeathTest,WrongNumberOfBandsInBlockForInsertBlock)268 TEST(BlockFramerDeathTest, WrongNumberOfBandsInBlockForInsertBlock) {
269 for (auto rate : {16000, 32000, 48000}) {
270 for (auto correct_num_channels : {1, 2, 8}) {
271 SCOPED_TRACE(ProduceDebugText(rate, correct_num_channels));
272 const size_t correct_num_bands = NumBandsForRate(rate);
273 const size_t wrong_num_bands = (correct_num_bands % 3) + 1;
274 RunWronglySizedInsertParameterTest(rate, correct_num_channels,
275 wrong_num_bands, correct_num_channels);
276 }
277 }
278 }
279
TEST(BlockFramerDeathTest,WrongNumberOfChannelsInBlockForInsertBlock)280 TEST(BlockFramerDeathTest, WrongNumberOfChannelsInBlockForInsertBlock) {
281 for (auto rate : {16000, 32000, 48000}) {
282 for (auto correct_num_channels : {1, 2, 8}) {
283 SCOPED_TRACE(ProduceDebugText(rate, correct_num_channels));
284 const size_t correct_num_bands = NumBandsForRate(rate);
285 const size_t wrong_num_channels = correct_num_channels + 1;
286 RunWronglySizedInsertParameterTest(rate, correct_num_channels,
287 correct_num_bands, wrong_num_channels);
288 }
289 }
290 }
291
TEST(BlockFramerDeathTest,WrongNumberOfPreceedingApiCallsForInsertBlock)292 TEST(BlockFramerDeathTest, WrongNumberOfPreceedingApiCallsForInsertBlock) {
293 for (size_t num_channels : {1, 2, 8}) {
294 for (auto rate : {16000, 32000, 48000}) {
295 for (size_t num_calls = 0; num_calls < 4; ++num_calls) {
296 rtc::StringBuilder ss;
297 ss << "Sample rate: " << rate;
298 ss << ", Num channels: " << num_channels;
299 ss << ", Num preceeding InsertBlockAndExtractSubFrame calls: "
300 << num_calls;
301
302 SCOPED_TRACE(ss.str());
303 RunWronglyInsertOrderTest(rate, num_channels, num_calls);
304 }
305 }
306 }
307 }
308
309 // Verifies that the verification for 0 number of channels works.
TEST(BlockFramerDeathTest,ZeroNumberOfChannelsParameter)310 TEST(BlockFramerDeathTest, ZeroNumberOfChannelsParameter) {
311 EXPECT_DEATH(BlockFramer(16000, 0), "");
312 }
313
314 // Verifies that the verification for 0 number of bands works.
TEST(BlockFramerDeathTest,ZeroNumberOfBandsParameter)315 TEST(BlockFramerDeathTest, ZeroNumberOfBandsParameter) {
316 EXPECT_DEATH(BlockFramer(0, 1), "");
317 }
318
319 // Verifies that the verification for null sub_frame pointer works.
TEST(BlockFramerDeathTest,NullSubFrameParameter)320 TEST(BlockFramerDeathTest, NullSubFrameParameter) {
321 EXPECT_DEATH(
322 BlockFramer(1, 1).InsertBlockAndExtractSubFrame(Block(1, 1), nullptr),
323 "");
324 }
325
326 #endif
327
TEST(BlockFramer,FrameBitexactness)328 TEST(BlockFramer, FrameBitexactness) {
329 for (auto rate : {16000, 32000, 48000}) {
330 for (auto num_channels : {1, 2, 4, 8}) {
331 SCOPED_TRACE(ProduceDebugText(rate, num_channels));
332 RunFramerTest(rate, num_channels);
333 }
334 }
335 }
336
337 } // namespace webrtc
338