| 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 |