libresidfp  1.2.3
SID.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 SIDFP_H
24 #define SIDFP_H
25 
26 #include <memory>
27 
28 #include <cassert>
29 #include <cstdint>
30 
31 #include "residfp/residfp_defs.h"
32 #include "siddefs-fp.h"
33 #include "ExternalFilter.h"
34 #include "Filter.h"
35 #include "Voice.h"
36 #include "State.h"
37 
38 namespace reSIDfp
39 {
40 
41 class Filter;
42 class Filter6581;
43 class Filter8580;
44 class Resampler;
45 
49 class SIDError
50 {
51 private:
52  const char* message;
53 
54 public:
55  explicit SIDError(const char* msg) :
56  message(msg) {}
57  const char* getMessage() const { return message; }
58 };
59 
63 class SID
64 {
65  friend class State;
66 
67 private:
69  Filter* filter;
70 
72  Filter6581* const filter6581;
73 
75  Filter8580* const filter8580;
76 
78  std::unique_ptr<Resampler> resampler;
79 
84  ExternalFilter externalFilter;
85 
87  Voice voice[3];
88 
90  int scaleFactor;
91 
93  int busValueTtl;
94 
96  int modelTTL;
97 
99  unsigned int nextVoiceSync;
100 
101  unsigned int offset_6581;
102 
104  ChipModel model;
105 
107  CombinedWaveforms cws;
108 
109  // Dac leakage
110  double dacLeakage;
111 
113  uint8_t busValue;
114 
116 
117  uint8_t paddleX = 0xff;
118  uint8_t paddleY = 0xff;
120 
126  float envDAC[256];
127 
133  float oscDAC[4096];
134 
136  Params* p;
137 
138 private:
144  void ageBusValue(int n);
145 
152  void voiceSync(bool sync);
153 
155  inline void clockWaveGen()
156  {
157  voice[0].wave()->clock();
158  voice[1].wave()->clock();
159  voice[2].wave()->clock();
160  }
161 
163  inline void clockEnvGen()
164  {
165  voice[0].envelope()->clock();
166  voice[1].envelope()->clock();
167  voice[2].envelope()->clock();
168  }
169 
171  inline int32_t clockFilt()
172  {
173  uint16_t filtOutput = filter->clock(voice[0], voice[1], voice[2]);
174  int32_t exFiltInput = static_cast<int32_t>(filtOutput) + INT16_MIN;
175  return externalFilter.clock(exFiltInput);
176  }
177 
178 private:
179  SID(const SID&) = delete;
180  SID& operator=(const SID&) = delete;
181 
182 public:
183  SID();
184  ~SID();
185 
192  void setChipModel(ChipModel model);
193 
197  ChipModel getChipModel() const { return model; }
198 
205  void setCombinedWaveforms(CombinedWaveforms cws);
206 
210  void reset();
211 
220  void input(int value);
221 
228  uint8_t peek(int offset) const;
229 
250  uint8_t read(int offset);
251 
258  void write(int offset, uint8_t value);
259 
285  double clockFrequency,
286  SamplingMethod method,
287  double samplingFrequency
288  );
289 
297  int clock(unsigned int cycles, int16_t* buf);
298 
306  int clock(int16_t* buf, int bufSize);
307 
315  void clockDigital(unsigned int cycles);
316 
327  void clockSilent(unsigned int cycles);
328 
334  void setFilter6581Curve(double filterCurve);
335 
341  void setFilter6581Range(double adjustment);
342 
348  void setFilter8580Curve(double filterCurve);
349 
355  void enableFilter(bool enable);
356 
360  void enableOld6581caps(bool enable);
361 
365  void setPaddle(uint8_t x, uint8_t y);
366 
367  /*
368  * Set the DAC leakage level.
369  */
370  void setDacLeakage(double level);
371 
372  /*
373  * Set the 6581 wave offset.
374  */
375  void setOffset6581(double offset);
376 
377  /*
378  * Set the DC-Blocker resistance.
379  */
380  void setDCBRes(double res);
381 };
382 
383 } // namespace reSIDfp
384 
385 #if RESIDFP_INLINING || defined(SID_CPP)
386 
387 #include <algorithm>
388 
389 #include "resample/Resampler.h"
390 
391 namespace reSIDfp
392 {
393 
394 RESIDFP_INLINE
395 void SID::ageBusValue(int n)
396 {
397  if (likely(busValueTtl != 0))
398  {
399  busValueTtl -= n;
400 
401  if (unlikely(busValueTtl <= 0))
402  {
403  busValue = 0;
404  busValueTtl = 0;
405  }
406  }
407 }
408 
409 RESIDFP_INLINE
410 int SID::clock(unsigned int cycles, int16_t* buf)
411 {
412  assert(buf);
413 
414  ageBusValue(cycles);
415  int s = 0;
416 
417  while (cycles != 0)
418  {
419  unsigned int delta_t = std::min(nextVoiceSync, cycles);
420 
421  if (likely(delta_t > 0))
422  {
423  for (unsigned int i = 0; i < delta_t; i++)
424  {
425  clockWaveGen();
426  clockEnvGen();
427 
428  int32_t output = clockFilt();
429  if (unlikely(resampler->input(output)))
430  {
431  buf[s++] = resampler->getOutput(scaleFactor);
432  }
433  }
434 
435  cycles -= delta_t;
436  nextVoiceSync -= delta_t;
437  }
438 
439  if (unlikely(nextVoiceSync == 0))
440  {
441  voiceSync(true);
442  }
443  }
444 
445  return s;
446 }
447 
448 RESIDFP_INLINE
449 int SID::clock(int16_t* buf, int bufSize)
450 {
451  assert(buf);
452  assert(bufSize > 0);
453 
454  int cycles = 0;
455 
456  for (int s = 0; s < bufSize;)
457  {
458  unsigned int delta_t = nextVoiceSync;
459 
460  if (likely(delta_t > 0))
461  {
462  unsigned int i = 0;
463  do
464  {
465  i++;
466  clockWaveGen();
467  clockEnvGen();
468 
469  int32_t output = clockFilt();
470  if (unlikely(resampler->input(output)))
471  {
472  buf[s++] = resampler->getOutput(scaleFactor);
473  if (unlikely(s == bufSize))
474  {
475  break;
476  }
477  }
478  }
479  while (i < delta_t);
480 
481  cycles += i;
482  nextVoiceSync -= i;
483  }
484 
485  if (likely(nextVoiceSync == 0))
486  {
487  voiceSync(true);
488  }
489  }
490 
491  ageBusValue(cycles);
492 
493  return cycles;
494 }
495 
496 } // namespace reSIDfp
497 
498 #endif
499 
500 #endif
Definition: SID.h:49
uint16_t clock(Voice &voice1, Voice &voice2, Voice &voice3)
Definition: Filter.h:216
void enableOld6581caps(bool enable)
Definition: SID.cpp:199
Definition: State.h:35
Definition: Voice.h:38
int clock(unsigned int cycles, int16_t *buf)
Definition: SID.h:410
void clockDigital(unsigned int cycles)
Definition: SID.cpp:557
void setFilter6581Curve(double filterCurve)
Definition: SID.cpp:175
Definition: SID.h:63
void setFilter6581Range(double adjustment)
Definition: SID.cpp:181
uint8_t read(int offset)
Definition: SID.cpp:377
void input(int value)
Definition: SID.cpp:350
void clock()
Definition: WaveformGenerator.h:315
Definition: Dac.cpp:27
void enableFilter(bool enable)
Definition: SID.cpp:193
uint8_t peek(int offset) const
Definition: SID.cpp:356
void setPaddle(uint8_t x, uint8_t y)
Definition: SID.cpp:622
Definition: ExternalFilter.h:86
void setSamplingParameters(double clockFrequency, SamplingMethod method, double samplingFrequency)
Definition: SID.cpp:531
void clockSilent(unsigned int cycles)
Definition: SID.cpp:588
Definition: Filter6581.h:320
void setCombinedWaveforms(CombinedWaveforms cws)
Definition: SID.cpp:305
void clock()
Definition: EnvelopeGenerator.h:181
void write(int offset, uint8_t value)
Definition: SID.cpp:412
Definition: Filter.h:38
void setChipModel(ChipModel model)
Definition: SID.cpp:239
Definition: State.h:45
ChipModel getChipModel() const
Definition: SID.h:197
void setFilter8580Curve(double filterCurve)
Definition: SID.cpp:187
void reset()
Definition: SID.cpp:329
int32_t clock(int32_t input)
Definition: ExternalFilter.h:150