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.

220 lines
4.4KB

  1. #pragma once
  2. #include <assert.h>
  3. #include <string.h>
  4. #include <samplerate.h>
  5. namespace rack {
  6. /** A simple cyclic buffer.
  7. S must be a power of 2.
  8. push() is constant time O(1)
  9. */
  10. template <typename T, size_t S>
  11. struct RingBuffer {
  12. T data[S];
  13. size_t start = 0;
  14. size_t end = 0;
  15. size_t mask(size_t i) const {
  16. return i & (S - 1);
  17. }
  18. void push(T t) {
  19. size_t i = mask(end++);
  20. data[i] = t;
  21. }
  22. T shift() {
  23. return data[mask(start++)];
  24. }
  25. bool empty() const {
  26. return start >= end;
  27. }
  28. bool full() const {
  29. return end - start >= S;
  30. }
  31. size_t size() const {
  32. return end - start;
  33. }
  34. };
  35. /** A cyclic buffer which maintains a valid linear array of size S by keeping a copy of the buffer in adjacent memory.
  36. S must be a power of 2.
  37. push() is constant time O(2) relative to RingBuffer
  38. */
  39. template <typename T, size_t S>
  40. struct DoubleRingBuffer {
  41. T data[S*2];
  42. size_t start = 0;
  43. size_t end = 0;
  44. size_t mask(size_t i) const {
  45. return i & (S - 1);
  46. }
  47. void push(T t) {
  48. size_t i = mask(end++);
  49. data[i] = t;
  50. data[i + S] = t;
  51. }
  52. T shift() {
  53. return data[mask(start++)];
  54. }
  55. bool empty() const {
  56. return start >= end;
  57. }
  58. bool full() const {
  59. return end - start >= S;
  60. }
  61. size_t size() const {
  62. return end - start;
  63. }
  64. /** Returns a pointer to S consecutive elements for appending.
  65. If any data is appended, you must call endIncr afterwards.
  66. Pointer is invalidated when any other method is called.
  67. */
  68. T *endData() {
  69. return &data[mask(end)];
  70. }
  71. void endIncr(size_t n) {
  72. size_t mend = mask(end) + n;
  73. if (mend > S) {
  74. // Copy data backward from the doubled block to the main block
  75. memcpy(data, &data[S], sizeof(T) * (mend - S));
  76. // Don't bother copying forward
  77. }
  78. end += n;
  79. }
  80. /** Returns a pointer to S consecutive elements for consumption
  81. If any data is consumed, call startIncr afterwards.
  82. */
  83. const T *startData() const {
  84. return &data[mask(start)];
  85. }
  86. void startIncr(size_t n) {
  87. start += n;
  88. }
  89. };
  90. /** A cyclic buffer which maintains a valid linear array of size S by sliding along a larger block of size N.
  91. The linear array of S elements are moved back to the start of the block once it outgrows past the end.
  92. This happens every N - S pushes, so the push() time is O(1 + S / (N - S)).
  93. For example, a float buffer of size 64 in a block of size 1024 is nearly as efficient as RingBuffer.
  94. */
  95. template <typename T, size_t S, size_t N>
  96. struct AppleRingBuffer {
  97. T data[N];
  98. size_t start = 0;
  99. size_t end = 0;
  100. void push(T t) {
  101. data[end++] = t;
  102. if (end >= N) {
  103. // move end block to beginning
  104. memmove(data, &data[N - S], sizeof(T) * S);
  105. start -= N - S;
  106. end = S;
  107. }
  108. }
  109. T shift() {
  110. return data[start++];
  111. }
  112. bool empty() const {
  113. return start >= end;
  114. }
  115. bool full() const {
  116. return end - start >= S;
  117. }
  118. size_t size() const {
  119. return end - start;
  120. }
  121. /** Returns a pointer to S consecutive elements for appending, requesting to append n elements.
  122. */
  123. T *endData(size_t n) {
  124. // TODO
  125. return &data[end];
  126. }
  127. /** Returns a pointer to S consecutive elements for consumption
  128. If any data is consumed, call startIncr afterwards.
  129. */
  130. const T *startData() const {
  131. return &data[start];
  132. }
  133. void startIncr(size_t n) {
  134. // This is valid as long as n < S
  135. start += n;
  136. }
  137. };
  138. struct SampleRateConverter {
  139. SRC_STATE *state;
  140. SRC_DATA data;
  141. SampleRateConverter() {
  142. int error;
  143. state = src_new(SRC_SINC_FASTEST, 1, &error);
  144. assert(!error);
  145. data.src_ratio = 1.0;
  146. data.end_of_input = false;
  147. }
  148. ~SampleRateConverter() {
  149. src_delete(state);
  150. }
  151. void setRatio(float r) {
  152. data.src_ratio = r;
  153. }
  154. void process(float *in, int inLength, float *out, int outLength) {
  155. data.data_in = in;
  156. data.input_frames = inLength;
  157. data.data_out = out;
  158. data.output_frames = outLength;
  159. src_process(state, &data);
  160. }
  161. };
  162. template <size_t OVERSAMPLE>
  163. struct Decimator {
  164. SRC_STATE *state;
  165. SRC_DATA data;
  166. Decimator() {
  167. int error;
  168. state = src_new(SRC_SINC_FASTEST, 1, &error);
  169. assert(!error);
  170. data.data_in = NULL;
  171. data.data_out = NULL;
  172. data.input_frames = OVERSAMPLE;
  173. data.output_frames = 1;
  174. data.end_of_input = false;
  175. data.src_ratio = 1.0 / OVERSAMPLE;
  176. }
  177. ~Decimator() {
  178. src_delete(state);
  179. }
  180. /** input must be length OVERSAMPLE */
  181. float process(float *input) {
  182. float output[1];
  183. data.data_in = input;
  184. data.data_out = output;
  185. src_process(state, &data);
  186. if (data.output_frames_gen > 0) {
  187. return output[0];
  188. }
  189. else {
  190. return 0.0;
  191. }
  192. }
  193. void reset() {
  194. src_reset(state);
  195. }
  196. };
  197. } // namespace rack