blob: b6419f7c609f58933bdfac5ddaa48fd83fca5c3a [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
11#include "webrtc/modules/audio_processing/aec3/block_framer.h"
12
13#include <sstream>
14#include <string>
15#include <vector>
16
peah522d71b2017-02-23 05:16:26 -080017#include "webrtc/modules/audio_processing/aec3/aec3_common.h"
peahd0263542017-01-03 04:20:34 -080018#include "webrtc/test/gtest.h"
19
20namespace webrtc {
21namespace {
22
23void 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
31float 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
41bool 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
56void 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.
65void 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.
94void 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.
115void 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.
141void 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
161std::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)
170TEST(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
180TEST(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
191TEST(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
201TEST(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
212TEST(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
221TEST(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
229TEST(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.
244TEST(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
254TEST(BlockFramer, FrameBitexactness) {
255 for (auto rate : {8000, 16000, 32000, 48000}) {
256 SCOPED_TRACE(ProduceDebugText(rate));
257 RunFramerTest(rate);
258 }
259}
260
261} // namespace webrtc