| 
							- #pragma once
 - 
 - #include <assert.h>
 - #include <string.h>
 - #include <speex/speex_resampler.h>
 - #include "frame.hpp"
 - 
 - 
 - namespace rack {
 - 
 - template<int CHANNELS>
 - struct SampleRateConverter {
 - 	SpeexResamplerState *st = NULL;
 - 	int channels = CHANNELS;
 - 	int quality = SPEEX_RESAMPLER_QUALITY_DEFAULT;
 - 	int inRate = 44100;
 - 	int outRate = 44100;
 - 
 - 	SampleRateConverter() {
 - 		refreshState();
 - 	}
 - 	~SampleRateConverter() {
 - 		if (st) {
 - 			speex_resampler_destroy(st);
 - 		}
 - 	}
 - 
 - 	/** Sets the number of channels to actually process. This can be at most CHANNELS. */
 - 	void setChannels(int channels) {
 - 		assert(channels <= CHANNELS);
 - 		if (channels == this->channels)
 - 			return;
 - 		this->channels = channels;
 - 		refreshState();
 - 	}
 - 
 - 	/** From 0 (worst, fastest) to 10 (best, slowest) */
 - 	void setQuality(int quality) {
 - 		if (quality == this->quality)
 - 			return;
 - 		this->quality = quality;
 - 		refreshState();
 - 	}
 - 
 - 	void setRates(int inRate, int outRate) {
 - 		if (inRate == this->inRate && outRate == this->outRate)
 - 			return;
 - 		this->inRate = inRate;
 - 		this->outRate = outRate;
 - 		refreshState();
 - 	}
 - 
 - 	void refreshState() {
 - 		if (st) {
 - 			speex_resampler_destroy(st);
 - 			st = NULL;
 - 		}
 - 
 - 		if (channels > 0 && inRate != outRate) {
 - 			int err;
 - 			st = speex_resampler_init(channels, inRate, outRate, quality, &err);
 - 			assert(st);
 - 			assert(err == RESAMPLER_ERR_SUCCESS);
 - 
 - 			speex_resampler_set_input_stride(st, CHANNELS);
 - 			speex_resampler_set_output_stride(st, CHANNELS);
 - 		}
 - 	}
 - 
 - 	/** `in` and `out` are interlaced with the number of channels */
 - 	void process(const Frame<CHANNELS> *in, int *inFrames, Frame<CHANNELS> *out, int *outFrames) {
 - 		assert(in);
 - 		assert(inFrames);
 - 		assert(out);
 - 		assert(outFrames);
 - 		if (st) {
 - 			// Resample each channel at a time
 - 			spx_uint32_t inLen;
 - 			spx_uint32_t outLen;
 - 			for (int i = 0; i < channels; i++) {
 - 				inLen = *inFrames;
 - 				outLen = *outFrames;
 - 				int err = speex_resampler_process_float(st, i, ((const float*) in) + i, &inLen, ((float*) out) + i, &outLen);
 - 				assert(err == RESAMPLER_ERR_SUCCESS);
 - 			}
 - 			*inFrames = inLen;
 - 			*outFrames = outLen;
 - 		}
 - 		else {
 - 			// Simply copy the buffer without conversion
 - 			int frames = min(*inFrames, *outFrames);
 - 			memcpy(out, in, frames * sizeof(Frame<CHANNELS>));
 - 			*inFrames = frames;
 - 			*outFrames = frames;
 - 		}
 - 	}
 - };
 - 
 - } // namespace rack
 
 
  |