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.

CarlaRingBuffer.hpp 7.5KB

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