libsidplayfp 2.13.1
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
35namespace reSIDfp
36{
37
39{
40private:
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
67protected:
69 const double C;
70
72
73
74 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
105private:
106 Randomnoise rnd;
107
108private:
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
117protected:
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
253public:
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 template<int N>
273 inline unsigned short getNormalizedCurrentFactor(double wl) const
274 {
275 const double tmp = (1 << N) * currFactorCoeff * wl;
276 assert(tmp > -0.5 && tmp < 65535.5);
277 return static_cast<unsigned short>(tmp + 0.5);
278 }
279
280 inline unsigned short getNVmin() const
281 {
282 const double tmp = N16 * vmin;
283 assert(tmp > -0.5 && tmp < 65535.5);
284 return static_cast<unsigned short>(tmp + 0.5);
285 }
286
287 inline int getNormalizedVoice(float value, unsigned int env) const
288 {
289 return static_cast<int>(getNormalizedValue(getVoiceVoltage(value, env)));
290 }
291};
292
293} // namespace reSIDfp
294
295#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