libsidplayfp 2.15.0
envelope.h
1// ---------------------------------------------------------------------------
2// This file is part of reSID, a MOS6581 SID emulator engine.
3// Copyright (C) 2010 Dag Lem <resid@nimrod.no>
4//
5// This program is free software; you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation; either version 2 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program; if not, write to the Free Software
17// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18// ---------------------------------------------------------------------------
19
20#ifndef RESID_ENVELOPE_H
21#define RESID_ENVELOPE_H
22
23#include "resid-config.h"
24
25namespace reSID
26{
27
28// ----------------------------------------------------------------------------
29// A 15 bit counter is used to implement the envelope rates, in effect
30// dividing the clock to the envelope counter by the currently selected rate
31// period.
32// In addition, another counter is used to implement the exponential envelope
33// decay, in effect further dividing the clock to the envelope counter.
34// The period of this counter is set to 1, 2, 4, 8, 16, 30 at the envelope
35// counter values 255, 93, 54, 26, 14, 6, respectively.
36// ----------------------------------------------------------------------------
38{
39public:
41
42 enum State { ATTACK, DECAY_SUSTAIN, RELEASE, FREEZED };
43
44 void set_chip_model(chip_model model);
45
46 void clock();
47 void clock(cycle_count delta_t);
48 void reset();
49
50 void writeCONTROL_REG(reg8);
51 void writeATTACK_DECAY(reg8);
52 void writeSUSTAIN_RELEASE(reg8);
53 reg8 readENV();
54
55 // 8-bit envelope output.
56 short output();
57
58protected:
59 void set_exponential_counter();
60
61 void state_change();
62
63 reg16 rate_counter;
64 reg16 rate_period;
65 reg8 exponential_counter;
66 reg8 exponential_counter_period;
67 reg8 new_exponential_counter_period;
68 reg8 envelope_counter;
69 reg8 env3;
70 // Emulation of pipeline delay for envelope decrement.
71 cycle_count envelope_pipeline;
72 cycle_count exponential_pipeline;
73 cycle_count state_pipeline;
74 bool hold_zero;
75 bool reset_rate_counter;
76
77 reg4 attack;
78 reg4 decay;
79 reg4 sustain;
80 reg4 release;
81
82 reg8 gate;
83
84 State state;
85 State next_state;
86
87 chip_model sid_model;
88
89 // Lookup table to convert from attack, decay, or release value to rate
90 // counter period.
91 static reg16 rate_counter_period[];
92
93 // The 16 selectable sustain levels.
94 static reg8 sustain_level[];
95
96 // DAC lookup tables.
97 static unsigned short model_dac[2][1 << 8];
98
99friend class SID;
100};
101
102
103// ----------------------------------------------------------------------------
104// Inline functions.
105// The following functions are defined inline because they are called every
106// time a sample is calculated.
107// ----------------------------------------------------------------------------
108
109#if RESID_INLINING || defined(RESID_ENVELOPE_CC)
110
111// ----------------------------------------------------------------------------
112// SID clocking - 1 cycle.
113// ----------------------------------------------------------------------------
114RESID_INLINE
115void EnvelopeGenerator::clock()
116{
117 // The ENV3 value is sampled at the first phase of the clock
118 env3 = envelope_counter;
119
120 if (unlikely(state_pipeline)) {
121 state_change();
122 }
123
124 // If the exponential counter period != 1, the envelope decrement is delayed
125 // 1 cycle. This is only modeled for single cycle clocking.
126 if (unlikely(envelope_pipeline != 0) && (--envelope_pipeline == 0)) {
127 if (likely(!hold_zero)) {
128 if (state == ATTACK) {
129 ++envelope_counter &= 0xff;
130 if (unlikely(envelope_counter == 0xff)) {
131 state = DECAY_SUSTAIN;
132 rate_period = rate_counter_period[decay];
133 }
134 }
135 else if ((state == DECAY_SUSTAIN) || (state == RELEASE)) {
136 --envelope_counter &= 0xff;
137 }
138
139 set_exponential_counter();
140 }
141 }
142
143 if (unlikely(exponential_pipeline != 0) && (--exponential_pipeline == 0)) {
144 exponential_counter = 0;
145
146 if (((state == DECAY_SUSTAIN) && (envelope_counter != sustain_level[sustain]))
147 || (state == RELEASE)) {
148 // The envelope counter can flip from 0x00 to 0xff by changing state to
149 // attack, then to release. The envelope counter will then continue
150 // counting down in the release state.
151 // This has been verified by sampling ENV3.
152
153 envelope_pipeline = 1;
154 }
155 }
156 else if (unlikely(reset_rate_counter)) {
157 rate_counter = 0;
158 reset_rate_counter = false;
159
160 if (state == ATTACK) {
161 // The first envelope step in the attack state also resets the exponential
162 // counter. This has been verified by sampling ENV3.
163 exponential_counter = 0; // NOTE this is actually delayed one cycle, not modeled
164
165 // The envelope counter can flip from 0xff to 0x00 by changing state to
166 // release, then to attack. The envelope counter is then frozen at
167 // zero; to unlock this situation the state must be changed to release,
168 // then to attack. This has been verified by sampling ENV3.
169
170 envelope_pipeline = 2;
171 }
172 else {
173 if ((!hold_zero) && ++exponential_counter == exponential_counter_period) {
174 exponential_pipeline = exponential_counter_period != 1 ? 2 : 1;
175 }
176 }
177 }
178
179 // Check for ADSR delay bug.
180 // If the rate counter comparison value is set below the current value of the
181 // rate counter, the counter will continue counting up until it wraps around
182 // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the
183 // envelope can finally be stepped.
184 // This has been verified by sampling ENV3.
185 //
186 if (likely(rate_counter != rate_period)) {
187 if (unlikely(++rate_counter & 0x8000)) {
188 ++rate_counter &= 0x7fff;
189 }
190 }
191 else
192 reset_rate_counter = true;
193}
194
195
196// ----------------------------------------------------------------------------
197// SID clocking - delta_t cycles.
198// ----------------------------------------------------------------------------
199RESID_INLINE
200void EnvelopeGenerator::clock(cycle_count delta_t)
201{
202 // NB! Any pipelined envelope counter decrement from single cycle clocking
203 // will be lost. It is not worth the trouble to flush the pipeline here.
204
205 if (unlikely(state_pipeline)) {
206 if (next_state == ATTACK) {
207 state = ATTACK;
208 hold_zero = false;
209 rate_period = rate_counter_period[attack];
210 } else if (next_state == RELEASE) {
211 state = RELEASE;
212 rate_period = rate_counter_period[release];
213 } else if (next_state == FREEZED) {
214 hold_zero = true;
215 }
216 state_pipeline = 0;
217 }
218
219 // Check for ADSR delay bug.
220 // If the rate counter comparison value is set below the current value of the
221 // rate counter, the counter will continue counting up until it wraps around
222 // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the
223 // envelope can finally be stepped.
224 // This has been verified by sampling ENV3.
225 //
226
227 // NB! This requires two's complement integer.
228 int rate_step = rate_period - rate_counter;
229 if (unlikely(rate_step <= 0)) {
230 rate_step += 0x7fff;
231 }
232
233 while (delta_t) {
234 if (delta_t < rate_step) {
235 // likely (~65%)
236 rate_counter += delta_t;
237 if (unlikely(rate_counter & 0x8000)) {
238 ++rate_counter &= 0x7fff;
239 }
240 return;
241 }
242
243 rate_counter = 0;
244 delta_t -= rate_step;
245
246 // The first envelope step in the attack state also resets the exponential
247 // counter. This has been verified by sampling ENV3.
248 //
249 if (state == ATTACK || ++exponential_counter == exponential_counter_period) {
250 // likely (~50%)
251 exponential_counter = 0;
252
253 // Check whether the envelope counter is frozen at zero.
254 if (unlikely(hold_zero)) {
255 rate_step = rate_period;
256 continue;
257 }
258
259 switch (state) {
260 case ATTACK:
261 // The envelope counter can flip from 0xff to 0x00 by changing state to
262 // release, then to attack. The envelope counter is then frozen at
263 // zero; to unlock this situation the state must be changed to release,
264 // then to attack. This has been verified by sampling ENV3.
265 //
266 ++envelope_counter &= 0xff;
267 if (unlikely(envelope_counter == 0xff)) {
268 state = DECAY_SUSTAIN;
269 rate_period = rate_counter_period[decay];
270 }
271 break;
272 case DECAY_SUSTAIN:
273 if (likely(envelope_counter != sustain_level[sustain])) {
274 --envelope_counter;
275 }
276 break;
277 case RELEASE:
278 // The envelope counter can flip from 0x00 to 0xff by changing state to
279 // attack, then to release. The envelope counter will then continue
280 // counting down in the release state.
281 // This has been verified by sampling ENV3.
282 // NB! The operation below requires two's complement integer.
283 //
284 --envelope_counter &= 0xff;
285 break;
286 case FREEZED:
287 // we should never get here
288 break;
289 }
290
291 // Check for change of exponential counter period.
292 set_exponential_counter();
293 if (unlikely(new_exponential_counter_period > 0)) {
294 exponential_counter_period = new_exponential_counter_period;
295 new_exponential_counter_period = 0;
296 if (next_state == FREEZED) {
297 hold_zero = true;
298 }
299 }
300 }
301
302 rate_step = rate_period;
303 }
304}
305
345RESID_INLINE
347{
348 state_pipeline--;
349
350 switch (next_state) {
351 case ATTACK:
352 if (state_pipeline == 0) {
353 state = ATTACK;
354 // The attack register is correctly activated during second cycle of attack phase
355 rate_period = rate_counter_period[attack];
356 hold_zero = false;
357 }
358 break;
359 case DECAY_SUSTAIN:
360 break;
361 case RELEASE:
362 if (((state == ATTACK) && (state_pipeline == 0))
363 || ((state == DECAY_SUSTAIN) && (state_pipeline == 1))) {
364 state = RELEASE;
365 rate_period = rate_counter_period[release];
366 }
367 break;
368 case FREEZED:
369 break;
370 }
371}
372
373
374// ----------------------------------------------------------------------------
375// Read the envelope generator output.
376// ----------------------------------------------------------------------------
377RESID_INLINE
378short EnvelopeGenerator::output()
379{
380 // DAC imperfections are emulated by using envelope_counter as an index
381 // into a DAC lookup table. readENV() uses envelope_counter directly.
382 return model_dac[sid_model][envelope_counter];
383}
384
385RESID_INLINE
386void EnvelopeGenerator::set_exponential_counter()
387{
388 // Check for change of exponential counter period.
389 switch (envelope_counter) {
390 case 0xff:
391 exponential_counter_period = 1;
392 break;
393 case 0x5d:
394 exponential_counter_period = 2;
395 break;
396 case 0x36:
397 exponential_counter_period = 4;
398 break;
399 case 0x1a:
400 exponential_counter_period = 8;
401 break;
402 case 0x0e:
403 exponential_counter_period = 16;
404 break;
405 case 0x06:
406 exponential_counter_period = 30;
407 break;
408 case 0x00:
409 // TODO write a test to verify that 0x00 really changes the period
410 // e.g. set R = 0xf, gate on to 0x06, gate off to 0x00, gate on to 0x04,
411 // gate off, sample.
412 exponential_counter_period = 1;
413
414 // When the envelope counter is changed to zero, it is frozen at zero.
415 // This has been verified by sampling ENV3.
416 hold_zero = true;
417 break;
418 }
419}
420
421#endif // RESID_INLINING || defined(RESID_ENVELOPE_CC)
422
423} // namespace reSID
424
425#endif // not RESID_ENVELOPE_H
Definition envelope.h:38
void state_change()
Definition envelope.h:346
Definition sid.h:39