-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrc_filter.jsfx-inc
235 lines (184 loc) · 5.1 KB
/
rc_filter.jsfx-inc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
desc:1st-order RC filter
// Copyright (C) 2012-2019 Theo Niessink <[email protected]>
// This work is free. You can redistribute it and/or modify it under the
// terms of the Do What The Fuck You Want To Public License, Version 2,
// as published by Sam Hocevar. See http://www.wtfpl.net/ for more details.
/* Example
desc:RC filter
slider1:1000<20,20000,1>Cutoff (Hz)
import Tale/rc_filter.jsfx-inc
@slider
lp.rc_setf(slider1);
@sample
spl0 = spl1 = lp.rc_lp(0.5*(spl0 + spl1));
Setting Functions
* rc_setf(freq)
Example: lp.rc_setf(1000);
Sets the filter cutoff frequency (specified in Hz), and returns the
filter coefficient.
* rc_set(rc)
Example: lp.rc_set(0.00015);
Sets the filter cutoff frequency by means of the RC time constant
(specified in seconds), and returns the filter coefficient.
(To convert from Hz to RC time constant or vice versa, do 1/(2*$pi*x),
i.e. freq=1/(2*$pi*rc) and rc=1/(2*$pi*freq).)
* rc_sett(time)
Example: env.rc_sett(0.100);
Sets the filter cutoff frequency so that it takes the specified time
(in seconds) to almost fully (99.3%) change from one constant value to
another (e.g. from 0.0 to 1.0), and returns the filter coefficient.
(To convert from seconds to RC time constant, divide by 5. To convert
from RC time constant to seconds, multiple with 5.)
* rc_leaky_set(rc)
Example: sum.rc_leaky_set(0.022);
Sets the feedback coefficient of the leaky integrator to the specified
RC time constant (in seconds), and returns the filter coefficient.
Filter Functions
* rc_lp(sample) -- Low-pass
* rc_hp(sample) -- High-pass
* rc_ap(sample) -- All-pass
Example: output = lp.rc_lp(input);
Sends a sample through the filter, and returns its output.
* rc_leaky(sample)
Example: output = sum.rc_leaky(input);
Sends a sample through the leaky integrator, and returns its output.
High Precision Functions
* rc_setf_precise(freq)
* rc_sett_precise(time)
* rc_set_precise(rc)
* rc_leaky_set_precise(rc)
* rc_hp_precise(sample)
Example: lp.rc_setf_precise(1000);
Example: output = hp.rc_hp_precise(input);
High precision versions of setting/filter functions, which are less
efficient but more precise.
Note: There are no specialized high precision versions of the
low-pass, all-pass, or leaky integrator filter funtions.
Instance Variables
* a
Example: lp2.a = lp1.a;
The filter coefficient.
* lp
Example: output = lp.lp;
The low-pass filter output value.
* hp
Example: output = hp.hp;
The high precision high-pass filter output value.
* in
Example: input = hp.in;
The high precision high-pass filter input value.
*/
@init
// Fast approximations
function rc_set(rc)
// global(srate)
instance(a)
(
a = 1 / (rc * srate + 1);
);
function rc_setf(freq)
// global(srate)
instance(a)
(
a = 1 / (srate / (2*$pi * freq) + 1);
);
function rc_sett(time)
// global(srate)
instance(a)
(
a = 1 / (0.2 * time * srate + 1);
);
// High precision
function rc_set_precise(rc)
// global(srate)
instance(a)
(
a = 1 - exp(-1 / (rc * srate));
);
function rc_setf_precise(freq)
// global(srate)
instance(a)
(
a = 1 - exp(-2*$pi * freq / srate);
);
function rc_sett_precise(time)
// global(srate)
instance(a)
(
a = 1 - exp(-5 / (time * srate));
);
// Source: https://dsp.stackexchange.com/questions/28308/exponential-weighted-moving-average-time-constant/28314#28314
function rc_set_exact(rc)
// global(srate)
instance(a)
local(cos_w0)
(
cos_w0 = cos(min(1 / (rc * srate), $pi)) - 2;
a = sqrt(sqr(cos_w0) - 1) + cos_w0 + 1;
);
function rc_setf_exact(freq)
// global(srate)
instance(a)
local(cos_w0)
(
cos_w0 = cos(min(freq / srate * (2*$pi), $pi)) - 2;
a = sqrt(sqr(cos_w0) - 1) + cos_w0 + 1;
);
function rc_sett_exact(time)
// global(srate)
instance(a)
local(cos_w0)
(
cos_w0 = cos(min(5 / (time * srate), $pi)) - 2;
a = sqrt(sqr(cos_w0) - 1) + cos_w0 + 1;
);
// Low-pass
function rc_lp(sample)
instance(lp, a)
(
lp += a * (sample - lp);
);
// High-pass
function rc_hp(sample)
instance(lp, a)
(
lp += a * (sample - lp);
sample - lp;
);
function rc_hp_precise(sample)
instance(hp, a, in)
(
hp = (1 - 0.5*a) * (sample - in) + (1 - a) * hp;
in = sample;
hp;
);
// All-pass
function rc_ap(sample)
instance(lp, a)
(
lp += a * (sample - lp);
lp - (sample - lp);
);
// Leaky integrator
function rc_leaky_set(rc)
// global(srate)
instance(a)
(
a = 1 - 1 / (rc * srate + 1);
);
function rc_leaky_set_precise(rc)
// global(srate)
instance(a)
(
a = exp(-1 / (rc * srate));
);
function rc_leaky(sample)
instance(lp, a)
(
lp = a * (sample + lp);
);
// Legacy, use rc_sett() instead.
function rc_sets(time)
(
this.rc_sett(time);
);