/[svn]/linuxsampler/trunk/src/engines/gig/Filter.h
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/gig/Filter.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 791 by persson, Sun Oct 16 14:50:20 2005 UTC revision 877 by persson, Sun Jun 25 13:54:17 2006 UTC
# Line 4  Line 4 
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6   *   Copyright (C) 2005 Christian Schoenebeck                              *   *   Copyright (C) 2005 Christian Schoenebeck                              *
7     *   Copyright (C) 2006 Christian Schoenebeck and Andreas Persson          *
8   *                                                                         *   *                                                                         *
9   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
10   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 28  Line 29 
29    
30  #include <gig.h>  #include <gig.h>
31    
32  #include "../common/BiquadFilter.h"  namespace LinuxSampler { namespace gig {
33    
34  // TODO: Gigasampler's "Turbo Lowpass" and "Bandreject" filters not implemented yet      class FilterBase {
35        public:
36            virtual float Apply(float x) = 0;
37            virtual void SetParameters(float f1, float f2, float scale) = 0;
38            virtual ~FilterBase() {}
39    
40            virtual void Reset() {
41                y1 = y2 = y3 = x1 = x2 = x3 = 0;
42            }
43    
44        private:
45            float y1, y2, y3;
46    
47        protected:
48            float a1, a2, a3, x1, x2, x3;
49    
50            void KillDenormal(float& f) {
51                f += 1e-18f;
52                f -= 1e-18f;
53            }
54    
55            float ApplyA(float x) {
56                float y = x - a1 * y1 - a2 * y2 - a3 * y3;
57                KillDenormal(y);
58                y3 = y2;
59                y2 = y1;
60                y1 = y;
61                return y;
62            }
63        };
64    
65  #define LSF_BW 0.9      class LowpassFilter : public FilterBase {
66  #define LSF_FB 0.9f      protected:
67            float b0;
68        public:
69            float Apply(float x) {
70                return ApplyA(b0 * x);
71            }
72    
73            void SetParameters(float f1, float f2, float scale) {
74                float f1_2 = f1 * f1;
75                b0 = f1_2 * scale;
76                a1 = f2;
77                a2 = f1_2 - 1;
78                a3 = -f2;
79            }
80        };
81    
82  namespace LinuxSampler { namespace gig {      class BandpassFilter : public FilterBase {
83            float b0, b2;
84        public:
85            float Apply(float x) {
86                float y = ApplyA(b0 * x + b2 * x2);
87                x2 = x1;
88                x1 = x;
89                return y;
90            }
91    
92            void SetParameters(float f1, float f2, float scale) {
93                b0 = f1 * scale;
94                b2 = -b0;
95                a1 = f2;
96                a2 = f1 * f1 - 1;
97                a3 = -f2;
98            }
99        };
100    
101        class HighpassFilter : public FilterBase {
102            float scale;
103        public:
104            float Apply(float x) {
105                float y = ApplyA(-x + x1 + x2 - x3);
106                x3 = x2;
107                x2 = x1;
108                x1 = x;
109                return y * scale;
110            }
111    
112            void SetParameters(float f1, float f2, float scale) {
113                a1 = f2;
114                a2 = f1 * f1 - 1;
115                a3 = -f2;
116                this->scale = scale;
117            }
118        };
119    
120        class BandrejectFilter : public FilterBase {
121            float scale, b2;
122        public:
123            float Apply(float x) {
124                float y = ApplyA(x - x1 + b2 * x2 + x3);
125                x3 = x2;
126                x2 = x1;
127                x1 = x;
128                return y * scale;
129            }
130    
131            void SetParameters(float f1, float f2, float scale) {
132                b2 = f1 * f1 - 1;
133                a1 = f2;
134                a2 = b2;
135                a3 = -f2;
136                this->scale = scale;
137            }
138        };
139    
140        class LowpassTurboFilter : public LowpassFilter {
141            float b20, y21, y22, y23;
142        public:
143            float Apply(float x) {
144                float y = b20 * LowpassFilter::Apply(x)
145                    - a1 * y21 - a2 * y22 - a3 * y23;
146                KillDenormal(y);
147                y23 = y22;
148                y22 = y21;
149                y21 = y;
150    
151                return y;
152            }
153    
154            void SetParameters(float f1, float f2, float scale) {
155                LowpassFilter::SetParameters(f1, f2, scale);
156                b20 = b0 * 0.5;
157            }
158    
159            void Reset() {
160                LowpassFilter::Reset();
161                y21 = y22 = y23 = 0;
162            }
163        };
164    
165      /**      /**
166       * These are filters similar to the ones from Gigasampler.       * These are filters similar to the ones from Gigasampler.
167       */       */
168      class Filter {      class Filter {
169          protected:          protected:
170              BandpassFilter    BasicBPFilter;              HighpassFilter     HPFilter;
171              HighpassFilter    HPFilter;              BandpassFilter     BPFilter;
172              BandpassFilter    BPFilter;              LowpassFilter      LPFilter;
173              LowpassFilter     LPFilter;              BandrejectFilter   BRFilter;
174              BiquadFilter*     pFilter;              LowpassTurboFilter LPTFilter;
175              bq_t              scale;              FilterBase*        pFilter;
             bq_t              resonance;  
             bq_t              cutoff;  
             ::gig::vcf_type_t Type;  
 #if __GNUC__ >= 4  
             float fFB;  
 #else  
             static const float fFB = LSF_FB;  
 #endif  
176    
177          public:          public:
   
178              Filter() {              Filter() {
179                  // set filter type to 'lowpass' by default                  // set filter type to 'lowpass' by default
180                  pFilter = &LPFilter;                  pFilter = &LPFilter;
                 Type    = ::gig::vcf_type_lowpass;  
 #if __GNUC__ >= 4  
                 fFB = LSF_FB;  
 #endif  
181              }              }
182    
183              inline bq_t Cutoff()     { return cutoff; }              void SetType(::gig::vcf_type_t FilterType) {
   
             inline bq_t Resonance()  { return resonance; }  
   
             inline void SetType(::gig::vcf_type_t FilterType) {  
184                  switch (FilterType) {                  switch (FilterType) {
185                      case ::gig::vcf_type_highpass:                      case ::gig::vcf_type_highpass:
186                          pFilter = &HPFilter;                          pFilter = &HPFilter;
187                          break;                          break;
188                      case ::gig::vcf_type_bandreject: //TODO: not implemented yet                      case ::gig::vcf_type_bandreject:
189                          FilterType = ::gig::vcf_type_bandpass;                          pFilter = &BRFilter;
190                            break;
191                      case ::gig::vcf_type_bandpass:                      case ::gig::vcf_type_bandpass:
192                          pFilter = &BPFilter;                          pFilter = &BPFilter;
193                          break;                          break;
194                      case ::gig::vcf_type_lowpassturbo: //TODO: not implemented yet                      case ::gig::vcf_type_lowpassturbo:
195                            pFilter = &LPTFilter;
196                            break;
197                      default:                      default:
                         FilterType = ::gig::vcf_type_lowpass;  
                     case ::gig::vcf_type_lowpass:  
198                          pFilter = &LPFilter;                          pFilter = &LPFilter;
   
                 }  
                 Type = FilterType;  
             }  
   
             inline void SetParameters(bq_t cutoff, bq_t resonance, bq_t fs) {  
                 BasicBPFilter.SetParameters(cutoff, 0.7, fs);  
                 switch (Type) {  
                     case ::gig::vcf_type_highpass:  
                         HPFilter.SetParameters(cutoff, 1.87 - resonance * 1.7526, fs);  
                         break;  
                     case ::gig::vcf_type_bandpass:  
                         BPFilter.SetParameters(cutoff, 1.87 - resonance * 1.7526, fs);  
                         break;  
                     case ::gig::vcf_type_lowpass:  
                         LPFilter.SetParameters(cutoff, 1.87 - resonance * 1.7526, fs);  
                         break;  
199                  }                  }
                 this->scale     = resonance < 0.4 ? 1.0f : 1.4f - resonance * 1.016f;  
                 this->resonance = resonance;  
                 this->cutoff    = cutoff;  
200              }              }
201    
202              inline void SetParameters(biquad_param_t* base, biquad_param_t* main, bq_t cutoff, bq_t resonance, bq_t fs) {              void SetParameters(float cutoff, float resonance, float fs) {
203                  BasicBPFilter.SetParameters(base, cutoff, 0.7, fs);                  float f1 = cutoff * 0.0075279;
204                  switch (Type) {                  float f2 = f1 - 1 + resonance * cutoff * (-5.5389e-5 + 1.1982e-7 * cutoff);
205                      case ::gig::vcf_type_highpass:                  float scale = resonance < 51 ? 1.0f : 1.3762f - 0.0075073f * resonance;
206                          HPFilter.SetParameters(main, cutoff, 1.87 - resonance * 1.7526, fs);                  pFilter->SetParameters(f1, f2, scale);
                         break;  
                     case ::gig::vcf_type_bandpass:  
                         BPFilter.SetParameters(main, cutoff, 1.87 - resonance * 1.7526, fs);  
                         break;  
                     case ::gig::vcf_type_lowpass:  
                         LPFilter.SetParameters(main, cutoff, 1.87 - resonance * 1.7526, fs);  
                         break;  
                 }  
                 this->scale     = resonance < 0.4 ? 1.0f : 1.4f - resonance * 1.016f;  
                 this->resonance = resonance;  
                 this->cutoff    = cutoff;  
207              }              }
208    
209              void Reset() {              void Reset() {
                 BasicBPFilter.Reset();  
210                  HPFilter.Reset();                  HPFilter.Reset();
211                  BPFilter.Reset();                  BPFilter.Reset();
212                  LPFilter.Reset();                  LPFilter.Reset();
213                    BRFilter.Reset();
214                    LPTFilter.Reset();
215              }              }
216    
217              inline bq_t Apply(const bq_t in) {              float Apply(float in) {
218                  return pFilter->Apply(in) * this->scale;                  return pFilter->Apply(in);
                 // + BasicBPFilter.ApplyFB(in, this->resonance * LSF_FB) * this->resonance;  
219              }              }
   
             inline bq_t Apply(biquad_param_t* base, biquad_param_t* main, const bq_t in) {  
                 return pFilter->Apply(main, in) * this->scale;  
                 // + BasicBPFilter.ApplyFB(base, in, this->resonance * LSF_FB) * this->resonance;  
             }  
   
 #if CONFIG_ASM && ARCH_X86  
             // expects to find input in xmm0 and leaves output in xmm7  
             inline void Apply4StepsSSE(biquad_param_t* base, biquad_param_t* main) {  
                 float fb;  
                 __asm__ __volatile__ (  
                     "movss %0, %%xmm4\n\t"  
                     "mulss %1, %%xmm4      # this->resonance * LSF_FB\n\t"  
                     "movss %%xmm4, %2\n\t"  
                     :: "m" (fFB),       /* %0 */  
                        "m" (resonance), /* %1 */  
                        "m" (fb)         /* %2 */  
                 );  
                 BasicBPFilter.ApplyFB4StepsSSE(base, fb); // leaves output in xmm7  
                 __asm__ __volatile__ (  
                     "movss  %0, %%xmm4\n\t"  
                     "shufps $0, %%xmm4, %%xmm4     # copy to other 3 cells\n\t"  
                     "mulps  %%xmm4, %%xmm7         # ApplyFB() * this->resonance\n\t"  
                     :: "m" (resonance) /* %0 */  
                 );  
                 pFilter->Apply4StepsSSE(main); // leaves output in xmm6  
                 __asm__ __volatile__ (  
                     "movss  %0, %%xmm5\n\t"  
                     "shufps $0, %%xmm5, %%xmm5     # copy to other 3 cells\n\t"  
                     "mulps  %%xmm5, %%xmm6         # Apply() * this->scale\n\t"  
                     "addps  %%xmm6, %%xmm7         # xmm7 = result\n\t"  
                     :: "m" (scale) /* %0 */  
                 );  
             }  
 #endif // CONFIG_ASM && ARCH_X86  
   
220      };      };
221    
222  }} //namespace LinuxSampler::gig  }} //namespace LinuxSampler::gig

Legend:
Removed from v.791  
changed lines
  Added in v.877

  ViewVC Help
Powered by ViewVC