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.

127 lines
5.1KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. The code included in this file is provided under the terms of the ISC license
  8. http://www.isc.org/downloads/software-support-policy/isc-license. Permission
  9. To use, copy, modify, and/or distribute this software for any purpose with or
  10. without fee is hereby granted provided that the above copyright notice and
  11. this permission notice appear in all copies.
  12. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  13. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  14. DISCLAIMED.
  15. ==============================================================================
  16. */
  17. namespace juce
  18. {
  19. //==============================================================================
  20. /**
  21. Encapsulates the logic for a single-threaded FIFO.
  22. This might be useful for building buffers which can be written and read in
  23. blocks of different sizes. For example, in an audio effect we might wish to
  24. run some processing on fixed-size blocks of audio input, but the host may
  25. provide input blocks of varying sizes. In this situation, we might want to
  26. store the previous input in a buffer, and extract a fixed-size block
  27. whenever there are enough samples available. The SingleThreadedAbstractFifo
  28. implements logic suitable for this use-case.
  29. This class is quite similar to AbstractFifo, in that it only keeps track of
  30. the current read/write locations. The user is responsible for providing the
  31. actual buffer that will be read/written.
  32. The intended usage of this class is as follows:
  33. - Create some backing storage in a vector, AudioBuffer etc.
  34. - Construct a SingleThreadedAbstractFifo to manage the buffer, passing the
  35. number of items in the buffer.
  36. - Each time new input is ready, call write(), passing the number of items
  37. you wish to write into the buffer. This function returns a pair of ranges
  38. describing which indices in the backing storage should be written.
  39. - Call getNumReadable() to find out how many items are ready to read from
  40. the buffer.
  41. - If there are enough items ready to read, call read(), passing the number
  42. of items you require. This function returns a pair of ranges describing
  43. which indices in the backing storage may be read.
  44. Unlike AbstractFifo, the SingleThreadedAbstractFifo is intended for use
  45. from a single thread. It is not safe to call any non-const member function
  46. of SingleThreadedAbstractFifo concurrently with any other member function.
  47. @see AbstractFifo
  48. @tags{Core}
  49. */
  50. class SingleThreadedAbstractFifo
  51. {
  52. public:
  53. /** Creates a SingleThreadedAbstractFifo with no size. */
  54. SingleThreadedAbstractFifo() = default;
  55. /** Creates a SingleThreadedAbstractFifo that can manage a buffer of the specified size. */
  56. explicit SingleThreadedAbstractFifo (int sizeIn)
  57. : size (sizeIn)
  58. {
  59. // This class only works properly when the size is a power of two.
  60. // Use nextPowerOfTwo() to find a good size, and ensure that your
  61. // backing storage is the same size.
  62. jassert (isPowerOfTwo (sizeIn));
  63. }
  64. /** Returns the number of unused elements present in the buffer. */
  65. int getRemainingSpace() const { return size - numReadable; }
  66. /** Returns the number of pending elements present in the buffer. */
  67. int getNumReadable() const { return numReadable; }
  68. /** Returns the size of the managed buffer. */
  69. int getSize() const { return size; }
  70. /** Returns two blocks in the buffer where new items may be written.
  71. Note that if the buffer is running low on free space, the sum of the lengths of
  72. the returned ranges may be less than num!
  73. */
  74. std::array<Range<int>, 2> write (int num)
  75. {
  76. const auto startPos = (readPos + numReadable) & (size - 1);
  77. const auto maxToWrite = jmin (getRemainingSpace(), num);
  78. const auto firstBlockSize = jmin (maxToWrite, size - startPos);
  79. numReadable += maxToWrite;
  80. return { { { startPos, startPos + firstBlockSize }, { 0, maxToWrite - firstBlockSize } } };
  81. }
  82. /** Returns two blocks in the buffer from which new items may be read.
  83. Note that if the buffer doesn't have the requested number of items available,
  84. the sum of the lengths of the returned ranges may be less than num!
  85. */
  86. std::array<Range<int>, 2> read (int num)
  87. {
  88. const auto startPos = readPos;
  89. const auto maxToRead = jmin (numReadable, num);
  90. const auto firstBlockSize = jmin (maxToRead, size - startPos);
  91. readPos = (startPos + maxToRead) & (size - 1);
  92. numReadable -= maxToRead;
  93. return { { { startPos, startPos + firstBlockSize }, { 0, maxToRead - firstBlockSize } } };
  94. }
  95. private:
  96. int size = 0, readPos = 0, numReadable = 0;
  97. };
  98. } // namespace juce