aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/vasp/source/ops_flt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'externals/grill/vasp/source/ops_flt.cpp')
-rw-r--r--externals/grill/vasp/source/ops_flt.cpp234
1 files changed, 234 insertions, 0 deletions
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<class T> 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<S>,p); }
+
+VASP_UNARY("vasp.fix",fix,true,"Bashes denormals/NANs to zero")