]> git.sesse.net Git - nageru/blob - filter.h
Move the R128 and correlation measurements into AudioMixer.
[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
37 #define FILTER_MAX_ORDER 4
38
39 class Filter  
40 {
41         friend class StereoFilter;
42         friend class SplittingStereoFilter;
43 public:
44         Filter();
45         
46         void init(FilterType type, int new_order);
47
48         void update(); //update coefficients
49 #ifndef NDEBUG
50         void debug();
51 #endif
52         std::complex<double> evaluate_transfer_function(float omega);
53
54         FilterType get_type()                   { return filtertype; }
55         unsigned get_order()                    { return filter_order; }
56
57         // cutoff is taken to be in the [0..pi> (see set_linear_cutoff, below).
58         void render(float *inout_array, unsigned int buf_size, float cutoff, float resonance);
59
60         // Set cutoff, from [0..pi> (where pi is the Nyquist frequency).
61         // Overridden by render() if you use that.
62         void set_linear_cutoff(float new_omega)
63         {
64                 omega = new_omega;
65         }
66
67         void set_resonance(float new_resonance)
68         {
69                 resonance = new_resonance;
70         }
71
72 #ifdef __SSE__
73         // We don't need the stride argument for SSE, as StereoFilter
74         // has its own SSE implementations.
75         void render_chunk(float *inout_buf, unsigned nSamples);
76 #else
77         void render_chunk(float *inout_buf, unsigned nSamples, unsigned stride = 1);
78 #endif
79
80         FilterType filtertype;
81 private:
82         float omega; //which is 2*Pi*frequency /SAMPLE_RATE
83         float resonance;
84
85 public:
86         unsigned filter_order;
87 private:
88         float b0, b1, b2, a1, a2; //filter coefs
89
90         struct FeedbackBuffer {
91                 float d0,d1; //feedback buffers
92         } feedback[FILTER_MAX_ORDER];
93
94         void calcSinCos(float omega, float *sinVal, float *cosVal)
95         {
96                 *sinVal = (float)sin(omega);
97                 *cosVal = (float)cos(omega);
98         }
99 };
100
101
102 class StereoFilter
103 {
104 public:
105         void init(FilterType type, int new_order);
106         
107         void render(float *inout_left_ptr, unsigned n_samples, float cutoff, float resonance);
108 #ifndef NDEBUG
109 #ifdef __SSE__
110         void debug() { parm_filter.debug(); }
111 #else
112         void debug() { filters[0].debug(); }
113 #endif
114 #endif
115 #ifdef __SSE__
116         FilterType get_type() { return parm_filter.get_type(); }
117 #else
118         FilterType get_type() { return filters[0].get_type(); }
119 #endif
120
121 private:
122 #ifdef __SSE__
123         // We only use the filter to calculate coefficients; we don't actually
124         // use its feedbacks.
125         Filter parm_filter;
126         struct SIMDFeedbackBuffer {
127                 __m128 d0, d1;
128         } feedback[FILTER_MAX_ORDER];
129 #else
130         Filter filters[2];
131 #endif
132 };
133
134 #endif // !defined(_FILTER_H)