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