diff options
Diffstat (limited to 'apps/plugins/pdbox/PDa/extra/hlshelf.c')
-rw-r--r-- | apps/plugins/pdbox/PDa/extra/hlshelf.c | 466 |
1 files changed, 241 insertions, 225 deletions
diff --git a/apps/plugins/pdbox/PDa/extra/hlshelf.c b/apps/plugins/pdbox/PDa/extra/hlshelf.c index 242a2e625f..49f413f9ca 100644 --- a/apps/plugins/pdbox/PDa/extra/hlshelf.c +++ b/apps/plugins/pdbox/PDa/extra/hlshelf.c | |||
@@ -1,226 +1,242 @@ | |||
1 | /* (C) Guenter Geiger <geiger@epy.co.at> */ | 1 | /* (C) Guenter Geiger <geiger@epy.co.at> */ |
2 | 2 | ||
3 | 3 | ||
4 | #include <m_pd.h> | 4 | #ifdef ROCKBOX |
5 | #include <math.h> | 5 | #include "plugin.h" |
6 | 6 | #include "pdbox.h" | |
7 | #ifdef NT | 7 | #include "m_pd.h" |
8 | #pragma warning( disable : 4244 ) | 8 | #include "math.h" |
9 | #pragma warning( disable : 4305 ) | 9 | #else /* ROCKBOX */ |
10 | #endif | 10 | #include <m_pd.h> |
11 | 11 | #include <math.h> | |
12 | /* ------------------------ hlshelf ----------------------------- */ | 12 | |
13 | 13 | #ifdef NT | |
14 | 14 | #pragma warning( disable : 4244 ) | |
15 | #ifndef M_PI | 15 | #pragma warning( disable : 4305 ) |
16 | #define M_PI 3.141593f | 16 | #endif |
17 | #endif | 17 | #endif /* ROCKBOX */ |
18 | 18 | ||
19 | #define SRATE 44100.0 | 19 | /* ------------------------ hlshelf ----------------------------- */ |
20 | #define MAX_GAIN 120.0f | 20 | |
21 | 21 | ||
22 | static t_class *hlshelf_class; | 22 | #ifndef M_PI |
23 | 23 | #define M_PI 3.141593f | |
24 | 24 | #endif | |
25 | typedef struct _hlshelf | 25 | |
26 | { | 26 | #define SRATE 44100.0 |
27 | t_object x_obj; | 27 | #define MAX_GAIN 120.0f |
28 | float s_rate; | 28 | |
29 | float s_gain0; | 29 | static t_class *hlshelf_class; |
30 | float s_gain1; | 30 | |
31 | float s_gain2; | 31 | |
32 | float s_ltransfq; | 32 | typedef struct _hlshelf |
33 | float s_htransfq; | 33 | { |
34 | float s_lradians; | 34 | t_object x_obj; |
35 | float s_hradians; | 35 | float s_rate; |
36 | } t_hlshelf; | 36 | float s_gain0; |
37 | 37 | float s_gain1; | |
38 | 38 | float s_gain2; | |
39 | int hlshelf_check_stability(t_float fb1, | 39 | float s_ltransfq; |
40 | t_float fb2, | 40 | float s_htransfq; |
41 | t_float ff1, | 41 | float s_lradians; |
42 | t_float ff2, | 42 | float s_hradians; |
43 | t_float ff3) | 43 | } t_hlshelf; |
44 | { | 44 | |
45 | float discriminant = fb1 * fb1 + 4 * fb2; | 45 | |
46 | 46 | int hlshelf_check_stability(t_float fb1, | |
47 | if (discriminant < 0) /* imaginary roots -- resonant filter */ | 47 | t_float fb2, |
48 | { | 48 | t_float ff1, |
49 | /* they're conjugates so we just check that the product | 49 | t_float ff2, |
50 | is less than one */ | 50 | t_float ff3) |
51 | if (fb2 >= -1.0f) goto stable; | 51 | { |
52 | } | 52 | #ifdef ROCKBOX |
53 | else /* real roots */ | 53 | (void) ff1; |
54 | { | 54 | (void) ff2; |
55 | /* check that the parabola 1 - fb1 x - fb2 x^2 has a | 55 | (void) ff3; |
56 | vertex between -1 and 1, and that it's nonnegative | 56 | #endif |
57 | at both ends, which implies both roots are in [1-,1]. */ | 57 | float discriminant = fb1 * fb1 + 4 * fb2; |
58 | if (fb1 <= 2.0f && fb1 >= -2.0f && | 58 | |
59 | 1.0f - fb1 -fb2 >= 0 && 1.0f + fb1 - fb2 >= 0) | 59 | if (discriminant < 0) /* imaginary roots -- resonant filter */ |
60 | goto stable; | 60 | { |
61 | } | 61 | /* they're conjugates so we just check that the product |
62 | return 0; | 62 | is less than one */ |
63 | stable: | 63 | if (fb2 >= -1.0f) goto stable; |
64 | return 1; | 64 | } |
65 | } | 65 | else /* real roots */ |
66 | 66 | { | |
67 | 67 | /* check that the parabola 1 - fb1 x - fb2 x^2 has a | |
68 | void hlshelf_check(t_hlshelf *x) | 68 | vertex between -1 and 1, and that it's nonnegative |
69 | { | 69 | at both ends, which implies both roots are in [1-,1]. */ |
70 | 70 | if (fb1 <= 2.0f && fb1 >= -2.0f && | |
71 | if(x->s_gain0 - x->s_gain1 > MAX_GAIN) { | 71 | 1.0f - fb1 -fb2 >= 0 && 1.0f + fb1 - fb2 >= 0) |
72 | x->s_gain0 = x->s_gain1 + MAX_GAIN; | 72 | goto stable; |
73 | post("setting gain0 to %f",x->s_gain0); | 73 | } |
74 | } | 74 | return 0; |
75 | 75 | stable: | |
76 | 76 | return 1; | |
77 | if(x->s_gain1 > MAX_GAIN) { | 77 | } |
78 | x->s_gain1 = MAX_GAIN; | 78 | |
79 | post("setting gain1 to %f",x->s_gain1); | 79 | |
80 | } | 80 | void hlshelf_check(t_hlshelf *x) |
81 | 81 | { | |
82 | if(x->s_gain2 - x->s_gain1 > MAX_GAIN) { | 82 | |
83 | x->s_gain2 = x->s_gain1 + MAX_GAIN; | 83 | if(x->s_gain0 - x->s_gain1 > MAX_GAIN) { |
84 | post("setting gain2 to %f",x->s_gain2); | 84 | x->s_gain0 = x->s_gain1 + MAX_GAIN; |
85 | } | 85 | post("setting gain0 to %f",x->s_gain0); |
86 | 86 | } | |
87 | /* constrain: 0 <= x->s_ltransfq < x->s_htransfq. */ | 87 | |
88 | x->s_ltransfq = (x->s_ltransfq < x->s_htransfq) ? x->s_ltransfq : x->s_htransfq - 0.5f; | 88 | |
89 | 89 | if(x->s_gain1 > MAX_GAIN) { | |
90 | if (x->s_ltransfq < 0) x->s_ltransfq = 0.0f; | 90 | x->s_gain1 = MAX_GAIN; |
91 | 91 | post("setting gain1 to %f",x->s_gain1); | |
92 | x->s_lradians = M_PI * x->s_ltransfq / x->s_rate; | 92 | } |
93 | x->s_hradians= M_PI * (0.5f - (x->s_htransfq / x->s_rate)); | 93 | |
94 | 94 | if(x->s_gain2 - x->s_gain1 > MAX_GAIN) { | |
95 | } | 95 | x->s_gain2 = x->s_gain1 + MAX_GAIN; |
96 | 96 | post("setting gain2 to %f",x->s_gain2); | |
97 | 97 | } | |
98 | void hlshelf_bang(t_hlshelf *x) | 98 | |
99 | { | 99 | /* constrain: 0 <= x->s_ltransfq < x->s_htransfq. */ |
100 | t_atom at[6]; | 100 | x->s_ltransfq = (x->s_ltransfq < x->s_htransfq) ? x->s_ltransfq : x->s_htransfq - 0.5f; |
101 | float c0, c1, c2, d0, d1, d2; /* output coefs */ | 101 | |
102 | float a1, a2, b1, b2, g1, g2; /* temp coefs */ | 102 | if (x->s_ltransfq < 0) x->s_ltransfq = 0.0f; |
103 | double xf; | 103 | |
104 | 104 | x->s_lradians = M_PI * x->s_ltransfq / x->s_rate; | |
105 | hlshelf_check(x); | 105 | x->s_hradians= M_PI * (0.5f - (x->s_htransfq / x->s_rate)); |
106 | 106 | ||
107 | /* low shelf */ | 107 | } |
108 | xf = 0.5 * 0.115129255 * (double)(x->s_gain0 - x->s_gain1); /* ln(10) / 20 = 0.115129255 */ | 108 | |
109 | if(xf < -200.) /* exp(x) -> 0 */ | 109 | |
110 | { | 110 | void hlshelf_bang(t_hlshelf *x) |
111 | a1 = 1.0f; | 111 | { |
112 | b1 = -1.0f; | 112 | t_atom at[6]; |
113 | g1 = 0.0f; | 113 | float c0, c1, c2, d0, d1, d2; /* output coefs */ |
114 | } | 114 | float a1, a2, b1, b2, g1, g2; /* temp coefs */ |
115 | else | 115 | double xf; |
116 | { | 116 | |
117 | double t = tan(x->s_lradians); | 117 | hlshelf_check(x); |
118 | double e = exp(xf); | 118 | |
119 | double r = t / e; | 119 | /* low shelf */ |
120 | double kr = t * e; | 120 | xf = 0.5 * 0.115129255 * (double)(x->s_gain0 - x->s_gain1); /* ln(10) / 20 = 0.115129255 */ |
121 | 121 | if(xf < -200.) /* exp(x) -> 0 */ | |
122 | a1 = (r - 1) / (r + 1); | 122 | { |
123 | b1 = (kr - 1) / (kr + 1); | 123 | a1 = 1.0f; |
124 | g1 = (kr + 1) / (r + 1); | 124 | b1 = -1.0f; |
125 | } | 125 | g1 = 0.0f; |
126 | 126 | } | |
127 | /* high shelf */ | 127 | else |
128 | xf = 0.5 * 0.115129255 * (double)(x->s_gain2 - x->s_gain1); /* ln(10) / 20 = 0.115129255 */ | 128 | { |
129 | if(xf < -200.) /* exp(x) -> 0 */ | 129 | double t = tan(x->s_lradians); |
130 | { | 130 | double e = exp(xf); |
131 | a2 = -1.0f; | 131 | double r = t / e; |
132 | b2 = 1.0f; | 132 | double kr = t * e; |
133 | g2 = 0.0f; | 133 | |
134 | } | 134 | a1 = (r - 1) / (r + 1); |
135 | else | 135 | b1 = (kr - 1) / (kr + 1); |
136 | { | 136 | g1 = (kr + 1) / (r + 1); |
137 | double t = tan(x->s_hradians); | 137 | } |
138 | double e = exp(xf); | 138 | |
139 | double r = t / e; | 139 | /* high shelf */ |
140 | double kr = t * e; | 140 | xf = 0.5 * 0.115129255 * (double)(x->s_gain2 - x->s_gain1); /* ln(10) / 20 = 0.115129255 */ |
141 | 141 | if(xf < -200.) /* exp(x) -> 0 */ | |
142 | a2 = (1 - r) / (1 + r); | 142 | { |
143 | b2 = (1 - kr) / (1 + kr); | 143 | a2 = -1.0f; |
144 | g2 = (1 + kr) / (1 + r); | 144 | b2 = 1.0f; |
145 | } | 145 | g2 = 0.0f; |
146 | 146 | } | |
147 | /* form product */ | 147 | else |
148 | c0 = g1 * g2 * (float)(exp((double)(x->s_gain1) * 0.05f * 2.302585093f)); ; | 148 | { |
149 | c1 = a1 + a2; | 149 | double t = tan(x->s_hradians); |
150 | c2 = a1 * a2; | 150 | double e = exp(xf); |
151 | d0 = 1.0f; | 151 | double r = t / e; |
152 | d1 = b1 + b2; | 152 | double kr = t * e; |
153 | d2 = b1 * b2; | 153 | |
154 | 154 | a2 = (1 - r) / (1 + r); | |
155 | if (!hlshelf_check_stability(-c1/d0,-c2/d0,d0/d0,d1/d0,d2/d0)) { | 155 | b2 = (1 - kr) / (1 + kr); |
156 | post("hlshelf: filter unstable -> resetting"); | 156 | g2 = (1 + kr) / (1 + r); |
157 | c0=1.;c1=0.;c2=0.; | 157 | } |
158 | d0=1.;d1=0.;d2=0.; | 158 | |
159 | } | 159 | /* form product */ |
160 | 160 | c0 = g1 * g2 * (float)(exp((double)(x->s_gain1) * 0.05f * 2.302585093f)); ; | |
161 | SETFLOAT(at,-c1/d0); | 161 | c1 = a1 + a2; |
162 | SETFLOAT(at+1,-c2/d0); | 162 | c2 = a1 * a2; |
163 | SETFLOAT(at+2,d0/d0); | 163 | d0 = 1.0f; |
164 | SETFLOAT(at+3,d1/d0); | 164 | d1 = b1 + b2; |
165 | SETFLOAT(at+4,d2/d0); | 165 | d2 = b1 * b2; |
166 | 166 | ||
167 | outlet_list(x->x_obj.ob_outlet,&s_list,5,at); | 167 | if (!hlshelf_check_stability(-c1/d0,-c2/d0,d0/d0,d1/d0,d2/d0)) { |
168 | } | 168 | post("hlshelf: filter unstable -> resetting"); |
169 | 169 | c0=1.;c1=0.;c2=0.; | |
170 | void hlshelf_float(t_hlshelf *x,t_floatarg f) | 170 | d0=1.;d1=0.;d2=0.; |
171 | { | 171 | } |
172 | x->s_gain0 = f; | 172 | |
173 | hlshelf_bang(x); | 173 | SETFLOAT(at,-c1/d0); |
174 | } | 174 | SETFLOAT(at+1,-c2/d0); |
175 | 175 | SETFLOAT(at+2,d0/d0); | |
176 | 176 | SETFLOAT(at+3,d1/d0); | |
177 | static void *hlshelf_new(t_symbol* s,t_int argc, t_atom* at) | 177 | SETFLOAT(at+4,d2/d0); |
178 | { | 178 | |
179 | t_hlshelf *x = (t_hlshelf *)pd_new(hlshelf_class); | 179 | outlet_list(x->x_obj.ob_outlet,&s_list,5,at); |
180 | t_float k0 = atom_getfloat(at); | 180 | } |
181 | t_float k1 = atom_getfloat(at+1); | 181 | |
182 | t_float k2 = atom_getfloat(at+2); | 182 | void hlshelf_float(t_hlshelf *x,t_floatarg f) |
183 | t_float f1 = atom_getfloat(at+3); | 183 | { |
184 | t_float f2 = atom_getfloat(at+4); | 184 | x->s_gain0 = f; |
185 | 185 | hlshelf_bang(x); | |
186 | 186 | } | |
187 | f1 = atom_getfloat(at); | 187 | |
188 | f2 = atom_getfloat(at); | 188 | |
189 | 189 | static void *hlshelf_new(t_symbol* s,t_int argc, t_atom* at) | |
190 | if ((f1 == 0.0f && f2 == 0.0f) || f1 > f2){ /* all gains = 0db */ | 190 | { |
191 | f1 = 150.0f; | 191 | #ifdef ROCKBOX |
192 | f2 = 5000.0f; | 192 | (void) s; |
193 | } | 193 | (void) argc; |
194 | 194 | #endif | |
195 | if (f1 < 0) f1 = 0.0f; | 195 | t_hlshelf *x = (t_hlshelf *)pd_new(hlshelf_class); |
196 | if (f2 > SRATE) f2 = .5f*SRATE; | 196 | t_float k0 = atom_getfloat(at); |
197 | 197 | t_float k1 = atom_getfloat(at+1); | |
198 | x->s_rate = SRATE; /* srate default */ | 198 | t_float k2 = atom_getfloat(at+2); |
199 | x->s_gain0 = k0; | 199 | t_float f1 = atom_getfloat(at+3); |
200 | x->s_gain1 = k1; | 200 | t_float f2 = atom_getfloat(at+4); |
201 | x->s_gain2 = k2; | 201 | |
202 | 202 | ||
203 | x->s_ltransfq = 0.0f; | 203 | f1 = atom_getfloat(at); |
204 | x->s_htransfq = SRATE/2; | 204 | f2 = atom_getfloat(at); |
205 | 205 | ||
206 | x->s_lradians = M_PI * x->s_ltransfq / x->s_rate; | 206 | if ((f1 == 0.0f && f2 == 0.0f) || f1 > f2){ /* all gains = 0db */ |
207 | x->s_hradians= M_PI * (0.5f - (x->s_htransfq / x->s_rate)); | 207 | f1 = 150.0f; |
208 | 208 | f2 = 5000.0f; | |
209 | floatinlet_new(&x->x_obj, &x->s_gain1); | 209 | } |
210 | floatinlet_new(&x->x_obj, &x->s_gain2); | 210 | |
211 | floatinlet_new(&x->x_obj, &x->s_ltransfq); | 211 | if (f1 < 0) f1 = 0.0f; |
212 | floatinlet_new(&x->x_obj, &x->s_htransfq); | 212 | if (f2 > SRATE) f2 = .5f*SRATE; |
213 | outlet_new(&x->x_obj, &s_list); | 213 | |
214 | 214 | x->s_rate = SRATE; /* srate default */ | |
215 | return (x); | 215 | x->s_gain0 = k0; |
216 | } | 216 | x->s_gain1 = k1; |
217 | 217 | x->s_gain2 = k2; | |
218 | void hlshelf_setup(void) | 218 | |
219 | { | 219 | x->s_ltransfq = 0.0f; |
220 | hlshelf_class = class_new(gensym("hlshelf"), (t_newmethod)hlshelf_new, 0, | 220 | x->s_htransfq = SRATE/2; |
221 | sizeof(t_hlshelf), 0, A_GIMME, 0); | 221 | |
222 | class_addbang(hlshelf_class,hlshelf_bang); | 222 | x->s_lradians = M_PI * x->s_ltransfq / x->s_rate; |
223 | class_addfloat(hlshelf_class,hlshelf_float); | 223 | x->s_hradians= M_PI * (0.5f - (x->s_htransfq / x->s_rate)); |
224 | } | 224 | |
225 | 225 | floatinlet_new(&x->x_obj, &x->s_gain1); | |
226 | floatinlet_new(&x->x_obj, &x->s_gain2); | ||
227 | floatinlet_new(&x->x_obj, &x->s_ltransfq); | ||
228 | floatinlet_new(&x->x_obj, &x->s_htransfq); | ||
229 | outlet_new(&x->x_obj, &s_list); | ||
230 | |||
231 | return (x); | ||
232 | } | ||
233 | |||
234 | void hlshelf_setup(void) | ||
235 | { | ||
236 | hlshelf_class = class_new(gensym("hlshelf"), (t_newmethod)hlshelf_new, 0, | ||
237 | sizeof(t_hlshelf), 0, A_GIMME, 0); | ||
238 | class_addbang(hlshelf_class,hlshelf_bang); | ||
239 | class_addfloat(hlshelf_class,hlshelf_float); | ||
240 | } | ||
241 | |||
226 | 242 | ||