Skip to main content

Ring Buffers

About Ring Buffers

Ring buffers, also known as circular buffers, are a common data structure used in audio programming to store and process audio samples.

A ring buffer is a fixed-sized buffer that is treated as if it were connected end-to-end, forming a loop. When data is written to the buffer, it is written to the current position and the position is incremented. If the position reaches the end of the buffer, it wraps around to the beginning of the buffer. Similarly, when data is read from the buffer, it is read from the current position and the position is incremented. If the position reaches the end of the buffer, it wraps around to the beginning of the buffer.

Ring buffers are useful in audio programming because they allow for efficient processing of continuous streams of audio data. For example, when recording audio, samples can be written to a ring buffer in real-time. When processing audio, the buffer can be read from at a constant rate, allowing for efficient processing without the need for expensive memory allocations or data copies.

Ring buffers can also be used to implement delay effects, such as reverb or echo, by reading samples from the buffer at a delayed time offset. Additionally, ring buffers can be used to implement circular or rotating buffers, which can be used to implement audio loops or other cyclic audio effects.

Using the AudioRingBuffer class

The AudioRingBuffer class provides a convenient way to read and write from different AudioBuffers.

You have to set its size with numberOfFrames and the audio properties to match to the input/output AudioBuffer:

  • data type of samples (float, int16)
  • number of channels
  • interleaved ([LRLRLR]) or non-interleaved ([LLL], [RRR]).

You can write and read from the AudioRingBuffer using produce and consume.

AudioRingBuffer<float> ringBuffer(48000, 2, false);

if (sourceBuffer.getNumberOfFrames() <= ringBuffer.getAvailableFramesToProduce()) {
ringBuffer.produce(sourceBuffer, sourceBuffer.getNumberOfFrames());
}

ringBuffer.consume(destinationBuffer, ringBuffer.getAvailableFramesToConsume())