1
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
5
An audio time-stretching and pitch-shifting library.
6
Copyright 2007-2008 Chris Cannam.
8
This program is free software; you can redistribute it and/or
9
modify it under the terms of the GNU General Public License as
10
published by the Free Software Foundation; either version 2 of the
11
License, or (at your option) any later version. See the file
12
COPYING included with this distribution for more information.
15
#ifndef _RUBBERBAND_RINGBUFFER_H_
16
#define _RUBBERBAND_RINGBUFFER_H_
19
#include <sys/types.h>
27
#include "Scavenger.h"
31
//#define DEBUG_RINGBUFFER 1
35
#define MUNLOCK(a,b) 1
37
#define MLOCK(a,b) ::mlock(a,b)
38
#define MUNLOCK(a,b) ::munlock(a,b)
41
#ifdef DEBUG_RINGBUFFER
45
namespace RubberBand {
48
* RingBuffer implements a lock-free ring buffer for one writer and N
49
* readers, that is to be used to store a sample type T.
52
template <typename T, int N = 1>
57
* Create a ring buffer with room to write n samples.
59
* Note that the internal storage size will actually be n+1
60
* samples, as one element is unavailable for administrative
61
* reasons. Since the ring buffer performs best if its size is a
62
* power of two, this means n should ideally be some power of two
67
virtual ~RingBuffer();
70
* Return the total capacity of the ring buffer in samples.
71
* (This is the argument n passed to the constructor.)
76
* Resize the ring buffer. This also empties it; use resized()
77
* below if you do not want this to happen. Actually swaps in a
78
* new, larger buffer; the old buffer is scavenged after a seemly
79
* delay. Should be called from the write thread.
81
void resize(int newSize);
84
* Return a new ring buffer (allocated with "new" -- called must
85
* delete when no longer needed) of the given size, containing the
86
* same data as this one. If another thread reads from or writes
87
* to this buffer during the call, the results may be incomplete
88
* or inconsistent. If this buffer's data will not fit in the new
89
* size, the contents are undefined.
91
RingBuffer<T, N> *resized(int newSize, int R = 0) const;
94
* Lock the ring buffer into physical memory. Returns true
100
* Reset read and write pointers, thus emptying the buffer.
101
* Should be called from the write thread.
106
* Return the amount of data available for reading by reader R, in
109
int getReadSpace(int R = 0) const;
112
* Return the amount of space available for writing, in samples.
114
int getWriteSpace() const;
117
* Read n samples from the buffer, for reader R. If fewer than n
118
* are available, the remainder will be zeroed out. Returns the
119
* number of samples actually read.
121
int read(T *R__ destination, int n, int R = 0);
124
* Read n samples from the buffer, for reader R, adding them to
125
* the destination. If fewer than n are available, the remainder
126
* will be left alone. Returns the number of samples actually
129
int readAdding(T *R__ destination, int n, int R = 0);
132
* Read one sample from the buffer, for reader R. If no sample is
133
* available, this will silently return zero. Calling this
134
* repeatedly is obviously slower than calling read once, but it
135
* may be good enough if you don't want to allocate a buffer to
138
T readOne(int R = 0);
141
* Read n samples from the buffer, if available, for reader R,
142
* without advancing the read pointer -- i.e. a subsequent read()
143
* or skip() will be necessary to empty the buffer. If fewer than
144
* n are available, the remainder will be zeroed out. Returns the
145
* number of samples actually read.
147
int peek(T *R__ destination, int n, int R = 0) const;
150
* Read one sample from the buffer, if available, without
151
* advancing the read pointer -- i.e. a subsequent read() or
152
* skip() will be necessary to empty the buffer. Returns zero if
153
* no sample was available.
155
T peekOne(int R = 0) const;
158
* Pretend to read n samples from the buffer, for reader R,
159
* without actually returning them (i.e. discard the next n
160
* samples). Returns the number of samples actually available for
163
int skip(int n, int R = 0);
166
* Write n samples to the buffer. If insufficient space is
167
* available, not all samples may actually be written. Returns
168
* the number of samples actually written.
170
int write(const T *source, int n);
173
* Write n zero-value samples to the buffer. If insufficient
174
* space is available, not all zeros may actually be written.
175
* Returns the number of zeroes actually written.
181
volatile int m_writer;
182
volatile int m_readers[N];
186
static Scavenger<ScavengerArrayWrapper<T> > m_scavenger;
189
RingBuffer(const RingBuffer &); // not provided
190
RingBuffer &operator=(const RingBuffer &); // not provided
193
template <typename T, int N>
194
Scavenger<ScavengerArrayWrapper<T> > RingBuffer<T, N>::m_scavenger;
196
template <typename T, int N>
197
RingBuffer<T, N>::RingBuffer(int n) :
198
m_buffer(new T[n + 1]),
203
#ifdef DEBUG_RINGBUFFER
204
std::cerr << "RingBuffer<T," << N << ">[" << this << "]::RingBuffer(" << n << ")" << std::endl;
207
for (int i = 0; i < N; ++i) m_readers[i] = 0;
209
m_scavenger.scavenge();
212
template <typename T, int N>
213
RingBuffer<T, N>::~RingBuffer()
215
#ifdef DEBUG_RINGBUFFER
216
std::cerr << "RingBuffer<T," << N << ">[" << this << "]::~RingBuffer" << std::endl;
220
MUNLOCK((void *)m_buffer, m_size * sizeof(T));
224
m_scavenger.scavenge();
227
template <typename T, int N>
229
RingBuffer<T, N>::getSize() const
231
#ifdef DEBUG_RINGBUFFER
232
std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getSize(): " << m_size-1 << std::endl;
238
template <typename T, int N>
240
RingBuffer<T, N>::resize(int newSize)
242
#ifdef DEBUG_RINGBUFFER
243
std::cerr << "RingBuffer<T," << N << ">[" << this << "]::resize(" << newSize << ")" << std::endl;
246
m_scavenger.scavenge();
249
MUNLOCK((void *)m_buffer, m_size * sizeof(T));
252
m_scavenger.claim(new ScavengerArrayWrapper<T>(m_buffer));
255
m_buffer = new T[newSize + 1];
256
m_size = newSize + 1;
259
if (MLOCK((void *)m_buffer, m_size * sizeof(T))) {
265
template <typename T, int N>
267
RingBuffer<T, N>::resized(int newSize, int R) const
269
RingBuffer<T, N> *newBuffer = new RingBuffer<T, N>(newSize);
272
int r = m_readers[R];
275
T value = m_buffer[r];
276
newBuffer->write(&value, 1);
277
if (++r == m_size) r = 0;
283
template <typename T, int N>
285
RingBuffer<T, N>::mlock()
287
if (MLOCK((void *)m_buffer, m_size * sizeof(T))) return false;
292
template <typename T, int N>
294
RingBuffer<T, N>::reset()
296
#ifdef DEBUG_RINGBUFFER
297
std::cerr << "RingBuffer<T," << N << ">[" << this << "]::reset" << std::endl;
301
for (int i = 0; i < N; ++i) m_readers[i] = 0;
304
template <typename T, int N>
306
RingBuffer<T, N>::getReadSpace(int R) const
308
int writer = m_writer;
309
int reader = m_readers[R];
312
#ifdef DEBUG_RINGBUFFER
313
std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getReadSpace(" << R << "): reader " << reader << ", writer " << writer << std::endl;
316
if (writer > reader) space = writer - reader;
317
else if (writer < reader) space = (writer + m_size) - reader;
320
#ifdef DEBUG_RINGBUFFER
321
std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getReadSpace(" << R << "): " << space << std::endl;
327
template <typename T, int N>
329
RingBuffer<T, N>::getWriteSpace() const
332
for (int i = 0; i < N; ++i) {
333
int writer = m_writer;
334
int reader = m_readers[i];
335
int here = (reader + m_size - writer - 1);
336
if (here >= m_size) here -= m_size;
337
if (i == 0 || here < space) space = here;
340
#ifdef DEBUG_RINGBUFFER
341
int rs(getReadSpace()), rp(m_readers[0]);
343
std::cerr << "RingBuffer: write space " << space << ", read space "
344
<< rs << ", total " << (space + rs) << ", m_size " << m_size << std::endl;
345
std::cerr << "RingBuffer: reader " << rp << ", writer " << m_writer << std::endl;
348
#ifdef DEBUG_RINGBUFFER
349
std::cerr << "RingBuffer<T," << N << ">[" << this << "]::getWriteSpace(): " << space << std::endl;
355
template <typename T, int N>
357
RingBuffer<T, N>::read(T *R__ destination, int n, int R)
359
Profiler profiler("RingBuffer::read");
361
#ifdef DEBUG_RINGBUFFER
362
std::cerr << "RingBuffer<T," << N << ">[" << this << "]::read(dest, " << n << ", " << R << ")" << std::endl;
365
int available = getReadSpace(R);
367
#ifdef DEBUG_RINGBUFFER
368
std::cerr << "WARNING: Only " << available << " samples available"
371
for (int i = available; i < n; ++i) {
376
if (n == 0) return n;
378
int reader = m_readers[R];
379
int here = m_size - reader;
380
T *const R__ bufbase = m_buffer + reader;
383
for (int i = 0; i < n; ++i) {
384
destination[i] = bufbase[i];
387
for (int i = 0; i < here; ++i) {
388
destination[i] = bufbase[i];
390
T *const R__ destbase = destination + here;
391
const int nh = n - here;
392
for (int i = 0; i < nh; ++i) {
393
destbase[i] = m_buffer[i];
398
while (reader >= m_size) reader -= m_size;
399
m_readers[R] = reader;
401
#ifdef DEBUG_RINGBUFFER
402
std::cerr << "RingBuffer<T," << N << ">[" << this << "]::read: read " << n << ", reader now " << m_readers[R] << std::endl;
408
template <typename T, int N>
410
RingBuffer<T, N>::readAdding(T *R__ destination, int n, int R)
412
Profiler profiler("RingBuffer::readAdding");
414
#ifdef DEBUG_RINGBUFFER
415
std::cerr << "RingBuffer<T," << N << ">[" << this << "]::readAdding(dest, " << n << ", " << R << ")" << std::endl;
418
int available = getReadSpace(R);
420
#ifdef DEBUG_RINGBUFFER
421
std::cerr << "WARNING: Only " << available << " samples available"
426
if (n == 0) return n;
428
int reader = m_readers[R];
429
int here = m_size - reader;
430
const T *const R__ bufbase = m_buffer + reader;
433
for (int i = 0; i < n; ++i) {
434
destination[i] += bufbase[i];
437
for (int i = 0; i < here; ++i) {
438
destination[i] += bufbase[i];
440
T *const R__ destbase = destination + here;
441
const int nh = n - here;
442
for (int i = 0; i < nh; ++i) {
443
destbase[i] += m_buffer[i];
448
while (reader >= m_size) reader -= m_size;
449
m_readers[R] = reader;
453
template <typename T, int N>
455
RingBuffer<T, N>::readOne(int R)
457
#ifdef DEBUG_RINGBUFFER
458
std::cerr << "RingBuffer<T," << N << ">[" << this << "]::readOne(" << R << ")" << std::endl;
461
if (m_writer == m_readers[R]) {
462
#ifdef DEBUG_RINGBUFFER
463
std::cerr << "WARNING: No sample available"
468
int reader = m_readers[R];
469
T value = m_buffer[reader];
470
if (++reader == m_size) reader = 0;
471
m_readers[R] = reader;
475
template <typename T, int N>
477
RingBuffer<T, N>::peek(T *R__ destination, int n, int R) const
479
Profiler profiler("RingBuffer::peek");
481
#ifdef DEBUG_RINGBUFFER
482
std::cerr << "RingBuffer<T," << N << ">[" << this << "]::peek(dest, " << n << ", " << R << ")" << std::endl;
485
int available = getReadSpace(R);
487
#ifdef DEBUG_RINGBUFFER
488
std::cerr << "WARNING: Only " << available << " samples available"
491
memset(destination + available, 0, (n - available) * sizeof(T));
494
if (n == 0) return n;
496
int reader = m_readers[R];
497
int here = m_size - reader;
498
const T *const R__ bufbase = m_buffer + reader;
501
for (int i = 0; i < n; ++i) {
502
destination[i] = bufbase[i];
505
for (int i = 0; i < here; ++i) {
506
destination[i] = bufbase[i];
508
T *const R__ destbase = destination + here;
509
const int nh = n - here;
510
for (int i = 0; i < nh; ++i) {
511
destbase[i] = m_buffer[i];
515
#ifdef DEBUG_RINGBUFFER
516
std::cerr << "RingBuffer<T," << N << ">[" << this << "]::peek: read " << n << std::endl;
522
template <typename T, int N>
524
RingBuffer<T, N>::peekOne(int R) const
526
#ifdef DEBUG_RINGBUFFER
527
std::cerr << "RingBuffer<T," << N << ">[" << this << "]::peek(" << R << ")" << std::endl;
530
if (m_writer == m_readers[R]) {
531
#ifdef DEBUG_RINGBUFFER
532
std::cerr << "WARNING: No sample available"
537
T value = m_buffer[m_readers[R]];
541
template <typename T, int N>
543
RingBuffer<T, N>::skip(int n, int R)
545
#ifdef DEBUG_RINGBUFFER
546
std::cerr << "RingBuffer<T," << N << ">[" << this << "]::skip(" << n << ", " << R << ")" << std::endl;
549
int available = getReadSpace(R);
551
#ifdef DEBUG_RINGBUFFER
552
std::cerr << "WARNING: Only " << available << " samples available"
557
if (n == 0) return n;
559
int reader = m_readers[R];
561
while (reader >= m_size) reader -= m_size;
562
m_readers[R] = reader;
566
template <typename T, int N>
568
RingBuffer<T, N>::write(const T *source, int n)
570
Profiler profiler("RingBuffer::write");
572
#ifdef DEBUG_RINGBUFFER
573
std::cerr << "RingBuffer<T," << N << ">[" << this << "]::write(" << n << ")" << std::endl;
576
int available = getWriteSpace();
578
#ifdef DEBUG_RINGBUFFER
579
std::cerr << "WARNING: Only room for " << available << " samples"
584
if (n == 0) return n;
586
int writer = m_writer;
587
int here = m_size - writer;
588
T *const R__ bufbase = m_buffer + writer;
591
for (int i = 0; i < n; ++i) {
592
bufbase[i] = source[i];
595
for (int i = 0; i < here; ++i) {
596
bufbase[i] = source[i];
598
const int nh = n - here;
599
const T *const R__ srcbase = source + here;
600
T *const R__ buf = m_buffer;
601
for (int i = 0; i < nh; ++i) {
607
while (writer >= m_size) writer -= m_size;
610
#ifdef DEBUG_RINGBUFFER
611
std::cerr << "RingBuffer<T," << N << ">[" << this << "]::write: wrote " << n << ", writer now " << m_writer << std::endl;
617
template <typename T, int N>
619
RingBuffer<T, N>::zero(int n)
621
Profiler profiler("RingBuffer::zero");
623
#ifdef DEBUG_RINGBUFFER
624
std::cerr << "RingBuffer<T," << N << ">[" << this << "]::zero(" << n << ")" << std::endl;
627
int available = getWriteSpace();
629
#ifdef DEBUG_RINGBUFFER
630
std::cerr << "WARNING: Only room for " << available << " samples"
635
if (n == 0) return n;
637
int writer = m_writer;
638
int here = m_size - writer;
639
T *const R__ bufbase = m_buffer + writer;
642
for (int i = 0; i < n; ++i) {
646
for (int i = 0; i < here; ++i) {
649
const int nh = n - here;
650
for (int i = 0; i < nh; ++i) {
656
while (writer >= m_size) writer -= m_size;
659
#ifdef DEBUG_RINGBUFFER
660
std::cerr << "writer -> " << m_writer << std::endl;
668
//#include "RingBuffer.cpp"
670
#endif // _RINGBUFFER_H_