From 9815096db22c73cacdbb65512d1b61d633db7fa8 Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Mon, 2 Dec 2002 19:21:08 +0000 Subject: "version 0.1.1" svn path=/trunk/; revision=267 --- externals/grill/vasp/source/ops_flt.cpp | 234 ++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 externals/grill/vasp/source/ops_flt.cpp (limited to 'externals/grill/vasp/source/ops_flt.cpp') diff --git a/externals/grill/vasp/source/ops_flt.cpp b/externals/grill/vasp/source/ops_flt.cpp new file mode 100644 index 00000000..64fb74ca --- /dev/null +++ b/externals/grill/vasp/source/ops_flt.cpp @@ -0,0 +1,234 @@ +/* + +VASP modular - vector assembling signal processor / objects for Max/MSP and PD + +Copyright (c) 2002 Thomas Grill (xovo@gmx.net) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +#include "ops_flt.h" +#include "opdefs.h" +#include "util.h" + +// --- highpass --------------------------------------- + +//! \todo handle carry +//! \todo handle yield + +BL VecOp::d_fhp(OpParam &p) +{ + if(p.revdir) + post("%s - reversing operation direction due to overlap: opposite sample delay",p.opname); + +/* + R coef = (2*PI)/perln; + if(coef > 1) coef = 1; +*/ + const R coef = 1-p.flt.coef; + const I arep = abs(p.flt.rep); + S *src = p.rsdt,*dst = p.rddt; + + for(I ti = 0; ti < arep; ++ti) { + register S v1; + I i; + + // t+ direction + for(i = 0,v1 = 0; i < p.frames; ++i) { + register const S v0 = *src + coef*v1; + *dst = v0-v1; + v1 = v0; + src += p.rss,dst += p.rds; + } + + if(p.flt.rep < 0) { + if(++ti == arep) break; + + // t- direction + for(i = p.frames-1,v1 = 0; i >= 0; --i) { + src -= p.rss,dst -= p.rds; + register const S v0 = *src + coef*v1; + *dst = v0-v1; + v1 = v0; + } + } + } + + return true; +} + + +// --- lowpass --------------------------------------- + +//! \todo handle carry +//! \todo handle yield + +BL VecOp::d_flp(OpParam &p) +{ + if(p.revdir) + post("%s - reversing operation direction due to overlap: opposite sample delay",p.opname); + +/* + R coef = (2*PI)/perln; + if(coef > 1) coef = 1; +*/ + + const R coef = p.flt.coef,feed = 1-coef; + const I arep = abs(p.flt.rep); + + for(I ti = 0; ti < arep; ++ti) { + register S v1; + I i; + S *src = p.rsdt,*dst = p.rddt; + + // t+ direction + for(i = 0,v1 = 0; i < p.frames; ++i) { + v1 = *dst = coef* *src + feed*v1; + src += p.rss,dst += p.rds; + } + + if(p.flt.rep < 0) { + if(++ti == arep) break; + + // t- direction + for(i = p.frames-1,v1 = 0; i >= 0; --i) { + src -= p.rss,dst -= p.rds; + v1 = *dst = coef* *src + feed*v1; + } + } + } + + return true; +} + + + +Vasp *VaspOp::m_fhp(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst,BL hp) +{ + Vasp *ret = NULL; + if(arg.IsList() && arg.GetList().Count() >= 1) { + RVecBlock *vecs = GetRVecs(p.opname,src,dst); + if(vecs) { + p.flt.coef = 2*PI/flext::GetAFloat(arg.GetList()[0]); + if(p.flt.coef > 1) p.flt.coef = 1; + p.flt.rep = arg.GetList().Count() >= 2?flext::GetAInt(arg.GetList()[1]):1; + p.flt.rep = -p.flt.rep; // fwd/bwd operation +/* + if(p.SROvr()) { + p.SDRRev(); + post("%s - reversing operation direction due to overlap: opposite sample delay",opnm); + } +*/ + ret = DoOp(vecs,hp?VecOp::d_fhp:VecOp::d_flp,p); + + delete vecs; + } + } + + return ret; +} + +VASP_ANYOP("vasp.flp",flp,1,true,VASP_ARG(),"Passive low pass filter") +VASP_ANYOP("vasp.fhp",fhp,1,true,VASP_ARG(),"Passive high pass filter") + + +// --- integrate/differentiate + +/*! \brief Integration + \remark The delay of the result is +/- one sample, depending on the direction of the calculation + + \todo different modes how to initialize first carry? + \todo repetition count +*/ +BL VecOp::d_int(OpParam &p) +{ + if(p.revdir) + post("%s - reversed operation direction due to overlap: opposite sample delay",p.opname); + + register S d = p.intdif.carry; + register I i; + _D_LOOP(i,p.frames) + *p.rddt = (d += *p.rsdt); + p.rsdt += p.rss,p.rddt += p.rds; + _E_LOOP + p.intdif.carry = d; + return true; +} + +/*! \brief Differentiation + \remark The delay of the result is +/- one sample, depending on the direction of the calculation + + \todo different modes how to initialize first carry? + \todo repetition count +*/ +BL VecOp::d_dif(OpParam &p) +{ + if(p.revdir) + post("%s - reversed operation direction due to overlap: opposite sample delay",p.opname); + + register S d = p.intdif.carry; + register I i; + _D_LOOP(i,p.frames) + register S d1 = *p.rsdt; + *p.rddt = d1-d,d = d1; + p.rsdt += p.rss,p.rddt += p.rds; + _E_LOOP + p.intdif.carry = d; + return true; +} + +/*! \brief Does vasp integration/differentiation. + + \param arg argument list + \param dst destination vasp (NULL for in-place operation) + \param inv true for differentiation + \return normalized destination vasp +*/ +Vasp *VaspOp::m_int(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst,BL inv) +{ + Vasp *ret = NULL; + RVecBlock *vecs = GetRVecs(p.opname,src,dst); + if(vecs) { + p.intdif.carry = 0,p.intdif.rep = 1; + if(arg.IsList() && arg.GetList().Count() >= 1) p.intdif.rep = flext::GetAInt(arg.GetList()[0]); + + if(p.intdif.rep < 0) { + post("%s - invalid repetition count (%i) -> set to 1",p.opname,p.intdif.rep); + p.intdif.rep = 1; + } + + ret = DoOp(vecs,inv?VecOp::d_dif:VecOp::d_int,p); + delete vecs; + } + return ret; +} + +VASP_ANYOP("vasp.int",int,0,true,VASP_ARG_I(1),"Integration") +VASP_ANYOP("vasp.dif",dif,0,true,VASP_ARG_I(1),"Differentiation") + + + +/*! \brief Bashes denormals and NANs to zero + + \param arg argument list + \param dst destination vasp (NULL for in-place operation) + \return normalized destination vasp +*/ +template inline V f_fix(T &v,T a) +{ + if(a != a) // NAN + v = 0; + else { + // denormal bashing (doesn't propagate to the next stage) + + static const F anti_denormal = 1e-18F; + a += anti_denormal; + a -= anti_denormal; + v = a; + } +} + +BL VecOp::d_fix(OpParam &p) { D__run(f_fix,p); } + +VASP_UNARY("vasp.fix",fix,true,"Bashes denormals/NANs to zero") -- cgit v1.2.1