blob: c7b6311867f518086e625aac449db7f6583c9645 [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
Philipp Hanckec4fe8252025-05-06 22:39:5415#include <cstdint>
16#include <cstring>
Henrik Lundin00eb12a2018-09-05 16:14:5217#include <vector>
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2118
Philipp Hanckec4fe8252025-05-06 22:39:5419#include "modules/audio_coding/neteq/audio_vector.h"
Karl Wiberge40468b2017-11-22 09:42:2620#include "rtc_base/numerics/safe_conversions.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3121#include "test/gtest.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2122
23namespace webrtc {
24
25// This is a value-parameterized test. The test cases are instantiated with
26// different values for the test parameter, which is used to determine the
27// number of channels in the AudioMultiBuffer. Note that it is not possible
28// to combine typed testing with value-parameterized testing, and since the
29// tests for AudioVector already covers a number of different type parameters,
30// this test focuses on testing different number of channels, and keeping the
31// value type constant.
pbos@webrtc.org3004c792013-05-07 12:36:2132
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2133class AudioMultiVectorTest : public ::testing::TestWithParam<size_t> {
34 protected:
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2135 AudioMultiVectorTest()
36 : num_channels_(GetParam()), // Get the test parameter.
Henrik Lundin00eb12a2018-09-05 16:14:5237 array_interleaved_(num_channels_ * array_length()) {}
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2138
Henrik Lundin00eb12a2018-09-05 16:14:5239 ~AudioMultiVectorTest() = default;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2140
41 virtual void SetUp() {
42 // Populate test arrays.
pbos@webrtc.org3004c792013-05-07 12:36:2143 for (size_t i = 0; i < array_length(); ++i) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:4444 array_[i] = static_cast<int16_t>(i);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2145 }
Henrik Lundin00eb12a2018-09-05 16:14:5246 int16_t* ptr = array_interleaved_.data();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2147 // Write 100, 101, 102, ... for first channel.
48 // Write 200, 201, 202, ... for second channel.
49 // And so on.
pbos@webrtc.org3004c792013-05-07 12:36:2150 for (size_t i = 0; i < array_length(); ++i) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2151 for (size_t j = 1; j <= num_channels_; ++j) {
Evan Shrubsoleef95b202025-02-24 14:55:0452 *ptr = checked_cast<int16_t>(j * 100 + i);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2153 ++ptr;
54 }
55 }
56 }
57
Yves Gerey665174f2018-06-19 13:03:0558 size_t array_length() const { return sizeof(array_) / sizeof(array_[0]); }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2159
60 const size_t num_channels_;
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:4461 int16_t array_[10];
Henrik Lundin00eb12a2018-09-05 16:14:5262 std::vector<int16_t> array_interleaved_;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2163};
64
65// Create and destroy AudioMultiVector objects, both empty and with a predefined
66// length.
67TEST_P(AudioMultiVectorTest, CreateAndDestroy) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:4468 AudioMultiVector vec1(num_channels_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2169 EXPECT_TRUE(vec1.Empty());
70 EXPECT_EQ(num_channels_, vec1.Channels());
71 EXPECT_EQ(0u, vec1.Size());
72
73 size_t initial_size = 17;
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:4474 AudioMultiVector vec2(num_channels_, initial_size);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2175 EXPECT_FALSE(vec2.Empty());
76 EXPECT_EQ(num_channels_, vec2.Channels());
77 EXPECT_EQ(initial_size, vec2.Size());
78}
79
80// Test the subscript operator [] for getting and setting.
81TEST_P(AudioMultiVectorTest, SubscriptOperator) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:4482 AudioMultiVector vec(num_channels_, array_length());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2183 for (size_t channel = 0; channel < num_channels_; ++channel) {
pbos@webrtc.org3004c792013-05-07 12:36:2184 for (size_t i = 0; i < array_length(); ++i) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:4485 vec[channel][i] = static_cast<int16_t>(i);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2186 // Make sure to use the const version.
henrik.lundin@webrtc.org1871dd22013-10-14 20:33:2587 const AudioVector& audio_vec = vec[channel];
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:4488 EXPECT_EQ(static_cast<int16_t>(i), audio_vec[i]);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:2189 }
90 }
91}
92
93// Test the PushBackInterleaved method and the CopyFrom method. The Clear
94// method is also invoked.
95TEST_P(AudioMultiVectorTest, PushBackInterleavedAndCopy) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:4496 AudioMultiVector vec(num_channels_);
Henrik Lundin00eb12a2018-09-05 16:14:5297 vec.PushBackInterleaved(array_interleaved_);
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:4498 AudioMultiVector vec_copy(num_channels_);
Artem Titovd00ce742021-07-28 18:00:1799 vec.CopyTo(&vec_copy); // Copy from `vec` to `vec_copy`.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21100 ASSERT_EQ(num_channels_, vec.Channels());
pbos@webrtc.org3004c792013-05-07 12:36:21101 ASSERT_EQ(array_length(), vec.Size());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21102 ASSERT_EQ(num_channels_, vec_copy.Channels());
pbos@webrtc.org3004c792013-05-07 12:36:21103 ASSERT_EQ(array_length(), vec_copy.Size());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21104 for (size_t channel = 0; channel < vec.Channels(); ++channel) {
pbos@webrtc.org3004c792013-05-07 12:36:21105 for (size_t i = 0; i < array_length(); ++i) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44106 EXPECT_EQ(static_cast<int16_t>((channel + 1) * 100 + i), vec[channel][i]);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21107 EXPECT_EQ(vec[channel][i], vec_copy[channel][i]);
108 }
109 }
110
Artem Titovd00ce742021-07-28 18:00:17111 // Clear `vec` and verify that it is empty.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21112 vec.Clear();
113 EXPECT_TRUE(vec.Empty());
114
115 // Now copy the empty vector and verify that the copy becomes empty too.
henrik.lundin@webrtc.orgf6ab6f82014-09-04 10:58:43116 vec.CopyTo(&vec_copy);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21117 EXPECT_TRUE(vec_copy.Empty());
118}
119
120// Try to copy to a NULL pointer. Nothing should happen.
121TEST_P(AudioMultiVectorTest, CopyToNull) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44122 AudioMultiVector vec(num_channels_);
123 AudioMultiVector* vec_copy = NULL;
Henrik Lundin00eb12a2018-09-05 16:14:52124 vec.PushBackInterleaved(array_interleaved_);
henrik.lundin@webrtc.orgf6ab6f82014-09-04 10:58:43125 vec.CopyTo(vec_copy);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21126}
127
128// Test the PushBack method with another AudioMultiVector as input argument.
129TEST_P(AudioMultiVectorTest, PushBackVector) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44130 AudioMultiVector vec1(num_channels_, array_length());
131 AudioMultiVector vec2(num_channels_, array_length());
pbos@webrtc.org3004c792013-05-07 12:36:21132 // Set the first vector to [0, 1, ..., array_length() - 1] +
133 // 100 * channel_number.
134 // Set the second vector to [array_length(), array_length() + 1, ...,
135 // 2 * array_length() - 1] + 100 * channel_number.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21136 for (size_t channel = 0; channel < num_channels_; ++channel) {
pbos@webrtc.org3004c792013-05-07 12:36:21137 for (size_t i = 0; i < array_length(); ++i) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44138 vec1[channel][i] = static_cast<int16_t>(i + 100 * channel);
139 vec2[channel][i] =
140 static_cast<int16_t>(i + 100 * channel + array_length());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21141 }
142 }
143 // Append vec2 to the back of vec1.
144 vec1.PushBack(vec2);
pbos@webrtc.org3004c792013-05-07 12:36:21145 ASSERT_EQ(2u * array_length(), vec1.Size());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21146 for (size_t channel = 0; channel < num_channels_; ++channel) {
pbos@webrtc.org3004c792013-05-07 12:36:21147 for (size_t i = 0; i < 2 * array_length(); ++i) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44148 EXPECT_EQ(static_cast<int16_t>(i + 100 * channel), vec1[channel][i]);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21149 }
150 }
151}
152
153// Test the PushBackFromIndex method.
154TEST_P(AudioMultiVectorTest, PushBackFromIndex) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44155 AudioMultiVector vec1(num_channels_);
Henrik Lundin00eb12a2018-09-05 16:14:52156 vec1.PushBackInterleaved(array_interleaved_);
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44157 AudioMultiVector vec2(num_channels_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21158
159 // Append vec1 to the back of vec2 (which is empty). Read vec1 from the second
160 // last element.
pbos@webrtc.org3004c792013-05-07 12:36:21161 vec2.PushBackFromIndex(vec1, array_length() - 2);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21162 ASSERT_EQ(2u, vec2.Size());
163 for (size_t channel = 0; channel < num_channels_; ++channel) {
164 for (size_t i = 0; i < 2; ++i) {
Yves Gerey665174f2018-06-19 13:03:05165 EXPECT_EQ(array_interleaved_[channel +
166 num_channels_ * (array_length() - 2 + i)],
167 vec2[channel][i]);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21168 }
169 }
170}
171
172// Starts with pushing some values to the vector, then test the Zeros method.
173TEST_P(AudioMultiVectorTest, Zeros) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44174 AudioMultiVector vec(num_channels_);
Henrik Lundin00eb12a2018-09-05 16:14:52175 vec.PushBackInterleaved(array_interleaved_);
pbos@webrtc.org3004c792013-05-07 12:36:21176 vec.Zeros(2 * array_length());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21177 ASSERT_EQ(num_channels_, vec.Channels());
pbos@webrtc.org3004c792013-05-07 12:36:21178 ASSERT_EQ(2u * array_length(), vec.Size());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21179 for (size_t channel = 0; channel < num_channels_; ++channel) {
pbos@webrtc.org3004c792013-05-07 12:36:21180 for (size_t i = 0; i < 2 * array_length(); ++i) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21181 EXPECT_EQ(0, vec[channel][i]);
182 }
183 }
184}
185
186// Test the ReadInterleaved method
187TEST_P(AudioMultiVectorTest, ReadInterleaved) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44188 AudioMultiVector vec(num_channels_);
Henrik Lundin00eb12a2018-09-05 16:14:52189 vec.PushBackInterleaved(array_interleaved_);
190 int16_t* output = new int16_t[array_interleaved_.size()];
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21191 // Read 5 samples.
192 size_t read_samples = 5;
193 EXPECT_EQ(num_channels_ * read_samples,
194 vec.ReadInterleaved(read_samples, output));
Henrik Lundin00eb12a2018-09-05 16:14:52195 EXPECT_EQ(0, memcmp(array_interleaved_.data(), output,
196 read_samples * sizeof(int16_t)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21197
198 // Read too many samples. Expect to get all samples from the vector.
Henrik Lundin00eb12a2018-09-05 16:14:52199 EXPECT_EQ(array_interleaved_.size(),
pbos@webrtc.org3004c792013-05-07 12:36:21200 vec.ReadInterleaved(array_length() + 1, output));
Henrik Lundin00eb12a2018-09-05 16:14:52201 EXPECT_EQ(0, memcmp(array_interleaved_.data(), output,
202 read_samples * sizeof(int16_t)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21203
Yves Gerey665174f2018-06-19 13:03:05204 delete[] output;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21205}
206
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21207// Test the PopFront method.
208TEST_P(AudioMultiVectorTest, PopFront) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44209 AudioMultiVector vec(num_channels_);
Henrik Lundin00eb12a2018-09-05 16:14:52210 vec.PushBackInterleaved(array_interleaved_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21211 vec.PopFront(1); // Remove one element from each channel.
pbos@webrtc.org3004c792013-05-07 12:36:21212 ASSERT_EQ(array_length() - 1u, vec.Size());
Artem Titovd00ce742021-07-28 18:00:17213 // Let `ptr` point to the second element of the first channel in the
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21214 // interleaved array.
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44215 int16_t* ptr = &array_interleaved_[num_channels_];
pbos@webrtc.org3004c792013-05-07 12:36:21216 for (size_t i = 0; i < array_length() - 1; ++i) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21217 for (size_t channel = 0; channel < num_channels_; ++channel) {
218 EXPECT_EQ(*ptr, vec[channel][i]);
219 ++ptr;
220 }
221 }
pbos@webrtc.org3004c792013-05-07 12:36:21222 vec.PopFront(array_length()); // Remove more elements than vector size.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21223 EXPECT_EQ(0u, vec.Size());
224}
225
226// Test the PopBack method.
227TEST_P(AudioMultiVectorTest, PopBack) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44228 AudioMultiVector vec(num_channels_);
Henrik Lundin00eb12a2018-09-05 16:14:52229 vec.PushBackInterleaved(array_interleaved_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21230 vec.PopBack(1); // Remove one element from each channel.
pbos@webrtc.org3004c792013-05-07 12:36:21231 ASSERT_EQ(array_length() - 1u, vec.Size());
Artem Titovd00ce742021-07-28 18:00:17232 // Let `ptr` point to the first element of the first channel in the
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21233 // interleaved array.
Henrik Lundin00eb12a2018-09-05 16:14:52234 int16_t* ptr = array_interleaved_.data();
pbos@webrtc.org3004c792013-05-07 12:36:21235 for (size_t i = 0; i < array_length() - 1; ++i) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21236 for (size_t channel = 0; channel < num_channels_; ++channel) {
237 EXPECT_EQ(*ptr, vec[channel][i]);
238 ++ptr;
239 }
240 }
pbos@webrtc.org3004c792013-05-07 12:36:21241 vec.PopBack(array_length()); // Remove more elements than vector size.
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21242 EXPECT_EQ(0u, vec.Size());
243}
244
245// Test the AssertSize method.
246TEST_P(AudioMultiVectorTest, AssertSize) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44247 AudioMultiVector vec(num_channels_, array_length());
pbos@webrtc.org3004c792013-05-07 12:36:21248 EXPECT_EQ(array_length(), vec.Size());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21249 // Start with asserting with smaller sizes than already allocated.
250 vec.AssertSize(0);
pbos@webrtc.org3004c792013-05-07 12:36:21251 vec.AssertSize(array_length() - 1);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21252 // Nothing should have changed.
pbos@webrtc.org3004c792013-05-07 12:36:21253 EXPECT_EQ(array_length(), vec.Size());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21254 // Assert with one element longer than already allocated.
pbos@webrtc.org3004c792013-05-07 12:36:21255 vec.AssertSize(array_length() + 1);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21256 // Expect vector to have grown.
pbos@webrtc.org3004c792013-05-07 12:36:21257 EXPECT_EQ(array_length() + 1, vec.Size());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21258 // Also check the individual AudioVectors.
259 for (size_t channel = 0; channel < vec.Channels(); ++channel) {
pbos@webrtc.org3004c792013-05-07 12:36:21260 EXPECT_EQ(array_length() + 1u, vec[channel].Size());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21261 }
262}
263
264// Test the PushBack method with another AudioMultiVector as input argument.
265TEST_P(AudioMultiVectorTest, OverwriteAt) {
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44266 AudioMultiVector vec1(num_channels_);
Henrik Lundin00eb12a2018-09-05 16:14:52267 vec1.PushBackInterleaved(array_interleaved_);
henrik.lundin@webrtc.orgfd11bbf2013-09-30 20:38:44268 AudioMultiVector vec2(num_channels_);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21269 vec2.Zeros(3); // 3 zeros in each channel.
270 // Overwrite vec2 at position 5.
271 vec1.OverwriteAt(vec2, 3, 5);
272 // Verify result.
pbos@webrtc.org3004c792013-05-07 12:36:21273 // Length remains the same.
274 ASSERT_EQ(array_length(), vec1.Size());
Henrik Lundin00eb12a2018-09-05 16:14:52275 int16_t* ptr = array_interleaved_.data();
pbos@webrtc.org3004c792013-05-07 12:36:21276 for (size_t i = 0; i < array_length() - 1; ++i) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21277 for (size_t channel = 0; channel < num_channels_; ++channel) {
278 if (i >= 5 && i <= 7) {
279 // Elements 5, 6, 7 should have been replaced with zeros.
280 EXPECT_EQ(0, vec1[channel][i]);
281 } else {
282 EXPECT_EQ(*ptr, vec1[channel][i]);
283 }
284 ++ptr;
285 }
286 }
287}
288
henrik.lundin@webrtc.org7825b1a2014-09-04 07:39:21289// Test the CopyChannel method, when the test is instantiated with at least two
290// channels.
291TEST_P(AudioMultiVectorTest, CopyChannel) {
292 if (num_channels_ < 2)
293 return;
294
295 AudioMultiVector vec(num_channels_);
Henrik Lundin00eb12a2018-09-05 16:14:52296 vec.PushBackInterleaved(array_interleaved_);
henrik.lundin@webrtc.org7825b1a2014-09-04 07:39:21297 // Create a reference copy.
298 AudioMultiVector ref(num_channels_);
299 ref.PushBack(vec);
300 // Copy from first to last channel.
301 vec.CopyChannel(0, num_channels_ - 1);
302 // Verify that the first and last channels are identical; the others should
303 // be left untouched.
304 for (size_t i = 0; i < array_length(); ++i) {
305 // Verify that all but the last channel are untouched.
306 for (size_t channel = 0; channel < num_channels_ - 1; ++channel) {
307 EXPECT_EQ(ref[channel][i], vec[channel][i]);
308 }
309 // Verify that the last and the first channels are identical.
310 EXPECT_EQ(vec[0][i], vec[num_channels_ - 1][i]);
311 }
312}
313
Jakob Ivarsson136ef252022-09-23 20:03:09314TEST_P(AudioMultiVectorTest, PushBackEmptyArray) {
315 AudioMultiVector vec(num_channels_);
316 vec.PushBackInterleaved({});
317 EXPECT_TRUE(vec.Empty());
318}
319
Mirko Bonadeic84f6612019-01-31 11:20:57320INSTANTIATE_TEST_SUITE_P(TestNumChannels,
321 AudioMultiVectorTest,
322 ::testing::Values(static_cast<size_t>(1),
323 static_cast<size_t>(2),
324 static_cast<size_t>(5)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21325} // namespace webrtc