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