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