OLD | NEW |
| (Empty) |
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 "webrtc/modules/audio_processing/aec3/block_framer.h" | |
12 | |
13 #include <sstream> | |
14 #include <string> | |
15 #include <vector> | |
16 | |
17 #include "webrtc/modules/audio_processing/aec3/aec3_constants.h" | |
18 #include "webrtc/test/gtest.h" | |
19 | |
20 namespace webrtc { | |
21 namespace { | |
22 | |
23 void SetupSubFrameView(std::vector<std::vector<float>>* sub_frame, | |
24 std::vector<rtc::ArrayView<float>>* sub_frame_view) { | |
25 for (size_t k = 0; k < sub_frame_view->size(); ++k) { | |
26 (*sub_frame_view)[k] = | |
27 rtc::ArrayView<float>((*sub_frame)[k].data(), (*sub_frame)[k].size()); | |
28 } | |
29 } | |
30 | |
31 float ComputeSampleValue(size_t chunk_counter, | |
32 size_t chunk_size, | |
33 size_t band, | |
34 size_t sample_index, | |
35 int offset) { | |
36 float value = | |
37 static_cast<int>(chunk_counter * chunk_size + sample_index) + offset; | |
38 return value > 0 ? 5000 * band + value : 0; | |
39 } | |
40 | |
41 bool VerifySubFrame(size_t sub_frame_counter, | |
42 int offset, | |
43 const std::vector<rtc::ArrayView<float>>& sub_frame_view) { | |
44 for (size_t k = 0; k < sub_frame_view.size(); ++k) { | |
45 for (size_t i = 0; i < sub_frame_view[k].size(); ++i) { | |
46 const float reference_value = | |
47 ComputeSampleValue(sub_frame_counter, kSubFrameLength, k, i, offset); | |
48 if (reference_value != sub_frame_view[k][i]) { | |
49 return false; | |
50 } | |
51 } | |
52 } | |
53 return true; | |
54 } | |
55 | |
56 void FillBlock(size_t block_counter, std::vector<std::vector<float>>* block) { | |
57 for (size_t k = 0; k < block->size(); ++k) { | |
58 for (size_t i = 0; i < (*block)[0].size(); ++i) { | |
59 (*block)[k][i] = ComputeSampleValue(block_counter, kBlockSize, k, i, 0); | |
60 } | |
61 } | |
62 } | |
63 | |
64 // Verifies that the BlockFramer is able to produce the expected frame content. | |
65 void RunFramerTest(int sample_rate_hz) { | |
66 constexpr size_t kNumSubFramesToProcess = 2; | |
67 const size_t num_bands = NumBandsForRate(sample_rate_hz); | |
68 | |
69 std::vector<std::vector<float>> block(num_bands, | |
70 std::vector<float>(kBlockSize, 0.f)); | |
71 std::vector<std::vector<float>> output_sub_frame( | |
72 num_bands, std::vector<float>(kSubFrameLength, 0.f)); | |
73 std::vector<rtc::ArrayView<float>> output_sub_frame_view(num_bands); | |
74 SetupSubFrameView(&output_sub_frame, &output_sub_frame_view); | |
75 BlockFramer framer(num_bands); | |
76 | |
77 size_t block_index = 0; | |
78 for (size_t sub_frame_index = 0; sub_frame_index < kNumSubFramesToProcess; | |
79 ++sub_frame_index) { | |
80 FillBlock(block_index++, &block); | |
81 framer.InsertBlockAndExtractSubFrame(block, &output_sub_frame_view); | |
82 EXPECT_TRUE(VerifySubFrame(sub_frame_index, -64, output_sub_frame_view)); | |
83 | |
84 if ((sub_frame_index + 1) % 4 == 0) { | |
85 FillBlock(block_index++, &block); | |
86 framer.InsertBlock(block); | |
87 } | |
88 } | |
89 } | |
90 | |
91 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) | |
92 // Verifies that the BlockFramer crashes if the InsertBlockAndExtractSubFrame | |
93 // method is called for inputs with the wrong number of bands or band lengths. | |
94 void RunWronglySizedInsertAndExtractParametersTest(int sample_rate_hz, | |
95 size_t num_block_bands, | |
96 size_t block_length, | |
97 size_t num_sub_frame_bands, | |
98 size_t sub_frame_length) { | |
99 const size_t correct_num_bands = NumBandsForRate(sample_rate_hz); | |
100 | |
101 std::vector<std::vector<float>> block(num_block_bands, | |
102 std::vector<float>(block_length, 0.f)); | |
103 std::vector<std::vector<float>> output_sub_frame( | |
104 num_sub_frame_bands, std::vector<float>(sub_frame_length, 0.f)); | |
105 std::vector<rtc::ArrayView<float>> output_sub_frame_view( | |
106 output_sub_frame.size()); | |
107 SetupSubFrameView(&output_sub_frame, &output_sub_frame_view); | |
108 BlockFramer framer(correct_num_bands); | |
109 EXPECT_DEATH( | |
110 framer.InsertBlockAndExtractSubFrame(block, &output_sub_frame_view), ""); | |
111 } | |
112 | |
113 // Verifies that the BlockFramer crashes if the InsertBlock method is called for | |
114 // inputs with the wrong number of bands or band lengths. | |
115 void RunWronglySizedInsertParameterTest(int sample_rate_hz, | |
116 size_t num_block_bands, | |
117 size_t block_length) { | |
118 const size_t correct_num_bands = NumBandsForRate(sample_rate_hz); | |
119 | |
120 std::vector<std::vector<float>> correct_block( | |
121 correct_num_bands, std::vector<float>(kBlockSize, 0.f)); | |
122 std::vector<std::vector<float>> wrong_block( | |
123 num_block_bands, std::vector<float>(block_length, 0.f)); | |
124 std::vector<std::vector<float>> output_sub_frame( | |
125 correct_num_bands, std::vector<float>(kSubFrameLength, 0.f)); | |
126 std::vector<rtc::ArrayView<float>> output_sub_frame_view( | |
127 output_sub_frame.size()); | |
128 SetupSubFrameView(&output_sub_frame, &output_sub_frame_view); | |
129 BlockFramer framer(correct_num_bands); | |
130 framer.InsertBlockAndExtractSubFrame(correct_block, &output_sub_frame_view); | |
131 framer.InsertBlockAndExtractSubFrame(correct_block, &output_sub_frame_view); | |
132 framer.InsertBlockAndExtractSubFrame(correct_block, &output_sub_frame_view); | |
133 framer.InsertBlockAndExtractSubFrame(correct_block, &output_sub_frame_view); | |
134 | |
135 EXPECT_DEATH(framer.InsertBlock(wrong_block), ""); | |
136 } | |
137 | |
138 // Verifies that the BlockFramer crashes if the InsertBlock method is called | |
139 // after a wrong number of previous InsertBlockAndExtractSubFrame method calls | |
140 // have been made. | |
141 void RunWronglyInsertOrderTest(int sample_rate_hz, | |
142 size_t num_preceeding_api_calls) { | |
143 const size_t correct_num_bands = NumBandsForRate(sample_rate_hz); | |
144 | |
145 std::vector<std::vector<float>> block(correct_num_bands, | |
146 std::vector<float>(kBlockSize, 0.f)); | |
147 std::vector<std::vector<float>> output_sub_frame( | |
148 correct_num_bands, std::vector<float>(kSubFrameLength, 0.f)); | |
149 std::vector<rtc::ArrayView<float>> output_sub_frame_view( | |
150 output_sub_frame.size()); | |
151 SetupSubFrameView(&output_sub_frame, &output_sub_frame_view); | |
152 BlockFramer framer(correct_num_bands); | |
153 for (size_t k = 0; k < num_preceeding_api_calls; ++k) { | |
154 framer.InsertBlockAndExtractSubFrame(block, &output_sub_frame_view); | |
155 } | |
156 | |
157 EXPECT_DEATH(framer.InsertBlock(block), ""); | |
158 } | |
159 #endif | |
160 | |
161 std::string ProduceDebugText(int sample_rate_hz) { | |
162 std::ostringstream ss; | |
163 ss << "Sample rate: " << sample_rate_hz; | |
164 return ss.str(); | |
165 } | |
166 | |
167 } // namespace | |
168 | |
169 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) | |
170 TEST(BlockFramer, WrongNumberOfBandsInBlockForInsertBlockAndExtractSubFrame) { | |
171 for (auto rate : {8000, 16000, 32000, 48000}) { | |
172 SCOPED_TRACE(ProduceDebugText(rate)); | |
173 const size_t correct_num_bands = NumBandsForRate(rate); | |
174 const size_t wrong_num_bands = (correct_num_bands % 3) + 1; | |
175 RunWronglySizedInsertAndExtractParametersTest( | |
176 rate, wrong_num_bands, kBlockSize, correct_num_bands, kSubFrameLength); | |
177 } | |
178 } | |
179 | |
180 TEST(BlockFramer, | |
181 WrongNumberOfBandsInSubFrameForInsertBlockAndExtractSubFrame) { | |
182 for (auto rate : {8000, 16000, 32000, 48000}) { | |
183 SCOPED_TRACE(ProduceDebugText(rate)); | |
184 const size_t correct_num_bands = NumBandsForRate(rate); | |
185 const size_t wrong_num_bands = (correct_num_bands % 3) + 1; | |
186 RunWronglySizedInsertAndExtractParametersTest( | |
187 rate, correct_num_bands, kBlockSize, wrong_num_bands, kSubFrameLength); | |
188 } | |
189 } | |
190 | |
191 TEST(BlockFramer, WrongNumberOfSamplesInBlockForInsertBlockAndExtractSubFrame) { | |
192 for (auto rate : {8000, 16000, 32000, 48000}) { | |
193 SCOPED_TRACE(ProduceDebugText(rate)); | |
194 const size_t correct_num_bands = NumBandsForRate(rate); | |
195 RunWronglySizedInsertAndExtractParametersTest( | |
196 rate, correct_num_bands, kBlockSize - 1, correct_num_bands, | |
197 kSubFrameLength); | |
198 } | |
199 } | |
200 | |
201 TEST(BlockFramer, | |
202 WrongNumberOfSamplesInSubFrameForInsertBlockAndExtractSubFrame) { | |
203 for (auto rate : {8000, 16000, 32000, 48000}) { | |
204 SCOPED_TRACE(ProduceDebugText(rate)); | |
205 const size_t correct_num_bands = NumBandsForRate(rate); | |
206 RunWronglySizedInsertAndExtractParametersTest(rate, correct_num_bands, | |
207 kBlockSize, correct_num_bands, | |
208 kSubFrameLength - 1); | |
209 } | |
210 } | |
211 | |
212 TEST(BlockFramer, WrongNumberOfBandsInBlockForInsertBlock) { | |
213 for (auto rate : {8000, 16000, 32000, 48000}) { | |
214 SCOPED_TRACE(ProduceDebugText(rate)); | |
215 const size_t correct_num_bands = NumBandsForRate(rate); | |
216 const size_t wrong_num_bands = (correct_num_bands % 3) + 1; | |
217 RunWronglySizedInsertParameterTest(rate, wrong_num_bands, kBlockSize); | |
218 } | |
219 } | |
220 | |
221 TEST(BlockFramer, WrongNumberOfSamplesInBlockForInsertBlock) { | |
222 for (auto rate : {8000, 16000, 32000, 48000}) { | |
223 SCOPED_TRACE(ProduceDebugText(rate)); | |
224 const size_t correct_num_bands = NumBandsForRate(rate); | |
225 RunWronglySizedInsertParameterTest(rate, correct_num_bands, kBlockSize - 1); | |
226 } | |
227 } | |
228 | |
229 TEST(BlockFramer, WrongNumberOfPreceedingApiCallsForInsertBlock) { | |
230 for (auto rate : {8000, 16000, 32000, 48000}) { | |
231 for (size_t num_calls = 0; num_calls < 4; ++num_calls) { | |
232 std::ostringstream ss; | |
233 ss << "Sample rate: " << rate; | |
234 ss << ", Num preceeding InsertBlockAndExtractSubFrame calls: " | |
235 << num_calls; | |
236 | |
237 SCOPED_TRACE(ss.str()); | |
238 RunWronglyInsertOrderTest(rate, num_calls); | |
239 } | |
240 } | |
241 } | |
242 | |
243 // Verifiers that the verification for null sub_frame pointer works. | |
244 TEST(BlockFramer, NullSubFrameParameter) { | |
245 EXPECT_DEATH(BlockFramer(1).InsertBlockAndExtractSubFrame( | |
246 std::vector<std::vector<float>>( | |
247 1, std::vector<float>(kBlockSize, 0.f)), | |
248 nullptr), | |
249 ""); | |
250 } | |
251 | |
252 #endif | |
253 | |
254 TEST(BlockFramer, FrameBitexactness) { | |
255 for (auto rate : {8000, 16000, 32000, 48000}) { | |
256 SCOPED_TRACE(ProduceDebugText(rate)); | |
257 RunFramerTest(rate); | |
258 } | |
259 } | |
260 | |
261 } // namespace webrtc | |
OLD | NEW |