home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / buzzmachines_massive.exe / Dev / Geoffroy Notefilter SourceCode / CookbookFilter.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-05-25  |  6.4 KB  |  256 lines

  1. // CookbookFilter.cpp: implementation of the CookbookFilter class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4.  
  5. #include "CookbookFilter.h"
  6. #include "../dsplib.h"
  7.  
  8. #define MIN_GAIN_VALUE 0.00000000001f
  9. #define LN2SUR2 0.34657359027997265470861606072909f
  10.  
  11. //////////////////////////////////////////////////////////////////////
  12. // Construction/Destruction
  13. //////////////////////////////////////////////////////////////////////
  14.  
  15. CookbookFilter::CookbookFilter()
  16. {
  17.     lx1 = lx2 = ly1 = ly2 = 0.0f;
  18.     rx1 = rx2 = ry1 = ry2 = 0.0f;
  19.     param_cutoff = 22050;
  20.     param_resonance = 0;
  21.     samplesPerSec = 44100;
  22.     type = LPF;
  23.     slope = 1.0f;
  24.     dBGain = -60.0f;
  25.     bandwidth = 0.1f;
  26.  
  27.     computeCoeffs();
  28. }
  29.  
  30. CookbookFilter::~CookbookFilter()
  31. {
  32.  
  33. }
  34.  
  35. void CookbookFilter::setGain(float gain)
  36. {
  37.     // if previous gain was 0, we have to calculate the coeffs
  38.     if (this->gain <= MIN_GAIN_VALUE) { 
  39.         this->gain = gain;
  40.         computeCoeffs();
  41.     } else {
  42.         this->gain = gain;
  43.     }
  44. }
  45.  
  46. void CookbookFilter::setSampleRate(int samplesPerSec)
  47. {
  48.     this->samplesPerSec = samplesPerSec;
  49.  
  50.     if (gain != 0.0f) computeCoeffs();
  51. }
  52.  
  53. void CookbookFilter::setFrequency(float freq) 
  54. {
  55.     this->param_cutoff = freq;
  56.  
  57.     if (gain != 0.0f) computeCoeffs();
  58. }
  59.  
  60. void CookbookFilter::setQ(float q) 
  61. {
  62.     this->param_resonance = q;
  63.  
  64.     if (gain != 0.0f) computeCoeffs();
  65. }
  66.  
  67. void CookbookFilter::setType(CookbookFilter::filtertype type)
  68. {
  69.     this->type = type;
  70.  
  71.     if (gain != 0.0f) computeCoeffs();
  72. }
  73.  
  74.  
  75. void CookbookFilter::computeCoeffs()
  76. {
  77.     float alpha, beta, omega, sn, cs;
  78.     float a0, a1, a2, b0, b1, b2;
  79.     float A;
  80.  
  81.     if (type == PEAKINGEQ || type == LOWSHELF || type == HIGHSHELF) {
  82.         A = pow(10.0f, dBGain/40.0f);
  83.     }
  84.  
  85.     omega = 2.0f * PI * param_cutoff / samplesPerSec;
  86.     sn = sin (omega); cs = cos (omega);
  87.  
  88.     /*
  89.     if (type == BPF || type == NOTCH || type == PEAKINGEQ) {
  90.         // on a bandwidth en octave au lieu de Q
  91.         param_resonance = 1.0f / (2.0f * sinh(LN2SUR2 * bandwidth * omega/sn));
  92.     } else if (type == LOWSHELF || type == HIGHSHELF) {
  93.         // on a la slope au lieu de Q
  94.         param_resonance = 1.0f / sqrt( (A+1.0f/A) * (1/slope - 1) + 2 );
  95.     }
  96.     */
  97.  
  98.  
  99.     alpha = sn / param_resonance;
  100.  
  101.     if (type == LOWSHELF || type == HIGHSHELF) {
  102.         beta  = sqrt((pow(A,2.0f) + 1.0f)/param_resonance - pow(A-1.0f,2.0f));
  103.     }        
  104.  
  105.     switch (type) {
  106.     case LPF:
  107.                 b0 =  (1.0f - cs)/2.0f;
  108.                 b1 =   1.0f - cs;
  109.                 b2 =  (1.0f - cs)/2.0f;
  110.                 a0 =   1.0f + alpha;
  111.                 a1 =  -2.0f*cs;
  112.                 a2 =   1.0f - alpha;
  113.                 break;
  114.  
  115.     case HPF:
  116.                 b0 =  (1.0f + cs)/2.0f;
  117.                 b1 = -(1.0f + cs);
  118.                 b2 =  (1.0f + cs)/2.0f;
  119.                 a0 =   1.0f + alpha;
  120.                 a1 =  -2*cs;
  121.                 a2 =   1.0f - alpha;
  122.                 break;
  123.  
  124.     case BPF:
  125.                 b0 =   param_resonance * alpha;
  126.                 b1 =   0;
  127.                 b2 =  -param_resonance * alpha;
  128.                 a0 =   1.0f + alpha;
  129.                 a1 =  -2.0f*cs;
  130.                 a2 =   1.0f - alpha;
  131. /*
  132.                 b0 =   alpha;
  133.                 b1 =   0;
  134.                 b2 =  -alpha;
  135.                 a0 =   1.0f + alpha;
  136.                 a1 =  -2.0f*cs;
  137.                 a2 =   1.0f - alpha;
  138. */
  139.                 break;
  140.  
  141.     case NOTCH:
  142.                 b0 =   1.0f;
  143.                 b1 =  -2.0f*cs;
  144.                 b2 =   1.0f;
  145.                 a0 =   1.0f + alpha;
  146.                 a1 =  -2.0f*cs;
  147.                 a2 =   1.0f - alpha;
  148.                 break;
  149.  
  150.     case PEAKINGEQ:
  151.                 b0 =   1.0f + alpha*A;
  152.                 b1 =  -2.0f*cs;
  153.                 b2 =   1.0f - alpha*A;
  154.                 a0 =   1.0f + alpha/A;
  155.                 a1 =  -2.0f*cs;
  156.                 a2 =   1.0f - alpha/A;
  157.                 break;
  158.  
  159.     case LOWSHELF:
  160.                 b0 =    A*( (A+1.0f) - (A-1.0f)*cs + beta*sn );
  161.                 b1 =  2.0f*A*( (A-1.0f) - (A+1.0f)*cs           );
  162.                 b2 =    A*( (A+1.0f) - (A-1.0f)*cs - beta*sn );
  163.                 a0 =        (A+1.0f) + (A-1.0f)*cs + beta*sn;
  164.                 a1 =   -2.0f*( (A-1.0f) + (A+1.0f)*cs);
  165.                 a2 =        (A+1.0f) + (A-1.0f)*cs - beta*sn;
  166.  
  167.     case HIGHSHELF:
  168.                 b0 =    A*( (A+1.0f) + (A-1.0f)*cs + beta*sn );
  169.                 b1 = -2.0f*A*( (A-1.0f) + (A+1.0f)*cs           );
  170.                 b2 =    A*( (A+1.0f) + (A-1.0f)*cs - beta*sn );
  171.                 a0 =        (A+1.0f) - (A-1.0f)*cs + beta*sn;
  172.                 a1 =    2.0f*( (A-1.0f) - (A+1.0f)*cs           );
  173.                 a2 =        (A+1.0f) - (A-1.0f)*cs - beta*sn;
  174.  
  175.     default:
  176.                 // zero everything
  177.                 b0 =   0;
  178.                 b1 =   0;
  179.                 b2 =   0;
  180.                 a0 =   1;
  181.                 a1 =   0;
  182.                 a2 =   0;
  183.                 break;
  184.     }
  185.     
  186.     filtCoefTab[0] = b0/a0;
  187.     filtCoefTab[1] = b1/a0;
  188.     filtCoefTab[2] = b2/a0;
  189.     filtCoefTab[3] = -a1/a0;
  190.     filtCoefTab[4] = -a2/a0;
  191. }
  192.  
  193. #define valeurabsolue(a) ((a)<0?(-a):(a))
  194.  
  195. bool CookbookFilter::MDKWorkStereo(float *psamples, int numsamples, int const mode) {
  196.     float inL, inR, outL, outR, temp_y;
  197.     int            i;
  198.  
  199.     // something is not normal, return false
  200.     if (param_cutoff < 20.0f || param_cutoff > 22000.0f || gain <= MIN_GAIN_VALUE) {
  201.         return false;
  202.     }
  203.     
  204.     for( i=0; i<numsamples*2; i++ ) {
  205.  
  206.                 inL = psamples[i];
  207.                 inR = psamples[i+1];
  208.  
  209.                 if (valeurabsolue(inL) <=MIN_GAIN_VALUE || valeurabsolue(inR) <=MIN_GAIN_VALUE) {
  210.                     continue;
  211.                 }
  212.  
  213.                 outL = inL;
  214.                 outR = inR;
  215.  
  216.                 // Left
  217.                 temp_y = filtCoefTab[0] * outL +
  218.                             filtCoefTab[1] * lx1 +
  219.                             filtCoefTab[2] * lx2 +
  220.                             filtCoefTab[3] * ly1 +
  221.                             filtCoefTab[4] * ly2;
  222.                 ly2 = ly1; ly1 = temp_y; lx2 = lx1; lx1 = outL ; outL = temp_y;
  223.  
  224.                 // Right
  225.                 temp_y = filtCoefTab[0] * outR +
  226.                             filtCoefTab[1] * rx1 +
  227.                             filtCoefTab[2] * rx2 +
  228.                             filtCoefTab[3] * ry1 +
  229.                             filtCoefTab[4] * ry2;
  230.                 ry2 = ry1; ry1 = temp_y; rx2 = rx1; rx1 = outR ; outR = temp_y;
  231.  
  232.                 psamples[i] = outL * gain;
  233.                 i++;
  234.                 psamples[i] = outR * gain;
  235.     };
  236.     return true;
  237. }
  238.  
  239. void CookbookFilter::setSlope(float slope)
  240. {
  241.     this->slope = slope;
  242.     if (gain != 0.0f) computeCoeffs();
  243. }
  244.  
  245. void CookbookFilter::setdBGain(float dBGain)
  246. {
  247.     this->dBGain = dBGain;
  248.     if (gain != 0.0f) computeCoeffs();
  249. }
  250.  
  251. void CookbookFilter::setBandwidth(float bandwidth)
  252. {
  253.     this->bandwidth = bandwidth;
  254.     if (gain != 0.0f) computeCoeffs();
  255. }
  256.