libsidplayfp  2.11.0
FilterModelConfig.h
1 /*
2  * This file is part of libsidplayfp, a SID player engine.
3  *
4  * Copyright 2011-2024 Leandro Nini <drfiemost@users.sourceforge.net>
5  * Copyright 2007-2010 Antti Lankila
6  * Copyright 2004,2010 Dag Lem
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 FILTERMODELCONFIG_H
24 #define FILTERMODELCONFIG_H
25 
26 #include <algorithm>
27 #include <random>
28 #include <cassert>
29 
30 #include "OpAmp.h"
31 #include "Spline.h"
32 
33 #include "sidcxx11.h"
34 
35 namespace reSIDfp
36 {
37 
39 {
40 private:
41  /*
42  * Hack to add quick dither when converting values from float to int
43  * and avoid quantization noise.
44  * Hopefully this can be removed the day we move all the analog part
45  * processing to floats.
46  *
47  * Not sure about the effect of using such small buffer of numbers
48  * since the random sequence repeats every 1024 values but for
49  * now it seems to do the job.
50  */
51  class Randomnoise
52  {
53  private:
54  double buffer[1024];
55  mutable int index = 0;
56  public:
57  Randomnoise()
58  {
59  std::uniform_real_distribution<double> unif(0., 1.);
60  std::default_random_engine re;
61  for (int i=0; i<1024; i++)
62  buffer[i] = unif(re);
63  }
64  double getNoise() const { index = (index + 1) & 0x3ff; return buffer[index]; }
65  };
66 
67 protected:
69  const double C;
70 
72 
73  static constexpr double Ut = 26.0e-3;
75 
76  const double Vdd;
77  const double Vth;
78  const double Vddt;
79  double uCox;
81 
82  // Derived stuff
83  const double vmin, vmax;
84  const double denorm, norm;
85 
87  const double N16;
88 
89  const double voice_voltage_range;
90 
93 
95 
96  unsigned short* mixer[8]; //-V730_NOINIT this is initialized in the derived class constructor
97  unsigned short* summer[5]; //-V730_NOINIT this is initialized in the derived class constructor
98  unsigned short* volume[16]; //-V730_NOINIT this is initialized in the derived class constructor
99  unsigned short* resonance[16]; //-V730_NOINIT this is initialized in the derived class constructor
101 
103  unsigned short opamp_rev[1 << 16]; //-V730_NOINIT this is initialized in the derived class constructor
104 
105 private:
106  Randomnoise rnd;
107 
108 private:
109  FilterModelConfig(const FilterModelConfig&) = delete;
110  FilterModelConfig& operator= (const FilterModelConfig&) = delete;
111 
112  inline double getVoiceVoltage(float value, unsigned int env) const
113  {
114  return value * voice_voltage_range + getVoiceDC(env);
115  }
116 
117 protected:
128  double vvr,
129  double c,
130  double vdd,
131  double vth,
132  double ucox,
133  const Spline::Point *opamp_voltage,
134  int opamp_size
135  );
136 
138 
139  void setUCox(double new_uCox);
140 
141  virtual double getVoiceDC(unsigned int env) const = 0;
142 
152  inline void buildSummerTable(const OpAmp& opampModel)
153  {
154  const double r_N16 = 1. / N16;
155 
156  for (int i = 0; i < 5; i++)
157  {
158  const int idiv = 2 + i; // 2 - 6 input "resistors".
159  const int size = idiv << 16;
160  const double n = idiv;
161  const double r_idiv = 1. / idiv;
162  opampModel.reset();
163  summer[i] = new unsigned short[size];
164 
165  for (int vi = 0; vi < size; vi++)
166  {
167  const double vin = vmin + vi * r_N16 * r_idiv; /* vmin .. vmax */
168  summer[i][vi] = getNormalizedValue(opampModel.solve(n, vin));
169  }
170  }
171  }
172 
181  inline void buildMixerTable(const OpAmp& opampModel, double nRatio)
182  {
183  const double r_N16 = 1. / N16;
184 
185  for (int i = 0; i < 8; i++)
186  {
187  const int idiv = (i == 0) ? 1 : i;
188  const int size = (i == 0) ? 1 : i << 16;
189  const double n = i * nRatio;
190  const double r_idiv = 1. / idiv;
191  opampModel.reset();
192  mixer[i] = new unsigned short[size];
193 
194  for (int vi = 0; vi < size; vi++)
195  {
196  const double vin = vmin + vi * r_N16 * r_idiv; /* vmin .. vmax */
197  mixer[i][vi] = getNormalizedValue(opampModel.solve(n, vin));
198  }
199  }
200  }
201 
209  inline void buildVolumeTable(const OpAmp& opampModel, double nDivisor)
210  {
211  const double r_N16 = 1. / N16;
212 
213  for (int n8 = 0; n8 < 16; n8++)
214  {
215  const int size = 1 << 16;
216  const double n = n8 / nDivisor;
217  opampModel.reset();
218  volume[n8] = new unsigned short[size];
219 
220  for (int vi = 0; vi < size; vi++)
221  {
222  const double vin = vmin + vi * r_N16; /* vmin .. vmax */
223  volume[n8][vi] = getNormalizedValue(opampModel.solve(n, vin));
224  }
225  }
226  }
227 
235  inline void buildResonanceTable(const OpAmp& opampModel, const double resonance_n[16])
236  {
237  const double r_N16 = 1. / N16;
238 
239  for (int n8 = 0; n8 < 16; n8++)
240  {
241  const int size = 1 << 16;
242  opampModel.reset();
243  resonance[n8] = new unsigned short[size];
244 
245  for (int vi = 0; vi < size; vi++)
246  {
247  const double vin = vmin + vi * r_N16; /* vmin .. vmax */
248  resonance[n8][vi] = getNormalizedValue(opampModel.solve(resonance_n[n8], vin));
249  }
250  }
251  }
252 
253 public:
254  unsigned short** getVolume() { return volume; }
255  unsigned short** getResonance() { return resonance; }
256  unsigned short** getSummer() { return summer; }
257  unsigned short** getMixer() { return mixer; }
258 
259  inline unsigned short getOpampRev(int i) const { return opamp_rev[i]; }
260  inline double getVddt() const { return Vddt; }
261  inline double getVth() const { return Vth; }
262 
263  // helper functions
264 
265  inline unsigned short getNormalizedValue(double value) const
266  {
267  const double tmp = N16 * (value - vmin);
268  assert(tmp >= 0. && tmp <= 65535.);
269  return static_cast<unsigned short>(tmp + rnd.getNoise());
270  }
271 
272  inline unsigned short getNormalizedCurrentFactor(double wl) const
273  {
274  const double tmp = (1 << 13) * currFactorCoeff * wl;
275  assert(tmp > -0.5 && tmp < 65535.5);
276  return static_cast<unsigned short>(tmp + 0.5);
277  }
278 
279  inline unsigned short getNVmin() const
280  {
281  const double tmp = N16 * vmin;
282  assert(tmp > -0.5 && tmp < 65535.5);
283  return static_cast<unsigned short>(tmp + 0.5);
284  }
285 
286  inline int getNormalizedVoice(float value, unsigned int env) const
287  {
288  return static_cast<int>(getNormalizedValue(getVoiceVoltage(value, env)));
289  }
290 };
291 
292 } // namespace reSIDfp
293 
294 #endif
Definition: FilterModelConfig.h:39
void buildVolumeTable(const OpAmp &opampModel, double nDivisor)
Definition: FilterModelConfig.h:209
const double Vdd
Positive supply voltage.
Definition: FilterModelConfig.h:76
unsigned short * mixer[8]
Lookup tables for gain and summer op-amps in output stage / filter.
Definition: FilterModelConfig.h:96
void buildResonanceTable(const OpAmp &opampModel, const double resonance_n[16])
Definition: FilterModelConfig.h:235
double uCox
Transconductance coefficient: u*Cox.
Definition: FilterModelConfig.h:79
const double Vddt
Vdd - Vth.
Definition: FilterModelConfig.h:78
double currFactorCoeff
Current factor coefficient for op-amp integrators.
Definition: FilterModelConfig.h:92
const double C
Capacitor value.
Definition: FilterModelConfig.h:69
unsigned short opamp_rev[1<< 16]
Reverse op-amp transfer function.
Definition: FilterModelConfig.h:103
static constexpr double Ut
Transistor parameters.
Definition: FilterModelConfig.h:74
const double Vth
Threshold voltage.
Definition: FilterModelConfig.h:77
void buildMixerTable(const OpAmp &opampModel, double nRatio)
Definition: FilterModelConfig.h:181
const double N16
Fixed point scaling for 16 bit op-amp output.
Definition: FilterModelConfig.h:87
void buildSummerTable(const OpAmp &opampModel)
Definition: FilterModelConfig.h:152
Definition: OpAmp.h:71
double solve(double n, double vi) const
Definition: OpAmp.cpp:33
void reset() const
Definition: OpAmp.h:102
Definition: Spline.h:42