home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / goattracker_2.68.zip / src / resid / envelope.h < prev    next >
C/C++ Source or Header  |  2009-01-03  |  10KB  |  310 lines

  1. //  ---------------------------------------------------------------------------
  2. //  This file is part of reSID, a MOS6581 SID emulator engine.
  3. //  Copyright (C) 2004  Dag Lem <resid@nimrod.no>
  4. //
  5. //  This program is free software; you can redistribute it and/or modify
  6. //  it under the terms of the GNU General Public License as published by
  7. //  the Free Software Foundation; either version 2 of the License, or
  8. //  (at your option) any later version.
  9. //
  10. //  This program is distributed in the hope that it will be useful,
  11. //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //  GNU General Public License for more details.
  14. //
  15. //  You should have received a copy of the GNU General Public License
  16. //  along with this program; if not, write to the Free Software
  17. //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18. //  ---------------------------------------------------------------------------
  19. // C64 DTV modifications written by
  20. //   Daniel Kahlin <daniel@kahlin.net>
  21. // Copyright (C) 2007  Daniel Kahlin <daniel@kahlin.net>
  22.  
  23. #ifndef __ENVELOPE_H__
  24. #define __ENVELOPE_H__
  25.  
  26. #include "siddefs.h"
  27.  
  28. // ----------------------------------------------------------------------------
  29. // A 15 bit counter is used to implement the envelope rates, in effect
  30. // dividing the clock to the envelope counter by the currently selected rate
  31. // period.
  32. // In addition, another counter is used to implement the exponential envelope
  33. // decay, in effect further dividing the clock to the envelope counter.
  34. // The period of this counter is set to 1, 2, 4, 8, 16, 30 at the envelope
  35. // counter values 255, 93, 54, 26, 14, 6, respectively.
  36. // ----------------------------------------------------------------------------
  37. class EnvelopeGenerator
  38. {
  39. public:
  40.   EnvelopeGenerator();
  41.  
  42.   enum State { ATTACK, DECAY_SUSTAIN, RELEASE };
  43.  
  44.   RESID_INLINE void clock();
  45.   RESID_INLINE void clock(cycle_count delta_t);
  46.   void reset();
  47.  
  48.   void writeCONTROL_REG(reg8);
  49.   void writeATTACK_DECAY(reg8);
  50.   void writeSUSTAIN_RELEASE(reg8);
  51.   reg8 readENV();
  52.   void writeENV(reg8);
  53.  
  54.   // 8-bit envelope output.
  55.   RESID_INLINE reg8 output();
  56.  
  57. protected:
  58.   reg16 rate_counter;
  59.   reg16 rate_period;
  60.   reg8 exponential_counter;
  61.   reg8 exponential_counter_period;
  62.   reg8 envelope_counter;
  63.   bool hold_zero;
  64.  
  65.   reg4 attack;
  66.   reg4 decay;
  67.   reg4 sustain;
  68.   reg4 release;
  69.  
  70.   reg8 gate;
  71.  
  72.   State state;
  73.  
  74.   // Lookup table to convert from attack, decay, or release value to rate
  75.   // counter period.
  76.   static reg16 rate_counter_period[];
  77.  
  78.   // The 16 selectable sustain levels.
  79.   static reg8 sustain_level[];
  80.  
  81. friend class SID;
  82. };
  83.  
  84.  
  85. // ----------------------------------------------------------------------------
  86. // Inline functions.
  87. // The following functions are defined inline because they are called every
  88. // time a sample is calculated.
  89. // ----------------------------------------------------------------------------
  90.  
  91. #if RESID_INLINING || defined(__ENVELOPE_CC__)
  92.  
  93. // ----------------------------------------------------------------------------
  94. // SID clocking - 1 cycle.
  95. // ----------------------------------------------------------------------------
  96. RESID_INLINE
  97. void EnvelopeGenerator::clock()
  98. {
  99.   // Check for ADSR delay bug.
  100.   // If the rate counter comparison value is set below the current value of the
  101.   // rate counter, the counter will continue counting up until it wraps around
  102.   // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the
  103.   // envelope can finally be stepped.
  104.   // This has been verified by sampling ENV3.
  105.   //
  106.   if (++rate_counter & 0x8000) {
  107.     ++rate_counter &= 0x7fff;
  108.   }
  109.  
  110.   if (rate_counter != rate_period) {
  111.     return;
  112.   }
  113.  
  114.   rate_counter = 0;
  115.  
  116.   // The first envelope step in the attack state also resets the exponential
  117.   // counter. This has been verified by sampling ENV3.
  118.   //
  119.   if (state == ATTACK || ++exponential_counter == exponential_counter_period)
  120.   {
  121.     exponential_counter = 0;
  122.  
  123.     // Check whether the envelope counter is frozen at zero.
  124.     if (hold_zero) {
  125.       return;
  126.     }
  127.  
  128.     switch (state) {
  129.     case ATTACK:
  130.       // The envelope counter can flip from 0xff to 0x00 by changing state to
  131.       // release, then to attack. The envelope counter is then frozen at
  132.       // zero; to unlock this situation the state must be changed to release,
  133.       // then to attack. This has been verified by sampling ENV3.
  134.       //
  135.       ++envelope_counter &= 0xff;
  136.       if (envelope_counter == 0xff) {
  137.     state = DECAY_SUSTAIN;
  138.     rate_period = rate_counter_period[decay];
  139.       }
  140.       break;
  141.     case DECAY_SUSTAIN:
  142.       if (envelope_counter != sustain_level[sustain]) {
  143.     --envelope_counter;
  144.       }
  145.       break;
  146.     case RELEASE:
  147.       // The envelope counter can flip from 0x00 to 0xff by changing state to
  148.       // attack, then to release. The envelope counter will then continue
  149.       // counting down in the release state.
  150.       // This has been verified by sampling ENV3.
  151.       // NB! The operation below requires two's complement integer.
  152.       //
  153.       --envelope_counter &= 0xff;
  154.       break;
  155.     }
  156.     
  157.     // Check for change of exponential counter period.
  158.     switch (envelope_counter) {
  159.     case 0xff:
  160.       exponential_counter_period = 1;
  161.       break;
  162.     case 0x5d:
  163.       exponential_counter_period = 2;
  164.       break;
  165.     case 0x36:
  166.       exponential_counter_period = 4;
  167.       break;
  168.     case 0x1a:
  169.       exponential_counter_period = 8;
  170.       break;
  171.     case 0x0e:
  172.       exponential_counter_period = 16;
  173.       break;
  174.     case 0x06:
  175.       exponential_counter_period = 30;
  176.       break;
  177.     case 0x00:
  178.       exponential_counter_period = 1;
  179.  
  180.       // When the envelope counter is changed to zero, it is frozen at zero.
  181.       // This has been verified by sampling ENV3.
  182.       hold_zero = true;
  183.       break;
  184.     }
  185.   }
  186. }
  187.  
  188.  
  189. // ----------------------------------------------------------------------------
  190. // SID clocking - delta_t cycles.
  191. // ----------------------------------------------------------------------------
  192. RESID_INLINE
  193. void EnvelopeGenerator::clock(cycle_count delta_t)
  194. {
  195.   // Check for ADSR delay bug.
  196.   // If the rate counter comparison value is set below the current value of the
  197.   // rate counter, the counter will continue counting up until it wraps around
  198.   // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the
  199.   // envelope can finally be stepped.
  200.   // This has been verified by sampling ENV3.
  201.   //
  202.  
  203.   // NB! This requires two's complement integer.
  204.   int rate_step = rate_period - rate_counter;
  205.   if (rate_step <= 0) {
  206.     rate_step += 0x7fff;
  207.   }
  208.  
  209.   while (delta_t) {
  210.     if (delta_t < rate_step) {
  211.       rate_counter += delta_t;
  212.       if (rate_counter & 0x8000) {
  213.     ++rate_counter &= 0x7fff;
  214.       }
  215.       return;
  216.     }
  217.  
  218.     rate_counter = 0;
  219.     delta_t -= rate_step;
  220.  
  221.     // The first envelope step in the attack state also resets the exponential
  222.     // counter. This has been verified by sampling ENV3.
  223.     //
  224.     if (state == ATTACK    || ++exponential_counter == exponential_counter_period)
  225.     {
  226.       exponential_counter = 0;
  227.  
  228.       // Check whether the envelope counter is frozen at zero.
  229.       if (hold_zero) {
  230.     rate_step = rate_period;
  231.     continue;
  232.       }
  233.  
  234.       switch (state) {
  235.       case ATTACK:
  236.     // The envelope counter can flip from 0xff to 0x00 by changing state to
  237.     // release, then to attack. The envelope counter is then frozen at
  238.     // zero; to unlock this situation the state must be changed to release,
  239.     // then to attack. This has been verified by sampling ENV3.
  240.     //
  241.     ++envelope_counter &= 0xff;
  242.     if (envelope_counter == 0xff) {
  243.       state = DECAY_SUSTAIN;
  244.       rate_period = rate_counter_period[decay];
  245.     }
  246.     break;
  247.       case DECAY_SUSTAIN:
  248.     if (envelope_counter != sustain_level[sustain]) {
  249.       --envelope_counter;
  250.     }
  251.     break;
  252.       case RELEASE:
  253.     // The envelope counter can flip from 0x00 to 0xff by changing state to
  254.     // attack, then to release. The envelope counter will then continue
  255.     // counting down in the release state.
  256.     // This has been verified by sampling ENV3.
  257.     // NB! The operation below requires two's complement integer.
  258.     //
  259.     --envelope_counter &= 0xff;
  260.     break;
  261.       }
  262.  
  263.       // Check for change of exponential counter period.
  264.       switch (envelope_counter) {
  265.       case 0xff:
  266.     exponential_counter_period = 1;
  267.     break;
  268.       case 0x5d:
  269.     exponential_counter_period = 2;
  270.     break;
  271.       case 0x36:
  272.     exponential_counter_period = 4;
  273.     break;
  274.       case 0x1a:
  275.     exponential_counter_period = 8;
  276.     break;
  277.       case 0x0e:
  278.     exponential_counter_period = 16;
  279.     break;
  280.       case 0x06:
  281.     exponential_counter_period = 30;
  282.     break;
  283.       case 0x00:
  284.     exponential_counter_period = 1;
  285.  
  286.     // When the envelope counter is changed to zero, it is frozen at zero.
  287.     // This has been verified by sampling ENV3.
  288.     hold_zero = true;
  289.     break;
  290.       }
  291.     }
  292.  
  293.     rate_step = rate_period;
  294.   }
  295. }
  296.  
  297.  
  298. // ----------------------------------------------------------------------------
  299. // Read the envelope generator output.
  300. // ----------------------------------------------------------------------------
  301. RESID_INLINE
  302. reg8 EnvelopeGenerator::output()
  303. {
  304.   return envelope_counter;
  305. }
  306.  
  307. #endif // RESID_INLINING || defined(__ENVELOPE_CC__)
  308.  
  309. #endif // not __ENVELOPE_H__
  310.