audio_vector_unittest.cc (13496B)
1 /* 2 * Copyright (c) 2012 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_coding/neteq/audio_vector.h" 12 13 #include <array> 14 #include <cstdint> 15 #include <cstdlib> 16 17 #include "api/audio/audio_view.h" 18 #include "rtc_base/numerics/safe_conversions.h" 19 #include "test/gtest.h" 20 21 namespace webrtc { 22 23 class AudioVectorTest : public ::testing::Test { 24 protected: 25 void SetUp() override { 26 // Populate test array. 27 for (size_t i = 0; i < array_length(); ++i) { 28 array_[i] = checked_cast<int16_t>(i); 29 } 30 } 31 32 constexpr size_t array_length() const { 33 return sizeof(array_) / sizeof(array_[0]); 34 } 35 36 int16_t array_[10]; 37 }; 38 39 // Create and destroy AudioVector objects, both empty and with a predefined 40 // length. 41 TEST_F(AudioVectorTest, CreateAndDestroy) { 42 AudioVector vec1; 43 EXPECT_TRUE(vec1.Empty()); 44 EXPECT_EQ(0u, vec1.Size()); 45 46 size_t initial_size = 17; 47 AudioVector vec2(initial_size); 48 EXPECT_FALSE(vec2.Empty()); 49 EXPECT_EQ(initial_size, vec2.Size()); 50 } 51 52 // Test the subscript operator [] for getting and setting. 53 TEST_F(AudioVectorTest, SubscriptOperator) { 54 AudioVector vec(array_length()); 55 for (size_t i = 0; i < array_length(); ++i) { 56 vec[i] = static_cast<int16_t>(i); 57 const int16_t& value = vec[i]; // Make sure to use the const version. 58 EXPECT_EQ(static_cast<int16_t>(i), value); 59 } 60 } 61 62 // Test the PushBack method and the CopyFrom method. The Clear method is also 63 // invoked. 64 TEST_F(AudioVectorTest, PushBackAndCopy) { 65 AudioVector vec; 66 AudioVector vec_copy; 67 vec.PushBack(array_, array_length()); 68 vec.CopyTo(&vec_copy); // Copy from `vec` to `vec_copy`. 69 ASSERT_EQ(array_length(), vec.Size()); 70 ASSERT_EQ(array_length(), vec_copy.Size()); 71 for (size_t i = 0; i < array_length(); ++i) { 72 EXPECT_EQ(array_[i], vec[i]); 73 EXPECT_EQ(array_[i], vec_copy[i]); 74 } 75 76 // Clear `vec` and verify that it is empty. 77 vec.Clear(); 78 EXPECT_TRUE(vec.Empty()); 79 80 // Now copy the empty vector and verify that the copy becomes empty too. 81 vec.CopyTo(&vec_copy); 82 EXPECT_TRUE(vec_copy.Empty()); 83 } 84 85 TEST_F(AudioVectorTest, CopyTo) { 86 AudioVector vec; 87 vec.PushBack(array_, array_length()); 88 ASSERT_EQ(vec.Size(), 10u); 89 90 std::array<int16_t, 10> buffer; 91 MonoView<int16_t> view(&buffer[0], buffer.size()); 92 // Try to read 10 samples from position 1, which should fail. 93 EXPECT_FALSE(vec.CopyTo(1, view)); 94 // Reading 10 samples from position 0, should succeed. 95 EXPECT_TRUE(vec.CopyTo(0, view)); 96 EXPECT_EQ(view[5], 5); // sanity check. 97 98 // Free up space at the front of the buffer. This changes 99 // the internal start position without reallocating memory. 100 vec.PopFront(2); 101 102 std::array<int16_t, 2> new_values = {20, 21}; 103 vec.PushBack(&new_values[0], new_values.size()); 104 105 // Now the CopyTo() operation will need to wrap around 106 // the end of the internal buffer to fill the view. 107 EXPECT_TRUE(vec.CopyTo(0, view)); 108 EXPECT_EQ(view[0], 2); 109 EXPECT_EQ(view[8], 20); 110 EXPECT_EQ(view[9], 21); 111 } 112 113 // Test the PushBack method with another AudioVector as input argument. 114 TEST_F(AudioVectorTest, PushBackVector) { 115 static const size_t kLength = 10; 116 AudioVector vec1(kLength); 117 AudioVector vec2(kLength); 118 // Set the first vector to [0, 1, ..., kLength - 1]. 119 // Set the second vector to [kLength, kLength + 1, ..., 2 * kLength - 1]. 120 for (size_t i = 0; i < kLength; ++i) { 121 vec1[i] = static_cast<int16_t>(i); 122 vec2[i] = static_cast<int16_t>(i + kLength); 123 } 124 // Append vec2 to the back of vec1. 125 vec1.PushBack(vec2); 126 ASSERT_EQ(2 * kLength, vec1.Size()); 127 for (size_t i = 0; i < 2 * kLength; ++i) { 128 EXPECT_EQ(static_cast<int16_t>(i), vec1[i]); 129 } 130 } 131 132 // Test the PushFront method. 133 TEST_F(AudioVectorTest, PushFront) { 134 AudioVector vec; 135 vec.PushFront(array_, array_length()); 136 ASSERT_EQ(array_length(), vec.Size()); 137 for (size_t i = 0; i < array_length(); ++i) { 138 EXPECT_EQ(array_[i], vec[i]); 139 } 140 } 141 142 // Test the PushFront method with another AudioVector as input argument. 143 TEST_F(AudioVectorTest, PushFrontVector) { 144 static const size_t kLength = 10; 145 AudioVector vec1(kLength); 146 AudioVector vec2(kLength); 147 // Set the first vector to [0, 1, ..., kLength - 1]. 148 // Set the second vector to [kLength, kLength + 1, ..., 2 * kLength - 1]. 149 for (size_t i = 0; i < kLength; ++i) { 150 vec1[i] = static_cast<int16_t>(i); 151 vec2[i] = static_cast<int16_t>(i + kLength); 152 } 153 // Prepend vec1 to the front of vec2. 154 vec2.PushFront(vec1); 155 ASSERT_EQ(2 * kLength, vec2.Size()); 156 for (size_t i = 0; i < 2 * kLength; ++i) { 157 EXPECT_EQ(static_cast<int16_t>(i), vec2[i]); 158 } 159 } 160 161 // Test the PopFront method. 162 TEST_F(AudioVectorTest, PopFront) { 163 AudioVector vec; 164 vec.PushBack(array_, array_length()); 165 vec.PopFront(1); // Remove one element. 166 EXPECT_EQ(array_length() - 1u, vec.Size()); 167 for (size_t i = 0; i < array_length() - 1; ++i) { 168 EXPECT_EQ(static_cast<int16_t>(i + 1), vec[i]); 169 } 170 vec.PopFront(array_length()); // Remove more elements than vector size. 171 EXPECT_EQ(0u, vec.Size()); 172 } 173 174 // Test the PopBack method. 175 TEST_F(AudioVectorTest, PopBack) { 176 AudioVector vec; 177 vec.PushBack(array_, array_length()); 178 vec.PopBack(1); // Remove one element. 179 EXPECT_EQ(array_length() - 1u, vec.Size()); 180 for (size_t i = 0; i < array_length() - 1; ++i) { 181 EXPECT_EQ(static_cast<int16_t>(i), vec[i]); 182 } 183 vec.PopBack(array_length()); // Remove more elements than vector size. 184 EXPECT_EQ(0u, vec.Size()); 185 } 186 187 // Test the Extend method. 188 TEST_F(AudioVectorTest, Extend) { 189 AudioVector vec; 190 vec.PushBack(array_, array_length()); 191 vec.Extend(5); // Extend with 5 elements, which should all be zeros. 192 ASSERT_EQ(array_length() + 5u, vec.Size()); 193 // Verify that all are zero. 194 for (size_t i = array_length(); i < array_length() + 5; ++i) { 195 EXPECT_EQ(0, vec[i]); 196 } 197 } 198 199 // Test the InsertAt method with an insert position in the middle of the vector. 200 TEST_F(AudioVectorTest, InsertAt) { 201 AudioVector vec; 202 vec.PushBack(array_, array_length()); 203 static const int kNewLength = 5; 204 int16_t new_array[kNewLength]; 205 // Set array elements to {100, 101, 102, ... }. 206 for (int i = 0; i < kNewLength; ++i) { 207 new_array[i] = 100 + i; 208 } 209 int insert_position = 5; 210 vec.InsertAt(new_array, kNewLength, insert_position); 211 // Verify that the vector looks as follows: 212 // {0, 1, ..., `insert_position` - 1, 100, 101, ..., 100 + kNewLength - 1, 213 // `insert_position`, `insert_position` + 1, ..., kLength - 1}. 214 size_t pos = 0; 215 for (int i = 0; i < insert_position; ++i) { 216 EXPECT_EQ(array_[i], vec[pos]); 217 ++pos; 218 } 219 for (int i = 0; i < kNewLength; ++i) { 220 EXPECT_EQ(new_array[i], vec[pos]); 221 ++pos; 222 } 223 for (size_t i = insert_position; i < array_length(); ++i) { 224 EXPECT_EQ(array_[i], vec[pos]); 225 ++pos; 226 } 227 } 228 229 // Test the InsertZerosAt method with an insert position in the middle of the 230 // vector. Use the InsertAt method as reference. 231 TEST_F(AudioVectorTest, InsertZerosAt) { 232 AudioVector vec; 233 AudioVector vec_ref; 234 vec.PushBack(array_, array_length()); 235 vec_ref.PushBack(array_, array_length()); 236 static const int kNewLength = 5; 237 int insert_position = 5; 238 vec.InsertZerosAt(kNewLength, insert_position); 239 int16_t new_array[kNewLength] = {0}; // All zero elements. 240 vec_ref.InsertAt(new_array, kNewLength, insert_position); 241 // Verify that the vectors are identical. 242 ASSERT_EQ(vec_ref.Size(), vec.Size()); 243 for (size_t i = 0; i < vec.Size(); ++i) { 244 EXPECT_EQ(vec_ref[i], vec[i]); 245 } 246 } 247 248 // Test the InsertAt method with an insert position at the start of the vector. 249 TEST_F(AudioVectorTest, InsertAtBeginning) { 250 AudioVector vec; 251 vec.PushBack(array_, array_length()); 252 static const int kNewLength = 5; 253 int16_t new_array[kNewLength]; 254 // Set array elements to {100, 101, 102, ... }. 255 for (int i = 0; i < kNewLength; ++i) { 256 new_array[i] = 100 + i; 257 } 258 int insert_position = 0; 259 vec.InsertAt(new_array, kNewLength, insert_position); 260 // Verify that the vector looks as follows: 261 // {100, 101, ..., 100 + kNewLength - 1, 262 // 0, 1, ..., kLength - 1}. 263 size_t pos = 0; 264 for (int i = 0; i < kNewLength; ++i) { 265 EXPECT_EQ(new_array[i], vec[pos]); 266 ++pos; 267 } 268 for (size_t i = insert_position; i < array_length(); ++i) { 269 EXPECT_EQ(array_[i], vec[pos]); 270 ++pos; 271 } 272 } 273 274 // Test the InsertAt method with an insert position at the end of the vector. 275 TEST_F(AudioVectorTest, InsertAtEnd) { 276 AudioVector vec; 277 vec.PushBack(array_, array_length()); 278 static const int kNewLength = 5; 279 int16_t new_array[kNewLength]; 280 // Set array elements to {100, 101, 102, ... }. 281 for (int i = 0; i < kNewLength; ++i) { 282 new_array[i] = 100 + i; 283 } 284 int insert_position = checked_cast<int>(array_length()); 285 vec.InsertAt(new_array, kNewLength, insert_position); 286 // Verify that the vector looks as follows: 287 // {0, 1, ..., kLength - 1, 100, 101, ..., 100 + kNewLength - 1 }. 288 size_t pos = 0; 289 for (size_t i = 0; i < array_length(); ++i) { 290 EXPECT_EQ(array_[i], vec[pos]); 291 ++pos; 292 } 293 for (int i = 0; i < kNewLength; ++i) { 294 EXPECT_EQ(new_array[i], vec[pos]); 295 ++pos; 296 } 297 } 298 299 // Test the InsertAt method with an insert position beyond the end of the 300 // vector. Verify that a position beyond the end of the vector does not lead to 301 // an error. The expected outcome is the same as if the vector end was used as 302 // input position. That is, the input position should be capped at the maximum 303 // allowed value. 304 TEST_F(AudioVectorTest, InsertBeyondEnd) { 305 AudioVector vec; 306 vec.PushBack(array_, array_length()); 307 static const int kNewLength = 5; 308 int16_t new_array[kNewLength]; 309 // Set array elements to {100, 101, 102, ... }. 310 for (int i = 0; i < kNewLength; ++i) { 311 new_array[i] = 100 + i; 312 } 313 int insert_position = checked_cast<int>(array_length() + 10); // Too large. 314 vec.InsertAt(new_array, kNewLength, insert_position); 315 // Verify that the vector looks as follows: 316 // {0, 1, ..., kLength - 1, 100, 101, ..., 100 + kNewLength - 1 }. 317 size_t pos = 0; 318 for (size_t i = 0; i < array_length(); ++i) { 319 EXPECT_EQ(array_[i], vec[pos]); 320 ++pos; 321 } 322 for (int i = 0; i < kNewLength; ++i) { 323 EXPECT_EQ(new_array[i], vec[pos]); 324 ++pos; 325 } 326 } 327 328 // Test the OverwriteAt method with a position such that all of the new values 329 // fit within the old vector. 330 TEST_F(AudioVectorTest, OverwriteAt) { 331 AudioVector vec; 332 vec.PushBack(array_, array_length()); 333 static const int kNewLength = 5; 334 int16_t new_array[kNewLength]; 335 // Set array elements to {100, 101, 102, ... }. 336 for (int i = 0; i < kNewLength; ++i) { 337 new_array[i] = 100 + i; 338 } 339 size_t insert_position = 2; 340 vec.OverwriteAt(new_array, kNewLength, insert_position); 341 // Verify that the vector looks as follows: 342 // {0, ..., `insert_position` - 1, 100, 101, ..., 100 + kNewLength - 1, 343 // `insert_position`, `insert_position` + 1, ..., kLength - 1}. 344 size_t pos = 0; 345 for (pos = 0; pos < insert_position; ++pos) { 346 EXPECT_EQ(array_[pos], vec[pos]); 347 } 348 for (int i = 0; i < kNewLength; ++i) { 349 EXPECT_EQ(new_array[i], vec[pos]); 350 ++pos; 351 } 352 for (; pos < array_length(); ++pos) { 353 EXPECT_EQ(array_[pos], vec[pos]); 354 } 355 } 356 357 // Test the OverwriteAt method with a position such that some of the new values 358 // extend beyond the end of the current vector. This is valid, and the vector is 359 // expected to expand to accommodate the new values. 360 TEST_F(AudioVectorTest, OverwriteBeyondEnd) { 361 AudioVector vec; 362 vec.PushBack(array_, array_length()); 363 static const int kNewLength = 5; 364 int16_t new_array[kNewLength]; 365 // Set array elements to {100, 101, 102, ... }. 366 for (int i = 0; i < kNewLength; ++i) { 367 new_array[i] = 100 + i; 368 } 369 int insert_position = checked_cast<int>(array_length() - 2); 370 vec.OverwriteAt(new_array, kNewLength, insert_position); 371 ASSERT_EQ(array_length() - 2u + kNewLength, vec.Size()); 372 // Verify that the vector looks as follows: 373 // {0, ..., `insert_position` - 1, 100, 101, ..., 100 + kNewLength - 1, 374 // `insert_position`, `insert_position` + 1, ..., kLength - 1}. 375 int pos = 0; 376 for (pos = 0; pos < insert_position; ++pos) { 377 EXPECT_EQ(array_[pos], vec[pos]); 378 } 379 for (int i = 0; i < kNewLength; ++i) { 380 EXPECT_EQ(new_array[i], vec[pos]); 381 ++pos; 382 } 383 // Verify that we checked to the end of `vec`. 384 EXPECT_EQ(vec.Size(), static_cast<size_t>(pos)); 385 } 386 387 TEST_F(AudioVectorTest, CrossFade) { 388 static const size_t kLength = 100; 389 static const size_t kFadeLength = 10; 390 AudioVector vec1(kLength); 391 AudioVector vec2(kLength); 392 // Set all vector elements to 0 in `vec1` and 100 in `vec2`. 393 for (size_t i = 0; i < kLength; ++i) { 394 vec1[i] = 0; 395 vec2[i] = 100; 396 } 397 vec1.CrossFade(vec2, kFadeLength); 398 ASSERT_EQ(2 * kLength - kFadeLength, vec1.Size()); 399 // First part untouched. 400 for (size_t i = 0; i < kLength - kFadeLength; ++i) { 401 EXPECT_EQ(0, vec1[i]); 402 } 403 // Check mixing zone. 404 for (size_t i = 0; i < kFadeLength; ++i) { 405 EXPECT_NEAR((i + 1) * 100 / (kFadeLength + 1), 406 vec1[kLength - kFadeLength + i], 1); 407 } 408 // Second part untouched. 409 for (size_t i = kLength; i < vec1.Size(); ++i) { 410 EXPECT_EQ(100, vec1[i]); 411 } 412 } 413 414 } // namespace webrtc