libsidplayfp 1.8.8
EnvelopeGenerator.h
1/*
2 * This file is part of libsidplayfp, a SID player engine.
3 *
4 * Copyright 2011-2013 Leandro Nini <drfiemost@users.sourceforge.net>
5 * Copyright 2007-2010 Antti Lankila
6 * Copyright 2004,2010 Dag Lem <resid@nimrod.no>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22
23#ifndef ENVELOPEGENERATOR_H
24#define ENVELOPEGENERATOR_H
25
26#include "siddefs-fp.h"
27
28namespace reSIDfp
29{
30
43{
44private:
49 enum State
50 {
51 ATTACK, DECAY_SUSTAIN, RELEASE
52 };
53
54private:
56 int lfsr;
57
59 int rate;
60
65 int exponential_counter;
66
71 int exponential_counter_period;
72
74 int attack;
75
77 int decay;
78
80 int sustain;
81
83 int release;
84
86 State state;
87
89 bool hold_zero;
90
91 bool envelope_pipeline;
92
94 bool gate;
95
97 unsigned char envelope_counter;
98
104 short dac[256];
105
106private:
118 static const int adsrtable[16];
119
120private:
121 void set_exponential_counter();
122
123public:
131 void setChipModel(ChipModel chipModel);
132
136 void clock();
137
143 short output() const { return dac[envelope_counter]; }
144
149 lfsr(0),
150 rate(0),
151 exponential_counter(0),
152 exponential_counter_period(1),
153 attack(0),
154 decay(0),
155 sustain(0),
156 release(0),
157 state(RELEASE),
158 hold_zero(true),
159 envelope_pipeline(false),
160 gate(false),
161 envelope_counter(0) {}
162
166 void reset();
167
174 void writeCONTROL_REG(unsigned char control);
175
182 void writeATTACK_DECAY(unsigned char attack_decay);
183
190 void writeSUSTAIN_RELEASE(unsigned char sustain_release);
191
197 unsigned char readENV() const { return envelope_counter; }
198};
199
200} // namespace reSIDfp
201
202#if RESID_INLINING || defined(ENVELOPEGENERATOR_CPP)
203
204namespace reSIDfp
205{
206
207RESID_INLINE
209{
210 if (unlikely(envelope_pipeline))
211 {
212 --envelope_counter;
213 envelope_pipeline = false;
214 // Check for change of exponential counter period.
215 set_exponential_counter();
216 }
217
218 // Check for ADSR delay bug.
219 // If the rate counter comparison value is set below the current value of the
220 // rate counter, the counter will continue counting up until it wraps around
221 // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the
222 // envelope can constly be stepped.
223 // This has been verified by sampling ENV3.
224 //
225 // Envelope is now implemented like in the real machine with a shift register
226 // so the ADSR delay bug should be correcly modeled
227
228 // check to see if LFSR matches table value
229 if (likely(lfsr != rate))
230 {
231 // it wasn't a match, clock the LFSR once
232 // by performing XOR on last 2 bits
233 const int feedback = ((lfsr << 14) ^ (lfsr << 13)) & 0x4000;
234 lfsr = (lfsr >> 1) | feedback;
235 return;
236 }
237
238 // reset LFSR
239 lfsr = 0x7fff;
240
241 // The first envelope step in the attack state also resets the exponential
242 // counter. This has been verified by sampling ENV3.
243 //
244 if (state == ATTACK || ++exponential_counter == exponential_counter_period)
245 {
246 // likely (~50%)
247 exponential_counter = 0;
248
249 // Check whether the envelope counter is frozen at zero.
250 if (unlikely(hold_zero))
251 {
252 return;
253 }
254
255 switch (state)
256 {
257 case ATTACK:
258 // The envelope counter can flip from 0xff to 0x00 by changing state to
259 // release, then to attack. The envelope counter is then frozen at
260 // zero; to unlock this situation the state must be changed to release,
261 // then to attack. This has been verified by sampling ENV3.
262 //
263 ++envelope_counter;
264
265 if (unlikely(envelope_counter == 0xff))
266 {
267 state = DECAY_SUSTAIN;
268 rate = adsrtable[decay];
269 }
270
271 break;
272
273 case DECAY_SUSTAIN:
274
275 // From the sustain levels it follows that both the low and high 4 bits
276 // of the envelope counter are compared to the 4-bit sustain value.
277 // This has been verified by sampling ENV3.
278 //
279 // For a detailed description see:
280 // http://ploguechipsounds.blogspot.it/2010/11/new-research-on-sid-adsr.html
281 if (likely(envelope_counter == (sustain << 4 | sustain)))
282 {
283 return;
284 }
285
286 // fall-through
287
288 case RELEASE:
289
290 // The envelope counter can flip from 0x00 to 0xff by changing state to
291 // attack, then to release. The envelope counter will then continue
292 // counting down in the release state.
293 // This has been verified by sampling ENV3.
294 // NB! The operation below requires two's complement integer.
295 //
296 if (unlikely(exponential_counter_period != 1))
297 {
298 // The decrement is delayed one cycle.
299 envelope_pipeline = true;
300 return;
301 }
302
303 --envelope_counter;
304 break;
305 }
306
307 // Check for change of exponential counter period.
308 set_exponential_counter();
309 }
310}
311
312} // namespace reSIDfp
313
314#endif
315
316#endif
Definition: EnvelopeGenerator.h:43
void writeATTACK_DECAY(unsigned char attack_decay)
Definition: EnvelopeGenerator.cpp:175
void reset()
Definition: EnvelopeGenerator.cpp:120
void writeSUSTAIN_RELEASE(unsigned char sustain_release)
Definition: EnvelopeGenerator.cpp:190
void writeCONTROL_REG(unsigned char control)
Definition: EnvelopeGenerator.cpp:141
short output() const
Definition: EnvelopeGenerator.h:143
unsigned char readENV() const
Definition: EnvelopeGenerator.h:197
void setChipModel(ChipModel chipModel)
Definition: EnvelopeGenerator.cpp:99
void clock()
Definition: EnvelopeGenerator.h:208
EnvelopeGenerator()
Definition: EnvelopeGenerator.h:148