Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

241 lines
6.3KB

  1. /*
  2. * Carla Ring Buffer based on dssi-vst code
  3. * Copyright (C) 2004-2010 Chris Cannam <cannam@all-day-breakfast.com>
  4. * Copyright (C) 2013 Filipe Coelho <falktx@falktx.com>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation; either version 2 of
  9. * the License, or any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  17. */
  18. #ifndef CARLA_RING_BUFFER_HPP_INCLUDED
  19. #define CARLA_RING_BUFFER_HPP_INCLUDED
  20. #include "CarlaJuceUtils.hpp"
  21. #ifndef RING_BUFFER_SIZE
  22. # define RING_BUFFER_SIZE 2048
  23. #endif
  24. // -----------------------------------------------------------------------
  25. // RingBuffer struct
  26. PRE_PACKED_STRUCTURE
  27. struct RingBuffer {
  28. int32_t head, tail, written;
  29. bool invalidateCommit;
  30. char buf[RING_BUFFER_SIZE];
  31. } POST_PACKED_STRUCTURE;
  32. // -----------------------------------------------------------------------
  33. // RingBufferControl class
  34. class RingBufferControl
  35. {
  36. public:
  37. RingBufferControl(RingBuffer* const ringBuf)
  38. : fRingBuf(nullptr)
  39. {
  40. if (ringBuf != nullptr)
  41. setRingBuffer(ringBuf, true);
  42. }
  43. void setRingBuffer(RingBuffer* const ringBuf, const bool reset)
  44. {
  45. CARLA_ASSERT(ringBuf != nullptr);
  46. CARLA_ASSERT(ringBuf != fRingBuf);
  47. fRingBuf = ringBuf;
  48. if (! reset)
  49. return;
  50. fRingBuf->head = 0;
  51. fRingBuf->tail = 0;
  52. fRingBuf->written = 0;
  53. fRingBuf->invalidateCommit = false;
  54. carla_zeroChar(fRingBuf->buf, RING_BUFFER_SIZE);
  55. }
  56. // -------------------------------------------------------------------
  57. void commitWrite()
  58. {
  59. CARLA_SAFE_ASSERT_RETURN(fRingBuf != nullptr,);
  60. if (fRingBuf->invalidateCommit)
  61. {
  62. fRingBuf->written = fRingBuf->head;
  63. fRingBuf->invalidateCommit = false;
  64. }
  65. else
  66. {
  67. fRingBuf->head = fRingBuf->written;
  68. }
  69. }
  70. bool dataAvailable() const
  71. {
  72. CARLA_SAFE_ASSERT_RETURN(fRingBuf != nullptr, false);
  73. return (fRingBuf->head != fRingBuf->tail);
  74. }
  75. // -------------------------------------------------------------------
  76. char readChar()
  77. {
  78. char c = 0;
  79. tryRead(&c, sizeof(char));
  80. return c;
  81. }
  82. int32_t readInt()
  83. {
  84. int32_t i = 0;
  85. tryRead(&i, sizeof(int32_t));
  86. return i;
  87. }
  88. int64_t readLong()
  89. {
  90. int64_t l = 0;
  91. tryRead(&l, sizeof(int64_t));
  92. return l;
  93. }
  94. float readFloat()
  95. {
  96. float f = 0.0f;
  97. tryRead(&f, sizeof(float));
  98. return f;
  99. }
  100. // -------------------------------------------------------------------
  101. void writeChar(const char value)
  102. {
  103. tryWrite(&value, sizeof(char));
  104. }
  105. void writeInt(const int32_t value)
  106. {
  107. tryWrite(&value, sizeof(int32_t));
  108. }
  109. void writeLong(const int64_t value)
  110. {
  111. tryWrite(&value, sizeof(int64_t));
  112. }
  113. void writeFloat(const float value)
  114. {
  115. tryWrite(&value, sizeof(float));
  116. }
  117. // -------------------------------------------------------------------
  118. private:
  119. RingBuffer* fRingBuf;
  120. void tryRead(void* const buf, const size_t size)
  121. {
  122. CARLA_SAFE_ASSERT_RETURN(fRingBuf != nullptr,);
  123. CARLA_SAFE_ASSERT_RETURN(buf != nullptr,);
  124. CARLA_SAFE_ASSERT_RETURN(size != 0,);
  125. // this should not happen
  126. CARLA_ASSERT(fRingBuf->head >= 0);
  127. CARLA_ASSERT(fRingBuf->tail >= 0);
  128. CARLA_ASSERT(fRingBuf->written >= 0);
  129. // empty
  130. if (fRingBuf->head == fRingBuf->tail)
  131. return;
  132. char* const charbuf(static_cast<char*>(buf));
  133. const size_t head(static_cast<size_t>(fRingBuf->head));
  134. const size_t tail(static_cast<size_t>(fRingBuf->tail));
  135. const size_t wrap((head < tail) ? RING_BUFFER_SIZE : 0);
  136. if (head - tail + wrap < size)
  137. {
  138. carla_stderr2("RingBufferControl::tryRead() - failed");
  139. return;
  140. }
  141. size_t readto = tail + size;
  142. if (readto >= RING_BUFFER_SIZE)
  143. {
  144. readto -= RING_BUFFER_SIZE;
  145. const size_t firstpart(RING_BUFFER_SIZE - tail);
  146. std::memcpy(charbuf, fRingBuf->buf + tail, firstpart);
  147. std::memcpy(charbuf + firstpart, fRingBuf->buf, readto);
  148. }
  149. else
  150. {
  151. std::memcpy(charbuf, fRingBuf->buf + tail, size);
  152. }
  153. fRingBuf->tail = static_cast<int32_t>(readto);
  154. }
  155. void tryWrite(const void* const buf, const size_t size)
  156. {
  157. CARLA_SAFE_ASSERT_RETURN(fRingBuf != nullptr,);
  158. CARLA_SAFE_ASSERT_RETURN(buf != nullptr,);
  159. CARLA_SAFE_ASSERT_RETURN(size != 0,);
  160. // this should not happen
  161. CARLA_ASSERT(fRingBuf->head >= 0);
  162. CARLA_ASSERT(fRingBuf->tail >= 0);
  163. CARLA_ASSERT(fRingBuf->written >= 0);
  164. const char* const charbuf(static_cast<const char*>(buf));
  165. const size_t tail(static_cast<size_t>(fRingBuf->tail));
  166. const size_t wrtn(static_cast<size_t>(fRingBuf->written));
  167. const size_t wrap((tail <= wrtn) ? RING_BUFFER_SIZE : 0);
  168. if (tail - wrtn + wrap <= size)
  169. {
  170. carla_stderr2("RingBufferControl::tryWrite() - buffer full!");
  171. fRingBuf->invalidateCommit = true;
  172. return;
  173. }
  174. size_t writeto = wrtn + size;
  175. if (writeto >= RING_BUFFER_SIZE)
  176. {
  177. writeto -= RING_BUFFER_SIZE;
  178. const size_t firstpart(RING_BUFFER_SIZE - wrtn);
  179. std::memcpy(fRingBuf->buf + wrtn, charbuf, firstpart);
  180. std::memcpy(fRingBuf->buf, charbuf + firstpart, writeto);
  181. }
  182. else
  183. {
  184. std::memcpy(fRingBuf->buf + wrtn, charbuf, size);
  185. }
  186. fRingBuf->written = static_cast<int32_t>(writeto);
  187. }
  188. CARLA_PREVENT_HEAP_ALLOCATION
  189. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(RingBufferControl)
  190. };
  191. // -----------------------------------------------------------------------
  192. #endif // CARLA_RING_BUFFER_HPP_INCLUDED