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.

250 lines
5.2KB

  1. #pragma once
  2. #include <assert.h>
  3. #include <string.h>
  4. #include <samplerate.h>
  5. #include "util.hpp"
  6. // in minBLEP.cpp
  7. float *generateMinBLEP(int zeroCrossings, int overSampling);
  8. namespace rack {
  9. /** A simple cyclic buffer.
  10. S must be a power of 2.
  11. push() is constant time O(1)
  12. */
  13. template <typename T, size_t S>
  14. struct RingBuffer {
  15. T data[S];
  16. size_t start = 0;
  17. size_t end = 0;
  18. size_t mask(size_t i) const {
  19. return i & (S - 1);
  20. }
  21. void push(T t) {
  22. size_t i = mask(end++);
  23. data[i] = t;
  24. }
  25. T shift() {
  26. return data[mask(start++)];
  27. }
  28. void clear() {
  29. start = end;
  30. }
  31. bool empty() const {
  32. return start >= end;
  33. }
  34. bool full() const {
  35. return end - start >= S;
  36. }
  37. size_t size() const {
  38. return end - start;
  39. }
  40. };
  41. /** A cyclic buffer which maintains a valid linear array of size S by keeping a copy of the buffer in adjacent memory.
  42. S must be a power of 2.
  43. push() is constant time O(2) relative to RingBuffer
  44. */
  45. template <typename T, size_t S>
  46. struct DoubleRingBuffer {
  47. T data[S*2];
  48. size_t start = 0;
  49. size_t end = 0;
  50. size_t mask(size_t i) const {
  51. return i & (S - 1);
  52. }
  53. void push(T t) {
  54. size_t i = mask(end++);
  55. data[i] = t;
  56. data[i + S] = t;
  57. }
  58. T shift() {
  59. return data[mask(start++)];
  60. }
  61. void clear() {
  62. start = end;
  63. }
  64. bool empty() const {
  65. return start >= end;
  66. }
  67. bool full() const {
  68. return end - start >= S;
  69. }
  70. size_t size() const {
  71. return end - start;
  72. }
  73. /** Returns a pointer to S consecutive elements for appending.
  74. If any data is appended, you must call endIncr afterwards.
  75. Pointer is invalidated when any other method is called.
  76. */
  77. T *endData() {
  78. return &data[mask(end)];
  79. }
  80. void endIncr(size_t n) {
  81. size_t mend = mask(end) + n;
  82. if (mend > S) {
  83. // Copy data backward from the doubled block to the main block
  84. memcpy(data, &data[S], sizeof(T) * (mend - S));
  85. // Don't bother copying forward
  86. }
  87. end += n;
  88. }
  89. /** Returns a pointer to S consecutive elements for consumption
  90. If any data is consumed, call startIncr afterwards.
  91. */
  92. const T *startData() const {
  93. return &data[mask(start)];
  94. }
  95. void startIncr(size_t n) {
  96. start += n;
  97. }
  98. };
  99. /** A cyclic buffer which maintains a valid linear array of size S by sliding along a larger block of size N.
  100. The linear array of S elements are moved back to the start of the block once it outgrows past the end.
  101. This happens every N - S pushes, so the push() time is O(1 + S / (N - S)).
  102. For example, a float buffer of size 64 in a block of size 1024 is nearly as efficient as RingBuffer.
  103. */
  104. template <typename T, size_t S, size_t N>
  105. struct AppleRingBuffer {
  106. T data[N];
  107. size_t start = 0;
  108. size_t end = 0;
  109. void push(T t) {
  110. data[end++] = t;
  111. if (end >= N) {
  112. // move end block to beginning
  113. memmove(data, &data[N - S], sizeof(T) * S);
  114. start -= N - S;
  115. end = S;
  116. }
  117. }
  118. T shift() {
  119. return data[start++];
  120. }
  121. bool empty() const {
  122. return start >= end;
  123. }
  124. bool full() const {
  125. return end - start >= S;
  126. }
  127. size_t size() const {
  128. return end - start;
  129. }
  130. /** Returns a pointer to S consecutive elements for appending, requesting to append n elements.
  131. */
  132. T *endData(size_t n) {
  133. // TODO
  134. return &data[end];
  135. }
  136. /** Returns a pointer to S consecutive elements for consumption
  137. If any data is consumed, call startIncr afterwards.
  138. */
  139. const T *startData() const {
  140. return &data[start];
  141. }
  142. void startIncr(size_t n) {
  143. // This is valid as long as n < S
  144. start += n;
  145. }
  146. };
  147. template<int CHANNELS>
  148. struct SampleRateConverter {
  149. SRC_STATE *state;
  150. SRC_DATA data;
  151. SampleRateConverter() {
  152. int error;
  153. state = src_new(SRC_SINC_FASTEST, CHANNELS, &error);
  154. assert(!error);
  155. data.src_ratio = 1.0;
  156. data.end_of_input = false;
  157. }
  158. ~SampleRateConverter() {
  159. src_delete(state);
  160. }
  161. void setRatio(float r) {
  162. src_set_ratio(state, r);
  163. data.src_ratio = r;
  164. }
  165. /** `in` and `out` are interlaced with the number of channels */
  166. void process(float *in, int *inFrames, float *out, int *outFrames) {
  167. data.data_in = in;
  168. data.input_frames = *inFrames;
  169. data.data_out = out;
  170. data.output_frames = *outFrames;
  171. src_process(state, &data);
  172. *inFrames = data.input_frames_used;
  173. *outFrames = data.output_frames_gen;
  174. }
  175. void reset() {
  176. src_reset(state);
  177. }
  178. };
  179. template<int ZERO_CROSSINGS>
  180. struct MinBLEP {
  181. float buf[2*ZERO_CROSSINGS] = {};
  182. int pos = 0;
  183. /** You must set this to the array generated by generateMinBLEP() */
  184. float *minblep = NULL;
  185. int oversample;
  186. /** Places a discontinuity with magnitude dx at -1 < p <= 0 relative to the current frame */
  187. void jump(float p, float dx) {
  188. if (p <= -1 || 0 < p)
  189. return;
  190. for (int j = 0; j < 2*ZERO_CROSSINGS; j++) {
  191. float minblepIndex = ((float)j - p) * oversample;
  192. int index = (pos + j) % (2*ZERO_CROSSINGS);
  193. buf[index] += dx * (-1.0 + interpf(minblep, minblepIndex));
  194. }
  195. }
  196. float shift() {
  197. float v = buf[pos];
  198. buf[pos] = 0.0;
  199. pos = (pos + 1) % (2*ZERO_CROSSINGS);
  200. return v;
  201. }
  202. };
  203. struct RCFilter {
  204. float c = 0.0;
  205. float xstate[1] = {};
  206. float ystate[1] = {};
  207. // `r` is the ratio between the cutoff frequency and sample rate, i.e. r = f_c / f_s
  208. void setCutoff(float r) {
  209. c = 2.0 / r;
  210. }
  211. void process(float x) {
  212. float y = (x + xstate[0] - ystate[0] * (1 - c)) / (1 + c);
  213. xstate[0] = x;
  214. ystate[0] = y;
  215. }
  216. float lowpass() {
  217. return ystate[0];
  218. }
  219. float highpass() {
  220. return xstate[0] - ystate[0];
  221. }
  222. };
  223. } // namespace rack