1 /*
2 * TBVCF
3 *
4 * This code has been extracted from the Csound opcode "tbvcf".
5 * It has been modified to work as a Soundpipe module.
6 *
7 * Original Author(s): Hans Mikelson
8 * Year: 2000
9 * Location: Opcodes/biquad.c
10 *
11 */
12
13
14 #include <math.h>
15 #include <stdint.h>
16 #include <stdlib.h>
17 #define ROOT2 (1.4142135623730950488)
18
19 #ifndef M_PI
20 #define M_PI 3.14159265358979323846 /* pi */
21 #endif
22
23 #include "soundpipe.h"
24
sp_tbvcf_create(sp_tbvcf ** p)25 int sp_tbvcf_create(sp_tbvcf **p)
26 {
27 *p = malloc(sizeof(sp_tbvcf));
28 return SP_OK;
29 }
30
sp_tbvcf_destroy(sp_tbvcf ** p)31 int sp_tbvcf_destroy(sp_tbvcf **p)
32 {
33 free(*p);
34 return SP_OK;
35 }
36
sp_tbvcf_init(sp_data * sp,sp_tbvcf * p)37 int sp_tbvcf_init(sp_data *sp, sp_tbvcf *p)
38 {
39 p->fco = 500.0;
40 p->res = 0.8;
41 p->dist = 2.0;
42 p->asym = 0.5;
43
44 p->sr = sp->sr;
45 p->onedsr = 1.0 / p->sr;
46
47 p->iskip = 0.0;
48 if(p->iskip == 0.0){
49 p->y = p->y1 = p->y2 = 0.0;
50 }
51 p->fcocod = p->fco;
52 p->rezcod = p->res;
53
54
55 return SP_OK;
56 }
57
58 /* TODO: clean up code here. */
sp_tbvcf_compute(sp_data * sp,sp_tbvcf * p,SPFLOAT * in,SPFLOAT * out)59 int sp_tbvcf_compute(sp_data *sp, sp_tbvcf *p, SPFLOAT *in, SPFLOAT *out)
60 {
61 SPFLOAT x;
62 SPFLOAT fco, res, dist, asym;
63 SPFLOAT y = p->y, y1 = p->y1, y2 = p->y2;
64 /* The initialisations are fake to fool compiler warnings */
65 SPFLOAT ih, fdbk, d, ad;
66 SPFLOAT fc=0.0, fco1=0.0, q=0.0, q1=0.0;
67
68 ih = 0.001; /* ih is the incremental factor */
69
70 /* Set up the pointers
71 fcoptr = p->fco;
72 resptr = p->res;
73 distptr = p->dist;
74 asymptr = p->asym; */
75
76 /* Get the values for the k-rate variables
77 fco = (SPFLOAT)*fcoptr;
78 res = (SPFLOAT)*resptr;
79 dist = (SPFLOAT)*distptr;
80 asym = (SPFLOAT)*asymptr; */
81
82 /* This should work in sp world */
83 fco = p->fco;
84 res = p->res;
85 dist = p->dist;
86 asym = p->asym;
87
88 /* Try to decouple the variables */
89 if ((p->rezcod==0) && (p->fcocod==0)) { /* Calc once only */
90 q1 = res/(1.0 + sqrt(dist));
91 fco1 = pow(fco*260.0/(1.0+q1*0.5),0.58);
92 q = q1*fco1*fco1*0.0005;
93 fc = fco1*p->onedsr*(p->sr/8.0);
94 }
95 if ((p->rezcod!=0) || (p->fcocod!=0)) {
96 q1 = res/(1.0 + sqrt(dist));
97 fco1 = pow(fco*260.0/(1.0+q1*0.5),0.58);
98 q = q1*fco1*fco1*0.0005;
99 fc = fco1*p->onedsr*(p->sr/8.0);
100 }
101 x = *in;
102 fdbk = q*y/(1.0 + exp(-3.0*y)*asym);
103 y1 = y1 + ih*((x - y1)*fc - fdbk);
104 d = -0.1*y*20.0;
105 ad = (d*d*d + y2)*100.0*dist;
106 y2 = y2 + ih*((y1 - y2)*fc + ad);
107 y = y + ih*((y2 - y)*fc);
108 *out = (y*fc/1000.0*(1.0 + q1)*3.2);
109
110 p->y = y; p->y1 = y1; p->y2 = y2;
111 return SP_OK;
112 }
113