libresidfp  1.2.3
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 #include <cstdint>
30 
31 namespace reSIDfp
32 {
33 
46 {
47  friend class State;
48 
49 public:
54  enum class State
55  {
56  ATTACK, DECAY_SUSTAIN, RELEASE
57  };
58 
59 private:
61  uint16_t lfsr = 0x7fff;
62 
64  uint16_t rate = 0;
65 
70  unsigned int exponential_counter = 0;
71 
76  unsigned int exponential_counter_period = 1;
77  unsigned int new_exponential_counter_period = 0;
78 
79  unsigned int state_pipeline = 0;
80 
82  unsigned int envelope_pipeline = 0;
83 
84  unsigned int exponential_pipeline = 0;
85 
87  State state = State::RELEASE;
88  State next_state = State::RELEASE;
89 
91  bool counter_enabled = true;
92 
94  bool gate = false;
95 
97  bool resetLfsr = false;
98 
100  uint8_t envelope_counter = 0xaa;
101 
103  uint8_t attack = 0;
104 
106  uint8_t decay = 0;
107 
109  uint8_t sustain = 0;
110 
112  uint8_t release = 0;
113 
115  uint8_t env3 = 0;
116 
117 private:
118  static const uint16_t adsrtable[16];
119 
120 private:
121  void set_exponential_counter();
122 
123  void state_change();
124 
125 public:
129  void clock();
130 
134  uint8_t output() const { return envelope_counter; }
135 
139  void reset();
140 
147  void writeCONTROL_REG(uint8_t control);
148 
155  void writeATTACK_DECAY(uint8_t attack_decay);
156 
163  void writeSUSTAIN_RELEASE(uint8_t sustain_release);
164 
170  uint8_t readENV() const { return env3; }
171 };
172 
173 } // namespace reSIDfp
174 
175 #if RESIDFP_INLINING || defined(ENVELOPEGENERATOR_CPP)
176 
177 namespace reSIDfp
178 {
179 
180 RESIDFP_INLINE
182 {
183  env3 = envelope_counter;
184 
185  if (unlikely(new_exponential_counter_period > 0))
186  {
187  exponential_counter_period = new_exponential_counter_period;
188  new_exponential_counter_period = 0;
189  }
190 
191  if (unlikely(state_pipeline))
192  {
193  state_change();
194  }
195 
196  if (unlikely(envelope_pipeline != 0) && (--envelope_pipeline == 0))
197  {
198  if (likely(counter_enabled))
199  {
200  if (state == State::ATTACK)
201  {
202  if (++envelope_counter==0xff)
203  {
204  next_state = State::DECAY_SUSTAIN;
205  state_pipeline = 3;
206  }
207  }
208  else if ((state == State::DECAY_SUSTAIN) || (state == State::RELEASE))
209  {
210  if (--envelope_counter==0x00)
211  {
212  counter_enabled = false;
213  }
214  }
215 
216  set_exponential_counter();
217  }
218  }
219  else if (unlikely(exponential_pipeline != 0) && (--exponential_pipeline == 0))
220  {
221  exponential_counter = 0;
222 
223  if (((state == State::DECAY_SUSTAIN) && (envelope_counter != sustain))
224  || (state == State::RELEASE))
225  {
226  // The envelope counter can flip from 0x00 to 0xff by changing state to
227  // attack, then to release. The envelope counter will then continue
228  // counting down in the release state.
229  // This has been verified by sampling ENV3.
230 
231  envelope_pipeline = 1;
232  }
233  }
234  else if (unlikely(resetLfsr))
235  {
236  lfsr = 0x7fff;
237  resetLfsr = false;
238 
239  if (state == State::ATTACK)
240  {
241  // The first envelope step in the attack state also resets the exponential
242  // counter. This has been verified by sampling ENV3.
243  exponential_counter = 0; // NOTE this is actually delayed one cycle, not modeled
244 
245  // The envelope counter can flip from 0xff to 0x00 by changing state to
246  // release, then to attack. The envelope counter is then frozen at
247  // zero; to unlock this situation the state must be changed to release,
248  // then to attack. This has been verified by sampling ENV3.
249 
250  envelope_pipeline = 2;
251  }
252  else
253  {
254  if (counter_enabled && (++exponential_counter == exponential_counter_period))
255  exponential_pipeline = exponential_counter_period != 1 ? 2 : 1;
256  }
257  }
258 
259  // ADSR delay bug.
260  // If the rate counter comparison value is set below the current value of the
261  // rate counter, the counter will continue counting up until it wraps around
262  // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the
263  // envelope can constly be stepped.
264  // This has been verified by sampling ENV3.
265 
266  // check to see if LFSR matches table value
267  if (likely(lfsr != rate))
268  {
269  // it wasn't a match, clock the LFSR once
270  // by performing XOR on last 2 bits
271  const unsigned int feedback = ((lfsr << 14) ^ (lfsr << 13)) & 0x4000;
272  lfsr = (lfsr >> 1) | feedback;
273  }
274  else
275  {
276  resetLfsr = true;
277  }
278 }
279 
319 RESIDFP_INLINE
320 void EnvelopeGenerator::state_change()
321 {
322  state_pipeline--;
323 
324  switch (next_state)
325  {
326  case State::ATTACK:
327  if (state_pipeline == 1)
328  {
329  // The decay rate is "accidentally" enabled during first cycle of attack phase
330  rate = adsrtable[decay];
331  }
332  else if (state_pipeline == 0)
333  {
334  state = State::ATTACK;
335  // The attack rate is correctly enabled during second cycle of attack phase
336  rate = adsrtable[attack];
337  counter_enabled = true;
338  }
339  break;
340  case State::DECAY_SUSTAIN:
341  if (state_pipeline == 0)
342  {
343  state = State::DECAY_SUSTAIN;
344  rate = adsrtable[decay];
345  }
346  break;
347  case State::RELEASE:
348  if (((state == State::ATTACK) && (state_pipeline == 0))
349  || ((state == State::DECAY_SUSTAIN) && (state_pipeline == 1)))
350  {
351  state = State::RELEASE;
352  rate = adsrtable[release];
353  }
354  break;
355  }
356 }
357 
358 RESIDFP_INLINE
359 void EnvelopeGenerator::set_exponential_counter()
360 {
361  // Check for change of exponential counter period.
362  //
363  // For a detailed description see:
364  // http://ploguechipsounds.blogspot.it/2010/03/sid-6581r3-adsr-tables-up-close.html
365  switch (envelope_counter)
366  {
367  case 0xff:
368  case 0x00:
369  new_exponential_counter_period = 1;
370  break;
371 
372  case 0x5d:
373  new_exponential_counter_period = 2;
374  break;
375 
376  case 0x36:
377  new_exponential_counter_period = 4;
378  break;
379 
380  case 0x1a:
381  new_exponential_counter_period = 8;
382  break;
383 
384  case 0x0e:
385  new_exponential_counter_period = 16;
386  break;
387 
388  case 0x06:
389  new_exponential_counter_period = 30;
390  break;
391  }
392 }
393 
394 } // namespace reSIDfp
395 
396 #endif
397 
398 #endif
uint8_t readENV() const
Definition: EnvelopeGenerator.h:170
void writeCONTROL_REG(uint8_t control)
Definition: EnvelopeGenerator.cpp:87
void reset()
Definition: EnvelopeGenerator.cpp:62
Definition: Dac.cpp:27
uint8_t output() const
Definition: EnvelopeGenerator.h:134
void writeATTACK_DECAY(uint8_t attack_decay)
Definition: EnvelopeGenerator.cpp:122
State
Definition: EnvelopeGenerator.h:54
void writeSUSTAIN_RELEASE(uint8_t sustain_release)
Definition: EnvelopeGenerator.cpp:137
Definition: EnvelopeGenerator.h:45
void clock()
Definition: EnvelopeGenerator.h:181
Definition: State.h:45