Home | History | Annotate | Download | only in neteq
      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