libsidplayfp  1.0.3
Filter6581.h
1 /*
2  * This file is part of libsidplayfp, a SID player engine.
3  *
4  * Copyright 2011-2013 Leandro Nini <drfiemost@users.sourceforge.net>
5  * Copyright 2007-2010 Antti Lankila
6  * Copyright 2004,2010 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 FILTER6581_H
24 #define FILTER6581_H
25 
26 #include "siddefs-fp.h"
27 
28 #include "Filter.h"
29 #include "FilterModelConfig.h"
30 
31 namespace reSIDfp
32 {
33 
34 class Integrator;
35 
47 class Filter6581 : public Filter
48 {
49 private:
51  int Vhp;
52 
54  int Vbp;
55 
57  int Vlp;
58 
60  int ve;
61 
62  const int voiceScaleS14, voiceDC, vo_T16;
63 
65  unsigned short* currentGain;
66 
68  unsigned short* currentMixer;
69 
71  unsigned short* currentSummer;
72 
74  unsigned short* currentResonance;
75 
77  Integrator* hpIntegrator;
78 
80  Integrator* bpIntegrator;
81 
82  const unsigned int* f0_dac;
83 
84  unsigned short** mixer;
85  unsigned short** summer;
86  unsigned short** gain;
87 
88 public:
89  Filter6581() :
90  Vhp(0),
91  Vbp(0),
92  Vlp(0),
93  ve(0),
94  voiceScaleS14(FilterModelConfig::getInstance()->getVoiceScaleS14()),
95  voiceDC(FilterModelConfig::getInstance()->getVoiceDC()),
96  vo_T16(FilterModelConfig::getInstance()->getVO_T16()),
97  currentGain(0),
98  currentMixer(0),
99  currentSummer(0),
100  currentResonance(0),
101  hpIntegrator(FilterModelConfig::getInstance()->buildIntegrator()),
102  bpIntegrator(FilterModelConfig::getInstance()->buildIntegrator()),
103  f0_dac(FilterModelConfig::getInstance()->getDAC(FilterModelConfig::getInstance()->getDacZero(0.5))),
104  mixer(FilterModelConfig::getInstance()->getMixer()),
105  summer(FilterModelConfig::getInstance()->getSummer()),
106  gain(FilterModelConfig::getInstance()->getGain())
107  {
108  input(0);
109  }
110 
111  ~Filter6581();
112 
113  int clock(int voice1, int voice2, int voice3);
114 
115  void input(int sample) { ve = (sample * voiceScaleS14 * 3 >> 10) + mixer[0][0]; }
116 
120  void updatedCenterFrequency();
121 
128  void updatedResonance() { currentResonance = gain[~res & 0xf]; }
129 
130  void updatedMixing();
131 
132 public:
138  void setFilterCurve(double curvePosition);
139 };
140 
141 } // namespace reSIDfp
142 
143 #if RESID_INLINING || defined(FILTER6581_CPP)
144 
145 #include "Integrator.h"
146 
147 namespace reSIDfp
148 {
149 
150 RESID_INLINE
151 int Filter6581::clock(int voice1, int voice2, int voice3)
152 {
153 
154  const int v1 = (voice1 * voiceScaleS14 >> 18) + voiceDC;
155  const int v2 = (voice2 * voiceScaleS14 >> 18) + voiceDC;
156  const int v3 = (voice3 * voiceScaleS14 >> 18) + voiceDC;
157 
158  int Vi = 0;
159  int Vo = 0;
160 
161  if (filt1)
162  {
163  Vi += v1;
164  }
165  else
166  {
167  Vo += v1;
168  }
169 
170  if (filt2)
171  {
172  Vi += v2;
173  }
174  else
175  {
176  Vo += v2;
177  }
178 
179  // NB! Voice 3 is not silenced by voice3off if it is routed
180  // through the filter.
181  if (filt3)
182  {
183  Vi += v3;
184  }
185  else if (!voice3off)
186  {
187  Vo += v3;
188  }
189 
190  if (filtE)
191  {
192  Vi += ve;
193  }
194  else
195  {
196  Vo += ve;
197  }
198 
199  const int oldVhp = Vhp;
200  Vhp = currentSummer[currentResonance[Vbp] + Vlp + Vi];
201  Vlp = bpIntegrator->solve(Vbp + vo_T16) - vo_T16;
202  Vbp = hpIntegrator->solve(oldVhp + vo_T16) - vo_T16;
203 
204  if (lp)
205  {
206  Vo += Vlp;
207  }
208 
209  if (bp)
210  {
211  Vo += Vbp;
212  }
213 
214  if (hp)
215  {
216  Vo += Vhp;
217  }
218 
219  return currentGain[currentMixer[Vo]] - (1 << 15);
220 }
221 
222 } // namespace reSIDfp
223 
224 #endif
225 
226 #endif