15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(henrika): add test which included |start_frame| in Consume() call.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/audio_fifo.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AudioFifoTest : public testing::Test {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioFifoTest() {}
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~AudioFifoTest() {}
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void VerifyValue(const float data[], int size, float value) {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < size; ++i)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_FLOAT_EQ(value, data[i]) << "i=" << i;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AudioFifoTest);
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that construction works as intended.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioFifoTest, Construct) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kChannels = 6;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kMaxFrameCount = 128;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioFifo fifo(kChannels, kMaxFrameCount);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(fifo.frames(), 0);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Pushes audio bus objects to a FIFO and fill it up to different degrees.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioFifoTest, Push) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kChannels = 2;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kMaxFrameCount = 128;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioFifo fifo(kChannels, kMaxFrameCount);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE("Push 50%");
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kMaxFrameCount / 2);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(fifo.frames(), 0);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fifo.Push(bus.get());
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(fifo.frames(), bus->frames());
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fifo.Clear();
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE("Push 100%");
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kMaxFrameCount);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(fifo.frames(), 0);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fifo.Push(bus.get());
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(fifo.frames(), bus->frames());
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fifo.Clear();
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Consumes audio bus objects from a FIFO and empty it to different degrees.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioFifoTest, Consume) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kChannels = 2;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kMaxFrameCount = 128;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioFifo fifo(kChannels, kMaxFrameCount);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kMaxFrameCount);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fifo.Push(bus.get());
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(fifo.frames(), kMaxFrameCount);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE("Consume 50%");
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kMaxFrameCount / 2);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fifo.Consume(bus.get(), 0, bus->frames());
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(fifo.frames() == bus->frames());
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fifo.Push(bus.get());
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(fifo.frames(), kMaxFrameCount);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE("Consume 100%");
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kMaxFrameCount);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fifo.Consume(bus.get(), 0, bus->frames());
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(fifo.frames(), 0);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fifo.Push(bus.get());
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(fifo.frames(), kMaxFrameCount);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify that the frames() method of the FIFO works as intended while
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// appending and removing audio bus elements to/from the FIFO.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioFifoTest, FramesInFifo) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kChannels = 2;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kMaxFrameCount = 64;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioFifo fifo(kChannels, kMaxFrameCount);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fill up the FIFO and verify that the size grows as it should while adding
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // one audio frame each time.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, 1);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int n = 0;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (fifo.frames() < kMaxFrameCount) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fifo.Push(bus.get());
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(fifo.frames(), ++n);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(fifo.frames(), kMaxFrameCount);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Empty the FIFO and verify that the size decreases as it should.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reduce the size of the FIFO by one frame each time.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (fifo.frames() > 0) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fifo.Consume(bus.get(), 0, bus->frames());
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(fifo.frames(), --n);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(fifo.frames(), 0);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that a steady-state size of #frames in the FIFO is maintained
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // during a sequence of Push/Consume calls which involves wrapping. We ensure
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // wrapping by selecting a buffer size which does divides the FIFO size
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with a remainder of one.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> bus2 =
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AudioBus::Create(kChannels, (kMaxFrameCount / 4) - 1);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int frames_in_fifo = bus2->frames();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fifo.Push(bus2.get());
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(fifo.frames(), frames_in_fifo);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int n = 0; n < kMaxFrameCount; ++n) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fifo.Push(bus2.get());
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fifo.Consume(bus2.get(), 0, frames_in_fifo);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(fifo.frames(), frames_in_fifo);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Perform a sequence of Push/Consume calls and verify that the data written
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to the FIFO is correctly retrieved, i.e., that the order is correct and the
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// values are correct.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioFifoTest, VerifyDataValues) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kChannels = 2;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kFrameCount = 2;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kFifoFrameCount = 5 * kFrameCount;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioFifo fifo(kChannels, kFifoFrameCount);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(fifo.frames(), 0);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(bus->frames(), kFrameCount);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start by filling up the FIFO with audio frames. The first audio frame
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will contain all 1's, the second all 2's etc. All channels contain the
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // same value.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int value = 1;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (fifo.frames() < kFifoFrameCount) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < bus->channels(); ++j)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::fill(bus->channel(j), bus->channel(j) + bus->frames(), value);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fifo.Push(bus.get());
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(fifo.frames(), bus->frames() * value);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++value;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FIFO should be full now.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(fifo.frames(), kFifoFrameCount);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Consume all audio frames in the FIFO and verify that the stored values
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // are correct. In this example, we shall read out: 1, 2, 3, 4, 5 in that
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // order. Note that we set |frames_to_consume| to half the size of the bus.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It means that we shall read out the same value two times in row.
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value = 1;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int n = 1;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int frames_to_consume = bus->frames() / 2;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (fifo.frames() > 0) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fifo.Consume(bus.get(), 0, frames_to_consume);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < bus->channels(); ++j)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VerifyValue(bus->channel(j), frames_to_consume, value);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (n++ % 2 == 0)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++value;  // counts 1, 1, 2, 2, 3, 3,...
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // FIFO should be empty now.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(fifo.frames(), 0);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Push one audio bus to the FIFO and fill it with 1's.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value = 1;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int j = 0; j < bus->channels(); ++j)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::fill(bus->channel(j), bus->channel(j) + bus->frames(), value);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fifo.Push(bus.get());
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(fifo.frames(), bus->frames());
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Keep calling Consume/Push a few rounds and verify that we read out the
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // correct values. The number of elements shall be fixed (kFrameCount) during
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this phase.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 5 * kFifoFrameCount; i++) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fifo.Consume(bus.get(), 0, bus->frames());
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int j = 0; j < bus->channels(); ++j) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VerifyValue(bus->channel(j), bus->channels(), value);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::fill(bus->channel(j), bus->channel(j) + bus->frames(), value + 1);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fifo.Push(bus.get());
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(fifo.frames(), bus->frames());
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++value;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
195