From 6ebefb4c8b523ecac35b7440907ef9e57d0154f0 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 23 May 2008 03:41:45 +0000 Subject: Merge improvemennts to MIDI stuff from Ardour. git-svn-id: http://svn.drobilla.net/lad/raul@1227 a436a847-0d15-0410-975c-d299462d15a1 --- raul/RingBuffer.hpp | 114 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 89 insertions(+), 25 deletions(-) (limited to 'raul/RingBuffer.hpp') diff --git a/raul/RingBuffer.hpp b/raul/RingBuffer.hpp index 4098a2f..dff1464 100644 --- a/raul/RingBuffer.hpp +++ b/raul/RingBuffer.hpp @@ -1,5 +1,5 @@ /* This file is part of Raul. - * Copyright (C) 2007 Dave Robillard + * Copyright (C) 2007-2008 Dave Robillard * * Raul is free software; you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software @@ -19,6 +19,7 @@ #define RAUL_RING_BUFFER_HPP #include +#include #include namespace Raul { @@ -62,7 +63,7 @@ public: if (w > r) { return ((r - w + _size) % _size) - 1; - } else if(w < r) { + } else if (w < r) { return (r - w) - 1; } else { return _size - 1; @@ -83,20 +84,65 @@ public: size_t capacity() const { return _size; } + size_t peek(size_t size, T* dst); + bool full_peek(size_t size, T* dst); + size_t read(size_t size, T* dst); - void write(size_t size, const T* src); - bool full_read(size_t size, T* dst); + bool skip(size_t size); + + void write(size_t size, const T* src); + protected: - mutable gint _write_ptr; - mutable gint _read_ptr; + mutable int _write_ptr; + mutable int _read_ptr; size_t _size; ///< Size (capacity) in bytes - T* _buf; ///< size, event, size, event... + T* _buf; ///< size, event, size, event... }; +/** Peek at the ringbuffer (read w/o advancing read pointer). + * + * Note that a full read may not be done if the data wraps around. + * Caller must check return value and call again if necessary, or use the + * full_peek method which does this automatically. + */ +template +size_t +RingBuffer::peek(size_t size, T* dst) +{ + const size_t priv_read_ptr = g_atomic_int_get(&_read_ptr); + + const size_t read_size = (priv_read_ptr + size < _size) + ? size + : _size - priv_read_ptr; + + memcpy(dst, &_buf[priv_read_ptr], read_size); + + return read_size; +} + + +template +bool +RingBuffer::full_peek(size_t size, T* dst) +{ + if (read_space() < size) { + return false; + } + + const size_t read_size = peek(size, dst); + + if (read_size < size) { + peek(size - read_size, dst + read_size); + } + + return true; +} + + /** Read from the ringbuffer. * * Note that a full read may not be done if the data wraps around. @@ -121,6 +167,40 @@ RingBuffer::read(size_t size, T* dst) } +template +bool +RingBuffer::full_read(size_t size, T* dst) +{ + if (read_space() < size) { + return false; + } + + const size_t read_size = read(size, dst); + + if (read_size < size) { + read(size - read_size, dst + read_size); + } + + return true; +} + + +template +bool +RingBuffer::skip(size_t size) +{ + if (read_space() < size) { + std::cerr << "WARNING: Attempt to skip past end of MIDI ring buffer" << std::endl; + return false; + } + + const size_t priv_read_ptr = g_atomic_int_get(&_read_ptr); + g_atomic_int_set(&_read_ptr, (priv_read_ptr + size) % _size); + + return true; +} + + template inline void RingBuffer::write(size_t size, const T* src) @@ -129,33 +209,17 @@ RingBuffer::write(size_t size, const T* src) if (priv_write_ptr + size <= _size) { memcpy(&_buf[priv_write_ptr], src, size); - g_atomic_int_set(&_write_ptr, (priv_write_ptr + size) % _size); + g_atomic_int_set(&_write_ptr, (priv_write_ptr + size) % _size); } else { const size_t this_size = _size - priv_write_ptr; assert(this_size < size); assert(priv_write_ptr + this_size <= _size); memcpy(&_buf[priv_write_ptr], src, this_size); memcpy(&_buf[0], src+this_size, size - this_size); - g_atomic_int_set(&_write_ptr, size - this_size); + g_atomic_int_set(&_write_ptr, size - this_size); } } - -template -bool -RingBuffer::full_read(size_t size, T* dst) -{ - if (read_space() < size) - return false; - - const size_t read_size = read(size, dst); - - if (read_size < size) - read(size - read_size, dst + read_size); - - return true; -} - } // namespace Raul -- cgit v1.2.1