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