For a side project involving real-time audio processing I needed a FIFO or Circular Buffer to pass sample data from the microphone sampling thread to the processing thread. The sampling thread happens more often with smaller number of samples to put into the FIFO. The processing thread happens less frequently so requires a faster way to bulk read from the FIFO. The mirroring technique used in this FIFO reduces the bulk read operation to a single memcpy of contiguous memory without worrying about wrap around.

Mirrored FIFO

The concept was based on the techniques used in “virtual ring buffers” but without mapping virtual memory. For more information see: The Magic Ring Buffer and Circular (ring) buffer plus neat virtual memory mapping trick posts.

$ ./test.exe
MirroredFifo example usage

Empty fifo: canReadCount=0 canWriteCount=10
One entry in fifo: writeCount=1 canReadCount=1 canWriteCount=9
Contents: [0]
Full fifo: writeCount=9 canReadCount=10 canWriteCount=0
Contents: [0, 0, 1, 2, 3, 4, 5, 6, 7, 8]
One below full fifo: readCount=1 canReadCount=9 canWriteCount=1
Contents: [0, 1, 2, 3, 4, 5, 6, 7, 8]
Empty fifo: readCount=9 canReadCount=0 canWriteCount=10
Contents: []
Half Full fifo: writeCount=5 canReadCount=5 canWriteCount=5
Contents: [0, 1, 2, 3, 4]
Empty fifo: readCount=5 canReadCount=0 canWriteCount=10
Contents: []
Looped Full fifo: writeCount=10 canReadCount=10 canWriteCount=0
Contents: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Empty fifo: readCount=10 canReadCount=0 canWriteCount=10
Contents: []
Full fifo: writeCount=10 canReadCount=10 canWriteCount=0
Contents: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Cleared Empty fifo: canReadCount=0 canWriteCount=10
Contents: []
Half Full fifo: writeCount=5 canReadCount=5 canWriteCount=5
Contents: [0, 1, 2, 3, 4]
Full Overwritten fifo: writeCount=10 canReadCount=10 canWriteCount=0
Contents: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Source code for library and example is at https://github.com/bensherlock/sherlock-code/blob/master/include/MirroredFifo.h .