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.

samplerate.hpp 2.2KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #pragma once
  2. #include <assert.h>
  3. #include <string.h>
  4. #include <speex/speex_resampler.h>
  5. #include "frame.hpp"
  6. namespace rack {
  7. template<int CHANNELS>
  8. struct SampleRateConverter {
  9. SpeexResamplerState *st = NULL;
  10. int channels = CHANNELS;
  11. int quality = SPEEX_RESAMPLER_QUALITY_DEFAULT;
  12. int inRate = 44100;
  13. int outRate = 44100;
  14. SampleRateConverter() {
  15. refreshState();
  16. }
  17. ~SampleRateConverter() {
  18. if (st) {
  19. speex_resampler_destroy(st);
  20. }
  21. }
  22. /** Sets the number of channels to actually process. This can be at most CHANNELS. */
  23. void setChannels(int channels) {
  24. assert(channels <= CHANNELS);
  25. if (channels == this->channels)
  26. return;
  27. this->channels = channels;
  28. refreshState();
  29. }
  30. void setQuality(int quality) {
  31. if (quality == this->quality)
  32. return;
  33. this->quality = quality;
  34. refreshState();
  35. }
  36. void setRates(int inRate, int outRate) {
  37. if (inRate == this->inRate && outRate == this->outRate)
  38. return;
  39. this->inRate = inRate;
  40. this->outRate = outRate;
  41. refreshState();
  42. }
  43. void refreshState() {
  44. if (st) {
  45. speex_resampler_destroy(st);
  46. st = NULL;
  47. }
  48. if (channels > 0 && inRate != outRate) {
  49. int err;
  50. st = speex_resampler_init(channels, inRate, outRate, quality, &err);
  51. assert(st);
  52. assert(err == RESAMPLER_ERR_SUCCESS);
  53. speex_resampler_set_input_stride(st, CHANNELS);
  54. speex_resampler_set_output_stride(st, CHANNELS);
  55. }
  56. }
  57. /** `in` and `out` are interlaced with the number of channels */
  58. void process(const Frame<CHANNELS> *in, int *inFrames, Frame<CHANNELS> *out, int *outFrames) {
  59. assert(in);
  60. assert(inFrames);
  61. assert(out);
  62. assert(outFrames);
  63. if (st) {
  64. // Resample each channel at a time
  65. spx_uint32_t inLen;
  66. spx_uint32_t outLen;
  67. for (int i = 0; i < channels; i++) {
  68. inLen = *inFrames;
  69. outLen = *outFrames;
  70. int err = speex_resampler_process_float(st, i, ((const float*) in) + i, &inLen, ((float*) out) + i, &outLen);
  71. assert(err == RESAMPLER_ERR_SUCCESS);
  72. }
  73. *inFrames = inLen;
  74. *outFrames = outLen;
  75. }
  76. else {
  77. // Simply copy the buffer without conversion
  78. int frames = min(*inFrames, *outFrames);
  79. memcpy(out, in, frames * sizeof(Frame<CHANNELS>));
  80. *inFrames = frames;
  81. *outFrames = frames;
  82. }
  83. }
  84. };
  85. } // namespace rack