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.3KB

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