DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/hardware/reSID/envelope.h
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__