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.

344 lines
7.4KB

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