blob: d981ccb7cd616811acedf84bb9a42035a712071d [file] [log] [blame]
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +00001/*
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/neteq4/audio_multi_vector.h"
12
13#include <assert.h>
14#include <stdlib.h>
15
16#include <string>
17
18#include "gtest/gtest.h"
19#include "webrtc/typedefs.h"
20
21namespace 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.
pbos@webrtc.org98b20112013-05-07 12:36:21 +000030
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +000031class AudioMultiVectorTest : public ::testing::TestWithParam<size_t> {
32 protected:
33 typedef int16_t T; // Use this value type for all tests.
34
35 AudioMultiVectorTest()
36 : num_channels_(GetParam()), // Get the test parameter.
pbos@webrtc.org98b20112013-05-07 12:36:21 +000037 interleaved_length_(num_channels_ * array_length()) {
38 array_interleaved_ = new T[num_channels_ * array_length()];
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +000039 }
40
41 ~AudioMultiVectorTest() {
42 delete [] array_interleaved_;
43 }
44
45 virtual void SetUp() {
46 // Populate test arrays.
pbos@webrtc.org98b20112013-05-07 12:36:21 +000047 for (size_t i = 0; i < array_length(); ++i) {
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +000048 array_[i] = static_cast<T>(i);
49 }
50 T* ptr = array_interleaved_;
51 // Write 100, 101, 102, ... for first channel.
52 // Write 200, 201, 202, ... for second channel.
53 // And so on.
pbos@webrtc.org98b20112013-05-07 12:36:21 +000054 for (size_t i = 0; i < array_length(); ++i) {
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +000055 for (size_t j = 1; j <= num_channels_; ++j) {
56 *ptr = j * 100 + i;
57 ++ptr;
58 }
59 }
60 }
61
pbos@webrtc.org98b20112013-05-07 12:36:21 +000062 size_t array_length() const {
63 return sizeof(array_) / sizeof(array_[0]);
64 }
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +000065
66 const size_t num_channels_;
67 size_t interleaved_length_;
pbos@webrtc.org98b20112013-05-07 12:36:21 +000068 T array_[10];
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +000069 T* array_interleaved_;
70};
71
72// Create and destroy AudioMultiVector objects, both empty and with a predefined
73// length.
74TEST_P(AudioMultiVectorTest, CreateAndDestroy) {
75 AudioMultiVector<T> vec1(num_channels_);
76 EXPECT_TRUE(vec1.Empty());
77 EXPECT_EQ(num_channels_, vec1.Channels());
78 EXPECT_EQ(0u, vec1.Size());
79
80 size_t initial_size = 17;
81 AudioMultiVector<T> vec2(num_channels_, initial_size);
82 EXPECT_FALSE(vec2.Empty());
83 EXPECT_EQ(num_channels_, vec2.Channels());
84 EXPECT_EQ(initial_size, vec2.Size());
85}
86
87// Test the subscript operator [] for getting and setting.
88TEST_P(AudioMultiVectorTest, SubscriptOperator) {
pbos@webrtc.org98b20112013-05-07 12:36:21 +000089 AudioMultiVector<T> vec(num_channels_, array_length());
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +000090 for (size_t channel = 0; channel < num_channels_; ++channel) {
pbos@webrtc.org98b20112013-05-07 12:36:21 +000091 for (size_t i = 0; i < array_length(); ++i) {
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +000092 vec[channel][i] = static_cast<T>(i);
93 // Make sure to use the const version.
94 const AudioVector<T>& audio_vec = vec[channel];
95 EXPECT_EQ(static_cast<T>(i), audio_vec[i]);
96 }
97 }
98}
99
100// Test the PushBackInterleaved method and the CopyFrom method. The Clear
101// method is also invoked.
102TEST_P(AudioMultiVectorTest, PushBackInterleavedAndCopy) {
103 AudioMultiVector<T> vec(num_channels_);
104 vec.PushBackInterleaved(array_interleaved_, interleaved_length_);
105 AudioMultiVector<T> vec_copy(num_channels_);
106 vec.CopyFrom(&vec_copy); // Copy from |vec| to |vec_copy|.
107 ASSERT_EQ(num_channels_, vec.Channels());
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000108 ASSERT_EQ(array_length(), vec.Size());
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000109 ASSERT_EQ(num_channels_, vec_copy.Channels());
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000110 ASSERT_EQ(array_length(), vec_copy.Size());
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000111 for (size_t channel = 0; channel < vec.Channels(); ++channel) {
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000112 for (size_t i = 0; i < array_length(); ++i) {
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000113 EXPECT_EQ(static_cast<T>((channel + 1) * 100 + i), vec[channel][i]);
114 EXPECT_EQ(vec[channel][i], vec_copy[channel][i]);
115 }
116 }
117
118 // Clear |vec| and verify that it is empty.
119 vec.Clear();
120 EXPECT_TRUE(vec.Empty());
121
122 // Now copy the empty vector and verify that the copy becomes empty too.
123 vec.CopyFrom(&vec_copy);
124 EXPECT_TRUE(vec_copy.Empty());
125}
126
127// Try to copy to a NULL pointer. Nothing should happen.
128TEST_P(AudioMultiVectorTest, CopyToNull) {
129 AudioMultiVector<T> vec(num_channels_);
130 AudioMultiVector<T>* vec_copy = NULL;
131 vec.PushBackInterleaved(array_interleaved_, interleaved_length_);
132 vec.CopyFrom(vec_copy);
133}
134
135// Test the PushBack method with another AudioMultiVector as input argument.
136TEST_P(AudioMultiVectorTest, PushBackVector) {
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000137 AudioMultiVector<T> vec1(num_channels_, array_length());
138 AudioMultiVector<T> vec2(num_channels_, array_length());
139 // Set the first vector to [0, 1, ..., array_length() - 1] +
140 // 100 * channel_number.
141 // Set the second vector to [array_length(), array_length() + 1, ...,
142 // 2 * array_length() - 1] + 100 * channel_number.
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000143 for (size_t channel = 0; channel < num_channels_; ++channel) {
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000144 for (size_t i = 0; i < array_length(); ++i) {
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000145 vec1[channel][i] = static_cast<T>(i + 100 * channel);
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000146 vec2[channel][i] = static_cast<T>(i + 100 * channel + array_length());
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000147 }
148 }
149 // Append vec2 to the back of vec1.
150 vec1.PushBack(vec2);
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000151 ASSERT_EQ(2u * array_length(), vec1.Size());
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000152 for (size_t channel = 0; channel < num_channels_; ++channel) {
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000153 for (size_t i = 0; i < 2 * array_length(); ++i) {
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000154 EXPECT_EQ(static_cast<T>(i + 100 * channel), vec1[channel][i]);
155 }
156 }
157}
158
159// Test the PushBackFromIndex method.
160TEST_P(AudioMultiVectorTest, PushBackFromIndex) {
161 AudioMultiVector<T> vec1(num_channels_);
162 vec1.PushBackInterleaved(array_interleaved_, interleaved_length_);
163 AudioMultiVector<T> vec2(num_channels_);
164
165 // Append vec1 to the back of vec2 (which is empty). Read vec1 from the second
166 // last element.
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000167 vec2.PushBackFromIndex(vec1, array_length() - 2);
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000168 ASSERT_EQ(2u, vec2.Size());
169 for (size_t channel = 0; channel < num_channels_; ++channel) {
170 for (size_t i = 0; i < 2; ++i) {
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000171 EXPECT_EQ(array_interleaved_[channel + num_channels_ *
172 (array_length() - 2 + i)], vec2[channel][i]);
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000173 }
174 }
175}
176
177// Starts with pushing some values to the vector, then test the Zeros method.
178TEST_P(AudioMultiVectorTest, Zeros) {
179 AudioMultiVector<T> vec(num_channels_);
180 vec.PushBackInterleaved(array_interleaved_, interleaved_length_);
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000181 vec.Zeros(2 * array_length());
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000182 ASSERT_EQ(num_channels_, vec.Channels());
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000183 ASSERT_EQ(2u * array_length(), vec.Size());
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000184 for (size_t channel = 0; channel < num_channels_; ++channel) {
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000185 for (size_t i = 0; i < 2 * array_length(); ++i) {
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000186 EXPECT_EQ(0, vec[channel][i]);
187 }
188 }
189}
190
191// Test the ReadInterleaved method
192TEST_P(AudioMultiVectorTest, ReadInterleaved) {
193 AudioMultiVector<T> vec(num_channels_);
194 vec.PushBackInterleaved(array_interleaved_, interleaved_length_);
195 T* output = new T[interleaved_length_];
196 // Read 5 samples.
197 size_t read_samples = 5;
198 EXPECT_EQ(num_channels_ * read_samples,
199 vec.ReadInterleaved(read_samples, output));
200 EXPECT_EQ(0, memcmp(array_interleaved_, output, read_samples * sizeof(T)));
201
202 // Read too many samples. Expect to get all samples from the vector.
203 EXPECT_EQ(interleaved_length_,
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000204 vec.ReadInterleaved(array_length() + 1, output));
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000205 EXPECT_EQ(0, memcmp(array_interleaved_, output, read_samples * sizeof(T)));
206
207 delete [] output;
208}
209
210// Try to read to a NULL pointer. Expected to return 0.
211TEST_P(AudioMultiVectorTest, ReadInterleavedToNull) {
212 AudioMultiVector<T> vec(num_channels_);
213 vec.PushBackInterleaved(array_interleaved_, interleaved_length_);
214 T* output = NULL;
215 // Read 5 samples.
216 size_t read_samples = 5;
217 EXPECT_EQ(0u, vec.ReadInterleaved(read_samples, output));
218}
219
220// Test the PopFront method.
221TEST_P(AudioMultiVectorTest, PopFront) {
222 AudioMultiVector<T> vec(num_channels_);
223 vec.PushBackInterleaved(array_interleaved_, interleaved_length_);
224 vec.PopFront(1); // Remove one element from each channel.
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000225 ASSERT_EQ(array_length() - 1u, vec.Size());
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000226 // Let |ptr| point to the second element of the first channel in the
227 // interleaved array.
228 T* ptr = &array_interleaved_[num_channels_];
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000229 for (size_t i = 0; i < array_length() - 1; ++i) {
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000230 for (size_t channel = 0; channel < num_channels_; ++channel) {
231 EXPECT_EQ(*ptr, vec[channel][i]);
232 ++ptr;
233 }
234 }
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000235 vec.PopFront(array_length()); // Remove more elements than vector size.
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000236 EXPECT_EQ(0u, vec.Size());
237}
238
239// Test the PopBack method.
240TEST_P(AudioMultiVectorTest, PopBack) {
241 AudioMultiVector<T> vec(num_channels_);
242 vec.PushBackInterleaved(array_interleaved_, interleaved_length_);
243 vec.PopBack(1); // Remove one element from each channel.
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000244 ASSERT_EQ(array_length() - 1u, vec.Size());
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000245 // Let |ptr| point to the first element of the first channel in the
246 // interleaved array.
247 T* ptr = array_interleaved_;
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000248 for (size_t i = 0; i < array_length() - 1; ++i) {
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000249 for (size_t channel = 0; channel < num_channels_; ++channel) {
250 EXPECT_EQ(*ptr, vec[channel][i]);
251 ++ptr;
252 }
253 }
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000254 vec.PopBack(array_length()); // Remove more elements than vector size.
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000255 EXPECT_EQ(0u, vec.Size());
256}
257
258// Test the AssertSize method.
259TEST_P(AudioMultiVectorTest, AssertSize) {
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000260 AudioMultiVector<T> vec(num_channels_, array_length());
261 EXPECT_EQ(array_length(), vec.Size());
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000262 // Start with asserting with smaller sizes than already allocated.
263 vec.AssertSize(0);
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000264 vec.AssertSize(array_length() - 1);
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000265 // Nothing should have changed.
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000266 EXPECT_EQ(array_length(), vec.Size());
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000267 // Assert with one element longer than already allocated.
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000268 vec.AssertSize(array_length() + 1);
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000269 // Expect vector to have grown.
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000270 EXPECT_EQ(array_length() + 1, vec.Size());
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000271 // Also check the individual AudioVectors.
272 for (size_t channel = 0; channel < vec.Channels(); ++channel) {
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000273 EXPECT_EQ(array_length() + 1u, vec[channel].Size());
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000274 }
275}
276
277// Test the PushBack method with another AudioMultiVector as input argument.
278TEST_P(AudioMultiVectorTest, OverwriteAt) {
279 AudioMultiVector<T> vec1(num_channels_);
280 vec1.PushBackInterleaved(array_interleaved_, interleaved_length_);
281 AudioMultiVector<T> vec2(num_channels_);
282 vec2.Zeros(3); // 3 zeros in each channel.
283 // Overwrite vec2 at position 5.
284 vec1.OverwriteAt(vec2, 3, 5);
285 // Verify result.
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000286 // Length remains the same.
287 ASSERT_EQ(array_length(), vec1.Size());
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000288 T* ptr = array_interleaved_;
pbos@webrtc.org98b20112013-05-07 12:36:21 +0000289 for (size_t i = 0; i < array_length() - 1; ++i) {
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000290 for (size_t channel = 0; channel < num_channels_; ++channel) {
291 if (i >= 5 && i <= 7) {
292 // Elements 5, 6, 7 should have been replaced with zeros.
293 EXPECT_EQ(0, vec1[channel][i]);
294 } else {
295 EXPECT_EQ(*ptr, vec1[channel][i]);
296 }
297 ++ptr;
298 }
299 }
300}
301
302INSTANTIATE_TEST_CASE_P(TestNumChannels,
303 AudioMultiVectorTest,
304 ::testing::Values(static_cast<size_t>(1),
305 static_cast<size_t>(2),
306 static_cast<size_t>(5)));
307} // namespace webrtc