libsidplayfp  2.4.0
EnvelopeGenerator.h
1 /*
2  * This file is part of libsidplayfp, a SID player engine.
3  *
4  * Copyright 2011-2022 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  unsigned int new_exponential_counter_period;
74 
75  unsigned int state_pipeline;
76 
78  unsigned int envelope_pipeline;
79 
80  unsigned int exponential_pipeline;
81 
83  State state;
84  State next_state;
85 
87  bool counter_enabled;
88 
90  bool gate;
91 
93  bool resetLfsr;
94 
96  unsigned char envelope_counter;
97 
99  unsigned char attack;
100 
102  unsigned char decay;
103 
105  unsigned char sustain;
106 
108  unsigned char release;
109 
111  unsigned char env3;
112 
113 private:
114  static const unsigned int adsrtable[16];
115 
116 private:
117  void set_exponential_counter();
118 
119  void state_change();
120 
121 public:
125  void clock();
126 
130  unsigned int output() const { return envelope_counter; }
131 
136  lfsr(0x7fff),
137  rate(0),
138  exponential_counter(0),
139  exponential_counter_period(1),
140  new_exponential_counter_period(0),
141  state_pipeline(0),
142  envelope_pipeline(0),
143  exponential_pipeline(0),
144  state(RELEASE),
145  next_state(RELEASE),
146  counter_enabled(true),
147  gate(false),
148  resetLfsr(false),
149  envelope_counter(0xaa),
150  attack(0),
151  decay(0),
152  sustain(0),
153  release(0),
154  env3(0)
155  {}
156 
160  void reset();
161 
168  void writeCONTROL_REG(unsigned char control);
169 
176  void writeATTACK_DECAY(unsigned char attack_decay);
177 
184  void writeSUSTAIN_RELEASE(unsigned char sustain_release);
185 
191  unsigned char readENV() const { return env3; }
192 };
193 
194 } // namespace reSIDfp
195 
196 #if RESID_INLINING || defined(ENVELOPEGENERATOR_CPP)
197 
198 namespace reSIDfp
199 {
200 
201 RESID_INLINE
203 {
204  env3 = envelope_counter;
205 
206  if (unlikely(new_exponential_counter_period > 0))
207  {
208  exponential_counter_period = new_exponential_counter_period;
209  new_exponential_counter_period = 0;
210  }
211 
212  if (unlikely(state_pipeline))
213  {
214  state_change();
215  }
216 
217  if (unlikely(envelope_pipeline != 0) && (--envelope_pipeline == 0))
218  {
219  if (likely(counter_enabled))
220  {
221  if (state == ATTACK)
222  {
223  if (++envelope_counter==0xff)
224  {
225  next_state = DECAY_SUSTAIN;
226  state_pipeline = 3;
227  }
228  }
229  else if ((state == DECAY_SUSTAIN) || (state == RELEASE))
230  {
231  if (--envelope_counter==0x00)
232  {
233  counter_enabled = false;
234  }
235  }
236 
237  set_exponential_counter();
238  }
239  }
240  else if (unlikely(exponential_pipeline != 0) && (--exponential_pipeline == 0))
241  {
242  exponential_counter = 0;
243 
244  if (((state == DECAY_SUSTAIN) && (envelope_counter != sustain))
245  || (state == RELEASE))
246  {
247  // The envelope counter can flip from 0x00 to 0xff by changing state to
248  // attack, then to release. The envelope counter will then continue
249  // counting down in the release state.
250  // This has been verified by sampling ENV3.
251 
252  envelope_pipeline = 1;
253  }
254  }
255  else if (unlikely(resetLfsr))
256  {
257  lfsr = 0x7fff;
258  resetLfsr = false;
259 
260  if (state == ATTACK)
261  {
262  // The first envelope step in the attack state also resets the exponential
263  // counter. This has been verified by sampling ENV3.
264  exponential_counter = 0; // NOTE this is actually delayed one cycle, not modeled
265 
266  // The envelope counter can flip from 0xff to 0x00 by changing state to
267  // release, then to attack. The envelope counter is then frozen at
268  // zero; to unlock this situation the state must be changed to release,
269  // then to attack. This has been verified by sampling ENV3.
270 
271  envelope_pipeline = 2;
272  }
273  else
274  {
275  if (counter_enabled && (++exponential_counter == exponential_counter_period))
276  exponential_pipeline = exponential_counter_period != 1 ? 2 : 1;
277  }
278  }
279 
280  // ADSR delay bug.
281  // If the rate counter comparison value is set below the current value of the
282  // rate counter, the counter will continue counting up until it wraps around
283  // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the
284  // envelope can constly be stepped.
285  // This has been verified by sampling ENV3.
286 
287  // check to see if LFSR matches table value
288  if (likely(lfsr != rate))
289  {
290  // it wasn't a match, clock the LFSR once
291  // by performing XOR on last 2 bits
292  const unsigned int feedback = ((lfsr << 14) ^ (lfsr << 13)) & 0x4000;
293  lfsr = (lfsr >> 1) | feedback;
294  }
295  else
296  {
297  resetLfsr = true;
298  }
299 }
300 
340 RESID_INLINE
341 void EnvelopeGenerator::state_change()
342 {
343  state_pipeline--;
344 
345  switch (next_state)
346  {
347  case ATTACK:
348  if (state_pipeline == 1)
349  {
350  // The decay rate is "accidentally" enabled during first cycle of attack phase
351  rate = adsrtable[decay];
352  }
353  else if (state_pipeline == 0)
354  {
355  state = ATTACK;
356  // The attack rate is correctly enabled during second cycle of attack phase
357  rate = adsrtable[attack];
358  counter_enabled = true;
359  }
360  break;
361  case DECAY_SUSTAIN:
362  if (state_pipeline == 0)
363  {
364  state = DECAY_SUSTAIN;
365  rate = adsrtable[decay];
366  }
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  case 0x00:
390  new_exponential_counter_period = 1;
391  break;
392 
393  case 0x5d:
394  new_exponential_counter_period = 2;
395  break;
396 
397  case 0x36:
398  new_exponential_counter_period = 4;
399  break;
400 
401  case 0x1a:
402  new_exponential_counter_period = 8;
403  break;
404 
405  case 0x0e:
406  new_exponential_counter_period = 16;
407  break;
408 
409  case 0x06:
410  new_exponential_counter_period = 30;
411  break;
412  }
413 }
414 
415 } // namespace reSIDfp
416 
417 #endif
418 
419 #endif
Definition: EnvelopeGenerator.h:44
unsigned int output() const
Definition: EnvelopeGenerator.h:130
void writeATTACK_DECAY(unsigned char attack_decay)
Definition: EnvelopeGenerator.cpp:122
void reset()
Definition: EnvelopeGenerator.cpp:62
void writeSUSTAIN_RELEASE(unsigned char sustain_release)
Definition: EnvelopeGenerator.cpp:137
void writeCONTROL_REG(unsigned char control)
Definition: EnvelopeGenerator.cpp:87
unsigned char readENV() const
Definition: EnvelopeGenerator.h:191
void clock()
Definition: EnvelopeGenerator.h:202
EnvelopeGenerator()
Definition: EnvelopeGenerator.h:135