blob: d1351d821015010033918b498d0816b62b79adfa [file] [log] [blame]
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:211/*
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
Mirko Bonadei92ea95e2017-09-15 04:47:3111#include "modules/audio_coding/neteq/audio_multi_vector.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2112
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2113#include <stdlib.h>
14
15#include <string>
Henrik Lundin00eb12a2018-09-05 16:14:5216#include <vector>
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2117
Karl Wiberge40468b2017-11-22 09:42:2618#include "rtc_base/numerics/safe_conversions.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3119#include "test/gtest.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2120
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.org3004c792013-05-07 12:36:2130
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2131class AudioMultiVectorTest : public ::testing::TestWithParam<size_t> {
32 protected:
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2133 AudioMultiVectorTest()
34 : num_channels_(GetParam()), // Get the test parameter.
Henrik Lundin00eb12a2018-09-05 16:14:5235 array_interleaved_(num_channels_ * array_length()) {}
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2136
Henrik Lundin00eb12a2018-09-05 16:14:5237 ~AudioMultiVectorTest() = default;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2138
39 virtual void SetUp() {
40 // Populate test arrays.
pbos@webrtc.org3004c792013-05-07 12:36:2141 for (size_t i = 0; i < array_length(); ++i) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:4442 array_[i] = static_cast<int16_t>(i);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2143 }
Henrik Lundin00eb12a2018-09-05 16:14:5244 int16_t* ptr = array_interleaved_.data();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2145 // Write 100, 101, 102, ... for first channel.
46 // Write 200, 201, 202, ... for second channel.
47 // And so on.
pbos@webrtc.org3004c792013-05-07 12:36:2148 for (size_t i = 0; i < array_length(); ++i) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2149 for (size_t j = 1; j <= num_channels_; ++j) {
Mirko Bonadei737e0732017-10-19 07:00:1750 *ptr = rtc::checked_cast<int16_t>(j * 100 + i);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2151 ++ptr;
52 }
53 }
54 }
55
Yves Gerey665174f2018-06-19 13:03:0556 size_t array_length() const { return sizeof(array_) / sizeof(array_[0]); }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2157
58 const size_t num_channels_;
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:4459 int16_t array_[10];
Henrik Lundin00eb12a2018-09-05 16:14:5260 std::vector<int16_t> array_interleaved_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2161};
62
63// Create and destroy AudioMultiVector objects, both empty and with a predefined
64// length.
65TEST_P(AudioMultiVectorTest, CreateAndDestroy) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:4466 AudioMultiVector vec1(num_channels_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2167 EXPECT_TRUE(vec1.Empty());
68 EXPECT_EQ(num_channels_, vec1.Channels());
69 EXPECT_EQ(0u, vec1.Size());
70
71 size_t initial_size = 17;
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:4472 AudioMultiVector vec2(num_channels_, initial_size);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2173 EXPECT_FALSE(vec2.Empty());
74 EXPECT_EQ(num_channels_, vec2.Channels());
75 EXPECT_EQ(initial_size, vec2.Size());
76}
77
78// Test the subscript operator [] for getting and setting.
79TEST_P(AudioMultiVectorTest, SubscriptOperator) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:4480 AudioMultiVector vec(num_channels_, array_length());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2181 for (size_t channel = 0; channel < num_channels_; ++channel) {
pbos@webrtc.org3004c792013-05-07 12:36:2182 for (size_t i = 0; i < array_length(); ++i) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:4483 vec[channel][i] = static_cast<int16_t>(i);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2184 // Make sure to use the const version.
henrik.lundin@webrtc.org1871dd22013-10-14 20:33:2585 const AudioVector& audio_vec = vec[channel];
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:4486 EXPECT_EQ(static_cast<int16_t>(i), audio_vec[i]);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2187 }
88 }
89}
90
91// Test the PushBackInterleaved method and the CopyFrom method. The Clear
92// method is also invoked.
93TEST_P(AudioMultiVectorTest, PushBackInterleavedAndCopy) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:4494 AudioMultiVector vec(num_channels_);
Henrik Lundin00eb12a2018-09-05 16:14:5295 vec.PushBackInterleaved(array_interleaved_);
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:4496 AudioMultiVector vec_copy(num_channels_);
henrik.lundin@webrtc.orgf6ab6f82014-09-04 10:58:4397 vec.CopyTo(&vec_copy); // Copy from |vec| to |vec_copy|.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2198 ASSERT_EQ(num_channels_, vec.Channels());
pbos@webrtc.org3004c792013-05-07 12:36:2199 ASSERT_EQ(array_length(), vec.Size());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21100 ASSERT_EQ(num_channels_, vec_copy.Channels());
pbos@webrtc.org3004c792013-05-07 12:36:21101 ASSERT_EQ(array_length(), vec_copy.Size());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21102 for (size_t channel = 0; channel < vec.Channels(); ++channel) {
pbos@webrtc.org3004c792013-05-07 12:36:21103 for (size_t i = 0; i < array_length(); ++i) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44104 EXPECT_EQ(static_cast<int16_t>((channel + 1) * 100 + i), vec[channel][i]);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21105 EXPECT_EQ(vec[channel][i], vec_copy[channel][i]);
106 }
107 }
108
109 // Clear |vec| and verify that it is empty.
110 vec.Clear();
111 EXPECT_TRUE(vec.Empty());
112
113 // Now copy the empty vector and verify that the copy becomes empty too.
henrik.lundin@webrtc.orgf6ab6f82014-09-04 10:58:43114 vec.CopyTo(&vec_copy);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21115 EXPECT_TRUE(vec_copy.Empty());
116}
117
118// Try to copy to a NULL pointer. Nothing should happen.
119TEST_P(AudioMultiVectorTest, CopyToNull) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44120 AudioMultiVector vec(num_channels_);
121 AudioMultiVector* vec_copy = NULL;
Henrik Lundin00eb12a2018-09-05 16:14:52122 vec.PushBackInterleaved(array_interleaved_);
henrik.lundin@webrtc.orgf6ab6f82014-09-04 10:58:43123 vec.CopyTo(vec_copy);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21124}
125
126// Test the PushBack method with another AudioMultiVector as input argument.
127TEST_P(AudioMultiVectorTest, PushBackVector) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44128 AudioMultiVector vec1(num_channels_, array_length());
129 AudioMultiVector vec2(num_channels_, array_length());
pbos@webrtc.org3004c792013-05-07 12:36:21130 // Set the first vector to [0, 1, ..., array_length() - 1] +
131 // 100 * channel_number.
132 // Set the second vector to [array_length(), array_length() + 1, ...,
133 // 2 * array_length() - 1] + 100 * channel_number.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21134 for (size_t channel = 0; channel < num_channels_; ++channel) {
pbos@webrtc.org3004c792013-05-07 12:36:21135 for (size_t i = 0; i < array_length(); ++i) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44136 vec1[channel][i] = static_cast<int16_t>(i + 100 * channel);
137 vec2[channel][i] =
138 static_cast<int16_t>(i + 100 * channel + array_length());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21139 }
140 }
141 // Append vec2 to the back of vec1.
142 vec1.PushBack(vec2);
pbos@webrtc.org3004c792013-05-07 12:36:21143 ASSERT_EQ(2u * array_length(), vec1.Size());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21144 for (size_t channel = 0; channel < num_channels_; ++channel) {
pbos@webrtc.org3004c792013-05-07 12:36:21145 for (size_t i = 0; i < 2 * array_length(); ++i) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44146 EXPECT_EQ(static_cast<int16_t>(i + 100 * channel), vec1[channel][i]);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21147 }
148 }
149}
150
151// Test the PushBackFromIndex method.
152TEST_P(AudioMultiVectorTest, PushBackFromIndex) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44153 AudioMultiVector vec1(num_channels_);
Henrik Lundin00eb12a2018-09-05 16:14:52154 vec1.PushBackInterleaved(array_interleaved_);
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44155 AudioMultiVector vec2(num_channels_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21156
157 // Append vec1 to the back of vec2 (which is empty). Read vec1 from the second
158 // last element.
pbos@webrtc.org3004c792013-05-07 12:36:21159 vec2.PushBackFromIndex(vec1, array_length() - 2);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21160 ASSERT_EQ(2u, vec2.Size());
161 for (size_t channel = 0; channel < num_channels_; ++channel) {
162 for (size_t i = 0; i < 2; ++i) {
Yves Gerey665174f2018-06-19 13:03:05163 EXPECT_EQ(array_interleaved_[channel +
164 num_channels_ * (array_length() - 2 + i)],
165 vec2[channel][i]);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21166 }
167 }
168}
169
170// Starts with pushing some values to the vector, then test the Zeros method.
171TEST_P(AudioMultiVectorTest, Zeros) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44172 AudioMultiVector vec(num_channels_);
Henrik Lundin00eb12a2018-09-05 16:14:52173 vec.PushBackInterleaved(array_interleaved_);
pbos@webrtc.org3004c792013-05-07 12:36:21174 vec.Zeros(2 * array_length());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21175 ASSERT_EQ(num_channels_, vec.Channels());
pbos@webrtc.org3004c792013-05-07 12:36:21176 ASSERT_EQ(2u * array_length(), vec.Size());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21177 for (size_t channel = 0; channel < num_channels_; ++channel) {
pbos@webrtc.org3004c792013-05-07 12:36:21178 for (size_t i = 0; i < 2 * array_length(); ++i) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21179 EXPECT_EQ(0, vec[channel][i]);
180 }
181 }
182}
183
184// Test the ReadInterleaved method
185TEST_P(AudioMultiVectorTest, ReadInterleaved) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44186 AudioMultiVector vec(num_channels_);
Henrik Lundin00eb12a2018-09-05 16:14:52187 vec.PushBackInterleaved(array_interleaved_);
188 int16_t* output = new int16_t[array_interleaved_.size()];
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21189 // Read 5 samples.
190 size_t read_samples = 5;
191 EXPECT_EQ(num_channels_ * read_samples,
192 vec.ReadInterleaved(read_samples, output));
Henrik Lundin00eb12a2018-09-05 16:14:52193 EXPECT_EQ(0, memcmp(array_interleaved_.data(), output,
194 read_samples * sizeof(int16_t)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21195
196 // Read too many samples. Expect to get all samples from the vector.
Henrik Lundin00eb12a2018-09-05 16:14:52197 EXPECT_EQ(array_interleaved_.size(),
pbos@webrtc.org3004c792013-05-07 12:36:21198 vec.ReadInterleaved(array_length() + 1, output));
Henrik Lundin00eb12a2018-09-05 16:14:52199 EXPECT_EQ(0, memcmp(array_interleaved_.data(), output,
200 read_samples * sizeof(int16_t)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21201
Yves Gerey665174f2018-06-19 13:03:05202 delete[] output;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21203}
204
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21205// Test the PopFront method.
206TEST_P(AudioMultiVectorTest, PopFront) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44207 AudioMultiVector vec(num_channels_);
Henrik Lundin00eb12a2018-09-05 16:14:52208 vec.PushBackInterleaved(array_interleaved_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21209 vec.PopFront(1); // Remove one element from each channel.
pbos@webrtc.org3004c792013-05-07 12:36:21210 ASSERT_EQ(array_length() - 1u, vec.Size());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21211 // Let |ptr| point to the second element of the first channel in the
212 // interleaved array.
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44213 int16_t* ptr = &array_interleaved_[num_channels_];
pbos@webrtc.org3004c792013-05-07 12:36:21214 for (size_t i = 0; i < array_length() - 1; ++i) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21215 for (size_t channel = 0; channel < num_channels_; ++channel) {
216 EXPECT_EQ(*ptr, vec[channel][i]);
217 ++ptr;
218 }
219 }
pbos@webrtc.org3004c792013-05-07 12:36:21220 vec.PopFront(array_length()); // Remove more elements than vector size.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21221 EXPECT_EQ(0u, vec.Size());
222}
223
224// Test the PopBack method.
225TEST_P(AudioMultiVectorTest, PopBack) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44226 AudioMultiVector vec(num_channels_);
Henrik Lundin00eb12a2018-09-05 16:14:52227 vec.PushBackInterleaved(array_interleaved_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21228 vec.PopBack(1); // Remove one element from each channel.
pbos@webrtc.org3004c792013-05-07 12:36:21229 ASSERT_EQ(array_length() - 1u, vec.Size());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21230 // Let |ptr| point to the first element of the first channel in the
231 // interleaved array.
Henrik Lundin00eb12a2018-09-05 16:14:52232 int16_t* ptr = array_interleaved_.data();
pbos@webrtc.org3004c792013-05-07 12:36:21233 for (size_t i = 0; i < array_length() - 1; ++i) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21234 for (size_t channel = 0; channel < num_channels_; ++channel) {
235 EXPECT_EQ(*ptr, vec[channel][i]);
236 ++ptr;
237 }
238 }
pbos@webrtc.org3004c792013-05-07 12:36:21239 vec.PopBack(array_length()); // Remove more elements than vector size.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21240 EXPECT_EQ(0u, vec.Size());
241}
242
243// Test the AssertSize method.
244TEST_P(AudioMultiVectorTest, AssertSize) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44245 AudioMultiVector vec(num_channels_, array_length());
pbos@webrtc.org3004c792013-05-07 12:36:21246 EXPECT_EQ(array_length(), vec.Size());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21247 // Start with asserting with smaller sizes than already allocated.
248 vec.AssertSize(0);
pbos@webrtc.org3004c792013-05-07 12:36:21249 vec.AssertSize(array_length() - 1);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21250 // Nothing should have changed.
pbos@webrtc.org3004c792013-05-07 12:36:21251 EXPECT_EQ(array_length(), vec.Size());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21252 // Assert with one element longer than already allocated.
pbos@webrtc.org3004c792013-05-07 12:36:21253 vec.AssertSize(array_length() + 1);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21254 // Expect vector to have grown.
pbos@webrtc.org3004c792013-05-07 12:36:21255 EXPECT_EQ(array_length() + 1, vec.Size());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21256 // Also check the individual AudioVectors.
257 for (size_t channel = 0; channel < vec.Channels(); ++channel) {
pbos@webrtc.org3004c792013-05-07 12:36:21258 EXPECT_EQ(array_length() + 1u, vec[channel].Size());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21259 }
260}
261
262// Test the PushBack method with another AudioMultiVector as input argument.
263TEST_P(AudioMultiVectorTest, OverwriteAt) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44264 AudioMultiVector vec1(num_channels_);
Henrik Lundin00eb12a2018-09-05 16:14:52265 vec1.PushBackInterleaved(array_interleaved_);
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44266 AudioMultiVector vec2(num_channels_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21267 vec2.Zeros(3); // 3 zeros in each channel.
268 // Overwrite vec2 at position 5.
269 vec1.OverwriteAt(vec2, 3, 5);
270 // Verify result.
pbos@webrtc.org3004c792013-05-07 12:36:21271 // Length remains the same.
272 ASSERT_EQ(array_length(), vec1.Size());
Henrik Lundin00eb12a2018-09-05 16:14:52273 int16_t* ptr = array_interleaved_.data();
pbos@webrtc.org3004c792013-05-07 12:36:21274 for (size_t i = 0; i < array_length() - 1; ++i) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21275 for (size_t channel = 0; channel < num_channels_; ++channel) {
276 if (i >= 5 && i <= 7) {
277 // Elements 5, 6, 7 should have been replaced with zeros.
278 EXPECT_EQ(0, vec1[channel][i]);
279 } else {
280 EXPECT_EQ(*ptr, vec1[channel][i]);
281 }
282 ++ptr;
283 }
284 }
285}
286
henrik.lundin@webrtc.org7825b1a2014-09-04 07:39:21287// Test the CopyChannel method, when the test is instantiated with at least two
288// channels.
289TEST_P(AudioMultiVectorTest, CopyChannel) {
290 if (num_channels_ < 2)
291 return;
292
293 AudioMultiVector vec(num_channels_);
Henrik Lundin00eb12a2018-09-05 16:14:52294 vec.PushBackInterleaved(array_interleaved_);
henrik.lundin@webrtc.org7825b1a2014-09-04 07:39:21295 // Create a reference copy.
296 AudioMultiVector ref(num_channels_);
297 ref.PushBack(vec);
298 // Copy from first to last channel.
299 vec.CopyChannel(0, num_channels_ - 1);
300 // Verify that the first and last channels are identical; the others should
301 // be left untouched.
302 for (size_t i = 0; i < array_length(); ++i) {
303 // Verify that all but the last channel are untouched.
304 for (size_t channel = 0; channel < num_channels_ - 1; ++channel) {
305 EXPECT_EQ(ref[channel][i], vec[channel][i]);
306 }
307 // Verify that the last and the first channels are identical.
308 EXPECT_EQ(vec[0][i], vec[num_channels_ - 1][i]);
309 }
310}
311
Mirko Bonadeic84f6612019-01-31 11:20:57312INSTANTIATE_TEST_SUITE_P(TestNumChannels,
313 AudioMultiVectorTest,
314 ::testing::Values(static_cast<size_t>(1),
315 static_cast<size_t>(2),
316 static_cast<size_t>(5)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21317} // namespace webrtc