libsidplayfp  2.12.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 class State
51  {
52  ATTACK, DECAY_SUSTAIN, RELEASE
53  };
54 
55 private:
57  unsigned int lfsr = 0x7fff;
58 
60  unsigned int rate = 0;
61 
66  unsigned int exponential_counter = 0;
67 
72  unsigned int exponential_counter_period = 1;
73  unsigned int new_exponential_counter_period = 0;
74 
75  unsigned int state_pipeline = 0;
76 
78  unsigned int envelope_pipeline = 0;
79 
80  unsigned int exponential_pipeline = 0;
81 
83  State state = State::RELEASE;
84  State next_state = State::RELEASE;
85 
87  bool counter_enabled = true;
88 
90  bool gate = false;
91 
93  bool resetLfsr = false;
94 
96  unsigned char envelope_counter = 0xaa;
97 
99  unsigned char attack = 0;
100 
102  unsigned char decay = 0;
103 
105  unsigned char sustain = 0;
106 
108  unsigned char release = 0;
109 
111  unsigned char env3 = 0;
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 
135  void reset();
136 
143  void writeCONTROL_REG(unsigned char control);
144 
151  void writeATTACK_DECAY(unsigned char attack_decay);
152 
159  void writeSUSTAIN_RELEASE(unsigned char sustain_release);
160 
166  unsigned char readENV() const { return env3; }
167 };
168 
169 } // namespace reSIDfp
170 
171 #if RESID_INLINING || defined(ENVELOPEGENERATOR_CPP)
172 
173 namespace reSIDfp
174 {
175 
176 RESID_INLINE
178 {
179  env3 = envelope_counter;
180 
181  if (unlikely(new_exponential_counter_period > 0))
182  {
183  exponential_counter_period = new_exponential_counter_period;
184  new_exponential_counter_period = 0;
185  }
186 
187  if (unlikely(state_pipeline))
188  {
189  state_change();
190  }
191 
192  if (unlikely(envelope_pipeline != 0) && (--envelope_pipeline == 0))
193  {
194  if (likely(counter_enabled))
195  {
196  if (state == State::ATTACK)
197  {
198  if (++envelope_counter==0xff)
199  {
200  next_state = State::DECAY_SUSTAIN;
201  state_pipeline = 3;
202  }
203  }
204  else if ((state == State::DECAY_SUSTAIN) || (state == State::RELEASE))
205  {
206  if (--envelope_counter==0x00)
207  {
208  counter_enabled = false;
209  }
210  }
211 
212  set_exponential_counter();
213  }
214  }
215  else if (unlikely(exponential_pipeline != 0) && (--exponential_pipeline == 0))
216  {
217  exponential_counter = 0;
218 
219  if (((state == State::DECAY_SUSTAIN) && (envelope_counter != sustain))
220  || (state == State::RELEASE))
221  {
222  // The envelope counter can flip from 0x00 to 0xff by changing state to
223  // attack, then to release. The envelope counter will then continue
224  // counting down in the release state.
225  // This has been verified by sampling ENV3.
226 
227  envelope_pipeline = 1;
228  }
229  }
230  else if (unlikely(resetLfsr))
231  {
232  lfsr = 0x7fff;
233  resetLfsr = false;
234 
235  if (state == State::ATTACK)
236  {
237  // The first envelope step in the attack state also resets the exponential
238  // counter. This has been verified by sampling ENV3.
239  exponential_counter = 0; // NOTE this is actually delayed one cycle, not modeled
240 
241  // The envelope counter can flip from 0xff to 0x00 by changing state to
242  // release, then to attack. The envelope counter is then frozen at
243  // zero; to unlock this situation the state must be changed to release,
244  // then to attack. This has been verified by sampling ENV3.
245 
246  envelope_pipeline = 2;
247  }
248  else
249  {
250  if (counter_enabled && (++exponential_counter == exponential_counter_period))
251  exponential_pipeline = exponential_counter_period != 1 ? 2 : 1;
252  }
253  }
254 
255  // ADSR delay bug.
256  // If the rate counter comparison value is set below the current value of the
257  // rate counter, the counter will continue counting up until it wraps around
258  // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the
259  // envelope can constly be stepped.
260  // This has been verified by sampling ENV3.
261 
262  // check to see if LFSR matches table value
263  if (likely(lfsr != rate))
264  {
265  // it wasn't a match, clock the LFSR once
266  // by performing XOR on last 2 bits
267  const unsigned int feedback = ((lfsr << 14) ^ (lfsr << 13)) & 0x4000;
268  lfsr = (lfsr >> 1) | feedback;
269  }
270  else
271  {
272  resetLfsr = true;
273  }
274 }
275 
315 RESID_INLINE
316 void EnvelopeGenerator::state_change()
317 {
318  state_pipeline--;
319 
320  switch (next_state)
321  {
322  case State::ATTACK:
323  if (state_pipeline == 1)
324  {
325  // The decay rate is "accidentally" enabled during first cycle of attack phase
326  rate = adsrtable[decay];
327  }
328  else if (state_pipeline == 0)
329  {
330  state = State::ATTACK;
331  // The attack rate is correctly enabled during second cycle of attack phase
332  rate = adsrtable[attack];
333  counter_enabled = true;
334  }
335  break;
336  case State::DECAY_SUSTAIN:
337  if (state_pipeline == 0)
338  {
339  state = State::DECAY_SUSTAIN;
340  rate = adsrtable[decay];
341  }
342  break;
343  case State::RELEASE:
344  if (((state == State::ATTACK) && (state_pipeline == 0))
345  || ((state == State::DECAY_SUSTAIN) && (state_pipeline == 1)))
346  {
347  state = State::RELEASE;
348  rate = adsrtable[release];
349  }
350  break;
351  }
352 }
353 
354 RESID_INLINE
355 void EnvelopeGenerator::set_exponential_counter()
356 {
357  // Check for change of exponential counter period.
358  //
359  // For a detailed description see:
360  // http://ploguechipsounds.blogspot.it/2010/03/sid-6581r3-adsr-tables-up-close.html
361  switch (envelope_counter)
362  {
363  case 0xff:
364  case 0x00:
365  new_exponential_counter_period = 1;
366  break;
367 
368  case 0x5d:
369  new_exponential_counter_period = 2;
370  break;
371 
372  case 0x36:
373  new_exponential_counter_period = 4;
374  break;
375 
376  case 0x1a:
377  new_exponential_counter_period = 8;
378  break;
379 
380  case 0x0e:
381  new_exponential_counter_period = 16;
382  break;
383 
384  case 0x06:
385  new_exponential_counter_period = 30;
386  break;
387  }
388 }
389 
390 } // namespace reSIDfp
391 
392 #endif
393 
394 #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:166
void clock()
Definition: EnvelopeGenerator.h:177