Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // TODO(henrika): add test which included |start_frame| in Consume() call.
      6 
      7 #include "media/base/audio_fifo.h"
      8 #include "testing/gtest/include/gtest/gtest.h"
      9 
     10 namespace media {
     11 
     12 class AudioFifoTest : public testing::Test {
     13  public:
     14   AudioFifoTest() {}
     15   virtual ~AudioFifoTest() {}
     16 
     17   void VerifyValue(const float data[], int size, float value) {
     18     for (int i = 0; i < size; ++i)
     19       ASSERT_FLOAT_EQ(value, data[i]) << "i=" << i;
     20   }
     21 
     22  protected:
     23   DISALLOW_COPY_AND_ASSIGN(AudioFifoTest);
     24 };
     25 
     26 // Verify that construction works as intended.
     27 TEST_F(AudioFifoTest, Construct) {
     28   static const int kChannels = 6;
     29   static const int kMaxFrameCount = 128;
     30   AudioFifo fifo(kChannels, kMaxFrameCount);
     31   EXPECT_EQ(fifo.frames(), 0);
     32 }
     33 
     34 // Pushes audio bus objects to a FIFO and fill it up to different degrees.
     35 TEST_F(AudioFifoTest, Push) {
     36   static const int kChannels = 2;
     37   static const int kMaxFrameCount = 128;
     38   AudioFifo fifo(kChannels, kMaxFrameCount);
     39   {
     40     SCOPED_TRACE("Push 50%");
     41     scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kMaxFrameCount / 2);
     42     EXPECT_EQ(fifo.frames(), 0);
     43     fifo.Push(bus.get());
     44     EXPECT_EQ(fifo.frames(), bus->frames());
     45     fifo.Clear();
     46   }
     47   {
     48     SCOPED_TRACE("Push 100%");
     49     scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kMaxFrameCount);
     50     EXPECT_EQ(fifo.frames(), 0);
     51     fifo.Push(bus.get());
     52     EXPECT_EQ(fifo.frames(), bus->frames());
     53     fifo.Clear();
     54   }
     55 }
     56 
     57 // Consumes audio bus objects from a FIFO and empty it to different degrees.
     58 TEST_F(AudioFifoTest, Consume) {
     59   static const int kChannels = 2;
     60   static const int kMaxFrameCount = 128;
     61   AudioFifo fifo(kChannels, kMaxFrameCount);
     62   {
     63     scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kMaxFrameCount);
     64     fifo.Push(bus.get());
     65     EXPECT_EQ(fifo.frames(), kMaxFrameCount);
     66   }
     67   {
     68     SCOPED_TRACE("Consume 50%");
     69     scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kMaxFrameCount / 2);
     70     fifo.Consume(bus.get(), 0, bus->frames());
     71     EXPECT_TRUE(fifo.frames() == bus->frames());
     72     fifo.Push(bus.get());
     73     EXPECT_EQ(fifo.frames(), kMaxFrameCount);
     74   }
     75   {
     76     SCOPED_TRACE("Consume 100%");
     77     scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kMaxFrameCount);
     78     fifo.Consume(bus.get(), 0, bus->frames());
     79     EXPECT_EQ(fifo.frames(), 0);
     80     fifo.Push(bus.get());
     81     EXPECT_EQ(fifo.frames(), kMaxFrameCount);
     82   }
     83 }
     84 
     85 // Verify that the frames() method of the FIFO works as intended while
     86 // appending and removing audio bus elements to/from the FIFO.
     87 TEST_F(AudioFifoTest, FramesInFifo) {
     88   static const int kChannels = 2;
     89   static const int kMaxFrameCount = 64;
     90   AudioFifo fifo(kChannels, kMaxFrameCount);
     91 
     92   // Fill up the FIFO and verify that the size grows as it should while adding
     93   // one audio frame each time.
     94   scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, 1);
     95   int n = 0;
     96   while (fifo.frames() < kMaxFrameCount) {
     97     fifo.Push(bus.get());
     98     EXPECT_EQ(fifo.frames(), ++n);
     99   }
    100   EXPECT_EQ(fifo.frames(), kMaxFrameCount);
    101 
    102   // Empty the FIFO and verify that the size decreases as it should.
    103   // Reduce the size of the FIFO by one frame each time.
    104   while (fifo.frames() > 0) {
    105     fifo.Consume(bus.get(), 0, bus->frames());
    106     EXPECT_EQ(fifo.frames(), --n);
    107   }
    108   EXPECT_EQ(fifo.frames(), 0);
    109 
    110   // Verify that a steady-state size of #frames in the FIFO is maintained
    111   // during a sequence of Push/Consume calls which involves wrapping. We ensure
    112   // wrapping by selecting a buffer size which does divides the FIFO size
    113   // with a remainder of one.
    114   scoped_ptr<AudioBus> bus2 =
    115       AudioBus::Create(kChannels, (kMaxFrameCount / 4) - 1);
    116   const int frames_in_fifo = bus2->frames();
    117   fifo.Push(bus2.get());
    118   EXPECT_EQ(fifo.frames(), frames_in_fifo);
    119   for (int n = 0; n < kMaxFrameCount; ++n) {
    120     fifo.Push(bus2.get());
    121     fifo.Consume(bus2.get(), 0, frames_in_fifo);
    122     EXPECT_EQ(fifo.frames(), frames_in_fifo);
    123   }
    124 }
    125 
    126 // Perform a sequence of Push/Consume calls and verify that the data written
    127 // to the FIFO is correctly retrieved, i.e., that the order is correct and the
    128 // values are correct.
    129 TEST_F(AudioFifoTest, VerifyDataValues) {
    130   static const int kChannels = 2;
    131   static const int kFrameCount = 2;
    132   static const int kFifoFrameCount = 5 * kFrameCount;
    133 
    134   AudioFifo fifo(kChannels, kFifoFrameCount);
    135   scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount);
    136   EXPECT_EQ(fifo.frames(), 0);
    137   EXPECT_EQ(bus->frames(), kFrameCount);
    138 
    139   // Start by filling up the FIFO with audio frames. The first audio frame
    140   // will contain all 1's, the second all 2's etc. All channels contain the
    141   // same value.
    142   int value = 1;
    143   while (fifo.frames() < kFifoFrameCount) {
    144     for (int j = 0; j < bus->channels(); ++j)
    145       std::fill(bus->channel(j), bus->channel(j) + bus->frames(), value);
    146     fifo.Push(bus.get());
    147     EXPECT_EQ(fifo.frames(), bus->frames() * value);
    148     ++value;
    149   }
    150 
    151   // FIFO should be full now.
    152   EXPECT_EQ(fifo.frames(), kFifoFrameCount);
    153 
    154   // Consume all audio frames in the FIFO and verify that the stored values
    155   // are correct. In this example, we shall read out: 1, 2, 3, 4, 5 in that
    156   // order. Note that we set |frames_to_consume| to half the size of the bus.
    157   // It means that we shall read out the same value two times in row.
    158   value = 1;
    159   int n = 1;
    160   const int frames_to_consume = bus->frames() / 2;
    161   while (fifo.frames() > 0) {
    162     fifo.Consume(bus.get(), 0, frames_to_consume);
    163     for (int j = 0; j < bus->channels(); ++j)
    164       VerifyValue(bus->channel(j), frames_to_consume, value);
    165     if (n++ % 2 == 0)
    166       ++value;  // counts 1, 1, 2, 2, 3, 3,...
    167   }
    168 
    169   // FIFO should be empty now.
    170   EXPECT_EQ(fifo.frames(), 0);
    171 
    172   // Push one audio bus to the FIFO and fill it with 1's.
    173   value = 1;
    174   for (int j = 0; j < bus->channels(); ++j)
    175     std::fill(bus->channel(j), bus->channel(j) + bus->frames(), value);
    176   fifo.Push(bus.get());
    177   EXPECT_EQ(fifo.frames(), bus->frames());
    178 
    179   // Keep calling Consume/Push a few rounds and verify that we read out the
    180   // correct values. The number of elements shall be fixed (kFrameCount) during
    181   // this phase.
    182   for (int i = 0; i < 5 * kFifoFrameCount; i++) {
    183     fifo.Consume(bus.get(), 0, bus->frames());
    184     for (int j = 0; j < bus->channels(); ++j) {
    185       VerifyValue(bus->channel(j), bus->channels(), value);
    186       std::fill(bus->channel(j), bus->channel(j) + bus->frames(), value + 1);
    187     }
    188     fifo.Push(bus.get());
    189     EXPECT_EQ(fifo.frames(), bus->frames());
    190     ++value;
    191   }
    192 }
    193 
    194 }  // namespace media
    195