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.

317 lines
6.8KB

  1. #pragma once
  2. #include <assert.h>
  3. #include <string.h>
  4. #include <samplerate.h>
  5. #include <complex.h>
  6. #include "math.hpp"
  7. namespace rack {
  8. /** Construct a C-style complex float
  9. With -O3 this is as fast as the 1.0 + 1.0*I syntax but it stops the compiler from complaining
  10. */
  11. inline float _Complex complexf(float r, float i) {
  12. union {
  13. float x[2];
  14. float _Complex c;
  15. } v;
  16. v.x[0] = r;
  17. v.x[1] = i;
  18. return v.c;
  19. }
  20. /** Simple FFT implementation
  21. If you need something fast, use pffft, KissFFT, etc instead.
  22. The size N must be a power of 2
  23. */
  24. struct SimpleFFT {
  25. int N;
  26. /** Twiddle factors e^(2pi k/N), interleaved complex numbers */
  27. float _Complex *tw;
  28. SimpleFFT(int N, bool inverse) : N(N) {
  29. tw = new float _Complex[N];
  30. for (int i = 0; i < N; i++) {
  31. float phase = 2*M_PI * (float)i / N;
  32. if (inverse)
  33. phase *= -1.0;
  34. tw[i] = cexpf(phase * complexf(0.0, 1.0));
  35. }
  36. }
  37. ~SimpleFFT() {
  38. delete[] tw;
  39. }
  40. /** Reference naive implementation
  41. x and y are arrays of interleaved complex numbers
  42. y must be size N/s
  43. s is the stride factor for the x array which divides the size N
  44. */
  45. void dft(const float _Complex *x, float _Complex *y, int s=1) {
  46. for (int k = 0; k < N/s; k++) {
  47. float _Complex yk = 0.0;
  48. for (int n = 0; n < N; n += s) {
  49. int m = (n*k) % N;
  50. yk += x[n] * tw[m];
  51. }
  52. y[k] = yk;
  53. }
  54. }
  55. void fft(const float _Complex *x, float _Complex *y, int s=1) {
  56. if (N/s <= 2) {
  57. // Naive DFT is faster than further FFT recursions at this point
  58. dft(x, y, s);
  59. return;
  60. }
  61. float _Complex e[N/(2*s)]; // Even inputs
  62. float _Complex o[N/(2*s)]; // Odd inputs
  63. fft(x, e, 2*s);
  64. fft(x + s, o, 2*s);
  65. for (int k = 0; k < N/(2*s); k++) {
  66. int m = (k*s) % N;
  67. y[k] = e[k] + tw[m] * o[k];
  68. y[k + N/(2*s)] = e[k] - tw[m] * o[k];
  69. }
  70. }
  71. };
  72. /** A simple cyclic buffer.
  73. S must be a power of 2.
  74. push() is constant time O(1)
  75. */
  76. template <typename T, size_t S>
  77. struct RingBuffer {
  78. T data[S];
  79. size_t start = 0;
  80. size_t end = 0;
  81. size_t mask(size_t i) const {
  82. return i & (S - 1);
  83. }
  84. void push(T t) {
  85. size_t i = mask(end++);
  86. data[i] = t;
  87. }
  88. T shift() {
  89. return data[mask(start++)];
  90. }
  91. void clear() {
  92. start = end;
  93. }
  94. bool empty() const {
  95. return start >= end;
  96. }
  97. bool full() const {
  98. return end - start >= S;
  99. }
  100. size_t size() const {
  101. return end - start;
  102. }
  103. };
  104. /** A cyclic buffer which maintains a valid linear array of size S by keeping a copy of the buffer in adjacent memory.
  105. S must be a power of 2.
  106. push() is constant time O(2) relative to RingBuffer
  107. */
  108. template <typename T, size_t S>
  109. struct DoubleRingBuffer {
  110. T data[S*2];
  111. size_t start = 0;
  112. size_t end = 0;
  113. size_t mask(size_t i) const {
  114. return i & (S - 1);
  115. }
  116. void push(T t) {
  117. size_t i = mask(end++);
  118. data[i] = t;
  119. data[i + S] = t;
  120. }
  121. T shift() {
  122. return data[mask(start++)];
  123. }
  124. void clear() {
  125. start = end;
  126. }
  127. bool empty() const {
  128. return start >= end;
  129. }
  130. bool full() const {
  131. return end - start >= S;
  132. }
  133. size_t size() const {
  134. return end - start;
  135. }
  136. /** Returns a pointer to S consecutive elements for appending.
  137. If any data is appended, you must call endIncr afterwards.
  138. Pointer is invalidated when any other method is called.
  139. */
  140. T *endData() {
  141. return &data[mask(end)];
  142. }
  143. void endIncr(size_t n) {
  144. size_t mend = mask(end) + n;
  145. if (mend > S) {
  146. // Copy data backward from the doubled block to the main block
  147. memcpy(data, &data[S], sizeof(T) * (mend - S));
  148. // Don't bother copying forward
  149. }
  150. end += n;
  151. }
  152. /** Returns a pointer to S consecutive elements for consumption
  153. If any data is consumed, call startIncr afterwards.
  154. */
  155. const T *startData() const {
  156. return &data[mask(start)];
  157. }
  158. void startIncr(size_t n) {
  159. start += n;
  160. }
  161. };
  162. /** A cyclic buffer which maintains a valid linear array of size S by sliding along a larger block of size N.
  163. The linear array of S elements are moved back to the start of the block once it outgrows past the end.
  164. This happens every N - S pushes, so the push() time is O(1 + S / (N - S)).
  165. For example, a float buffer of size 64 in a block of size 1024 is nearly as efficient as RingBuffer.
  166. */
  167. template <typename T, size_t S, size_t N>
  168. struct AppleRingBuffer {
  169. T data[N];
  170. size_t start = 0;
  171. size_t end = 0;
  172. void push(T t) {
  173. data[end++] = t;
  174. if (end >= N) {
  175. // move end block to beginning
  176. memmove(data, &data[N - S], sizeof(T) * S);
  177. start -= N - S;
  178. end = S;
  179. }
  180. }
  181. T shift() {
  182. return data[start++];
  183. }
  184. bool empty() const {
  185. return start >= end;
  186. }
  187. bool full() const {
  188. return end - start >= S;
  189. }
  190. size_t size() const {
  191. return end - start;
  192. }
  193. /** Returns a pointer to S consecutive elements for appending, requesting to append n elements.
  194. */
  195. T *endData(size_t n) {
  196. // TODO
  197. return &data[end];
  198. }
  199. /** Returns a pointer to S consecutive elements for consumption
  200. If any data is consumed, call startIncr afterwards.
  201. */
  202. const T *startData() const {
  203. return &data[start];
  204. }
  205. void startIncr(size_t n) {
  206. // This is valid as long as n < S
  207. start += n;
  208. }
  209. };
  210. template<int CHANNELS>
  211. struct SampleRateConverter {
  212. SRC_STATE *state;
  213. SRC_DATA data;
  214. SampleRateConverter() {
  215. int error;
  216. state = src_new(SRC_SINC_FASTEST, CHANNELS, &error);
  217. assert(!error);
  218. data.src_ratio = 1.0;
  219. data.end_of_input = false;
  220. }
  221. ~SampleRateConverter() {
  222. src_delete(state);
  223. }
  224. void setRatio(float r) {
  225. src_set_ratio(state, r);
  226. data.src_ratio = r;
  227. }
  228. /** `in` and `out` are interlaced with the number of channels */
  229. void process(float *in, int *inFrames, float *out, int *outFrames) {
  230. data.data_in = in;
  231. data.input_frames = *inFrames;
  232. data.data_out = out;
  233. data.output_frames = *outFrames;
  234. src_process(state, &data);
  235. *inFrames = data.input_frames_used;
  236. *outFrames = data.output_frames_gen;
  237. }
  238. void reset() {
  239. src_reset(state);
  240. }
  241. };
  242. // Pre-made minBLEP samples in minBLEP.cpp
  243. extern const float minblep_16_32[];
  244. template<int ZERO_CROSSINGS>
  245. struct MinBLEP {
  246. float buf[2*ZERO_CROSSINGS] = {};
  247. int pos = 0;
  248. const float *minblep;
  249. int oversample;
  250. /** Places a discontinuity with magnitude dx at -1 < p <= 0 relative to the current frame */
  251. void jump(float p, float dx) {
  252. if (p <= -1 || 0 < p)
  253. return;
  254. for (int j = 0; j < 2*ZERO_CROSSINGS; j++) {
  255. float minblepIndex = ((float)j - p) * oversample;
  256. int index = (pos + j) % (2*ZERO_CROSSINGS);
  257. buf[index] += dx * (-1.0 + interpf(minblep, minblepIndex));
  258. }
  259. }
  260. float shift() {
  261. float v = buf[pos];
  262. buf[pos] = 0.0;
  263. pos = (pos + 1) % (2*ZERO_CROSSINGS);
  264. return v;
  265. }
  266. };
  267. struct RCFilter {
  268. float c = 0.0;
  269. float xstate[1] = {};
  270. float ystate[1] = {};
  271. // `r` is the ratio between the cutoff frequency and sample rate, i.e. r = f_c / f_s
  272. void setCutoff(float r) {
  273. c = 2.0 / r;
  274. }
  275. void process(float x) {
  276. float y = (x + xstate[0] - ystate[0] * (1 - c)) / (1 + c);
  277. xstate[0] = x;
  278. ystate[0] = y;
  279. }
  280. float lowpass() {
  281. return ystate[0];
  282. }
  283. float highpass() {
  284. return xstate[0] - ystate[0];
  285. }
  286. };
  287. } // namespace rack