home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / goattracker_2.68.zip / src / resid-fp / filter.cpp < prev    next >
C/C++ Source or Header  |  2009-01-03  |  5KB  |  173 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. //  Filter distortion code written by Antti S. Lankila 2007 - 2008.
  20.  
  21. #define __FILTER_CC__
  22. #include "filter.h"
  23. #include "sid.h"
  24.   
  25. // ----------------------------------------------------------------------------
  26. // Constructor.
  27. // ----------------------------------------------------------------------------
  28. FilterFP::FilterFP()
  29. {
  30.   model = (chip_model) 0; // neither 6581/8580; init time only
  31.   enable_filter(true);
  32.   /* approximate; sid.cc calls us when set_sampling_parameters() occurs. */
  33.   set_clock_frequency(1e6f);
  34.   /* these parameters are a work-in-progress. */
  35.   set_distortion_properties(2.5e-3f, 1536.f, 1e-4f);
  36.   /* sound similar to alankila6581r4ar3789 */
  37.   set_type3_properties(1.40e6f, 1.47e8f, 1.0059f, 1.55e4f);
  38.   /* sound similar to trurl8580r5_3691 */
  39.   set_type4_properties(6.55f, 20.f);
  40.   reset();
  41.   set_chip_model(MOS6581FP);
  42. }
  43.  
  44.  
  45. // ----------------------------------------------------------------------------
  46. // Enable filter.
  47. // ----------------------------------------------------------------------------
  48. void FilterFP::enable_filter(bool enable)
  49. {
  50.   enabled = enable;
  51. }
  52.  
  53.  
  54. // ----------------------------------------------------------------------------
  55. // Set chip model.
  56. // ----------------------------------------------------------------------------
  57. void FilterFP::set_chip_model(chip_model model)
  58. {
  59.     this->model = model;
  60.     set_Q();
  61.     set_w0();
  62. }
  63.  
  64. /* dist_CT eliminates 1/x at hot spot */
  65. void FilterFP::set_clock_frequency(float clock) {
  66.     clock_frequency = clock;
  67.     calculate_helpers();
  68. }
  69.  
  70. void FilterFP::set_distortion_properties(float r, float p, float cft)
  71. {
  72.     distortion_rate = r;
  73.     distortion_point = p;
  74.     /* baseresistance is used to determine material resistivity later */
  75.     distortion_cf_threshold = cft;
  76.     calculate_helpers();
  77. }
  78.  
  79. void FilterFP::set_type4_properties(float k, float b)
  80. {
  81.     type4_k = k;
  82.     type4_b = b;
  83. }
  84.  
  85. void FilterFP::set_type3_properties(float br, float o, float s, float mfr)
  86. {
  87.     type3_baseresistance = br;
  88.     type3_offset = o;
  89.     type3_steepness = -logf(s); /* s^x to e^(x*ln(s)), 1/e^x == e^-x. */
  90.     type3_minimumfetresistance = mfr;
  91. }
  92.  
  93. void FilterFP::calculate_helpers()
  94. {
  95.     if (clock_frequency != 0.f)
  96.         distortion_CT = 1.f / (sidcaps_6581 * clock_frequency);
  97.     set_w0();
  98. }
  99.  
  100. // ----------------------------------------------------------------------------
  101. // SID reset.
  102. // ----------------------------------------------------------------------------
  103. void FilterFP::reset()
  104. {
  105.   fc = 0;
  106.   res = filt = voice3off = hp_bp_lp = 0; 
  107.   vol = 0;
  108.   volf = Vhp = Vbp = Vlp = 0;
  109.   set_w0();
  110.   set_Q();
  111. }
  112.  
  113. // ----------------------------------------------------------------------------
  114. // Register functions.
  115. // ----------------------------------------------------------------------------
  116. void FilterFP::writeFC_LO(reg8 fc_lo)
  117. {
  118.   fc = (fc & 0x7f8) | (fc_lo & 0x007);
  119.   set_w0();
  120. }
  121.  
  122. void FilterFP::writeFC_HI(reg8 fc_hi)
  123. {
  124.   fc = ((fc_hi << 3) & 0x7f8) | (fc & 0x007);
  125.   set_w0();
  126. }
  127.  
  128. void FilterFP::writeRES_FILT(reg8 res_filt)
  129. {
  130.   res = (res_filt >> 4) & 0x0f;
  131.   set_Q();
  132.  
  133.   filt = res_filt & 0x0f;
  134. }
  135.  
  136. void FilterFP::writeMODE_VOL(reg8 mode_vol)
  137. {
  138.   voice3off = mode_vol & 0x80;
  139.  
  140.   hp_bp_lp = (mode_vol >> 4) & 0x07;
  141.  
  142.   vol = mode_vol & 0x0f;
  143.   volf = (float) vol / 15.f;
  144. }
  145.  
  146. // Set filter cutoff frequency.
  147. void FilterFP::set_w0()
  148. {
  149.   if (model == MOS6581FP) {
  150.     /* div once by extra kinkiness because I fitted the type3 eq with that variant. */
  151.     float type3_fc_kink = SIDFP::kinked_dac(fc, kinkiness, 11) / kinkiness;
  152.     type3_fc_kink_exp = type3_offset * expf(type3_fc_kink * type3_steepness);
  153.     if (distortion_rate != 0.f) {
  154.         type3_fc_distortion_offset_hp = (distortion_point - type3_fc_kink) * (0.5f) / distortion_rate;
  155.         type3_fc_distortion_offset_bp = type3_fc_distortion_offset_hp;
  156.     }
  157.     else {
  158.         type3_fc_distortion_offset_bp = 9e9f;
  159.         type3_fc_distortion_offset_hp = 9e9f;
  160.     }
  161.   }
  162.   if (model == MOS8580FP) {
  163.     type4_w0_cache = type4_w0();
  164.   }
  165. }
  166.  
  167. // Set filter resonance.
  168. void FilterFP::set_Q()
  169. {
  170.   float Q = res / 15.f;
  171.   _1_div_Q = 1.f / (0.707f + Q * 1.5f);
  172. }
  173.