DOSBox-X
|
00001 // --------------------------------------------------------------------------- 00002 // This file is part of reSID, a MOS6581 SID emulator engine. 00003 // Copyright (C) 2004 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 along 00016 // with this program; if not, write to the Free Software Foundation, Inc., 00017 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 // --------------------------------------------------------------------------- 00019 00020 #ifndef __ENVELOPE_H__ 00021 #define __ENVELOPE_H__ 00022 00023 #include "siddefs.h" 00024 #include <sstream> 00025 00026 00027 // ---------------------------------------------------------------------------- 00028 // A 15 bit counter is used to implement the envelope rates, in effect 00029 // dividing the clock to the envelope counter by the currently selected rate 00030 // period. 00031 // In addition, another counter is used to implement the exponential envelope 00032 // decay, in effect further dividing the clock to the envelope counter. 00033 // The period of this counter is set to 1, 2, 4, 8, 16, 30 at the envelope 00034 // counter values 255, 93, 54, 26, 14, 6, respectively. 00035 // ---------------------------------------------------------------------------- 00036 class EnvelopeGenerator 00037 { 00038 public: 00039 EnvelopeGenerator(); 00040 00041 enum State { ATTACK, DECAY_SUSTAIN, RELEASE }; 00042 00043 RESID_INLINE void clock(); 00044 RESID_INLINE void clock(cycle_count delta_t); 00045 void reset(); 00046 00047 void writeCONTROL_REG(reg8); 00048 void writeATTACK_DECAY(reg8); 00049 void writeSUSTAIN_RELEASE(reg8); 00050 reg8 readENV(); 00051 00052 // 8-bit envelope output. 00053 RESID_INLINE reg8 output(); 00054 00055 void SaveState( std::ostream& stream ); 00056 void LoadState( std::istream& stream ); 00057 00058 protected: 00059 reg16 rate_counter; 00060 reg16 rate_period; 00061 reg8 exponential_counter; 00062 reg8 exponential_counter_period; 00063 reg8 envelope_counter; 00064 bool hold_zero; 00065 00066 reg4 attack; 00067 reg4 decay; 00068 reg4 sustain; 00069 reg4 release; 00070 00071 reg8 gate; 00072 00073 State state; 00074 00075 // Lookup table to convert from attack, decay, or release value to rate 00076 // counter period. 00077 static reg16 rate_counter_period[]; 00078 00079 // The 16 selectable sustain levels. 00080 static reg8 sustain_level[]; 00081 00082 friend class SID2; 00083 }; 00084 00085 00086 // ---------------------------------------------------------------------------- 00087 // Inline functions. 00088 // The following functions are defined inline because they are called every 00089 // time a sample is calculated. 00090 // ---------------------------------------------------------------------------- 00091 00092 #if RESID_INLINING || defined(__ENVELOPE_CC__) 00093 00094 // ---------------------------------------------------------------------------- 00095 // SID clocking - 1 cycle. 00096 // ---------------------------------------------------------------------------- 00097 RESID_INLINE 00098 void EnvelopeGenerator::clock() 00099 { 00100 // Check for ADSR delay bug. 00101 // If the rate counter comparison value is set below the current value of the 00102 // rate counter, the counter will continue counting up until it wraps around 00103 // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the 00104 // envelope can finally be stepped. 00105 // This has been verified by sampling ENV3. 00106 // 00107 if (++rate_counter & 0x8000) { 00108 ++rate_counter &= 0x7fff; 00109 } 00110 00111 if (rate_counter != rate_period) { 00112 return; 00113 } 00114 00115 rate_counter = 0; 00116 00117 // The first envelope step in the attack state also resets the exponential 00118 // counter. This has been verified by sampling ENV3. 00119 // 00120 if (state == ATTACK || ++exponential_counter == exponential_counter_period) 00121 { 00122 exponential_counter = 0; 00123 00124 // Check whether the envelope counter is frozen at zero. 00125 if (hold_zero) { 00126 return; 00127 } 00128 00129 switch (state) { 00130 case ATTACK: 00131 // The envelope counter can flip from 0xff to 0x00 by changing state to 00132 // release, then to attack. The envelope counter is then frozen at 00133 // zero; to unlock this situation the state must be changed to release, 00134 // then to attack. This has been verified by sampling ENV3. 00135 // 00136 ++envelope_counter &= 0xff; 00137 if (envelope_counter == 0xff) { 00138 state = DECAY_SUSTAIN; 00139 rate_period = rate_counter_period[decay]; 00140 } 00141 break; 00142 case DECAY_SUSTAIN: 00143 if (envelope_counter != sustain_level[sustain]) { 00144 --envelope_counter; 00145 } 00146 break; 00147 case RELEASE: 00148 // The envelope counter can flip from 0x00 to 0xff by changing state to 00149 // attack, then to release. The envelope counter will then continue 00150 // counting down in the release state. 00151 // This has been verified by sampling ENV3. 00152 // NB! The operation below requires two's complement integer. 00153 // 00154 --envelope_counter &= 0xff; 00155 break; 00156 } 00157 00158 // Check for change of exponential counter period. 00159 switch (envelope_counter) { 00160 case 0xff: 00161 exponential_counter_period = 1; 00162 break; 00163 case 0x5d: 00164 exponential_counter_period = 2; 00165 break; 00166 case 0x36: 00167 exponential_counter_period = 4; 00168 break; 00169 case 0x1a: 00170 exponential_counter_period = 8; 00171 break; 00172 case 0x0e: 00173 exponential_counter_period = 16; 00174 break; 00175 case 0x06: 00176 exponential_counter_period = 30; 00177 break; 00178 case 0x00: 00179 exponential_counter_period = 1; 00180 00181 // When the envelope counter is changed to zero, it is frozen at zero. 00182 // This has been verified by sampling ENV3. 00183 hold_zero = true; 00184 break; 00185 } 00186 } 00187 } 00188 00189 00190 // ---------------------------------------------------------------------------- 00191 // SID clocking - delta_t cycles. 00192 // ---------------------------------------------------------------------------- 00193 RESID_INLINE 00194 void EnvelopeGenerator::clock(cycle_count delta_t) 00195 { 00196 // Check for ADSR delay bug. 00197 // If the rate counter comparison value is set below the current value of the 00198 // rate counter, the counter will continue counting up until it wraps around 00199 // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the 00200 // envelope can finally be stepped. 00201 // This has been verified by sampling ENV3. 00202 // 00203 00204 // NB! This requires two's complement integer. 00205 int rate_step = (int)(rate_period - rate_counter); 00206 if (rate_step <= 0) { 00207 rate_step += 0x7fff; 00208 } 00209 00210 while (delta_t) { 00211 if (delta_t < rate_step) { 00212 rate_counter += (unsigned int)delta_t; 00213 if (rate_counter & 0x8000u) { 00214 ++rate_counter &= 0x7fffu; 00215 } 00216 return; 00217 } 00218 00219 rate_counter = 0; 00220 delta_t -= rate_step; 00221 00222 // The first envelope step in the attack state also resets the exponential 00223 // counter. This has been verified by sampling ENV3. 00224 // 00225 if (state == ATTACK || ++exponential_counter == exponential_counter_period) 00226 { 00227 exponential_counter = 0; 00228 00229 // Check whether the envelope counter is frozen at zero. 00230 if (hold_zero) { 00231 rate_step = (int)rate_period; 00232 continue; 00233 } 00234 00235 switch (state) { 00236 case ATTACK: 00237 // The envelope counter can flip from 0xff to 0x00 by changing state to 00238 // release, then to attack. The envelope counter is then frozen at 00239 // zero; to unlock this situation the state must be changed to release, 00240 // then to attack. This has been verified by sampling ENV3. 00241 // 00242 ++envelope_counter &= 0xff; 00243 if (envelope_counter == 0xff) { 00244 state = DECAY_SUSTAIN; 00245 rate_period = rate_counter_period[decay]; 00246 } 00247 break; 00248 case DECAY_SUSTAIN: 00249 if (envelope_counter != sustain_level[sustain]) { 00250 --envelope_counter; 00251 } 00252 break; 00253 case RELEASE: 00254 // The envelope counter can flip from 0x00 to 0xff by changing state to 00255 // attack, then to release. The envelope counter will then continue 00256 // counting down in the release state. 00257 // This has been verified by sampling ENV3. 00258 // NB! The operation below requires two's complement integer. 00259 // 00260 --envelope_counter &= 0xff; 00261 break; 00262 } 00263 00264 // Check for change of exponential counter period. 00265 switch (envelope_counter) { 00266 case 0xff: 00267 exponential_counter_period = 1; 00268 break; 00269 case 0x5d: 00270 exponential_counter_period = 2; 00271 break; 00272 case 0x36: 00273 exponential_counter_period = 4; 00274 break; 00275 case 0x1a: 00276 exponential_counter_period = 8; 00277 break; 00278 case 0x0e: 00279 exponential_counter_period = 16; 00280 break; 00281 case 0x06: 00282 exponential_counter_period = 30; 00283 break; 00284 case 0x00: 00285 exponential_counter_period = 1; 00286 00287 // When the envelope counter is changed to zero, it is frozen at zero. 00288 // This has been verified by sampling ENV3. 00289 hold_zero = true; 00290 break; 00291 } 00292 } 00293 00294 rate_step = (int)rate_period; 00295 } 00296 } 00297 00298 00299 // ---------------------------------------------------------------------------- 00300 // Read the envelope generator output. 00301 // ---------------------------------------------------------------------------- 00302 RESID_INLINE 00303 reg8 EnvelopeGenerator::output() 00304 { 00305 return envelope_counter; 00306 } 00307 00308 #endif // RESID_INLINING || defined(__ENVELOPE_CC__) 00309 00310 #endif // not __ENVELOPE_H__