RingBuffer.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. * RingBuffer.h - an effective and flexible implementation of a ringbuffer for LMMS
  3. *
  4. * Copyright (c) 2014 Vesa Kivimäki
  5. * Copyright (c) 2005-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
  6. *
  7. * This file is part of LMMS - https://lmms.io
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 2 of the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public
  20. * License along with this program (see COPYING); if not, write to the
  21. * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  22. * Boston, MA 02110-1301 USA.
  23. *
  24. */
  25. #ifndef RINGBUFFER_H
  26. #define RINGBUFFER_H
  27. #include <QObject>
  28. #include "lmms_basics.h"
  29. #include "lmms_math.h"
  30. #include "MemoryManager.h"
  31. /** \brief A basic LMMS ring buffer for single-thread use. For thread and realtime safe alternative see LocklessRingBuffer.
  32. */
  33. class LMMS_EXPORT RingBuffer : public QObject
  34. {
  35. Q_OBJECT
  36. MM_OPERATORS
  37. public:
  38. /** \brief Constructs a ringbuffer of specified size, will not care about samplerate changes
  39. * \param size The size of the buffer in frames. The actual size will be size + period size
  40. */
  41. RingBuffer( f_cnt_t size );
  42. /** \brief Constructs a ringbuffer of specified samplerate-dependent size, which will be updated when samplerate changes
  43. * \param size The size of the buffer in milliseconds. The actual size will be size + period size
  44. */
  45. RingBuffer( float size );
  46. virtual ~RingBuffer();
  47. ////////////////////////////////////
  48. // Provided functions //
  49. ////////////////////////////////////
  50. // utility functions
  51. /** \brief Clears the ringbuffer of any data and resets the position to 0
  52. */
  53. void reset();
  54. /** \brief Changes the size of the ringbuffer. Clears all data.
  55. * \param size New size in frames
  56. */
  57. void changeSize( f_cnt_t size );
  58. /** \brief Changes the size of the ringbuffer. Clears all data.
  59. * \param size New size in milliseconds
  60. */
  61. void changeSize( float size );
  62. /** \brief Sets whether the ringbuffer size is adjusted for samplerate when samplerate changes
  63. * \param b True if samplerate should affect buffer size
  64. */
  65. void setSamplerateAware( bool b );
  66. // position adjustment functions
  67. /** \brief Advances the position by one period
  68. */
  69. void advance();
  70. /** \brief Moves position forwards/backwards by an amount of frames
  71. * \param amount Number of frames to move, may be negative
  72. */
  73. void movePosition( f_cnt_t amount );
  74. /** \brief Moves position forwards/backwards by an amount of milliseconds
  75. * \param amount Number of milliseconds to move, may be negative
  76. */
  77. void movePosition( float amount );
  78. // read functions
  79. /** \brief Destructively reads a period-sized buffer from the current position, writes it
  80. * to a specified destination, and advances the position by one period
  81. * \param dst Destination pointer
  82. */
  83. void pop( sampleFrame * dst );
  84. // note: ringbuffer position is unaffected by all other read functions beside pop()
  85. /** \brief Reads a period-sized buffer from the ringbuffer and writes it to a specified destination
  86. * \param dst Destination pointer
  87. * \param offset Offset in frames against current position, may be negative
  88. */
  89. void read( sampleFrame * dst, f_cnt_t offset=0 );
  90. /** \brief Reads a period-sized buffer from the ringbuffer and writes it to a specified destination
  91. * \param dst Destination pointer
  92. * \param offset Offset in milliseconds against current position, may be negative
  93. */
  94. void read( sampleFrame * dst, float offset );
  95. /** \brief Reads a buffer of specified size from the ringbuffer and writes it to a specified destination
  96. * \param dst Destination pointer
  97. * \param offset Offset in frames against current position, may be negative
  98. * \param length Length in frames of the buffer to read - must not be higher than the size of the ringbuffer!
  99. */
  100. void read( sampleFrame * dst, f_cnt_t offset, f_cnt_t length );
  101. /** \brief Reads a buffer of specified size from the ringbuffer and writes it to a specified destination
  102. * \param dst Destination pointer
  103. * \param offset Offset in milliseconds against current position, may be negative
  104. * \param length Length in frames of the buffer to read - must not be higher than the size of the ringbuffer!
  105. */
  106. void read( sampleFrame * dst, float offset, f_cnt_t length );
  107. // write functions
  108. /** \brief Writes a buffer of sampleframes to the ringbuffer at specified position
  109. * \param src Pointer to the source buffer
  110. * \param offset Offset in frames against current position, may *NOT* be negative
  111. * \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
  112. */
  113. void write( sampleFrame * src, f_cnt_t offset=0, f_cnt_t length=0 );
  114. /** \brief Writes a buffer of sampleframes to the ringbuffer at specified position
  115. * \param src Pointer to the source buffer
  116. * \param offset Offset in milliseconds against current position, may *NOT* be negative
  117. * \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
  118. */
  119. void write( sampleFrame * src, float offset, f_cnt_t length=0 );
  120. /** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position
  121. * \param src Pointer to the source buffer
  122. * \param offset Offset in frames against current position, may *NOT* be negative
  123. * \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
  124. */
  125. void writeAdding( sampleFrame * src, f_cnt_t offset=0, f_cnt_t length=0 );
  126. /** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position
  127. * \param src Pointer to the source buffer
  128. * \param offset Offset in milliseconds against current position, may *NOT* be negative
  129. * \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
  130. */
  131. void writeAdding( sampleFrame * src, float offset, f_cnt_t length=0 );
  132. /** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
  133. * a specified multiplier applied to the frames
  134. * \param src Pointer to the source buffer
  135. * \param offset Offset in frames against current position, may *NOT* be negative
  136. * \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
  137. * \param level Multiplier applied to the frames before they're written to the ringbuffer
  138. */
  139. void writeAddingMultiplied( sampleFrame * src, f_cnt_t offset, f_cnt_t length, float level );
  140. /** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
  141. * a specified multiplier applied to the frames
  142. * \param src Pointer to the source buffer
  143. * \param offset Offset in milliseconds against current position, may *NOT* be negative
  144. * \param length Length of the source buffer, if zero, period size is used
  145. * \param level Multiplier applied to the frames before they're written to the ringbuffer
  146. */
  147. void writeAddingMultiplied( sampleFrame * src, float offset, f_cnt_t length, float level );
  148. /** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
  149. * a specified multiplier applied to the frames, with swapped channels
  150. * \param src Pointer to the source buffer
  151. * \param offset Offset in frames against current position, may *NOT* be negative
  152. * \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
  153. * \param level Multiplier applied to the frames before they're written to the ringbuffer
  154. */
  155. void writeSwappedAddingMultiplied( sampleFrame * src, f_cnt_t offset, f_cnt_t length, float level );
  156. /** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
  157. * a specified multiplier applied to the frames, with swapped channels
  158. * \param src Pointer to the source buffer
  159. * \param offset Offset in milliseconds against current position, may *NOT* be negative
  160. * \param length Length of the source buffer, if zero, period size is used
  161. * \param level Multiplier applied to the frames before they're written to the ringbuffer
  162. */
  163. void writeSwappedAddingMultiplied( sampleFrame * src, float offset, f_cnt_t length, float level );
  164. protected slots:
  165. void updateSamplerate();
  166. private:
  167. inline f_cnt_t msToFrames( float ms )
  168. {
  169. return static_cast<f_cnt_t>( ceilf( ms * (float)m_samplerate * 0.001f ) );
  170. }
  171. const fpp_t m_fpp;
  172. sample_rate_t m_samplerate;
  173. size_t m_size;
  174. sampleFrame * m_buffer;
  175. volatile unsigned int m_position;
  176. };
  177. #endif