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 "webrtc/modules/audio_coding/neteq/audio_vector.h" 12 13#include <assert.h> 14#include <stdlib.h> 15 16#include <string> 17 18#include "testing/gtest/include/gtest/gtest.h" 19#include "webrtc/typedefs.h" 20 21namespace webrtc { 22 23class AudioVectorTest : public ::testing::Test { 24 protected: 25 virtual void SetUp() { 26 // Populate test array. 27 for (size_t i = 0; i < array_length(); ++i) { 28 array_[i] = i; 29 } 30 } 31 32 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. 41TEST_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. 53TEST_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. 64TEST_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// Try to copy to a NULL pointer. Nothing should happen. 86TEST_F(AudioVectorTest, CopyToNull) { 87 AudioVector vec; 88 AudioVector* vec_copy = NULL; 89 vec.PushBack(array_, array_length()); 90 vec.CopyTo(vec_copy); 91} 92 93// Test the PushBack method with another AudioVector as input argument. 94TEST_F(AudioVectorTest, PushBackVector) { 95 static const size_t kLength = 10; 96 AudioVector vec1(kLength); 97 AudioVector vec2(kLength); 98 // Set the first vector to [0, 1, ..., kLength - 1]. 99 // Set the second vector to [kLength, kLength + 1, ..., 2 * kLength - 1]. 100 for (size_t i = 0; i < kLength; ++i) { 101 vec1[i] = static_cast<int16_t>(i); 102 vec2[i] = static_cast<int16_t>(i + kLength); 103 } 104 // Append vec2 to the back of vec1. 105 vec1.PushBack(vec2); 106 ASSERT_EQ(2 * kLength, vec1.Size()); 107 for (size_t i = 0; i < 2 * kLength; ++i) { 108 EXPECT_EQ(static_cast<int16_t>(i), vec1[i]); 109 } 110} 111 112// Test the PushFront method. 113TEST_F(AudioVectorTest, PushFront) { 114 AudioVector vec; 115 vec.PushFront(array_, array_length()); 116 ASSERT_EQ(array_length(), vec.Size()); 117 for (size_t i = 0; i < array_length(); ++i) { 118 EXPECT_EQ(array_[i], vec[i]); 119 } 120} 121 122// Test the PushFront method with another AudioVector as input argument. 123TEST_F(AudioVectorTest, PushFrontVector) { 124 static const size_t kLength = 10; 125 AudioVector vec1(kLength); 126 AudioVector vec2(kLength); 127 // Set the first vector to [0, 1, ..., kLength - 1]. 128 // Set the second vector to [kLength, kLength + 1, ..., 2 * kLength - 1]. 129 for (size_t i = 0; i < kLength; ++i) { 130 vec1[i] = static_cast<int16_t>(i); 131 vec2[i] = static_cast<int16_t>(i + kLength); 132 } 133 // Prepend vec1 to the front of vec2. 134 vec2.PushFront(vec1); 135 ASSERT_EQ(2 * kLength, vec2.Size()); 136 for (size_t i = 0; i < 2 * kLength; ++i) { 137 EXPECT_EQ(static_cast<int16_t>(i), vec2[i]); 138 } 139} 140 141// Test the PopFront method. 142TEST_F(AudioVectorTest, PopFront) { 143 AudioVector vec; 144 vec.PushBack(array_, array_length()); 145 vec.PopFront(1); // Remove one element. 146 EXPECT_EQ(array_length() - 1u, vec.Size()); 147 for (size_t i = 0; i < array_length() - 1; ++i) { 148 EXPECT_EQ(static_cast<int16_t>(i + 1), vec[i]); 149 } 150 vec.PopFront(array_length()); // Remove more elements than vector size. 151 EXPECT_EQ(0u, vec.Size()); 152} 153 154// Test the PopBack method. 155TEST_F(AudioVectorTest, PopBack) { 156 AudioVector vec; 157 vec.PushBack(array_, array_length()); 158 vec.PopBack(1); // Remove one element. 159 EXPECT_EQ(array_length() - 1u, vec.Size()); 160 for (size_t i = 0; i < array_length() - 1; ++i) { 161 EXPECT_EQ(static_cast<int16_t>(i), vec[i]); 162 } 163 vec.PopBack(array_length()); // Remove more elements than vector size. 164 EXPECT_EQ(0u, vec.Size()); 165} 166 167// Test the Extend method. 168TEST_F(AudioVectorTest, Extend) { 169 AudioVector vec; 170 vec.PushBack(array_, array_length()); 171 vec.Extend(5); // Extend with 5 elements, which should all be zeros. 172 ASSERT_EQ(array_length() + 5u, vec.Size()); 173 // Verify that all are zero. 174 for (size_t i = array_length(); i < array_length() + 5; ++i) { 175 EXPECT_EQ(0, vec[i]); 176 } 177} 178 179// Test the InsertAt method with an insert position in the middle of the vector. 180TEST_F(AudioVectorTest, InsertAt) { 181 AudioVector vec; 182 vec.PushBack(array_, array_length()); 183 static const int kNewLength = 5; 184 int16_t new_array[kNewLength]; 185 // Set array elements to {100, 101, 102, ... }. 186 for (int i = 0; i < kNewLength; ++i) { 187 new_array[i] = 100 + i; 188 } 189 int insert_position = 5; 190 vec.InsertAt(new_array, kNewLength, insert_position); 191 // Verify that the vector looks as follows: 192 // {0, 1, ..., |insert_position| - 1, 100, 101, ..., 100 + kNewLength - 1, 193 // |insert_position|, |insert_position| + 1, ..., kLength - 1}. 194 size_t pos = 0; 195 for (int i = 0; i < insert_position; ++i) { 196 EXPECT_EQ(array_[i], vec[pos]); 197 ++pos; 198 } 199 for (int i = 0; i < kNewLength; ++i) { 200 EXPECT_EQ(new_array[i], vec[pos]); 201 ++pos; 202 } 203 for (size_t i = insert_position; i < array_length(); ++i) { 204 EXPECT_EQ(array_[i], vec[pos]); 205 ++pos; 206 } 207} 208 209// Test the InsertZerosAt method with an insert position in the middle of the 210// vector. Use the InsertAt method as reference. 211TEST_F(AudioVectorTest, InsertZerosAt) { 212 AudioVector vec; 213 AudioVector vec_ref; 214 vec.PushBack(array_, array_length()); 215 vec_ref.PushBack(array_, array_length()); 216 static const int kNewLength = 5; 217 int insert_position = 5; 218 vec.InsertZerosAt(kNewLength, insert_position); 219 int16_t new_array[kNewLength] = {0}; // All zero elements. 220 vec_ref.InsertAt(new_array, kNewLength, insert_position); 221 // Verify that the vectors are identical. 222 ASSERT_EQ(vec_ref.Size(), vec.Size()); 223 for (size_t i = 0; i < vec.Size(); ++i) { 224 EXPECT_EQ(vec_ref[i], vec[i]); 225 } 226} 227 228// Test the InsertAt method with an insert position at the start of the vector. 229TEST_F(AudioVectorTest, InsertAtBeginning) { 230 AudioVector vec; 231 vec.PushBack(array_, array_length()); 232 static const int kNewLength = 5; 233 int16_t new_array[kNewLength]; 234 // Set array elements to {100, 101, 102, ... }. 235 for (int i = 0; i < kNewLength; ++i) { 236 new_array[i] = 100 + i; 237 } 238 int insert_position = 0; 239 vec.InsertAt(new_array, kNewLength, insert_position); 240 // Verify that the vector looks as follows: 241 // {100, 101, ..., 100 + kNewLength - 1, 242 // 0, 1, ..., kLength - 1}. 243 size_t pos = 0; 244 for (int i = 0; i < kNewLength; ++i) { 245 EXPECT_EQ(new_array[i], vec[pos]); 246 ++pos; 247 } 248 for (size_t i = insert_position; i < array_length(); ++i) { 249 EXPECT_EQ(array_[i], vec[pos]); 250 ++pos; 251 } 252} 253 254// Test the InsertAt method with an insert position at the end of the vector. 255TEST_F(AudioVectorTest, InsertAtEnd) { 256 AudioVector vec; 257 vec.PushBack(array_, array_length()); 258 static const int kNewLength = 5; 259 int16_t new_array[kNewLength]; 260 // Set array elements to {100, 101, 102, ... }. 261 for (int i = 0; i < kNewLength; ++i) { 262 new_array[i] = 100 + i; 263 } 264 int insert_position = array_length(); 265 vec.InsertAt(new_array, kNewLength, insert_position); 266 // Verify that the vector looks as follows: 267 // {0, 1, ..., kLength - 1, 100, 101, ..., 100 + kNewLength - 1 }. 268 size_t pos = 0; 269 for (size_t i = 0; i < array_length(); ++i) { 270 EXPECT_EQ(array_[i], vec[pos]); 271 ++pos; 272 } 273 for (int i = 0; i < kNewLength; ++i) { 274 EXPECT_EQ(new_array[i], vec[pos]); 275 ++pos; 276 } 277} 278 279// Test the InsertAt method with an insert position beyond the end of the 280// vector. Verify that a position beyond the end of the vector does not lead to 281// an error. The expected outcome is the same as if the vector end was used as 282// input position. That is, the input position should be capped at the maximum 283// allowed value. 284TEST_F(AudioVectorTest, InsertBeyondEnd) { 285 AudioVector vec; 286 vec.PushBack(array_, array_length()); 287 static const int kNewLength = 5; 288 int16_t new_array[kNewLength]; 289 // Set array elements to {100, 101, 102, ... }. 290 for (int i = 0; i < kNewLength; ++i) { 291 new_array[i] = 100 + i; 292 } 293 int insert_position = array_length() + 10; // Too large. 294 vec.InsertAt(new_array, kNewLength, insert_position); 295 // Verify that the vector looks as follows: 296 // {0, 1, ..., kLength - 1, 100, 101, ..., 100 + kNewLength - 1 }. 297 size_t pos = 0; 298 for (size_t i = 0; i < array_length(); ++i) { 299 EXPECT_EQ(array_[i], vec[pos]); 300 ++pos; 301 } 302 for (int i = 0; i < kNewLength; ++i) { 303 EXPECT_EQ(new_array[i], vec[pos]); 304 ++pos; 305 } 306} 307 308// Test the OverwriteAt method with a position such that all of the new values 309// fit within the old vector. 310TEST_F(AudioVectorTest, OverwriteAt) { 311 AudioVector vec; 312 vec.PushBack(array_, array_length()); 313 static const int kNewLength = 5; 314 int16_t new_array[kNewLength]; 315 // Set array elements to {100, 101, 102, ... }. 316 for (int i = 0; i < kNewLength; ++i) { 317 new_array[i] = 100 + i; 318 } 319 size_t insert_position = 2; 320 vec.OverwriteAt(new_array, kNewLength, insert_position); 321 // Verify that the vector looks as follows: 322 // {0, ..., |insert_position| - 1, 100, 101, ..., 100 + kNewLength - 1, 323 // |insert_position|, |insert_position| + 1, ..., kLength - 1}. 324 size_t pos = 0; 325 for (pos = 0; pos < insert_position; ++pos) { 326 EXPECT_EQ(array_[pos], vec[pos]); 327 } 328 for (int i = 0; i < kNewLength; ++i) { 329 EXPECT_EQ(new_array[i], vec[pos]); 330 ++pos; 331 } 332 for (; pos < array_length(); ++pos) { 333 EXPECT_EQ(array_[pos], vec[pos]); 334 } 335} 336 337// Test the OverwriteAt method with a position such that some of the new values 338// extend beyond the end of the current vector. This is valid, and the vector is 339// expected to expand to accommodate the new values. 340TEST_F(AudioVectorTest, OverwriteBeyondEnd) { 341 AudioVector vec; 342 vec.PushBack(array_, array_length()); 343 static const int kNewLength = 5; 344 int16_t new_array[kNewLength]; 345 // Set array elements to {100, 101, 102, ... }. 346 for (int i = 0; i < kNewLength; ++i) { 347 new_array[i] = 100 + i; 348 } 349 int insert_position = array_length() - 2; 350 vec.OverwriteAt(new_array, kNewLength, insert_position); 351 ASSERT_EQ(array_length() - 2u + kNewLength, vec.Size()); 352 // Verify that the vector looks as follows: 353 // {0, ..., |insert_position| - 1, 100, 101, ..., 100 + kNewLength - 1, 354 // |insert_position|, |insert_position| + 1, ..., kLength - 1}. 355 int pos = 0; 356 for (pos = 0; pos < insert_position; ++pos) { 357 EXPECT_EQ(array_[pos], vec[pos]); 358 } 359 for (int i = 0; i < kNewLength; ++i) { 360 EXPECT_EQ(new_array[i], vec[pos]); 361 ++pos; 362 } 363 // Verify that we checked to the end of |vec|. 364 EXPECT_EQ(vec.Size(), static_cast<size_t>(pos)); 365} 366 367TEST_F(AudioVectorTest, CrossFade) { 368 static const size_t kLength = 100; 369 static const size_t kFadeLength = 10; 370 AudioVector vec1(kLength); 371 AudioVector vec2(kLength); 372 // Set all vector elements to 0 in |vec1| and 100 in |vec2|. 373 for (size_t i = 0; i < kLength; ++i) { 374 vec1[i] = 0; 375 vec2[i] = 100; 376 } 377 vec1.CrossFade(vec2, kFadeLength); 378 ASSERT_EQ(2 * kLength - kFadeLength, vec1.Size()); 379 // First part untouched. 380 for (size_t i = 0; i < kLength - kFadeLength; ++i) { 381 EXPECT_EQ(0, vec1[i]); 382 } 383 // Check mixing zone. 384 for (size_t i = 0 ; i < kFadeLength; ++i) { 385 EXPECT_NEAR((i + 1) * 100 / (kFadeLength + 1), 386 vec1[kLength - kFadeLength + i], 1); 387 } 388 // Second part untouched. 389 for (size_t i = kLength; i < vec1.Size(); ++i) { 390 EXPECT_EQ(100, vec1[i]); 391 } 392} 393 394} // namespace webrtc 395