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.

235 lines
6.1KB

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