libresidfp  1.2.3
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 
32 namespace reSIDfp
33 {
34 
38 class Filter
39 {
40  friend class State;
41 
42 private:
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 
99 private:
101  uint8_t vol = 0;
102 
104  bool enabled = true;
105 
107  uint8_t filt = 0;
108 
109 protected:
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 
141 public:
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 
212 namespace reSIDfp
213 {
214 
215 RESIDFP_INLINE
216 uint16_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
uint16_t clock(Voice &voice1, Voice &voice2, Voice &voice3)
Definition: Filter.h:216
Definition: Voice.h:38
void writeMODE_VOL(uint8_t mode_vol)
Definition: Filter.cpp:104
void updateMixing()
Definition: Filter.cpp:51
virtual void updateCenterFrequency()=0
Definition: Dac.cpp:27
uint8_t output() const
Definition: EnvelopeGenerator.h:134
Definition: Integrator.h:31
Definition: FilterModelConfig.h:39
void writeRES_FILT(uint8_t res_filt)
Definition: Filter.cpp:87
RESIDFP_INLINE float output()
Definition: Voice.h:67
void writeFC_LO(uint8_t fc_lo)
Definition: Filter.cpp:75
void reset()
Definition: Filter.cpp:143
unsigned int getFC() const
Definition: Filter.h:130
void enable(bool enable)
Definition: Filter.cpp:129
void input(int16_t input)
Definition: Filter.h:203
Definition: Filter.h:38
Definition: State.h:45
void updateResonance(uint8_t res)
Definition: Filter.h:120
void writeFC_HI(uint8_t fc_hi)
Definition: Filter.cpp:81