libsidplayfp  2.0.2
EnvelopeGenerator.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 2018 VICE Project
6  * Copyright 2007-2010 Antti Lankila
7  * Copyright 2004,2010 Dag Lem <resid@nimrod.no>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  */
23 
24 #ifndef ENVELOPEGENERATOR_H
25 #define ENVELOPEGENERATOR_H
26 
27 #include "siddefs-fp.h"
28 
29 namespace reSIDfp
30 {
31 
44 {
45 private:
50  enum State
51  {
52  ATTACK, DECAY_SUSTAIN, RELEASE
53  };
54 
55 private:
57  unsigned int lfsr;
58 
60  unsigned int rate;
61 
66  unsigned int exponential_counter;
67 
72  unsigned int exponential_counter_period;
73 
74  unsigned int state_pipeline;
75 
77  unsigned int envelope_pipeline;
78 
79  unsigned int exponential_pipeline;
80 
82  State state;
83  State next_state;
84 
86  bool counter_enabled;
87 
89  bool gate;
90 
92  bool resetLfsr;
93 
95  unsigned char envelope_counter;
96 
98  unsigned char attack;
99 
101  unsigned char decay;
102 
104  unsigned char sustain;
105 
107  unsigned char release;
108 
110  unsigned char env3;
111 
117  float dac[256];
118 
119 private:
120  static const unsigned int adsrtable[16];
121 
122 private:
123  void set_exponential_counter();
124 
125  void state_change();
126 
127 public:
135  void setChipModel(ChipModel chipModel);
136 
140  void clock();
141 
147  float output() const { return dac[envelope_counter]; }
148 
153  lfsr(0x7fff),
154  rate(0),
155  exponential_counter(0),
156  exponential_counter_period(1),
157  state_pipeline(0),
158  envelope_pipeline(0),
159  exponential_pipeline(0),
160  state(RELEASE),
161  next_state(RELEASE),
162  counter_enabled(true),
163  gate(false),
164  resetLfsr(false),
165  envelope_counter(0xaa),
166  attack(0),
167  decay(0),
168  sustain(0),
169  release(0),
170  env3(0)
171  {}
172 
176  void reset();
177 
184  void writeCONTROL_REG(unsigned char control);
185 
192  void writeATTACK_DECAY(unsigned char attack_decay);
193 
200  void writeSUSTAIN_RELEASE(unsigned char sustain_release);
201 
207  unsigned char readENV() const { return env3; }
208 };
209 
210 } // namespace reSIDfp
211 
212 #if RESID_INLINING || defined(ENVELOPEGENERATOR_CPP)
213 
214 namespace reSIDfp
215 {
216 
217 RESID_INLINE
219 {
220  env3 = envelope_counter;
221 
222  if (unlikely(state_pipeline))
223  {
224  state_change();
225  }
226 
227  if (unlikely(envelope_pipeline != 0) && (--envelope_pipeline == 0))
228  {
229  if (likely(counter_enabled))
230  {
231  if (state == ATTACK)
232  {
233  if (++envelope_counter==0xff)
234  {
235  state = DECAY_SUSTAIN;
236  rate = adsrtable[decay];
237  }
238  }
239  else if ((state == DECAY_SUSTAIN) || (state == RELEASE))
240  {
241  if (--envelope_counter==0x00)
242  {
243  counter_enabled = false;
244  }
245  }
246 
247  set_exponential_counter();
248  }
249  }
250  else if (unlikely(exponential_pipeline != 0) && (--exponential_pipeline == 0))
251  {
252  exponential_counter = 0;
253 
254  if (((state == DECAY_SUSTAIN) && (envelope_counter != sustain))
255  || (state == RELEASE))
256  {
257  // The envelope counter can flip from 0x00 to 0xff by changing state to
258  // attack, then to release. The envelope counter will then continue
259  // counting down in the release state.
260  // This has been verified by sampling ENV3.
261 
262  envelope_pipeline = 1;
263  }
264  }
265  else if (unlikely(resetLfsr))
266  {
267  lfsr = 0x7fff;
268  resetLfsr = false;
269 
270  if (state == ATTACK)
271  {
272  // The first envelope step in the attack state also resets the exponential
273  // counter. This has been verified by sampling ENV3.
274  exponential_counter = 0; // NOTE this is actually delayed one cycle, not modeled
275 
276  // The envelope counter can flip from 0xff to 0x00 by changing state to
277  // release, then to attack. The envelope counter is then frozen at
278  // zero; to unlock this situation the state must be changed to release,
279  // then to attack. This has been verified by sampling ENV3.
280 
281  envelope_pipeline = 2;
282  }
283  else
284  {
285  if (counter_enabled && (++exponential_counter == exponential_counter_period))
286  exponential_pipeline = exponential_counter_period != 1 ? 2 : 1;
287  }
288  }
289 
290  // ADSR delay bug.
291  // If the rate counter comparison value is set below the current value of the
292  // rate counter, the counter will continue counting up until it wraps around
293  // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the
294  // envelope can constly be stepped.
295  // This has been verified by sampling ENV3.
296 
297  // check to see if LFSR matches table value
298  if (likely(lfsr != rate))
299  {
300  // it wasn't a match, clock the LFSR once
301  // by performing XOR on last 2 bits
302  const unsigned int feedback = ((lfsr << 14) ^ (lfsr << 13)) & 0x4000;
303  lfsr = (lfsr >> 1) | feedback;
304  }
305  else
306  {
307  resetLfsr = true;
308  }
309 }
310 
350 RESID_INLINE
351 void EnvelopeGenerator::state_change()
352 {
353  state_pipeline--;
354 
355  switch (next_state)
356  {
357  case ATTACK:
358  if (state_pipeline == 0)
359  {
360  state = ATTACK;
361  // The attack rate register is correctly enabled during second cycle of attack phase
362  rate = adsrtable[attack];
363  counter_enabled = true;
364  }
365  break;
366  case DECAY_SUSTAIN:
367  break;
368  case RELEASE:
369  if (((state == ATTACK) && (state_pipeline == 0))
370  || ((state == DECAY_SUSTAIN) && (state_pipeline == 1)))
371  {
372  state = RELEASE;
373  rate = adsrtable[release];
374  }
375  break;
376  }
377 }
378 
379 RESID_INLINE
380 void EnvelopeGenerator::set_exponential_counter()
381 {
382  // Check for change of exponential counter period.
383  //
384  // For a detailed description see:
385  // http://ploguechipsounds.blogspot.it/2010/03/sid-6581r3-adsr-tables-up-close.html
386  switch (envelope_counter)
387  {
388  case 0xff:
389  exponential_counter_period = 1;
390  break;
391 
392  case 0x5d:
393  exponential_counter_period = 2;
394  break;
395 
396  case 0x36:
397  exponential_counter_period = 4;
398  break;
399 
400  case 0x1a:
401  exponential_counter_period = 8;
402  break;
403 
404  case 0x0e:
405  exponential_counter_period = 16;
406  break;
407 
408  case 0x06:
409  exponential_counter_period = 30;
410  break;
411 
412  case 0x00:
413  exponential_counter_period = 1;
414  break;
415  }
416 }
417 
418 } // namespace reSIDfp
419 
420 #endif
421 
422 #endif
reSIDfp::EnvelopeGenerator::output
float output() const
Definition: EnvelopeGenerator.h:147
reSIDfp::EnvelopeGenerator::EnvelopeGenerator
EnvelopeGenerator()
Definition: EnvelopeGenerator.h:152
reSIDfp::EnvelopeGenerator::readENV
unsigned char readENV() const
Definition: EnvelopeGenerator.h:207
reSIDfp::EnvelopeGenerator::writeSUSTAIN_RELEASE
void writeSUSTAIN_RELEASE(unsigned char sustain_release)
Definition: EnvelopeGenerator.cpp:156
reSIDfp::EnvelopeGenerator::writeATTACK_DECAY
void writeATTACK_DECAY(unsigned char attack_decay)
Definition: EnvelopeGenerator.cpp:141
reSIDfp::EnvelopeGenerator::clock
void clock()
Definition: EnvelopeGenerator.h:218
reSIDfp::EnvelopeGenerator::reset
void reset()
Definition: EnvelopeGenerator.cpp:77
reSIDfp::EnvelopeGenerator::setChipModel
void setChipModel(ChipModel chipModel)
Definition: EnvelopeGenerator.cpp:66
reSIDfp::EnvelopeGenerator
Definition: EnvelopeGenerator.h:44
reSIDfp::EnvelopeGenerator::writeCONTROL_REG
void writeCONTROL_REG(unsigned char control)
Definition: EnvelopeGenerator.cpp:101