summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/extra/hlshelf.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/extra/hlshelf.c')
-rw-r--r--apps/plugins/pdbox/PDa/extra/hlshelf.c466
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
22static t_class *hlshelf_class; 22#ifndef M_PI
23 23#define M_PI 3.141593f
24 24#endif
25typedef 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; 29static t_class *hlshelf_class;
30 float s_gain1; 30
31 float s_gain2; 31
32 float s_ltransfq; 32typedef 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;
39int 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 46int 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 */
63stable: 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
68void 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 75stable:
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 } 80void 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 }
98void 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 { 110void 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.;
170void 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);
177static 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); 182void 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 189static 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;
218void 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
234void 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