libsidplayfp  1.2.2
EnvelopeGenerator.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 ENVELOPEGENERATOR_H
24 #define ENVELOPEGENERATOR_H
25 
26 #include "siddefs-fp.h"
27 
28 namespace reSIDfp
29 {
30 
45 {
46 private:
51  enum State
52  {
53  ATTACK, DECAY_SUSTAIN, RELEASE
54  };
55 
59  int lfsr;
60 
64  int rate;
65 
70  int exponential_counter;
71 
76  int exponential_counter_period;
77 
79  int attack;
80 
82  int decay;
83 
85  int sustain;
86 
88  int release;
89 
91  State state;
92 
96  bool hold_zero;
97 
98  bool envelope_pipeline;
99 
101  bool gate;
102 
104  unsigned char envelope_counter;
105 
111  short dac[256];
112 
113  void set_exponential_counter();
114 
126  static const int adsrtable[16];
127 
128 public:
136  void setChipModel(ChipModel chipModel);
137 
141  void clock();
142 
148  short output() const { return dac[envelope_counter]; }
149 
154  lfsr(0),
155  rate(0),
156  exponential_counter(0),
157  exponential_counter_period(1),
158  attack(0),
159  decay(0),
160  sustain(0),
161  release(0),
162  state(RELEASE),
163  hold_zero(true),
164  envelope_pipeline(false),
165  gate(false),
166  envelope_counter(0) {}
167 
171  void reset();
172 
173  // ----------------------------------------------------------------------------
174  // Register functions.
175  // ----------------------------------------------------------------------------
176 
181  void writeCONTROL_REG(unsigned char control);
182 
187  void writeATTACK_DECAY(unsigned char attack_decay);
188 
193  void writeSUSTAIN_RELEASE(unsigned char sustain_release);
194 
200  unsigned char readENV() const { return envelope_counter; }
201 };
202 
203 } // namespace reSIDfp
204 
205 #if RESID_INLINING || defined(ENVELOPEGENERATOR_CPP)
206 
207 namespace reSIDfp
208 {
209 
210 RESID_INLINE
212 {
213  if (envelope_pipeline)
214  {
215  --envelope_counter;
216  envelope_pipeline = false;
217  // Check for change of exponential counter period.
218  set_exponential_counter();
219  }
220 
221  // Check for ADSR delay bug.
222  // If the rate counter comparison value is set below the current value of the
223  // rate counter, the counter will continue counting up until it wraps around
224  // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the
225  // envelope can constly be stepped.
226  // This has been verified by sampling ENV3.
227  //
228  // Envelope is now implemented like in the real machine with a shift register
229  // so the ADSR delay bug should be correcly modeled
230 
231  // check to see if LFSR matches table value
232  if (lfsr != rate)
233  {
234  // it wasn't a match, clock the LFSR once
235  // by performing XOR on last 2 bits
236  const int feedback = ((lfsr << 14) ^ (lfsr << 13)) & 0x4000;
237  lfsr = (lfsr >> 1) | feedback;
238  return;
239  }
240 
241  // reset LFSR
242  lfsr = 0x7fff;
243 
244  // The first envelope step in the attack state also resets the exponential
245  // counter. This has been verified by sampling ENV3.
246  //
247  if (state == ATTACK || ++exponential_counter == exponential_counter_period)
248  {
249  // likely (~50%)
250  exponential_counter = 0;
251 
252  // Check whether the envelope counter is frozen at zero.
253  if (hold_zero)
254  {
255  return;
256  }
257 
258  switch (state)
259  {
260  case ATTACK:
261  // The envelope counter can flip from 0xff to 0x00 by changing state to
262  // release, then to attack. The envelope counter is then frozen at
263  // zero; to unlock this situation the state must be changed to release,
264  // then to attack. This has been verified by sampling ENV3.
265  //
266  ++envelope_counter;
267 
268  if (envelope_counter == (unsigned char) 0xff)
269  {
270  state = DECAY_SUSTAIN;
271  rate = adsrtable[decay];
272  }
273 
274  break;
275 
276  case DECAY_SUSTAIN:
277 
278  // From the sustain levels it follows that both the low and high 4 bits
279  // of the envelope counter are compared to the 4-bit sustain value.
280  // This has been verified by sampling ENV3.
281  //
282  // For a detailed description see:
283  // http://ploguechipsounds.blogspot.it/2010/11/new-research-on-sid-adsr.html
284  if (envelope_counter == (unsigned char)(sustain << 4 | sustain))
285  {
286  return;
287  }
288 
289  // fall-through
290 
291  case RELEASE:
292 
293  // The envelope counter can flip from 0x00 to 0xff by changing state to
294  // attack, then to release. The envelope counter will then continue
295  // counting down in the release state.
296  // This has been verified by sampling ENV3.
297  // NB! The operation below requires two's complement integer.
298  //
299  if (exponential_counter_period != 1)
300  {
301  // The decrement is delayed one cycle.
302  envelope_pipeline = true;
303  return;
304  }
305 
306  --envelope_counter;
307  break;
308  }
309 
310  // Check for change of exponential counter period.
311  set_exponential_counter();
312  }
313 }
314 
315 } // namespace reSIDfp
316 
317 #endif
318 
319 #endif
void clock()
Definition: EnvelopeGenerator.h:211
void reset()
Definition: EnvelopeGenerator.cpp:120
void setChipModel(ChipModel chipModel)
Definition: EnvelopeGenerator.cpp:99
void writeCONTROL_REG(unsigned char control)
Definition: EnvelopeGenerator.cpp:141
short output() const
Definition: EnvelopeGenerator.h:148
unsigned char readENV() const
Definition: EnvelopeGenerator.h:200
EnvelopeGenerator()
Definition: EnvelopeGenerator.h:153
Definition: EnvelopeGenerator.h:44
void writeSUSTAIN_RELEASE(unsigned char sustain_release)
Definition: EnvelopeGenerator.cpp:186
void writeATTACK_DECAY(unsigned char attack_decay)
Definition: EnvelopeGenerator.cpp:171