OpenShot Audio Library | OpenShotAudio 0.3.2
Loading...
Searching...
No Matches
juce_AbstractFifo.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2017 - ROLI Ltd.
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
32
33int AbstractFifo::getTotalSize() const noexcept { return bufferSize; }
34int AbstractFifo::getFreeSpace() const noexcept { return bufferSize - getNumReady() - 1; }
35
37{
38 auto vs = validStart.get();
39 auto ve = validEnd.get();
40 return ve >= vs ? (ve - vs) : (bufferSize - (vs - ve));
41}
42
44{
45 validEnd = 0;
46 validStart = 0;
47}
48
50{
51 jassert (newSize > 0);
52 reset();
53 bufferSize = newSize;
54}
55
56//==============================================================================
57void AbstractFifo::prepareToWrite (int numToWrite, int& startIndex1, int& blockSize1,
58 int& startIndex2, int& blockSize2) const noexcept
59{
60 auto vs = validStart.get();
61 auto ve = validEnd.get();
62
63 auto freeSpace = ve >= vs ? (bufferSize - (ve - vs)) : (vs - ve);
64 numToWrite = jmin (numToWrite, freeSpace - 1);
65
66 if (numToWrite <= 0)
67 {
68 startIndex1 = 0;
69 startIndex2 = 0;
70 blockSize1 = 0;
71 blockSize2 = 0;
72 }
73 else
74 {
75 startIndex1 = ve;
76 startIndex2 = 0;
77 blockSize1 = jmin (bufferSize - ve, numToWrite);
78 numToWrite -= blockSize1;
79 blockSize2 = numToWrite <= 0 ? 0 : jmin (numToWrite, vs);
80 }
81}
82
84{
85 jassert (numWritten >= 0 && numWritten < bufferSize);
86
87 auto newEnd = validEnd.get() + numWritten;
88
89 if (newEnd >= bufferSize)
90 newEnd -= bufferSize;
91
92 validEnd = newEnd;
93}
94
95void AbstractFifo::prepareToRead (int numWanted, int& startIndex1, int& blockSize1,
96 int& startIndex2, int& blockSize2) const noexcept
97{
98 auto vs = validStart.get();
99 auto ve = validEnd.get();
100
101 auto numReady = ve >= vs ? (ve - vs) : (bufferSize - (vs - ve));
102 numWanted = jmin (numWanted, numReady);
103
104 if (numWanted <= 0)
105 {
106 startIndex1 = 0;
107 startIndex2 = 0;
108 blockSize1 = 0;
109 blockSize2 = 0;
110 }
111 else
112 {
113 startIndex1 = vs;
114 startIndex2 = 0;
115 blockSize1 = jmin (bufferSize - vs, numWanted);
116 numWanted -= blockSize1;
117 blockSize2 = numWanted <= 0 ? 0 : jmin (numWanted, ve);
118 }
119}
120
122{
123 jassert (numRead >= 0 && numRead <= bufferSize);
124
125 auto newStart = validStart.get() + numRead;
126
127 if (newStart >= bufferSize)
128 newStart -= bufferSize;
129
130 validStart = newStart;
131}
132
133//==============================================================================
134template <AbstractFifo::ReadOrWrite mode>
136 : startIndex1 (other.startIndex1),
137 blockSize1 (other.blockSize1),
138 startIndex2 (other.startIndex2),
139 blockSize2 (other.blockSize2)
140{
141 swap (other);
142}
143
144template <AbstractFifo::ReadOrWrite mode>
145AbstractFifo::ScopedReadWrite<mode>&
146AbstractFifo::ScopedReadWrite<mode>::operator= (ScopedReadWrite&& other) noexcept
147{
148 swap (other);
149 return *this;
150}
151
152template <AbstractFifo::ReadOrWrite mode>
153void AbstractFifo::ScopedReadWrite<mode>::swap (ScopedReadWrite& other) noexcept
154{
155 std::swap (other.fifo, fifo);
156 std::swap (other.startIndex1, startIndex1);
157 std::swap (other.blockSize1, blockSize1);
158 std::swap (other.startIndex2, startIndex2);
159 std::swap (other.blockSize2, blockSize2);
160}
161
162template class AbstractFifo::ScopedReadWrite<AbstractFifo::ReadOrWrite::read>;
163template class AbstractFifo::ScopedReadWrite<AbstractFifo::ReadOrWrite::write>;
164
165AbstractFifo::ScopedRead AbstractFifo::read (int numToRead) noexcept { return { *this, numToRead }; }
166AbstractFifo::ScopedWrite AbstractFifo::write (int numToWrite) noexcept { return { *this, numToWrite }; }
167
168
169//==============================================================================
170//==============================================================================
171#if JUCE_UNIT_TESTS
172
173class AbstractFifoTests : public UnitTest
174{
175public:
177 : UnitTest ("Abstract Fifo", UnitTestCategories::containers)
178 {}
179
180 struct WriteThread : public Thread
181 {
182 WriteThread (AbstractFifo& f, int* b, Random rng)
183 : Thread ("fifo writer"), fifo (f), buffer (b), random (rng)
184 {
185 startThread();
186 }
187
188 ~WriteThread()
189 {
190 stopThread (5000);
191 }
192
193 void run()
194 {
195 int n = 0;
196
197 while (! threadShouldExit())
198 {
199 int num = random.nextInt (2000) + 1;
200
201 auto writer = fifo.write (num);
202
203 jassert (writer.blockSize1 >= 0 && writer.blockSize2 >= 0);
204 jassert (writer.blockSize1 == 0
205 || (writer.startIndex1 >= 0 && writer.startIndex1 < fifo.getTotalSize()));
206 jassert (writer.blockSize2 == 0
207 || (writer.startIndex2 >= 0 && writer.startIndex2 < fifo.getTotalSize()));
208
209 writer.forEach ([this, &n] (int index) { this->buffer[index] = n++; });
210 }
211 }
212
213 AbstractFifo& fifo;
214 int* buffer;
215 Random random;
216 };
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
263static AbstractFifoTests fifoUnitTests;
264
265#endif
266
267} // 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