rockbox/apps/plugins/pdbox/PDa/intern/vcf~.c
Peter D'Hoye 526b5580da Cut the files in half and it might work better (note to self: check your tree is really clean before patching)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21070 a1c6a512-1295-4272-9138-f99709370657
2009-05-24 21:28:16 +00:00

119 lines
3.2 KiB
C

#include <m_pd.h>
#include <m_fixed.h>
#include "cos_table.h"
/* ---------------- vcf~ - 2-pole bandpass filter. ----------------- */
/* GG: complex resonator with signal frequency control
this time using the bigger cos_table without interpolation
really have to switch to a separate fixpoint format sometime
*/
typedef struct vcfctl
{
t_sample c_re;
t_sample c_im;
t_sample c_q;
t_sample c_isr;
} t_vcfctl;
typedef struct sigvcf
{
t_object x_obj;
t_vcfctl x_cspace;
t_vcfctl *x_ctl;
float x_f;
} t_sigvcf;
t_class *sigvcf_class;
static void *sigvcf_new(t_floatarg q)
{
t_sigvcf *x = (t_sigvcf *)pd_new(sigvcf_class);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1"));
outlet_new(&x->x_obj, gensym("signal"));
outlet_new(&x->x_obj, gensym("signal"));
x->x_ctl = &x->x_cspace;
x->x_cspace.c_re = 0;
x->x_cspace.c_im = 0;
x->x_cspace.c_q = ftofix(q);
x->x_cspace.c_isr = 0;
x->x_f = 0;
return (x);
}
static void sigvcf_ft1(t_sigvcf *x, t_floatarg f)
{
x->x_ctl->c_q = (f > 0 ? ftofix(f) : 0);
}
static t_int *sigvcf_perform(t_int *w)
{
t_sample *in1 = (t_sample *)(w[1]);
t_sample *in2 = (t_sample *)(w[2]);
t_sample *out1 = (t_sample *)(w[3]);
t_sample *out2 = (t_sample *)(w[4]);
t_vcfctl *c = (t_vcfctl *)(w[5]);
int n = (t_int)(w[6]);
int i;
t_sample re = c->c_re, re2;
t_sample im = c->c_im;
t_sample q = c->c_q;
t_sample qinv = (q > 0 ? idiv(ftofix(1.0),q) : 0);
t_sample ampcorrect = ftofix(2.0f) - idiv(ftofix(2.0f) , (q + ftofix(2.0f)));
t_sample isr = c->c_isr;
t_sample coefr, coefi;
t_sample *tab = cos_table;
t_sample oneminusr,cfindx,cf,r;
for (i = 0; i < n; i++)
{
cf = mult(*in2++,isr);
if (cf < 0) cf = 0;
cfindx = mult(cf,ftofix(0.15915494))>>(fix1-ILOGCOSTABSIZE); /* 1/2*PI */
r = (qinv > 0 ? ftofix(1.01) - mult(cf,qinv) : 0);
if (r < 0) r = 0;
oneminusr = ftofix(1.02f) - r; /* hand adapted */
/* r*cos(cf) */
coefr = mult(r,tab[cfindx]);
/* r*sin(cf) */
cfindx-=(ICOSTABSIZE>>2);
cfindx += cfindx < 0 ? ICOSTABSIZE:0;
coefi = mult(r,tab[cfindx]);
re2 = re;
*out1++ = re = mult(ampcorrect,mult(oneminusr,*in1++))
+ mult(coefr,re2) - mult(coefi, im);
*out2++ = im = mult(coefi,re2) + mult(coefr,im);
}
c->c_re = re;
c->c_im = im;
return (w+7);
}
static void sigvcf_dsp(t_sigvcf *x, t_signal **sp)
{
/* TODO sr is hardcoded */
x->x_ctl->c_isr = ftofix(0.0001424758);
// idiv(ftofix(6.28318),ftofix(sp[0]->s_sr));
post("%f",fixtof(x->x_ctl->c_isr));
dsp_add(sigvcf_perform, 6,
sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec,
x->x_ctl, sp[0]->s_n);
}
void vcf_tilde_setup(void)
{
sigvcf_class = class_new(gensym("vcf~"), (t_newmethod)sigvcf_new, 0,
sizeof(t_sigvcf), 0, A_DEFFLOAT, 0);
CLASS_MAINSIGNALIN(sigvcf_class, t_sigvcf, x_f);
class_addmethod(sigvcf_class, (t_method)sigvcf_dsp, gensym("dsp"), 0);
class_addmethod(sigvcf_class, (t_method)sigvcf_ft1,
gensym("ft1"), A_FLOAT, 0);
class_sethelpsymbol(sigvcf_class, gensym("lop~-help.pd"));
}