libsidplayfp 2.3.0
EnvelopeGenerator.h
1/*
2 * This file is part of libsidplayfp, a SID player engine.
3 *
4 * Copyright 2011-2020 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
29namespace reSIDfp
30{
31
44{
45private:
50 enum State
51 {
52 ATTACK, DECAY_SUSTAIN, RELEASE
53 };
54
55private:
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
114 float* dac; //-V730_NOINIT this is initialized in the SID constructor
115
116private:
117 static const unsigned int adsrtable[16];
118
119private:
120 void set_exponential_counter();
121
122 void state_change();
123
124public:
132 void setDAC(float* dac) { this->dac = dac; }
133
137 void clock();
138
144 float output() const { return dac[envelope_counter]; }
145
150 lfsr(0x7fff),
151 rate(0),
152 exponential_counter(0),
153 exponential_counter_period(1),
154 new_exponential_counter_period(0),
155 state_pipeline(0),
156 envelope_pipeline(0),
157 exponential_pipeline(0),
158 state(RELEASE),
159 next_state(RELEASE),
160 counter_enabled(true),
161 gate(false),
162 resetLfsr(false),
163 envelope_counter(0xaa),
164 attack(0),
165 decay(0),
166 sustain(0),
167 release(0),
168 env3(0)
169 {}
170
174 void reset();
175
182 void writeCONTROL_REG(unsigned char control);
183
190 void writeATTACK_DECAY(unsigned char attack_decay);
191
198 void writeSUSTAIN_RELEASE(unsigned char sustain_release);
199
205 unsigned char readENV() const { return env3; }
206};
207
208} // namespace reSIDfp
209
210#if RESID_INLINING || defined(ENVELOPEGENERATOR_CPP)
211
212namespace reSIDfp
213{
214
215RESID_INLINE
217{
218 env3 = envelope_counter;
219
220 if (unlikely(new_exponential_counter_period > 0))
221 {
222 exponential_counter_period = new_exponential_counter_period;
223 new_exponential_counter_period = 0;
224 }
225
226 if (unlikely(state_pipeline))
227 {
228 state_change();
229 }
230
231 if (unlikely(envelope_pipeline != 0) && (--envelope_pipeline == 0))
232 {
233 if (likely(counter_enabled))
234 {
235 if (state == ATTACK)
236 {
237 if (++envelope_counter==0xff)
238 {
239 next_state = DECAY_SUSTAIN;
240 state_pipeline = 3;
241 }
242 }
243 else if ((state == DECAY_SUSTAIN) || (state == RELEASE))
244 {
245 if (--envelope_counter==0x00)
246 {
247 counter_enabled = false;
248 }
249 }
250
251 set_exponential_counter();
252 }
253 }
254 else if (unlikely(exponential_pipeline != 0) && (--exponential_pipeline == 0))
255 {
256 exponential_counter = 0;
257
258 if (((state == DECAY_SUSTAIN) && (envelope_counter != sustain))
259 || (state == RELEASE))
260 {
261 // The envelope counter can flip from 0x00 to 0xff by changing state to
262 // attack, then to release. The envelope counter will then continue
263 // counting down in the release state.
264 // This has been verified by sampling ENV3.
265
266 envelope_pipeline = 1;
267 }
268 }
269 else if (unlikely(resetLfsr))
270 {
271 lfsr = 0x7fff;
272 resetLfsr = false;
273
274 if (state == ATTACK)
275 {
276 // The first envelope step in the attack state also resets the exponential
277 // counter. This has been verified by sampling ENV3.
278 exponential_counter = 0; // NOTE this is actually delayed one cycle, not modeled
279
280 // The envelope counter can flip from 0xff to 0x00 by changing state to
281 // release, then to attack. The envelope counter is then frozen at
282 // zero; to unlock this situation the state must be changed to release,
283 // then to attack. This has been verified by sampling ENV3.
284
285 envelope_pipeline = 2;
286 }
287 else
288 {
289 if (counter_enabled && (++exponential_counter == exponential_counter_period))
290 exponential_pipeline = exponential_counter_period != 1 ? 2 : 1;
291 }
292 }
293
294 // ADSR delay bug.
295 // If the rate counter comparison value is set below the current value of the
296 // rate counter, the counter will continue counting up until it wraps around
297 // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the
298 // envelope can constly be stepped.
299 // This has been verified by sampling ENV3.
300
301 // check to see if LFSR matches table value
302 if (likely(lfsr != rate))
303 {
304 // it wasn't a match, clock the LFSR once
305 // by performing XOR on last 2 bits
306 const unsigned int feedback = ((lfsr << 14) ^ (lfsr << 13)) & 0x4000;
307 lfsr = (lfsr >> 1) | feedback;
308 }
309 else
310 {
311 resetLfsr = true;
312 }
313}
314
354RESID_INLINE
355void EnvelopeGenerator::state_change()
356{
357 state_pipeline--;
358
359 switch (next_state)
360 {
361 case ATTACK:
362 if (state_pipeline == 1)
363 {
364 // The decay rate is "accidentally" enabled during first cycle of attack phase
365 rate = adsrtable[decay];
366 }
367 else if (state_pipeline == 0)
368 {
369 state = ATTACK;
370 // The attack rate is correctly enabled during second cycle of attack phase
371 rate = adsrtable[attack];
372 counter_enabled = true;
373 }
374 break;
375 case DECAY_SUSTAIN:
376 if (state_pipeline == 0)
377 {
378 state = DECAY_SUSTAIN;
379 rate = adsrtable[decay];
380 }
381 break;
382 case RELEASE:
383 if (((state == ATTACK) && (state_pipeline == 0))
384 || ((state == DECAY_SUSTAIN) && (state_pipeline == 1)))
385 {
386 state = RELEASE;
387 rate = adsrtable[release];
388 }
389 break;
390 }
391}
392
393RESID_INLINE
394void EnvelopeGenerator::set_exponential_counter()
395{
396 // Check for change of exponential counter period.
397 //
398 // For a detailed description see:
399 // http://ploguechipsounds.blogspot.it/2010/03/sid-6581r3-adsr-tables-up-close.html
400 switch (envelope_counter)
401 {
402 case 0xff:
403 case 0x00:
404 new_exponential_counter_period = 1;
405 break;
406
407 case 0x5d:
408 new_exponential_counter_period = 2;
409 break;
410
411 case 0x36:
412 new_exponential_counter_period = 4;
413 break;
414
415 case 0x1a:
416 new_exponential_counter_period = 8;
417 break;
418
419 case 0x0e:
420 new_exponential_counter_period = 16;
421 break;
422
423 case 0x06:
424 new_exponential_counter_period = 30;
425 break;
426 }
427}
428
429} // namespace reSIDfp
430
431#endif
432
433#endif
Definition EnvelopeGenerator.h:44
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
float output() const
Definition EnvelopeGenerator.h:144
void writeCONTROL_REG(unsigned char control)
Definition EnvelopeGenerator.cpp:87
unsigned char readENV() const
Definition EnvelopeGenerator.h:205
void clock()
Definition EnvelopeGenerator.h:216
EnvelopeGenerator()
Definition EnvelopeGenerator.h:149
void setDAC(float *dac)
Definition EnvelopeGenerator.h:132