home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / goattracker_2.65.zip / src / resid / envelope.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-03-19  |  9.2 KB  |  306 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.  
  20. #ifndef __ENVELOPE_H__
  21. #define __ENVELOPE_H__
  22.  
  23. #include "siddefs.h"
  24.  
  25. // ----------------------------------------------------------------------------
  26. // A 15 bit counter is used to implement the envelope rates, in effect
  27. // dividing the clock to the envelope counter by the currently selected rate
  28. // period.
  29. // In addition, another counter is used to implement the exponential envelope
  30. // decay, in effect further dividing the clock to the envelope counter.
  31. // The period of this counter is set to 1, 2, 4, 8, 16, 30 at the envelope
  32. // counter values 255, 93, 54, 26, 14, 6, respectively.
  33. // ----------------------------------------------------------------------------
  34. class EnvelopeGenerator
  35. {
  36. public:
  37.   EnvelopeGenerator();
  38.  
  39.   enum State { ATTACK, DECAY_SUSTAIN, RELEASE };
  40.  
  41.   RESID_INLINE void clock();
  42.   RESID_INLINE void clock(cycle_count delta_t);
  43.   void reset();
  44.  
  45.   void writeCONTROL_REG(reg8);
  46.   void writeATTACK_DECAY(reg8);
  47.   void writeSUSTAIN_RELEASE(reg8);
  48.   reg8 readENV();
  49.  
  50.   // 8-bit envelope output.
  51.   RESID_INLINE reg8 output();
  52.  
  53. protected:
  54.   reg16 rate_counter;
  55.   reg16 rate_period;
  56.   reg8 exponential_counter;
  57.   reg8 exponential_counter_period;
  58.   reg8 envelope_counter;
  59.   bool hold_zero;
  60.  
  61.   reg4 attack;
  62.   reg4 decay;
  63.   reg4 sustain;
  64.   reg4 release;
  65.  
  66.   reg8 gate;
  67.  
  68.   State state;
  69.  
  70.   // Lookup table to convert from attack, decay, or release value to rate
  71.   // counter period.
  72.   static reg16 rate_counter_period[];
  73.  
  74.   // The 16 selectable sustain levels.
  75.   static reg8 sustain_level[];
  76.  
  77. friend class SID;
  78. };
  79.  
  80.  
  81. // ----------------------------------------------------------------------------
  82. // Inline functions.
  83. // The following functions are defined inline because they are called every
  84. // time a sample is calculated.
  85. // ----------------------------------------------------------------------------
  86.  
  87. #if RESID_INLINING || defined(__ENVELOPE_CC__)
  88.  
  89. // ----------------------------------------------------------------------------
  90. // SID clocking - 1 cycle.
  91. // ----------------------------------------------------------------------------
  92. RESID_INLINE
  93. void EnvelopeGenerator::clock()
  94. {
  95.   // Check for ADSR delay bug.
  96.   // If the rate counter comparison value is set below the current value of the
  97.   // rate counter, the counter will continue counting up until it wraps around
  98.   // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the
  99.   // envelope can finally be stepped.
  100.   // This has been verified by sampling ENV3.
  101.   //
  102.   if (++rate_counter & 0x8000) {
  103.     ++rate_counter &= 0x7fff;
  104.   }
  105.  
  106.   if (rate_counter != rate_period) {
  107.     return;
  108.   }
  109.  
  110.   rate_counter = 0;
  111.  
  112.   // The first envelope step in the attack state also resets the exponential
  113.   // counter. This has been verified by sampling ENV3.
  114.   //
  115.   if (state == ATTACK || ++exponential_counter == exponential_counter_period)
  116.   {
  117.     exponential_counter = 0;
  118.  
  119.     // Check whether the envelope counter is frozen at zero.
  120.     if (hold_zero) {
  121.       return;
  122.     }
  123.  
  124.     switch (state) {
  125.     case ATTACK:
  126.       // The envelope counter can flip from 0xff to 0x00 by changing state to
  127.       // release, then to attack. The envelope counter is then frozen at
  128.       // zero; to unlock this situation the state must be changed to release,
  129.       // then to attack. This has been verified by sampling ENV3.
  130.       //
  131.       ++envelope_counter &= 0xff;
  132.       if (envelope_counter == 0xff) {
  133.   state = DECAY_SUSTAIN;
  134.   rate_period = rate_counter_period[decay];
  135.       }
  136.       break;
  137.     case DECAY_SUSTAIN:
  138.       if (envelope_counter != sustain_level[sustain]) {
  139.   --envelope_counter;
  140.       }
  141.       break;
  142.     case RELEASE:
  143.       // The envelope counter can flip from 0x00 to 0xff by changing state to
  144.       // attack, then to release. The envelope counter will then continue
  145.       // counting down in the release state.
  146.       // This has been verified by sampling ENV3.
  147.       // NB! The operation below requires two's complement integer.
  148.       //
  149.       --envelope_counter &= 0xff;
  150.       break;
  151.     }
  152.     
  153.     // Check for change of exponential counter period.
  154.     switch (envelope_counter) {
  155.     case 0xff:
  156.       exponential_counter_period = 1;
  157.       break;
  158.     case 0x5d:
  159.       exponential_counter_period = 2;
  160.       break;
  161.     case 0x36:
  162.       exponential_counter_period = 4;
  163.       break;
  164.     case 0x1a:
  165.       exponential_counter_period = 8;
  166.       break;
  167.     case 0x0e:
  168.       exponential_counter_period = 16;
  169.       break;
  170.     case 0x06:
  171.       exponential_counter_period = 30;
  172.       break;
  173.     case 0x00:
  174.       exponential_counter_period = 1;
  175.  
  176.       // When the envelope counter is changed to zero, it is frozen at zero.
  177.       // This has been verified by sampling ENV3.
  178.       hold_zero = true;
  179.       break;
  180.     }
  181.   }
  182. }
  183.  
  184.  
  185. // ----------------------------------------------------------------------------
  186. // SID clocking - delta_t cycles.
  187. // ----------------------------------------------------------------------------
  188. RESID_INLINE
  189. void EnvelopeGenerator::clock(cycle_count delta_t)
  190. {
  191.   // Check for ADSR delay bug.
  192.   // If the rate counter comparison value is set below the current value of the
  193.   // rate counter, the counter will continue counting up until it wraps around
  194.   // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the
  195.   // envelope can finally be stepped.
  196.   // This has been verified by sampling ENV3.
  197.   //
  198.  
  199.   // NB! This requires two's complement integer.
  200.   int rate_step = rate_period - rate_counter;
  201.   if (rate_step <= 0) {
  202.     rate_step += 0x7fff;
  203.   }
  204.  
  205.   while (delta_t) {
  206.     if (delta_t < rate_step) {
  207.       rate_counter += delta_t;
  208.       if (rate_counter & 0x8000) {
  209.   ++rate_counter &= 0x7fff;
  210.       }
  211.       return;
  212.     }
  213.  
  214.     rate_counter = 0;
  215.     delta_t -= rate_step;
  216.  
  217.     // The first envelope step in the attack state also resets the exponential
  218.     // counter. This has been verified by sampling ENV3.
  219.     //
  220.     if (state == ATTACK || ++exponential_counter == exponential_counter_period)
  221.     {
  222.       exponential_counter = 0;
  223.  
  224.       // Check whether the envelope counter is frozen at zero.
  225.       if (hold_zero) {
  226.   rate_step = rate_period;
  227.   continue;
  228.       }
  229.  
  230.       switch (state) {
  231.       case ATTACK:
  232.   // The envelope counter can flip from 0xff to 0x00 by changing state to
  233.   // release, then to attack. The envelope counter is then frozen at
  234.   // zero; to unlock this situation the state must be changed to release,
  235.   // then to attack. This has been verified by sampling ENV3.
  236.   //
  237.   ++envelope_counter &= 0xff;
  238.   if (envelope_counter == 0xff) {
  239.     state = DECAY_SUSTAIN;
  240.     rate_period = rate_counter_period[decay];
  241.   }
  242.   break;
  243.       case DECAY_SUSTAIN:
  244.   if (envelope_counter != sustain_level[sustain]) {
  245.     --envelope_counter;
  246.   }
  247.   break;
  248.       case RELEASE:
  249.   // The envelope counter can flip from 0x00 to 0xff by changing state to
  250.   // attack, then to release. The envelope counter will then continue
  251.   // counting down in the release state.
  252.   // This has been verified by sampling ENV3.
  253.   // NB! The operation below requires two's complement integer.
  254.   //
  255.   --envelope_counter &= 0xff;
  256.   break;
  257.       }
  258.  
  259.       // Check for change of exponential counter period.
  260.       switch (envelope_counter) {
  261.       case 0xff:
  262.   exponential_counter_period = 1;
  263.   break;
  264.       case 0x5d:
  265.   exponential_counter_period = 2;
  266.   break;
  267.       case 0x36:
  268.   exponential_counter_period = 4;
  269.   break;
  270.       case 0x1a:
  271.   exponential_counter_period = 8;
  272.   break;
  273.       case 0x0e:
  274.   exponential_counter_period = 16;
  275.   break;
  276.       case 0x06:
  277.   exponential_counter_period = 30;
  278.   break;
  279.       case 0x00:
  280.   exponential_counter_period = 1;
  281.  
  282.   // When the envelope counter is changed to zero, it is frozen at zero.
  283.   // This has been verified by sampling ENV3.
  284.   hold_zero = true;
  285.   break;
  286.       }
  287.     }
  288.  
  289.     rate_step = rate_period;
  290.   }
  291. }
  292.  
  293.  
  294. // ----------------------------------------------------------------------------
  295. // Read the envelope generator output.
  296. // ----------------------------------------------------------------------------
  297. RESID_INLINE
  298. reg8 EnvelopeGenerator::output()
  299. {
  300.   return envelope_counter;
  301. }
  302.  
  303. #endif // RESID_INLINING || defined(__ENVELOPE_CC__)
  304.  
  305. #endif // not __ENVELOPE_H__
  306.