libsidplayfp  1.8.7
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 
25 namespace 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 {
39 public:
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 
58 protected:
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 
91 friend 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 // ----------------------------------------------------------------------------
106 RESID_INLINE
107 void 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 // ----------------------------------------------------------------------------
199 RESID_INLINE
200 void 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 // ----------------------------------------------------------------------------
288 RESID_INLINE
289 short 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 
296 RESID_INLINE
297 void 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: dac.cc:45
Definition: sid.h:34
Definition: envelope.h:37