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