libsidplayfp 1.0.3
|
00001 // --------------------------------------------------------------------------- 00002 // This file is part of reSID, a MOS6581 SID emulator engine. 00003 // Copyright (C) 2010 Dag Lem <resid@nimrod.no> 00004 // 00005 // This program is free software; you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation; either version 2 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with this program; if not, write to the Free Software 00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 // --------------------------------------------------------------------------- 00019 00020 #ifndef RESID_ENVELOPE_H 00021 #define RESID_ENVELOPE_H 00022 00023 #include "resid-config.h" 00024 00025 namespace reSID 00026 { 00027 00028 // ---------------------------------------------------------------------------- 00029 // A 15 bit counter is used to implement the envelope rates, in effect 00030 // dividing the clock to the envelope counter by the currently selected rate 00031 // period. 00032 // In addition, another counter is used to implement the exponential envelope 00033 // decay, in effect further dividing the clock to the envelope counter. 00034 // The period of this counter is set to 1, 2, 4, 8, 16, 30 at the envelope 00035 // counter values 255, 93, 54, 26, 14, 6, respectively. 00036 // ---------------------------------------------------------------------------- 00037 class EnvelopeGenerator 00038 { 00039 public: 00040 EnvelopeGenerator(); 00041 00042 enum State { ATTACK, DECAY_SUSTAIN, RELEASE }; 00043 00044 void set_chip_model(chip_model model); 00045 00046 void clock(); 00047 void clock(cycle_count delta_t); 00048 void reset(); 00049 00050 void writeCONTROL_REG(reg8); 00051 void writeATTACK_DECAY(reg8); 00052 void writeSUSTAIN_RELEASE(reg8); 00053 reg8 readENV(); 00054 00055 // 8-bit envelope output. 00056 short output(); 00057 00058 protected: 00059 void set_exponential_counter(); 00060 00061 reg16 rate_counter; 00062 reg16 rate_period; 00063 reg8 exponential_counter; 00064 reg8 exponential_counter_period; 00065 reg8 envelope_counter; 00066 // Emulation of pipeline delay for envelope decrement. 00067 cycle_count envelope_pipeline; 00068 bool hold_zero; 00069 00070 reg4 attack; 00071 reg4 decay; 00072 reg4 sustain; 00073 reg4 release; 00074 00075 reg8 gate; 00076 00077 State state; 00078 00079 chip_model sid_model; 00080 00081 // Lookup table to convert from attack, decay, or release value to rate 00082 // counter period. 00083 static reg16 rate_counter_period[]; 00084 00085 // The 16 selectable sustain levels. 00086 static reg8 sustain_level[]; 00087 00088 // DAC lookup tables. 00089 static unsigned short model_dac[2][1 << 8]; 00090 00091 friend class SID; 00092 }; 00093 00094 00095 // ---------------------------------------------------------------------------- 00096 // Inline functions. 00097 // The following functions are defined inline because they are called every 00098 // time a sample is calculated. 00099 // ---------------------------------------------------------------------------- 00100 00101 #if RESID_INLINING || defined(RESID_ENVELOPE_CC) 00102 00103 // ---------------------------------------------------------------------------- 00104 // SID clocking - 1 cycle. 00105 // ---------------------------------------------------------------------------- 00106 RESID_INLINE 00107 void EnvelopeGenerator::clock() 00108 { 00109 // If the exponential counter period != 1, the envelope decrement is delayed 00110 // 1 cycle. This is only modeled for single cycle clocking. 00111 if (unlikely(envelope_pipeline)) { 00112 --envelope_counter; 00113 envelope_pipeline = 0; 00114 // Check for change of exponential counter period. 00115 set_exponential_counter(); 00116 } 00117 00118 // Check for ADSR delay bug. 00119 // If the rate counter comparison value is set below the current value of the 00120 // rate counter, the counter will continue counting up until it wraps around 00121 // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the 00122 // envelope can finally be stepped. 00123 // This has been verified by sampling ENV3. 00124 // 00125 if (unlikely(++rate_counter & 0x8000)) { 00126 ++rate_counter &= 0x7fff; 00127 } 00128 00129 if (likely(rate_counter != rate_period)) { 00130 return; 00131 } 00132 00133 rate_counter = 0; 00134 00135 // The first envelope step in the attack state also resets the exponential 00136 // counter. This has been verified by sampling ENV3. 00137 // 00138 if (state == ATTACK || ++exponential_counter == exponential_counter_period) 00139 { 00140 // likely (~50%) 00141 exponential_counter = 0; 00142 00143 // Check whether the envelope counter is frozen at zero. 00144 if (unlikely(hold_zero)) { 00145 return; 00146 } 00147 00148 switch (state) { 00149 case ATTACK: 00150 // The envelope counter can flip from 0xff to 0x00 by changing state to 00151 // release, then to attack. The envelope counter is then frozen at 00152 // zero; to unlock this situation the state must be changed to release, 00153 // then to attack. This has been verified by sampling ENV3. 00154 // 00155 ++envelope_counter &= 0xff; 00156 if (unlikely(envelope_counter == 0xff)) { 00157 state = DECAY_SUSTAIN; 00158 rate_period = rate_counter_period[decay]; 00159 } 00160 break; 00161 case DECAY_SUSTAIN: 00162 if (likely(envelope_counter == sustain_level[sustain])) { 00163 return; 00164 } 00165 if (exponential_counter_period != 1) { 00166 // unlikely (15%) 00167 // The decrement is delayed one cycle. 00168 envelope_pipeline = 1; 00169 return; 00170 } 00171 --envelope_counter; 00172 break; 00173 case RELEASE: 00174 // The envelope counter can flip from 0x00 to 0xff by changing state to 00175 // attack, then to release. The envelope counter will then continue 00176 // counting down in the release state. 00177 // This has been verified by sampling ENV3. 00178 // NB! The operation below requires two's complement integer. 00179 // 00180 if (exponential_counter_period != 1) { 00181 // likely (~50%) 00182 // The decrement is delayed one cycle. 00183 envelope_pipeline = 1; 00184 return; 00185 } 00186 --envelope_counter &= 0xff; 00187 break; 00188 } 00189 00190 // Check for change of exponential counter period. 00191 set_exponential_counter(); 00192 } 00193 } 00194 00195 00196 // ---------------------------------------------------------------------------- 00197 // SID clocking - delta_t cycles. 00198 // ---------------------------------------------------------------------------- 00199 RESID_INLINE 00200 void EnvelopeGenerator::clock(cycle_count delta_t) 00201 { 00202 // NB! Any pipelined envelope counter decrement from single cycle clocking 00203 // will be lost. It is not worth the trouble to flush the pipeline here. 00204 00205 // Check for ADSR delay bug. 00206 // If the rate counter comparison value is set below the current value of the 00207 // rate counter, the counter will continue counting up until it wraps around 00208 // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the 00209 // envelope can finally be stepped. 00210 // This has been verified by sampling ENV3. 00211 // 00212 00213 // NB! This requires two's complement integer. 00214 int rate_step = rate_period - rate_counter; 00215 if (unlikely(rate_step <= 0)) { 00216 rate_step += 0x7fff; 00217 } 00218 00219 while (delta_t) { 00220 if (delta_t < rate_step) { 00221 // likely (~65%) 00222 rate_counter += delta_t; 00223 if (unlikely(rate_counter & 0x8000)) { 00224 ++rate_counter &= 0x7fff; 00225 } 00226 return; 00227 } 00228 00229 rate_counter = 0; 00230 delta_t -= rate_step; 00231 00232 // The first envelope step in the attack state also resets the exponential 00233 // counter. This has been verified by sampling ENV3. 00234 // 00235 if (state == ATTACK || ++exponential_counter == exponential_counter_period) 00236 { 00237 // likely (~50%) 00238 exponential_counter = 0; 00239 00240 // Check whether the envelope counter is frozen at zero. 00241 if (unlikely(hold_zero)) { 00242 rate_step = rate_period; 00243 continue; 00244 } 00245 00246 switch (state) { 00247 case ATTACK: 00248 // The envelope counter can flip from 0xff to 0x00 by changing state to 00249 // release, then to attack. The envelope counter is then frozen at 00250 // zero; to unlock this situation the state must be changed to release, 00251 // then to attack. This has been verified by sampling ENV3. 00252 // 00253 ++envelope_counter &= 0xff; 00254 if (unlikely(envelope_counter == 0xff)) { 00255 state = DECAY_SUSTAIN; 00256 rate_period = rate_counter_period[decay]; 00257 } 00258 break; 00259 case DECAY_SUSTAIN: 00260 if (likely(envelope_counter == sustain_level[sustain])) { 00261 return; 00262 } 00263 --envelope_counter; 00264 break; 00265 case RELEASE: 00266 // The envelope counter can flip from 0x00 to 0xff by changing state to 00267 // attack, then to release. The envelope counter will then continue 00268 // counting down in the release state. 00269 // This has been verified by sampling ENV3. 00270 // NB! The operation below requires two's complement integer. 00271 // 00272 --envelope_counter &= 0xff; 00273 break; 00274 } 00275 00276 // Check for change of exponential counter period. 00277 set_exponential_counter(); 00278 } 00279 00280 rate_step = rate_period; 00281 } 00282 } 00283 00284 00285 // ---------------------------------------------------------------------------- 00286 // Read the envelope generator output. 00287 // ---------------------------------------------------------------------------- 00288 RESID_INLINE 00289 short EnvelopeGenerator::output() 00290 { 00291 // DAC imperfections are emulated by using envelope_counter as an index 00292 // into a DAC lookup table. readENV() uses envelope_counter directly. 00293 return model_dac[sid_model][envelope_counter]; 00294 } 00295 00296 RESID_INLINE 00297 void EnvelopeGenerator::set_exponential_counter() 00298 { 00299 // Check for change of exponential counter period. 00300 switch (envelope_counter) { 00301 case 0xff: 00302 exponential_counter_period = 1; 00303 break; 00304 case 0x5d: 00305 exponential_counter_period = 2; 00306 break; 00307 case 0x36: 00308 exponential_counter_period = 4; 00309 break; 00310 case 0x1a: 00311 exponential_counter_period = 8; 00312 break; 00313 case 0x0e: 00314 exponential_counter_period = 16; 00315 break; 00316 case 0x06: 00317 exponential_counter_period = 30; 00318 break; 00319 case 0x00: 00320 // FIXME: Check whether 0x00 really changes the period. 00321 // E.g. set R = 0xf, gate on to 0x06, gate off to 0x00, gate on to 0x04, 00322 // gate off, sample. 00323 exponential_counter_period = 1; 00324 00325 // When the envelope counter is changed to zero, it is frozen at zero. 00326 // This has been verified by sampling ENV3. 00327 hold_zero = true; 00328 break; 00329 } 00330 } 00331 00332 #endif // RESID_INLINING || defined(RESID_ENVELOPE_CC) 00333 00334 } // namespace reSID 00335 00336 #endif // not RESID_ENVELOPE_H