History

First commit.

mulshine committed 7 years ago

Commit 127a1131 parent 824e8d1147 files · +49021 −-7Browse files

Showing the changes to LEAF/Src_cpp/leaf-filter.cpp (1 of 147 files). Show all

Unified · Split

LEAF/Src_cpp/leaf-filter.cpp+777−0
@@ -0,0 +1,777 @@
1+/*
2+ ==============================================================================
3+
4+ LEAFFilter.c
5+ Created: 20 Jan 2017 12:01:10pm
6+ Author: Michael R Mulshine
7+
8+ ==============================================================================
9+*/
10+
11+#if _WIN32 || _WIN64
12+
13+#include "..\Inc\leaf-filter.h"
14+#include "..\Inc\leaf-wavetables.h"
15+#include "..\leaf.h"
16+
17+#else
18+
19+#include "../Inc/leaf-filter.h"
20+#include "../Inc/leaf-wavetables.h"
21+#include "../leaf.h"
22+
23+#endif
24+
25+void tButterworth_init(tButterworth* const f, int N, float f1, float f2)
26+{
27+ f->f1 = f1;
28+ f->f2 = f2;
29+ f->gain = 1.0f;
30+
31+ f->N = N;
32+
33+ if (f->N > NUM_SVF_BW) f->N = NUM_SVF_BW;
34+
35+ for(int i = 0; i < N/2; ++i)
36+ {
37+ tSVF_init(&f->low[i], SVFTypeHighpass, f1, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)));
38+ tSVF_init(&f->high[i], SVFTypeLowpass, f2, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)));
39+ }
40+}
41+
42+void tButterworth_free(tButterworth* const f)
43+{
44+ for(int i = 0; i < f->N/2; ++i)
45+ {
46+ tSVF_free(&f->low[i]);
47+ tSVF_free(&f->high[i]);
48+ }
49+
50+ leaf_free(f);
51+}
52+
53+float tButterworth_tick(tButterworth* const f, float samp)
54+{
55+ for(int i = 0; i < ((f->N)/2); ++i)
56+ {
57+ samp = tSVF_tick(&f->low[i],samp);
58+ samp = tSVF_tick(&f->high[i],samp);
59+ }
60+ return samp;
61+}
62+
63+void tButterworth_setF1(tButterworth* const f, float f1)
64+{
65+ f->f1 = f1;
66+ for(int i = 0; i < ((f->N)/2); ++i) tSVF_setFreq(&f->low[i], f1);
67+}
68+
69+void tButterworth_setF2(tButterworth* const f, float f2)
70+{
71+ f->f2 = f2;
72+ for(int i = 0; i < ((f->N)/2); ++i) tSVF_setFreq(&f->high[i], f2);
73+}
74+
75+void tButterworth_setFreqs(tButterworth* const f, float f1, float f2)
76+{
77+ f->f1 = f1;
78+ f->f2 = f2;
79+ for(int i = 0; i < ((f->N)/2); ++i)
80+ {
81+ tSVF_setFreq(&f->low[i], f1);
82+ tSVF_setFreq(&f->high[i], f2);
83+ }
84+}
85+
86+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OneZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
87+void tOneZero_init(tOneZero* const f, float theZero)
88+{
89+ f->gain = 1.0f;
90+ f->lastIn = 0.0f;
91+ f->lastOut = 0.0f;
92+ tOneZero_setZero(f, theZero);
93+}
94+
95+void tOneZero_free(tOneZero* const f)
96+{
97+ leaf_free(f);
98+}
99+
100+float tOneZero_tick(tOneZero* const f, float input)
101+{
102+ float in = input * f->gain;
103+ float out = f->b1 * f->lastIn + f->b0 * in;
104+
105+ f->lastIn = in;
106+
107+ return out;
108+}
109+
110+void tOneZero_setZero(tOneZero* const f, float theZero)
111+{
112+ if (theZero > 0.0f) f->b0 = 1.0f / (1.0f + theZero);
113+ else f->b0 = 1.0f / (1.0f - theZero);
114+
115+ f->b1 = -theZero * f->b0;
116+
117+}
118+
119+void tOneZero_setB0(tOneZero* const f, float b0)
120+{
121+ f->b0 = b0;
122+}
123+
124+void tOneZero_setB1(tOneZero* const f, float b1)
125+{
126+ f->b1 = b1;
127+}
128+
129+void tOneZero_setCoefficients(tOneZero* const f, float b0, float b1)
130+{
131+ f->b0 = b0;
132+ f->b1 = b1;
133+}
134+
135+void tOneZero_setGain(tOneZero *f, float gain)
136+{
137+ f->gain = gain;
138+}
139+
140+float tOneZero_getPhaseDelay(tOneZero* const f, float frequency )
141+{
142+ if ( frequency <= 0.0f) frequency = 0.05f;
143+
144+ f->frequency = frequency;
145+
146+ float omegaT = 2 * PI * frequency * leaf.invSampleRate;
147+ float real = 0.0, imag = 0.0;
148+
149+ real += f->b0;
150+
151+ real += f->b1 * cosf(omegaT);
152+ imag -= f->b1 * sinf(omegaT);
153+
154+ real *= f->gain;
155+ imag *= f->gain;
156+
157+ float phase = atan2f( imag, real );
158+
159+ real = 0.0; imag = 0.0;
160+
161+ phase -= atan2f( imag, real );
162+
163+ phase = fmodf( -phase, 2 * PI );
164+
165+ return phase / omegaT;
166+}
167+
168+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ TwoZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
169+void tTwoZero_init(tTwoZero* const f)
170+{
171+ f->gain = 1.0f;
172+ f->lastIn[0] = 0.0f;
173+ f->lastIn[1] = 0.0f;
174+}
175+
176+void tTwoZero_free(tTwoZero* const f)
177+{
178+ leaf_free(f);
179+}
180+
181+float tTwoZero_tick(tTwoZero* const f, float input)
182+{
183+ float in = input * f->gain;
184+ float out = f->b2 * f->lastIn[1] + f->b1 * f->lastIn[0] + f->b0 * in;
185+
186+ f->lastIn[1] = f->lastIn[0];
187+ f->lastIn[0] = in;
188+
189+ return out;
190+}
191+
192+void tTwoZero_setNotch(tTwoZero* const f, float freq, float radius)
193+{
194+ // Should also deal with frequency being > half sample rate / nyquist. See STK
195+ if (freq < 0.0f) freq = 0.0f;
196+ if (radius < 0.0f) radius = 0.0f;
197+
198+ f->frequency = freq;
199+ f->radius = radius;
200+
201+ f->b2 = radius * radius;
202+ f->b1 = -2.0f * radius * cosf(TWO_PI * freq * leaf.invSampleRate); // OPTIMIZE with LOOKUP or APPROXIMATION
203+
204+ // Normalize the filter gain. From STK.
205+ if ( f->b1 > 0.0f ) // Maximum at z = 0.
206+ f->b0 = 1.0f / ( 1.0f + f->b1 + f->b2 );
207+ else // Maximum at z = -1.
208+ f->b0 = 1.0f / ( 1.0f - f->b1 + f->b2 );
209+ f->b1 *= f->b0;
210+ f->b2 *= f->b0;
211+
212+}
213+
214+void tTwoZero_setB0(tTwoZero* const f, float b0)
215+{
216+ f->b0 = b0;
217+}
218+
219+void tTwoZero_setB1(tTwoZero* const f, float b1)
220+{
221+ f->b1 = b1;
222+}
223+
224+void tTwoZero_setCoefficients(tTwoZero* const f, float b0, float b1, float b2)
225+{
226+ f->b0 = b0;
227+ f->b1 = b1;
228+ f->b2 = b2;
229+}
230+
231+void tTwoZero_setGain(tTwoZero* const f, float gain)
232+{
233+ f->gain = gain;
234+}
235+
236+void tTwoZeroSampleRateChanged(tTwoZero* const f)
237+{
238+ tTwoZero_setNotch(f, f->frequency, f->radius);
239+}
240+
241+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OnePole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
242+void tOnePole_init(tOnePole* const f, float thePole)
243+{
244+ f->gain = 1.0f;
245+ f->a0 = 1.0;
246+
247+ tOnePole_setPole(f, thePole);
248+
249+ f->lastIn = 0.0f;
250+ f->lastOut = 0.0f;
251+}
252+
253+void tOnePole_free(tOnePole* const f)
254+{
255+ leaf_free(f);
256+}
257+
258+void tOnePole_setB0(tOnePole* const f, float b0)
259+{
260+ f->b0 = b0;
261+}
262+
263+void tOnePole_setA1(tOnePole* const f, float a1)
264+{
265+ if (a1 >= 1.0f) a1 = 0.999999f;
266+
267+ f->a1 = a1;
268+}
269+
270+void tOnePole_setPole(tOnePole* const f, float thePole)
271+{
272+ if (thePole >= 1.0f) thePole = 0.999999f;
273+
274+ // Normalize coefficients for peak unity gain.
275+ if (thePole > 0.0f) f->b0 = (1.0f - thePole);
276+ else f->b0 = (1.0f + thePole);
277+
278+ f->a1 = -thePole;
279+}
280+
281+void tOnePole_setCoefficients(tOnePole* const f, float b0, float a1)
282+{
283+ if (a1 >= 1.0f) a1 = 0.999999f;
284+
285+ f->b0 = b0;
286+ f->a1 = a1;
287+}
288+
289+void tOnePole_setGain(tOnePole* const f, float gain)
290+{
291+ f->gain = gain;
292+}
293+
294+float tOnePole_tick(tOnePole* const f, float input)
295+{
296+ float in = input * f->gain;
297+ float out = (f->b0 * in) - (f->a1 * f->lastOut);
298+
299+ f->lastIn = in;
300+ f->lastOut = out;
301+
302+ return out;
303+}
304+
305+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ TwoPole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
306+void tTwoPole_init(tTwoPole* const f)
307+{
308+ f->gain = 1.0f;
309+ f->a0 = 1.0;
310+ f->b0 = 1.0;
311+
312+ f->lastOut[0] = 0.0f;
313+ f->lastOut[1] = 0.0f;
314+}
315+
316+void tTwoPole_free(tTwoPole* const f)
317+{
318+ leaf_free(f);
319+}
320+
321+float tTwoPole_tick(tTwoPole* const f, float input)
322+{
323+ float in = input * f->gain;
324+ float out = (f->b0 * in) - (f->a1 * f->lastOut[0]) - (f->a2 * f->lastOut[1]);
325+
326+ f->lastOut[1] = f->lastOut[0];
327+ f->lastOut[0] = out;
328+
329+ return out;
330+}
331+
332+void tTwoPole_setB0(tTwoPole* const f, float b0)
333+{
334+ f->b0 = b0;
335+}
336+
337+void tTwoPole_setA1(tTwoPole* const f, float a1)
338+{
339+ f->a1 = a1;
340+}
341+
342+void tTwoPole_setA2(tTwoPole* const f, float a2)
343+{
344+ f->a2 = a2;
345+}
346+
347+
348+void tTwoPole_setResonance(tTwoPole* const f, float frequency, float radius, oBool normalize)
349+{
350+ if (frequency < 0.0f) frequency = 0.0f; // need to also handle when frequency > nyquist
351+ if (radius < 0.0f) radius = 0.0f;
352+ if (radius >= 1.0f) radius = 0.999999f;
353+
354+ f->radius = radius;
355+ f->frequency = frequency;
356+ f->normalize = normalize;
357+
358+ f->a2 = radius * radius;
359+ f->a1 = -2.0f * radius * cos(TWO_PI * frequency * leaf.invSampleRate);
360+
361+ if ( normalize )
362+ {
363+ // Normalize the filter gain ... not terribly efficient.
364+ float real = 1 - radius + (f->a2 - radius) * cos(TWO_PI * 2 * frequency * leaf.invSampleRate);
365+ float imag = (f->a2 - radius) * sin(TWO_PI * 2 * frequency * leaf.invSampleRate);
366+ f->b0 = sqrt( pow(real, 2) + pow(imag, 2) );
367+ }
368+}
369+
370+void tTwoPole_setCoefficients(tTwoPole* const f, float b0, float a1, float a2)
371+{
372+ f->b0 = b0;
373+ f->a1 = a1;
374+ f->a2 = a2;
375+}
376+
377+void tTwoPole_setGain(tTwoPole* const f, float gain)
378+{
379+ f->gain = gain;
380+}
381+
382+void tTwoPoleSampleRateChanged (tTwoPole* const f)
383+{
384+ f->a2 = f->radius * f->radius;
385+ f->a1 = -2.0f * f->radius * cos(TWO_PI * f->frequency * leaf.invSampleRate);
386+
387+ if ( f->normalize )
388+ {
389+ // Normalize the filter gain ... not terribly efficient.
390+ float real = 1 - f->radius + (f->a2 - f->radius) * cos(TWO_PI * 2 * f->frequency * leaf.invSampleRate);
391+ float imag = (f->a2 - f->radius) * sin(TWO_PI * 2 * f->frequency * leaf.invSampleRate);
392+ f->b0 = sqrt( pow(real, 2) + pow(imag, 2) );
393+ }
394+}
395+
396+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ PoleZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
397+void tPoleZero_init(tPoleZero* const f)
398+{
399+ f->gain = 1.0f;
400+ f->b0 = 1.0;
401+ f->a0 = 1.0;
402+
403+ f->lastIn = 0.0f;
404+ f->lastOut = 0.0f;
405+}
406+
407+void tPoleZero_free(tPoleZero* const f)
408+{
409+ leaf_free(f);
410+}
411+
412+void tPoleZero_setB0(tPoleZero* const pzf, float b0)
413+{
414+ pzf->b0 = b0;
415+}
416+
417+void tPoleZero_setB1(tPoleZero* const pzf, float b1)
418+{
419+ pzf->b1 = b1;
420+}
421+
422+void tPoleZero_setA1(tPoleZero* const pzf, float a1)
423+{
424+ if (a1 >= 1.0f) // a1 should be less than 1.0
425+ {
426+ a1 = 0.999999f;
427+ }
428+
429+ pzf->a1 = a1;
430+}
431+
432+void tPoleZero_setCoefficients(tPoleZero* const pzf, float b0, float b1, float a1)
433+{
434+ if (a1 >= 1.0f) // a1 should be less than 1.0
435+ {
436+ a1 = 0.999999f;
437+ }
438+
439+ pzf->b0 = b0;
440+ pzf->b1 = b1;
441+ pzf->a1 = a1;
442+}
443+
444+void tPoleZero_setAllpass(tPoleZero* const pzf, float coeff)
445+{
446+ if (coeff >= 1.0f) // allpass coefficient >= 1.0 makes filter unstable
447+ {
448+ coeff = 0.999999f;
449+ }
450+
451+ pzf->b0 = coeff;
452+ pzf->b1 = 1.0f;
453+ pzf->a0 = 1.0f;
454+ pzf->a1 = coeff;
455+}
456+
457+void tPoleZero_setBlockZero(tPoleZero* const pzf, float thePole)
458+{
459+ if (thePole >= 1.0f) // allpass coefficient >= 1.0 makes filter unstable
460+ {
461+ thePole = 0.999999f;
462+ }
463+
464+ pzf->b0 = 1.0f;
465+ pzf->b1 = -1.0f;
466+ pzf->a0 = 1.0f;
467+ pzf->a1 = -thePole;
468+}
469+
470+void tPoleZero_setGain(tPoleZero* const pzf, float gain)
471+{
472+ pzf->gain = gain;
473+}
474+
475+float tPoleZero_tick(tPoleZero* const pzf, float input)
476+{
477+ float in = input * pzf->gain;
478+ float out = (pzf->b0 * in) + (pzf->b1 * pzf->lastIn) - (pzf->a1 * pzf->lastOut);
479+
480+ pzf->lastIn = in;
481+ pzf->lastOut = out;
482+
483+ return out;
484+}
485+
486+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ BiQuad Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
487+void tBiQuad_init(tBiQuad* const f)
488+{
489+ f->gain = 1.0f;
490+
491+ f->b0 = 0.0f;
492+ f->a0 = 0.0f;
493+
494+ f->lastIn[0] = 0.0f;
495+ f->lastIn[1] = 0.0f;
496+ f->lastOut[0] = 0.0f;
497+ f->lastOut[1] = 0.0f;
498+}
499+
500+void tBiQuad_free(tBiQuad* const f)
501+{
502+ leaf_free(f);
503+}
504+
505+float tBiQuad_tick(tBiQuad* const f, float input)
506+{
507+ float in = input * f->gain;
508+ float out = f->b0 * in + f->b1 * f->lastIn[0] + f->b2 * f->lastIn[1];
509+ out -= f->a2 * f->lastOut[1] + f->a1 * f->lastOut[0];
510+
511+ f->lastIn[1] = f->lastIn[0];
512+ f->lastIn[0] = in;
513+
514+ f->lastOut[1] = f->lastOut[0];
515+ f->lastOut[0] = out;
516+
517+ return out;
518+}
519+
520+void tBiQuad_setResonance(tBiQuad* const f, float freq, float radius, oBool normalize)
521+{
522+ // Should also deal with frequency being > half sample rate / nyquist. See STK
523+ if (freq < 0.0f) freq = 0.0f;
524+ if (radius < 0.0f) radius = 0.0f;
525+ if (radius >= 1.0f) radius = 1.0f;
526+
527+ f->frequency = freq;
528+ f->radius = radius;
529+ f->normalize = normalize;
530+
531+ f->a2 = radius * radius;
532+ f->a1 = -2.0f * radius * cosf(TWO_PI * freq * leaf.invSampleRate);
533+
534+ if (normalize)
535+ {
536+ f->b0 = 0.5f - 0.5f * f->a2;
537+ f->b1 = 0.0f;
538+ f->b2 = -f->b0;
539+ }
540+}
541+
542+void tBiQuad_setNotch(tBiQuad* const f, float freq, float radius)
543+{
544+ // Should also deal with frequency being > half sample rate / nyquist. See STK
545+ if (freq < 0.0f) freq = 0.0f;
546+ if (radius < 0.0f) radius = 0.0f;
547+
548+ f->b2 = radius * radius;
549+ f->b1 = -2.0f * radius * cosf(TWO_PI * freq * leaf.invSampleRate); // OPTIMIZE with LOOKUP or APPROXIMATION
550+
551+ // Does not attempt to normalize filter gain.
552+}
553+
554+void tBiQuad_setEqualGainZeros(tBiQuad* const f)
555+{
556+ f->b0 = 1.0f;
557+ f->b1 = 0.0f;
558+ f->b2 = -1.0f;
559+}
560+
561+void tBiQuad_setB0(tBiQuad* const f, float b0)
562+{
563+ f->b0 = b0;
564+}
565+
566+void tBiQuad_setB1(tBiQuad* const f, float b1)
567+{
568+ f->b1 = b1;
569+}
570+
571+void tBiQuad_setB2(tBiQuad* const f, float b2)
572+{
573+ f->b2 = b2;
574+}
575+
576+void tBiQuad_setA1(tBiQuad* const f, float a1)
577+{
578+ f->a1 = a1;
579+}
580+
581+void tBiQuad_setA2(tBiQuad* const f, float a2)
582+{
583+ f->a2 = a2;
584+}
585+
586+void tBiQuad_setCoefficients(tBiQuad* const f, float b0, float b1, float b2, float a1, float a2)
587+{
588+ f->b0 = b0;
589+ f->b1 = b1;
590+ f->b2 = b2;
591+ f->a1 = a1;
592+ f->a2 = a2;
593+}
594+
595+void tBiQuad_setGain(tBiQuad* const f, float gain)
596+{
597+ f->gain = gain;
598+}
599+
600+void tBiQuadSampleRateChanged(tBiQuad* const f)
601+{
602+ f->a2 = f->radius * f->radius;
603+ f->a1 = -2.0f * f->radius * cosf(TWO_PI * f->frequency * leaf.invSampleRate);
604+
605+ if (f->normalize)
606+ {
607+ f->b0 = 0.5f - 0.5f * f->a2;
608+ f->b1 = 0.0f;
609+ f->b2 = -f->b0;
610+ }
611+}
612+
613+/* Highpass */
614+void tHighpass_setFreq(tHighpass* const f, float freq)
615+{
616+ f->frequency = freq;
617+ f->R = (1.0f-((freq * 2.0f * 3.14f) * leaf.invSampleRate));
618+
619+}
620+
621+float tHighpass_getFreq(tHighpass* const f)
622+{
623+ return f->frequency;
624+}
625+
626+// From JOS DC Blocker
627+float tHighpass_tick(tHighpass* const f, float x)
628+{
629+ f->ys = x - f->xs + f->R * f->ys;
630+ f->xs = x;
631+ return f->ys;
632+}
633+
634+void tHighpass_init(tHighpass* const f, float freq)
635+{
636+ f->R = (1.0f-((freq * 2.0f * 3.14f)* leaf.invSampleRate));
637+ f->ys = 0.0f;
638+ f->xs = 0.0f;
639+
640+ f->frequency = freq;
641+}
642+
643+void tHighpass_free(tHighpass* const f)
644+{
645+ leaf_free(f);
646+}
647+
648+void tHighpassSampleRateChanged(tHighpass* const f)
649+{
650+ f->R = (1.0f-((f->frequency * 2.0f * 3.14f) * leaf.invSampleRate));
651+}
652+
653+float tSVF_tick(tSVF* const svf, float v0)
654+{
655+ float v1,v2,v3;
656+ v3 = v0 - svf->ic2eq;
657+ v1 = (svf->a1 * svf->ic1eq) + (svf->a2 * v3);
658+ v2 = svf->ic2eq + (svf->a2 * svf->ic1eq) + (svf->a3 * v3);
659+ svf->ic1eq = (2.0f * v1) - svf->ic1eq;
660+ svf->ic2eq = (2.0f * v2) - svf->ic2eq;
661+
662+ if (svf->type == SVFTypeLowpass) return v2;
663+ else if (svf->type == SVFTypeBandpass) return v1;
664+ else if (svf->type == SVFTypeHighpass) return v0 - (svf->k * v1) - v2;
665+ else if (svf->type == SVFTypeNotch) return v0 - (svf->k * v1);
666+ else if (svf->type == SVFTypePeak) return v0 - (svf->k * v1) - (2.0f * v2);
667+ else return 0.0f;
668+
669+}
670+
671+// Less efficient, more accurate version of SVF, in which cutoff frequency is taken as floating point Hz value and tanh
672+// is calculated when frequency changes.
673+void tSVF_init(tSVF* const svf, SVFType type, float freq, float Q)
674+{
675+ svf->type = type;
676+
677+ svf->ic1eq = 0;
678+ svf->ic2eq = 0;
679+
680+ float a1,a2,a3,g,k;
681+ g = tanf(PI * freq * leaf.invSampleRate);
682+ k = 1.0f/LEAF_clip(0.01f,Q,10.0f);
683+ a1 = 1.0f/(1.0f+g*(g+k));
684+ a2 = g*a1;
685+ a3 = g*a2;
686+
687+ svf->g = g;
688+ svf->k = k;
689+ svf->a1 = a1;
690+ svf->a2 = a2;
691+ svf->a3 = a3;
692+}
693+
694+void tSVF_free(tSVF* const svf)
695+{
696+ leaf_free(svf);
697+}
698+
699+int tSVF_setFreq(tSVF* const svf, float freq)
700+{
701+ svf->g = tanf(PI * freq * leaf.invSampleRate);
702+ svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
703+ svf->a2 = svf->g * svf->a1;
704+ svf->a3 = svf->g * svf->a2;
705+
706+ return 0;
707+}
708+
709+int tSVF_setQ(tSVF* const svf, float Q)
710+{
711+ svf->k = 1.0f/LEAF_clip(0.01f,Q,10.0f);
712+ svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
713+ svf->a2 = svf->g * svf->a1;
714+ svf->a3 = svf->g * svf->a2;
715+
716+ return 0;
717+}
718+
719+// Efficient version of tSVF where frequency is set based on 12-bit integer input for lookup in tanh wavetable.
720+void tSVFE_init(tSVFE* const svf, SVFType type, uint16_t input, float Q)
721+{
722+ svf->type = type;
723+
724+ svf->ic1eq = 0;
725+ svf->ic2eq = 0;
726+
727+ float a1,a2,a3,g,k;
728+ g = filtertan[input];
729+ k = 1.0f/Q;
730+ a1 = 1.0f/(1.0f+g*(g+k));
731+ a2 = g*a1;
732+ a3 = g*a2;
733+
734+ svf->g = g;
735+ svf->k = k;
736+ svf->a1 = a1;
737+ svf->a2 = a2;
738+ svf->a3 = a3;
739+}
740+
741+float tSVFE_tick(tSVFE* const svf, float v0)
742+{
743+ float v1,v2,v3;
744+ v3 = v0 - svf->ic2eq;
745+ v1 = (svf->a1 * svf->ic1eq) + (svf->a2 * v3);
746+ v2 = svf->ic2eq + (svf->a2 * svf->ic1eq) + (svf->a3 * v3);
747+ svf->ic1eq = (2.0f * v1) - svf->ic1eq;
748+ svf->ic2eq = (2.0f * v2) - svf->ic2eq;
749+
750+ if (svf->type == SVFTypeLowpass) return v2;
751+ else if (svf->type == SVFTypeBandpass) return v1;
752+ else if (svf->type == SVFTypeHighpass) return v0 - (svf->k * v1) - v2;
753+ else if (svf->type == SVFTypeNotch) return v0 - (svf->k * v1);
754+ else if (svf->type == SVFTypePeak) return v0 - (svf->k * v1) - (2.0f * v2);
755+ else return 0.0f;
756+
757+}
758+
759+int tSVFE_setFreq(tSVFE* const svf, uint16_t input)
760+{
761+ svf->g = filtertan[input];
762+ svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
763+ svf->a2 = svf->g * svf->a1;
764+ svf->a3 = svf->g * svf->a2;
765+
766+ return 0;
767+}
768+
769+int tSVFE_setQ(tSVFE* const svf, float Q)
770+{
771+ svf->k = 1.0f/Q;
772+ svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
773+ svf->a2 = svf->g * svf->a1;
774+ svf->a3 = svf->g * svf->a2;
775+
776+ return 0;
777+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t