123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- /*
- * RingBuffer.h - an effective and flexible implementation of a ringbuffer for LMMS
- *
- * Copyright (c) 2014 Vesa Kivimäki
- * Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
- *
- * This file is part of LMMS - https://lmms.io
- *
- * This program 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 Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program (see COPYING); if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- */
- #ifndef RINGBUFFER_H
- #define RINGBUFFER_H
- #include <QObject>
- #include "lmms_basics.h"
- #include "lmms_math.h"
- #include "MemoryManager.h"
- /** \brief A basic LMMS ring buffer for single-thread use. For thread and realtime safe alternative see LocklessRingBuffer.
- */
- class LMMS_EXPORT RingBuffer : public QObject
- {
- Q_OBJECT
- MM_OPERATORS
- public:
- /** \brief Constructs a ringbuffer of specified size, will not care about samplerate changes
- * \param size The size of the buffer in frames. The actual size will be size + period size
- */
- RingBuffer( f_cnt_t size );
- /** \brief Constructs a ringbuffer of specified samplerate-dependent size, which will be updated when samplerate changes
- * \param size The size of the buffer in milliseconds. The actual size will be size + period size
- */
- RingBuffer( float size );
- virtual ~RingBuffer();
- ////////////////////////////////////
- // Provided functions //
- ////////////////////////////////////
- // utility functions
- /** \brief Clears the ringbuffer of any data and resets the position to 0
- */
- void reset();
- /** \brief Changes the size of the ringbuffer. Clears all data.
- * \param size New size in frames
- */
- void changeSize( f_cnt_t size );
- /** \brief Changes the size of the ringbuffer. Clears all data.
- * \param size New size in milliseconds
- */
- void changeSize( float size );
- /** \brief Sets whether the ringbuffer size is adjusted for samplerate when samplerate changes
- * \param b True if samplerate should affect buffer size
- */
- void setSamplerateAware( bool b );
- // position adjustment functions
- /** \brief Advances the position by one period
- */
- void advance();
- /** \brief Moves position forwards/backwards by an amount of frames
- * \param amount Number of frames to move, may be negative
- */
- void movePosition( f_cnt_t amount );
- /** \brief Moves position forwards/backwards by an amount of milliseconds
- * \param amount Number of milliseconds to move, may be negative
- */
- void movePosition( float amount );
- // read functions
- /** \brief Destructively reads a period-sized buffer from the current position, writes it
- * to a specified destination, and advances the position by one period
- * \param dst Destination pointer
- */
- void pop( sampleFrame * dst );
- // note: ringbuffer position is unaffected by all other read functions beside pop()
- /** \brief Reads a period-sized buffer from the ringbuffer and writes it to a specified destination
- * \param dst Destination pointer
- * \param offset Offset in frames against current position, may be negative
- */
- void read( sampleFrame * dst, f_cnt_t offset=0 );
- /** \brief Reads a period-sized buffer from the ringbuffer and writes it to a specified destination
- * \param dst Destination pointer
- * \param offset Offset in milliseconds against current position, may be negative
- */
- void read( sampleFrame * dst, float offset );
- /** \brief Reads a buffer of specified size from the ringbuffer and writes it to a specified destination
- * \param dst Destination pointer
- * \param offset Offset in frames against current position, may be negative
- * \param length Length in frames of the buffer to read - must not be higher than the size of the ringbuffer!
- */
- void read( sampleFrame * dst, f_cnt_t offset, f_cnt_t length );
- /** \brief Reads a buffer of specified size from the ringbuffer and writes it to a specified destination
- * \param dst Destination pointer
- * \param offset Offset in milliseconds against current position, may be negative
- * \param length Length in frames of the buffer to read - must not be higher than the size of the ringbuffer!
- */
- void read( sampleFrame * dst, float offset, f_cnt_t length );
- // write functions
- /** \brief Writes a buffer of sampleframes to the ringbuffer at specified position
- * \param src Pointer to the source buffer
- * \param offset Offset in frames against current position, may *NOT* be negative
- * \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
- */
- void write( sampleFrame * src, f_cnt_t offset=0, f_cnt_t length=0 );
- /** \brief Writes a buffer of sampleframes to the ringbuffer at specified position
- * \param src Pointer to the source buffer
- * \param offset Offset in milliseconds against current position, may *NOT* be negative
- * \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
- */
- void write( sampleFrame * src, float offset, f_cnt_t length=0 );
- /** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position
- * \param src Pointer to the source buffer
- * \param offset Offset in frames against current position, may *NOT* be negative
- * \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
- */
- void writeAdding( sampleFrame * src, f_cnt_t offset=0, f_cnt_t length=0 );
- /** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position
- * \param src Pointer to the source buffer
- * \param offset Offset in milliseconds against current position, may *NOT* be negative
- * \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
- */
- void writeAdding( sampleFrame * src, float offset, f_cnt_t length=0 );
- /** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
- * a specified multiplier applied to the frames
- * \param src Pointer to the source buffer
- * \param offset Offset in frames against current position, may *NOT* be negative
- * \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
- * \param level Multiplier applied to the frames before they're written to the ringbuffer
- */
- void writeAddingMultiplied( sampleFrame * src, f_cnt_t offset, f_cnt_t length, float level );
- /** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
- * a specified multiplier applied to the frames
- * \param src Pointer to the source buffer
- * \param offset Offset in milliseconds against current position, may *NOT* be negative
- * \param length Length of the source buffer, if zero, period size is used
- * \param level Multiplier applied to the frames before they're written to the ringbuffer
- */
- void writeAddingMultiplied( sampleFrame * src, float offset, f_cnt_t length, float level );
- /** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
- * a specified multiplier applied to the frames, with swapped channels
- * \param src Pointer to the source buffer
- * \param offset Offset in frames against current position, may *NOT* be negative
- * \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
- * \param level Multiplier applied to the frames before they're written to the ringbuffer
- */
- void writeSwappedAddingMultiplied( sampleFrame * src, f_cnt_t offset, f_cnt_t length, float level );
- /** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
- * a specified multiplier applied to the frames, with swapped channels
- * \param src Pointer to the source buffer
- * \param offset Offset in milliseconds against current position, may *NOT* be negative
- * \param length Length of the source buffer, if zero, period size is used
- * \param level Multiplier applied to the frames before they're written to the ringbuffer
- */
- void writeSwappedAddingMultiplied( sampleFrame * src, float offset, f_cnt_t length, float level );
- protected slots:
- void updateSamplerate();
- private:
- inline f_cnt_t msToFrames( float ms )
- {
- return static_cast<f_cnt_t>( ceilf( ms * (float)m_samplerate * 0.001f ) );
- }
- const fpp_t m_fpp;
- sample_rate_t m_samplerate;
- size_t m_size;
- sampleFrame * m_buffer;
- volatile unsigned int m_position;
- };
- #endif
|