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_multi_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 // This is a value-parameterized test. The test cases are instantiated with
24 // different values for the test parameter, which is used to determine the
25 // number of channels in the AudioMultiBuffer. Note that it is not possible
26 // to combine typed testing with value-parameterized testing, and since the
27 // tests for AudioVector already covers a number of different type parameters,
28 // this test focuses on testing different number of channels, and keeping the
29 // value type constant.
30
31 class AudioMultiVectorTest : public ::testing::TestWithParam<size_t> {
32 protected:
AudioMultiVectorTest()33 AudioMultiVectorTest()
34 : num_channels_(GetParam()), // Get the test parameter.
35 interleaved_length_(num_channels_ * array_length()) {
36 array_interleaved_ = new int16_t[num_channels_ * array_length()];
37 }
38
~AudioMultiVectorTest()39 ~AudioMultiVectorTest() {
40 delete [] array_interleaved_;
41 }
42
SetUp()43 virtual void SetUp() {
44 // Populate test arrays.
45 for (size_t i = 0; i < array_length(); ++i) {
46 array_[i] = static_cast<int16_t>(i);
47 }
48 int16_t* ptr = array_interleaved_;
49 // Write 100, 101, 102, ... for first channel.
50 // Write 200, 201, 202, ... for second channel.
51 // And so on.
52 for (size_t i = 0; i < array_length(); ++i) {
53 for (size_t j = 1; j <= num_channels_; ++j) {
54 *ptr = j * 100 + i;
55 ++ptr;
56 }
57 }
58 }
59
array_length() const60 size_t array_length() const {
61 return sizeof(array_) / sizeof(array_[0]);
62 }
63
64 const size_t num_channels_;
65 size_t interleaved_length_;
66 int16_t array_[10];
67 int16_t* array_interleaved_;
68 };
69
70 // Create and destroy AudioMultiVector objects, both empty and with a predefined
71 // length.
TEST_P(AudioMultiVectorTest,CreateAndDestroy)72 TEST_P(AudioMultiVectorTest, CreateAndDestroy) {
73 AudioMultiVector vec1(num_channels_);
74 EXPECT_TRUE(vec1.Empty());
75 EXPECT_EQ(num_channels_, vec1.Channels());
76 EXPECT_EQ(0u, vec1.Size());
77
78 size_t initial_size = 17;
79 AudioMultiVector vec2(num_channels_, initial_size);
80 EXPECT_FALSE(vec2.Empty());
81 EXPECT_EQ(num_channels_, vec2.Channels());
82 EXPECT_EQ(initial_size, vec2.Size());
83 }
84
85 // Test the subscript operator [] for getting and setting.
TEST_P(AudioMultiVectorTest,SubscriptOperator)86 TEST_P(AudioMultiVectorTest, SubscriptOperator) {
87 AudioMultiVector vec(num_channels_, array_length());
88 for (size_t channel = 0; channel < num_channels_; ++channel) {
89 for (size_t i = 0; i < array_length(); ++i) {
90 vec[channel][i] = static_cast<int16_t>(i);
91 // Make sure to use the const version.
92 const AudioVector& audio_vec = vec[channel];
93 EXPECT_EQ(static_cast<int16_t>(i), audio_vec[i]);
94 }
95 }
96 }
97
98 // Test the PushBackInterleaved method and the CopyFrom method. The Clear
99 // method is also invoked.
TEST_P(AudioMultiVectorTest,PushBackInterleavedAndCopy)100 TEST_P(AudioMultiVectorTest, PushBackInterleavedAndCopy) {
101 AudioMultiVector vec(num_channels_);
102 vec.PushBackInterleaved(array_interleaved_, interleaved_length_);
103 AudioMultiVector vec_copy(num_channels_);
104 vec.CopyTo(&vec_copy); // Copy from |vec| to |vec_copy|.
105 ASSERT_EQ(num_channels_, vec.Channels());
106 ASSERT_EQ(array_length(), vec.Size());
107 ASSERT_EQ(num_channels_, vec_copy.Channels());
108 ASSERT_EQ(array_length(), vec_copy.Size());
109 for (size_t channel = 0; channel < vec.Channels(); ++channel) {
110 for (size_t i = 0; i < array_length(); ++i) {
111 EXPECT_EQ(static_cast<int16_t>((channel + 1) * 100 + i), vec[channel][i]);
112 EXPECT_EQ(vec[channel][i], vec_copy[channel][i]);
113 }
114 }
115
116 // Clear |vec| and verify that it is empty.
117 vec.Clear();
118 EXPECT_TRUE(vec.Empty());
119
120 // Now copy the empty vector and verify that the copy becomes empty too.
121 vec.CopyTo(&vec_copy);
122 EXPECT_TRUE(vec_copy.Empty());
123 }
124
125 // Try to copy to a NULL pointer. Nothing should happen.
TEST_P(AudioMultiVectorTest,CopyToNull)126 TEST_P(AudioMultiVectorTest, CopyToNull) {
127 AudioMultiVector vec(num_channels_);
128 AudioMultiVector* vec_copy = NULL;
129 vec.PushBackInterleaved(array_interleaved_, interleaved_length_);
130 vec.CopyTo(vec_copy);
131 }
132
133 // Test the PushBack method with another AudioMultiVector as input argument.
TEST_P(AudioMultiVectorTest,PushBackVector)134 TEST_P(AudioMultiVectorTest, PushBackVector) {
135 AudioMultiVector vec1(num_channels_, array_length());
136 AudioMultiVector vec2(num_channels_, array_length());
137 // Set the first vector to [0, 1, ..., array_length() - 1] +
138 // 100 * channel_number.
139 // Set the second vector to [array_length(), array_length() + 1, ...,
140 // 2 * array_length() - 1] + 100 * channel_number.
141 for (size_t channel = 0; channel < num_channels_; ++channel) {
142 for (size_t i = 0; i < array_length(); ++i) {
143 vec1[channel][i] = static_cast<int16_t>(i + 100 * channel);
144 vec2[channel][i] =
145 static_cast<int16_t>(i + 100 * channel + array_length());
146 }
147 }
148 // Append vec2 to the back of vec1.
149 vec1.PushBack(vec2);
150 ASSERT_EQ(2u * array_length(), vec1.Size());
151 for (size_t channel = 0; channel < num_channels_; ++channel) {
152 for (size_t i = 0; i < 2 * array_length(); ++i) {
153 EXPECT_EQ(static_cast<int16_t>(i + 100 * channel), vec1[channel][i]);
154 }
155 }
156 }
157
158 // Test the PushBackFromIndex method.
TEST_P(AudioMultiVectorTest,PushBackFromIndex)159 TEST_P(AudioMultiVectorTest, PushBackFromIndex) {
160 AudioMultiVector vec1(num_channels_);
161 vec1.PushBackInterleaved(array_interleaved_, interleaved_length_);
162 AudioMultiVector vec2(num_channels_);
163
164 // Append vec1 to the back of vec2 (which is empty). Read vec1 from the second
165 // last element.
166 vec2.PushBackFromIndex(vec1, array_length() - 2);
167 ASSERT_EQ(2u, vec2.Size());
168 for (size_t channel = 0; channel < num_channels_; ++channel) {
169 for (size_t i = 0; i < 2; ++i) {
170 EXPECT_EQ(array_interleaved_[channel + num_channels_ *
171 (array_length() - 2 + i)], vec2[channel][i]);
172 }
173 }
174 }
175
176 // Starts with pushing some values to the vector, then test the Zeros method.
TEST_P(AudioMultiVectorTest,Zeros)177 TEST_P(AudioMultiVectorTest, Zeros) {
178 AudioMultiVector vec(num_channels_);
179 vec.PushBackInterleaved(array_interleaved_, interleaved_length_);
180 vec.Zeros(2 * array_length());
181 ASSERT_EQ(num_channels_, vec.Channels());
182 ASSERT_EQ(2u * array_length(), vec.Size());
183 for (size_t channel = 0; channel < num_channels_; ++channel) {
184 for (size_t i = 0; i < 2 * array_length(); ++i) {
185 EXPECT_EQ(0, vec[channel][i]);
186 }
187 }
188 }
189
190 // Test the ReadInterleaved method
TEST_P(AudioMultiVectorTest,ReadInterleaved)191 TEST_P(AudioMultiVectorTest, ReadInterleaved) {
192 AudioMultiVector vec(num_channels_);
193 vec.PushBackInterleaved(array_interleaved_, interleaved_length_);
194 int16_t* output = new int16_t[interleaved_length_];
195 // Read 5 samples.
196 size_t read_samples = 5;
197 EXPECT_EQ(num_channels_ * read_samples,
198 vec.ReadInterleaved(read_samples, output));
199 EXPECT_EQ(0,
200 memcmp(array_interleaved_, output, read_samples * sizeof(int16_t)));
201
202 // Read too many samples. Expect to get all samples from the vector.
203 EXPECT_EQ(interleaved_length_,
204 vec.ReadInterleaved(array_length() + 1, output));
205 EXPECT_EQ(0,
206 memcmp(array_interleaved_, output, read_samples * sizeof(int16_t)));
207
208 delete [] output;
209 }
210
211 // Try to read to a NULL pointer. Expected to return 0.
TEST_P(AudioMultiVectorTest,ReadInterleavedToNull)212 TEST_P(AudioMultiVectorTest, ReadInterleavedToNull) {
213 AudioMultiVector vec(num_channels_);
214 vec.PushBackInterleaved(array_interleaved_, interleaved_length_);
215 int16_t* output = NULL;
216 // Read 5 samples.
217 size_t read_samples = 5;
218 EXPECT_EQ(0u, vec.ReadInterleaved(read_samples, output));
219 }
220
221 // Test the PopFront method.
TEST_P(AudioMultiVectorTest,PopFront)222 TEST_P(AudioMultiVectorTest, PopFront) {
223 AudioMultiVector vec(num_channels_);
224 vec.PushBackInterleaved(array_interleaved_, interleaved_length_);
225 vec.PopFront(1); // Remove one element from each channel.
226 ASSERT_EQ(array_length() - 1u, vec.Size());
227 // Let |ptr| point to the second element of the first channel in the
228 // interleaved array.
229 int16_t* ptr = &array_interleaved_[num_channels_];
230 for (size_t i = 0; i < array_length() - 1; ++i) {
231 for (size_t channel = 0; channel < num_channels_; ++channel) {
232 EXPECT_EQ(*ptr, vec[channel][i]);
233 ++ptr;
234 }
235 }
236 vec.PopFront(array_length()); // Remove more elements than vector size.
237 EXPECT_EQ(0u, vec.Size());
238 }
239
240 // Test the PopBack method.
TEST_P(AudioMultiVectorTest,PopBack)241 TEST_P(AudioMultiVectorTest, PopBack) {
242 AudioMultiVector vec(num_channels_);
243 vec.PushBackInterleaved(array_interleaved_, interleaved_length_);
244 vec.PopBack(1); // Remove one element from each channel.
245 ASSERT_EQ(array_length() - 1u, vec.Size());
246 // Let |ptr| point to the first element of the first channel in the
247 // interleaved array.
248 int16_t* ptr = array_interleaved_;
249 for (size_t i = 0; i < array_length() - 1; ++i) {
250 for (size_t channel = 0; channel < num_channels_; ++channel) {
251 EXPECT_EQ(*ptr, vec[channel][i]);
252 ++ptr;
253 }
254 }
255 vec.PopBack(array_length()); // Remove more elements than vector size.
256 EXPECT_EQ(0u, vec.Size());
257 }
258
259 // Test the AssertSize method.
TEST_P(AudioMultiVectorTest,AssertSize)260 TEST_P(AudioMultiVectorTest, AssertSize) {
261 AudioMultiVector vec(num_channels_, array_length());
262 EXPECT_EQ(array_length(), vec.Size());
263 // Start with asserting with smaller sizes than already allocated.
264 vec.AssertSize(0);
265 vec.AssertSize(array_length() - 1);
266 // Nothing should have changed.
267 EXPECT_EQ(array_length(), vec.Size());
268 // Assert with one element longer than already allocated.
269 vec.AssertSize(array_length() + 1);
270 // Expect vector to have grown.
271 EXPECT_EQ(array_length() + 1, vec.Size());
272 // Also check the individual AudioVectors.
273 for (size_t channel = 0; channel < vec.Channels(); ++channel) {
274 EXPECT_EQ(array_length() + 1u, vec[channel].Size());
275 }
276 }
277
278 // Test the PushBack method with another AudioMultiVector as input argument.
TEST_P(AudioMultiVectorTest,OverwriteAt)279 TEST_P(AudioMultiVectorTest, OverwriteAt) {
280 AudioMultiVector vec1(num_channels_);
281 vec1.PushBackInterleaved(array_interleaved_, interleaved_length_);
282 AudioMultiVector vec2(num_channels_);
283 vec2.Zeros(3); // 3 zeros in each channel.
284 // Overwrite vec2 at position 5.
285 vec1.OverwriteAt(vec2, 3, 5);
286 // Verify result.
287 // Length remains the same.
288 ASSERT_EQ(array_length(), vec1.Size());
289 int16_t* ptr = array_interleaved_;
290 for (size_t i = 0; i < array_length() - 1; ++i) {
291 for (size_t channel = 0; channel < num_channels_; ++channel) {
292 if (i >= 5 && i <= 7) {
293 // Elements 5, 6, 7 should have been replaced with zeros.
294 EXPECT_EQ(0, vec1[channel][i]);
295 } else {
296 EXPECT_EQ(*ptr, vec1[channel][i]);
297 }
298 ++ptr;
299 }
300 }
301 }
302
303 // Test the CopyChannel method, when the test is instantiated with at least two
304 // channels.
TEST_P(AudioMultiVectorTest,CopyChannel)305 TEST_P(AudioMultiVectorTest, CopyChannel) {
306 if (num_channels_ < 2)
307 return;
308
309 AudioMultiVector vec(num_channels_);
310 vec.PushBackInterleaved(array_interleaved_, interleaved_length_);
311 // Create a reference copy.
312 AudioMultiVector ref(num_channels_);
313 ref.PushBack(vec);
314 // Copy from first to last channel.
315 vec.CopyChannel(0, num_channels_ - 1);
316 // Verify that the first and last channels are identical; the others should
317 // be left untouched.
318 for (size_t i = 0; i < array_length(); ++i) {
319 // Verify that all but the last channel are untouched.
320 for (size_t channel = 0; channel < num_channels_ - 1; ++channel) {
321 EXPECT_EQ(ref[channel][i], vec[channel][i]);
322 }
323 // Verify that the last and the first channels are identical.
324 EXPECT_EQ(vec[0][i], vec[num_channels_ - 1][i]);
325 }
326 }
327
328 INSTANTIATE_TEST_CASE_P(TestNumChannels,
329 AudioMultiVectorTest,
330 ::testing::Values(static_cast<size_t>(1),
331 static_cast<size_t>(2),
332 static_cast<size_t>(5)));
333 } // namespace webrtc
334