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.

dsp.hpp 9.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  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. typedef void (*stepCallback)(float x, const float y[], float dydt[]);
  69. /** Solve an ODE system using the 1st order Euler method */
  70. void stepEuler(stepCallback f, float x, float dx, float y[], int len);
  71. /** Solve an ODE system using the 4th order Runge-Kutta method */
  72. void stepRK4(stepCallback f, float x, float dx, float y[], int len);
  73. /** A simple cyclic buffer.
  74. S must be a power of 2.
  75. push() is constant time O(1)
  76. */
  77. template <typename T, int S>
  78. struct RingBuffer {
  79. T data[S];
  80. int start = 0;
  81. int end = 0;
  82. int mask(int i) const {
  83. return i & (S - 1);
  84. }
  85. void push(T t) {
  86. int i = mask(end++);
  87. data[i] = t;
  88. }
  89. T shift() {
  90. return data[mask(start++)];
  91. }
  92. void clear() {
  93. start = end;
  94. }
  95. bool empty() const {
  96. return start >= end;
  97. }
  98. bool full() const {
  99. return end - start >= S;
  100. }
  101. int size() const {
  102. return end - start;
  103. }
  104. int capacity() const {
  105. return S - size();
  106. }
  107. };
  108. /** A cyclic buffer which maintains a valid linear array of size S by keeping a copy of the buffer in adjacent memory.
  109. S must be a power of 2.
  110. push() is constant time O(2) relative to RingBuffer
  111. */
  112. template <typename T, int S>
  113. struct DoubleRingBuffer {
  114. T data[S*2];
  115. int start = 0;
  116. int end = 0;
  117. int mask(int i) const {
  118. return i & (S - 1);
  119. }
  120. void push(T t) {
  121. int i = mask(end++);
  122. data[i] = t;
  123. data[i + S] = t;
  124. }
  125. T shift() {
  126. return data[mask(start++)];
  127. }
  128. void clear() {
  129. start = end;
  130. }
  131. bool empty() const {
  132. return start >= end;
  133. }
  134. bool full() const {
  135. return end - start >= S;
  136. }
  137. int size() const {
  138. return end - start;
  139. }
  140. int capacity() const {
  141. return S - size();
  142. }
  143. /** Returns a pointer to S consecutive elements for appending.
  144. If any data is appended, you must call endIncr afterwards.
  145. Pointer is invalidated when any other method is called.
  146. */
  147. T *endData() {
  148. return &data[mask(end)];
  149. }
  150. void endIncr(int n) {
  151. int e = mask(end);
  152. int e1 = e + n;
  153. int e2 = mini(e1, S);
  154. // Copy data forward
  155. memcpy(data + S + e, data + e, sizeof(T) * (e2 - e));
  156. if (e1 > S) {
  157. // Copy data backward from the doubled block to the main block
  158. memcpy(data, data + S, sizeof(T) * (e1 - S));
  159. }
  160. end += n;
  161. }
  162. /** Returns a pointer to S consecutive elements for consumption
  163. If any data is consumed, call startIncr afterwards.
  164. */
  165. const T *startData() const {
  166. return &data[mask(start)];
  167. }
  168. void startIncr(int n) {
  169. start += n;
  170. }
  171. };
  172. /** A cyclic buffer which maintains a valid linear array of size S by sliding along a larger block of size N.
  173. The linear array of S elements are moved back to the start of the block once it outgrows past the end.
  174. This happens every N - S pushes, so the push() time is O(1 + S / (N - S)).
  175. For example, a float buffer of size 64 in a block of size 1024 is nearly as efficient as RingBuffer.
  176. */
  177. template <typename T, size_t S, size_t N>
  178. struct AppleRingBuffer {
  179. T data[N];
  180. size_t start = 0;
  181. size_t end = 0;
  182. void push(T t) {
  183. data[end++] = t;
  184. if (end >= N) {
  185. // move end block to beginning
  186. memmove(data, &data[N - S], sizeof(T) * S);
  187. start -= N - S;
  188. end = S;
  189. }
  190. }
  191. T shift() {
  192. return data[start++];
  193. }
  194. bool empty() const {
  195. return start >= end;
  196. }
  197. bool full() const {
  198. return end - start >= S;
  199. }
  200. size_t size() const {
  201. return end - start;
  202. }
  203. /** Returns a pointer to S consecutive elements for appending, requesting to append n elements.
  204. */
  205. T *endData(size_t n) {
  206. // TODO
  207. return &data[end];
  208. }
  209. /** Returns a pointer to S consecutive elements for consumption
  210. If any data is consumed, call startIncr afterwards.
  211. */
  212. const T *startData() const {
  213. return &data[start];
  214. }
  215. void startIncr(size_t n) {
  216. // This is valid as long as n < S
  217. start += n;
  218. }
  219. };
  220. template<int CHANNELS>
  221. struct SampleRateConverter {
  222. SRC_STATE *state;
  223. SRC_DATA data;
  224. SampleRateConverter() {
  225. int error;
  226. state = src_new(SRC_SINC_FASTEST, CHANNELS, &error);
  227. assert(!error);
  228. data.src_ratio = 1.0;
  229. data.end_of_input = false;
  230. }
  231. ~SampleRateConverter() {
  232. src_delete(state);
  233. }
  234. /** output_sample_rate / input_sample_rate */
  235. void setRatio(float r) {
  236. src_set_ratio(state, r);
  237. data.src_ratio = r;
  238. }
  239. void setRatioSmooth(float r) {
  240. data.src_ratio = r;
  241. }
  242. /** `in` and `out` are interlaced with the number of channels */
  243. void process(const Frame<CHANNELS> *in, int *inFrames, Frame<CHANNELS> *out, int *outFrames) {
  244. // Old versions of libsamplerate use float* here instead of const float*
  245. data.data_in = (float*) in;
  246. data.input_frames = *inFrames;
  247. data.data_out = (float*) out;
  248. data.output_frames = *outFrames;
  249. src_process(state, &data);
  250. *inFrames = data.input_frames_used;
  251. *outFrames = data.output_frames_gen;
  252. }
  253. void reset() {
  254. src_reset(state);
  255. }
  256. };
  257. /** Perform a direct convolution
  258. x[-len + 1] to x[0] must be defined
  259. */
  260. inline float convolve(const float *x, const float *kernel, int len) {
  261. float y = 0.0;
  262. for (int i = 0; i < len; i++) {
  263. y += x[-i] * kernel[i];
  264. }
  265. return y;
  266. }
  267. inline void blackmanHarrisWindow(float *x, int n) {
  268. const float a0 = 0.35875;
  269. const float a1 = 0.48829;
  270. const float a2 = 0.14128;
  271. const float a3 = 0.01168;
  272. for (int i = 0; i < n; i++) {
  273. x[i] *= a0
  274. - a1 * cosf(2 * M_PI * i / (n - 1))
  275. + a2 * cosf(4 * M_PI * i / (n - 1))
  276. - a3 * cosf(6 * M_PI * i / (n - 1));
  277. }
  278. }
  279. inline void boxcarFIR(float *x, int n, float cutoff) {
  280. for (int i = 0; i < n; i++) {
  281. float t = (float)i / (n - 1) * 2.0 - 1.0;
  282. x[i] = sincf(t * n * cutoff);
  283. }
  284. }
  285. template<int OVERSAMPLE, int QUALITY>
  286. struct Decimator {
  287. DoubleRingBuffer<float, OVERSAMPLE*QUALITY> inBuffer;
  288. float kernel[OVERSAMPLE*QUALITY];
  289. Decimator(float cutoff = 0.9) {
  290. boxcarFIR(kernel, OVERSAMPLE*QUALITY, cutoff * 0.5 / OVERSAMPLE);
  291. blackmanHarrisWindow(kernel, OVERSAMPLE*QUALITY);
  292. // The sum of the kernel should be 1
  293. float sum = 0.0;
  294. for (int i = 0; i < OVERSAMPLE*QUALITY; i++) {
  295. sum += kernel[i];
  296. }
  297. for (int i = 0; i < OVERSAMPLE*QUALITY; i++) {
  298. kernel[i] /= sum;
  299. }
  300. }
  301. float process(float *in) {
  302. memcpy(inBuffer.endData(), in, OVERSAMPLE*sizeof(float));
  303. inBuffer.endIncr(OVERSAMPLE);
  304. float out = convolve(inBuffer.endData() + OVERSAMPLE*QUALITY, kernel, OVERSAMPLE*QUALITY);
  305. // Ignore the ring buffer's start position
  306. return out;
  307. }
  308. };
  309. // Pre-made minBLEP samples in minBLEP.cpp
  310. extern const float minblep_16_32[];
  311. template<int ZERO_CROSSINGS>
  312. struct MinBLEP {
  313. float buf[2*ZERO_CROSSINGS] = {};
  314. int pos = 0;
  315. const float *minblep;
  316. int oversample;
  317. /** Places a discontinuity with magnitude dx at -1 < p <= 0 relative to the current frame */
  318. void jump(float p, float dx) {
  319. if (p <= -1 || 0 < p)
  320. return;
  321. for (int j = 0; j < 2*ZERO_CROSSINGS; j++) {
  322. float minblepIndex = ((float)j - p) * oversample;
  323. int index = (pos + j) % (2*ZERO_CROSSINGS);
  324. buf[index] += dx * (-1.0 + interpf(minblep, minblepIndex));
  325. }
  326. }
  327. float shift() {
  328. float v = buf[pos];
  329. buf[pos] = 0.0;
  330. pos = (pos + 1) % (2*ZERO_CROSSINGS);
  331. return v;
  332. }
  333. };
  334. struct RCFilter {
  335. float c = 0.0;
  336. float xstate[1] = {};
  337. float ystate[1] = {};
  338. // `r` is the ratio between the cutoff frequency and sample rate, i.e. r = f_c / f_s
  339. void setCutoff(float r) {
  340. c = 2.0 / r;
  341. }
  342. void process(float x) {
  343. float y = (x + xstate[0] - ystate[0] * (1 - c)) / (1 + c);
  344. xstate[0] = x;
  345. ystate[0] = y;
  346. }
  347. float lowpass() {
  348. return ystate[0];
  349. }
  350. float highpass() {
  351. return xstate[0] - ystate[0];
  352. }
  353. };
  354. struct PeakFilter {
  355. float state = 0.0;
  356. float c = 0.0;
  357. /** Rate is lambda / sampleRate */
  358. void setRate(float r) {
  359. c = 1.0 - r;
  360. }
  361. void process(float x) {
  362. if (x > state)
  363. state = x;
  364. state *= c;
  365. }
  366. float peak() {
  367. return state;
  368. }
  369. };
  370. struct SlewLimiter {
  371. float rise = 1.0;
  372. float fall = 1.0;
  373. float out = 0.0;
  374. float process(float in) {
  375. float delta = clampf(in - out, -fall, rise);
  376. out += delta;
  377. return out;
  378. }
  379. };
  380. struct SchmittTrigger {
  381. // false is low, true is high
  382. bool state = false;
  383. float low = 0.0;
  384. float high = 1.0;
  385. void setThresholds(float low, float high) {
  386. this->low = low;
  387. this->high = high;
  388. }
  389. /** Returns true if triggered */
  390. bool process(float in) {
  391. if (state) {
  392. if (in < low)
  393. state = false;
  394. }
  395. else {
  396. if (in >= high) {
  397. state = true;
  398. return true;
  399. }
  400. }
  401. return false;
  402. }
  403. };
  404. } // namespace rack