66#define ATK_RATE_FACTOR 1 .001f
77#define ATK_SMOOTHING_SPEED 1 .0f
88
9- class FifoBuffer2
9+ class FifoBuffer2 : public juce ::Timer
1010{
1111public:
1212 FifoBuffer2 ()
13- : buffer()
14- , fifo(1 )
13+ : minNumChannels(2 )
14+ , minBufferSize(2048 )
15+ , buffer(minNumChannels, minBufferSize + 1 )
16+ , fifo(minBufferSize + 1 )
1517 {
18+ timerCallback ();
19+ startTimer (100 );
1620 }
1721
18- void setSize ( int numChannels, int numSamples)
22+ void timerCallback () override
1923 {
20- buffer.setSize (numChannels, numSamples, false , false , true );
21- fifo.setTotalSize (numSamples);
22- this ->reset ();
24+ if (isPrepared.load (std::memory_order_acquire))
25+ return ;
26+
27+ juce::ScopedLock lock1 (writeLock);
28+ juce::ScopedLock lock2 (readLock);
29+
30+ fifo.reset ();
31+ auto freeSpace = fifo.getFreeSpace ();
32+
33+ if (freeSpace < minBufferSize)
34+ freeSpace = 2 * freeSpace;
35+
36+ if (buffer.getNumChannels () < minNumChannels)
37+ minNumChannels = 2 * minNumChannels;
38+
39+ setSize (minNumChannels, freeSpace);
40+
41+ isPrepared.store (true , std::memory_order_release);
2342 }
2443
2544 int write (const float * const * src, int numChannels, int numSamples)
2645 {
27- jassert (buffer.getNumSamples () >= numSamples);
28- jassert (buffer.getNumChannels () >= numChannels);
46+ juce::ScopedLock lock (writeLock);
47+
48+ if (minBufferSize < numSamples || minNumChannels < numChannels)
49+ {
50+ isPrepared.store (false , std::memory_order_release);
51+
52+ minBufferSize = std::max (minBufferSize, numSamples);
53+ minNumChannels = std::max (minNumChannels, numChannels);
54+ }
55+
56+ if (!isPrepared.load (std::memory_order_acquire))
57+ return 0 ;
58+
59+ numChannels = std::min (numChannels, buffer.getNumChannels ());
2960
3061 int start1, size1, start2, size2;
3162 int written = 0 ;
@@ -44,15 +75,27 @@ class FifoBuffer2
4475 written += size2;
4576 }
4677
78+ // jassert(written == numSamples);
79+
4780 fifo.finishedWrite (written);
4881 return written;
4982 }
5083
5184 int read (float * const * dest, int numChannels, int numSamples, bool advanceRead = true , bool addToBuffer = false )
5285 {
53- jassert (buffer.getNumSamples () >= numSamples);
54- jassert (buffer.getNumChannels () >= numChannels);
55- jassert (fifo.getNumReady () >= numSamples);
86+ juce::ScopedLock lock (readLock);
87+ if (minBufferSize < numSamples || minNumChannels < numChannels)
88+ {
89+ isPrepared.store (false , std::memory_order_release);
90+
91+ minBufferSize = std::max (minBufferSize, numSamples);
92+ minNumChannels = std::max (minNumChannels, numChannels);
93+ }
94+
95+ if (!isPrepared.load (std::memory_order_acquire))
96+ return 0 ;
97+
98+ numChannels = std::min (numChannels, buffer.getNumChannels ());
5699
57100 int start1, size1, start2, size2;
58101 int readCount = 0 ;
@@ -91,8 +134,6 @@ class FifoBuffer2
91134 readCount += size2;
92135 }
93136
94- jassert (readCount == numSamples);
95-
96137 if (advanceRead)
97138 fifo.finishedRead (readCount);
98139
@@ -114,12 +155,6 @@ class FifoBuffer2
114155 return fifo.getFreeSpace ();
115156 }
116157
117- void reset ()
118- {
119- buffer.clear ();
120- fifo.reset ();
121- }
122-
123158 auto & getBuffer ()
124159 {
125160 return buffer;
@@ -131,8 +166,29 @@ class FifoBuffer2
131166 }
132167
133168private:
169+ void reset ()
170+ {
171+ buffer.clear ();
172+ fifo.reset ();
173+ }
174+
175+ void setSize (int numChannels, int numSamples)
176+ {
177+ buffer.setSize (numChannels, numSamples + 1 , false , false , true );
178+ fifo.setTotalSize (numSamples + 1 );
179+ reset ();
180+ }
181+
182+ private:
183+ int minBufferSize;
184+ int minNumChannels;
185+
134186 juce::AudioBuffer<float > buffer;
135187 juce::AbstractFifo fifo;
188+
189+ juce::CriticalSection writeLock;
190+ juce::CriticalSection readLock;
191+ std::atomic_bool isPrepared{false };
136192};
137193
138194class SyncBuffer : public juce ::Timer
@@ -143,7 +199,7 @@ class SyncBuffer : public juce::Timer
143199 , readerBufferSize(-1 )
144200 , writerBufferSize(-1 )
145201 {
146- startTimerHz ( 60 );
202+ startTimer ( 100 );
147203 }
148204
149205 void timerCallback () override
@@ -194,17 +250,13 @@ class SyncBuffer : public juce::Timer
194250
195251 tempBuffer.setSize (numChannels, 2 * maxBufferSize, false , false , true );
196252
197- fifoBuffer.setSize (numChannels, 2 * maxBufferSize);
198-
199253 rateSmoothing.reset (
200254 readerSampleRate.load (std::memory_order_acquire) / readerBufferSize.load (std::memory_order_acquire) * 1.0 ,
201255 ATK_SMOOTHING_SPEED
202256 );
203257 rateSmoothing.setCurrentAndTargetValue (1.0 );
204258
205259 tempBuffer.clear ();
206- for (int ch = 0 ; ch < numChannels; ++ch)
207- tempBuffer.clear (ch, 0 , minBufferSize);
208260 fifoBuffer.write (tempBuffer.getArrayOfWritePointers (), numChannels, minBufferSize);
209261
210262 isPrepared.store (true , std::memory_order_release);
@@ -268,12 +320,16 @@ class SyncBuffer : public juce::Timer
268320
269321 int samplesNeeded = std::ceil (numSamples * ratio);
270322
323+ if (!addToBuffer)
324+ for (int ch = 0 ; ch < numChannels; ++ch)
325+ std::memset (dest[ch], 0 , sizeof (float ) * numSamples);
326+
327+ #ifdef JUCE_DEBUG
271328 if (maxAvailable < samplesNeeded)
272- return 0 ;
329+ DBG (" needed " << samplesNeeded << " available " << maxAvailable << " ratio " << ratio);
330+ #endif
273331
274- // #if defined(JUCE_DEBUG) && defined(JUCE_WINDOWS)
275- // DBG(ratio);
276- // #endif
332+ tempBuffer.setSize (numChannels, samplesNeeded, false , false , true );
277333
278334 auto samplesGot = fifoBuffer.read (tempBuffer.getArrayOfWritePointers (), numChannels, samplesNeeded, false );
279335
@@ -282,25 +338,15 @@ class SyncBuffer : public juce::Timer
282338 for (int i = 0 ; i < interpolators.size (); i++)
283339 {
284340 auto ch = i % numChannels;
285- if (addToBuffer || ch >= interpolators.size ())
286- samplesConsumed = interpolators[i].processAdding (
287- ratio,
288- tempBuffer.getReadPointer (ch),
289- dest[ch],
290- numSamples,
291- maxAvailable,
292- maxAvailable,
293- 1 .0f
294- );
295- else
296- samplesConsumed = interpolators[i].process (
297- ratio,
298- tempBuffer.getReadPointer (ch),
299- dest[ch],
300- numSamples,
301- maxAvailable,
302- maxAvailable
303- );
341+ samplesConsumed = interpolators[i].processAdding (
342+ ratio,
343+ tempBuffer.getReadPointer (ch),
344+ dest[ch],
345+ numSamples,
346+ maxAvailable,
347+ maxAvailable,
348+ 1 .0f
349+ );
304350 }
305351
306352 fifoBuffer.advanceRead (samplesConsumed);
@@ -347,7 +393,6 @@ class SyncBuffer : public juce::Timer
347393 std::vector<juce::LagrangeInterpolator> interpolators;
348394
349395 juce::AudioBuffer<float > tempBuffer;
350- // std::vector<float*> tempPtrs;
351396
352397 std::atomic<int > readerBufferSize;
353398 std::atomic<int > writerBufferSize;
@@ -364,7 +409,4 @@ class SyncBuffer : public juce::Timer
364409
365410 juce::CriticalSection readLock;
366411 juce::CriticalSection writeLock;
367-
368- // std::atomic_bool isReading = false;
369- // std::atomic_bool isWriting = false;
370412};
0 commit comments