|
13 | 13 | #ifndef LOWPASS_H_ |
14 | 14 | #define LOWPASS_H_ |
15 | 15 |
|
16 | | -#include "IntegerType.h" |
17 | | -#include "AudioOutput.h" |
18 | | - |
19 | | - |
20 | | - |
21 | | -/* |
22 | | -simple resonant filter posted to musicdsp.org by Paul Kellett |
23 | | -http://www.musicdsp.org/archive.php?classid=3#259 |
24 | | -
|
25 | | -Two versions are available: LowPassFilter and LowPassFilter16. |
26 | | -LowPassFilter is an optimized version that uses 8bits values to set |
27 | | -the resonance and the cutoff_freq. It can works on 8bits samples only |
28 | | -on 8bits platforms. |
29 | | -LowPassFilter16 consumes more CPU ressources but uses 16bits values |
30 | | -for resonance and cutoff_freq and can work on samples up to 16bits on |
31 | | -8bits platforms and up to 32 on 32bits platforms. |
32 | | -
|
33 | | -// set feedback amount given f and q between 0 and 1 |
34 | | -fb = q + q/(1.0 - f); |
35 | | -In order to avoid a slow division we use the use a Taylor expansion to approximate 1/(1.0 - f): |
36 | | -Close to f=0: 1/(1.0-f) approx 1.0+f. |
37 | | -Hence: fb = q + q * (1.0 + f) |
38 | | -This approximation is less and less valid with an increasing cutoff, leading to a reduction of the resonance of the filter at high cutoff frequencies. |
39 | | -
|
40 | | -// for each sample... |
41 | | -buf0 = buf0 + f * (in - buf0 + fb * (buf0 - buf1)); |
42 | | -buf1 = buf1 + f * (buf0 - buf1); |
43 | | -out = buf1; |
44 | | -
|
45 | | -fixed point version of the filter |
46 | | -"dave's blog of art and programming" http://www.pawfal.org/dave/blog/2011/09/ |
47 | | -*/ |
48 | | - |
49 | | -// we are using .n fixed point (n bits for the fractional part) |
50 | | -//#define FX_SHIFT 8 |
51 | | -//#define SHIFTED_1 ((uint8_t)255) |
52 | | - |
53 | | -/** A resonant low pass filter for audio signals. |
54 | | - */ |
55 | | -template<typename su=uint8_t> |
56 | | -class LowPassFilterNbits |
57 | | -{ |
58 | | - |
59 | | -public: |
60 | | - /** Constructor. |
61 | | - */ |
62 | | - LowPassFilterNbits() { ; } |
63 | | - |
64 | | - |
65 | | - /** deprecated. Use setCutoffFreqAndResonance(su cutoff, su |
66 | | - resonance). |
67 | | -
|
68 | | - Set the cut off frequency, |
69 | | - @param cutoff use the range 0-255 to represent 0-8191 Hz (AUDIO_RATE/2) for LowPassFilter, cutoff use the range 0-65535 to represent 0-AUDIO_RATE/2. |
70 | | - Be careful of distortion at the lower end, especially with high resonance. |
71 | | - */ |
72 | | - void setCutoffFreq(su cutoff) |
73 | | - { |
74 | | - f = cutoff; |
75 | | - fb = q + ucfxmul(q, (typename IntegerType<sizeof(su)+sizeof(su)>::unsigned_type) SHIFTED_1 + cutoff); |
76 | | - } |
77 | | - |
78 | | - /** deprecated. Use setCutoffFreqAndResonance(su cutoff, su |
79 | | - resonance). |
80 | | -
|
81 | | - Set the resonance. If you hear unwanted distortion, back off the resonance. |
82 | | - After setting resonance, you need to call setCuttoffFreq() to hear the change! |
83 | | - @param resonance in the range 0-255 for LowPassFilter, 0-65535 for LowPassFilter16, with 255/65535 being most resonant |
84 | | - @note Remember to call setCuttoffFreq() after resonance is changed! |
85 | | - */ |
86 | | - void setResonance(su resonance) { q = resonance; } |
87 | | - |
88 | | - /** |
89 | | - Set the cut off frequency and resonance. Replaces setCutoffFreq() and |
90 | | - setResonance(). (Because the internal calculations need to be done whenever either parameter changes.) |
91 | | - @param cutoff range 0-255 represents 0-8191 Hz (AUDIO_RATE/2) for LowPassFilter, range 0-65535 for LowPassFilter16 |
92 | | - Be careful of distortion at the lower end, especially with high resonance. |
93 | | - @param resonance range 0-255 for LowPassFilter, 0-65535 for LowPassFilter16, 255/65535 is most resonant. |
94 | | - */ |
95 | | - void setCutoffFreqAndResonance(su cutoff, su resonance) |
96 | | - { |
97 | | - f = cutoff; |
98 | | - q = resonance; // hopefully optimised away when compiled, just here for |
99 | | - // backwards compatibility |
100 | | - fb = q + ucfxmul(q,(typename IntegerType<sizeof(su)+sizeof(su)>::unsigned_type) SHIFTED_1 + cutoff); |
101 | | - } |
102 | | - |
103 | | - /** Calculate the next sample, given an input signal. |
104 | | - @param in the signal input. Should not be more than 8bits on 8bits platforms (Arduino) if using LowPassFilter and not LowPassFilter16. |
105 | | - @return the signal output. |
106 | | - @note Timing: about 11us. |
107 | | - */ |
108 | | - // 10.5 to 12.5 us, mostly 10.5 us (was 14us) |
109 | | - inline AudioOutputStorage_t next(AudioOutputStorage_t in) |
110 | | - { |
111 | | - // setPin13High(); |
112 | | - buf0 += fxmul(((in - buf0) + fxmul(fb, buf0 - buf1)), f); |
113 | | - buf1 += ifxmul(buf0 - buf1, f); // could overflow if input changes fast |
114 | | - return buf1; |
115 | | - } |
116 | | - |
117 | | -private: |
118 | | - su q; |
119 | | - su f; |
120 | | - typename IntegerType<sizeof(su)+sizeof(su)>::unsigned_type fb; |
121 | | - AudioOutputStorage_t buf0, buf1; |
122 | | - const uint8_t FX_SHIFT = sizeof(su) << 3; |
123 | | - const uint8_t FX_SHIFT_M_1 = FX_SHIFT-1; |
124 | | - const su SHIFTED_1 = (1<<FX_SHIFT)-1; |
125 | | - |
126 | | - // // multiply two fixed point numbers (returns fixed point) |
127 | | - // inline |
128 | | - // long fxmul(long a, long b) |
129 | | - // { |
130 | | - // return (a*b)>>FX_SHIFT; |
131 | | - // } |
132 | | - |
133 | | - // multiply two fixed point numbers (returns fixed point) |
134 | | - inline typename IntegerType<sizeof(su)+sizeof(su)>::unsigned_type ucfxmul(su a, typename IntegerType<sizeof(su)+sizeof(su)>::unsigned_type b) |
135 | | - { |
136 | | - return (((typename IntegerType<sizeof(su)+sizeof(su)>::unsigned_type)a * (b >> 1)) >> (FX_SHIFT_M_1)); |
137 | | - } |
138 | | - |
139 | | - // multiply two fixed point numbers (returns fixed point) |
140 | | - inline typename IntegerType<sizeof(AudioOutputStorage_t)+sizeof(su)-1>::signed_type ifxmul(typename IntegerType<sizeof(AudioOutputStorage_t )+sizeof(su)-1>::signed_type a, su b) { return ((a * b) >> FX_SHIFT); } |
141 | | - |
142 | | - // multiply two fixed point numbers (returns fixed point) |
143 | | - inline typename IntegerType<sizeof(AudioOutputStorage_t)+sizeof(AudioOutputStorage_t)>::signed_type fxmul(typename IntegerType<sizeof(AudioOutputStorage_t)+sizeof(AudioOutputStorage_t)>::signed_type a, typename IntegerType<sizeof(AudioOutputStorage_t)+sizeof(su)-1>::signed_type b) { return ((a * b) >> FX_SHIFT); } |
144 | | -}; |
145 | | - |
146 | | -typedef LowPassFilterNbits<> LowPassFilter; |
147 | | -typedef LowPassFilterNbits<uint16_t> LowPassFilter16; |
148 | | - |
149 | | - |
150 | | -/** |
151 | | -@example 10.Audio_Filters/LowPassFilter/LowPassFilter.ino |
152 | | -This example demonstrates the LowPassFilter class. |
153 | | -
|
154 | | -@example 10.Audio_Filters/LowPassFilter/LowPassFilter16.ino |
155 | | -This example demonstrates the LowPassFilter16 class. |
156 | | -*/ |
| 16 | +#include<ResonantFilter.h> |
| 17 | +#warning This header is deprecated, please use ResonantFilter.h instead. |
157 | 18 |
|
158 | 19 | #endif /* LOWPASS_H_ */ |
0 commit comments