libsidplayfp  2.0.2
Filter8580.h
1 /*
2  * This file is part of libsidplayfp, a SID player engine.
3  *
4  * Copyright 2011-2019 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 FILTER8580_H
24 #define FILTER8580_H
25 
26 #include "siddefs-fp.h"
27 
28 #include <memory>
29 
30 #include "Filter.h"
31 #include "FilterModelConfig8580.h"
32 #include "Integrator8580.h"
33 
34 #include "sidcxx11.h"
35 
36 namespace reSIDfp
37 {
38 
39 class Integrator8580;
40 
281 class Filter8580 final : public Filter
282 {
283 private:
284  unsigned short** mixer;
285  unsigned short** summer;
286  unsigned short** gain_res;
287  unsigned short** gain_vol;
288 
289  const int voiceScaleS14;
290  const int voiceDC;
291 
292  double cp;
293 
295  std::unique_ptr<Integrator8580> const hpIntegrator;
296 
298  std::unique_ptr<Integrator8580> const bpIntegrator;
299 
300 protected:
304  void updatedCenterFrequency() override;
305 
315  void updateResonance(unsigned char res) override { currentResonance = gain_res[res]; }
316 
317  void updatedMixing() override;
318 
319 public:
320  Filter8580() :
321  mixer(FilterModelConfig8580::getInstance()->getMixer()),
322  summer(FilterModelConfig8580::getInstance()->getSummer()),
323  gain_res(FilterModelConfig8580::getInstance()->getGainRes()),
324  gain_vol(FilterModelConfig8580::getInstance()->getGainVol()),
325  voiceScaleS14(FilterModelConfig8580::getInstance()->getVoiceScaleS14()),
326  voiceDC(FilterModelConfig8580::getInstance()->getVoiceDC()),
327  cp(0.5),
328  hpIntegrator(FilterModelConfig8580::getInstance()->buildIntegrator()),
329  bpIntegrator(FilterModelConfig8580::getInstance()->buildIntegrator())
330  {
331  setFilterCurve(cp);
332  input(0);
333  }
334 
335  ~Filter8580();
336 
337  int clock(int voice1, int voice2, int voice3) override;
338 
339  void input(int sample) override { ve = (sample * voiceScaleS14 * 3 >> 14) + mixer[0][0]; }
340 
346  void setFilterCurve(double curvePosition);
347 };
348 
349 } // namespace reSIDfp
350 
351 #if RESID_INLINING || defined(FILTER8580_CPP)
352 
353 namespace reSIDfp
354 {
355 
356 RESID_INLINE
357 int Filter8580::clock(int voice1, int voice2, int voice3)
358 {
359  voice1 = (voice1 * voiceScaleS14 >> 18) + voiceDC;
360  voice2 = (voice2 * voiceScaleS14 >> 18) + voiceDC;
361  // Voice 3 is silenced by voice3off if it is not routed through the filter.
362  voice3 = filt3 || !voice3off ? (voice3 * voiceScaleS14 >> 18) + voiceDC : 0;
363 
364  int Vi = 0;
365  int Vo = 0;
366 
367  (filt1 ? Vi : Vo) += voice1;
368  (filt2 ? Vi : Vo) += voice2;
369  (filt3 ? Vi : Vo) += voice3;
370  (filtE ? Vi : Vo) += ve;
371 
372  Vhp = currentSummer[currentResonance[Vbp] + Vlp + Vi];
373  Vbp = hpIntegrator->solve(Vhp);
374  Vlp = bpIntegrator->solve(Vbp);
375 
376  if (lp) Vo += Vlp;
377  if (bp) Vo += Vbp;
378  if (hp) Vo += Vhp;
379 
380  return currentGain[currentMixer[Vo]] - (1 << 15);
381 }
382 
383 } // namespace reSIDfp
384 
385 #endif
386 
387 #endif