Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 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 #include "platform/audio/PushPullFIFO.h" | |
| 6 | |
| 7 #include "platform/testing/TestingPlatformSupport.h" | |
| 8 #include "testing/gtest/include/gtest/gtest-death-test.h" | |
| 9 #include "testing/gtest/include/gtest/gtest.h" | |
| 10 #include "wtf/PtrUtil.h" | |
| 11 #include <memory> | |
| 12 | |
| 13 namespace blink { | |
| 14 | |
| 15 namespace { | |
| 16 | |
| 17 const unsigned kNumberOfChannel = 2; | |
| 18 const size_t kFIFOSize = 8192; | |
| 19 const size_t kCallbackBufferSize = 1024; | |
|
Raymond Toy
2017/01/12 19:29:40
If you have to pick values for this, why not use "
o1ka
2017/01/13 11:23:44
I believe we need to have parametrized tests (TEST
hongchan
2017/01/13 23:29:23
Please bear with me - this is my first attempt to
hongchan
2017/01/13 23:29:23
Done.
| |
| 20 const size_t kRenderQuantum = 128; | |
|
o1ka
2017/01/13 11:23:44
The values are multipliers of each other, so many
| |
| 21 | |
| 22 // Fills AudioBus with a value. | |
| 23 void fillBusWithValue(AudioBus* targetBus, float value) { | |
| 24 for (unsigned c = 0; c < targetBus->numberOfChannels(); ++c) { | |
| 25 float* busChannel = targetBus->channel(c)->mutableData(); | |
| 26 std::fill(busChannel, busChannel + targetBus->channel(c)->length(), value); | |
| 27 } | |
| 28 } | |
| 29 | |
| 30 // Check if AudioBus is filled with a specific value within the given range. | |
|
o1ka
2017/01/13 11:23:44
To make sure the indexes are always consistent and
hongchan
2017/01/13 23:29:23
Done.
| |
| 31 bool isBusConstantValueOf(AudioBus* targetBus, | |
| 32 float value, | |
| 33 unsigned startFrame, | |
| 34 unsigned endFrame) { | |
| 35 for (unsigned c = 0; c < targetBus->numberOfChannels(); ++c) { | |
| 36 const float* busChannel = targetBus->channel(c)->data(); | |
| 37 for (unsigned i = startFrame; i < endFrame; ++i) { | |
| 38 if (busChannel[i] != value) | |
| 39 return false; | |
| 40 } | |
| 41 } | |
| 42 return true; | |
| 43 } | |
| 44 | |
| 45 } // namespace | |
| 46 | |
| 47 TEST(PushPullFIFOTest, Construction) { | |
| 48 std::unique_ptr<PushPullFIFO> fifo = | |
| 49 WTF::wrapUnique(new PushPullFIFO(kNumberOfChannel, kFIFOSize)); | |
| 50 | |
| 51 EXPECT_EQ(static_cast<int>(kFIFOSize), fifo->length()); | |
| 52 EXPECT_EQ(0, fifo->framesAvailable()); | |
| 53 EXPECT_EQ(kNumberOfChannel, fifo->numberOfChannels()); | |
| 54 } | |
| 55 | |
| 56 TEST(PushPullFIFOTest, BasicOperation) { | |
| 57 // Create a FIFO of 2X render quantum. (256 frames) | |
| 58 std::unique_ptr<PushPullFIFO> fifo = | |
| 59 WTF::wrapUnique(new PushPullFIFO(kNumberOfChannel, 2 * kRenderQuantum)); | |
| 60 | |
| 61 RefPtr<AudioBus> inputBus = | |
| 62 AudioBus::create(kNumberOfChannel, kRenderQuantum); | |
| 63 RefPtr<AudioBus> outputBus = | |
| 64 AudioBus::create(kNumberOfChannel, 2 * kRenderQuantum); | |
| 65 | |
| 66 // Create an input vector (128 frames) of '1'. | |
| 67 fillBusWithValue(inputBus.get(), 1); | |
| 68 EXPECT_TRUE(isBusConstantValueOf(inputBus.get(), 1, 0, kRenderQuantum)); | |
| 69 | |
| 70 // Push and pull by 128 frames. | |
| 71 fifo->push(inputBus.get()); | |
| 72 fifo->pull(outputBus.get(), kRenderQuantum); | |
| 73 | |
| 74 // Thus no frames available in FIFO. | |
| 75 EXPECT_EQ(fifo->framesAvailable(), 0); | |
| 76 | |
| 77 // The half of output bus should be the exact copy of input bus. The rest | |
| 78 // should be 0. | |
| 79 EXPECT_TRUE(isBusConstantValueOf(outputBus.get(), 1, 0, kRenderQuantum)); | |
| 80 EXPECT_TRUE(isBusConstantValueOf(outputBus.get(), 0, kRenderQuantum, | |
| 81 2 * kRenderQuantum)); | |
| 82 } | |
| 83 | |
| 84 TEST(PushPullFIFOTest, WrapAround) { | |
| 85 std::unique_ptr<PushPullFIFO> fifo = | |
| 86 WTF::wrapUnique(new PushPullFIFO(kNumberOfChannel, kCallbackBufferSize)); | |
| 87 | |
| 88 RefPtr<AudioBus> inputBus = | |
| 89 AudioBus::create(kNumberOfChannel, kRenderQuantum); | |
| 90 RefPtr<AudioBus> outputBus = | |
| 91 AudioBus::create(kNumberOfChannel, kCallbackBufferSize); | |
| 92 | |
| 93 unsigned numberOfblocks = kCallbackBufferSize / kRenderQuantum; | |
| 94 | |
| 95 // The first round fills the FIFO with 1. | |
| 96 fillBusWithValue(inputBus.get(), 1); | |
| 97 for (unsigned i = 0; i < numberOfblocks; ++i) | |
| 98 fifo->push(inputBus.get()); | |
| 99 | |
| 100 // Then pull the half of FIFO. | |
| 101 for (unsigned i = 0; i < 0.5 * numberOfblocks; ++i) | |
| 102 fifo->pull(outputBus.get(), kRenderQuantum); | |
| 103 | |
| 104 // Fill the emptied half with 2. After this point the FIFO content should | |
| 105 // be { 2, 2, 2, 2, 1, 1, 1, 1 } by each 128 frame block. Note that the read | |
| 106 // index is in the middle. | |
| 107 fillBusWithValue(inputBus.get(), 2); | |
| 108 for (unsigned i = 0; i < 0.5 * numberOfblocks; ++i) | |
| 109 fifo->push(inputBus.get()); | |
| 110 | |
| 111 // If FIFO is pulled 8 times (numberOfBlocks), it must produce the following | |
| 112 // block sequence because of warp-around. | |
| 113 float expectedValueInBlocks[] = {1, 1, 1, 1, 2, 2, 2, 2}; | |
| 114 | |
| 115 for (unsigned i = 0; i < numberOfblocks; ++i) { | |
| 116 fifo->pull(outputBus.get(), kRenderQuantum); | |
| 117 EXPECT_TRUE(isBusConstantValueOf(outputBus.get(), expectedValueInBlocks[i], | |
| 118 0, kRenderQuantum)); | |
| 119 } | |
| 120 } | |
| 121 | |
| 122 TEST(PushPullFIFOTest, Overflow) { | |
| 123 std::unique_ptr<PushPullFIFO> fifo = | |
| 124 WTF::wrapUnique(new PushPullFIFO(kNumberOfChannel, kCallbackBufferSize)); | |
| 125 RefPtr<AudioBus> inputBus = | |
| 126 AudioBus::create(kNumberOfChannel, kRenderQuantum); | |
| 127 | |
| 128 unsigned numberOfblocks = kCallbackBufferSize / kRenderQuantum; | |
| 129 | |
| 130 // Push data up to the full capacity of FIFO. | |
| 131 fillBusWithValue(inputBus.get(), 1); | |
| 132 for (unsigned i = 0; i < numberOfblocks; ++i) | |
| 133 fifo->push(inputBus.get()); | |
| 134 | |
| 135 // Pushing one more time without pulling causes DCHECK failure. | |
| 136 EXPECT_DEBUG_DEATH(fifo->push(inputBus.get()), "fifoOverflow"); | |
|
o1ka
2017/01/13 11:23:44
But this should not be the case in real life, righ
hongchan
2017/01/13 23:29:23
Without DCHECK, how can the test runner detect suc
| |
| 137 } | |
| 138 | |
| 139 TEST(PushPullFIFOTest, Underflow) { | |
| 140 std::unique_ptr<PushPullFIFO> fifo = | |
| 141 WTF::wrapUnique(new PushPullFIFO(kNumberOfChannel, kCallbackBufferSize)); | |
| 142 RefPtr<AudioBus> inputBus = | |
| 143 AudioBus::create(kNumberOfChannel, kRenderQuantum); | |
| 144 RefPtr<AudioBus> outputBus = | |
| 145 AudioBus::create(kNumberOfChannel, kRenderQuantum); | |
| 146 | |
| 147 unsigned numberOfblocks = kCallbackBufferSize / kRenderQuantum; | |
| 148 | |
| 149 fillBusWithValue(inputBus.get(), 1); | |
| 150 for (unsigned i = 0; i < numberOfblocks; ++i) | |
| 151 fifo->push(inputBus.get()); | |
| 152 | |
| 153 // Then pull the entire FIFO content. The FIFO will be empty. | |
| 154 for (unsigned i = 0; i < numberOfblocks; ++i) | |
| 155 fifo->pull(outputBus.get(), kRenderQuantum); | |
| 156 | |
| 157 // Pulling an empty FIFO results the silence. | |
| 158 fifo->pull(outputBus.get(), kRenderQuantum); | |
| 159 EXPECT_TRUE(isBusConstantValueOf(outputBus.get(), 0, 0, kRenderQuantum)); | |
| 160 } | |
| 161 | |
| 162 } // namespace blink | |
| OLD | NEW |