1 /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
2  * Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
3  *
4  *  This program is free software: you can redistribute it and/or modify
5  *  it under the terms of the GNU Lesser General Public License as published by
6  *  the Free Software Foundation, either version 2.1 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU Lesser General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Lesser General Public License
15  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <cstring>
19 
20 #include "internals.h"
21 
22 #include "Analog.h"
23 #include "Synth.h"
24 
25 namespace MT32Emu {
26 
27 /* FIR approximation of the overall impulse response of the cascade composed of the sample & hold circuit and the low pass filter
28  * of the MT-32 first generation.
29  * The coefficients below are found by windowing the inverse DFT of the 1024 pin frequency response converted to the minimum phase.
30  * The frequency response of the LPF is computed directly, the effect of the S&H is approximated by multiplying the LPF frequency
31  * response by the corresponding sinc. Although, the LPF has DC gain of 3.2, we ignore this in the emulation and use normalised model.
32  * The peak gain of the normalised cascade appears about 1.7 near 11.8 kHz. Relative error doesn't exceed 1% for the frequencies
33  * below 12.5 kHz. In the higher frequency range, the relative error is below 8%. Peak error value is at 16 kHz.
34  */
35 static const FloatSample COARSE_LPF_FLOAT_TAPS_MT32[] = {
36 	1.272473681f, -0.220267785f, -0.158039905f, 0.179603785f, -0.111484097f, 0.054137498f, -0.023518029f, 0.010997169f, -0.006935698f
37 };
38 
39 // Similar approximation for new MT-32 and CM-32L/LAPC-I LPF. As the voltage controlled amplifier was introduced, LPF has unity DC gain.
40 // The peak gain value shifted towards higher frequencies and a bit higher about 1.83 near 13 kHz.
41 static const FloatSample COARSE_LPF_FLOAT_TAPS_CM32L[] = {
42 	1.340615635f, -0.403331694f, 0.036005517f, 0.066156844f, -0.069672532f, 0.049563806f, -0.031113416f, 0.019169774f, -0.012421368f
43 };
44 
45 static const unsigned int COARSE_LPF_INT_FRACTION_BITS = 14;
46 
47 // Integer versions of the FIRs above multiplied by (1 << 14) and rounded.
48 static const IntSampleEx COARSE_LPF_INT_TAPS_MT32[] = {
49 	20848, -3609, -2589, 2943, -1827, 887, -385, 180, -114
50 };
51 
52 static const IntSampleEx COARSE_LPF_INT_TAPS_CM32L[] = {
53 	21965, -6608, 590, 1084, -1142, 812, -510, 314, -204
54 };
55 
56 /* Combined FIR that both approximates the impulse response of the analogue circuits of sample & hold and the low pass filter
57  * in the audible frequency range (below 20 kHz) and attenuates unwanted mirror spectra above 28 kHz as well. It is a polyphase
58  * filter intended for resampling the signal to 48 kHz yet for applying high frequency boost.
59  * As with the filter above, the analogue LPF frequency response is obtained for 1536 pin grid for range up to 96 kHz and multiplied
60  * by the corresponding sinc. The result is further squared, windowed and passed to generalised Parks-McClellan routine as a desired response.
61  * Finally, the minimum phase factor is found that's essentially the coefficients below.
62  * Relative error in the audible frequency range doesn't exceed 0.0006%, attenuation in the stopband is better than 100 dB.
63  * This level of performance makes it nearly bit-accurate for standard 16-bit sample resolution.
64  */
65 
66 // FIR version for MT-32 first generation.
67 static const FloatSample ACCURATE_LPF_TAPS_MT32[] = {
68 	0.003429281f, 0.025929869f, 0.096587777f, 0.228884848f, 0.372413431f, 0.412386503f, 0.263980018f,
69 	-0.014504962f, -0.237394528f, -0.257043496f, -0.103436603f, 0.063996095f, 0.124562333f, 0.083703206f,
70 	0.013921662f, -0.033475018f, -0.046239712f, -0.029310921f, 0.00126585f, 0.021060961f, 0.017925605f,
71 	0.003559874f, -0.005105248f, -0.005647917f, -0.004157918f, -0.002065664f, 0.00158747f, 0.003762585f,
72 	0.001867137f, -0.001090028f, -0.001433979f, -0.00022367f, 4.34308E-05f, -0.000247827f, 0.000157087f,
73 	0.000605823f, 0.000197317f, -0.000370511f, -0.000261202f, 9.96069E-05f, 9.85073E-05f, -5.28754E-05f,
74 	-1.00912E-05f, 7.69943E-05f, 2.03162E-05f, -5.67967E-05f, -3.30637E-05f, 1.61958E-05f, 1.73041E-05f
75 };
76 
77 // FIR version for new MT-32 and CM-32L/LAPC-I.
78 static const FloatSample ACCURATE_LPF_TAPS_CM32L[] = {
79 	0.003917452f, 0.030693861f, 0.116424199f, 0.275101674f, 0.43217361f, 0.431247894f, 0.183255659f,
80 	-0.174955671f, -0.354240244f, -0.212401714f, 0.072259178f, 0.204655344f, 0.108336211f, -0.039099027f,
81 	-0.075138174f, -0.026261906f, 0.00582663f, 0.003052193f, 0.00613657f, 0.017017951f, 0.008732535f,
82 	-0.011027427f, -0.012933664f, 0.001158097f, 0.006765958f, 0.00046778f, -0.002191106f, 0.001561017f,
83 	0.001842871f, -0.001996876f, -0.002315836f, 0.000980965f, 0.001817454f, -0.000243272f, -0.000972848f,
84 	0.000149941f, 0.000498886f, -0.000204436f, -0.000347415f, 0.000142386f, 0.000249137f, -4.32946E-05f,
85 	-0.000131231f, 3.88575E-07f, 4.48813E-05f, -1.31906E-06f, -1.03499E-05f, 7.71971E-06f, 2.86721E-06f
86 };
87 
88 // According to the CM-64 PCB schematic, there is a difference in the values of the LPF entrance resistors for the reverb and non-reverb channels.
89 // This effectively results in non-unity LPF DC gain for the reverb channel of 0.68 while the LPF has unity DC gain for the LA32 output channels.
90 // In emulation, the reverb output gain is multiplied by this factor to compensate for the LPF gain difference.
91 static const float CM32L_REVERB_TO_LA32_ANALOG_OUTPUT_GAIN_FACTOR = 0.68f;
92 
93 static const unsigned int OUTPUT_GAIN_FRACTION_BITS = 8;
94 static const float OUTPUT_GAIN_MULTIPLIER = float(1 << OUTPUT_GAIN_FRACTION_BITS);
95 
96 static const unsigned int COARSE_LPF_DELAY_LINE_LENGTH = 8; // Must be a power of 2
97 static const unsigned int ACCURATE_LPF_DELAY_LINE_LENGTH = 16; // Must be a power of 2
98 static const unsigned int ACCURATE_LPF_NUMBER_OF_PHASES = 3; // Upsampling factor
99 static const unsigned int ACCURATE_LPF_PHASE_INCREMENT_REGULAR = 2; // Downsampling factor
100 static const unsigned int ACCURATE_LPF_PHASE_INCREMENT_OVERSAMPLED = 1; // No downsampling
101 static const Bit32u ACCURATE_LPF_DELTAS_REGULAR[][ACCURATE_LPF_NUMBER_OF_PHASES] = { { 0, 0, 0 }, { 1, 1, 0 }, { 1, 2, 1 } };
102 static const Bit32u ACCURATE_LPF_DELTAS_OVERSAMPLED[][ACCURATE_LPF_NUMBER_OF_PHASES] = { { 0, 0, 0 }, { 1, 0, 0 }, { 1, 0, 1 } };
103 
104 template <class SampleEx>
105 class AbstractLowPassFilter {
106 public:
107 	static AbstractLowPassFilter<SampleEx> &createLowPassFilter(const AnalogOutputMode mode, const bool oldMT32AnalogLPF);
108 
~AbstractLowPassFilter()109 	virtual ~AbstractLowPassFilter() {}
110 	virtual SampleEx process(const SampleEx sample) = 0;
111 
hasNextSample() const112 	virtual bool hasNextSample() const {
113 		return false;
114 	}
115 
getOutputSampleRate() const116 	virtual unsigned int getOutputSampleRate() const {
117 		return SAMPLE_RATE;
118 	}
119 
estimateInSampleCount(const unsigned int outSamples) const120 	virtual unsigned int estimateInSampleCount(const unsigned int outSamples) const {
121 		return outSamples;
122 	}
123 
addPositionIncrement(const unsigned int)124 	virtual void addPositionIncrement(const unsigned int) {}
125 };
126 
127 template <class SampleEx>
128 class NullLowPassFilter : public AbstractLowPassFilter<SampleEx> {
129 public:
process(const SampleEx sample)130 	SampleEx process(const SampleEx sample) {
131 		return sample;
132 	}
133 };
134 
135 template <class SampleEx>
136 class CoarseLowPassFilter : public AbstractLowPassFilter<SampleEx> {
137 private:
138 	const SampleEx * const lpfTaps;
139 	SampleEx ringBuffer[COARSE_LPF_DELAY_LINE_LENGTH];
140 	unsigned int ringBufferPosition;
141 
142 public:
143 	static inline const SampleEx *getLPFTaps(const bool oldMT32AnalogLPF);
144 	static inline SampleEx normaliseSample(const SampleEx sample);
145 
CoarseLowPassFilter(const bool oldMT32AnalogLPF)146 	explicit CoarseLowPassFilter(const bool oldMT32AnalogLPF) :
147 		lpfTaps(getLPFTaps(oldMT32AnalogLPF)),
148 		ringBufferPosition(0)
149 	{
150 		Synth::muteSampleBuffer(ringBuffer, COARSE_LPF_DELAY_LINE_LENGTH);
151 	}
152 
process(const SampleEx inSample)153 	SampleEx process(const SampleEx inSample) {
154 		static const unsigned int DELAY_LINE_MASK = COARSE_LPF_DELAY_LINE_LENGTH - 1;
155 
156 		SampleEx sample = lpfTaps[COARSE_LPF_DELAY_LINE_LENGTH] * ringBuffer[ringBufferPosition];
157 		ringBuffer[ringBufferPosition] = Synth::clipSampleEx(inSample);
158 
159 		for (unsigned int i = 0; i < COARSE_LPF_DELAY_LINE_LENGTH; i++) {
160 			sample += lpfTaps[i] * ringBuffer[(i + ringBufferPosition) & DELAY_LINE_MASK];
161 		}
162 
163 		ringBufferPosition = (ringBufferPosition - 1) & DELAY_LINE_MASK;
164 
165 		return normaliseSample(sample);
166 	}
167 };
168 
169 class AccurateLowPassFilter : public AbstractLowPassFilter<IntSampleEx>, public AbstractLowPassFilter<FloatSample> {
170 private:
171 	const FloatSample * const LPF_TAPS;
172 	const Bit32u (* const deltas)[ACCURATE_LPF_NUMBER_OF_PHASES];
173 	const unsigned int phaseIncrement;
174 	const unsigned int outputSampleRate;
175 
176 	FloatSample ringBuffer[ACCURATE_LPF_DELAY_LINE_LENGTH];
177 	unsigned int ringBufferPosition;
178 	unsigned int phase;
179 
180 public:
181 	AccurateLowPassFilter(const bool oldMT32AnalogLPF, const bool oversample);
182 	FloatSample process(const FloatSample sample);
183 	IntSampleEx process(const IntSampleEx sample);
184 	bool hasNextSample() const;
185 	unsigned int getOutputSampleRate() const;
186 	unsigned int estimateInSampleCount(const unsigned int outSamples) const;
187 	void addPositionIncrement(const unsigned int positionIncrement);
188 };
189 
normaliseSample(const IntSampleEx sample)190 static inline IntSampleEx normaliseSample(const IntSampleEx sample) {
191 	return sample >> OUTPUT_GAIN_FRACTION_BITS;
192 }
193 
normaliseSample(const FloatSample sample)194 static inline FloatSample normaliseSample(const FloatSample sample) {
195 	return sample;
196 }
197 
getActualReverbOutputGain(const float reverbGain,const bool mt32ReverbCompatibilityMode)198 static inline float getActualReverbOutputGain(const float reverbGain, const bool mt32ReverbCompatibilityMode) {
199 	return mt32ReverbCompatibilityMode ? reverbGain : reverbGain * CM32L_REVERB_TO_LA32_ANALOG_OUTPUT_GAIN_FACTOR;
200 }
201 
getIntOutputGain(const float outputGain)202 static inline IntSampleEx getIntOutputGain(const float outputGain) {
203 	return IntSampleEx(((OUTPUT_GAIN_MULTIPLIER < outputGain) ? OUTPUT_GAIN_MULTIPLIER : outputGain) * OUTPUT_GAIN_MULTIPLIER);
204 }
205 
206 template <class SampleEx>
207 class AnalogImpl : public Analog {
208 public:
209 	AbstractLowPassFilter<SampleEx> &leftChannelLPF;
210 	AbstractLowPassFilter<SampleEx> &rightChannelLPF;
211 	SampleEx synthGain;
212 	SampleEx reverbGain;
213 
AnalogImpl(const AnalogOutputMode mode,const bool oldMT32AnalogLPF)214 	AnalogImpl(const AnalogOutputMode mode, const bool oldMT32AnalogLPF) :
215 		leftChannelLPF(AbstractLowPassFilter<SampleEx>::createLowPassFilter(mode, oldMT32AnalogLPF)),
216 		rightChannelLPF(AbstractLowPassFilter<SampleEx>::createLowPassFilter(mode, oldMT32AnalogLPF)),
217 		synthGain(0),
218 		reverbGain(0)
219 	{}
220 
~AnalogImpl()221 	~AnalogImpl() {
222 		delete &leftChannelLPF;
223 		delete &rightChannelLPF;
224 	}
225 
getOutputSampleRate() const226 	unsigned int getOutputSampleRate() const {
227 		return leftChannelLPF.getOutputSampleRate();
228 	}
229 
getDACStreamsLength(const Bit32u outputLength) const230 	Bit32u getDACStreamsLength(const Bit32u outputLength) const {
231 		return leftChannelLPF.estimateInSampleCount(outputLength);
232 	}
233 
234 	void setSynthOutputGain(const float synthGain);
235 	void setReverbOutputGain(const float reverbGain, const bool mt32ReverbCompatibilityMode);
236 
237 	bool process(IntSample *outStream, const IntSample *nonReverbLeft, const IntSample *nonReverbRight, const IntSample *reverbDryLeft, const IntSample *reverbDryRight, const IntSample *reverbWetLeft, const IntSample *reverbWetRight, Bit32u outLength);
238 	bool process(FloatSample *outStream, const FloatSample *nonReverbLeft, const FloatSample *nonReverbRight, const FloatSample *reverbDryLeft, const FloatSample *reverbDryRight, const FloatSample *reverbWetLeft, const FloatSample *reverbWetRight, Bit32u outLength);
239 
240 	template <class Sample>
produceOutput(Sample * outStream,const Sample * nonReverbLeft,const Sample * nonReverbRight,const Sample * reverbDryLeft,const Sample * reverbDryRight,const Sample * reverbWetLeft,const Sample * reverbWetRight,Bit32u outLength)241 	void produceOutput(Sample *outStream, const Sample *nonReverbLeft, const Sample *nonReverbRight, const Sample *reverbDryLeft, const Sample *reverbDryRight, const Sample *reverbWetLeft, const Sample *reverbWetRight, Bit32u outLength) {
242 		if (outStream == NULL) {
243 			leftChannelLPF.addPositionIncrement(outLength);
244 			rightChannelLPF.addPositionIncrement(outLength);
245 			return;
246 		}
247 
248 		while (0 < (outLength--)) {
249 			SampleEx outSampleL;
250 			SampleEx outSampleR;
251 
252 			if (leftChannelLPF.hasNextSample()) {
253 				outSampleL = leftChannelLPF.process(0);
254 				outSampleR = rightChannelLPF.process(0);
255 			} else {
256 				SampleEx inSampleL = (SampleEx(*(nonReverbLeft++)) + SampleEx(*(reverbDryLeft++))) * synthGain + SampleEx(*(reverbWetLeft++)) * reverbGain;
257 				SampleEx inSampleR = (SampleEx(*(nonReverbRight++)) + SampleEx(*(reverbDryRight++))) * synthGain + SampleEx(*(reverbWetRight++)) * reverbGain;
258 
259 				outSampleL = leftChannelLPF.process(normaliseSample(inSampleL));
260 				outSampleR = rightChannelLPF.process(normaliseSample(inSampleR));
261 			}
262 
263 			*(outStream++) = Synth::clipSampleEx(outSampleL);
264 			*(outStream++) = Synth::clipSampleEx(outSampleR);
265 		}
266 	}
267 };
268 
createAnalog(const AnalogOutputMode mode,const bool oldMT32AnalogLPF,const RendererType rendererType)269 Analog *Analog::createAnalog(const AnalogOutputMode mode, const bool oldMT32AnalogLPF, const RendererType rendererType) {
270 	switch (rendererType)
271 	{
272 	case RendererType_BIT16S:
273 		return new AnalogImpl<IntSampleEx>(mode, oldMT32AnalogLPF);
274 	case RendererType_FLOAT:
275 		return new AnalogImpl<FloatSample>(mode, oldMT32AnalogLPF);
276 	}
277 	return NULL;
278 }
279 
280 template<>
process(IntSample * outStream,const IntSample * nonReverbLeft,const IntSample * nonReverbRight,const IntSample * reverbDryLeft,const IntSample * reverbDryRight,const IntSample * reverbWetLeft,const IntSample * reverbWetRight,Bit32u outLength)281 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) {
282 	produceOutput(outStream, nonReverbLeft, nonReverbRight, reverbDryLeft, reverbDryRight, reverbWetLeft, reverbWetRight, outLength);
283 	return true;
284 }
285 
286 template<>
process(IntSample *,const IntSample *,const IntSample *,const IntSample *,const IntSample *,const IntSample *,const IntSample *,Bit32u)287 bool AnalogImpl<FloatSample>::process(IntSample *, const IntSample *, const IntSample *, const IntSample *, const IntSample *, const IntSample *, const IntSample *, Bit32u) {
288 	return false;
289 }
290 
291 template<>
process(FloatSample *,const FloatSample *,const FloatSample *,const FloatSample *,const FloatSample *,const FloatSample *,const FloatSample *,Bit32u)292 bool AnalogImpl<IntSampleEx>::process(FloatSample *, const FloatSample *, const FloatSample *, const FloatSample *, const FloatSample *, const FloatSample *, const FloatSample *, Bit32u) {
293 	return false;
294 }
295 
296 template<>
process(FloatSample * outStream,const FloatSample * nonReverbLeft,const FloatSample * nonReverbRight,const FloatSample * reverbDryLeft,const FloatSample * reverbDryRight,const FloatSample * reverbWetLeft,const FloatSample * reverbWetRight,Bit32u outLength)297 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) {
298 	produceOutput(outStream, nonReverbLeft, nonReverbRight, reverbDryLeft, reverbDryRight, reverbWetLeft, reverbWetRight, outLength);
299 	return true;
300 }
301 
302 template<>
setSynthOutputGain(const float useSynthGain)303 void AnalogImpl<IntSampleEx>::setSynthOutputGain(const float useSynthGain) {
304 	synthGain = getIntOutputGain(useSynthGain);
305 }
306 
307 template<>
setReverbOutputGain(const float useReverbGain,const bool mt32ReverbCompatibilityMode)308 void AnalogImpl<IntSampleEx>::setReverbOutputGain(const float useReverbGain, const bool mt32ReverbCompatibilityMode) {
309 	reverbGain = getIntOutputGain(getActualReverbOutputGain(useReverbGain, mt32ReverbCompatibilityMode));
310 }
311 
312 template<>
setSynthOutputGain(const float useSynthGain)313 void AnalogImpl<FloatSample>::setSynthOutputGain(const float useSynthGain) {
314 	synthGain = useSynthGain;
315 }
316 
317 template<>
setReverbOutputGain(const float useReverbGain,const bool mt32ReverbCompatibilityMode)318 void AnalogImpl<FloatSample>::setReverbOutputGain(const float useReverbGain, const bool mt32ReverbCompatibilityMode) {
319 	reverbGain = getActualReverbOutputGain(useReverbGain, mt32ReverbCompatibilityMode);
320 }
321 
322 template<>
createLowPassFilter(AnalogOutputMode mode,bool oldMT32AnalogLPF)323 AbstractLowPassFilter<IntSampleEx> &AbstractLowPassFilter<IntSampleEx>::createLowPassFilter(AnalogOutputMode mode, bool oldMT32AnalogLPF) {
324 	switch (mode) {
325 	case AnalogOutputMode_COARSE:
326 		return *new CoarseLowPassFilter<IntSampleEx>(oldMT32AnalogLPF);
327 	case AnalogOutputMode_ACCURATE:
328 		return *new AccurateLowPassFilter(oldMT32AnalogLPF, false);
329 	case AnalogOutputMode_OVERSAMPLED:
330 		return *new AccurateLowPassFilter(oldMT32AnalogLPF, true);
331 	default:
332 		return *new NullLowPassFilter<IntSampleEx>;
333 	}
334 }
335 
336 template<>
createLowPassFilter(AnalogOutputMode mode,bool oldMT32AnalogLPF)337 AbstractLowPassFilter<FloatSample> &AbstractLowPassFilter<FloatSample>::createLowPassFilter(AnalogOutputMode mode, bool oldMT32AnalogLPF) {
338 	switch (mode) {
339 		case AnalogOutputMode_COARSE:
340 			return *new CoarseLowPassFilter<FloatSample>(oldMT32AnalogLPF);
341 		case AnalogOutputMode_ACCURATE:
342 			return *new AccurateLowPassFilter(oldMT32AnalogLPF, false);
343 		case AnalogOutputMode_OVERSAMPLED:
344 			return *new AccurateLowPassFilter(oldMT32AnalogLPF, true);
345 		default:
346 			return *new NullLowPassFilter<FloatSample>;
347 	}
348 }
349 
350 template<>
getLPFTaps(const bool oldMT32AnalogLPF)351 const IntSampleEx *CoarseLowPassFilter<IntSampleEx>::getLPFTaps(const bool oldMT32AnalogLPF) {
352 	return oldMT32AnalogLPF ? COARSE_LPF_INT_TAPS_MT32 : COARSE_LPF_INT_TAPS_CM32L;
353 }
354 
355 template<>
getLPFTaps(const bool oldMT32AnalogLPF)356 const FloatSample *CoarseLowPassFilter<FloatSample>::getLPFTaps(const bool oldMT32AnalogLPF) {
357 	return oldMT32AnalogLPF ? COARSE_LPF_FLOAT_TAPS_MT32 : COARSE_LPF_FLOAT_TAPS_CM32L;
358 }
359 
360 template<>
normaliseSample(const IntSampleEx sample)361 IntSampleEx CoarseLowPassFilter<IntSampleEx>::normaliseSample(const IntSampleEx sample) {
362 	return sample >> COARSE_LPF_INT_FRACTION_BITS;
363 }
364 
365 template<>
normaliseSample(const FloatSample sample)366 FloatSample CoarseLowPassFilter<FloatSample>::normaliseSample(const FloatSample sample) {
367 	return sample;
368 }
369 
AccurateLowPassFilter(const bool oldMT32AnalogLPF,const bool oversample)370 AccurateLowPassFilter::AccurateLowPassFilter(const bool oldMT32AnalogLPF, const bool oversample) :
371 	LPF_TAPS(oldMT32AnalogLPF ? ACCURATE_LPF_TAPS_MT32 : ACCURATE_LPF_TAPS_CM32L),
372 	deltas(oversample ? ACCURATE_LPF_DELTAS_OVERSAMPLED : ACCURATE_LPF_DELTAS_REGULAR),
373 	phaseIncrement(oversample ? ACCURATE_LPF_PHASE_INCREMENT_OVERSAMPLED : ACCURATE_LPF_PHASE_INCREMENT_REGULAR),
374 	outputSampleRate(SAMPLE_RATE * ACCURATE_LPF_NUMBER_OF_PHASES / phaseIncrement),
375 	ringBufferPosition(0),
376 	phase(0)
377 {
378 	Synth::muteSampleBuffer(ringBuffer, ACCURATE_LPF_DELAY_LINE_LENGTH);
379 }
380 
process(const FloatSample inSample)381 FloatSample AccurateLowPassFilter::process(const FloatSample inSample) {
382 	static const unsigned int DELAY_LINE_MASK = ACCURATE_LPF_DELAY_LINE_LENGTH - 1;
383 
384 	FloatSample sample = (phase == 0) ? LPF_TAPS[ACCURATE_LPF_DELAY_LINE_LENGTH * ACCURATE_LPF_NUMBER_OF_PHASES] * ringBuffer[ringBufferPosition] : 0.0f;
385 	if (!hasNextSample()) {
386 		ringBuffer[ringBufferPosition] = inSample;
387 	}
388 
389 	for (unsigned int tapIx = phase, delaySampleIx = 0; delaySampleIx < ACCURATE_LPF_DELAY_LINE_LENGTH; delaySampleIx++, tapIx += ACCURATE_LPF_NUMBER_OF_PHASES) {
390 		sample += LPF_TAPS[tapIx] * ringBuffer[(delaySampleIx + ringBufferPosition) & DELAY_LINE_MASK];
391 	}
392 
393 	phase += phaseIncrement;
394 	if (ACCURATE_LPF_NUMBER_OF_PHASES <= phase) {
395 		phase -= ACCURATE_LPF_NUMBER_OF_PHASES;
396 		ringBufferPosition = (ringBufferPosition - 1) & DELAY_LINE_MASK;
397 	}
398 
399 	return ACCURATE_LPF_NUMBER_OF_PHASES * sample;
400 }
401 
process(const IntSampleEx sample)402 IntSampleEx AccurateLowPassFilter::process(const IntSampleEx sample) {
403 	return IntSampleEx(process(FloatSample(sample)));
404 }
405 
hasNextSample() const406 bool AccurateLowPassFilter::hasNextSample() const {
407 	return phaseIncrement <= phase;
408 }
409 
getOutputSampleRate() const410 unsigned int AccurateLowPassFilter::getOutputSampleRate() const {
411 	return outputSampleRate;
412 }
413 
estimateInSampleCount(const unsigned int outSamples) const414 unsigned int AccurateLowPassFilter::estimateInSampleCount(const unsigned int outSamples) const {
415 	Bit32u cycleCount = outSamples / ACCURATE_LPF_NUMBER_OF_PHASES;
416 	Bit32u remainder = outSamples - cycleCount * ACCURATE_LPF_NUMBER_OF_PHASES;
417 	return cycleCount * phaseIncrement + deltas[remainder][phase];
418 }
419 
addPositionIncrement(const unsigned int positionIncrement)420 void AccurateLowPassFilter::addPositionIncrement(const unsigned int positionIncrement) {
421 	phase = (phase + positionIncrement * phaseIncrement) % ACCURATE_LPF_NUMBER_OF_PHASES;
422 }
423 
424 } // namespace MT32Emu
425