libsidplayfp  1.0.1
SID.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 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 "residfp-config.h"
27 
28 namespace reSIDfp
29 {
30 
31 class Filter;
32 class Filter6581;
33 class Filter8580;
34 class ExternalFilter;
35 class Potentiometer;
36 class Voice;
37 class Resampler;
38 
42 class SIDError
43 {
44 private:
45  const char* message;
46 
47 public:
48  SIDError(const char* msg) :
49  message(msg) {}
50  const char* getMessage() { return message; }
51 };
52 
64 class SID
65 {
66 private:
70  static const int BUS_TTL;
71 
73  Filter* filter;
74 
76  Filter6581* filter6581;
77 
79  Filter8580* filter8580;
80 
85  ExternalFilter* externalFilter;
86 
90  Resampler* resampler;
91 
93  Potentiometer* potX;
94 
96  Potentiometer* potY;
97 
99  Voice* voice[3];
100 
102  int busValueTtl;
103 
107  int nextVoiceSync;
108 
110  int delayedOffset;
111 
115  ChipModel model;
116 
118  unsigned char delayedValue;
119 
121  unsigned char busValue;
122 
123  bool muted[3];
124 
125 private:
132  void writeImmediate(int offset, unsigned char value);
133 
139  void ageBusValue(int n);
140 
146  int output() const;
147 
154  void voiceSync(bool sync);
155 
156 public:
157  SID();
158  ~SID();
159 
165  void setChipModel(ChipModel model);
166 
167  ChipModel getChipModel() const { return model; }
168 
172  void reset();
173 
182  void input(int value);
183 
204  unsigned char read(int offset);
205 
212  void write(int offset, unsigned char value);
213 
220  void mute(int channel, bool enable) { muted[channel] = enable; }
221 
246  void setSamplingParameters(double clockFrequency, SamplingMethod method, double samplingFrequency, double highestAccurateFrequency);
247 
255  int clock(int cycles, short* buf);
256 
267  void clockSilent(int cycles);
268 
274  Filter6581* getFilter6581() const { return filter6581; }
275 
281  Filter8580* getFilter8580() const { return filter8580; }
282 };
283 
284 } // namespace reSIDfp
285 
286 #if RESID_INLINING || defined(SID_CPP)
287 
288 #include <algorithm>
289 
290 #include "Filter.h"
291 #include "ExternalFilter.h"
292 #include "Voice.h"
293 #include "resample/Resampler.h"
294 
295 namespace reSIDfp
296 {
297 RESID_INLINE
298 int SID::output() const
299 {
300  return externalFilter->clock(
301  filter->clock(
302  voice[0]->output(voice[2]->wave()),
303  voice[1]->output(voice[0]->wave()),
304  voice[2]->output(voice[1]->wave())
305  )
306  );
307 }
308 
309 
310 RESID_INLINE
311 int SID::clock(int cycles, short* buf)
312 {
313  ageBusValue(cycles);
314  int s = 0;
315 
316  while (cycles != 0)
317  {
318  int delta_t = std::min(nextVoiceSync, cycles);
319 
320  if (delta_t > 0)
321  {
322  if (delayedOffset != -1)
323  {
324  delta_t = 1;
325  }
326 
327  for (int i = 0; i < delta_t; i ++)
328  {
329  if (resampler->input(output()))
330  {
331  buf[s++] = resampler->getOutput();
332  }
333 
334  /* clock waveform generators */
335  voice[0]->wave()->clock();
336  voice[1]->wave()->clock();
337  voice[2]->wave()->clock();
338 
339  /* clock envelope generators */
340  voice[0]->envelope()->clock();
341  voice[1]->envelope()->clock();
342  voice[2]->envelope()->clock();
343  }
344 
345  if (delayedOffset != -1)
346  {
347  writeImmediate(delayedOffset, delayedValue);
348  delayedOffset = -1;
349  }
350 
351  cycles -= delta_t;
352  nextVoiceSync -= delta_t;
353  }
354 
355  if (nextVoiceSync == 0)
356  {
357  voiceSync(true);
358  }
359  }
360 
361  return s;
362 }
363 
364 } // namespace reSIDfp
365 
366 #endif
367 
368 #endif