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.

40 lines
1.0KB

  1. #pragma once
  2. #include "string.h"
  3. #include "dsp/ringbuffer.hpp"
  4. #include "dsp/fir.hpp"
  5. namespace rack {
  6. template<int OVERSAMPLE, int QUALITY>
  7. struct Decimator {
  8. DoubleRingBuffer<float, OVERSAMPLE*QUALITY> inBuffer;
  9. float kernel[OVERSAMPLE*QUALITY];
  10. Decimator(float cutoff = 0.9) {
  11. boxcarFIR(kernel, OVERSAMPLE*QUALITY, cutoff * 0.5 / OVERSAMPLE);
  12. blackmanHarrisWindow(kernel, OVERSAMPLE*QUALITY);
  13. // The sum of the kernel should be 1
  14. float sum = 0.0;
  15. for (int i = 0; i < OVERSAMPLE*QUALITY; i++) {
  16. sum += kernel[i];
  17. }
  18. for (int i = 0; i < OVERSAMPLE*QUALITY; i++) {
  19. kernel[i] /= sum;
  20. }
  21. // Zero input buffer
  22. memset(inBuffer.data, 0, sizeof(inBuffer.data));
  23. }
  24. /** `in` must be OVERSAMPLE floats long */
  25. float process(float *in) {
  26. memcpy(inBuffer.endData(), in, OVERSAMPLE*sizeof(float));
  27. inBuffer.endIncr(OVERSAMPLE);
  28. float out = convolve(inBuffer.endData() + OVERSAMPLE*QUALITY, kernel, OVERSAMPLE*QUALITY);
  29. // Ignore the ring buffer's start position
  30. return out;
  31. }
  32. };
  33. } // namespace rack