libresidfp 1.1.1
Filter.h
1/*
2 * This file is part of libsidplayfp, a SID player engine.
3 *
4 * Copyright 2011-2026 Leandro Nini <drfiemost@users.sourceforge.net>
5 * Copyright 2007-2010 Antti Lankila
6 * Copyright 2004 Dag Lem <resid@nimrod.no>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22
23#ifndef FILTER_H
24#define FILTER_H
25
26#include "FilterModelConfig.h"
27#include "Integrator.h"
28#include "Voice.h"
29
30#include "siddefs-fp.h"
31
32namespace reSIDfp
33{
34
38class Filter
39{
40 friend class State;
41
42private:
43 uint16_t* mixer;
44 uint16_t* summer;
45 uint16_t* resonance;
46 uint16_t* volume;
47
48 const FilterModelConfig& m_fmc;
49
50 const Integrator& m_hpIntegrator;
51
52 const Integrator& m_bpIntegrator;
53
55 uint16_t* currentMixer = nullptr;
56
58 uint16_t* currentSummer = nullptr;
59
61 uint16_t* currentResonance = nullptr;
62
64 uint16_t* currentVolume = nullptr;
65
67 int32_t Vhp = 0;
68
70 int32_t Vbp = 0;
71
73 int32_t Vlp = 0;
74
76 float extin = 0;
77
79 uint16_t fc = 0;
80
82
83 bool filt1 = false;
84 bool filt2 = false;
85 bool filt3 = false;
86 bool filtE = false;
88
90 bool voice3off = false;
91
93
94 bool hp = false;
95 bool bp = false;
96 bool lp = false;
98
99private:
101 uint8_t vol = 0;
102
104 bool enabled = true;
105
107 uint8_t filt = 0;
108
109protected:
113 virtual void updateCenterFrequency() = 0;
114
120 void updateResonance(uint8_t res) { currentResonance = resonance + (res * (1<<16)); }
121
125 void updateMixing();
126
130 inline unsigned int getFC() const { return static_cast<unsigned int>(fc); }
131
132 virtual void restartIntegrators() = 0;
133
134 inline int32_t getNormalizedVoice(float v, uint8_t env) const
135 {
136 return m_fmc.getNormalizedVoice(v, env);
137 }
138
139 virtual int32_t getNormalizedMixerVoice(float v, uint8_t env) const = 0;
140
141public:
142 Filter(const FilterModelConfig& fmc,
143 const Integrator& hpIntegrator,
144 const Integrator& bpIntegrator);
145
146 virtual ~Filter() = default;
147
156 uint16_t clock(Voice& voice1, Voice& voice2, Voice& voice3);
157
163 void enable(bool enable);
164
168 void reset();
169
175 void writeFC_LO(uint8_t fc_lo);
176
182 void writeFC_HI(uint8_t fc_hi);
183
189 void writeRES_FILT(uint8_t res_filt);
190
196 void writeMODE_VOL(uint8_t mode_vol);
197
203 void input(int16_t input) { extin = input/65535.f; }
204
205 void restart() { restartIntegrators(); Vhp = 0; Vlp = 0; Vbp = 0; }
206};
207
208} // namespace reSIDfp
209
210#if RESIDFP_INLINING || defined(FILTER_CPP)
211
212namespace reSIDfp
213{
214
215RESIDFP_INLINE
216uint16_t Filter::clock(Voice& voice1, Voice& voice2, Voice& voice3)
217{
218 // Waveform outputs
219 const float wav1 = voice1.output();
220 const float wav2 = voice2.output();
221 const float wav3 = voice3.output();
222
223 // Envelope outputs
224 const uint8_t env1 = voice1.envelope()->output();
225 const uint8_t env2 = voice2.envelope()->output();
226 const uint8_t env3 = voice3.envelope()->output();
227
228 // Voltage summer for filter input
229 int32_t Vsum = 0;
230 Vsum += filt1 ? getNormalizedVoice(wav1, env1) : 0;
231 Vsum += filt2 ? getNormalizedVoice(wav2, env2) : 0;
232 Vsum += filt3 ? getNormalizedVoice(wav3, env3) : 0;
233 Vsum += filtE ? getNormalizedVoice(extin, 0) : 0;
234 Vsum += Vlp;
235 Vsum += currentResonance[Vbp];
236
237 // Filter
238 Vhp = currentSummer[Vsum];
239 Vbp = m_hpIntegrator.solve(Vhp);
240 Vlp = m_bpIntegrator.solve(Vbp);
241
242 int32_t Vfilt = 0;
243 if (lp) Vfilt += Vlp;
244 if (bp) Vfilt += Vbp;
245 if (hp) Vfilt += Vhp;
246
247 // Voltage summer for mixer input
248 int32_t Vmix = 0;
249 Vmix += filt1 ? 0 : getNormalizedMixerVoice(wav1, env1);
250 Vmix += filt2 ? 0 : getNormalizedMixerVoice(wav2, env2);
251 // Voice 3 is silenced by voice3off if it is not routed through the filter
252 Vmix += (filt3 || voice3off) ? 0 : getNormalizedMixerVoice(wav3, env3);
253 Vmix += filtE ? 0 : getNormalizedMixerVoice(extin, 0);
254 Vmix += Vfilt;
255
256 return currentVolume[currentMixer[Vmix]];
257}
258
259} // namespace reSIDfp
260
261#endif
262
263#endif
uint8_t output() const
Definition EnvelopeGenerator.h:134
Definition FilterModelConfig.h:40
Definition Filter.h:39
void writeFC_HI(uint8_t fc_hi)
Definition Filter.cpp:81
void updateResonance(uint8_t res)
Definition Filter.h:120
void input(int16_t input)
Definition Filter.h:203
void writeMODE_VOL(uint8_t mode_vol)
Definition Filter.cpp:104
void writeRES_FILT(uint8_t res_filt)
Definition Filter.cpp:87
void writeFC_LO(uint8_t fc_lo)
Definition Filter.cpp:75
void enable(bool enable)
Definition Filter.cpp:129
void reset()
Definition Filter.cpp:143
virtual void updateCenterFrequency()=0
void updateMixing()
Definition Filter.cpp:51
uint16_t clock(Voice &voice1, Voice &voice2, Voice &voice3)
Definition Filter.h:216
unsigned int getFC() const
Definition Filter.h:130
Definition Integrator.h:32
Definition Voice.h:39
RESIDFP_INLINE float output()
Definition Voice.h:67
Definition State.h:47