lbajardsilogic@0: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ lbajardsilogic@0: lbajardsilogic@0: /* lbajardsilogic@0: Sonic Visualiser lbajardsilogic@0: An audio file viewer and annotation editor. lbajardsilogic@0: Centre for Digital Music, Queen Mary, University of London. lbajardsilogic@0: lbajardsilogic@0: This program is free software; you can redistribute it and/or lbajardsilogic@0: modify it under the terms of the GNU General Public License as lbajardsilogic@0: published by the Free Software Foundation; either version 2 of the lbajardsilogic@0: License, or (at your option) any later version. See the file lbajardsilogic@0: COPYING included with this distribution for more information. lbajardsilogic@0: */ lbajardsilogic@0: lbajardsilogic@0: /* lbajardsilogic@0: This is a modified version of a source file from the lbajardsilogic@0: Rosegarden MIDI and audio sequencer and notation editor. lbajardsilogic@0: This file copyright 2000-2006 Chris Cannam. lbajardsilogic@0: */ lbajardsilogic@0: lbajardsilogic@0: #ifndef _RINGBUFFER_H_ lbajardsilogic@0: #define _RINGBUFFER_H_ lbajardsilogic@0: lbajardsilogic@0: #include lbajardsilogic@0: lbajardsilogic@0: #include "system/System.h" lbajardsilogic@0: #include "Scavenger.h" lbajardsilogic@0: lbajardsilogic@0: //#define DEBUG_RINGBUFFER 1 lbajardsilogic@0: lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: #include lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * RingBuffer implements a lock-free ring buffer for one writer and N lbajardsilogic@0: * readers, that is to be used to store a sample type T. lbajardsilogic@0: * lbajardsilogic@0: * For efficiency, RingBuffer frequently initialises samples by lbajardsilogic@0: * writing zeroes into their memory space, so T should normally be a lbajardsilogic@0: * simple type that can safely be set to zero using memset. lbajardsilogic@0: */ lbajardsilogic@0: lbajardsilogic@0: template lbajardsilogic@0: class RingBuffer lbajardsilogic@0: { lbajardsilogic@0: public: lbajardsilogic@0: /** lbajardsilogic@0: * Create a ring buffer with room to write n samples. lbajardsilogic@0: * lbajardsilogic@0: * Note that the internal storage size will actually be n+1 lbajardsilogic@0: * samples, as one element is unavailable for administrative lbajardsilogic@0: * reasons. Since the ring buffer performs best if its size is a lbajardsilogic@0: * power of two, this means n should ideally be some power of two lbajardsilogic@0: * minus one. lbajardsilogic@0: */ lbajardsilogic@0: RingBuffer(size_t n); lbajardsilogic@0: lbajardsilogic@0: virtual ~RingBuffer(); lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * Return the total capacity of the ring buffer in samples. lbajardsilogic@0: * (This is the argument n passed to the constructor.) lbajardsilogic@0: */ lbajardsilogic@0: size_t getSize() const; lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * Resize the ring buffer. This also empties it. Actually swaps lbajardsilogic@0: * in a new, larger buffer; the old buffer is scavenged after a lbajardsilogic@0: * seemly delay. Should be called from the write thread. lbajardsilogic@0: */ lbajardsilogic@0: void resize(size_t newSize); lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * Lock the ring buffer into physical memory. Returns true lbajardsilogic@0: * for success. lbajardsilogic@0: */ lbajardsilogic@0: bool mlock(); lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * Reset read and write pointers, thus emptying the buffer. lbajardsilogic@0: * Should be called from the write thread. lbajardsilogic@0: */ lbajardsilogic@0: void reset(); lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * Return the amount of data available for reading by reader R, in lbajardsilogic@0: * samples. lbajardsilogic@0: */ lbajardsilogic@0: size_t getReadSpace(int R = 0) const; lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * Return the amount of space available for writing, in samples. lbajardsilogic@0: */ lbajardsilogic@0: size_t getWriteSpace() const; lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * Read n samples from the buffer, for reader R. If fewer than n lbajardsilogic@0: * are available, the remainder will be zeroed out. Returns the lbajardsilogic@0: * number of samples actually read. lbajardsilogic@0: */ lbajardsilogic@0: size_t read(T *destination, size_t n, int R = 0); lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * Read n samples from the buffer, for reader R, adding them to lbajardsilogic@0: * the destination. If fewer than n are available, the remainder lbajardsilogic@0: * will be left alone. Returns the number of samples actually lbajardsilogic@0: * read. lbajardsilogic@0: */ lbajardsilogic@0: size_t readAdding(T *destination, size_t n, int R = 0); lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * Read one sample from the buffer, for reader R. If no sample is lbajardsilogic@0: * available, this will silently return zero. Calling this lbajardsilogic@0: * repeatedly is obviously slower than calling read once, but it lbajardsilogic@0: * may be good enough if you don't want to allocate a buffer to lbajardsilogic@0: * read into. lbajardsilogic@0: */ lbajardsilogic@0: T readOne(int R = 0); lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * Read n samples from the buffer, if available, for reader R, lbajardsilogic@0: * without advancing the read pointer -- i.e. a subsequent read() lbajardsilogic@0: * or skip() will be necessary to empty the buffer. If fewer than lbajardsilogic@0: * n are available, the remainder will be zeroed out. Returns the lbajardsilogic@0: * number of samples actually read. lbajardsilogic@0: */ lbajardsilogic@0: size_t peek(T *destination, size_t n, int R = 0) const; lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * Read one sample from the buffer, if available, without lbajardsilogic@0: * advancing the read pointer -- i.e. a subsequent read() or lbajardsilogic@0: * skip() will be necessary to empty the buffer. Returns zero if lbajardsilogic@0: * no sample was available. lbajardsilogic@0: */ lbajardsilogic@0: T peekOne(int R = 0) const; lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * Pretend to read n samples from the buffer, for reader R, lbajardsilogic@0: * without actually returning them (i.e. discard the next n lbajardsilogic@0: * samples). Returns the number of samples actually available for lbajardsilogic@0: * discarding. lbajardsilogic@0: */ lbajardsilogic@0: size_t skip(size_t n, int R = 0); lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * Write n samples to the buffer. If insufficient space is lbajardsilogic@0: * available, not all samples may actually be written. Returns lbajardsilogic@0: * the number of samples actually written. lbajardsilogic@0: */ lbajardsilogic@0: size_t write(const T *source, size_t n); lbajardsilogic@0: lbajardsilogic@0: /** lbajardsilogic@0: * Write n zero-value samples to the buffer. If insufficient lbajardsilogic@0: * space is available, not all zeros may actually be written. lbajardsilogic@0: * Returns the number of zeroes actually written. lbajardsilogic@0: */ lbajardsilogic@0: size_t zero(size_t n); lbajardsilogic@0: lbajardsilogic@0: protected: lbajardsilogic@0: T *m_buffer; lbajardsilogic@0: volatile size_t m_writer; lbajardsilogic@0: volatile size_t m_readers[N]; lbajardsilogic@0: size_t m_size; lbajardsilogic@0: bool m_mlocked; lbajardsilogic@0: lbajardsilogic@0: static Scavenger > m_scavenger; lbajardsilogic@0: lbajardsilogic@0: private: lbajardsilogic@0: RingBuffer(const RingBuffer &); // not provided lbajardsilogic@0: RingBuffer &operator=(const RingBuffer &); // not provided lbajardsilogic@0: }; lbajardsilogic@0: lbajardsilogic@0: template lbajardsilogic@0: Scavenger > RingBuffer::m_scavenger; lbajardsilogic@0: lbajardsilogic@0: template lbajardsilogic@0: RingBuffer::RingBuffer(size_t n) : lbajardsilogic@0: m_buffer(new T[n + 1]), lbajardsilogic@0: m_writer(0), lbajardsilogic@0: m_size(n + 1), lbajardsilogic@0: m_mlocked(false) lbajardsilogic@0: { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "RingBuffer[" << this << "]::RingBuffer(" << n << ")" << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: for (int i = 0; i < N; ++i) m_readers[i] = 0; lbajardsilogic@0: lbajardsilogic@0: m_scavenger.scavenge(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: template lbajardsilogic@0: RingBuffer::~RingBuffer() lbajardsilogic@0: { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "RingBuffer[" << this << "]::~RingBuffer" << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: if (m_mlocked) { lbajardsilogic@0: MUNLOCK((void *)m_buffer, m_size * sizeof(T)); lbajardsilogic@0: } lbajardsilogic@0: delete[] m_buffer; lbajardsilogic@0: lbajardsilogic@0: m_scavenger.scavenge(); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: template lbajardsilogic@0: size_t lbajardsilogic@0: RingBuffer::getSize() const lbajardsilogic@0: { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "RingBuffer[" << this << "]::getSize(): " << m_size-1 << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: return m_size - 1; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: template lbajardsilogic@0: void lbajardsilogic@0: RingBuffer::resize(size_t newSize) lbajardsilogic@0: { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "RingBuffer[" << this << "]::resize(" << newSize << ")" << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: m_scavenger.scavenge(); lbajardsilogic@0: lbajardsilogic@0: if (m_mlocked) { lbajardsilogic@0: MUNLOCK((void *)m_buffer, m_size * sizeof(T)); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_scavenger.claim(new ScavengerArrayWrapper(m_buffer)); lbajardsilogic@0: lbajardsilogic@0: reset(); lbajardsilogic@0: m_buffer = new T[newSize + 1]; lbajardsilogic@0: m_size = newSize + 1; lbajardsilogic@0: lbajardsilogic@0: if (m_mlocked) { lbajardsilogic@0: if (MLOCK((void *)m_buffer, m_size * sizeof(T))) { lbajardsilogic@0: m_mlocked = false; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: template lbajardsilogic@0: bool lbajardsilogic@0: RingBuffer::mlock() lbajardsilogic@0: { lbajardsilogic@0: if (MLOCK((void *)m_buffer, m_size * sizeof(T))) return false; lbajardsilogic@0: m_mlocked = true; lbajardsilogic@0: return true; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: template lbajardsilogic@0: void lbajardsilogic@0: RingBuffer::reset() lbajardsilogic@0: { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "RingBuffer[" << this << "]::reset" << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: m_writer = 0; lbajardsilogic@0: for (int i = 0; i < N; ++i) m_readers[i] = 0; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: template lbajardsilogic@0: size_t lbajardsilogic@0: RingBuffer::getReadSpace(int R) const lbajardsilogic@0: { lbajardsilogic@0: size_t writer = m_writer; lbajardsilogic@0: size_t reader = m_readers[R]; lbajardsilogic@0: size_t space = 0; lbajardsilogic@0: lbajardsilogic@0: if (writer > reader) space = writer - reader; lbajardsilogic@0: else space = ((writer + m_size) - reader) % m_size; lbajardsilogic@0: lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "RingBuffer[" << this << "]::getReadSpace(" << R << "): " << space << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: return space; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: template lbajardsilogic@0: size_t lbajardsilogic@0: RingBuffer::getWriteSpace() const lbajardsilogic@0: { lbajardsilogic@0: size_t space = 0; lbajardsilogic@0: for (int i = 0; i < N; ++i) { lbajardsilogic@0: size_t here = (m_readers[i] + m_size - m_writer - 1) % m_size; lbajardsilogic@0: if (i == 0 || here < space) space = here; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: size_t rs(getReadSpace()), rp(m_readers[0]); lbajardsilogic@0: lbajardsilogic@0: std::cerr << "RingBuffer: write space " << space << ", read space " lbajardsilogic@0: << rs << ", total " << (space + rs) << ", m_size " << m_size << std::endl; lbajardsilogic@0: std::cerr << "RingBuffer: reader " << rp << ", writer " << m_writer << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "RingBuffer[" << this << "]::getWriteSpace(): " << space << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: return space; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: template lbajardsilogic@0: size_t lbajardsilogic@0: RingBuffer::read(T *destination, size_t n, int R) lbajardsilogic@0: { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "RingBuffer[" << this << "]::read(dest, " << n << ", " << R << ")" << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: size_t available = getReadSpace(R); lbajardsilogic@0: if (n > available) { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "WARNING: Only " << available << " samples available" lbajardsilogic@0: << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: memset(destination + available, 0, (n - available) * sizeof(T)); lbajardsilogic@0: n = available; lbajardsilogic@0: } lbajardsilogic@0: if (n == 0) return n; lbajardsilogic@0: lbajardsilogic@0: size_t here = m_size - m_readers[R]; lbajardsilogic@0: if (here >= n) { lbajardsilogic@0: memcpy(destination, m_buffer + m_readers[R], n * sizeof(T)); lbajardsilogic@0: } else { lbajardsilogic@0: memcpy(destination, m_buffer + m_readers[R], here * sizeof(T)); lbajardsilogic@0: memcpy(destination + here, m_buffer, (n - here) * sizeof(T)); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_readers[R] = (m_readers[R] + n) % m_size; lbajardsilogic@0: lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "RingBuffer[" << this << "]::read: read " << n << ", reader now " << m_readers[R] << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: return n; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: template lbajardsilogic@0: size_t lbajardsilogic@0: RingBuffer::readAdding(T *destination, size_t n, int R) lbajardsilogic@0: { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "RingBuffer[" << this << "]::readAdding(dest, " << n << ", " << R << ")" << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: size_t available = getReadSpace(R); lbajardsilogic@0: if (n > available) { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "WARNING: Only " << available << " samples available" lbajardsilogic@0: << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: n = available; lbajardsilogic@0: } lbajardsilogic@0: if (n == 0) return n; lbajardsilogic@0: lbajardsilogic@0: size_t here = m_size - m_readers[R]; lbajardsilogic@0: lbajardsilogic@0: if (here >= n) { lbajardsilogic@0: for (size_t i = 0; i < n; ++i) { lbajardsilogic@0: destination[i] += (m_buffer + m_readers[R])[i]; lbajardsilogic@0: } lbajardsilogic@0: } else { lbajardsilogic@0: for (size_t i = 0; i < here; ++i) { lbajardsilogic@0: destination[i] += (m_buffer + m_readers[R])[i]; lbajardsilogic@0: } lbajardsilogic@0: for (size_t i = 0; i < (n - here); ++i) { lbajardsilogic@0: destination[i + here] += m_buffer[i]; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_readers[R] = (m_readers[R] + n) % m_size; lbajardsilogic@0: return n; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: template lbajardsilogic@0: T lbajardsilogic@0: RingBuffer::readOne(int R) lbajardsilogic@0: { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "RingBuffer[" << this << "]::readOne(" << R << ")" << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: if (m_writer == m_readers[R]) { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "WARNING: No sample available" lbajardsilogic@0: << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: T t; lbajardsilogic@0: memset(&t, 0, sizeof(T)); lbajardsilogic@0: return t; lbajardsilogic@0: } lbajardsilogic@0: T value = m_buffer[m_readers[R]]; lbajardsilogic@0: if (++m_readers[R] == m_size) m_readers[R] = 0; lbajardsilogic@0: return value; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: template lbajardsilogic@0: size_t lbajardsilogic@0: RingBuffer::peek(T *destination, size_t n, int R) const lbajardsilogic@0: { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "RingBuffer[" << this << "]::peek(dest, " << n << ", " << R << ")" << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: size_t available = getReadSpace(R); lbajardsilogic@0: if (n > available) { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "WARNING: Only " << available << " samples available" lbajardsilogic@0: << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: memset(destination + available, 0, (n - available) * sizeof(T)); lbajardsilogic@0: n = available; lbajardsilogic@0: } lbajardsilogic@0: if (n == 0) return n; lbajardsilogic@0: lbajardsilogic@0: size_t here = m_size - m_readers[R]; lbajardsilogic@0: if (here >= n) { lbajardsilogic@0: memcpy(destination, m_buffer + m_readers[R], n * sizeof(T)); lbajardsilogic@0: } else { lbajardsilogic@0: memcpy(destination, m_buffer + m_readers[R], here * sizeof(T)); lbajardsilogic@0: memcpy(destination + here, m_buffer, (n - here) * sizeof(T)); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "RingBuffer[" << this << "]::peek: read " << n << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: return n; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: template lbajardsilogic@0: T lbajardsilogic@0: RingBuffer::peekOne(int R) const lbajardsilogic@0: { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "RingBuffer[" << this << "]::peek(" << R << ")" << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: if (m_writer == m_readers[R]) { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "WARNING: No sample available" lbajardsilogic@0: << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: T t; lbajardsilogic@0: memset(&t, 0, sizeof(T)); lbajardsilogic@0: return t; lbajardsilogic@0: } lbajardsilogic@0: T value = m_buffer[m_readers[R]]; lbajardsilogic@0: return value; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: template lbajardsilogic@0: size_t lbajardsilogic@0: RingBuffer::skip(size_t n, int R) lbajardsilogic@0: { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "RingBuffer[" << this << "]::skip(" << n << ", " << R << ")" << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: size_t available = getReadSpace(R); lbajardsilogic@0: if (n > available) { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "WARNING: Only " << available << " samples available" lbajardsilogic@0: << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: n = available; lbajardsilogic@0: } lbajardsilogic@0: if (n == 0) return n; lbajardsilogic@0: m_readers[R] = (m_readers[R] + n) % m_size; lbajardsilogic@0: return n; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: template lbajardsilogic@0: size_t lbajardsilogic@0: RingBuffer::write(const T *source, size_t n) lbajardsilogic@0: { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "RingBuffer[" << this << "]::write(" << n << ")" << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: size_t available = getWriteSpace(); lbajardsilogic@0: if (n > available) { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "WARNING: Only room for " << available << " samples" lbajardsilogic@0: << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: n = available; lbajardsilogic@0: } lbajardsilogic@0: if (n == 0) return n; lbajardsilogic@0: lbajardsilogic@0: size_t here = m_size - m_writer; lbajardsilogic@0: if (here >= n) { lbajardsilogic@0: memcpy(m_buffer + m_writer, source, n * sizeof(T)); lbajardsilogic@0: } else { lbajardsilogic@0: memcpy(m_buffer + m_writer, source, here * sizeof(T)); lbajardsilogic@0: memcpy(m_buffer, source + here, (n - here) * sizeof(T)); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_writer = (m_writer + n) % m_size; lbajardsilogic@0: lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "RingBuffer[" << this << "]::write: wrote " << n << ", writer now " << m_writer << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: return n; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: template lbajardsilogic@0: size_t lbajardsilogic@0: RingBuffer::zero(size_t n) lbajardsilogic@0: { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "RingBuffer[" << this << "]::zero(" << n << ")" << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: lbajardsilogic@0: size_t available = getWriteSpace(); lbajardsilogic@0: if (n > available) { lbajardsilogic@0: #ifdef DEBUG_RINGBUFFER lbajardsilogic@0: std::cerr << "WARNING: Only room for " << available << " samples" lbajardsilogic@0: << std::endl; lbajardsilogic@0: #endif lbajardsilogic@0: n = available; lbajardsilogic@0: } lbajardsilogic@0: if (n == 0) return n; lbajardsilogic@0: lbajardsilogic@0: size_t here = m_size - m_writer; lbajardsilogic@0: if (here >= n) { lbajardsilogic@0: memset(m_buffer + m_writer, 0, n * sizeof(T)); lbajardsilogic@0: } else { lbajardsilogic@0: memset(m_buffer + m_writer, 0, here * sizeof(T)); lbajardsilogic@0: memset(m_buffer, 0, (n - here) * sizeof(T)); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_writer = (m_writer + n) % m_size; lbajardsilogic@0: return n; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: #endif // _RINGBUFFER_H_