Skip to content

Instantly share code, notes, and snippets.

@mfep
Created November 30, 2019 17:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mfep/510a82b54f2692306134072a0aaf2afa to your computer and use it in GitHub Desktop.
Save mfep/510a82b54f2692306134072a0aaf2afa to your computer and use it in GitHub Desktop.
RingBuffer implementation with JUCE
#pragma once
#include "../JuceLibraryCode/JuceHeader.h"
class RingBuffer
{
public:
static constexpr int Channels = 2;
RingBuffer(int samples) :
_buffer(Channels, samples),
_playhead{ 0 }
{
}
void append(int numSamples, const float* ldata, const float* rdata)
{
const int bufferLength = _buffer.getNumSamples();
if (numSamples >= bufferLength)
{
// copy the end of the input to the full buffer
const float* lptr = ldata + numSamples - bufferLength;
const float* rptr = rdata + numSamples - bufferLength;
_buffer.copyFrom(0, 0, lptr, bufferLength);
_buffer.copyFrom(1, 0, rptr, bufferLength);
_playhead = 0;
}
else if (const int endCount = bufferLength - _playhead; numSamples > endCount)
{
// copy to the end of buffer then another copy to the beginning
_buffer.copyFrom(0, _playhead, ldata, endCount);
_buffer.copyFrom(1, _playhead, rdata, endCount);
const int startCount = numSamples - endCount;
_buffer.copyFrom(0, 0, ldata + endCount, startCount);
_buffer.copyFrom(1, 0, rdata + endCount, startCount);
_playhead = (_playhead + numSamples) % bufferLength;
}
else
{
// single copy to the playhead position
_buffer.copyFrom(0, _playhead, ldata, numSamples);
_buffer.copyFrom(1, _playhead, rdata, numSamples);
_playhead = (_playhead + numSamples) % bufferLength;
}
}
void read(int delaySamples, juce::AudioBuffer<float>& outputBuffer) const
{
jassert(outputBuffer.getNumChannels() == Channels);
const int bufferLength = _buffer.getNumSamples();
const int numSamples = outputBuffer.getNumSamples();
jassert(bufferLength >= numSamples + delaySamples);
if (_playhead >= delaySamples + numSamples)
{
outputBuffer.copyFrom(0, 0, _buffer, 0, _playhead - delaySamples - numSamples, numSamples);
outputBuffer.copyFrom(1, 0, _buffer, 1, _playhead - delaySamples - numSamples, numSamples);
}
else if (_playhead > delaySamples)
{
// copy leftover from end
const int leftoverStart = bufferLength + _playhead - delaySamples - numSamples;
const int leftoverCount = delaySamples + numSamples - _playhead;
outputBuffer.copyFrom(0, 0, _buffer, 0, leftoverStart, leftoverCount);
outputBuffer.copyFrom(1, 0, _buffer, 1, leftoverStart, leftoverCount);
// copy rest from start
const int remainingCount = numSamples - leftoverCount;
outputBuffer.copyFrom(0, leftoverCount, _buffer, 0, 0, remainingCount);
outputBuffer.copyFrom(1, leftoverCount, _buffer, 1, 0, remainingCount);
}
else
{
// copy all without overflow
const int start = bufferLength + _playhead - delaySamples - numSamples;
outputBuffer.copyFrom(0, 0, _buffer, 0, start, numSamples);
outputBuffer.copyFrom(1, 0, _buffer, 1, start, numSamples);
}
}
private:
juce::AudioBuffer<float> _buffer;
int _playhead;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment