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 |