libsidplayfp 2.15.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
29namespace reSIDfp
30{
31
44{
45private:
50 enum class State
51 {
52 ATTACK, DECAY_SUSTAIN, RELEASE
53 };
54
55private:
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
113private:
114 static const unsigned int adsrtable[16];
115
116private:
117 void set_exponential_counter();
118
119 void state_change();
120
121public:
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
173namespace reSIDfp
174{
175
176RESID_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
315RESID_INLINE
316void 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
354RESID_INLINE
355void 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