1 // Copyright 2018 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 "services/audio/delay_buffer.h"
6
7 #include <algorithm>
8
9 #include "media/base/audio_bus.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 namespace audio {
13 namespace {
14
15 constexpr int kChannels = 1;
16 constexpr int kMaxFrames = 32;
17
18 #define EXPECT_BUS_VALUES_EQ(bus, begin, end, value) \
19 { \
20 const auto IsValue = [](float x) { return x == (value); }; \
21 EXPECT_TRUE(std::all_of((bus)->channel(0) + (begin), \
22 (bus)->channel(0) + (end) - (begin), IsValue)); \
23 }
24
TEST(DelayBufferTest,RecordsAMaximumNumberOfFrames)25 TEST(DelayBufferTest, RecordsAMaximumNumberOfFrames) {
26 DelayBuffer buffer(kMaxFrames);
27 ASSERT_EQ(buffer.GetBeginPosition(), buffer.GetEndPosition());
28
29 constexpr int frames_per_bus = kMaxFrames / 4;
30 const auto bus = media::AudioBus::Create(kChannels, frames_per_bus);
31 std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 1.0);
32
33 // Fill the buffer.
34 DelayBuffer::FrameTicks position = 0;
35 for (int i = 0; i < 4; ++i) {
36 buffer.Write(position, *bus, 1.0);
37 position += frames_per_bus;
38 EXPECT_EQ(0, buffer.GetBeginPosition());
39 EXPECT_EQ(position, buffer.GetEndPosition());
40 }
41
42 // Writing just one more bus should cause the leading frames to be dropped.
43 buffer.Write(position, *bus, 1.0);
44 position += frames_per_bus;
45 EXPECT_EQ(position - kMaxFrames, buffer.GetBeginPosition());
46 EXPECT_EQ(position, buffer.GetEndPosition());
47
48 // Now, simulate a gap in the recording by recording the next bus late.
49 position += frames_per_bus * 2;
50 buffer.Write(position, *bus, 1.0);
51 position += frames_per_bus;
52 EXPECT_EQ(position - kMaxFrames, buffer.GetBeginPosition());
53 EXPECT_EQ(position, buffer.GetEndPosition());
54 }
55
TEST(DelayBufferTest,ReadsSilenceIfNothingWasRecorded)56 TEST(DelayBufferTest, ReadsSilenceIfNothingWasRecorded) {
57 DelayBuffer buffer(kMaxFrames);
58 ASSERT_EQ(buffer.GetBeginPosition(), buffer.GetEndPosition());
59
60 DelayBuffer::FrameTicks position = 0;
61 constexpr int frames_per_bus = kMaxFrames / 4;
62 const auto bus = media::AudioBus::Create(kChannels, frames_per_bus);
63
64 for (int i = 0; i < 10; ++i) {
65 // Set data in the bus to confirm it is all going to be overwritten.
66 std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 1.0);
67
68 buffer.Read(position, frames_per_bus, bus.get());
69 EXPECT_EQ(buffer.GetBeginPosition(), buffer.GetEndPosition());
70 EXPECT_BUS_VALUES_EQ(bus, 0, frames_per_bus, 0.0);
71
72 position += frames_per_bus;
73 }
74 }
75
TEST(DelayBufferTest,ReadsSilenceIfOutsideRecordedRange)76 TEST(DelayBufferTest, ReadsSilenceIfOutsideRecordedRange) {
77 DelayBuffer buffer(kMaxFrames);
78 ASSERT_EQ(buffer.GetBeginPosition(), buffer.GetEndPosition());
79
80 constexpr int frames_per_bus = kMaxFrames / 4;
81 const auto bus = media::AudioBus::Create(kChannels, frames_per_bus);
82 std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 1.0);
83
84 // Fill the buffer.
85 DelayBuffer::FrameTicks position = 0;
86 for (int i = 0; i < 4; ++i) {
87 buffer.Write(position, *bus, 1.0);
88 position += frames_per_bus;
89 }
90 EXPECT_EQ(0, buffer.GetBeginPosition());
91 EXPECT_EQ(position, buffer.GetEndPosition());
92
93 // Read before the begin position and expect to get silence.
94 std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 0.5);
95 buffer.Read(-kMaxFrames, frames_per_bus, bus.get());
96 EXPECT_BUS_VALUES_EQ(bus, 0, frames_per_bus, 0.0);
97
98 // Read at a position one before the begin position. Expect the first sample
99 // to be 0.0, and the rest 1.0.
100 std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 0.5);
101 buffer.Read(buffer.GetBeginPosition() - 1, frames_per_bus, bus.get());
102 EXPECT_EQ(0.0, bus->channel(0)[0]);
103 EXPECT_BUS_VALUES_EQ(bus, 1, frames_per_bus - 1, 1.0);
104
105 // Read at a position where the last sample should be 0.0 and the rest 1.0.
106 std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 0.5);
107 buffer.Read(buffer.GetEndPosition() - frames_per_bus + 1, frames_per_bus,
108 bus.get());
109 EXPECT_BUS_VALUES_EQ(bus, 0, frames_per_bus - 1, 1.0);
110 EXPECT_EQ(0.0, bus->channel(0)[frames_per_bus - 1]);
111
112 // Read after the end position and expect to get silence.
113 std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 0.5);
114 buffer.Read(kMaxFrames, frames_per_bus, bus.get());
115 EXPECT_BUS_VALUES_EQ(bus, 0, frames_per_bus, 0.0);
116 }
117
TEST(DelayBufferTest,ReadsGapsInRecording)118 TEST(DelayBufferTest, ReadsGapsInRecording) {
119 DelayBuffer buffer(kMaxFrames);
120 ASSERT_EQ(buffer.GetBeginPosition(), buffer.GetEndPosition());
121
122 constexpr int frames_per_bus = kMaxFrames / 4;
123 const auto bus = media::AudioBus::Create(kChannels, frames_per_bus);
124 std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 1.0);
125
126 // Fill the buffer, but with a gap in the third quarter of it.
127 DelayBuffer::FrameTicks record_position = 0;
128 for (int i = 0; i < 4; ++i) {
129 if (i != 2) {
130 buffer.Write(record_position, *bus, 1.0);
131 }
132 record_position += frames_per_bus;
133 }
134 EXPECT_EQ(0, buffer.GetBeginPosition());
135 EXPECT_EQ(record_position, buffer.GetEndPosition());
136
137 // Read through the whole range, but offset by one frame early. Confirm the
138 // silence gap appears in the right place.
139 DelayBuffer::FrameTicks read_position = -1;
140 std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 0.5);
141 buffer.Read(read_position, frames_per_bus, bus.get());
142 read_position += frames_per_bus;
143 EXPECT_EQ(0.0, bus->channel(0)[0]);
144 EXPECT_BUS_VALUES_EQ(bus, 1, frames_per_bus - 1, 1.0);
145
146 std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 0.5);
147 buffer.Read(read_position, frames_per_bus, bus.get());
148 read_position += frames_per_bus;
149 EXPECT_BUS_VALUES_EQ(bus, 0, frames_per_bus, 1.0);
150
151 std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 0.5);
152 buffer.Read(read_position, frames_per_bus, bus.get());
153 read_position += frames_per_bus;
154 EXPECT_EQ(1.0, bus->channel(0)[0]);
155 // The gap begins.
156 EXPECT_BUS_VALUES_EQ(bus, 1, frames_per_bus - 1, 0.0);
157
158 std::fill(bus->channel(0), bus->channel(0) + frames_per_bus, 0.5);
159 buffer.Read(read_position, frames_per_bus, bus.get());
160 read_position += frames_per_bus;
161 EXPECT_EQ(0.0, bus->channel(0)[0]);
162 // The gap ends.
163 EXPECT_BUS_VALUES_EQ(bus, 1, frames_per_bus - 1, 1.0);
164 }
165
166 } // namespace
167 } // namespace audio
168