libsidplayfp  1.0.3
EnvelopeGenerator.h
00001 /*
00002  * This file is part of libsidplayfp, a SID player engine.
00003  *
00004  * Copyright 2011-2013 Leandro Nini <drfiemost@users.sourceforge.net>
00005  * Copyright 2007-2010 Antti Lankila
00006  * Copyright 2004 Dag Lem <resid@nimrod.no>
00007  *
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00021  */
00022 
00023 #ifndef ENVELOPEGENERATOR_H
00024 #define ENVELOPEGENERATOR_H
00025 
00026 #include "siddefs-fp.h"
00027 
00028 namespace reSIDfp
00029 {
00030 
00044 class EnvelopeGenerator
00045 {
00046 private:
00051     enum State
00052     {
00053         ATTACK, DECAY_SUSTAIN, RELEASE
00054     };
00055 
00059     int lfsr;
00060 
00064     int rate;
00065 
00070     int exponential_counter;
00071 
00076     int exponential_counter_period;
00077 
00079     int attack;
00080 
00082     int decay;
00083 
00085     int sustain;
00086 
00088     int release;
00089 
00091     State state;
00092 
00096     bool hold_zero;
00097 
00098     bool envelope_pipeline;
00099 
00101     bool gate;
00102 
00104     unsigned char envelope_counter;
00105 
00111     short dac[256];
00112 
00113     void set_exponential_counter();
00114 
00126     static const int adsrtable[16];
00127 
00128 public:
00136     void setChipModel(ChipModel chipModel);
00137 
00141     void clock();
00142 
00148     short output() const { return dac[envelope_counter]; }
00149 
00153     EnvelopeGenerator() :
00154         lfsr(0),
00155         rate(0),
00156         exponential_counter(0),
00157         exponential_counter_period(1),
00158         attack(0),
00159         decay(0),
00160         sustain(0),
00161         release(0),
00162         state(RELEASE),
00163         hold_zero(true),
00164         envelope_pipeline(false),
00165         gate(false),
00166         envelope_counter(0) {}
00167 
00171     void reset();
00172 
00173     // ----------------------------------------------------------------------------
00174     // Register functions.
00175     // ----------------------------------------------------------------------------
00176 
00181     void writeCONTROL_REG(unsigned char control);
00182 
00187     void writeATTACK_DECAY(unsigned char attack_decay);
00188 
00193     void writeSUSTAIN_RELEASE(unsigned char sustain_release);
00194 
00200     unsigned char readENV() const { return envelope_counter; }
00201 };
00202 
00203 } // namespace reSIDfp
00204 
00205 #if RESID_INLINING || defined(ENVELOPEGENERATOR_CPP)
00206 
00207 namespace reSIDfp
00208 {
00209 
00210 RESID_INLINE
00211 void EnvelopeGenerator::clock()
00212 {
00213     if (envelope_pipeline)
00214     {
00215         -- envelope_counter;
00216         envelope_pipeline = false;
00217         // Check for change of exponential counter period.
00218         set_exponential_counter();
00219     }
00220 
00221     // Check for ADSR delay bug.
00222     // If the rate counter comparison value is set below the current value of the
00223     // rate counter, the counter will continue counting up until it wraps around
00224     // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the
00225     // envelope can constly be stepped.
00226     // This has been verified by sampling ENV3.
00227     //
00228     // Envelope is now implemented like in the real machine with a shift register
00229     // so the ADSR delay bug should be correcly modeled
00230 
00231     // check to see if LFSR matches table value
00232     if (lfsr != rate)
00233     {
00234         // it wasn't a match, clock the LFSR once
00235         // by performing XOR on last 2 bits
00236         const int feedback = ((lfsr >> 14) ^ (lfsr >> 13)) & 0x01;
00237         lfsr = ((lfsr << 1) & 0x7fff) | feedback;
00238         return;
00239     }
00240 
00241     // reset LFSR
00242     lfsr = 0x7fff;
00243 
00244     // The first envelope step in the attack state also resets the exponential
00245     // counter. This has been verified by sampling ENV3.
00246     //
00247     if (state == ATTACK || ++exponential_counter == exponential_counter_period)
00248     {
00249         // likely (~50%)
00250         exponential_counter = 0;
00251 
00252         // Check whether the envelope counter is frozen at zero.
00253         if (hold_zero)
00254         {
00255             return;
00256         }
00257 
00258         switch (state)
00259         {
00260         case ATTACK:
00261             // The envelope counter can flip from 0xff to 0x00 by changing state to
00262             // release, then to attack. The envelope counter is then frozen at
00263             // zero; to unlock this situation the state must be changed to release,
00264             // then to attack. This has been verified by sampling ENV3.
00265             //
00266             ++ envelope_counter;
00267 
00268             if (envelope_counter == (unsigned char) 0xff)
00269             {
00270                 state = DECAY_SUSTAIN;
00271                 rate = adsrtable[decay];
00272             }
00273 
00274             break;
00275 
00276         case DECAY_SUSTAIN:
00277 
00278             // From the sustain levels it follows that both the low and high 4 bits
00279             // of the envelope counter are compared to the 4-bit sustain value.
00280             // This has been verified by sampling ENV3.
00281             //
00282             // For a detailed description see:
00283             // http://ploguechipsounds.blogspot.it/2010/11/new-research-on-sid-adsr.html
00284             if (envelope_counter == (unsigned char)(sustain << 4 | sustain))
00285             {
00286                 return;
00287             }
00288 
00289             if (exponential_counter_period != 1)
00290             {
00291                 // unlikely (15%)
00292                 // The decrement is delayed one cycle.
00293                 envelope_pipeline = true;
00294                 return;
00295             }
00296 
00297             -- envelope_counter;
00298             break;
00299 
00300         case RELEASE:
00301 
00302             // The envelope counter can flip from 0x00 to 0xff by changing state to
00303             // attack, then to release. The envelope counter will then continue
00304             // counting down in the release state.
00305             // This has been verified by sampling ENV3.
00306             // NB! The operation below requires two's complement integer.
00307             //
00308             if (exponential_counter_period != 1)
00309             {
00310                 // likely (~50%)
00311                 // The decrement is delayed one cycle.
00312                 envelope_pipeline = true;
00313                 return;
00314             }
00315 
00316             -- envelope_counter;
00317             break;
00318         }
00319 
00320         // Check for change of exponential counter period.
00321         set_exponential_counter();
00322     }
00323 }
00324 
00325 } // namespace reSIDfp
00326 
00327 #endif
00328 
00329 #endif