526b5580da
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21070 a1c6a512-1295-4272-9138-f99709370657
119 lines
3.2 KiB
C
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"));
|
|
}
|
|
|