The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

239 lines
6.8KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. BEGIN_JUCE_NAMESPACE
  19. //==============================================================================
  20. AbstractFifo::AbstractFifo (const int capacity) noexcept
  21. : bufferSize (capacity)
  22. {
  23. jassert (bufferSize > 0);
  24. }
  25. AbstractFifo::~AbstractFifo() {}
  26. int AbstractFifo::getTotalSize() const noexcept { return bufferSize; }
  27. int AbstractFifo::getFreeSpace() const noexcept { return bufferSize - getNumReady(); }
  28. int AbstractFifo::getNumReady() const noexcept
  29. {
  30. const int vs = validStart.get();
  31. const int ve = validEnd.get();
  32. return ve >= vs ? (ve - vs) : (bufferSize - (vs - ve));
  33. }
  34. void AbstractFifo::reset() noexcept
  35. {
  36. validEnd = 0;
  37. validStart = 0;
  38. }
  39. void AbstractFifo::setTotalSize (int newSize) noexcept
  40. {
  41. jassert (newSize > 0);
  42. reset();
  43. bufferSize = newSize;
  44. }
  45. //==============================================================================
  46. void AbstractFifo::prepareToWrite (int numToWrite, int& startIndex1, int& blockSize1, int& startIndex2, int& blockSize2) const noexcept
  47. {
  48. const int vs = validStart.get();
  49. const int ve = validEnd.value;
  50. const int freeSpace = ve >= vs ? (bufferSize - (ve - vs)) : (vs - ve);
  51. numToWrite = jmin (numToWrite, freeSpace - 1);
  52. if (numToWrite <= 0)
  53. {
  54. startIndex1 = 0;
  55. startIndex2 = 0;
  56. blockSize1 = 0;
  57. blockSize2 = 0;
  58. }
  59. else
  60. {
  61. startIndex1 = ve;
  62. startIndex2 = 0;
  63. blockSize1 = jmin (bufferSize - ve, numToWrite);
  64. numToWrite -= blockSize1;
  65. blockSize2 = numToWrite <= 0 ? 0 : jmin (numToWrite, vs);
  66. }
  67. }
  68. void AbstractFifo::finishedWrite (int numWritten) noexcept
  69. {
  70. jassert (numWritten >= 0 && numWritten < bufferSize);
  71. int newEnd = validEnd.value + numWritten;
  72. if (newEnd >= bufferSize)
  73. newEnd -= bufferSize;
  74. validEnd = newEnd;
  75. }
  76. void AbstractFifo::prepareToRead (int numWanted, int& startIndex1, int& blockSize1, int& startIndex2, int& blockSize2) const noexcept
  77. {
  78. const int vs = validStart.value;
  79. const int ve = validEnd.get();
  80. const int numReady = ve >= vs ? (ve - vs) : (bufferSize - (vs - ve));
  81. numWanted = jmin (numWanted, numReady);
  82. if (numWanted <= 0)
  83. {
  84. startIndex1 = 0;
  85. startIndex2 = 0;
  86. blockSize1 = 0;
  87. blockSize2 = 0;
  88. }
  89. else
  90. {
  91. startIndex1 = vs;
  92. startIndex2 = 0;
  93. blockSize1 = jmin (bufferSize - vs, numWanted);
  94. numWanted -= blockSize1;
  95. blockSize2 = numWanted <= 0 ? 0 : jmin (numWanted, ve);
  96. }
  97. }
  98. void AbstractFifo::finishedRead (int numRead) noexcept
  99. {
  100. jassert (numRead >= 0 && numRead <= bufferSize);
  101. int newStart = validStart.value + numRead;
  102. if (newStart >= bufferSize)
  103. newStart -= bufferSize;
  104. validStart = newStart;
  105. }
  106. //==============================================================================
  107. //==============================================================================
  108. #if JUCE_UNIT_TESTS
  109. class AbstractFifoTests : public UnitTest
  110. {
  111. public:
  112. AbstractFifoTests() : UnitTest ("Abstract Fifo") {}
  113. class WriteThread : public Thread
  114. {
  115. public:
  116. WriteThread (AbstractFifo& fifo_, int* buffer_)
  117. : Thread ("fifo writer"), fifo (fifo_), buffer (buffer_)
  118. {
  119. startThread();
  120. }
  121. ~WriteThread()
  122. {
  123. stopThread (5000);
  124. }
  125. void run()
  126. {
  127. int n = 0;
  128. Random r;
  129. while (! threadShouldExit())
  130. {
  131. int num = r.nextInt (2000) + 1;
  132. int start1, size1, start2, size2;
  133. fifo.prepareToWrite (num, start1, size1, start2, size2);
  134. jassert (size1 >= 0 && size2 >= 0);
  135. jassert (size1 == 0 || (start1 >= 0 && start1 < fifo.getTotalSize()));
  136. jassert (size2 == 0 || (start2 >= 0 && start2 < fifo.getTotalSize()));
  137. int i;
  138. for (i = 0; i < size1; ++i)
  139. buffer [start1 + i] = n++;
  140. for (i = 0; i < size2; ++i)
  141. buffer [start2 + i] = n++;
  142. fifo.finishedWrite (size1 + size2);
  143. }
  144. }
  145. private:
  146. AbstractFifo& fifo;
  147. int* buffer;
  148. };
  149. void runTest()
  150. {
  151. beginTest ("AbstractFifo");
  152. int buffer [5000];
  153. AbstractFifo fifo (numElementsInArray (buffer));
  154. WriteThread writer (fifo, buffer);
  155. int n = 0;
  156. Random r;
  157. for (int count = 1000000; --count >= 0;)
  158. {
  159. int num = r.nextInt (6000) + 1;
  160. int start1, size1, start2, size2;
  161. fifo.prepareToRead (num, start1, size1, start2, size2);
  162. if (! (size1 >= 0 && size2 >= 0)
  163. && (size1 == 0 || (start1 >= 0 && start1 < fifo.getTotalSize()))
  164. && (size2 == 0 || (start2 >= 0 && start2 < fifo.getTotalSize())))
  165. {
  166. expect (false, "prepareToRead returned -ve values");
  167. break;
  168. }
  169. bool failed = false;
  170. int i;
  171. for (i = 0; i < size1; ++i)
  172. failed = (buffer [start1 + i] != n++) || failed;
  173. for (i = 0; i < size2; ++i)
  174. failed = (buffer [start2 + i] != n++) || failed;
  175. if (failed)
  176. {
  177. expect (false, "read values were incorrect");
  178. break;
  179. }
  180. fifo.finishedRead (size1 + size2);
  181. }
  182. }
  183. };
  184. static AbstractFifoTests fifoUnitTests;
  185. #endif
  186. END_JUCE_NAMESPACE