OpenShot Audio Library | OpenShotAudio 0.4.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
31int AbstractFifo::getTotalSize() const noexcept { return bufferSize; }
32int AbstractFifo::getFreeSpace() const noexcept { return bufferSize - getNumReady() - 1; }
33
34int 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
41void AbstractFifo::reset() noexcept
42{
43 validEnd = 0;
44 validStart = 0;
45}
46
47void AbstractFifo::setTotalSize (int newSize) noexcept
48{
49 jassert (newSize > 0);
50 reset();
51 bufferSize = newSize;
52}
53
54//==============================================================================
55void 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
81void 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
93void 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
119void 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>
133AbstractFifo::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
void prepareToWrite(int numToWrite, int &startIndex1, int &blockSize1, int &startIndex2, int &blockSize2) const noexcept
int getTotalSize() const noexcept
void prepareToRead(int numWanted, int &startIndex1, int &blockSize1, int &startIndex2, int &blockSize2) const noexcept
AbstractFifo(int capacity) noexcept
void finishedRead(int numRead) noexcept
int getFreeSpace() const noexcept
void finishedWrite(int numWritten) noexcept
int getNumReady() const noexcept
void setTotalSize(int newSize) noexcept
Type get() const noexcept
Definition juce_Atomic.h:64