OpenShot Audio Library | OpenShotAudio: juce_AbstractFifo.cpp Source File

OpenShot Audio Library | OpenShotAudio 1.0.0

Loading...
Searching...
No Matches
juce_AbstractFifo.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26AbstractFifo::AbstractFifo (int capacity) noexcept : bufferSize (capacity)
27{
28 jassert (bufferSize > 0);
29}
30
31 int AbstractFifo::getTotalSize() const noexcept { return bufferSize; }
32 int AbstractFifo::getFreeSpace() const noexcept { return bufferSize - getNumReady() - 1; }
33
34 int AbstractFifo::getNumReady() const noexcept
35{
36 auto vs = validStart.get();
37 auto ve = validEnd.get();
38 return ve >= vs ? (ve - vs) : (bufferSize - (vs - ve));
39}
40
41 void AbstractFifo::reset() noexcept
42{
43 validEnd = 0;
44 validStart = 0;
45}
46
47 void AbstractFifo::setTotalSize (int newSize) noexcept
48{
49 jassert (newSize > 0);
50 reset();
51 bufferSize = newSize;
52}
53
54//==============================================================================
55 void AbstractFifo::prepareToWrite (int numToWrite, int& startIndex1, int& blockSize1,
56 int& startIndex2, int& blockSize2) const noexcept
57{
58 auto vs = validStart.get();
59 auto ve = validEnd.get();
60
61 auto freeSpace = ve >= vs ? (bufferSize - (ve - vs)) : (vs - ve);
62 numToWrite = jmin (numToWrite, freeSpace - 1);
63
64 if (numToWrite <= 0)
65 {
66 startIndex1 = 0;
67 startIndex2 = 0;
68 blockSize1 = 0;
69 blockSize2 = 0;
70 }
71 else
72 {
73 startIndex1 = ve;
74 startIndex2 = 0;
75 blockSize1 = jmin (bufferSize - ve, numToWrite);
76 numToWrite -= blockSize1;
77 blockSize2 = numToWrite <= 0 ? 0 : jmin (numToWrite, vs);
78 }
79}
80
81 void AbstractFifo::finishedWrite (int numWritten) noexcept
82{
83 jassert (numWritten >= 0 && numWritten < bufferSize);
84
85 auto newEnd = validEnd.get() + numWritten;
86
87 if (newEnd >= bufferSize)
88 newEnd -= bufferSize;
89
90 validEnd = newEnd;
91}
92
93 void AbstractFifo::prepareToRead (int numWanted, int& startIndex1, int& blockSize1,
94 int& startIndex2, int& blockSize2) const noexcept
95{
96 auto vs = validStart.get();
97 auto ve = validEnd.get();
98
99 auto numReady = ve >= vs ? (ve - vs) : (bufferSize - (vs - ve));
100 numWanted = jmin (numWanted, numReady);
101
102 if (numWanted <= 0)
103 {
104 startIndex1 = 0;
105 startIndex2 = 0;
106 blockSize1 = 0;
107 blockSize2 = 0;
108 }
109 else
110 {
111 startIndex1 = vs;
112 startIndex2 = 0;
113 blockSize1 = jmin (bufferSize - vs, numWanted);
114 numWanted -= blockSize1;
115 blockSize2 = numWanted <= 0 ? 0 : jmin (numWanted, ve);
116 }
117}
118
119 void AbstractFifo::finishedRead (int numRead) noexcept
120{
121 jassert (numRead >= 0 && numRead <= bufferSize);
122
123 auto newStart = validStart.get() + numRead;
124
125 if (newStart >= bufferSize)
126 newStart -= bufferSize;
127
128 validStart = newStart;
129}
130
131//==============================================================================
132template <AbstractFifo::ReadOrWrite mode>
133 AbstractFifo::ScopedReadWrite<mode>::ScopedReadWrite (ScopedReadWrite&& other) noexcept
134 : startIndex1 (other.startIndex1),
135 blockSize1 (other.blockSize1),
136 startIndex2 (other.startIndex2),
137 blockSize2 (other.blockSize2)
138{
139 swap (other);
140}
141
142template <AbstractFifo::ReadOrWrite mode>
143AbstractFifo::ScopedReadWrite<mode>&
144AbstractFifo::ScopedReadWrite<mode>::operator= (ScopedReadWrite&& other) noexcept
145{
146 swap (other);
147 return *this;
148}
149
150template <AbstractFifo::ReadOrWrite mode>
151void AbstractFifo::ScopedReadWrite<mode>::swap (ScopedReadWrite& other) noexcept
152{
153 std::swap (other.fifo, fifo);
154 std::swap (other.startIndex1, startIndex1);
155 std::swap (other.blockSize1, blockSize1);
156 std::swap (other.startIndex2, startIndex2);
157 std::swap (other.blockSize2, blockSize2);
158}
159
160template class AbstractFifo::ScopedReadWrite<AbstractFifo::ReadOrWrite::read>;
161template class AbstractFifo::ScopedReadWrite<AbstractFifo::ReadOrWrite::write>;
162
163AbstractFifo::ScopedRead AbstractFifo::read (int numToRead) noexcept { return { *this, numToRead }; }
164AbstractFifo::ScopedWrite AbstractFifo::write (int numToWrite) noexcept { return { *this, numToWrite }; }
165
166
167//==============================================================================
168//==============================================================================
169#if JUCE_UNIT_TESTS
170
171class AbstractFifoTests final : public UnitTest
172{
173public:
174 AbstractFifoTests()
175 : UnitTest ("Abstract Fifo", UnitTestCategories::containers)
176 {}
177
178 struct WriteThread final : public Thread
179 {
180 WriteThread (AbstractFifo& f, int* b, Random rng)
181 : Thread ("fifo writer"), fifo (f), buffer (b), random (rng)
182 {
183 startThread();
184 }
185
186 ~WriteThread() override
187 {
188 stopThread (5000);
189 }
190
191 void run() override
192 {
193 int n = 0;
194
195 while (! threadShouldExit())
196 {
197 int num = random.nextInt (2000) + 1;
198
199 auto writer = fifo.write (num);
200
201 jassert (writer.blockSize1 >= 0 && writer.blockSize2 >= 0);
202 jassert (writer.blockSize1 == 0
203 || (writer.startIndex1 >= 0 && writer.startIndex1 < fifo.getTotalSize()));
204 jassert (writer.blockSize2 == 0
205 || (writer.startIndex2 >= 0 && writer.startIndex2 < fifo.getTotalSize()));
206
207 writer.forEach ([this, &n] (int index) { this->buffer[index] = n++; });
208 }
209 }
210
211 AbstractFifo& fifo;
212 int* buffer;
213 Random random;
214 };
215
216 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6262)
217
218 void runTest() override
219 {
220 beginTest ("AbstractFifo");
221
222 int buffer[5000];
223 AbstractFifo fifo (numElementsInArray (buffer));
224
225 WriteThread writer (fifo, buffer, getRandom());
226
227 int n = 0;
228 Random r = getRandom();
229 r.combineSeed (12345);
230
231 for (int count = 100000; --count >= 0;)
232 {
233 int num = r.nextInt (6000) + 1;
234
235 auto reader = fifo.read (num);
236
237 if (! (reader.blockSize1 >= 0 && reader.blockSize2 >= 0)
238 && (reader.blockSize1 == 0
239 || (reader.startIndex1 >= 0 && reader.startIndex1 < fifo.getTotalSize()))
240 && (reader.blockSize2 == 0
241 || (reader.startIndex2 >= 0 && reader.startIndex2 < fifo.getTotalSize())))
242 {
243 expect (false, "prepareToRead returned -ve values");
244 break;
245 }
246
247 bool failed = false;
248
249 reader.forEach ([&failed, &buffer, &n] (int index)
250 {
251 failed = (buffer[index] != n++) || failed;
252 });
253
254 if (failed)
255 {
256 expect (false, "read values were incorrect");
257 break;
258 }
259 }
260 }
261
262 JUCE_END_IGNORE_WARNINGS_MSVC
263};
264
265static AbstractFifoTests fifoUnitTests;
266
267#endif
268
269} // namespace juce
juce::AbstractFifo::ScopedReadWrite
Definition juce_AbstractFifo.h:203
juce::AbstractFifo::ScopedReadWrite::ScopedReadWrite
ScopedReadWrite()=default
juce::AbstractFifo
Definition juce_AbstractFifo.h:73
juce::AbstractFifo::reset
void reset() noexcept
Definition juce_AbstractFifo.cpp:41
juce::AbstractFifo::prepareToWrite
void prepareToWrite(int numToWrite, int &startIndex1, int &blockSize1, int &startIndex2, int &blockSize2) const noexcept
Definition juce_AbstractFifo.cpp:55
juce::AbstractFifo::getTotalSize
int getTotalSize() const noexcept
Definition juce_AbstractFifo.cpp:31
juce::AbstractFifo::read
ScopedRead read(int numToRead) noexcept
Definition juce_AbstractFifo.cpp:163
juce::AbstractFifo::prepareToRead
void prepareToRead(int numWanted, int &startIndex1, int &blockSize1, int &startIndex2, int &blockSize2) const noexcept
Definition juce_AbstractFifo.cpp:93
juce::AbstractFifo::AbstractFifo
AbstractFifo(int capacity) noexcept
Definition juce_AbstractFifo.cpp:26
juce::AbstractFifo::finishedRead
void finishedRead(int numRead) noexcept
Definition juce_AbstractFifo.cpp:119
juce::AbstractFifo::getFreeSpace
int getFreeSpace() const noexcept
Definition juce_AbstractFifo.cpp:32
juce::AbstractFifo::finishedWrite
void finishedWrite(int numWritten) noexcept
Definition juce_AbstractFifo.cpp:81
juce::AbstractFifo::write
ScopedWrite write(int numToWrite) noexcept
Definition juce_AbstractFifo.cpp:164
juce::AbstractFifo::getNumReady
int getNumReady() const noexcept
Definition juce_AbstractFifo.cpp:34
juce::AbstractFifo::setTotalSize
void setTotalSize(int newSize) noexcept
Definition juce_AbstractFifo.cpp:47
juce::Random
Definition juce_Random.h:35
juce::UnitTest
Definition juce_UnitTest.h:70