RingBuffer.h 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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. class EXPORT RingBuffer : public QObject
  32. {
  33. Q_OBJECT
  34. MM_OPERATORS
  35. public:
  36. /** \brief Constructs a ringbuffer of specified size, will not care about samplerate changes
  37. * \param size The size of the buffer in frames. The actual size will be size + period size
  38. */
  39. RingBuffer( f_cnt_t size );
  40. /** \brief Constructs a ringbuffer of specified samplerate-dependent size, which will be updated when samplerate changes
  41. * \param size The size of the buffer in milliseconds. The actual size will be size + period size
  42. */
  43. RingBuffer( float size );
  44. virtual ~RingBuffer();
  45. ////////////////////////////////////
  46. // Provided functions //
  47. ////////////////////////////////////
  48. // utility functions
  49. /** \brief Clears the ringbuffer of any data and resets the position to 0
  50. */
  51. void reset();
  52. /** \brief Changes the size of the ringbuffer. Clears all data.
  53. * \param size New size in frames
  54. */
  55. void changeSize( f_cnt_t size );
  56. /** \brief Changes the size of the ringbuffer. Clears all data.
  57. * \param size New size in milliseconds
  58. */
  59. void changeSize( float size );
  60. /** \brief Sets whether the ringbuffer size is adjusted for samplerate when samplerate changes
  61. * \param b True if samplerate should affect buffer size
  62. */
  63. void setSamplerateAware( bool b );
  64. // position adjustment functions
  65. /** \brief Advances the position by one period
  66. */
  67. void advance();
  68. /** \brief Moves position forwards/backwards by an amount of frames
  69. * \param amount Number of frames to move, may be negative
  70. */
  71. void movePosition( f_cnt_t amount );
  72. /** \brief Moves position forwards/backwards by an amount of milliseconds
  73. * \param amount Number of milliseconds to move, may be negative
  74. */
  75. void movePosition( float amount );
  76. // read functions
  77. /** \brief Destructively reads a period-sized buffer from the current position, writes it
  78. * to a specified destination, and advances the position by one period
  79. * \param dst Destination pointer
  80. */
  81. void pop( sampleFrame * dst );
  82. // note: ringbuffer position is unaffected by all other read functions beside pop()
  83. /** \brief Reads a period-sized buffer from the ringbuffer and writes it to a specified destination
  84. * \param dst Destination pointer
  85. * \param offset Offset in frames against current position, may be negative
  86. */
  87. void read( sampleFrame * dst, f_cnt_t offset=0 );
  88. /** \brief Reads a period-sized buffer from the ringbuffer and writes it to a specified destination
  89. * \param dst Destination pointer
  90. * \param offset Offset in milliseconds against current position, may be negative
  91. */
  92. void read( sampleFrame * dst, float offset );
  93. /** \brief Reads a buffer of specified size from the ringbuffer and writes it to a specified destination
  94. * \param dst Destination pointer
  95. * \param offset Offset in frames against current position, may be negative
  96. * \param length Length in frames of the buffer to read - must not be higher than the size of the ringbuffer!
  97. */
  98. void read( sampleFrame * dst, f_cnt_t offset, f_cnt_t length );
  99. /** \brief Reads a buffer of specified size from the ringbuffer and writes it to a specified destination
  100. * \param dst Destination pointer
  101. * \param offset Offset in milliseconds against current position, may be negative
  102. * \param length Length in frames of the buffer to read - must not be higher than the size of the ringbuffer!
  103. */
  104. void read( sampleFrame * dst, float offset, f_cnt_t length );
  105. // write functions
  106. /** \brief Writes a buffer of sampleframes to the ringbuffer at specified position
  107. * \param src Pointer to the source buffer
  108. * \param offset Offset in frames against current position, may *NOT* be negative
  109. * \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
  110. */
  111. void write( sampleFrame * src, f_cnt_t offset=0, f_cnt_t length=0 );
  112. /** \brief Writes a buffer of sampleframes to the ringbuffer at specified position
  113. * \param src Pointer to the source buffer
  114. * \param offset Offset in milliseconds against current position, may *NOT* be negative
  115. * \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
  116. */
  117. void write( sampleFrame * src, float offset, f_cnt_t length=0 );
  118. /** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position
  119. * \param src Pointer to the source buffer
  120. * \param offset Offset in frames against current position, may *NOT* be negative
  121. * \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
  122. */
  123. void writeAdding( sampleFrame * src, f_cnt_t offset=0, f_cnt_t length=0 );
  124. /** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position
  125. * \param src Pointer to the source buffer
  126. * \param offset Offset in milliseconds against current position, may *NOT* be negative
  127. * \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
  128. */
  129. void writeAdding( sampleFrame * src, float offset, f_cnt_t length=0 );
  130. /** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
  131. * a specified multiplier applied to the frames
  132. * \param src Pointer to the source buffer
  133. * \param offset Offset in frames against current position, may *NOT* be negative
  134. * \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
  135. * \param level Multiplier applied to the frames before they're written to the ringbuffer
  136. */
  137. void writeAddingMultiplied( sampleFrame * src, f_cnt_t offset, f_cnt_t length, float level );
  138. /** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
  139. * a specified multiplier applied to the frames
  140. * \param src Pointer to the source buffer
  141. * \param offset Offset in milliseconds against current position, may *NOT* be negative
  142. * \param length Length of the source buffer, if zero, period size is used
  143. * \param level Multiplier applied to the frames before they're written to the ringbuffer
  144. */
  145. void writeAddingMultiplied( sampleFrame * src, float offset, f_cnt_t length, float level );
  146. /** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
  147. * a specified multiplier applied to the frames, with swapped channels
  148. * \param src Pointer to the source buffer
  149. * \param offset Offset in frames against current position, may *NOT* be negative
  150. * \param length Length of the source buffer, if zero, period size is used - must not be higher than the size of the ringbuffer!
  151. * \param level Multiplier applied to the frames before they're written to the ringbuffer
  152. */
  153. void writeSwappedAddingMultiplied( sampleFrame * src, f_cnt_t offset, f_cnt_t length, float level );
  154. /** \brief Mixes a buffer of sampleframes additively to the ringbuffer at specified position, with
  155. * a specified multiplier applied to the frames, with swapped channels
  156. * \param src Pointer to the source buffer
  157. * \param offset Offset in milliseconds against current position, may *NOT* be negative
  158. * \param length Length of the source buffer, if zero, period size is used
  159. * \param level Multiplier applied to the frames before they're written to the ringbuffer
  160. */
  161. void writeSwappedAddingMultiplied( sampleFrame * src, float offset, f_cnt_t length, float level );
  162. protected slots:
  163. void updateSamplerate();
  164. private:
  165. inline f_cnt_t msToFrames( float ms )
  166. {
  167. return static_cast<f_cnt_t>( ceilf( ms * (float)m_samplerate * 0.001f ) );
  168. }
  169. const fpp_t m_fpp;
  170. sample_rate_t m_samplerate;
  171. size_t m_size;
  172. sampleFrame * m_buffer;
  173. volatile unsigned int m_position;
  174. };
  175. #endif