libresidfp 1.1.1
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
31namespace reSIDfp
32{
33
46{
47 friend class State;
48
49public:
54 enum class State
55 {
56 ATTACK, DECAY_SUSTAIN, RELEASE
57 };
58
59private:
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
117private:
118 static const uint16_t adsrtable[16];
119
120private:
121 void set_exponential_counter();
122
123 void state_change();
124
125public:
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
177namespace reSIDfp
178{
179
180RESIDFP_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
319RESIDFP_INLINE
320void 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
358RESIDFP_INLINE
359void 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
Definition EnvelopeGenerator.h:46
void writeATTACK_DECAY(uint8_t attack_decay)
Definition EnvelopeGenerator.cpp:122
void reset()
Definition EnvelopeGenerator.cpp:62
void clock()
Definition EnvelopeGenerator.h:181
void writeCONTROL_REG(uint8_t control)
Definition EnvelopeGenerator.cpp:87
uint8_t readENV() const
Definition EnvelopeGenerator.h:170
uint8_t output() const
Definition EnvelopeGenerator.h:134
State
Definition EnvelopeGenerator.h:55
void writeSUSTAIN_RELEASE(uint8_t sustain_release)
Definition EnvelopeGenerator.cpp:137
Definition State.h:47