mirror of
https://github.com/cookiengineer/audacity
synced 2025-10-21 06:01:13 +02:00
Possibly correct some cases of clicky playback or corrupt recording...
... By reusing portaudio's ring buffer class, which has more safe inter-thread synchronization with memory fences
This commit is contained in:
@@ -23,12 +23,45 @@
|
||||
|
||||
|
||||
#include "RingBuffer.h"
|
||||
#include "Experimental.h"
|
||||
|
||||
#undef REWRITE_RING_BUFFER
|
||||
|
||||
// For now enabling the rewrite only for Mac
|
||||
|
||||
#ifdef EXPERIMENTAL_REWRITE_RING_BUFFER
|
||||
#define REWRITE_RING_BUFFER
|
||||
#elif defined (__APPLE__)
|
||||
#define REWRITE_RING_BUFFER
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
size_t roundUp(size_t n)
|
||||
{
|
||||
#ifdef REWRITE_RING_BUFFER
|
||||
// PaUtilRingBuffer requires a power of 2
|
||||
if (n == 0)
|
||||
return 1;
|
||||
|
||||
size_t prev = n;
|
||||
for (size_t temp = n; temp != 0; prev = temp, temp = ((temp - 1) & temp))
|
||||
;
|
||||
return prev == n ? prev : prev << 1;
|
||||
#else
|
||||
return n;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
RingBuffer::RingBuffer(sampleFormat format, size_t size)
|
||||
: mFormat{ format }
|
||||
, mBufferSize{ std::max<size_t>(size, 64) }
|
||||
, mBufferSize{ roundUp( std::max<size_t>(size, 64) ) }
|
||||
, mBuffer{ mBufferSize, mFormat }
|
||||
{
|
||||
#ifdef REWRITE_RING_BUFFER
|
||||
PaUtil_InitializeRingBuffer(
|
||||
&mRingBuffer, SAMPLE_SIZE(format), mBufferSize, mBuffer.ptr() );
|
||||
#endif
|
||||
}
|
||||
|
||||
RingBuffer::~RingBuffer()
|
||||
@@ -37,7 +70,11 @@ RingBuffer::~RingBuffer()
|
||||
|
||||
size_t RingBuffer::Len()
|
||||
{
|
||||
#ifdef REWRITE_RING_BUFFER
|
||||
return (mEnd + mBufferSize - mStart) % mBufferSize;
|
||||
#else
|
||||
assert(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
@@ -46,12 +83,19 @@ size_t RingBuffer::Len()
|
||||
|
||||
size_t RingBuffer::AvailForPut()
|
||||
{
|
||||
#ifdef REWRITE_RING_BUFFER
|
||||
return PaUtil_GetRingBufferWriteAvailable(&mRingBuffer);
|
||||
#else
|
||||
return std::max<size_t>(mBufferSize - Len(), 4) - 4;
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t RingBuffer::Put(samplePtr buffer, sampleFormat format,
|
||||
size_t samplesToCopy)
|
||||
{
|
||||
#ifdef REWRITE_RING_BUFFER
|
||||
return PaUtil_WriteRingBuffer(&mRingBuffer, buffer, samplesToCopy);
|
||||
#else
|
||||
samplesToCopy = std::min( samplesToCopy, AvailForPut() );
|
||||
auto src = buffer;
|
||||
size_t copied = 0;
|
||||
@@ -73,8 +117,11 @@ size_t RingBuffer::Put(samplePtr buffer, sampleFormat format,
|
||||
mEnd = pos;
|
||||
|
||||
return copied;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
// not used
|
||||
size_t RingBuffer::Clear(sampleFormat format, size_t samplesToClear)
|
||||
{
|
||||
samplesToClear = std::min( samplesToClear, AvailForPut() );
|
||||
@@ -95,6 +142,7 @@ size_t RingBuffer::Clear(sampleFormat format, size_t samplesToClear)
|
||||
|
||||
return cleared;
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// For the reader only:
|
||||
@@ -102,12 +150,19 @@ size_t RingBuffer::Clear(sampleFormat format, size_t samplesToClear)
|
||||
|
||||
size_t RingBuffer::AvailForGet()
|
||||
{
|
||||
#ifdef REWRITE_RING_BUFFER
|
||||
return PaUtil_GetRingBufferReadAvailable(&mRingBuffer);
|
||||
#else
|
||||
return Len();
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t RingBuffer::Get(samplePtr buffer, sampleFormat format,
|
||||
size_t samplesToCopy)
|
||||
{
|
||||
#ifdef REWRITE_RING_BUFFER
|
||||
return PaUtil_ReadRingBuffer(&mRingBuffer, buffer, samplesToCopy);
|
||||
#else
|
||||
samplesToCopy = std::min( samplesToCopy, Len() );
|
||||
auto dest = buffer;
|
||||
size_t copied = 0;
|
||||
@@ -126,13 +181,17 @@ size_t RingBuffer::Get(samplePtr buffer, sampleFormat format,
|
||||
}
|
||||
|
||||
return copied;
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t RingBuffer::Discard(size_t samplesToDiscard)
|
||||
{
|
||||
#ifdef REWRITE_RING_BUFFER
|
||||
PaUtil_AdvanceRingBufferReadIndex(&mRingBuffer, samplesToDiscard);
|
||||
#else
|
||||
samplesToDiscard = std::min( samplesToDiscard, Len() );
|
||||
|
||||
mStart = (mStart + samplesToDiscard) % mBufferSize;
|
||||
|
||||
#endif
|
||||
return samplesToDiscard;
|
||||
}
|
||||
|
Reference in New Issue
Block a user