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
21 namespace webrtc {
22
23 class AudioVectorTest : public ::testing::Test {
24 protected:
SetUp()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
array_length() const32 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.
TEST_F(AudioVectorTest,CreateAndDestroy)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.
TEST_F(AudioVectorTest,SubscriptOperator)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.
TEST_F(AudioVectorTest,PushBackAndCopy)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 // Try to copy to a NULL pointer. Nothing should happen.
TEST_F(AudioVectorTest,CopyToNull)86 TEST_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.
TEST_F(AudioVectorTest,PushBackVector)94 TEST_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.
TEST_F(AudioVectorTest,PushFront)113 TEST_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.
TEST_F(AudioVectorTest,PushFrontVector)123 TEST_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.
TEST_F(AudioVectorTest,PopFront)142 TEST_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.
TEST_F(AudioVectorTest,PopBack)155 TEST_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.
TEST_F(AudioVectorTest,Extend)168 TEST_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.
TEST_F(AudioVectorTest,InsertAt)180 TEST_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.
TEST_F(AudioVectorTest,InsertZerosAt)211 TEST_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.
TEST_F(AudioVectorTest,InsertAtBeginning)229 TEST_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.
TEST_F(AudioVectorTest,InsertAtEnd)255 TEST_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.
TEST_F(AudioVectorTest,InsertBeyondEnd)284 TEST_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.
TEST_F(AudioVectorTest,OverwriteAt)310 TEST_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.
TEST_F(AudioVectorTest,OverwriteBeyondEnd)340 TEST_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
TEST_F(AudioVectorTest,CrossFade)367 TEST_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