]> git.sesse.net Git - nageru/blob - filter.h
Let settings follow buses when editing the mapping.
[nageru] / filter.h
1 // Filter class:
2 // a cascaded biquad IIR filter
3 //
4 // Special cases for type=LPF/BPF/HPF:
5 //
6 //   Butterworth filter:    order=1, resonance=1/sqrt(2)
7 //   Linkwitz-Riley filter: order=2, resonance=1/2
8
9 #ifndef _FILTER_H
10 #define _FILTER_H 1
11
12 #define _USE_MATH_DEFINES
13 #include <math.h>
14 #include <string.h>
15 #include <complex>
16
17 #ifdef __SSE__
18 #include <xmmintrin.h>
19 #endif
20
21 #include "defs.h"
22
23 namespace std {
24 template <typename _Tp> struct complex;
25 }  // namespace std
26
27 enum FilterType
28 {
29         FILTER_NONE = 0,
30         FILTER_LPF,
31         FILTER_HPF,
32         FILTER_BPF,
33         FILTER_NOTCH,
34         FILTER_APF,
35
36         // EQ filters.
37         FILTER_PEAKING_EQ,
38         FILTER_LOW_SHELF,
39         FILTER_HIGH_SHELF,
40 };
41
42 #define FILTER_MAX_ORDER 4
43
44 class Filter  
45 {
46         friend class StereoFilter;
47         friend class SplittingStereoFilter;
48 public:
49         Filter();
50         
51         void init(FilterType type, int new_order);
52
53         void update(); //update coefficients
54 #ifndef NDEBUG
55         void debug();
56 #endif
57         std::complex<double> evaluate_transfer_function(float omega);
58
59         FilterType get_type()                   { return filtertype; }
60         unsigned get_order()                    { return filter_order; }
61
62         // cutoff is taken to be in the [0..pi> (see set_linear_cutoff, below).
63         void render(float *inout_array, unsigned int buf_size, float cutoff, float resonance);
64
65         // Set cutoff, from [0..pi> (where pi is the Nyquist frequency).
66         // Overridden by render() if you use that.
67         void set_linear_cutoff(float new_omega)
68         {
69                 omega = new_omega;
70         }
71
72         void set_resonance(float new_resonance)
73         {
74                 resonance = new_resonance;
75         }
76
77         // For EQ filters only.
78         void set_dbgain_normalized(float db_gain_div_40)
79         {
80                 A = pow(10.0f, db_gain_div_40);
81         }
82
83 #ifdef __SSE__
84         // We don't need the stride argument for SSE, as StereoFilter
85         // has its own SSE implementations.
86         void render_chunk(float *inout_buf, unsigned nSamples);
87 #else
88         void render_chunk(float *inout_buf, unsigned nSamples, unsigned stride = 1);
89 #endif
90
91         FilterType filtertype;
92 private:
93         float omega; //which is 2*Pi*frequency /SAMPLE_RATE
94         float resonance;
95         float A;  // which is 10^(db_gain / 40)
96
97 public:
98         unsigned filter_order;
99 private:
100         float b0, b1, b2, a1, a2; //filter coefs
101
102         struct FeedbackBuffer {
103                 float d0,d1; //feedback buffers
104         } feedback[FILTER_MAX_ORDER];
105
106         void calcSinCos(float omega, float *sinVal, float *cosVal)
107         {
108                 *sinVal = (float)sin(omega);
109                 *cosVal = (float)cos(omega);
110         }
111 };
112
113
114 class StereoFilter
115 {
116 public:
117         void init(FilterType type, int new_order);
118         
119         void render(float *inout_left_ptr, unsigned n_samples, float cutoff, float resonance, float dbgain_normalized = 0.0f);
120 #ifndef NDEBUG
121 #ifdef __SSE__
122         void debug() { parm_filter.debug(); }
123 #else
124         void debug() { filters[0].debug(); }
125 #endif
126 #endif
127 #ifdef __SSE__
128         FilterType get_type() { return parm_filter.get_type(); }
129 #else
130         FilterType get_type() { return filters[0].get_type(); }
131 #endif
132
133 private:
134 #ifdef __SSE__
135         // We only use the filter to calculate coefficients; we don't actually
136         // use its feedbacks.
137         Filter parm_filter;
138         struct SIMDFeedbackBuffer {
139                 __m128 d0, d1;
140         } feedback[FILTER_MAX_ORDER];
141 #else
142         Filter filters[2];
143 #endif
144 };
145
146 #endif // !defined(_FILTER_H)