home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / goattracker_2.73.zip / src / resid / extfilt.h < prev    next >
Encoding:
C/C++ Source or Header  |  2014-07-23  |  5.2 KB  |  165 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 __EXTFILT_H__
  21. #define __EXTFILT_H__
  22.  
  23. #include "siddefs.h"
  24.  
  25. // ----------------------------------------------------------------------------
  26. // The audio output stage in a Commodore 64 consists of two STC networks,
  27. // a low-pass filter with 3-dB frequency 16kHz followed by a high-pass
  28. // filter with 3-dB frequency 16Hz (the latter provided an audio equipment
  29. // input impedance of 1kOhm).
  30. // The STC networks are connected with a BJT supposedly meant to act as
  31. // a unity gain buffer, which is not really how it works. A more elaborate
  32. // model would include the BJT, however DC circuit analysis yields BJT
  33. // base-emitter and emitter-base impedances sufficiently low to produce
  34. // additional low-pass and high-pass 3dB-frequencies in the order of hundreds
  35. // of kHz. This calls for a sampling frequency of several MHz, which is far
  36. // too high for practical use.
  37. // ----------------------------------------------------------------------------
  38. class ExternalFilter
  39. {
  40. public:
  41.   ExternalFilter();
  42.  
  43.   void enable_filter(bool enable);
  44.   void set_chip_model(chip_model model);
  45.  
  46.   RESID_INLINE void clock(sound_sample Vi);
  47.   RESID_INLINE void clock(cycle_count delta_t, sound_sample Vi);
  48.   void reset();
  49.  
  50.   // Audio output (20 bits).
  51.   RESID_INLINE sound_sample output();
  52.  
  53. protected:
  54.   // Filter enabled.
  55.   bool enabled;
  56.  
  57.   // Maximum mixer DC offset.
  58.   sound_sample mixer_DC;
  59.  
  60.   // State of filters.
  61.   sound_sample Vlp; // lowpass
  62.   sound_sample Vhp; // highpass
  63.   sound_sample Vo;
  64.  
  65.   // Cutoff frequencies.
  66.   sound_sample w0lp;
  67.   sound_sample w0hp;
  68.  
  69. friend class SID;
  70. };
  71.  
  72.  
  73. // ----------------------------------------------------------------------------
  74. // Inline functions.
  75. // The following functions are defined inline because they are called every
  76. // time a sample is calculated.
  77. // ----------------------------------------------------------------------------
  78.  
  79. #if RESID_INLINING || defined(__EXTFILT_CC__)
  80.  
  81. // ----------------------------------------------------------------------------
  82. // SID clocking - 1 cycle.
  83. // ----------------------------------------------------------------------------
  84. RESID_INLINE
  85. void ExternalFilter::clock(sound_sample Vi)
  86. {
  87.   // This is handy for testing.
  88.   if (!enabled) {
  89.     // Remove maximum DC level since there is no filter to do it.
  90.     Vlp = Vhp = 0;
  91.     Vo = Vi - mixer_DC;
  92.     return;
  93.   }
  94.  
  95.   // delta_t is converted to seconds given a 1MHz clock by dividing
  96.   // with 1 000 000.
  97.  
  98.   // Calculate filter outputs.
  99.   // Vo  = Vlp - Vhp;
  100.   // Vlp = Vlp + w0lp*(Vi - Vlp)*delta_t;
  101.   // Vhp = Vhp + w0hp*(Vlp - Vhp)*delta_t;
  102.  
  103.   sound_sample dVlp = (w0lp >> 8)*(Vi - Vlp) >> 12;
  104.   sound_sample dVhp = w0hp*(Vlp - Vhp) >> 20;
  105.   Vo = Vlp - Vhp;
  106.   Vlp += dVlp;
  107.   Vhp += dVhp;
  108. }
  109.  
  110. // ----------------------------------------------------------------------------
  111. // SID clocking - delta_t cycles.
  112. // ----------------------------------------------------------------------------
  113. RESID_INLINE
  114. void ExternalFilter::clock(cycle_count delta_t,
  115.          sound_sample Vi)
  116. {
  117.   // This is handy for testing.
  118.   if (!enabled) {
  119.     // Remove maximum DC level since there is no filter to do it.
  120.     Vlp = Vhp = 0;
  121.     Vo = Vi - mixer_DC;
  122.     return;
  123.   }
  124.  
  125.   // Maximum delta cycles for the external filter to work satisfactorily
  126.   // is approximately 8.
  127.   cycle_count delta_t_flt = 8;
  128.  
  129.   while (delta_t) {
  130.     if (delta_t < delta_t_flt) {
  131.       delta_t_flt = delta_t;
  132.     }
  133.  
  134.     // delta_t is converted to seconds given a 1MHz clock by dividing
  135.     // with 1 000 000.
  136.  
  137.     // Calculate filter outputs.
  138.     // Vo  = Vlp - Vhp;
  139.     // Vlp = Vlp + w0lp*(Vi - Vlp)*delta_t;
  140.     // Vhp = Vhp + w0hp*(Vlp - Vhp)*delta_t;
  141.  
  142.     sound_sample dVlp = (w0lp*delta_t_flt >> 8)*(Vi - Vlp) >> 12;
  143.     sound_sample dVhp = w0hp*delta_t_flt*(Vlp - Vhp) >> 20;
  144.     Vo = Vlp - Vhp;
  145.     Vlp += dVlp;
  146.     Vhp += dVhp;
  147.  
  148.     delta_t -= delta_t_flt;
  149.   }
  150. }
  151.  
  152.  
  153. // ----------------------------------------------------------------------------
  154. // Audio output (19.5 bits).
  155. // ----------------------------------------------------------------------------
  156. RESID_INLINE
  157. sound_sample ExternalFilter::output()
  158. {
  159.   return Vo;
  160. }
  161.  
  162. #endif // RESID_INLINING || defined(__EXTFILT_CC__)
  163.  
  164. #endif // not __EXTFILT_H__
  165.