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.

249 lines
6.5KB

  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 "CarlaUtils.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(ringBuf)
  39. {
  40. if (ringBuf != nullptr)
  41. clear();
  42. }
  43. void clear()
  44. {
  45. CARLA_SAFE_ASSERT_RETURN(fRingBuf != nullptr,);
  46. fRingBuf->head = 0;
  47. fRingBuf->tail = 0;
  48. fRingBuf->written = 0;
  49. fRingBuf->invalidateCommit = false;
  50. carla_zeroChar(fRingBuf->buf, RING_BUFFER_SIZE);
  51. }
  52. void setRingBuffer(RingBuffer* const ringBuf, const bool reset)
  53. {
  54. CARLA_ASSERT(ringBuf != nullptr);
  55. CARLA_ASSERT(ringBuf != fRingBuf);
  56. fRingBuf = ringBuf;
  57. if (reset)
  58. clear();
  59. }
  60. // -------------------------------------------------------------------
  61. bool commitWrite()
  62. {
  63. CARLA_SAFE_ASSERT_RETURN(fRingBuf != nullptr, false);
  64. if (fRingBuf->invalidateCommit)
  65. {
  66. fRingBuf->written = fRingBuf->head;
  67. fRingBuf->invalidateCommit = false;
  68. return false;
  69. }
  70. else
  71. {
  72. fRingBuf->head = fRingBuf->written;
  73. return true;
  74. }
  75. }
  76. bool isDataAvailable() const
  77. {
  78. CARLA_SAFE_ASSERT_RETURN(fRingBuf != nullptr, false);
  79. return (fRingBuf->head != fRingBuf->tail);
  80. }
  81. // -------------------------------------------------------------------
  82. char readChar()
  83. {
  84. char c = 0;
  85. tryRead(&c, sizeof(char));
  86. return c;
  87. }
  88. int32_t readInt()
  89. {
  90. int32_t i = 0;
  91. tryRead(&i, sizeof(int32_t));
  92. return i;
  93. }
  94. int64_t readLong()
  95. {
  96. int64_t l = 0;
  97. tryRead(&l, sizeof(int64_t));
  98. return l;
  99. }
  100. float readFloat()
  101. {
  102. float f = 0.0f;
  103. tryRead(&f, sizeof(float));
  104. return f;
  105. }
  106. // -------------------------------------------------------------------
  107. void writeChar(const char value)
  108. {
  109. tryWrite(&value, sizeof(char));
  110. }
  111. void writeInt(const int32_t value)
  112. {
  113. tryWrite(&value, sizeof(int32_t));
  114. }
  115. void writeLong(const int64_t value)
  116. {
  117. tryWrite(&value, sizeof(int64_t));
  118. }
  119. void writeFloat(const float value)
  120. {
  121. tryWrite(&value, sizeof(float));
  122. }
  123. // -------------------------------------------------------------------
  124. protected:
  125. void tryRead(void* const buf, const size_t size)
  126. {
  127. CARLA_SAFE_ASSERT_RETURN(fRingBuf != nullptr,);
  128. CARLA_SAFE_ASSERT_RETURN(buf != nullptr,);
  129. CARLA_SAFE_ASSERT_RETURN(size != 0,);
  130. // this should not happen
  131. CARLA_ASSERT(fRingBuf->head >= 0);
  132. CARLA_ASSERT(fRingBuf->tail >= 0);
  133. CARLA_ASSERT(fRingBuf->written >= 0);
  134. // empty
  135. if (fRingBuf->head == fRingBuf->tail)
  136. return;
  137. char* const charbuf(static_cast<char*>(buf));
  138. const size_t head(static_cast<size_t>(fRingBuf->head));
  139. const size_t tail(static_cast<size_t>(fRingBuf->tail));
  140. const size_t wrap((head < tail) ? RING_BUFFER_SIZE : 0);
  141. if (head - tail + wrap < size)
  142. {
  143. carla_stderr2("RingBufferControl::tryRead() - failed");
  144. return;
  145. }
  146. size_t readto = tail + size;
  147. if (readto >= RING_BUFFER_SIZE)
  148. {
  149. readto -= RING_BUFFER_SIZE;
  150. const size_t firstpart(RING_BUFFER_SIZE - tail);
  151. std::memcpy(charbuf, fRingBuf->buf + tail, firstpart);
  152. std::memcpy(charbuf + firstpart, fRingBuf->buf, readto);
  153. }
  154. else
  155. {
  156. std::memcpy(charbuf, fRingBuf->buf + tail, size);
  157. }
  158. fRingBuf->tail = static_cast<int32_t>(readto);
  159. }
  160. void tryWrite(const void* const buf, const size_t size)
  161. {
  162. CARLA_SAFE_ASSERT_RETURN(fRingBuf != nullptr,);
  163. CARLA_SAFE_ASSERT_RETURN(buf != nullptr,);
  164. CARLA_SAFE_ASSERT_RETURN(size != 0,);
  165. // this should not happen
  166. CARLA_ASSERT(fRingBuf->head >= 0);
  167. CARLA_ASSERT(fRingBuf->tail >= 0);
  168. CARLA_ASSERT(fRingBuf->written >= 0);
  169. const char* const charbuf(static_cast<const char*>(buf));
  170. const size_t tail(static_cast<size_t>(fRingBuf->tail));
  171. const size_t wrtn(static_cast<size_t>(fRingBuf->written));
  172. const size_t wrap((tail <= wrtn) ? RING_BUFFER_SIZE : 0);
  173. if (tail - wrtn + wrap <= size)
  174. {
  175. carla_stderr2("RingBufferControl::tryWrite() - buffer full!");
  176. fRingBuf->invalidateCommit = true;
  177. return;
  178. }
  179. size_t writeto = wrtn + size;
  180. if (writeto >= RING_BUFFER_SIZE)
  181. {
  182. writeto -= RING_BUFFER_SIZE;
  183. const size_t firstpart(RING_BUFFER_SIZE - wrtn);
  184. std::memcpy(fRingBuf->buf + wrtn, charbuf, firstpart);
  185. std::memcpy(fRingBuf->buf, charbuf + firstpart, writeto);
  186. }
  187. else
  188. {
  189. std::memcpy(fRingBuf->buf + wrtn, charbuf, size);
  190. }
  191. fRingBuf->written = static_cast<int32_t>(writeto);
  192. }
  193. private:
  194. RingBuffer* fRingBuf;
  195. CARLA_PREVENT_HEAP_ALLOCATION
  196. CARLA_DECLARE_NON_COPY_CLASS(RingBufferControl)
  197. };
  198. // -----------------------------------------------------------------------
  199. #endif // CARLA_RING_BUFFER_HPP_INCLUDED