libsidplayfp  1.0.3
envelope.h
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