| Mozzi version v1.1.0 sound synthesis library for Arduino |

StateVariable.h
1 /*
2 * StateVariable.h
3 *
4 * This implementation copyright 2012 Tim Barrass.
5 *
6 * This file is part of Mozzi.
7 *
8 * Mozzi is licensed under a Creative Commons
9 * Attribution-NonCommercial-ShareAlike 4.0 International License.
10 *
11 */
12
13 /**
14 State Variable Filter (approximation of Chamberlin version)
15 Informed by pseudocode at http://www.musicdsp.org/showone.php?id=23 and
16 http://www.musicdsp.org/showone.php?id=142. Here's the original:
17 ---------------------
18 cutoff = cutoff freq in Hz
19 fs = sampling frequency //(e.g. 44100Hz)
20 f = 2 sin (pi * cutoff / fs) //[approximately]
21 q = resonance/bandwidth [0 < q <= 1] most res: q=1, less: q=0
22 low = lowpass output
23 high = highpass output
24 band = bandpass output
25 notch = notch output
26
27 scale = q
28
29 low=high=band=0;
30
31 //--beginloop
32 low = low + f * band;
33 high = scale * input - low - q*band;
34 band = f * high + band;
35 notch = high + low;
36 //--endloop
37 ----------------------
38 References :
39 Hal Chamberlin, Musical Applications of Microprocessors, 2nd Ed, Hayden Book
40 Company 1985. pp 490-492. Jon Dattorro, Effect Design Part 1, J. Audio Eng.
41 Soc., Vol 45, No. 9, 1997 September
42 */
43
44 #ifndef STATEVARIABLE_H_
45 #define STATEVARIABLE_H_
46
47 #include "Arduino.h"
48 #include "math.h"
49 #include "meta.h"
50 #include "mozzi_fixmath.h"
51 #include "mozzi_utils.h"
52
53 enum filter_types { LOWPASS, BANDPASS, HIGHPASS, NOTCH };
54
55 /** A State Variable filter which offers 12db resonant low, high, bandpass and
56 notch modes.
57 @tparam FILTER_TYPE choose between LOWPASS, BANDPASS, HIGHPASS and NOTCH.
58 @note To save processing time, this version of the filter does not saturate
59 internally, so any resonant peaks are unceremoniously truncated. It may be
60 worth adding code to constrain the internal variables to enable resonant
61 saturating effects.
62 @todo Try adding code to constrain the internal variables to enable resonant
63 saturating effects.
64 */
65 template <int8_t FILTER_TYPE> class StateVariable {
66
67 public:
68 /** Constructor.
69 */
70 StateVariable() {}
71
72 /** Set how resonant the filter will be.
73 @param resonance a byte value between 1 and 255.
74 The lower this value is, the more resonant the filter.
75 At very low values, the filter can output loud peaks which can exceed
76 Mozzi's output range, so you may need to attenuate the output in your sketch.
77 @note Timing < 500 ns
78 */
79 void setResonance(Q0n8 resonance) {
80 // qvalue goes from 255 to 0, representing .999 to 0 in fixed point
81 // lower q, more resonance
82 q = resonance;
83 scale = (Q0n8)sqrt((unsigned int)resonance << 8);
84 }
85
86 /** Set the centre or corner frequency of the filter.
87 @param centre_freq 20 - 4096 Hz (AUDIO_RATE/4).
88 This will be the cut-off frequency for LOWPASS and HIGHPASS, and the
89 centre frequency to pass or reduce for BANDPASS and NOTCH.
90 @note Timing 25-30us
91 @note The frequency calculation is VERY "approximate". This really needs to
92 be fixed.
93 */
94 void setCentreFreq(unsigned int centre_freq) {
95 // simple frequency tuning with error towards nyquist (reference? where did
96 // this come from?)
97 // f = (Q1n15)(((Q16n16_2PI*centre_freq)>>AUDIO_RATE_AS_LSHIFT)>>1);
98 f = (Q15n16)((Q16n16_2PI * centre_freq) >>
99 (AUDIO_RATE_AS_LSHIFT)); // this works best for now
100 // f = (Q15n16)(((Q16n16_2PI*centre_freq)<<(16-AUDIO_RATE_AS_LSHIFT))>>16);
101 // // a small shift left and a round 16 right is faster than big
102 // non-byte-aligned right in one go float ff =
103 // Q16n16_to_float(((Q16n16_PI*centre_freq))>>AUDIO_RATE_AS_LSHIFT); f =
104 // float_to_Q15n16(2.0f *sin(ff));
105 }
106
107 /** Calculate the next sample, given an input signal.
108 @param input the signal input.
109 @return the signal output.
110 @note Timing: 16 - 20 us
111 */
112 inline int next(int input) {
113 // chooses a different next() function depending on whether the
114 // filter is declared as LOWPASS, BANDPASS, HIGHPASS or NOTCH.
115 // See meta.h.
116 return next(input, Int2Type<FILTER_TYPE>());
117 }
118
119 private:
120 int low, band;
121 Q0n8 q, scale;
122 volatile Q15n16 f;
123
124 /** Calculate the next sample, given an input signal.
125 @param in the signal input.
126 @return the signal output.
127 @note Timing: 16 - 20 us
128 */
129 inline int next(int input, Int2Type<LOWPASS>) {
130 // setPin13High();
131 low += ((f * band) >> 16);
132 int high = (((long)input - low - (((long)band * q) >> 8)) * scale) >> 8;
133 band += ((f * high) >> 16);
134 // int notch = high + low;
135 // setPin13Low();
136 return low;
137 }
138
139 /** Calculate the next sample, given an input signal.
140 @param input the signal input.
141 @return the signal output.
142 @note Timing:
143 */
144 inline int next(int input, Int2Type<BANDPASS>) {
145 // setPin13High();
146 low += ((f * band) >> 16);
147 int high = (((long)input - low - (((long)band * q) >> 8)) * scale) >> 8;
148 band += ((f * high) >> 16);
149 // int notch = high + low;
150 // setPin13Low();
151 return band;
152 }
153
154 /** Calculate the next sample, given an input signal.
155 @param input the signal input.
156 @return the signal output.
157 @note Timing:
158 */
159 inline int next(int input, Int2Type<HIGHPASS>) {
160 // setPin13High();
161 low += ((f * band) >> 16);
162 int high = (((long)input - low - (((long)band * q) >> 8)) * scale) >> 8;
163 band += ((f * high) >> 16);
164 // int notch = high + low;
165 // setPin13Low();
166 return high;
167 }
168
169 /** Calculate the next sample, given an input signal.
170 @param input the signal input.
171 @return the signal output.
172 @note Timing: 16 - 20 us
173 */
174 inline int next(int input, Int2Type<NOTCH>) {
175 // setPin13High();
176 low += ((f * band) >> 16);
177 int high = (((long)input - low - (((long)band * q) >> 8)) * scale) >> 8;
178 band += ((f * high) >> 16);
179 int notch = high + low;
180 // setPin13Low();
181 return notch;
182 }
183 };
184
185 /**
186 @example 11.Audio_Filters/StateVariableFilter/StateVariableFilter.ino
187 This example demonstrates the StateVariable class.
188 */
189
190 #endif /* STATEVARIABLE_H_ */
Q15n16
int32_t Q15n16
signed fractional number using 15 integer bits and 16 fractional bits, represents -32767...
Definition: mozzi_fixmath.h:40
StateVariable::setResonance
void setResonance(Q0n8 resonance)
Set how resonant the filter will be.
Definition: StateVariable.h:79
Int2Type
Enables you to instantiate a template based on an integer value.
Definition: meta.h:20
StateVariable::StateVariable
StateVariable()
Constructor.
Definition: StateVariable.h:70
StateVariable::next
int next(int input)
Calculate the next sample, given an input signal.
Definition: StateVariable.h:112
StateVariable
A State Variable filter which offers 12db resonant low, high, bandpass and notch modes.
Definition: StateVariable.h:65
Q16n16_2PI
#define Q16n16_2PI
2*PI in Q16n16 format
Definition: mozzi_fixmath.h:69
Q0n8
uint8_t Q0n8
unsigned fractional number using 8 fractional bits, represents 0.0 to 0.996
Definition: mozzi_fixmath.h:27
StateVariable::setCentreFreq
void setCentreFreq(unsigned int centre_freq)
Set the centre or corner frequency of the filter.
Definition: StateVariable.h:94