diff options
Diffstat (limited to 'audio/softsynth/mt32/Analog.cpp')
-rw-r--r-- | audio/softsynth/mt32/Analog.cpp | 334 |
1 files changed, 212 insertions, 122 deletions
diff --git a/audio/softsynth/mt32/Analog.cpp b/audio/softsynth/mt32/Analog.cpp index 31e88561c4..2901198f2c 100644 --- a/audio/softsynth/mt32/Analog.cpp +++ b/audio/softsynth/mt32/Analog.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011-2016 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -24,8 +24,6 @@ namespace MT32Emu { -#if MT32EMU_USE_FLOAT_SAMPLES - /* FIR approximation of the overall impulse response of the cascade composed of the sample & hold circuit and the low pass filter * of the MT-32 first generation. * The coefficients below are found by windowing the inverse DFT of the 1024 pin frequency response converted to the minimum phase. @@ -34,31 +32,27 @@ namespace MT32Emu { * The peak gain of the normalised cascade appears about 1.7 near 11.8 kHz. Relative error doesn't exceed 1% for the frequencies * below 12.5 kHz. In the higher frequency range, the relative error is below 8%. Peak error value is at 16 kHz. */ -static const float COARSE_LPF_TAPS_MT32[] = { +static const FloatSample COARSE_LPF_FLOAT_TAPS_MT32[] = { 1.272473681f, -0.220267785f, -0.158039905f, 0.179603785f, -0.111484097f, 0.054137498f, -0.023518029f, 0.010997169f, -0.006935698f }; // Similar approximation for new MT-32 and CM-32L/LAPC-I LPF. As the voltage controlled amplifier was introduced, LPF has unity DC gain. // The peak gain value shifted towards higher frequencies and a bit higher about 1.83 near 13 kHz. -static const float COARSE_LPF_TAPS_CM32L[] = { +static const FloatSample COARSE_LPF_FLOAT_TAPS_CM32L[] = { 1.340615635f, -0.403331694f, 0.036005517f, 0.066156844f, -0.069672532f, 0.049563806f, -0.031113416f, 0.019169774f, -0.012421368f }; -#else - -static const unsigned int COARSE_LPF_FRACTION_BITS = 14; +static const unsigned int COARSE_LPF_INT_FRACTION_BITS = 14; // Integer versions of the FIRs above multiplied by (1 << 14) and rounded. -static const SampleEx COARSE_LPF_TAPS_MT32[] = { +static const IntSampleEx COARSE_LPF_INT_TAPS_MT32[] = { 20848, -3609, -2589, 2943, -1827, 887, -385, 180, -114 }; -static const SampleEx COARSE_LPF_TAPS_CM32L[] = { +static const IntSampleEx COARSE_LPF_INT_TAPS_CM32L[] = { 21965, -6608, 590, 1084, -1142, 812, -510, 314, -204 }; -#endif - /* Combined FIR that both approximates the impulse response of the analogue circuits of sample & hold and the low pass filter * in the audible frequency range (below 20 kHz) and attenuates unwanted mirror spectra above 28 kHz as well. It is a polyphase * filter intended for resampling the signal to 48 kHz yet for applying high frequency boost. @@ -70,7 +64,7 @@ static const SampleEx COARSE_LPF_TAPS_CM32L[] = { */ // FIR version for MT-32 first generation. -static const float ACCURATE_LPF_TAPS_MT32[] = { +static const FloatSample ACCURATE_LPF_TAPS_MT32[] = { 0.003429281f, 0.025929869f, 0.096587777f, 0.228884848f, 0.372413431f, 0.412386503f, 0.263980018f, -0.014504962f, -0.237394528f, -0.257043496f, -0.103436603f, 0.063996095f, 0.124562333f, 0.083703206f, 0.013921662f, -0.033475018f, -0.046239712f, -0.029310921f, 0.00126585f, 0.021060961f, 0.017925605f, @@ -81,7 +75,7 @@ static const float ACCURATE_LPF_TAPS_MT32[] = { }; // FIR version for new MT-32 and CM-32L/LAPC-I. -static const float ACCURATE_LPF_TAPS_CM32L[] = { +static const FloatSample ACCURATE_LPF_TAPS_CM32L[] = { 0.003917452f, 0.030693861f, 0.116424199f, 0.275101674f, 0.43217361f, 0.431247894f, 0.183255659f, -0.174955671f, -0.354240244f, -0.212401714f, 0.072259178f, 0.204655344f, 0.108336211f, -0.039099027f, -0.075138174f, -0.026261906f, 0.00582663f, 0.003052193f, 0.00613657f, 0.017017951f, 0.008732535f, @@ -107,177 +101,269 @@ static const unsigned int ACCURATE_LPF_PHASE_INCREMENT_OVERSAMPLED = 1; // No do static const Bit32u ACCURATE_LPF_DELTAS_REGULAR[][ACCURATE_LPF_NUMBER_OF_PHASES] = { { 0, 0, 0 }, { 1, 1, 0 }, { 1, 2, 1 } }; static const Bit32u ACCURATE_LPF_DELTAS_OVERSAMPLED[][ACCURATE_LPF_NUMBER_OF_PHASES] = { { 0, 0, 0 }, { 1, 0, 0 }, { 1, 0, 1 } }; +template <class SampleEx> class AbstractLowPassFilter { public: - static AbstractLowPassFilter &createLowPassFilter(AnalogOutputMode mode, bool oldMT32AnalogLPF); + static AbstractLowPassFilter<SampleEx> &createLowPassFilter(const AnalogOutputMode mode, const bool oldMT32AnalogLPF); virtual ~AbstractLowPassFilter() {} - virtual SampleEx process(SampleEx sample) = 0; - virtual bool hasNextSample() const; - virtual unsigned int getOutputSampleRate() const; - virtual unsigned int estimateInSampleCount(unsigned int outSamples) const; - virtual void addPositionIncrement(unsigned int) {} + virtual SampleEx process(const SampleEx sample) = 0; + + virtual bool hasNextSample() const { + return false; + } + + virtual unsigned int getOutputSampleRate() const { + return SAMPLE_RATE; + } + + virtual unsigned int estimateInSampleCount(const unsigned int outSamples) const { + return outSamples; + } + + virtual void addPositionIncrement(const unsigned int) {} }; -class NullLowPassFilter : public AbstractLowPassFilter { +template <class SampleEx> +class NullLowPassFilter : public AbstractLowPassFilter<SampleEx> { public: - SampleEx process(SampleEx sample); + SampleEx process(const SampleEx sample) { + return sample; + } }; -class CoarseLowPassFilter : public AbstractLowPassFilter { +template <class SampleEx> +class CoarseLowPassFilter : public AbstractLowPassFilter<SampleEx> { private: - const SampleEx * const LPF_TAPS; + const SampleEx * const lpfTaps; SampleEx ringBuffer[COARSE_LPF_DELAY_LINE_LENGTH]; unsigned int ringBufferPosition; public: - CoarseLowPassFilter(bool oldMT32AnalogLPF); - SampleEx process(SampleEx sample); + static inline const SampleEx *getLPFTaps(const bool oldMT32AnalogLPF); + static inline SampleEx normaliseSample(const SampleEx sample); + + explicit CoarseLowPassFilter(const bool oldMT32AnalogLPF) : + lpfTaps(getLPFTaps(oldMT32AnalogLPF)), + ringBufferPosition(0) + { + Synth::muteSampleBuffer(ringBuffer, COARSE_LPF_DELAY_LINE_LENGTH); + } + + SampleEx process(const SampleEx inSample) { + static const unsigned int DELAY_LINE_MASK = COARSE_LPF_DELAY_LINE_LENGTH - 1; + + SampleEx sample = lpfTaps[COARSE_LPF_DELAY_LINE_LENGTH] * ringBuffer[ringBufferPosition]; + ringBuffer[ringBufferPosition] = Synth::clipSampleEx(inSample); + + for (unsigned int i = 0; i < COARSE_LPF_DELAY_LINE_LENGTH; i++) { + sample += lpfTaps[i] * ringBuffer[(i + ringBufferPosition) & DELAY_LINE_MASK]; + } + + ringBufferPosition = (ringBufferPosition - 1) & DELAY_LINE_MASK; + + return normaliseSample(sample); + } }; -class AccurateLowPassFilter : public AbstractLowPassFilter { +class AccurateLowPassFilter : public AbstractLowPassFilter<IntSampleEx>, public AbstractLowPassFilter<FloatSample> { private: - const float * const LPF_TAPS; + const FloatSample * const LPF_TAPS; const Bit32u (* const deltas)[ACCURATE_LPF_NUMBER_OF_PHASES]; const unsigned int phaseIncrement; const unsigned int outputSampleRate; - SampleEx ringBuffer[ACCURATE_LPF_DELAY_LINE_LENGTH]; + FloatSample ringBuffer[ACCURATE_LPF_DELAY_LINE_LENGTH]; unsigned int ringBufferPosition; unsigned int phase; public: - AccurateLowPassFilter(bool oldMT32AnalogLPF, bool oversample); - SampleEx process(SampleEx sample); + AccurateLowPassFilter(const bool oldMT32AnalogLPF, const bool oversample); + FloatSample process(const FloatSample sample); + IntSampleEx process(const IntSampleEx sample); bool hasNextSample() const; unsigned int getOutputSampleRate() const; - unsigned int estimateInSampleCount(unsigned int outSamples) const; - void addPositionIncrement(unsigned int positionIncrement); + unsigned int estimateInSampleCount(const unsigned int outSamples) const; + void addPositionIncrement(const unsigned int positionIncrement); }; -Analog::Analog(const AnalogOutputMode mode, const bool oldMT32AnalogLPF) : - leftChannelLPF(AbstractLowPassFilter::createLowPassFilter(mode, oldMT32AnalogLPF)), - rightChannelLPF(AbstractLowPassFilter::createLowPassFilter(mode, oldMT32AnalogLPF)), - synthGain(0), - reverbGain(0) -{} +static inline IntSampleEx normaliseSample(const IntSampleEx sample) { + return sample >> OUTPUT_GAIN_FRACTION_BITS; +} + +static inline FloatSample normaliseSample(const FloatSample sample) { + return sample; +} + +static inline float getActualReverbOutputGain(const float reverbGain, const bool mt32ReverbCompatibilityMode) { + return mt32ReverbCompatibilityMode ? reverbGain : reverbGain * CM32L_REVERB_TO_LA32_ANALOG_OUTPUT_GAIN_FACTOR; +} -Analog::~Analog() { - delete &leftChannelLPF; - delete &rightChannelLPF; +static inline IntSampleEx getIntOutputGain(const float outputGain) { + return IntSampleEx(((OUTPUT_GAIN_MULTIPLIER < outputGain) ? OUTPUT_GAIN_MULTIPLIER : outputGain) * OUTPUT_GAIN_MULTIPLIER); } -void Analog::process(Sample *outStream, const Sample *nonReverbLeft, const Sample *nonReverbRight, const Sample *reverbDryLeft, const Sample *reverbDryRight, const Sample *reverbWetLeft, const Sample *reverbWetRight, Bit32u outLength) { - if (outStream == NULL) { - leftChannelLPF.addPositionIncrement(outLength); - rightChannelLPF.addPositionIncrement(outLength); - return; +template <class SampleEx> +class AnalogImpl : public Analog { +public: + AbstractLowPassFilter<SampleEx> &leftChannelLPF; + AbstractLowPassFilter<SampleEx> &rightChannelLPF; + SampleEx synthGain; + SampleEx reverbGain; + + AnalogImpl(const AnalogOutputMode mode, const bool oldMT32AnalogLPF) : + leftChannelLPF(AbstractLowPassFilter<SampleEx>::createLowPassFilter(mode, oldMT32AnalogLPF)), + rightChannelLPF(AbstractLowPassFilter<SampleEx>::createLowPassFilter(mode, oldMT32AnalogLPF)), + synthGain(0), + reverbGain(0) + {} + + ~AnalogImpl() { + delete &leftChannelLPF; + delete &rightChannelLPF; + } + + unsigned int getOutputSampleRate() const { + return leftChannelLPF.getOutputSampleRate(); } - while (0 < (outLength--)) { - SampleEx outSampleL; - SampleEx outSampleR; + Bit32u getDACStreamsLength(const Bit32u outputLength) const { + return leftChannelLPF.estimateInSampleCount(outputLength); + } - if (leftChannelLPF.hasNextSample()) { - outSampleL = leftChannelLPF.process(0); - outSampleR = rightChannelLPF.process(0); - } else { - SampleEx inSampleL = (SampleEx(*(nonReverbLeft++)) + SampleEx(*(reverbDryLeft++))) * synthGain + SampleEx(*(reverbWetLeft++)) * reverbGain; - SampleEx inSampleR = (SampleEx(*(nonReverbRight++)) + SampleEx(*(reverbDryRight++))) * synthGain + SampleEx(*(reverbWetRight++)) * reverbGain; + void setSynthOutputGain(const float synthGain); + void setReverbOutputGain(const float reverbGain, const bool mt32ReverbCompatibilityMode); -#if !MT32EMU_USE_FLOAT_SAMPLES - inSampleL >>= OUTPUT_GAIN_FRACTION_BITS; - inSampleR >>= OUTPUT_GAIN_FRACTION_BITS; -#endif + bool process(IntSample *outStream, const IntSample *nonReverbLeft, const IntSample *nonReverbRight, const IntSample *reverbDryLeft, const IntSample *reverbDryRight, const IntSample *reverbWetLeft, const IntSample *reverbWetRight, Bit32u outLength); + bool process(FloatSample *outStream, const FloatSample *nonReverbLeft, const FloatSample *nonReverbRight, const FloatSample *reverbDryLeft, const FloatSample *reverbDryRight, const FloatSample *reverbWetLeft, const FloatSample *reverbWetRight, Bit32u outLength); - outSampleL = leftChannelLPF.process(inSampleL); - outSampleR = rightChannelLPF.process(inSampleR); + template <class Sample> + void produceOutput(Sample *outStream, const Sample *nonReverbLeft, const Sample *nonReverbRight, const Sample *reverbDryLeft, const Sample *reverbDryRight, const Sample *reverbWetLeft, const Sample *reverbWetRight, Bit32u outLength) { + if (outStream == NULL) { + leftChannelLPF.addPositionIncrement(outLength); + rightChannelLPF.addPositionIncrement(outLength); + return; } - *(outStream++) = Synth::clipSampleEx(outSampleL); - *(outStream++) = Synth::clipSampleEx(outSampleR); + while (0 < (outLength--)) { + SampleEx outSampleL; + SampleEx outSampleR; + + if (leftChannelLPF.hasNextSample()) { + outSampleL = leftChannelLPF.process(0); + outSampleR = rightChannelLPF.process(0); + } else { + SampleEx inSampleL = (SampleEx(*(nonReverbLeft++)) + SampleEx(*(reverbDryLeft++))) * synthGain + SampleEx(*(reverbWetLeft++)) * reverbGain; + SampleEx inSampleR = (SampleEx(*(nonReverbRight++)) + SampleEx(*(reverbDryRight++))) * synthGain + SampleEx(*(reverbWetRight++)) * reverbGain; + + outSampleL = leftChannelLPF.process(normaliseSample(inSampleL)); + outSampleR = rightChannelLPF.process(normaliseSample(inSampleR)); + } + + *(outStream++) = Synth::clipSampleEx(outSampleL); + *(outStream++) = Synth::clipSampleEx(outSampleR); + } + } +}; + +Analog *Analog::createAnalog(const AnalogOutputMode mode, const bool oldMT32AnalogLPF, const RendererType rendererType) { + switch (rendererType) + { + case RendererType_BIT16S: + return new AnalogImpl<IntSampleEx>(mode, oldMT32AnalogLPF); + case RendererType_FLOAT: + return new AnalogImpl<FloatSample>(mode, oldMT32AnalogLPF); } + return NULL; +} + +template<> +bool AnalogImpl<IntSampleEx>::process(IntSample *outStream, const IntSample *nonReverbLeft, const IntSample *nonReverbRight, const IntSample *reverbDryLeft, const IntSample *reverbDryRight, const IntSample *reverbWetLeft, const IntSample *reverbWetRight, Bit32u outLength) { + produceOutput(outStream, nonReverbLeft, nonReverbRight, reverbDryLeft, reverbDryRight, reverbWetLeft, reverbWetRight, outLength); + return true; +} + +template<> +bool AnalogImpl<FloatSample>::process(IntSample *, const IntSample *, const IntSample *, const IntSample *, const IntSample *, const IntSample *, const IntSample *, Bit32u) { + return false; +} + +template<> +bool AnalogImpl<IntSampleEx>::process(FloatSample *, const FloatSample *, const FloatSample *, const FloatSample *, const FloatSample *, const FloatSample *, const FloatSample *, Bit32u) { + return false; } -unsigned int Analog::getOutputSampleRate() const { - return leftChannelLPF.getOutputSampleRate(); +template<> +bool AnalogImpl<FloatSample>::process(FloatSample *outStream, const FloatSample *nonReverbLeft, const FloatSample *nonReverbRight, const FloatSample *reverbDryLeft, const FloatSample *reverbDryRight, const FloatSample *reverbWetLeft, const FloatSample *reverbWetRight, Bit32u outLength) { + produceOutput(outStream, nonReverbLeft, nonReverbRight, reverbDryLeft, reverbDryRight, reverbWetLeft, reverbWetRight, outLength); + return true; } -Bit32u Analog::getDACStreamsLength(Bit32u outputLength) const { - return leftChannelLPF.estimateInSampleCount(outputLength); +template<> +void AnalogImpl<IntSampleEx>::setSynthOutputGain(const float useSynthGain) { + synthGain = getIntOutputGain(useSynthGain); } -void Analog::setSynthOutputGain(float useSynthGain) { -#if MT32EMU_USE_FLOAT_SAMPLES +template<> +void AnalogImpl<IntSampleEx>::setReverbOutputGain(const float useReverbGain, const bool mt32ReverbCompatibilityMode) { + reverbGain = getIntOutputGain(getActualReverbOutputGain(useReverbGain, mt32ReverbCompatibilityMode)); +} + +template<> +void AnalogImpl<FloatSample>::setSynthOutputGain(const float useSynthGain) { synthGain = useSynthGain; -#else - if (OUTPUT_GAIN_MULTIPLIER < useSynthGain) useSynthGain = OUTPUT_GAIN_MULTIPLIER; - synthGain = SampleEx(useSynthGain * OUTPUT_GAIN_MULTIPLIER); -#endif } -void Analog::setReverbOutputGain(float useReverbGain, bool mt32ReverbCompatibilityMode) { - if (!mt32ReverbCompatibilityMode) useReverbGain *= CM32L_REVERB_TO_LA32_ANALOG_OUTPUT_GAIN_FACTOR; -#if MT32EMU_USE_FLOAT_SAMPLES - reverbGain = useReverbGain; -#else - if (OUTPUT_GAIN_MULTIPLIER < useReverbGain) useReverbGain = OUTPUT_GAIN_MULTIPLIER; - reverbGain = SampleEx(useReverbGain * OUTPUT_GAIN_MULTIPLIER); -#endif +template<> +void AnalogImpl<FloatSample>::setReverbOutputGain(const float useReverbGain, const bool mt32ReverbCompatibilityMode) { + reverbGain = getActualReverbOutputGain(useReverbGain, mt32ReverbCompatibilityMode); +} + +template<> +AbstractLowPassFilter<IntSampleEx> &AbstractLowPassFilter<IntSampleEx>::createLowPassFilter(AnalogOutputMode mode, bool oldMT32AnalogLPF) { + switch (mode) { + case AnalogOutputMode_COARSE: + return *new CoarseLowPassFilter<IntSampleEx>(oldMT32AnalogLPF); + case AnalogOutputMode_ACCURATE: + return *new AccurateLowPassFilter(oldMT32AnalogLPF, false); + case AnalogOutputMode_OVERSAMPLED: + return *new AccurateLowPassFilter(oldMT32AnalogLPF, true); + default: + return *new NullLowPassFilter<IntSampleEx>; + } } -AbstractLowPassFilter &AbstractLowPassFilter::createLowPassFilter(AnalogOutputMode mode, bool oldMT32AnalogLPF) { +template<> +AbstractLowPassFilter<FloatSample> &AbstractLowPassFilter<FloatSample>::createLowPassFilter(AnalogOutputMode mode, bool oldMT32AnalogLPF) { switch (mode) { case AnalogOutputMode_COARSE: - return *new CoarseLowPassFilter(oldMT32AnalogLPF); + return *new CoarseLowPassFilter<FloatSample>(oldMT32AnalogLPF); case AnalogOutputMode_ACCURATE: return *new AccurateLowPassFilter(oldMT32AnalogLPF, false); case AnalogOutputMode_OVERSAMPLED: return *new AccurateLowPassFilter(oldMT32AnalogLPF, true); default: - return *new NullLowPassFilter; + return *new NullLowPassFilter<FloatSample>; } } -bool AbstractLowPassFilter::hasNextSample() const { - return false; -} - -unsigned int AbstractLowPassFilter::getOutputSampleRate() const { - return SAMPLE_RATE; -} - -unsigned int AbstractLowPassFilter::estimateInSampleCount(unsigned int outSamples) const { - return outSamples; +template<> +const IntSampleEx *CoarseLowPassFilter<IntSampleEx>::getLPFTaps(const bool oldMT32AnalogLPF) { + return oldMT32AnalogLPF ? COARSE_LPF_INT_TAPS_MT32 : COARSE_LPF_INT_TAPS_CM32L; } -SampleEx NullLowPassFilter::process(const SampleEx inSample) { - return inSample; +template<> +const FloatSample *CoarseLowPassFilter<FloatSample>::getLPFTaps(const bool oldMT32AnalogLPF) { + return oldMT32AnalogLPF ? COARSE_LPF_FLOAT_TAPS_MT32 : COARSE_LPF_FLOAT_TAPS_CM32L; } -CoarseLowPassFilter::CoarseLowPassFilter(bool oldMT32AnalogLPF) : - LPF_TAPS(oldMT32AnalogLPF ? COARSE_LPF_TAPS_MT32 : COARSE_LPF_TAPS_CM32L), - ringBufferPosition(0) -{ - Synth::muteSampleBuffer(ringBuffer, COARSE_LPF_DELAY_LINE_LENGTH); +template<> +IntSampleEx CoarseLowPassFilter<IntSampleEx>::normaliseSample(const IntSampleEx sample) { + return sample >> COARSE_LPF_INT_FRACTION_BITS; } -SampleEx CoarseLowPassFilter::process(const SampleEx inSample) { - static const unsigned int DELAY_LINE_MASK = COARSE_LPF_DELAY_LINE_LENGTH - 1; - - SampleEx sample = LPF_TAPS[COARSE_LPF_DELAY_LINE_LENGTH] * ringBuffer[ringBufferPosition]; - ringBuffer[ringBufferPosition] = Synth::clipSampleEx(inSample); - - for (unsigned int i = 0; i < COARSE_LPF_DELAY_LINE_LENGTH; i++) { - sample += LPF_TAPS[i] * ringBuffer[(i + ringBufferPosition) & DELAY_LINE_MASK]; - } - - ringBufferPosition = (ringBufferPosition - 1) & DELAY_LINE_MASK; - -#if !MT32EMU_USE_FLOAT_SAMPLES - sample >>= COARSE_LPF_FRACTION_BITS; -#endif - +template<> +FloatSample CoarseLowPassFilter<FloatSample>::normaliseSample(const FloatSample sample) { return sample; } @@ -292,10 +378,10 @@ AccurateLowPassFilter::AccurateLowPassFilter(const bool oldMT32AnalogLPF, const Synth::muteSampleBuffer(ringBuffer, ACCURATE_LPF_DELAY_LINE_LENGTH); } -SampleEx AccurateLowPassFilter::process(const SampleEx inSample) { +FloatSample AccurateLowPassFilter::process(const FloatSample inSample) { static const unsigned int DELAY_LINE_MASK = ACCURATE_LPF_DELAY_LINE_LENGTH - 1; - float sample = (phase == 0) ? LPF_TAPS[ACCURATE_LPF_DELAY_LINE_LENGTH * ACCURATE_LPF_NUMBER_OF_PHASES] * ringBuffer[ringBufferPosition] : 0.0f; + FloatSample sample = (phase == 0) ? LPF_TAPS[ACCURATE_LPF_DELAY_LINE_LENGTH * ACCURATE_LPF_NUMBER_OF_PHASES] * ringBuffer[ringBufferPosition] : 0.0f; if (!hasNextSample()) { ringBuffer[ringBufferPosition] = inSample; } @@ -310,7 +396,11 @@ SampleEx AccurateLowPassFilter::process(const SampleEx inSample) { ringBufferPosition = (ringBufferPosition - 1) & DELAY_LINE_MASK; } - return SampleEx(ACCURATE_LPF_NUMBER_OF_PHASES * sample); + return ACCURATE_LPF_NUMBER_OF_PHASES * sample; +} + +IntSampleEx AccurateLowPassFilter::process(const IntSampleEx sample) { + return IntSampleEx(process(FloatSample(sample))); } bool AccurateLowPassFilter::hasNextSample() const { @@ -321,7 +411,7 @@ unsigned int AccurateLowPassFilter::getOutputSampleRate() const { return outputSampleRate; } -unsigned int AccurateLowPassFilter::estimateInSampleCount(unsigned int outSamples) const { +unsigned int AccurateLowPassFilter::estimateInSampleCount(const unsigned int outSamples) const { Bit32u cycleCount = outSamples / ACCURATE_LPF_NUMBER_OF_PHASES; Bit32u remainder = outSamples - cycleCount * ACCURATE_LPF_NUMBER_OF_PHASES; return cycleCount * phaseIncrement + deltas[remainder][phase]; |