1
0
mirror of https://github.com/cookiengineer/audacity synced 2026-03-05 22:21:15 +01:00
Files
audacity/src/RingBuffer.cpp
Paul Licameli 9777d3e880 Alert user to drop-outs during recording...
1) When the program detects this, insert zeroes into the recording to keep the
other good parts synchronized.

2) When recording stops, a message box alerts the user, and a label track is
added showing the lost parts, labelled with consecutive numbers.

3) A menu item visible in alpha builds only is added to Tools, to simulate
recording errors at random times and test the reporting feature.
2018-01-15 14:48:39 -05:00

139 lines
3.0 KiB
C++

/**********************************************************************
Audacity: A Digital Audio Editor
RingBuffer.cpp
Dominic Mazzoni
*******************************************************************//*!
\class RingBuffer
\brief Holds streamed audio samples.
This class is thread-safe, assuming that there is only one
thread writing, and one thread reading. If two threads both
need to read, or both need to write, they need to lock this
class from outside using their own mutex.
AvailForPut and AvailForGet may underestimate but will never
overestimate.
*//*******************************************************************/
#include "RingBuffer.h"
RingBuffer::RingBuffer(sampleFormat format, size_t size)
: mFormat{ format }
, mBufferSize{ std::max<size_t>(size, 64) }
, mBuffer{ mBufferSize, mFormat }
{
}
RingBuffer::~RingBuffer()
{
}
size_t RingBuffer::Len()
{
return (mEnd + mBufferSize - mStart) % mBufferSize;
}
//
// For the writer only:
//
size_t RingBuffer::AvailForPut()
{
return std::max<size_t>(mBufferSize - Len(), 4) - 4;
}
size_t RingBuffer::Put(samplePtr buffer, sampleFormat format,
size_t samplesToCopy)
{
samplesToCopy = std::min( samplesToCopy, AvailForPut() );
auto src = buffer;
size_t copied = 0;
auto pos = mEnd;
while(samplesToCopy) {
auto block = std::min( samplesToCopy, mBufferSize - pos );
CopySamples(src, format,
mBuffer.ptr() + pos * SAMPLE_SIZE(mFormat), mFormat,
block);
src += block * SAMPLE_SIZE(format);
pos = (pos + block) % mBufferSize;
samplesToCopy -= block;
copied += block;
}
mEnd = pos;
return copied;
}
size_t RingBuffer::Clear(sampleFormat format, size_t samplesToClear)
{
samplesToClear = std::min( samplesToClear, AvailForPut() );
size_t cleared = 0;
auto pos = mEnd;
while(samplesToClear) {
auto block = std::min( samplesToClear, mBufferSize - pos );
ClearSamples(mBuffer.ptr(), format, pos, block);
pos = (pos + block) % mBufferSize;
samplesToClear -= block;
cleared += block;
}
mEnd = pos;
return cleared;
}
//
// For the reader only:
//
size_t RingBuffer::AvailForGet()
{
return Len();
}
size_t RingBuffer::Get(samplePtr buffer, sampleFormat format,
size_t samplesToCopy)
{
samplesToCopy = std::min( samplesToCopy, Len() );
auto dest = buffer;
size_t copied = 0;
while(samplesToCopy) {
auto block = std::min( samplesToCopy, mBufferSize - mStart );
CopySamples(mBuffer.ptr() + mStart * SAMPLE_SIZE(mFormat), mFormat,
dest, format,
block);
dest += block * SAMPLE_SIZE(format);
mStart = (mStart + block) % mBufferSize;
samplesToCopy -= block;
copied += block;
}
return copied;
}
size_t RingBuffer::Discard(size_t samplesToDiscard)
{
samplesToDiscard = std::min( samplesToDiscard, Len() );
mStart = (mStart + samplesToDiscard) % mBufferSize;
return samplesToDiscard;
}