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.

85 lines
1.8KB

  1. #include <dsp/minblep.hpp>
  2. #include <dsp/fft.hpp>
  3. #include <dsp/window.hpp>
  4. namespace rack {
  5. namespace dsp {
  6. void minBlepImpulse(int z, int o, float* output) {
  7. // Symmetric sinc array with `z` zero-crossings on each side
  8. int n = 2 * z * o;
  9. float* x = new float[n];
  10. for (int i = 0; i < n; i++) {
  11. float p = math::rescale((float) i, 0.f, (float)(n - 1), (float) - z, (float) z);
  12. x[i] = sinc(p);
  13. }
  14. // Apply window
  15. blackmanHarrisWindow(x, n);
  16. // Real cepstrum
  17. float* fx = new float[2 * n];
  18. // Valgrind complains that the array is uninitialized for some reason, unless we clear it.
  19. std::memset(fx, 0, sizeof(float) * 2 * n);
  20. RealFFT rfft(n);
  21. rfft.rfft(x, fx);
  22. // fx = log(abs(fx))
  23. fx[0] = std::log(std::fabs(fx[0]));
  24. for (int i = 1; i < n; i++) {
  25. fx[2 * i] = std::log(std::hypot(fx[2 * i], fx[2 * i + 1]));
  26. fx[2 * i + 1] = 0.f;
  27. }
  28. fx[1] = std::log(std::fabs(fx[1]));
  29. // Clamp values in case we have -inf
  30. for (int i = 0; i < 2 * n; i++) {
  31. fx[i] = std::fmax(-30.f, fx[i]);
  32. }
  33. rfft.irfft(fx, x);
  34. rfft.scale(x);
  35. // Minimum-phase reconstruction
  36. for (int i = 1; i < n / 2; i++) {
  37. x[i] *= 2.f;
  38. }
  39. for (int i = (n + 1) / 2; i < n; i++) {
  40. x[i] = 0.f;
  41. }
  42. rfft.rfft(x, fx);
  43. // fx = exp(fx)
  44. fx[0] = std::exp(fx[0]);
  45. for (int i = 1; i < n; i++) {
  46. float re = std::exp(fx[2 * i]);
  47. float im = fx[2 * i + 1];
  48. fx[2 * i] = re * std::cos(im);
  49. fx[2 * i + 1] = re * std::sin(im);
  50. }
  51. fx[1] = std::exp(fx[1]);
  52. rfft.irfft(fx, x);
  53. rfft.scale(x);
  54. // Integrate
  55. float total = 0.f;
  56. for (int i = 0; i < n; i++) {
  57. total += x[i];
  58. x[i] = total;
  59. }
  60. // Normalize
  61. float norm = 1.f / x[n - 1];
  62. for (int i = 0; i < n; i++) {
  63. x[i] *= norm;
  64. }
  65. std::memcpy(output, x, n * sizeof(float));
  66. // Cleanup
  67. delete[] x;
  68. delete[] fx;
  69. }
  70. } // namespace dsp
  71. } // namespace rack