libsidplayfp 1.8.8
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 };
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 reg16 rate_counter;
62 reg16 rate_period;
63 reg8 exponential_counter;
64 reg8 exponential_counter_period;
65 reg8 envelope_counter;
66 // Emulation of pipeline delay for envelope decrement.
67 cycle_count envelope_pipeline;
68 bool hold_zero;
69
70 reg4 attack;
71 reg4 decay;
72 reg4 sustain;
73 reg4 release;
74
75 reg8 gate;
76
77 State state;
78
79 chip_model sid_model;
80
81 // Lookup table to convert from attack, decay, or release value to rate
82 // counter period.
83 static reg16 rate_counter_period[];
84
85 // The 16 selectable sustain levels.
86 static reg8 sustain_level[];
87
88 // DAC lookup tables.
89 static unsigned short model_dac[2][1 << 8];
90
91friend class SID;
92};
93
94
95// ----------------------------------------------------------------------------
96// Inline functions.
97// The following functions are defined inline because they are called every
98// time a sample is calculated.
99// ----------------------------------------------------------------------------
100
101#if RESID_INLINING || defined(RESID_ENVELOPE_CC)
102
103// ----------------------------------------------------------------------------
104// SID clocking - 1 cycle.
105// ----------------------------------------------------------------------------
106RESID_INLINE
107void EnvelopeGenerator::clock()
108{
109 // If the exponential counter period != 1, the envelope decrement is delayed
110 // 1 cycle. This is only modeled for single cycle clocking.
111 if (unlikely(envelope_pipeline)) {
112 --envelope_counter;
113 envelope_pipeline = 0;
114 // Check for change of exponential counter period.
115 set_exponential_counter();
116 }
117
118 // Check for ADSR delay bug.
119 // If the rate counter comparison value is set below the current value of the
120 // rate counter, the counter will continue counting up until it wraps around
121 // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the
122 // envelope can finally be stepped.
123 // This has been verified by sampling ENV3.
124 //
125 if (unlikely(++rate_counter & 0x8000)) {
126 ++rate_counter &= 0x7fff;
127 }
128
129 if (likely(rate_counter != rate_period)) {
130 return;
131 }
132
133 rate_counter = 0;
134
135 // The first envelope step in the attack state also resets the exponential
136 // counter. This has been verified by sampling ENV3.
137 //
138 if (state == ATTACK || ++exponential_counter == exponential_counter_period)
139 {
140 // likely (~50%)
141 exponential_counter = 0;
142
143 // Check whether the envelope counter is frozen at zero.
144 if (unlikely(hold_zero)) {
145 return;
146 }
147
148 switch (state) {
149 case ATTACK:
150 // The envelope counter can flip from 0xff to 0x00 by changing state to
151 // release, then to attack. The envelope counter is then frozen at
152 // zero; to unlock this situation the state must be changed to release,
153 // then to attack. This has been verified by sampling ENV3.
154 //
155 ++envelope_counter &= 0xff;
156 if (unlikely(envelope_counter == 0xff)) {
157 state = DECAY_SUSTAIN;
158 rate_period = rate_counter_period[decay];
159 }
160 break;
161 case DECAY_SUSTAIN:
162 if (likely(envelope_counter == sustain_level[sustain])) {
163 return;
164 }
165 if (exponential_counter_period != 1) {
166 // unlikely (15%)
167 // The decrement is delayed one cycle.
168 envelope_pipeline = 1;
169 return;
170 }
171 --envelope_counter;
172 break;
173 case RELEASE:
174 // The envelope counter can flip from 0x00 to 0xff by changing state to
175 // attack, then to release. The envelope counter will then continue
176 // counting down in the release state.
177 // This has been verified by sampling ENV3.
178 // NB! The operation below requires two's complement integer.
179 //
180 if (exponential_counter_period != 1) {
181 // likely (~50%)
182 // The decrement is delayed one cycle.
183 envelope_pipeline = 1;
184 return;
185 }
186 --envelope_counter &= 0xff;
187 break;
188 }
189
190 // Check for change of exponential counter period.
191 set_exponential_counter();
192 }
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 // Check for ADSR delay bug.
206 // If the rate counter comparison value is set below the current value of the
207 // rate counter, the counter will continue counting up until it wraps around
208 // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the
209 // envelope can finally be stepped.
210 // This has been verified by sampling ENV3.
211 //
212
213 // NB! This requires two's complement integer.
214 int rate_step = rate_period - rate_counter;
215 if (unlikely(rate_step <= 0)) {
216 rate_step += 0x7fff;
217 }
218
219 while (delta_t) {
220 if (delta_t < rate_step) {
221 // likely (~65%)
222 rate_counter += delta_t;
223 if (unlikely(rate_counter & 0x8000)) {
224 ++rate_counter &= 0x7fff;
225 }
226 return;
227 }
228
229 rate_counter = 0;
230 delta_t -= rate_step;
231
232 // The first envelope step in the attack state also resets the exponential
233 // counter. This has been verified by sampling ENV3.
234 //
235 if (state == ATTACK || ++exponential_counter == exponential_counter_period)
236 {
237 // likely (~50%)
238 exponential_counter = 0;
239
240 // Check whether the envelope counter is frozen at zero.
241 if (unlikely(hold_zero)) {
242 rate_step = rate_period;
243 continue;
244 }
245
246 switch (state) {
247 case ATTACK:
248 // The envelope counter can flip from 0xff to 0x00 by changing state to
249 // release, then to attack. The envelope counter is then frozen at
250 // zero; to unlock this situation the state must be changed to release,
251 // then to attack. This has been verified by sampling ENV3.
252 //
253 ++envelope_counter &= 0xff;
254 if (unlikely(envelope_counter == 0xff)) {
255 state = DECAY_SUSTAIN;
256 rate_period = rate_counter_period[decay];
257 }
258 break;
259 case DECAY_SUSTAIN:
260 if (likely(envelope_counter == sustain_level[sustain])) {
261 return;
262 }
263 --envelope_counter;
264 break;
265 case RELEASE:
266 // The envelope counter can flip from 0x00 to 0xff by changing state to
267 // attack, then to release. The envelope counter will then continue
268 // counting down in the release state.
269 // This has been verified by sampling ENV3.
270 // NB! The operation below requires two's complement integer.
271 //
272 --envelope_counter &= 0xff;
273 break;
274 }
275
276 // Check for change of exponential counter period.
277 set_exponential_counter();
278 }
279
280 rate_step = rate_period;
281 }
282}
283
284
285// ----------------------------------------------------------------------------
286// Read the envelope generator output.
287// ----------------------------------------------------------------------------
288RESID_INLINE
289short EnvelopeGenerator::output()
290{
291 // DAC imperfections are emulated by using envelope_counter as an index
292 // into a DAC lookup table. readENV() uses envelope_counter directly.
293 return model_dac[sid_model][envelope_counter];
294}
295
296RESID_INLINE
297void EnvelopeGenerator::set_exponential_counter()
298{
299 // Check for change of exponential counter period.
300 switch (envelope_counter) {
301 case 0xff:
302 exponential_counter_period = 1;
303 break;
304 case 0x5d:
305 exponential_counter_period = 2;
306 break;
307 case 0x36:
308 exponential_counter_period = 4;
309 break;
310 case 0x1a:
311 exponential_counter_period = 8;
312 break;
313 case 0x0e:
314 exponential_counter_period = 16;
315 break;
316 case 0x06:
317 exponential_counter_period = 30;
318 break;
319 case 0x00:
320 // FIXME: Check whether 0x00 really changes the period.
321 // E.g. set R = 0xf, gate on to 0x06, gate off to 0x00, gate on to 0x04,
322 // gate off, sample.
323 exponential_counter_period = 1;
324
325 // When the envelope counter is changed to zero, it is frozen at zero.
326 // This has been verified by sampling ENV3.
327 hold_zero = true;
328 break;
329 }
330}
331
332#endif // RESID_INLINING || defined(RESID_ENVELOPE_CC)
333
334} // namespace reSID
335
336#endif // not RESID_ENVELOPE_H
Definition: envelope.h:38
Definition: sid.h:35