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 "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: 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 39 ~AudioMultiVectorTest() { 40 delete [] array_interleaved_; 41 } 42 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 60 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. 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. 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. 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.CopyFrom(&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.CopyFrom(&vec_copy); 122 EXPECT_TRUE(vec_copy.Empty()); 123 } 124 125 // Try to copy to a NULL pointer. Nothing should happen. 126 TEST_P(AudioMultiVectorTest, CopyToNull) { 127 AudioMultiVector vec(num_channels_); 128 AudioMultiVector* vec_copy = NULL; 129 vec.PushBackInterleaved(array_interleaved_, interleaved_length_); 130 vec.CopyFrom(vec_copy); 131 } 132 133 // Test the PushBack method with another AudioMultiVector as input argument. 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. 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. 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 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. 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. 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. 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. 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. 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 INSTANTIATE_TEST_CASE_P(TestNumChannels, 304 AudioMultiVectorTest, 305 ::testing::Values(static_cast<size_t>(1), 306 static_cast<size_t>(2), 307 static_cast<size_t>(5))); 308 } // namespace webrtc 309