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.

260 lines
6.1KB

  1. /*
  2. * Carla Ring Buffer imported from 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 GPL.txt file
  17. */
  18. #ifndef __CARLA_RING_BUFFER_HPP__
  19. #define __CARLA_RING_BUFFER_HPP__
  20. #include "CarlaJuceUtils.hpp"
  21. #define RING_BUFFER_SIZE 2048
  22. // -------------------------------------------------
  23. // RingBuffer struct
  24. struct RingBuffer {
  25. int head, tail, written;
  26. bool invalidateCommit;
  27. char buf[RING_BUFFER_SIZE];
  28. CARLA_DECLARE_NON_COPY_STRUCT(RingBuffer)
  29. };
  30. // -------------------------------------------------
  31. // RingBufferControl class
  32. class RingBufferControl
  33. {
  34. public:
  35. RingBufferControl(RingBuffer* const ringBuf)
  36. : fRingBuf(nullptr)
  37. {
  38. if (ringBuf != nullptr)
  39. setRingBuffer(ringBuf, true);
  40. }
  41. void setRingBuffer(RingBuffer* const ringBuf, const bool reset)
  42. {
  43. CARLA_ASSERT(ringBuf != nullptr);
  44. CARLA_ASSERT(ringBuf != fRingBuf);
  45. fRingBuf = ringBuf;
  46. if (! reset)
  47. return;
  48. fRingBuf->head = 0;
  49. fRingBuf->tail = 0;
  50. fRingBuf->written = 0;
  51. fRingBuf->invalidateCommit = false;
  52. carla_fill<char>(fRingBuf->buf, RING_BUFFER_SIZE, 0);
  53. }
  54. // ---------------------------------------------
  55. void commitWrite()
  56. {
  57. CARLA_ASSERT(fRingBuf != nullptr);
  58. if (fRingBuf == nullptr)
  59. return;
  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_ASSERT(fRingBuf != nullptr);
  73. if (fRingBuf == nullptr)
  74. return false;
  75. return (fRingBuf->tail != fRingBuf->head);
  76. }
  77. // ---------------------------------------------
  78. template<typename T>
  79. T read()
  80. {
  81. T t = 0;
  82. tryRead(&t, sizeof(T));
  83. return t;
  84. }
  85. char readChar()
  86. {
  87. char c = 0;
  88. tryRead(&c, sizeof(char));
  89. return c;
  90. }
  91. int readInt()
  92. {
  93. int i = 0;
  94. tryRead(&i, sizeof(int));
  95. return i;
  96. }
  97. long readLong()
  98. {
  99. long l = 0;
  100. tryRead(&l, sizeof(long));
  101. return l;
  102. }
  103. float readFloat()
  104. {
  105. float f = 0.0f;
  106. tryRead(&f, sizeof(float));
  107. return f;
  108. }
  109. // ---------------------------------------------
  110. template<typename T>
  111. void write(const T value)
  112. {
  113. tryWrite(&value, sizeof(T));
  114. }
  115. void writeChar(const char value)
  116. {
  117. tryWrite(&value, sizeof(char));
  118. }
  119. void writeInt(const int value)
  120. {
  121. tryWrite(&value, sizeof(int));
  122. }
  123. void writeLong(const long value)
  124. {
  125. tryWrite(&value, sizeof(long));
  126. }
  127. void writeFloat(const float value)
  128. {
  129. tryWrite(&value, sizeof(float));
  130. }
  131. // ---------------------------------------------
  132. private:
  133. RingBuffer* fRingBuf;
  134. void tryRead(void* const buf, const size_t size)
  135. {
  136. CARLA_ASSERT(fRingBuf != nullptr);
  137. CARLA_ASSERT(buf != nullptr);
  138. CARLA_ASSERT(size != 0);
  139. if (fRingBuf == nullptr)
  140. return;
  141. if (buf == nullptr)
  142. return;
  143. if (size == 0)
  144. return;
  145. // this should not happen
  146. CARLA_ASSERT(fRingBuf->head >= 0);
  147. CARLA_ASSERT(fRingBuf->tail >= 0);
  148. CARLA_ASSERT(fRingBuf->written >= 0);
  149. char* const charbuf(static_cast<char*>(buf));
  150. const size_t head(fRingBuf->head);
  151. const size_t tail(fRingBuf->tail);
  152. const size_t wrap((head <= tail) ? RING_BUFFER_SIZE : 0);
  153. if (head - tail + wrap < size)
  154. return;
  155. size_t readto = tail + size;
  156. if (readto >= RING_BUFFER_SIZE)
  157. {
  158. readto -= RING_BUFFER_SIZE;
  159. const size_t firstpart(RING_BUFFER_SIZE - tail);
  160. std::memcpy(charbuf, fRingBuf->buf + tail, firstpart);
  161. std::memcpy(charbuf + firstpart, fRingBuf->buf, readto);
  162. }
  163. else
  164. {
  165. std::memcpy(charbuf, fRingBuf->buf + tail, size);
  166. }
  167. fRingBuf->tail = readto;
  168. }
  169. void tryWrite(const void* const buf, const size_t size)
  170. {
  171. CARLA_ASSERT(fRingBuf != nullptr);
  172. CARLA_ASSERT(buf != nullptr);
  173. CARLA_ASSERT(size != 0);
  174. if (fRingBuf == nullptr)
  175. return;
  176. if (buf == nullptr)
  177. return;
  178. if (size == 0)
  179. return;
  180. const char* const charbuf(static_cast<const char*>(buf));
  181. const size_t tail(fRingBuf->tail);
  182. const size_t written(fRingBuf->written);
  183. const size_t wrap((tail <= written) ? RING_BUFFER_SIZE : 0);
  184. if (tail - written + wrap < size)
  185. {
  186. carla_stderr2("RingBufferControl::tryWrite() - buffer full!");
  187. fRingBuf->invalidateCommit = true;
  188. return;
  189. }
  190. size_t writeto = written + size;
  191. if (writeto >= RING_BUFFER_SIZE)
  192. {
  193. writeto -= RING_BUFFER_SIZE;
  194. const size_t firstpart(RING_BUFFER_SIZE - written);
  195. std::memcpy(fRingBuf->buf + written, charbuf, firstpart);
  196. std::memcpy(fRingBuf->buf, charbuf + firstpart, writeto);
  197. }
  198. else
  199. {
  200. std::memcpy(fRingBuf->buf + written, charbuf, size);
  201. }
  202. fRingBuf->written = writeto;
  203. }
  204. };
  205. // -------------------------------------------------
  206. #endif // __CARLA_RING_BUFFER_HPP__