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 8.2KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 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
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
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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. #if 0 //ndef CARLA_OS_WIN
  21. # include <sys/mman.h>
  22. # ifdef CARLA_OS_MAC
  23. # include <libkern/OSAtomic.h>
  24. # endif
  25. #endif
  26. // -----------------------------------------------------------------------
  27. // RingBuffer structs
  28. struct HeapBuffer {
  29. uint32_t size;
  30. int32_t head, tail, written;
  31. bool invalidateCommit;
  32. char* buf;
  33. HeapBuffer& operator=(const HeapBuffer& rb) noexcept
  34. {
  35. CARLA_SAFE_ASSERT_RETURN(size == rb.size, *this);
  36. size = rb.size;
  37. head = rb.head;
  38. tail = rb.tail;
  39. written = rb.written;
  40. invalidateCommit = rb.invalidateCommit;
  41. std::memcpy(buf, rb.buf, size);
  42. return *this;
  43. }
  44. };
  45. struct StackBuffer {
  46. static const uint32_t size = 4096;
  47. int32_t head, tail, written;
  48. bool invalidateCommit;
  49. char buf[size];
  50. };
  51. // -----------------------------------------------------------------------
  52. // RingBufferControl templated class
  53. template <class BufferStruct>
  54. class RingBufferControl
  55. {
  56. public:
  57. RingBufferControl(BufferStruct* const ringBuf) noexcept
  58. : fBuffer(ringBuf)
  59. {
  60. if (ringBuf != nullptr)
  61. clear();
  62. }
  63. void clear() noexcept
  64. {
  65. CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,);
  66. fBuffer->head = 0;
  67. fBuffer->tail = 0;
  68. fBuffer->written = 0;
  69. fBuffer->invalidateCommit = false;
  70. if (fBuffer->size > 0)
  71. carla_zeroChar(fBuffer->buf, fBuffer->size);
  72. }
  73. void setRingBuffer(BufferStruct* const ringBuf, const bool reset) noexcept
  74. {
  75. CARLA_SAFE_ASSERT_RETURN(ringBuf != nullptr,);
  76. CARLA_SAFE_ASSERT_RETURN(ringBuf != fBuffer,);
  77. fBuffer = ringBuf;
  78. if (reset)
  79. clear();
  80. }
  81. // -------------------------------------------------------------------
  82. bool commitWrite() noexcept
  83. {
  84. CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, false);
  85. if (fBuffer->invalidateCommit)
  86. {
  87. memoryBarrier();
  88. fBuffer->written = fBuffer->head;
  89. fBuffer->invalidateCommit = false;
  90. return false;
  91. }
  92. else
  93. {
  94. fBuffer->head = fBuffer->written;
  95. return true;
  96. }
  97. }
  98. bool isDataAvailable() const noexcept
  99. {
  100. CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr, false);
  101. return (fBuffer->head != fBuffer->tail);
  102. }
  103. #if 0
  104. void lockMemory() const noexcept
  105. {
  106. CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,);
  107. #ifdef CARLA_OS_WIN
  108. try {
  109. ::VirtualLock(fBuffer, sizeof(BufferStruct));
  110. ::VirtualLock(fBuffer->buf, fBuffer->size);
  111. } CARLA_SAFE_EXCEPTION("RingBufferControl::lockMemory");
  112. #else
  113. ::mlock(fBuffer, sizeof(BufferStruct));
  114. ::mlock(fBuffer->buf, fBuffer->size);
  115. #endif
  116. }
  117. #endif
  118. // -------------------------------------------------------------------
  119. char readChar() noexcept
  120. {
  121. char c = '\0';
  122. tryRead(&c, sizeof(char));
  123. return c;
  124. }
  125. int32_t readInt() noexcept
  126. {
  127. int32_t i = 0;
  128. tryRead(&i, sizeof(int32_t));
  129. return i;
  130. }
  131. uint32_t readUInt() noexcept
  132. {
  133. int32_t i = -1;
  134. tryRead(&i, sizeof(int32_t));
  135. return (i >= 0) ? static_cast<uint32_t>(i) : 0;
  136. }
  137. int64_t readLong() noexcept
  138. {
  139. int64_t l = 0;
  140. tryRead(&l, sizeof(int64_t));
  141. return l;
  142. }
  143. float readFloat() noexcept
  144. {
  145. float f = 0.0f;
  146. tryRead(&f, sizeof(float));
  147. return f;
  148. }
  149. // -------------------------------------------------------------------
  150. void writeChar(const char value) noexcept
  151. {
  152. tryWrite(&value, sizeof(char));
  153. }
  154. void writeInt(const int32_t value) noexcept
  155. {
  156. tryWrite(&value, sizeof(int32_t));
  157. }
  158. void writeLong(const int64_t value) noexcept
  159. {
  160. tryWrite(&value, sizeof(int64_t));
  161. }
  162. void writeFloat(const float value) noexcept
  163. {
  164. tryWrite(&value, sizeof(float));
  165. }
  166. // -------------------------------------------------------------------
  167. protected:
  168. void tryRead(void* const buf, const size_t size) noexcept
  169. {
  170. CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,);
  171. CARLA_SAFE_ASSERT_RETURN(buf != nullptr,);
  172. CARLA_SAFE_ASSERT_RETURN(size != 0,);
  173. CARLA_SAFE_ASSERT_RETURN(size < fBuffer->size,);
  174. // this should not happen
  175. CARLA_ASSERT(fBuffer->head >= 0);
  176. CARLA_ASSERT(fBuffer->tail >= 0);
  177. CARLA_ASSERT(fBuffer->written >= 0);
  178. // empty
  179. if (fBuffer->head == fBuffer->tail)
  180. return;
  181. char* const charbuf(static_cast<char*>(buf));
  182. const size_t head(static_cast<size_t>(fBuffer->head));
  183. const size_t tail(static_cast<size_t>(fBuffer->tail));
  184. const size_t wrap((head < tail) ? fBuffer->size : 0);
  185. if (head - tail + wrap < size)
  186. {
  187. carla_stderr2("RingBufferControl::tryRead() - failed");
  188. return;
  189. }
  190. size_t readto = tail + size;
  191. if (readto >= fBuffer->size)
  192. {
  193. readto -= fBuffer->size;
  194. const size_t firstpart(fBuffer->size - tail);
  195. std::memcpy(charbuf, fBuffer->buf + tail, firstpart);
  196. std::memcpy(charbuf + firstpart, fBuffer->buf, readto);
  197. }
  198. else
  199. {
  200. std::memcpy(charbuf, fBuffer->buf + tail, size);
  201. }
  202. memoryBarrier();
  203. fBuffer->tail = static_cast<int32_t>(readto);
  204. }
  205. void tryWrite(const void* const buf, const size_t size) noexcept
  206. {
  207. CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,);
  208. CARLA_SAFE_ASSERT_RETURN(buf != nullptr,);
  209. CARLA_SAFE_ASSERT_RETURN(size != 0,);
  210. CARLA_SAFE_ASSERT_RETURN(size < fBuffer->size,);
  211. // this should not happen
  212. CARLA_ASSERT(fBuffer->head >= 0);
  213. CARLA_ASSERT(fBuffer->tail >= 0);
  214. CARLA_ASSERT(fBuffer->written >= 0);
  215. const char* const charbuf(static_cast<const char*>(buf));
  216. const size_t tail(static_cast<size_t>(fBuffer->tail));
  217. const size_t wrtn(static_cast<size_t>(fBuffer->written));
  218. const size_t wrap((tail <= wrtn) ? fBuffer->size : 0);
  219. if (tail - wrtn + wrap <= size)
  220. {
  221. carla_stderr2("RingBufferControl::tryWrite() - buffer full!");
  222. fBuffer->invalidateCommit = true;
  223. return;
  224. }
  225. size_t writeto = wrtn + size;
  226. if (writeto >= fBuffer->size)
  227. {
  228. writeto -= fBuffer->size;
  229. const size_t firstpart(fBuffer->size - wrtn);
  230. std::memcpy(fBuffer->buf + wrtn, charbuf, firstpart);
  231. std::memcpy(fBuffer->buf, charbuf + firstpart, writeto);
  232. }
  233. else
  234. {
  235. std::memcpy(fBuffer->buf + wrtn, charbuf, size);
  236. }
  237. memoryBarrier();
  238. fBuffer->written = static_cast<int32_t>(writeto);
  239. }
  240. private:
  241. BufferStruct* fBuffer;
  242. static void memoryBarrier() noexcept
  243. {
  244. // this breaks win32<=>linux plugin bridges
  245. #if 0
  246. try {
  247. #if defined(CARLA_OS_MAC)
  248. ::OSMemoryBarrier();
  249. #elif defined(CARLA_OS_WIN)
  250. ::MemoryBarrier();
  251. #elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 401
  252. ::__sync_synchronize();
  253. #endif
  254. } CARLA_SAFE_EXCEPTION("RingBufferControl::memoryBarrier");
  255. #endif
  256. }
  257. CARLA_PREVENT_HEAP_ALLOCATION
  258. CARLA_DECLARE_NON_COPY_CLASS(RingBufferControl)
  259. };
  260. // -----------------------------------------------------------------------
  261. #endif // CARLA_RING_BUFFER_HPP_INCLUDED