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.

55 lines
1.4KB

  1. #pragma once
  2. #include <assert.h>
  3. #include <speex/speex_resampler.h>
  4. #include "frame.hpp"
  5. namespace rack {
  6. template<int CHANNELS>
  7. struct SampleRateConverter {
  8. SpeexResamplerState *state = NULL;
  9. bool noConversion = true;
  10. SampleRateConverter() {
  11. int error;
  12. state = speex_resampler_init(CHANNELS, 44100, 44100, SPEEX_RESAMPLER_QUALITY_DEFAULT, &error);
  13. assert(error == RESAMPLER_ERR_SUCCESS);
  14. }
  15. ~SampleRateConverter() {
  16. speex_resampler_destroy(state);
  17. }
  18. void setRates(float inRate, float outRate) {
  19. int error = speex_resampler_set_rate(state, inRate, outRate);
  20. assert(error == RESAMPLER_ERR_SUCCESS);
  21. noConversion = inRate == outRate;
  22. }
  23. void setRatioSmooth(float ratio) DEPRECATED {
  24. // FIXME: this doesn't do a smooth change -- speex doesn't appear to support that.
  25. const int base = 1000;
  26. setRates(base, ratio * base);
  27. }
  28. /** `in` and `out` are interlaced with the number of channels */
  29. void process(const Frame<CHANNELS> *in, int *inFrames, Frame<CHANNELS> *out, int *outFrames) {
  30. if (noConversion) {
  31. int len = std::min(*inFrames, *outFrames);
  32. memcpy(out, in, len * sizeof(Frame<CHANNELS>));
  33. *inFrames = len;
  34. *outFrames = len;
  35. return;
  36. }
  37. speex_resampler_process_interleaved_float(state, (const float*)in, (unsigned int*)inFrames, (float*)out, (unsigned int*)outFrames);
  38. }
  39. void reset() {
  40. int error = speex_resampler_reset_mem(state);
  41. assert(error == RESAMPLER_ERR_SUCCESS);
  42. }
  43. };
  44. } // namespace rack