xref: /aosp_15_r20/external/webrtc/modules/audio_processing/aec3/block_framer_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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