aboutsummaryrefslogtreecommitdiff
path: root/audio/softsynth/mt32/Analog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'audio/softsynth/mt32/Analog.cpp')
-rw-r--r--audio/softsynth/mt32/Analog.cpp334
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];