• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,std::vector<std::vector<std::vector<float>>> * block)67 void 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       }
76     }
77   }
78 }
79 
80 // Verifies that the BlockFramer is able to produce the expected frame content.
RunFramerTest(int sample_rate_hz,size_t num_channels)81 void RunFramerTest(int sample_rate_hz, size_t num_channels) {
82   constexpr size_t kNumSubFramesToProcess = 10;
83   const size_t num_bands = NumBandsForRate(sample_rate_hz);
84 
85   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));
93   SetupSubFrameView(&output_sub_frame, &output_sub_frame_view);
94   BlockFramer framer(num_bands, num_channels);
95 
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);
101     if (sub_frame_index > 1) {
102       EXPECT_TRUE(VerifySubFrame(sub_frame_index, -64, output_sub_frame_view));
103     }
104 
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.
RunWronglySizedInsertAndExtractParametersTest(int sample_rate_hz,size_t correct_num_channels,size_t num_block_bands,size_t num_block_channels,size_t block_length,size_t num_sub_frame_bands,size_t num_sub_frame_channels,size_t sub_frame_length)115 void 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) {
124   const size_t correct_num_bands = NumBandsForRate(sample_rate_hz);
125 
126   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));
137   SetupSubFrameView(&output_sub_frame, &output_sub_frame_view);
138   BlockFramer framer(correct_num_bands, correct_num_channels);
139   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.
RunWronglySizedInsertParameterTest(int sample_rate_hz,size_t correct_num_channels,size_t num_block_bands,size_t num_block_channels,size_t block_length)145 void RunWronglySizedInsertParameterTest(int sample_rate_hz,
146                                         size_t correct_num_channels,
147                                         size_t num_block_bands,
148                                         size_t num_block_channels,
149                                         size_t block_length) {
150   const size_t correct_num_bands = NumBandsForRate(sample_rate_hz);
151 
152   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));
167   SetupSubFrameView(&output_sub_frame, &output_sub_frame_view);
168   BlockFramer framer(correct_num_bands, correct_num_channels);
169   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.
180 
RunWronglyInsertOrderTest(int sample_rate_hz,size_t num_channels,size_t num_preceeding_api_calls)181 void RunWronglyInsertOrderTest(int sample_rate_hz,
182                                size_t num_channels,
183                                size_t num_preceeding_api_calls) {
184   const size_t correct_num_bands = NumBandsForRate(sample_rate_hz);
185 
186   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));
197   SetupSubFrameView(&output_sub_frame, &output_sub_frame_view);
198   BlockFramer framer(correct_num_bands, num_channels);
199   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 
ProduceDebugText(int sample_rate_hz,size_t num_channels)207 std::string ProduceDebugText(int sample_rate_hz, size_t num_channels) {
208   rtc::StringBuilder ss;
209   ss << "Sample rate: " << sample_rate_hz;
210   ss << ", number of channels: " << num_channels;
211   return ss.Release();
212 }
213 
214 }  // namespace
215 
216 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
TEST(BlockFramerDeathTest,WrongNumberOfBandsInBlockForInsertBlockAndExtractSubFrame)217 TEST(BlockFramerDeathTest,
218      WrongNumberOfBandsInBlockForInsertBlockAndExtractSubFrame) {
219   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 
TEST(BlockFramerDeathTest,WrongNumberOfChannelsInBlockForInsertBlockAndExtractSubFrame)231 TEST(BlockFramerDeathTest,
232      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     }
242   }
243 }
244 
TEST(BlockFramerDeathTest,WrongNumberOfBandsInSubFrameForInsertBlockAndExtractSubFrame)245 TEST(BlockFramerDeathTest,
246      WrongNumberOfBandsInSubFrameForInsertBlockAndExtractSubFrame) {
247   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 
TEST(BlockFramerDeathTest,WrongNumberOfChannelsInSubFrameForInsertBlockAndExtractSubFrame)259 TEST(BlockFramerDeathTest,
260      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     }
270   }
271 }
272 
TEST(BlockFramerDeathTest,WrongNumberOfSamplesInBlockForInsertBlockAndExtractSubFrame)273 TEST(BlockFramerDeathTest,
274      WrongNumberOfSamplesInBlockForInsertBlockAndExtractSubFrame) {
275   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     }
284   }
285 }
286 
TEST(BlockFramerDeathTest,WrongNumberOfSamplesInSubFrameForInsertBlockAndExtractSubFrame)287 TEST(BlockFramerDeathTest,
288      WrongNumberOfSamplesInSubFrameForInsertBlockAndExtractSubFrame) {
289   const size_t correct_num_channels = 1;
290   for (auto rate : {16000, 32000, 48000}) {
291     SCOPED_TRACE(ProduceDebugText(rate, correct_num_channels));
292     const size_t correct_num_bands = NumBandsForRate(rate);
293     RunWronglySizedInsertAndExtractParametersTest(
294         rate, correct_num_channels, correct_num_bands, correct_num_channels,
295         kBlockSize, correct_num_bands, correct_num_channels,
296         kSubFrameLength - 1);
297   }
298 }
299 
TEST(BlockFramerDeathTest,WrongNumberOfBandsInBlockForInsertBlock)300 TEST(BlockFramerDeathTest, WrongNumberOfBandsInBlockForInsertBlock) {
301   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);
309     }
310   }
311 }
312 
TEST(BlockFramerDeathTest,WrongNumberOfChannelsInBlockForInsertBlock)313 TEST(BlockFramerDeathTest, WrongNumberOfChannelsInBlockForInsertBlock) {
314   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 
TEST(BlockFramerDeathTest,WrongNumberOfSamplesInBlockForInsertBlock)326 TEST(BlockFramerDeathTest, WrongNumberOfSamplesInBlockForInsertBlock) {
327   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 
TEST(BlockFramerDeathTest,WrongNumberOfPreceedingApiCallsForInsertBlock)338 TEST(BlockFramerDeathTest, WrongNumberOfPreceedingApiCallsForInsertBlock) {
339   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.
TEST(BlockFramerDeathTest,ZeroNumberOfChannelsParameter)356 TEST(BlockFramerDeathTest, ZeroNumberOfChannelsParameter) {
357   EXPECT_DEATH(BlockFramer(16000, 0), "");
358 }
359 
360 // Verifies that the verification for 0 number of bands works.
TEST(BlockFramerDeathTest,ZeroNumberOfBandsParameter)361 TEST(BlockFramerDeathTest, ZeroNumberOfBandsParameter) {
362   EXPECT_DEATH(BlockFramer(0, 1), "");
363 }
364 
365 // Verifies that the verification for null sub_frame pointer works.
TEST(BlockFramerDeathTest,NullSubFrameParameter)366 TEST(BlockFramerDeathTest, NullSubFrameParameter) {
367   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))),
371                    nullptr),
372                "");
373 }
374 
375 #endif
376 
TEST(BlockFramer,FrameBitexactness)377 TEST(BlockFramer, FrameBitexactness) {
378   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     }
383   }
384 }
385 
386 }  // namespace webrtc
387