diff options
Diffstat (limited to 'externals/grill/vasp/source')
73 files changed, 11101 insertions, 0 deletions
diff --git a/externals/grill/vasp/source/arg.cpp b/externals/grill/vasp/source/arg.cpp new file mode 100644 index 00000000..89a6729c --- /dev/null +++ b/externals/grill/vasp/source/arg.cpp @@ -0,0 +1,216 @@ +#include "arg.h" +//#include <math.h> +#include "classes.h" + +Argument::Argument(): tp(tp_none),nxt(NULL) {} +Argument::~Argument() { ClearAll(); } + +Argument &Argument::Parse(I argc,t_atom *argv) +{ + if(argc == 0) + Clear(); + else // real? + if(argc == 1 && flext::CanbeFloat(argv[0])) + SetR(flext::GetAFloat(argv[0])); + else // complex? + if(argc == 2 && flext::CanbeFloat(argv[0]) && flext::CanbeFloat(argv[1])) + SetCX(flext::GetAFloat(argv[1]),flext::GetAFloat(argv[2])); + else // double? + if(argc >= 2 && flext::GetASymbol(argv[0]) == vasp_base::sym_double && + flext::CanbeFloat(argv[1]) && (argc == 2 || flext::CanbeFloat(argv[2])) + ) + SetR((D)flext::GetAFloat(argv[1])+(D)flext::GetAFloat(argv[2])); + else // envelope? + if(Env::ChkArgs(argc,argv)) { + Env *e = new Env(argc,argv); + if(e && e->Ok()) SetEnv(e); + else { + Clear(); + post("vasp - env argument is invalid"); + delete e; + } + } + else // vasp? + if(Vasp::ChkArgs(argc,argv)) { + Vasp *v = new Vasp(argc,argv); + if(v && v->Ok()) SetVasp(v); + else { + Clear(); + post("vasp - vasp argument is invalid"); + delete v; + } + } + else { + Clear(); + post("vasp - invalid arguments"); + } + return *this; +} + + +Argument &Argument::Clear() +{ + switch(tp) { + case tp_none: + break; + case tp_list: + if(dt.atoms) { delete dt.atoms; dt.atoms = NULL; } + break; + case tp_vasp: + if(dt.v) { delete dt.v; dt.v = NULL; } + break; + case tp_env: + if(dt.env) { delete dt.env; dt.env = NULL; } + break; + case tp_vx: + if(dt.vx) { delete dt.vx; dt.vx = NULL; } + break; + case tp_cx: + if(dt.cx) { delete dt.cx; dt.cx = NULL; } + break; + case tp_int: + case tp_float: + case tp_double: + break; + default: + error("Argument: Internal error - type unknown!"); + } + tp = tp_none; + return *this; +} + +Argument &Argument::ClearAll() +{ + Clear(); + if(nxt) { delete nxt; nxt = NULL; } + return *this; +} + +Argument &Argument::SetVasp(Vasp *v) +{ + if(tp != tp_none) Clear(); + dt.v = v; tp = tp_vasp; + return *this; +} + +Argument &Argument::SetEnv(Env *e) +{ + if(tp != tp_none) Clear(); + dt.env = e; tp = tp_env; + return *this; +} + +Argument &Argument::SetList(I argc,t_atom *argv) +{ + if(tp != tp_none) Clear(); + dt.atoms = new flext::AtomList(argc,argv); tp = tp_list; + return *this; +} + +Argument &Argument::SetR(F f) +{ + if(tp != tp_none) Clear(); + dt.f = f; tp = tp_float; + return *this; +} + +Argument &Argument::SetR(D f) +{ + if(tp != tp_none) Clear(); + dt.d = f; tp = tp_double; + return *this; +} + +Argument &Argument::SetI(I i) +{ + if(tp != tp_none) Clear(); + dt.i = i; tp = tp_int; + return *this; +} + +Argument &Argument::SetCX(F re,F im) +{ + if(tp != tp_none) Clear(); + dt.cx = new CX(re,im); tp = tp_cx; + return *this; +} + +Argument &Argument::SetVX(VX *vec) +{ + if(tp != tp_none) Clear(); + dt.vx = vec; tp = tp_vx; + return *this; +} + +I Argument::GetAInt() const { return (I)GetADouble(); } + +F Argument::GetAFloat() const { return GetADouble(); } + +D Argument::GetADouble() const +{ + if(IsInt()) return GetInt(); + else if(IsFloat()) return GetFloat(); + else if(IsDouble()) return GetDouble(); + else return 0; +} + +CX Argument::GetAComplex() const +{ + if(IsInt()) return (F)GetInt(); + else if(IsFloat()) return GetFloat(); + else if(IsDouble()) return GetDouble(); + else if(IsComplex()) return GetComplex(); + else return 0; +} + +Vasp Argument::GetAVasp() const +{ + if(IsVasp()) return GetVasp(); + else if(IsList()) return Vasp(dt.atoms->Count(),dt.atoms->Atoms()); + else return Vasp(); +} + +Env Argument::GetAEnv() const +{ + if(IsEnv()) return GetEnv(); + else if(IsList()) return Env(dt.atoms->Count(),dt.atoms->Atoms()); + else return Env(); +} + + +Argument &Argument::Add(Argument *n) +{ + if(nxt) nxt->Add(n); + else nxt = n; + return *n; +} + +Argument &Argument::Next(I i) +{ + if(i <= 0) return *this; + else { + Argument *n = Next(); + if(n) return n->Next(i-1); + else { + error("Argument: index not found!"); + return *this; + } + } +} + +Argument &Argument::AddVasp(Vasp *v) { Argument *a = new Argument; a->SetVasp(v); return Add(a); } + +Argument &Argument::AddEnv(Env *e) { Argument *a = new Argument; a->SetEnv(e); return Add(a); } + +Argument &Argument::AddList(I argc,t_atom *argv) { Argument *a = new Argument; a->SetList(argc,argv); return Add(a); } + +Argument &Argument::AddI(I i) { Argument *a = new Argument; a->SetI(i); return Add(a); } + +Argument &Argument::AddR(F f) { Argument *a = new Argument; a->SetR(f); return Add(a); } + +Argument &Argument::AddCX(F re,F im) { Argument *a = new Argument; a->SetCX(re,im); return Add(a); } + +Argument &Argument::AddVX(VX *vec) { Argument *a = new Argument; a->SetVX(vec); return Add(a); } + + + diff --git a/externals/grill/vasp/source/arg.h b/externals/grill/vasp/source/arg.h new file mode 100644 index 00000000..d6ebc378 --- /dev/null +++ b/externals/grill/vasp/source/arg.h @@ -0,0 +1,108 @@ +/* + +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. + +*/ + +#ifndef __VASP_ARG_H +#define __VASP_ARG_H + +#include "vasp.h" +#include "env.h" + +#define VASP_ARG() Argument() +#define VASP_ARG_I(VAL) Argument().SetR(VAL) +#define VASP_ARG_R(VAL) Argument().SetR(VAL) +#define VASP_ARG_CX(RV,IV) Argument().SetCX(RV,IV) + +class Argument +{ +public: + Argument(); + ~Argument(); + + Argument &Parse(I argc,t_atom *argv); + Argument &Clear(); + Argument &ClearAll(); + + Argument &SetVasp(Vasp *v); + Argument &SetEnv(Env *e); + Argument &SetList(I argc,t_atom *argv); + Argument &SetI(I i); + Argument &SetR(F f); + Argument &SetR(D d); + Argument &SetR(I i) { return SetR((F)i); } + Argument &SetCX(F re,F im); + Argument &SetVX(VX *vec); + + Argument *Next() { return nxt; } + Argument &Next(I i); + Argument &Add(Argument *a); + + Argument &AddVasp(Vasp *v); + Argument &AddEnv(Env *e); + Argument &AddList(I argc,t_atom *argv); + Argument &AddI(I i); + Argument &AddR(F f); + Argument &AddR(D d); + Argument &AddR(I i) { return AddR((F)i); } + Argument &AddCX(F re,F im); + Argument &AddVX(VX *vec); + + BL IsNone() const { return tp == tp_none; } + BL IsList() const { return tp == tp_list; } + BL IsVasp() const { return tp == tp_vasp; } + BL CanbeVasp() const { return tp == tp_vasp || (tp == tp_list && Vasp::ChkArgs(dt.atoms->Count(),dt.atoms->Atoms())); } + BL IsEnv() const { return tp == tp_env; } + BL CanbeEnv() const { return tp == tp_env || (tp == tp_env && Env::ChkArgs(dt.atoms->Count(),dt.atoms->Atoms())); } + BL IsInt() const { return tp == tp_int; } + BL CanbeInt() const { return tp == tp_int || tp == tp_float || tp_double; } + BL IsFloat() const { return tp == tp_float; } + BL CanbeFloat() const { return tp == tp_float || tp == tp_double || tp == tp_int; } + BL IsDouble() const { return tp == tp_double; } + BL CanbeDouble() const { return tp == tp_double || tp == tp_float || tp == tp_int; } + BL IsComplex() const { return tp == tp_cx; } + BL CanbeComplex() const { return tp == tp_cx || CanbeFloat(); } + BL IsVector() const { return tp == tp_vx; } + BL CanbeVector() const { return tp == tp_vx || CanbeComplex(); } + + const flext::AtomList &GetList() const { return *dt.atoms; } + const Vasp &GetVasp() const { return *dt.v; } + Vasp GetAVasp() const; + const Env &GetEnv() const { return *dt.env; } + Env GetAEnv() const; + I GetInt() const { return dt.i; } + I GetAInt() const; + F GetFloat() const { return dt.f; } + F GetAFloat() const; + D GetDouble() const { return dt.d; } + D GetADouble() const; + const CX &GetComplex() const { return *dt.cx; } + CX GetAComplex() const; + const VX &GetVector() const { return *dt.vx; } + VX GetAVector() const; + +protected: + enum { + tp_none,tp_vasp,tp_env,tp_list,tp_int,tp_float,tp_double,tp_cx,tp_vx + } tp; + + union { + Vasp *v; + Env *env; + flext::AtomList *atoms; + F f; + D d; + I i; + CX *cx; + VX *vx; + } dt; + + Argument *nxt; +}; + +#endif diff --git a/externals/grill/vasp/source/buflib.cpp b/externals/grill/vasp/source/buflib.cpp new file mode 100644 index 00000000..30b500c4 --- /dev/null +++ b/externals/grill/vasp/source/buflib.cpp @@ -0,0 +1,258 @@ +/* + +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 "buflib.h" +#include <stdio.h> + +#define LIBTICK 100 // tick time in ms +#define LIBTOL 2 // how many ticks till release + +#define REUSE_MAXLOSEREL 0.1 // max. fraction of lost buffer size +#define REUSE_MAXLOSEABS 10000 // max. lost buffer size + +#define LIBMAGIC 12349876L // magic number for s_thing data check + + +class FreeEntry +{ +public: + FreeEntry(t_symbol *s): sym(s),nxt(NULL) {} + + t_symbol *sym; + FreeEntry *nxt; +}; + +class BufEntry +{ +public: + BufEntry(t_symbol *s,I fr); + ~BufEntry(); + + V IncRef(); + V DecRef(); + +// UL magic; + t_symbol *sym; + I refcnt,tick; + BufEntry *nxt; + + I alloc,len; + S *data; +}; + + +static BufEntry *libhead = NULL,*libtail = NULL; +static FreeEntry *freehead = NULL,*freetail = NULL; +static I libcnt = 0,libtick = 0; +static t_clock *libclk = NULL; + +#ifdef FLEXT_THREADS +static flext::ThrMutex libmtx; +#endif + +static V FreeLibSym(t_symbol *s); + + + + +BufEntry::BufEntry(t_symbol *s,I fr): + sym(s), //magic(LIBMAGIC), + alloc(fr),len(fr),data(new S[fr]), + refcnt(0),nxt(NULL) +{ +// ASSERT(!flext_base::GetThing(sym)); +// flext_base::SetThing(sym,this); +} + +BufEntry::~BufEntry() +{ + if(sym) FreeLibSym(sym); + if(data) delete[] data; +} + +V BufEntry::IncRef() { ++refcnt; } +V BufEntry::DecRef() { --refcnt; tick = libtick; } + +static BufEntry *FindInLib(const t_symbol *s) +{ + BufEntry *e; + for(e = libhead; e && e->sym != s; e = e->nxt) (void)0; + return e?e:NULL; +} + +VBuffer *BufLib::Get(const VSymbol &s,I chn,I len,I offs) +{ + BufEntry *e = FindInLib(s.Symbol()); + if(e) + return new ImmBuf(e,len,offs); + else + return new SysBuf(s,chn,len,offs); +} + +V BufLib::IncRef(t_symbol *s) +{ + if(s) { + BufEntry *e = FindInLib(s); + if(e) e->IncRef(); + } +} + +V BufLib::DecRef(t_symbol *s) +{ + if(s) { + BufEntry *e = FindInLib(s); + if(e) e->DecRef(); + } +} + +static t_symbol *GetLibSym() +{ + if(freehead) { + // reuse from free-list + FreeEntry *r = freehead; + freehead = r->nxt; + if(!freehead) freetail = NULL; + t_symbol *s = r->sym; + delete r; + return s; + } + else { + // allocate new symbol + char tmp[20]; + #ifdef __MWERKS__ + std:: + #endif + sprintf(tmp,"vasp!%04i",libcnt); // what if libcnt has > 4 digits? + libcnt++; + return gensym(tmp); + } + + clock_delay(libclk,LIBTICK); +} + +static V FreeLibSym(t_symbol *sym) +{ + FreeEntry *f = new FreeEntry(sym); + if(!freehead) freehead = f; + else freetail->nxt = f; + freetail = f; +} + +static V LibTick(V *) +{ +#ifdef FLEXT_THREADS + libmtx.Lock(); +#endif + + // collect garbage + BufEntry *e,*p; + for(p = NULL,e = libhead; e; ) { + if(e->refcnt <= 0 && e->tick+LIBTOL < libtick) { + ASSERT(e->refcnt == 0); + + BufEntry *n = e->nxt; + + if(p) p->nxt = n; + else libhead = n; + + if(!n) libtail = p; + else e->nxt = NULL; + + delete e; + + e = n; + } + else + p = e,e = e->nxt; + } + + ++libtick; + clock_delay(libclk,LIBTICK); + +#ifdef FLEXT_THREADS + libmtx.Unlock(); +#endif +} + +BufEntry *BufLib::NewImm(I fr) +{ + if(!libclk) { + libclk = (t_clock *)clock_new(NULL,(t_method)LibTick); + clock_delay(libclk,LIBTICK); + } + + t_symbol *s = NULL; +// do { + s = GetLibSym(); +// } while(s->s_thing); + + BufEntry *entry = new BufEntry(s,fr); + +#ifdef FLEXT_THREADS + libmtx.Lock(); +#endif + + if(libtail) libtail->nxt = entry; + else libhead = entry; + libtail = entry; + +#ifdef FLEXT_THREADS + libmtx.Unlock(); +#endif + + return entry; +} + +static F reuse_maxloserel = (F)REUSE_MAXLOSEREL; +static I reuse_maxloseabs = REUSE_MAXLOSEABS; + +BufEntry *BufLib::Resize(BufEntry *e,I fr,BL keep) +{ + if(e->alloc >= fr && fr >= e->alloc*(1-reuse_maxloserel) && fr >= (e->alloc-reuse_maxloseabs)) { + // reuse buffer + e->len = fr; + } + else { + S *nd = new S[fr]; + if(keep) { + I l = fr; + if(e->len < l) l = e->len; + flext::CopyMem(e->data,nd,l); + } + + delete[] e->data; + e->data = nd; + e->len = e->alloc = fr; + } + return e; +} + + + +ImmBuf::ImmBuf(I len): + VBuffer(0,len), + entry(BufLib::NewImm(len)) +{} + +ImmBuf::ImmBuf(BufEntry *e,I len,I offs): + VBuffer(0,len,offs), + entry(e) +{} + +VSymbol ImmBuf::Symbol() const { return entry->sym; } + +I ImmBuf::Frames() const { return entry->len; } + +V ImmBuf::Frames(I fr,BL keep) { entry = BufLib::Resize(entry,fr,keep); } + +S *ImmBuf::Data() { return entry->data; } + + + diff --git a/externals/grill/vasp/source/buflib.h b/externals/grill/vasp/source/buflib.h new file mode 100644 index 00000000..f64bd8d1 --- /dev/null +++ b/externals/grill/vasp/source/buflib.h @@ -0,0 +1,37 @@ +/* + +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. + +*/ + +/*! \file buflib.h + \brief Routines for buffer management +*/ + +#ifndef __VASP_BUFLIB_H +#define __VASP_BUFLIB_H + +#include "classes.h" +#include "vbuffer.h" + +class BufEntry; + +namespace BufLib +{ + VBuffer *Get(const VSymbol &s,I chn = 0,I len = -1,I offs = 0); + + BufEntry *NewImm(I fr); + + V IncRef(t_symbol *s); + V DecRef(t_symbol *s); + + BufEntry *Resize(BufEntry *e,I fr,BL keep = false); +} + + + +#endif diff --git a/externals/grill/vasp/source/classes.cpp b/externals/grill/vasp/source/classes.cpp new file mode 100644 index 00000000..658cf0a7 --- /dev/null +++ b/externals/grill/vasp/source/classes.cpp @@ -0,0 +1,405 @@ +/* + +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 "classes.h" +//#include <stdarg.h> + + +/////////////////////////////////////////////////////////////////////////// +// vasp_base class +/////////////////////////////////////////////////////////////////////////// + +const t_symbol *vasp_base::sym_radio; +const t_symbol *vasp_base::sym_vasp; +const t_symbol *vasp_base::sym_env; +const t_symbol *vasp_base::sym_double; +const t_symbol *vasp_base::sym_complex; +const t_symbol *vasp_base::sym_vector; + +V vasp_base::setup(t_class *) +{ + sym_radio = MakeSymbol("radio"); + sym_vasp = MakeSymbol("vasp"); + sym_env = MakeSymbol("env"); + sym_double = MakeSymbol("double"); + sym_complex = MakeSymbol("complex"); + sym_vector = MakeSymbol("vector"); +} + +vasp_base::vasp_base(): + refresh(false),argchk(false), + unit(xsu_sample),loglvl(0) +{ + FLEXT_ADDMETHOD_(0,"radio",m_radio); + FLEXT_ADDMETHOD_(0,"argchk",m_argchk); + FLEXT_ADDMETHOD_(0,"loglvl",m_loglvl); + FLEXT_ADDMETHOD_E(0,"unit",m_unit); +} + +vasp_base::~vasp_base() {} + + +V vasp_base::m_radio(I argc,t_atom *argv) +{ + if(argc > 0 && IsSymbol(argv[0])) { + // send command to self! + m_methodmain(0,GetSymbol(argv[0]),argc-1,argv+1); + + // send command to the next objects in line + ToOutAnything(0,sym_radio,argc,argv); + } + else + post("%s - radio message invalid",thisName()); +} + + +V vasp_base::m_unit(xs_unit u) { unit = u; } +V vasp_base::m_argchk(BL chk) { argchk = chk; } +V vasp_base::m_loglvl(I lvl) { loglvl = lvl; } + + +BL vasp_base::ToOutVasp(I oix,Vasp &v) +{ + AtomList *lst = v.MakeList(false); + if(lst) { + ToOutAnything(oix,sym_vasp,lst->Count(),lst->Atoms()); + delete lst; + return true; + } + else return false; +} + +/////////////////////////////////////////////////////////////////////////// +// vasp_op class +/////////////////////////////////////////////////////////////////////////// + +vasp_op::vasp_op(BL op) +#ifdef FLEXT_THREADS + :detach(false),prior(-2), + thrid(0) +#endif +{ + FLEXT_ADDBANG(0,m_dobang); + FLEXT_ADDMETHOD_(0,"vasp",m_vasp); + FLEXT_ADDMETHOD_(0,"set",m_set); + if(op) FLEXT_ADDMETHOD_(0,"to",m_to); + + FLEXT_ADDMETHOD_(0,"update",m_update); + + FLEXT_ADDMETHOD_(0,"detach",m_detach); + FLEXT_ADDMETHOD_(0,"stop",m_stop); + FLEXT_ADDMETHOD_(0,"prior",m_prior); +} + +V vasp_op::m_dobang() +{ +#ifdef FLEXT_THREADS + if(detach) + FLEXT_CALLMETHOD(m_bang); + else +#endif + m_bang(); +} + +I vasp_op::m_set(I argc,t_atom *argv) +{ + Vasp arg(argc,argv); + + if(argc && !arg.Ok()) { + ref.Clear(); + post("%s - invalid vasp detected and ignored",thisName()); + } + else { + if(arg.Check()) + ref = arg; + else { + ref.Clear(); + post("%s - vasp reference is invalid",thisName()); + } + } + + return 0; +} + +V vasp_op::m_vasp(I argc,t_atom *argv) +{ + m_set(argc,argv); + m_dobang(); +} + +V vasp_op::m_to(I argc,t_atom *argv) +{ + Vasp to(argc,argv); + + if(argc && !to.Ok()) { + // empty vasp + dst.Clear(); + } + else + dst = to; +} + +V vasp_op::m_update(I argc,t_atom *argv) +{ + if(argc == 0) + ref.Refresh(); + else { + if(CanbeInt(argv[0])) + refresh = GetAInt(argv[0]) != 0; + else + post("%s(update) - argument should be omitted or integer",thisName()); + } +} + +V vasp_op::m_detach(BL thr) +{ +#ifdef FLEXT_THREADS + detach = thr; +#endif +} + +V vasp_op::m_prior(I p) +{ +#ifdef FLEXT_THREADS + prior = p; +#endif +} + +V vasp_op::m_stop() {} + +/////////////////////////////////////////////////////////////////////////// +// vasp_tx class +/////////////////////////////////////////////////////////////////////////// + +vasp_tx::vasp_tx(BL to): vasp_op(to) {} + +V vasp_tx::m_bang() +{ + // Thread has to wait until previous is finished + Lock(); + +#ifdef FLEXT_THREADS +// ChangePriority(prior); +#endif + + if(ref.Ok()) + { + Vasp *ret = x_work(); + if(ret) { + AtomList *lst = ret->MakeList(false); + if(lst) { + ToOutAnything(0,sym_vasp,lst->Count(),lst->Atoms()); + delete lst; + } + else + post("%s - empty list",thisName()); + if(refresh) ret->Refresh(); + delete ret; + } + else { +#ifdef _DEBUG + post("%s - no valid return",thisName()); +#endif + } + } + else { + post("%s - no valid vasp to work with",thisName()); + } + +#ifdef FLEXT_THREADS + thrid = 0; +#endif + Unlock(); +} + + +/////////////////////////////////////////////////////////////////////////// +// vasp_unop class +/////////////////////////////////////////////////////////////////////////// + +vasp_unop::vasp_unop(BL op,UL outcode): + vasp_tx(op) +{ + AddInAnything(); + AddOutAnything(1); + AddOutlets(outcode); +} + +Vasp *vasp_unop::x_work() { return tx_work(); } + +Vasp *vasp_unop::tx_work() +{ + error("%s - no work method implemented",thisName()); + return NULL; +} + +/////////////////////////////////////////////////////////////////////////// +// vasp_binop class +/////////////////////////////////////////////////////////////////////////// + + +vasp_binop::vasp_binop(I argc,t_atom *argv,const Argument &def,BL op,UL outcode): + vasp_tx(op) +{ + a_list(argc,argv); + if(arg.IsNone() && !def.IsNone()) arg = def; + + AddInAnything(2); + AddOutAnything(1); + AddOutlets(outcode); + + FLEXT_ADDMETHOD(1,a_list); + FLEXT_ADDMETHOD_(1,"vasp",a_vasp); + FLEXT_ADDMETHOD_(1,"env",a_env); + FLEXT_ADDMETHOD_(1,"float",a_float); + FLEXT_ADDMETHOD_(1,"double",a_double); + FLEXT_ADDMETHOD_(1,"int",a_int); + FLEXT_ADDMETHOD_(1,"complex",a_complex); + FLEXT_ADDMETHOD_(1,"vector",a_vector); + FLEXT_ADDMETHOD_(1,"radio",a_radio); +} + +V vasp_binop::a_list(I argc,t_atom *argv) +{ + if(argc) { + arg.Parse(argc,argv); + if(arg.IsNone()) + post("%s - list argument could not be evaluated (ignored)",thisName()); + else if(argchk) { + // check argument feasibility + } + } + else { +// post("%s - Empty list argument (ignored)",thisName()); + } +} + +V vasp_binop::a_vasp(I argc,t_atom *argv) +{ + Vasp *v = new Vasp(argc,argv); + if(v->Ok()) { + arg.SetVasp(v); + if(argchk) { + // check argument feasibility + } + } + else { + post("%s - invalid vasp argument (ignored)",thisName()); + delete v; + } +} + +V vasp_binop::a_env(I argc,t_atom *argv) +{ + Env *bp = new Env(argc,argv); + if(bp->Ok()) { + arg.SetEnv(bp); + if(argchk) { + // check argument feasibility + } + } + else { + post("%s - invalid env argument (ignored)",thisName()); + delete bp; + } +} + +V vasp_binop::a_float(F v) { arg.SetR(v); } + +V vasp_binop::a_double(I argc,t_atom *argv) +{ + if( + (argc == 1 && CanbeFloat(argv[0])) || + (argc == 2 && CanbeFloat(argv[0]) && CanbeFloat(argv[1])) + ) { + arg.SetR((D)GetAFloat(argv[0])+(D)GetAFloat(argv[1])); + if(argchk) { + // check argument feasibility + } + } + else + post("%s - invalid double argument (ignored)",thisName()); +} + +V vasp_binop::a_int(I v) { arg.SetI(v); } + +V vasp_binop::a_complex(I argc,t_atom *argv) +{ + if( + (argc == 1 && CanbeFloat(argv[0])) || + (argc == 2 && CanbeFloat(argv[0]) && CanbeFloat(argv[1])) + ) { + arg.SetCX(GetAFloat(argv[0]),GetAFloat(argv[1])); + if(argchk) { + // check argument feasibility + } + } + else + post("%s - invalid complex argument (ignored)",thisName()); +} + +V vasp_binop::a_vector(I argc,t_atom *argv) +{ + error("%s - vector type not implemented",thisName()); +} + + +Vasp *vasp_binop::x_work() { return tx_work(arg); } + +Vasp *vasp_binop::tx_work(const Argument &arg) +{ + error("%s - no work method implemented",thisName()); + return NULL; +} + + +/////////////////////////////////////////////////////////////////////////// +// vasp_anyop class +/////////////////////////////////////////////////////////////////////////// + + +vasp_anyop::vasp_anyop(I argc,t_atom *argv,const Argument &def,BL op,UL outcode): + vasp_tx(op) +{ + a_list(argc,argv); + if(arg.IsNone() && !def.IsNone()) arg = def; + + AddInAnything(2); + AddOutAnything(1); + AddOutlets(outcode); + + FLEXT_ADDMETHOD(1,a_list); + FLEXT_ADDMETHOD_(1,"vasp",a_list); + FLEXT_ADDMETHOD_(1,"radio",a_radio); +} + +V vasp_anyop::a_list(I argc,t_atom *argv) +{ + if(argc) { + arg.SetList(argc,argv); + if(arg.IsNone()) + post("%s - argument could not be evaluated (ignored)",thisName()); + else if(argchk) { + // check argument feasibility + } + } + else { +// post("%s - Empty list argument (ignored)",thisName()); + } +} + +Vasp *vasp_anyop::x_work() { return tx_work(arg); } + +Vasp *vasp_anyop::tx_work(const Argument &arg) +{ + error("%s - no work method implemented",thisName()); + return NULL; +} + diff --git a/externals/grill/vasp/source/classes.h b/externals/grill/vasp/source/classes.h new file mode 100644 index 00000000..5344f585 --- /dev/null +++ b/externals/grill/vasp/source/classes.h @@ -0,0 +1,278 @@ +/* + +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. + +*/ + +#ifndef __VASP_CLASSES_H +#define __VASP_CLASSES_H + +#include "vasp.h" +#include "arg.h" + + +class vasp_base: + public flext_base +{ + FLEXT_HEADER_S(vasp_base,flext_base,setup) + +public: + enum xs_unit { + xsu__ = -1, // don't change + xsu_sample = 0,xsu_buffer,xsu_ms,xsu_s + }; + + static const t_symbol *sym_vasp; + static const t_symbol *sym_env; + static const t_symbol *sym_double; + static const t_symbol *sym_complex; + static const t_symbol *sym_vector; + static const t_symbol *sym_radio; + +protected: + vasp_base(); + virtual ~vasp_base(); + + virtual V m_radio(I argc,t_atom *argv); // commands for all + + V m_argchk(BL chk); // precheck argument on arrival + V m_loglvl(I lvl); // noise level of log messages + V m_unit(xs_unit u); // unit command + + BL refresh; // immediate graphics refresh? + BL argchk; // pre-operation argument feasibility check + xs_unit unit; // time units + I loglvl; // noise level for log messages + + friend class Vasp; + + BL ToOutVasp(I outlet,Vasp &v); + +private: + static V setup(t_class *); + + FLEXT_CALLBACK_V(m_radio) + + FLEXT_CALLBACK_B(m_argchk) + FLEXT_CALLBACK_I(m_loglvl) + FLEXT_CALLBACK_1(m_unit,xs_unit) +}; + + +class vasp_op: + public vasp_base +{ + FLEXT_HEADER(vasp_op,vasp_base) + +protected: + vasp_op(BL withto = false); + + virtual V m_dobang(); // bang method + + virtual V m_vasp(I argc,t_atom *argv); // trigger + virtual I m_set(I argc,t_atom *argv); // non trigger + virtual V m_to(I argc,t_atom *argv); // set destination + V m_detach(BL thr); // detached thread + virtual V m_prior(I dp); // thread priority +- + virtual V m_stop(); // stop working + + virtual V m_update(I argc = 0,t_atom *argv = NULL); // graphics update + + // destination vasp + Vasp ref,dst; + + FLEXT_CALLBACK_V(m_to) + + FLEXT_CALLBACK(m_dobang) +#ifdef FLEXT_THREADS + FLEXT_THREAD(m_bang) + + ThrMutex runmtx; + V Lock() { runmtx.Lock(); } + V Unlock() { runmtx.Unlock(); } + + BL detach; // detached operation? + I prior; // thread priority + thrid_t thrid; +#else + FLEXT_CALLBACK(m_bang) + + V Lock() {} + V Unlock() {} +#endif + FLEXT_CALLBACK_V(m_vasp) + FLEXT_CALLBACK_V(m_set) + FLEXT_CALLBACK_V(m_update) + FLEXT_CALLBACK_B(m_detach) + FLEXT_CALLBACK_I(m_prior) + FLEXT_CALLBACK(m_stop) + +private: + virtual V m_bang() = 0; // do! and output current Vasp +}; + + + +class vasp_tx: + public vasp_op +{ + FLEXT_HEADER(vasp_tx,vasp_op) + +protected: + vasp_tx(BL withto = false); + + virtual V m_bang(); // do! and output current Vasp + + virtual Vasp *x_work() = 0; +}; + + + + +#define VASP_SETUP(op) FLEXT_SETUP(vasp_##op); + + + +// base class for unary operations + +class vasp_unop: + public vasp_tx +{ + FLEXT_HEADER(vasp_unop,vasp_tx) + +protected: + vasp_unop(BL withto = false,UL outcode = 0); + + virtual Vasp *x_work(); + virtual Vasp *tx_work(); +}; + + +// base class for binary operations + +class vasp_binop: + public vasp_tx +{ + FLEXT_HEADER(vasp_binop,vasp_tx) + +protected: + vasp_binop(I argc,t_atom *argv,const Argument &def = Argument(),BL withto = false,UL outcode = 0); + + // assignment functions + virtual V a_list(I argc,t_atom *argv); + /*virtual*/ V a_vasp(I argc,t_atom *argv); + /*virtual*/ V a_env(I argc,t_atom *argv); + /*virtual*/ V a_float(F f); + /*virtual*/ V a_int(I f); + /*virtual*/ V a_double(I argc,t_atom *argv); + /*virtual*/ V a_complex(I argc,t_atom *argv); + /*virtual*/ V a_vector(I argc,t_atom *argv); + + V a_radio(I,t_atom *) {} + + virtual Vasp *x_work(); + virtual Vasp *tx_work(const Argument &arg); + + Argument arg; + +private: + FLEXT_CALLBACK_V(a_list) + FLEXT_CALLBACK_V(a_vasp) + FLEXT_CALLBACK_V(a_env) + FLEXT_CALLBACK_1(a_float,F) + FLEXT_CALLBACK_1(a_int,I) + FLEXT_CALLBACK_V(a_double) + FLEXT_CALLBACK_V(a_complex) + FLEXT_CALLBACK_V(a_vector) + FLEXT_CALLBACK_V(a_radio) +}; + + +// base class for non-parsed (list) arguments + +class vasp_anyop: + public vasp_tx +{ + FLEXT_HEADER(vasp_anyop,vasp_tx) + +protected: + vasp_anyop(I argc,t_atom *argv,const Argument &def = Argument(),BL withto = false,UL outcode = 0); + + // assignment functions + virtual V a_list(I argc,t_atom *argv); + + V a_radio(I,t_atom *) {} + + virtual Vasp *x_work(); + virtual Vasp *tx_work(const Argument &arg); + + Argument arg; + +private: + FLEXT_CALLBACK_V(a_list) + FLEXT_CALLBACK_V(a_radio) +}; + + + +#define VASP_UNARY(name,op,to,help) \ +class vasp_##op: \ + public vasp_unop \ +{ \ + FLEXT_HEADER(vasp_##op,vasp_unop) \ +public: \ + vasp_##op(): vasp_unop(to) {} \ +protected: \ + virtual Vasp *tx_work() \ + { \ + OpParam p(thisName(),0); \ + return VaspOp::m_##op(p,ref,&dst); \ + } \ + virtual V m_help() { post("%s - " help,thisName()); } \ +}; \ +FLEXT_LIB("vasp," name,vasp_##op) + + +#define VASP_BINARY(name,op,to,def,help) \ +class vasp_ ## op: \ + public vasp_binop \ +{ \ + FLEXT_HEADER(vasp_##op,vasp_binop) \ +public: \ + vasp_##op(I argc,t_atom *argv): vasp_binop(argc,argv,def,to) {} \ +protected: \ + virtual Vasp *tx_work(const Argument &arg) \ + { \ + OpParam p(thisName(),1); \ + return VaspOp::m_##op(p,ref,arg,&dst); \ + } \ + virtual V m_help() { post("%s - " help,thisName()); } \ +}; \ +FLEXT_LIB_V("vasp," name,vasp_##op) + + +#define VASP_ANYOP(name,op,args,to,def,help) \ +class vasp_ ## op: \ + public vasp_anyop \ +{ \ + FLEXT_HEADER(vasp_##op,vasp_anyop) \ +public: \ + vasp_##op(I argc,t_atom *argv): vasp_anyop(argc,argv,def,to) {} \ +protected: \ + virtual Vasp *tx_work(const Argument &arg) \ + { \ + OpParam p(thisName(),args); \ + return VaspOp::m_##op(p,ref,arg,&dst); \ + } \ + virtual V m_help() { post("%s - " help,thisName()); } \ +}; \ +FLEXT_LIB_V("vasp," name,vasp_##op) + + +#define VASP__SETUP(op) FLEXT_SETUP(vasp_##op); + +#endif diff --git a/externals/grill/vasp/source/env.cpp b/externals/grill/vasp/source/env.cpp new file mode 100644 index 00000000..f846a227 --- /dev/null +++ b/externals/grill/vasp/source/env.cpp @@ -0,0 +1,144 @@ +/* + +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 "env.h" +#include "classes.h" +#include "util.h" + +Env::Env(I argc,const t_atom *argv) +{ + I ix = 0; + t_symbol *v = ix < argc?flext::GetASymbol(argv[ix]):NULL; + if(v && v == vasp_base::sym_env) ix++; // if it is "env" ignore it + + cnt = (argc-ix)/2; + pos = new R[cnt]; + val = new R[cnt]; + + R prev = -BIG; + BL ok = true; + for(I i = 0; i < cnt; ++i) { + val[i] = flext::GetAFloat(argv[ix++]); + pos[i] = flext::GetAFloat(argv[ix++]); + if(pos[i] < prev) ok = false; + prev = pos[i]; + } + + if(ix < argc) { + post("vasp - env pos/value pairs incomplete, omitted dangling value"); + } + + if(!ok) Clear(); +} + +/* +Env::Env(const Env &s): + cnt(s.cnt),pos(new R[s.cnt]),val(new R[s.cnt]) +{ + for(I i = 0; i < cnt; ++i) pos[i] = s.pos[i],val[i] = s.val[i]; +} +*/ + +Env::~Env() { Clear(); } + + +BL Env::ChkArgs(I argc,const t_atom *argv) +{ + I ix = 0; + + // vasp keyword + t_symbol *v = ix < argc?flext::GetASymbol(argv[ix]):NULL; + if(v && v == vasp_base::sym_env) ix++; // if it is "env" ignore it + + while(argc > ix) { + // check for position + if(flext::CanbeFloat(argv[ix])) ix++; + else + return false; + + // check for value + if(argc > ix) + if(flext::CanbeFloat(argv[ix])) ix++; + else + return false; + } + + return true; +} + + + +V Env::Clear() +{ + cnt = 0; + if(pos) delete[] pos; pos = NULL; + if(val) delete[] val; val = NULL; +} + + +Env::Iter::Iter(const Env &bpl): bp(bpl),ppt(-BIG),npt(BIG),pvl(0),k(0) {} + +V Env::Iter::Init(R p) +{ + I cnt = bp.Count(); + ASSERT(cnt > 0); + + if(p < bp.Pos(0)) { + // position is before the head + ix = -1; + ppt = -BIG; pvl = bp.Val(0); + } + else if(p > bp.Pos(cnt-1)) { + // position is after the tail + ix = cnt-1; + ppt = bp.Pos(ix); pvl = bp.Val(ix); + } + else { + // somewhere in the list + for(ix = 0; ix < cnt; ++ix) + if(p >= bp.Pos(ix)) break; + ppt = bp.Pos(ix); pvl = bp.Val(ix); + + ASSERT(ix < cnt); + } + + if(ix >= cnt) { + npt = BIG; nvl = pvl; + k = 0; + } + else { + npt = bp.Pos(ix+1); nvl = bp.Val(ix+1); + k = (nvl-pvl)/(npt-ppt); + } +} + +// \todo iteration first, then calculation of k +V Env::Iter::UpdateFwd(R p) +{ + do { + ppt = npt,pvl = nvl; + if(++ix >= bp.Count()-1) npt = BIG,k = 0; + else { + k = ((nvl = bp.Val(ix+1))-pvl)/((npt = bp.Pos(ix+1))-ppt); + } + } while(p > npt); +} + +// \todo iteration first, then calculation of k +V Env::Iter::UpdateBwd(R p) +{ + do { + npt = ppt,nvl = pvl; + if(--ix < 0) ppt = -BIG,k = 0; + else { + k = (nvl-(pvl = bp.Val(ix)))/(npt-(ppt = bp.Pos(ix))); + } + } while(p < ppt); +} diff --git a/externals/grill/vasp/source/env.h b/externals/grill/vasp/source/env.h new file mode 100644 index 00000000..e9f8dae7 --- /dev/null +++ b/externals/grill/vasp/source/env.h @@ -0,0 +1,73 @@ +/* + +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. + +*/ + +#ifndef __VASP_ENV_H +#define __VASP_ENV_H + +#include "vasp.h" + +class Env +{ +public: + Env(): cnt(0),pos(NULL),val(NULL) {} + Env(I argc,const t_atom *argv); +// Env(const Env &p); + ~Env(); + + static BL ChkArgs(I argc,const t_atom *argv); + + V Clear(); + + BL Ok() const { return cnt && pos != NULL && val != NULL; } + +// friend class Iter; + + class Iter + { + public: + Iter(const Env &e); + V Init(R p); + + R ValFwd(R p) + { + if(p > npt) UpdateFwd(p); + return pvl+k*(p-ppt); + } + + R ValBwd(R p) + { + if(p < ppt) UpdateBwd(p); + return pvl+k*(p-ppt); + } + + protected: + V UpdateFwd(R p); + V UpdateBwd(R p); + + const Env &bp; + I ix; + R ppt,npt; + R pvl,nvl; + R k; + }; + + I Count() const { return cnt; } + const R *Pos() const { return pos; } + const R *Val() const { return val; } + R Pos(I ix) const { return pos[ix]; } + R Val(I ix) const { return val[ix]; } + +protected: + I cnt; + R *pos,*val; +}; + +#endif + diff --git a/externals/grill/vasp/source/main.cpp b/externals/grill/vasp/source/main.cpp new file mode 100644 index 00000000..def63a43 --- /dev/null +++ b/externals/grill/vasp/source/main.cpp @@ -0,0 +1,209 @@ +/* + +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 "classes.h" + + +const C *VASP_VERSION = "0.1.1"; + +V lib_setup() +{ + post(""); + post("-----------------------------------------"); + post(" VASP modular %s ",VASP_VERSION); + post(" vector assembling signal processor "); + post(" (C)2002 Thomas Grill "); +#if defined(_DEBUG) && !defined(__MWERKS__) + post(" DEBUG BUILD - " __DATE__ " " __TIME__); +#endif + post(""); + post(" http://www.parasitaere-kapazitaeten.net "); + post("-----------------------------------------"); + post(""); + + // call the objects' setup routines + + VASP_SETUP(v); // vasp + VASP_SETUP(multi); // vasp.m + + VASP_SETUP(check); // vasp.check + VASP_SETUP(update); // vasp.update + + VASP_SETUP(sync); // vasp.sync + + VASP_SETUP(radio); // vasp.radio + + VASP_SETUP(vector); // vasp.vector + VASP_SETUP(qvectors); // vasp.vectors? + + VASP_SETUP(size); // vasp.size + VASP_SETUP(dsize); // vasp.size+ + VASP_SETUP(qsize); // vasp.size? + VASP_SETUP(msize); // vasp.size* + VASP_SETUP(rsize); // vasp.size/ + + VASP_SETUP(offset); // vasp.offset + VASP_SETUP(doffset); // vasp.offset+ + VASP_SETUP(qoffset); // vasp.offset? + + VASP_SETUP(frames); // vasp.frames + VASP_SETUP(dframes); // vasp.frames+ + VASP_SETUP(qframes); // vasp.frames? + VASP_SETUP(mframes); // vasp.frames* + VASP_SETUP(rframes); // vasp.frames/ + + VASP_SETUP(channel); // vasp.channel + VASP_SETUP(qchannel); // vasp.channel? + + VASP_SETUP(split); + VASP_SETUP(join); + VASP_SETUP(spit); + VASP_SETUP(gather); + VASP_SETUP(part); + + VASP_SETUP(list); + VASP_SETUP(nonzero); + + VASP_SETUP(imm); // vasp.imm + + VASP__SETUP(set); + VASP__SETUP(cset); + VASP_SETUP(copy); + VASP_SETUP(ccopy); + + VASP__SETUP(add); + VASP__SETUP(cadd); + VASP__SETUP(sub); + VASP__SETUP(csub); + VASP__SETUP(subr); + VASP__SETUP(csubr); + VASP__SETUP(mul); + VASP__SETUP(cmul); + VASP__SETUP(div); + VASP__SETUP(cdiv); + VASP__SETUP(divr); + VASP__SETUP(cdivr); + VASP__SETUP(mod); + + VASP__SETUP(sign) + VASP__SETUP(abs) + VASP__SETUP(cabs) + + VASP__SETUP(lwr) + VASP__SETUP(gtr) + VASP__SETUP(alwr) + VASP__SETUP(agtr) + VASP__SETUP(leq) + VASP__SETUP(geq) + VASP__SETUP(aleq) + VASP__SETUP(ageq) + VASP__SETUP(equ) + VASP__SETUP(neq) + + VASP__SETUP(min) + VASP__SETUP(rmin) + VASP__SETUP(max) + VASP__SETUP(rmax) + + VASP__SETUP(minmax) + + VASP_SETUP(qmin) + VASP_SETUP(qmax) + VASP_SETUP(qamin) + VASP_SETUP(qamax) + VASP_SETUP(qrmin) + VASP_SETUP(qrmax) + + VASP__SETUP(gate); + VASP__SETUP(rgate); +// VASP__SETUP(igate); +// VASP__SETUP(rigate); + + VASP_SETUP(peaks) + VASP_SETUP(valleys) + VASP_SETUP(rpeaks) + VASP_SETUP(rvalleys) + + VASP_SETUP(qpeaks); + +/* + VASP_SETUP(qvalleys); + VASP_SETUP(qrpeaks); + VASP_SETUP(qrvalleys); +*/ + + VASP__SETUP(sqr) + VASP__SETUP(ssqr) + VASP__SETUP(csqr) + VASP__SETUP(sqrt) + VASP__SETUP(ssqrt) + VASP__SETUP(pow) + VASP__SETUP(cpowi) + VASP__SETUP(rpow); + VASP__SETUP(radd); + + VASP__SETUP(exp) + VASP__SETUP(log) + + VASP__SETUP(polar) + VASP__SETUP(rect) + + VASP__SETUP(cnorm) +// VASP__SETUP(cswap) + VASP__SETUP(cconj) + + VASP_SETUP(shift) + VASP_SETUP(xshift) + VASP__SETUP(rot) + VASP__SETUP(xrot) + VASP__SETUP(mirr) + VASP__SETUP(xmirr) + + VASP__SETUP(osc) + VASP__SETUP(mosc) + VASP__SETUP(cosc) + VASP__SETUP(mcosc) + VASP__SETUP(phasor) + VASP__SETUP(mphasor) + VASP__SETUP(noise) + VASP__SETUP(cnoise) + + VASP__SETUP(window) + VASP__SETUP(mwindow) + VASP__SETUP(iwindow) + VASP__SETUP(miwindow) + VASP__SETUP(xwindow) + VASP__SETUP(mxwindow) + + VASP__SETUP(flp) + VASP__SETUP(fhp) + + VASP__SETUP(int) + VASP__SETUP(dif) + + VASP__SETUP(fix) + + VASP__SETUP(tilt) + VASP__SETUP(xtilt) + + VASP__SETUP(soffset) + VASP__SETUP(sframes) + + VASP__SETUP(rfft) + VASP__SETUP(rifft) + VASP__SETUP(cfft) + VASP__SETUP(cifft) +} + +FLEXT_LIB_SETUP(vasp,lib_setup) + +/////////////////////////////////////////////////////////////////////////// + + diff --git a/externals/grill/vasp/source/main.h b/externals/grill/vasp/source/main.h new file mode 100644 index 00000000..53d732c2 --- /dev/null +++ b/externals/grill/vasp/source/main.h @@ -0,0 +1,83 @@ +/* + +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. + +*/ + +#ifndef __VASP_H +#define __VASP_H + +#include <flext.h> + +#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 400) +#error You need at least flext version 0.4.0 +#endif + + +#include <typeinfo> +#include <stdlib.h> + +class complex; +class vector; + +#if 0 + #define I int + #define L long + #define UL unsigned long + #define F float + #define D double + #define C char + #define BL bool + #define V void + #define S t_sample // type for samples + #define R double // type for internal calculations + #define CX complex + #define VX vector +#else + typedef int I; + typedef long L; + typedef unsigned long UL; + typedef float F; + typedef double D; + typedef char C; + typedef bool BL; + typedef void V; + typedef t_sample S; // type for samples + typedef double R; // type for internal calculations + typedef complex CX; + typedef vector VX; +#endif + +#ifdef PD +// buffers are never interleaved - special optimizations may occur +// attention: possibly obsolete when immediate file access is implemented +#define VASP_CHN1 +#endif + +class complex +{ +public: + complex() {} + complex(F re,F im = 0): real(re),imag(im) {} + + F real,imag; +}; + +class vector +{ +public: + vector(): dim(0),data(NULL) {} + ~vector() { if(data) delete[] data; } + + I Dim() const { return dim; } + F *Data() { return data; } + const F *Data() const { return data; } +protected: + I dim; F *data; +}; + +#endif diff --git a/externals/grill/vasp/source/mixfft.cpp b/externals/grill/vasp/source/mixfft.cpp new file mode 100644 index 00000000..975e8cb1 --- /dev/null +++ b/externals/grill/vasp/source/mixfft.cpp @@ -0,0 +1,588 @@ + +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +#ifdef _MSC_VER +#pragma warning(disable: 4244) +#endif + +/************************************************************************ + fft(int n, double xRe[], double xIm[], double yRe[], double yIm[]) + ------------------------------------------------------------------------ + NOTE : This is copyrighted material, Not public domain. See below. + ------------------------------------------------------------------------ + Input/output: + int n transformation length. + double xRe[] real part of input sequence. + double xIm[] imaginary part of input sequence. + double yRe[] real part of output sequence. + double yIm[] imaginary part of output sequence. + ------------------------------------------------------------------------ + Function: + The procedure performs a fast discrete Fourier transform (FFT) of + a complex sequence, x, of an arbitrary length, n. The output, y, + is also a complex sequence of length n. + + y[k] = sum(x[m]*exp(-i*2*pi*k*m/n), m=0..(n-1)), k=0,...,(n-1) + + The largest prime factor of n must be less than or equal to the + constant maxPrimeFactor defined below. + ------------------------------------------------------------------------ + Author: + Jens Joergen Nielsen For non-commercial use only. + Bakkehusene 54 A $100 fee must be paid if used + DK-2970 Hoersholm commercially. Please contact. + DENMARK + + E-mail : jjn@get2net.dk All rights reserved. October 2000. + Homepage : http://home.get2net.dk/jjn + ------------------------------------------------------------------------ + Implementation notes: + The general idea is to factor the length of the DFT, n, into + factors that are efficiently handled by the routines. + + A number of short DFT's are implemented with a minimum of + arithmetical operations and using (almost) straight line code + resulting in very fast execution when the factors of n belong + to this set. Especially radix-10 is optimized. + + Prime factors, that are not in the set of short DFT's are handled + with direct evaluation of the DFP expression. + + Please report any problems to the author. + Suggestions and improvements are welcomed. + ------------------------------------------------------------------------ + Benchmarks: + The Microsoft Visual C++ compiler was used with the following + compile options: + /nologo /Gs /G2 /W4 /AH /Ox /D "NDEBUG" /D "_DOS" /FR + and the FFTBENCH test executed on a 50MHz 486DX : + + Length Time [s] Accuracy [dB] + + 128 0.0054 -314.8 + 256 0.0116 -309.8 + 512 0.0251 -290.8 + 1024 0.0567 -313.6 + 2048 0.1203 -306.4 + 4096 0.2600 -291.8 + 8192 0.5800 -305.1 + 100 0.0040 -278.5 + 200 0.0099 -280.3 + 500 0.0256 -278.5 + 1000 0.0540 -278.5 + 2000 0.1294 -280.6 + 5000 0.3300 -278.4 + 10000 0.7133 -278.5 + ------------------------------------------------------------------------ + The following procedures are used : + factorize : factor the transformation length. + transTableSetup : setup table with sofar-, actual-, and remainRadix. + permute : permutation allows in-place calculations. + twiddleTransf : twiddle multiplications and DFT's for one stage. + initTrig : initialise sine/cosine table. + fft_4 : length 4 DFT, a la Nussbaumer. + fft_5 : length 5 DFT, a la Nussbaumer. + fft_10 : length 10 DFT using prime factor FFT. + fft_odd : length n DFT, n odd. +*************************************************************************/ + +/************************************************************************ + + changes by Thomas Grill: + + - introduced REAL type for numbers + - made functions static + - threw fft_n functions out of twiddleTransf + if feasible, these will be inlined by the compiler + - changed log prints (to post) + +************************************************************************/ + +#define REAL float +extern "C" void post(const char *c,...); + +/************************************************************************/ + + +#define maxPrimeFactor 8000 // all static data should fit into 256kB of cache +#define maxPrimeFactorDiv2 (maxPrimeFactor+1)/2 +#define maxFactorCount 100 + +static double c3_1 = -1.5000000000000E+00; /* c3_1 = cos(2*pi/3)-1; */ +static double c3_2 = 8.6602540378444E-01; /* c3_2 = sin(2*pi/3); */ + +static double u5 = 1.2566370614359E+00; /* u5 = 2*pi/5; */ +static double c5_1 = -1.2500000000000E+00; /* c5_1 = (cos(u5)+cos(2*u5))/2-1;*/ +static double c5_2 = 5.5901699437495E-01; /* c5_2 = (cos(u5)-cos(2*u5))/2; */ +static double c5_3 = -9.5105651629515E-01; /* c5_3 = -sin(u5); */ +static double c5_4 = -1.5388417685876E+00; /* c5_4 = -(sin(u5)+sin(2*u5)); */ +static double c5_5 = 3.6327126400268E-01; /* c5_5 = (sin(u5)-sin(2*u5)); */ +static double c8 = 7.0710678118655E-01; /* c8 = 1/sqrt(2); */ + +static double pi; +static int groupOffset,dataOffset,blockOffset,adr; +static int groupNo,dataNo,blockNo,twNo; +static double omega; +static REAL tw_re,tw_im; +static REAL twiddleRe[maxPrimeFactor], twiddleIm[maxPrimeFactor]; +static REAL trigRe[maxPrimeFactor], trigIm[maxPrimeFactor]; +static REAL zRe[maxPrimeFactor], zIm[maxPrimeFactor]; +static REAL vRe[maxPrimeFactorDiv2], vIm[maxPrimeFactorDiv2]; +static REAL wRe[maxPrimeFactorDiv2], wIm[maxPrimeFactorDiv2]; + + +static void factorize(int n, int *nFact, int fact[]) +{ + int i,j,k; + int nRadix; + int radices[7]; + int factors[maxFactorCount]; + + nRadix = 6; + radices[1]= 2; + radices[2]= 3; + radices[3]= 4; + radices[4]= 5; + radices[5]= 8; + radices[6]= 10; + + if (n==1) + { + j=1; + factors[1]=1; + } + else j=0; + i=nRadix; + while ((n>1) && (i>0)) + { + if ((n % radices[i]) == 0) + { + n=n / radices[i]; + j=j+1; + factors[j]=radices[i]; + } + else i=i-1; + } + if (factors[j] == 2) /*substitute factors 2*8 with 4*4 */ + { + i = j-1; + while ((i>0) && (factors[i] != 8)) i--; + if (i>0) + { + factors[j] = 4; + factors[i] = 4; + } + } + if (n>1) + { + for (k=2; k<sqrt(n)+1; k++) + while ((n % k) == 0) + { + n=n / k; + j=j+1; + factors[j]=k; + } + if (n>1) + { + j=j+1; + factors[j]=n; + } + } + for (i=1; i<=j; i++) + { + fact[i] = factors[j-i+1]; + } + *nFact=j; +} /* factorize */ + +/**************************************************************************** + After N is factored the parameters that control the stages are generated. + For each stage we have: + sofar : the product of the radices so far. + actual : the radix handled in this stage. + remain : the product of the remaining radices. + ****************************************************************************/ + +static bool transTableSetup(int sofar[], int actual[], int remain[], + int *nFact, + int *nPoints) +{ + int i; + + factorize(*nPoints, nFact, actual); + if (actual[1] > maxPrimeFactor) + { + // T.Grill - replaced the printfs by a post + post("FFT: Prime factor of FFT length is too large (%d) - aborted",actual[1]); + return false; + } + + remain[0]=*nPoints; + sofar[1]=1; + remain[1]=*nPoints / actual[1]; + for (i=2; i<=*nFact; i++) + { + sofar[i]=sofar[i-1]*actual[i-1]; + remain[i]=remain[i-1] / actual[i]; + } + return true; +} /* transTableSetup */ + +/**************************************************************************** + The sequence y is the permuted input sequence x so that the following + transformations can be performed in-place, and the final result is the + normal order. + ****************************************************************************/ + +static void permute(int nPoint, int nFact, + int fact[], int remain[], + REAL xRe[], REAL xIm[], + REAL yRe[], REAL yIm[]) + +{ + int i,j,k; + int count[maxFactorCount]; + + for (i=1; i<=nFact; i++) count[i]=0; + k=0; + for (i=0; i<=nPoint-2; i++) + { + yRe[i] = xRe[k]; + yIm[i] = xIm[k]; + j=1; + k=k+remain[j]; + count[1] = count[1]+1; + while (count[j] >= fact[j]) + { + count[j]=0; + k=k-remain[j-1]+remain[j+1]; + j=j+1; + count[j]=count[j]+1; + } + } + yRe[nPoint-1]=xRe[nPoint-1]; + yIm[nPoint-1]=xIm[nPoint-1]; +} /* permute */ + + +/**************************************************************************** + Twiddle factor multiplications and transformations are performed on a + group of data. The number of multiplications with 1 are reduced by skipping + the twiddle multiplication of the first stage and of the first group of the + following stages. + ***************************************************************************/ + +static void initTrig(int radix) +{ + int i; + double w,xre,xim,xre1,xim1; + + w=2*pi/radix; + trigRe[0]=1; trigIm[0]=0; + xre1=xre=cos(w); + xim1=xim=-sin(w); + trigRe[1]=xre; trigIm[1]=xim; + for (i=2; i<radix; i++) + { + trigRe[i] = xre1 = xre*trigRe[i-1] - xim*trigIm[i-1]; + trigIm[i] = xim1 = xim*trigRe[i-1] + xre*trigIm[i-1]; +// trigRe[i] = xre1 = xre*xre1 - xim*xim1; +// trigIm[i] = xim1 = xim*xre1 + xre*xim1; + } +} /* initTrig */ + +static void fft_2(REAL aRe[], REAL aIm[]) +{ + double gem; + gem=zRe[0] + zRe[1]; + zRe[1]=zRe[0] - zRe[1]; zRe[0]=gem; + gem=zIm[0] + zIm[1]; + zIm[1]=zIm[0] - zIm[1]; zIm[0]=gem; +} + +static void fft_3(REAL aRe[], REAL aIm[]) +{ + REAL t1_re,t1_im; + REAL m2_re,m2_im; + REAL m1_re,m1_im; + REAL s1_re,s1_im; + t1_re=zRe[1] + zRe[2]; t1_im=zIm[1] + zIm[2]; + zRe[0]=zRe[0] + t1_re; zIm[0]=zIm[0] + t1_im; + m1_re=c3_1*t1_re; m1_im=c3_1*t1_im; + m2_re=c3_2*(zIm[1] - zIm[2]); + m2_im=c3_2*(zRe[2] - zRe[1]); + s1_re=zRe[0] + m1_re; s1_im=zIm[0] + m1_im; + zRe[1]=s1_re + m2_re; zIm[1]=s1_im + m2_im; + zRe[2]=s1_re - m2_re; zIm[2]=s1_im - m2_im; +} + +static void fft_4(REAL aRe[], REAL aIm[]) +{ + REAL t1_re,t1_im, t2_re,t2_im; + REAL m2_re,m2_im, m3_re,m3_im; + + t1_re=aRe[0] + aRe[2]; t1_im=aIm[0] + aIm[2]; + t2_re=aRe[1] + aRe[3]; t2_im=aIm[1] + aIm[3]; + + m2_re=aRe[0] - aRe[2]; m2_im=aIm[0] - aIm[2]; + m3_re=aIm[1] - aIm[3]; m3_im=aRe[3] - aRe[1]; + + aRe[0]=t1_re + t2_re; aIm[0]=t1_im + t2_im; + aRe[2]=t1_re - t2_re; aIm[2]=t1_im - t2_im; + aRe[1]=m2_re + m3_re; aIm[1]=m2_im + m3_im; + aRe[3]=m2_re - m3_re; aIm[3]=m2_im - m3_im; +} /* fft_4 */ + + +static void fft_5(REAL aRe[], REAL aIm[]) +{ + REAL t1_re,t1_im, t2_re,t2_im, t3_re,t3_im; + REAL t4_re,t4_im, t5_re,t5_im; + REAL m2_re,m2_im, m3_re,m3_im, m4_re,m4_im; + REAL m1_re,m1_im, m5_re,m5_im; + REAL s1_re,s1_im, s2_re,s2_im, s3_re,s3_im; + REAL s4_re,s4_im, s5_re,s5_im; + + t1_re=aRe[1] + aRe[4]; t1_im=aIm[1] + aIm[4]; + t2_re=aRe[2] + aRe[3]; t2_im=aIm[2] + aIm[3]; + t3_re=aRe[1] - aRe[4]; t3_im=aIm[1] - aIm[4]; + t4_re=aRe[3] - aRe[2]; t4_im=aIm[3] - aIm[2]; + t5_re=t1_re + t2_re; t5_im=t1_im + t2_im; + aRe[0]=aRe[0] + t5_re; aIm[0]=aIm[0] + t5_im; + m1_re=c5_1*t5_re; m1_im=c5_1*t5_im; + m2_re=c5_2*(t1_re - t2_re); m2_im=c5_2*(t1_im - t2_im); + + m3_re=-c5_3*(t3_im + t4_im); m3_im=c5_3*(t3_re + t4_re); + m4_re=-c5_4*t4_im; m4_im=c5_4*t4_re; + m5_re=-c5_5*t3_im; m5_im=c5_5*t3_re; + + s3_re=m3_re - m4_re; s3_im=m3_im - m4_im; + s5_re=m3_re + m5_re; s5_im=m3_im + m5_im; + s1_re=aRe[0] + m1_re; s1_im=aIm[0] + m1_im; + s2_re=s1_re + m2_re; s2_im=s1_im + m2_im; + s4_re=s1_re - m2_re; s4_im=s1_im - m2_im; + + aRe[1]=s2_re + s3_re; aIm[1]=s2_im + s3_im; + aRe[2]=s4_re + s5_re; aIm[2]=s4_im + s5_im; + aRe[3]=s4_re - s5_re; aIm[3]=s4_im - s5_im; + aRe[4]=s2_re - s3_re; aIm[4]=s2_im - s3_im; +} /* fft_5 */ + +static void fft_8() +{ + REAL aRe[4], aIm[4], bRe[4], bIm[4], gem; + + aRe[0] = zRe[0]; bRe[0] = zRe[1]; + aRe[1] = zRe[2]; bRe[1] = zRe[3]; + aRe[2] = zRe[4]; bRe[2] = zRe[5]; + aRe[3] = zRe[6]; bRe[3] = zRe[7]; + + aIm[0] = zIm[0]; bIm[0] = zIm[1]; + aIm[1] = zIm[2]; bIm[1] = zIm[3]; + aIm[2] = zIm[4]; bIm[2] = zIm[5]; + aIm[3] = zIm[6]; bIm[3] = zIm[7]; + + fft_4(aRe, aIm); fft_4(bRe, bIm); + + gem = c8*(bRe[1] + bIm[1]); + bIm[1] = c8*(bIm[1] - bRe[1]); + bRe[1] = gem; + gem = bIm[2]; + bIm[2] =-bRe[2]; + bRe[2] = gem; + gem = c8*(bIm[3] - bRe[3]); + bIm[3] =-c8*(bRe[3] + bIm[3]); + bRe[3] = gem; + + zRe[0] = aRe[0] + bRe[0]; zRe[4] = aRe[0] - bRe[0]; + zRe[1] = aRe[1] + bRe[1]; zRe[5] = aRe[1] - bRe[1]; + zRe[2] = aRe[2] + bRe[2]; zRe[6] = aRe[2] - bRe[2]; + zRe[3] = aRe[3] + bRe[3]; zRe[7] = aRe[3] - bRe[3]; + + zIm[0] = aIm[0] + bIm[0]; zIm[4] = aIm[0] - bIm[0]; + zIm[1] = aIm[1] + bIm[1]; zIm[5] = aIm[1] - bIm[1]; + zIm[2] = aIm[2] + bIm[2]; zIm[6] = aIm[2] - bIm[2]; + zIm[3] = aIm[3] + bIm[3]; zIm[7] = aIm[3] - bIm[3]; +} /* fft_8 */ + +static void fft_10() +{ + REAL aRe[5], aIm[5], bRe[5], bIm[5]; + + aRe[0] = zRe[0]; bRe[0] = zRe[5]; + aRe[1] = zRe[2]; bRe[1] = zRe[7]; + aRe[2] = zRe[4]; bRe[2] = zRe[9]; + aRe[3] = zRe[6]; bRe[3] = zRe[1]; + aRe[4] = zRe[8]; bRe[4] = zRe[3]; + + aIm[0] = zIm[0]; bIm[0] = zIm[5]; + aIm[1] = zIm[2]; bIm[1] = zIm[7]; + aIm[2] = zIm[4]; bIm[2] = zIm[9]; + aIm[3] = zIm[6]; bIm[3] = zIm[1]; + aIm[4] = zIm[8]; bIm[4] = zIm[3]; + + fft_5(aRe, aIm); fft_5(bRe, bIm); + + zRe[0] = aRe[0] + bRe[0]; zRe[5] = aRe[0] - bRe[0]; + zRe[6] = aRe[1] + bRe[1]; zRe[1] = aRe[1] - bRe[1]; + zRe[2] = aRe[2] + bRe[2]; zRe[7] = aRe[2] - bRe[2]; + zRe[8] = aRe[3] + bRe[3]; zRe[3] = aRe[3] - bRe[3]; + zRe[4] = aRe[4] + bRe[4]; zRe[9] = aRe[4] - bRe[4]; + + zIm[0] = aIm[0] + bIm[0]; zIm[5] = aIm[0] - bIm[0]; + zIm[6] = aIm[1] + bIm[1]; zIm[1] = aIm[1] - bIm[1]; + zIm[2] = aIm[2] + bIm[2]; zIm[7] = aIm[2] - bIm[2]; + zIm[8] = aIm[3] + bIm[3]; zIm[3] = aIm[3] - bIm[3]; + zIm[4] = aIm[4] + bIm[4]; zIm[9] = aIm[4] - bIm[4]; +} /* fft_10 */ + +static void fft_odd(int radix) +{ + REAL rere, reim, imre, imim; + int i,j,k,n,max; + + n = radix; + max = (n + 1)/2; + for (j=1; j < max; j++) + { + vRe[j] = zRe[j] + zRe[n-j]; + vIm[j] = zIm[j] - zIm[n-j]; + wRe[j] = zRe[j] - zRe[n-j]; + wIm[j] = zIm[j] + zIm[n-j]; + } + + for (j=1; j < max; j++) + { + zRe[j]=zRe[0]; + zIm[j]=zIm[0]; + zRe[n-j]=zRe[0]; + zIm[n-j]=zIm[0]; + k=j; + for (i=1; i < max; i++) + { + rere = trigRe[k] * vRe[i]; + imim = trigIm[k] * vIm[i]; + reim = trigRe[k] * wIm[i]; + imre = trigIm[k] * wRe[i]; + + zRe[n-j] += rere + imim; + zIm[n-j] += reim - imre; + zRe[j] += rere - imim; + zIm[j] += reim + imre; + + k = k + j; + if (k >= n) k = k - n; + } + } + for (j=1; j < max; j++) + { + zRe[0]=zRe[0] + vRe[j]; + zIm[0]=zIm[0] + wIm[j]; + } +} /* fft_odd */ + + +static void twiddleTransf(int sofarRadix, int radix, int remainRadix, + REAL yRe[], REAL yIm[]) + +{ /* twiddleTransf */ + double cosw, sinw, gem; + + initTrig(radix); + omega = 2*pi/(double)(sofarRadix*radix); + cosw = cos(omega); + sinw = -sin(omega); + tw_re = 1.0; + tw_im = 0; + dataOffset=0; + groupOffset=dataOffset; + adr=groupOffset; + for (dataNo=0; dataNo<sofarRadix; dataNo++) + { + if (sofarRadix>1) + { + twiddleRe[0] = 1.0; + twiddleIm[0] = 0.0; + twiddleRe[1] = tw_re; + twiddleIm[1] = tw_im; + for (twNo=2; twNo<radix; twNo++) + { + twiddleRe[twNo]=tw_re*twiddleRe[twNo-1] + - tw_im*twiddleIm[twNo-1]; + twiddleIm[twNo]=tw_im*twiddleRe[twNo-1] + + tw_re*twiddleIm[twNo-1]; + } + gem = cosw*tw_re - sinw*tw_im; + tw_im = sinw*tw_re + cosw*tw_im; + tw_re = gem; + } + for (groupNo=0; groupNo<remainRadix; groupNo++) + { + if ((sofarRadix>1) && (dataNo > 0)) + { + zRe[0]=yRe[adr]; + zIm[0]=yIm[adr]; + blockNo=1; + do { + adr = adr + sofarRadix; + zRe[blockNo]= twiddleRe[blockNo] * yRe[adr] + - twiddleIm[blockNo] * yIm[adr]; + zIm[blockNo]= twiddleRe[blockNo] * yIm[adr] + + twiddleIm[blockNo] * yRe[adr]; + + blockNo++; + } while (blockNo < radix); + } + else + for (blockNo=0; blockNo<radix; blockNo++) + { + zRe[blockNo]=yRe[adr]; + zIm[blockNo]=yIm[adr]; + adr=adr+sofarRadix; + } + switch(radix) { + // T.Grill - replaced the inlined code by their function counterparts + case 2 : fft_2(zRe,zIm); break; + case 3 : fft_3(zRe,zIm); break; + case 4 : fft_4(zRe,zIm); break; + case 5 : fft_5(zRe,zIm); break; + case 8 : fft_8(); break; + case 10 : fft_10(); break; + default : fft_odd(radix); break; + } + adr=groupOffset; + for (blockNo=0; blockNo<radix; blockNo++) + { + yRe[adr]=zRe[blockNo]; yIm[adr]=zIm[blockNo]; + adr=adr+sofarRadix; + } + groupOffset=groupOffset+sofarRadix*radix; + adr=groupOffset; + } + dataOffset=dataOffset+1; + groupOffset=dataOffset; + adr=groupOffset; + } +} /* twiddleTransf */ + +bool mixfft(int n, REAL *xRe, REAL *xIm,REAL *yRe, REAL *yIm) +{ + int sofarRadix[maxFactorCount], + actualRadix[maxFactorCount], + remainRadix[maxFactorCount]; + int nFactor; + int count; + + pi = 4*atan(1); + + if(!transTableSetup(sofarRadix, actualRadix, remainRadix, &nFactor, &n)) return false; + permute(n, nFactor, actualRadix, remainRadix, xRe, xIm, yRe, yIm); + + for (count=1; count<=nFactor; count++) + twiddleTransf(sofarRadix[count], actualRadix[count], remainRadix[count], + yRe, yIm); + return true; +} /* fft */ + diff --git a/externals/grill/vasp/source/obj_chns.cpp b/externals/grill/vasp/source/obj_chns.cpp new file mode 100755 index 00000000..1cd15c30 --- /dev/null +++ b/externals/grill/vasp/source/obj_chns.cpp @@ -0,0 +1,107 @@ +/* + +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 "classes.h" +#include "util.h" + + +/*! \class vasp_channel + \remark \b vasp.channel + \brief Sets channel index of vasp. + \since 0.0.8 + \param cmdln.1 int - index of vasp vector + \param inlet vasp - is stored and indexed vasp vector output + \param inlet bang - triggers indexed vasp vector output + \param inlet set - vasp to be stored (and not immediately output) + \retval outlet modified vasp +*/ +class vasp_channel: + public vasp_tx +{ + FLEXT_HEADER(vasp_channel,vasp_tx) + +public: + vasp_channel(I argc,t_atom *argv): + ix(0) + { + if(argc >= 1 && CanbeInt(argv[0])) + ix = GetAInt(argv[0]); + else if(argc) + post("%s - Index argument invalid -> set to 0",thisName()); + + AddInAnything(2); + AddOutAnything(); + SetupInOut(); + + FLEXT_ADDMETHOD(1,m_ix); + } + + V m_ix(I i) { ix = i; } + + virtual Vasp *x_work() + { + Vasp *ret = new Vasp(ref); + ret->Channel(ix); + return ret; + } + + virtual V m_help() { post("%s - Set channel index of vectors in vasp",thisName()); } + +protected: + I ix; + +private: + FLEXT_CALLBACK_I(m_ix); +}; + +FLEXT_LIB_V("vasp, vasp.channel vasp.c",vasp_channel) + + + +/*! \class vasp_qc + \remark \b vasp.c? + \brief Gets channel index of a vasp. + \since 0.0.8 + \param inlet vasp - is stored and output triggered + \param inlet bang - triggers output + \param inlet set - vasp to be stored + \retval outlet int - channel index of stored vasp + + \note Always returns index of 0th vasp + \note No output for invalid vasp? +*/ +class vasp_qchannel: + public vasp_op +{ + FLEXT_HEADER(vasp_qchannel,vasp_op) + +public: + vasp_qchannel() + { + AddInAnything(); + AddOutInt(); + SetupInOut(); + } + + virtual V m_bang() + { + if(ref.Ok()) + ToOutInt(0,ref.Vector(0).Channel()); + else + post("%s - Invalid vasp, no output",thisName()); + } + + virtual V m_help() { post("%s - Get channel index of 0th vector in vasp",thisName()); } +}; + +FLEXT_LIB("vasp, vasp.channel? vasp.c?",vasp_qchannel) + + + diff --git a/externals/grill/vasp/source/obj_frames.cpp b/externals/grill/vasp/source/obj_frames.cpp new file mode 100644 index 00000000..70210d61 --- /dev/null +++ b/externals/grill/vasp/source/obj_frames.cpp @@ -0,0 +1,228 @@ +/* + +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 "classes.h" +#include "util.h" + + +/*! \class vasp_frames + \remark \b vasp.frames + \brief Sets frame count of vasp. + \since 0.0.1 + \param cmdln.1 [_time=0] - frame count in time units + \param inlet.1 vasp - is stored and output triggered + \param inlet.1 bang - triggers output + \param inlet.1 set - vasp to be stored + \param inlet.2 _time - frame count in time units + \retval outlet vasp - modified vasp + + \todo Implement unit processing. +*/ +class vasp_frames: + public vasp_tx +{ + FLEXT_HEADER(vasp_frames,vasp_tx) + +public: + vasp_frames(I argc,t_atom *argv): + frms(0),setf(false) + { + if(argc && CanbeFloat(argv[0])) + m_arg(GetAFloat(argv[0])); + else if(argc) { + post("%s - argument invalid -> ignored",thisName()); + } + + AddInAnything(); + AddInFloat(); + AddOutAnything(); + SetupInOut(); + + FLEXT_ADDMETHOD(1,m_arg); + } + + virtual V m_arg(F f) + { + frms = (I)f; //! \todo unit processing + setf = true; + } + + virtual Vasp *x_work() + { + Vasp *ret = new Vasp(ref); + if(setf) ret->Frames(frms); + return ret; + } + + virtual V m_help() { post("%s - Set a vasp's frame count",thisName()); } +protected: + I frms; + BL setf; + +private: + FLEXT_CALLBACK_F(m_arg); +}; + +FLEXT_LIB_V("vasp, vasp.frames vasp.f",vasp_frames) + + + + +/*! \class vasp_dframes + \remark \b vasp.frames+ + \brief Sets frame count of vasp differentially. + \since 0.0.1 + \param cmdln.1 [_time=0] - increase of frame count in time units + \param inlet.1 vasp - is stored and output triggered + \param inlet.1 bang - triggers output + \param inlet.1 set - vasp to be stored + \param inlet.2 _time - increase of frame count in time units + \retval outlet vasp - modified vasp + + \todo Implement unit processing. +*/ +class vasp_dframes: + public vasp_frames +{ + FLEXT_HEADER(vasp_dframes,vasp_frames) + +public: + vasp_dframes(I argc,t_atom *argv): vasp_frames(argc,argv) {} + + virtual Vasp *x_work() + { + Vasp *ret = new Vasp(ref); + if(setf) ret->FramesD(frms); + return ret; + } + + virtual V m_help() { post("%s - Raise/lower a vasp's frame count",thisName()); } +}; + +FLEXT_LIB_V("vasp, vasp.frames+ vasp.f+",vasp_dframes) + + + +/*! \class vasp_mframes + \remark \b vasp.frames* + \brief Sets frame count of vasp by a factor + \since 0.0.6 + \param cmdln.1 [_number=1] - multiply of frame count + \param inlet.1 vasp - is stored and output triggered + \param inlet.1 bang - triggers output + \param inlet.1 set - vasp to be stored + \param inlet.2 _number - multiply of frame count + \retval outlet vasp - modified vasp +*/ +class vasp_mframes: + public vasp_frames +{ + FLEXT_HEADER(vasp_mframes,vasp_frames) + +public: + vasp_mframes(I argc,t_atom *argv): + vasp_frames(argc,argv) + { + if(argc && CanbeFloat(argv[0])) m_arg(GetAFloat(argv[0])); + } + + virtual Vasp *x_work() + { + Vasp *ret = new Vasp(ref); + if(setf) ret->FramesM(frms); + return ret; + } + + virtual V m_help() { post("%s - Multiply a vasp's frame count",thisName()); } + + virtual V m_arg(F f) + { + factor = f; + setf = true; + } + +protected: + F factor; +}; + +FLEXT_LIB_V("vasp, vasp.frames* vasp.f*",vasp_mframes) + + + +/*! \class vasp_rframes + \remark \b vasp.frames/ + \brief Sets frame count of vasp by a divisor + \since 0.0.6 + \param cmdln.1 [_number=1] - multiply of frame count + \param inlet.1 vasp - is stored and output triggered + \param inlet.1 bang - triggers output + \param inlet.1 set - vasp to be stored + \param inlet.2 _number - divisor of frame count + \retval outlet vasp - modified vasp +*/ +class vasp_rframes: + public vasp_mframes +{ + FLEXT_HEADER(vasp_rframes,vasp_mframes) + +public: + vasp_rframes(I argc,t_atom *argv): vasp_mframes(argc,argv) {} + + virtual Vasp *x_work() + { + Vasp *ret = new Vasp(ref); + if(setf) ret->FramesR(factor); + return ret; + } + + virtual V m_help() { post("%s - Divide a vasp's frame count",thisName()); } +}; + +FLEXT_LIB_V("vasp, vasp.frames/ vasp.f/",vasp_rframes) + + + +/*! \class vasp_qframes + \remark \b vasp.frames? + \brief Get frame count in time units + \since 0.0.1 + \param inlet vasp - is stored and output triggered + \param inlet bang - triggers output + \param inlet set - vasp to be stored + \retval outlet _time - frame count of vasp in time units + + \note Outputs 0 if vasp is undefined or invalid + + \todo Implement unit processing + \todo Should we provide a cmdln default vasp? + \todo Should we inhibit output for invalid vasps? +*/ +class vasp_qframes: + public vasp_op +{ + FLEXT_HEADER(vasp_qframes,vasp_op) + +public: + + vasp_qframes() + { + AddInAnything(); + AddOutInt(); + SetupInOut(); + } + + virtual V m_bang() { ToOutInt(0,ref.ChkFrames()); } //! \todo unit processing + + virtual V m_help() { post("%s - Get a vasp's frame count",thisName()); } +}; + +FLEXT_LIB("vasp, vasp.frames? vasp.f?",vasp_qframes) + + diff --git a/externals/grill/vasp/source/obj_imm.cpp b/externals/grill/vasp/source/obj_imm.cpp new file mode 100644 index 00000000..d1ca5da0 --- /dev/null +++ b/externals/grill/vasp/source/obj_imm.cpp @@ -0,0 +1,104 @@ +/* + +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. + +*/ + +/*! \file vasp_imm.cpp + \brief Definitions for immediate vasps +*/ + + +#include "classes.h" +#include "util.h" +#include "buflib.h" +#include "oploop.h" + + +/*! \class vasp_imm + \remark \b vasp.imm + \brief Get vasp immediate. + \since 0.0.6 + \param inlet.1 vasp - is stored and output triggered + \param inlet.1 bang - triggers output + \param inlet.1 set - vasp to be stored + \param inlet.1 frames - minimum frame length + \param inlet.2 int - minimum frame length + \retval outlet vasp! - vasp immediate + +*/ +class vasp_imm: + public vasp_op +{ + FLEXT_HEADER(vasp_imm,vasp_op) + +public: + vasp_imm(I argc,t_atom *argv): + frms(0) + { + if(argc >= 1 && CanbeInt(argv[0])) + m_frames(GetAInt(argv[0])); + else if(argc) + post("%s - Frame count argument invalid -> ignored",thisName()); + + AddInAnything(); + AddInInt(); + AddOutAnything(); + SetupInOut(); + + FLEXT_ADDMETHOD_(0,"frames",m_frames); + FLEXT_ADDMETHOD(1,m_frames); + } + + V m_frames(I n) { frms = n; } + + virtual V m_bang() + { + if(!ref.Ok() || !ref.Check()) { +/* + if(!frms) + post("%s - No length defined!",thisName()); + else +*/ + { + ImmBuf ibuf(frms); + Vasp ret(frms,Vasp::Ref(ibuf)); + ToOutVasp(0,ret); + } + } + else if(ref.Vectors() > 1) + post("%s - More than one vector in vasp!",thisName()); + else { + VBuffer *buf = ref.Buffer(0); + I len = buf->Length(),chns = buf->Channels(); + if(frms > len) len = frms; + + ImmBuf imm(len); + + S *dst = imm.Pointer(); + const S *src = buf->Pointer(); + register int i; + _D_LOOP(i,len) *(dst++) = *src,src += chns; _E_LOOP + + Vasp ret(len,Vasp::Ref(imm)); + ToOutVasp(0,ret); + } + } + + virtual V m_help() { post("%s - Get immediate vasp vectors",thisName()); } + +protected: + + I frms; + +private: + FLEXT_CALLBACK_I(m_frames) +}; + +FLEXT_LIB_V("vasp, vasp.imm vasp.!",vasp_imm) + + diff --git a/externals/grill/vasp/source/obj_offs.cpp b/externals/grill/vasp/source/obj_offs.cpp new file mode 100644 index 00000000..e424056f --- /dev/null +++ b/externals/grill/vasp/source/obj_offs.cpp @@ -0,0 +1,174 @@ +/* + +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 "classes.h" +#include "util.h" + + +/*! \class vasp_offset + \remark \b vasp.offset + \brief Sets offset of vasp vectors. + \since 0.0.1 + \param cmdln.1 [_time=0] - offset into buffer(s) + \param inlet.1 vasp - is stored and output triggered + \param inlet.1 bang - triggers output + \param inlet.1 set - vasp to be stored + \param inlet.2 _time - offset into buffer(s) + \retval outlet vasp - modified vasp + + \attention Normally vasp vectors have individual offsets - this operations sets all the offsets to equal values. + \todo Implement unit processing. +*/ +class vasp_offset: + public vasp_tx +{ + FLEXT_HEADER(vasp_offset,vasp_tx) + +public: + vasp_offset(I argc,t_atom *argv): + offs(0),seto(false) + { + if(argc >= 1 && CanbeFloat(argv[0])) + m_offs(GetAFloat(argv[0])); + else if(argc) + post("%s - Offset argument invalid -> ignored",thisName()); + + AddInAnything(); + AddInFloat(); + AddOutAnything(); + SetupInOut(); + + FLEXT_ADDMETHOD(1,m_offs); + } + + V m_offs(F o) + { + offs = (I)o; //! \todo unit processing + seto = true; + } + + virtual Vasp *x_work() + { + Vasp *ret = new Vasp(ref); + if(seto) ret->Offset(offs); + return ret; + } + + virtual V m_help() { post("%s - Set a vasp's offset(s) into the vector buffers",thisName()); } +protected: + I offs; + BL seto; + +private: + FLEXT_CALLBACK_F(m_offs); +}; + +FLEXT_LIB_V("vasp, vasp.offset vasp.o",vasp_offset) + + + + +/*! \class vasp_doffset + \remark \b vasp.offset+ + \brief Sets offset of vasp vectors differentially. + \since 0.0.1 + \param cmdln.1 [_time=0] - increase offset of into buffer(s) + \param inlet.1 vasp - is stored and output triggered + \param inlet.1 bang - triggers output + \param inlet.1 set - vasp to be stored + \param inlet.2 _time - increase of offset into buffer(s) + \retval outlet vasp - modified vasp + + \todo Implement unit processing +*/ +class vasp_doffset: + public vasp_offset +{ + FLEXT_HEADER(vasp_doffset,vasp_offset) + +public: + vasp_doffset(I argc,t_atom *argv): vasp_offset(argc,argv) {} + + virtual Vasp *x_work() + { + Vasp *ret = new Vasp(ref); + if(seto) ret->OffsetD(offs); + return ret; + } + + virtual V m_help() { post("%s - Shift a vasp's offset(s) into the vector buffers",thisName()); } +}; + +FLEXT_LIB_V("vasp, vasp.offset+ vasp.o+",vasp_doffset) + + + +/*! \class vasp_qoffset + \remark \b vasp.offset? + \brief Get offset of singled vector vasp. + \since 0.0.1 + \param inlet vasp - is stored and output triggered + \param inlet bang - triggers output + \param inlet set - vasp to be stored + \retval outlet _time - offset into vector buffer + + \note Outputs 0 if vasp is undefined or invalid + \note Only works for a vasp with one vector. No output otherwise. + + \todo Implement unit processing + \todo Should we provide a cmdln default vasp? + \todo Should we inhibit output for invalid vasps? +*/ +class vasp_qoffset: + public vasp_op +{ + FLEXT_HEADER(vasp_qoffset,vasp_op) + +public: + + vasp_qoffset() + { + AddInAnything(); +// AddOutAnything(); + AddOutFloat(); + SetupInOut(); + } + + virtual V m_bang() + { + if(!ref.Ok()) + post("%s - Invalid vasp!",thisName()); + else if(ref.Vectors() > 1) + post("%s - More than one vector in vasp!",thisName()); + else { + I o = 0; + if(ref.Vectors() == 1) { + o = ref.Vector(0).Offset(); + if(o < 0) o = 0; + else { + VBuffer *buf = ref.Buffer(0); + if(buf) { + I f = buf->Frames(); + if(o > f) o = f; + delete buf; + } + } + } + //! \todo unit processing +// ToOutVasp(0,ref); + ToOutFloat(0,o); + } + } + + virtual V m_help() { post("%s - Get a single vectored vasp's offset into the buffer",thisName()); } +}; + +FLEXT_LIB("vasp, vasp.offset? vasp.o?",vasp_qoffset) + diff --git a/externals/grill/vasp/source/obj_part.cpp b/externals/grill/vasp/source/obj_part.cpp new file mode 100644 index 00000000..2b0aa256 --- /dev/null +++ b/externals/grill/vasp/source/obj_part.cpp @@ -0,0 +1,102 @@ +/* + +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 "classes.h" +#include "util.h" + + +/*! \class vasp_part + \remark \b vasp.part + \brief Gets parts of vasp vectors. + \since 0.0.1 + \param cmdln.1 list - list of part lengts + \param inlet.1 vasp - is stored and output triggered + \param inlet.1 bang - triggers output + \param inlet.1 set - vasp to be stored + \param inlet.2 list - list of part lengts + \retval outlet.1 vasp - consecutive vasp parts + \retval outlet.2 vasp - remainder + + \todo Implement unit processing. + \remarks Output zero length vasps? +*/ +class vasp_part: + public vasp_op +{ + FLEXT_HEADER(vasp_part,vasp_op) + +public: + vasp_part(I argc,t_atom *argv): + part(NULL),parts(0) + { + m_part(argc,argv); + + AddInAnything(2); + AddOutAnything(2); + SetupInOut(); + + FLEXT_ADDMETHOD_(1,"list",m_part); + } + + ~vasp_part() { if(part) delete[] part; } + + V m_part(I argc,t_atom *argv) + { + if(part) delete[] part; parts = 0; + part = new I[argc]; + for(I i = 0; i < argc; ++i) { + BL warn = false; + I p = (I)GetAFloat(argv[i]); // \todo unit processing + if(p < 0 && !warn) { + post("%s - invalid part length(s) -> set to 0",thisName()); + p = 0; warn = true; + } + part[i] = p; ++parts; + } + } + + virtual V m_bang() + { + if(!ref.Ok()) { + post("%s - Invalid vasp!",thisName()); + return; + } + + I fr = ref.Frames(),o = 0,f = 0; + for(I i = 0; i < parts && (fr < 0 || fr); ++i) { + I p = part[i]; + if(fr >= 0) { p = min(p,fr); fr -= p; } + + Vasp ret(ref); + ret.Frames(p); + ret.OffsetD(o); + ToOutVasp(0,ret); + + o += p; + } + + if(fr) { + Vasp ret(ref); + ret.Frames(fr); + ret.OffsetD(o); + ToOutVasp(1,ret); + } + } + + virtual V m_help() { post("%s - Return consecutive vasps with lengths given by argument list",thisName()); } +protected: + I parts,*part; + + FLEXT_CALLBACK_V(m_part) +}; + +FLEXT_LIB_V("vasp, vasp.part",vasp_part) + + diff --git a/externals/grill/vasp/source/obj_peaks.cpp b/externals/grill/vasp/source/obj_peaks.cpp new file mode 100644 index 00000000..1c1a218d --- /dev/null +++ b/externals/grill/vasp/source/obj_peaks.cpp @@ -0,0 +1,111 @@ +/* + +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 "classes.h" +#include "util.h" +#include <math.h> + + +/*! \class vasp_qpeaks + \remark \b vasp.peaks? + \brief Get most pronounced peaks of a single vasp vector. + \since 0.0.6 + \param inlet vasp - is stored and output triggered + \param inlet bang - triggers output + \param inlet set - vasp to be stored + \retval outlet.0 list - peak positions + \retval outlet.1 list - peak values + + \note Outputs nothing if vasp is undefined or invalid + \note Only works for a vasp with one vector. No output otherwise. + \todo Units for peak position list +*/ +class vasp_qpeaks: + public vasp_op +{ + FLEXT_HEADER(vasp_qpeaks,vasp_op) + +public: + vasp_qpeaks(I argc,t_atom *argv): + peaks(1) + { + if(argc >= 1 && CanbeInt(argv[0])) + m_peaks(GetAInt(argv[0])); + else if(argc) + post("%s - Number argument invalid -> ignored",thisName()); + + AddInAnything(); + AddInInt(); + AddOutAnything(2); + SetupInOut(); + + FLEXT_ADDMETHOD(1,m_peaks); + } + + V m_peaks(I n) { peaks = n; } + + virtual V m_bang() + { + if(!ref.Ok()) + post("%s - Invalid vasp!",thisName()); + else if(ref.Vectors() > 1) + post("%s - More than one vector in vasp!",thisName()); + else { + VBuffer *buf = ref.Buffer(0); + I i,cnt = buf->Length(),pkfnd = 0; + S *p = buf->Pointer(); + + I mxpk = min(cnt,peaks); + t_atom *pos = new t_atom[mxpk],*lst = new t_atom[mxpk]; + for(i = 0; i < mxpk; ++i) SetFloat(lst[i],0); + + for(i = 0; i < cnt; ++i) { + const F v = fabs(p[i]); + + if(v && v > GetFloat(lst[mxpk-1])) { + I ix; + + for(ix = min(pkfnd-1,mxpk-1); ix >= 0; --ix) { + if(v > GetFloat(lst[ix])) { + if(ix < mxpk-1) { + pos[ix+1] = pos[ix]; + lst[ix+1] = lst[ix]; + } + } + else break; + } + ++ix; + + SetFloat(pos[ix],i); + SetFloat(lst[ix],v); + + if(++pkfnd > mxpk) pkfnd = mxpk; + } + } + + ToOutAnything(0,sym_list,pkfnd,pos); + ToOutAnything(1,sym_list,pkfnd,lst); + delete[] pos; + delete[] lst; + } + } + + virtual V m_help() { post("%s - Get list of most pronounced peaks of a vasp vector",thisName()); } + +protected: + I peaks; + +private: + FLEXT_CALLBACK_I(m_peaks); +}; + +FLEXT_LIB_V("vasp, vasp.peaks?",vasp_qpeaks) + + diff --git a/externals/grill/vasp/source/obj_q.cpp b/externals/grill/vasp/source/obj_q.cpp new file mode 100644 index 00000000..f0465109 --- /dev/null +++ b/externals/grill/vasp/source/obj_q.cpp @@ -0,0 +1,121 @@ +/* + +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 "classes.h" +#include "util.h" + + +/*! \class vasp_list + \remark \b vasp.list + \brief Get samples of a single vasp vector. + \since 0.0.1 + \param inlet vasp - is stored and output triggered + \param inlet bang - triggers output + \param inlet set - vasp to be stored + \retval outlet vector - vasp samples + + \note Outputs 0 if vasp is undefined or invalid + \note Only works for a vasp with one vector. No output otherwise. +*/ +class vasp_list: + public vasp_op +{ + FLEXT_HEADER(vasp_list,vasp_op) + +public: + + vasp_list() + { + AddInAnything(); + AddOutList(); + SetupInOut(); + } + + virtual V m_bang() + { + if(!ref.Ok()) + post("%s - Invalid vasp!",thisName()); + else if(ref.Vectors() > 1) + post("%s - More than one vector in vasp!",thisName()); + else { + VBuffer *buf = ref.Buffer(0); + I cnt = buf->Length(); + S *p = buf->Pointer(); + AtomList lst(cnt); + for(I i = 0; i < cnt; ++i,++p) SetFloat(lst[i],*p); + ToOutList(0,lst); + } + } + + virtual V m_help() { post("%s - Get list of samples of a vasp vector",thisName()); } +}; + +FLEXT_LIB("vasp, vasp.list vasp.?",vasp_list) + + + +/*! \class vasp_nonzero + \remark \b vasp.nonzero + \brief Get samples of a single vasp vector. + \since 0.0.2 + \param inlet vasp - is stored and output triggered + \param inlet bang - triggers output + \param inlet set - vasp to be stored + \retval outlet.0 list - non-zero samples positions + \retval outlet.1 list - non-zero sample values + + \note Outputs 0 if vasp is undefined or invalid + \note Only works for a vasp with one vector. No output otherwise. + \todo units for position list +*/ +class vasp_nonzero: + public vasp_op +{ + FLEXT_HEADER(vasp_nonzero,vasp_op) + +public: + + vasp_nonzero() + { + AddInAnything(); + AddOutList(2); + SetupInOut(); + } + + virtual V m_bang() + { + if(!ref.Ok()) + post("%s - Invalid vasp!",thisName()); + else if(ref.Vectors() > 1) + post("%s - More than one vector in vasp!",thisName()); + else { + VBuffer *buf = ref.Buffer(0); + I i,cnt = buf->Length(),cp,ci; + S *p = buf->Pointer(); + for(cp = i = 0; i < cnt; ++i,++p) if(*p) ++cp; + + AtomList pos(cp),lst(cp); + p = buf->Pointer(); + for(ci = i = 0; ci < cp; ++i,++p) + if(*p) { + SetFloat(pos[ci],i); + SetFloat(lst[ci],*p); + ++ci; + } + ToOutList(0,pos); + ToOutList(1,lst); + } + } + + virtual V m_help() { post("%s - Get list of non-zero samples of a vasp vector",thisName()); } +}; + +FLEXT_LIB("vasp, vasp.nonzero vasp.??",vasp_nonzero) + diff --git a/externals/grill/vasp/source/obj_radio.cpp b/externals/grill/vasp/source/obj_radio.cpp new file mode 100644 index 00000000..7b0608e3 --- /dev/null +++ b/externals/grill/vasp/source/obj_radio.cpp @@ -0,0 +1,57 @@ +/* + +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. + +*/ + +/*! \file obj_radio.cpp + \brief objects for radio messages. +*/ + + +#include "classes.h" + + +/*! \class vasp_radio + \remark \b vasp.radio + \brief Lets only radio messages pass through. + \since 0.0.6 + \param inlet.1 * - any message + \retval outlet.1 radio messages + \retval outlet.2 other messages +*/ +class vasp_radio: + public flext_base +{ + FLEXT_HEADER(vasp_radio,flext_base) + +public: + + vasp_radio() + { + AddInAnything(); + AddOutAnything(2); + SetupInOut(); + + FLEXT_ADDMETHOD(0,m_any); + } + + virtual V m_any(const t_symbol *s,I argc,t_atom *argv); + + virtual V m_help() { post("%s - split into radio and non-radio messages",thisName()); } +private: + FLEXT_CALLBACK_A(m_any); +}; + +FLEXT_LIB("vasp, vasp.radio",vasp_radio) + + +V vasp_radio::m_any(const t_symbol *s,I argc,t_atom *argv) +{ + ToOutAnything(s == vasp_base::sym_radio?0:1,s,argc,argv); +} + diff --git a/externals/grill/vasp/source/obj_size.cpp b/externals/grill/vasp/source/obj_size.cpp new file mode 100644 index 00000000..9a535e60 --- /dev/null +++ b/externals/grill/vasp/source/obj_size.cpp @@ -0,0 +1,248 @@ +/* + +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 "classes.h" +#include "util.h" + + +/*! \class vasp_size + \remark \b vasp.size + \brief Resize buffer. + \since 0.0.6 + \param cmdln.1 [_time=0] - size of buffer + \param inlet.1 vasp - is stored and output triggered + \param inlet.1 bang - triggers output + \param inlet.1 set - vasp to be stored + \param inlet.2 _time - offset into buffer(s) + \retval outlet vasp - modified vasp + + \attention Normally vasp vectors have individual offsets - this operations sets all the buffer sizes to equal values. + \todo Implement unit processing. +*/ +class vasp_size: + public vasp_tx +{ + FLEXT_HEADER(vasp_size,vasp_tx) + +public: + vasp_size(I argc,t_atom *argv): + size(0),sets(false) + { + if(argc >= 1 && CanbeFloat(argv[0])) + m_arg(GetAFloat(argv[0])); + else if(argc) + post("%s - Offset argument invalid -> ignored",thisName()); + + AddInAnything(); + AddInFloat(); + AddOutAnything(); + SetupInOut(); + + FLEXT_ADDMETHOD(1,m_arg); + } + + virtual V m_arg(F s) + { + size = (I)s; // \todo unit processing + sets = true; + } + + virtual Vasp *x_work() + { + Vasp *ret = new Vasp(ref); + if(sets) ret->Size(size); + return ret; + } + + virtual V m_help() { post("%s - Set the size of the vector buffers",thisName()); } +protected: + I size; + BL sets; + +private: + FLEXT_CALLBACK_F(m_arg); +}; + +FLEXT_LIB_V("vasp, vasp.size vasp.s",vasp_size) + + + + +/*! \class vasp_dsize + \remark \b vasp.size+ + \brief Sets vector buffer sizes differentially. + \since 0.0.6 + \param cmdln.1 [_time=0] - increase offset of into buffer(s) + \param inlet.1 vasp - is stored and output triggered + \param inlet.1 bang - triggers output + \param inlet.1 set - vasp to be stored + \param inlet.2 _time - increase of offset into buffer(s) + \retval outlet vasp - modified vasp + + \todo Implement unit processing +*/ +class vasp_dsize: + public vasp_size +{ + FLEXT_HEADER(vasp_dsize,vasp_size) + +public: + vasp_dsize(I argc,t_atom *argv): vasp_size(argc,argv) {} + + virtual Vasp *x_work() + { + Vasp *ret = new Vasp(ref); + if(sets) ret->SizeD(size); + return ret; + } + + virtual V m_help() { post("%s - Increase the size of the vector buffers",thisName()); } +}; + +FLEXT_LIB_V("vasp, vasp.size+ vasp.s+",vasp_dsize) + + + +/*! \class vasp_msize + \remark \b vasp.size* + \brief Sets vector buffer sizes by a factor + \since 0.0.6 + \param cmdln.1 [_number=1] - factor for size + \param inlet.1 vasp - is stored and output triggered + \param inlet.1 bang - triggers output + \param inlet.1 set - vasp to be stored + \param inlet.2 _number - factor for size + \retval outlet vasp - modified vasp +*/ +class vasp_msize: + public vasp_size +{ + FLEXT_HEADER(vasp_msize,vasp_size) + +public: + vasp_msize(I argc,t_atom *argv): + vasp_size(argc,argv) + { + if(argc && CanbeFloat(argv[0])) m_arg(GetAFloat(argv[0])); + } + + virtual Vasp *x_work() + { + Vasp *ret = new Vasp(ref); + if(sets) ret->SizeM(factor); + return ret; + } + + virtual V m_help() { post("%s - Multiply the size of the vector buffers",thisName()); } + + virtual V m_arg(F f) + { + factor = f; + sets = true; + } + +protected: + R factor; +}; + +FLEXT_LIB_V("vasp, vasp.size* vasp.s*",vasp_msize) + + + +/*! \class vasp_rsize + \remark \b vasp.size/ + \brief Sets vector buffer sizes by a factor + \since 0.0.6 + \param cmdln.1 [_number=1] - divisor for size + \param inlet.1 vasp - is stored and output triggered + \param inlet.1 bang - triggers output + \param inlet.1 set - vasp to be stored + \param inlet.2 _number - divisor for size + \retval outlet vasp - modified vasp +*/ +class vasp_rsize: + public vasp_msize +{ + FLEXT_HEADER(vasp_rsize,vasp_msize) + +public: + vasp_rsize(I argc,t_atom *argv): vasp_msize(argc,argv) {} + + virtual Vasp *x_work() + { + Vasp *ret = new Vasp(ref); + if(sets) ret->SizeR(factor); + return ret; + } + + virtual V m_help() { post("%s - Divide the size of the vector buffers",thisName()); } +}; + +FLEXT_LIB_V("vasp, vasp.size/ vasp.s/",vasp_rsize) + + + +/*! \class vasp_qsize + \remark \b vasp.size? + \brief Get size of a vector buffer. + \since 0.0.6 + \param inlet vasp - is stored and output triggered + \param inlet bang - triggers output + \param inlet set - vasp to be stored + \retval outlet _time - offset into vector buffer + + \note Outputs 0 if vasp is undefined or invalid + \note Only works for a vasp with one vector. No output otherwise. + + \todo Implement unit processing + \todo Should we provide a cmdln default vasp? + \todo Should we inhibit output for invalid vasps? +*/ +class vasp_qsize: + public vasp_op +{ + FLEXT_HEADER(vasp_qsize,vasp_op) + +public: + + vasp_qsize() + { + AddInAnything(); +// AddOutAnything(); + AddOutFloat(); + SetupInOut(); + } + + virtual V m_bang() + { + if(!ref.Ok()) + post("%s - Invalid vasp!",thisName()); + else if(ref.Vectors() > 1) + post("%s - More than one vector in vasp!",thisName()); + else { + I s = 0; + if(ref.Vectors() == 1) { + VBuffer *buf = ref.Buffer(0); + if(buf) { + s = buf->Frames(); + delete buf; + } + } + //! \todo unit processing +// ToOutVasp(0,ref); + ToOutFloat(0,s); + } + } + + virtual V m_help() { post("%s - Get the buffer size of a vector",thisName()); } +}; + +FLEXT_LIB("vasp, vasp.size? vasp.s?",vasp_qsize) + diff --git a/externals/grill/vasp/source/obj_split.cpp b/externals/grill/vasp/source/obj_split.cpp new file mode 100644 index 00000000..42921d2a --- /dev/null +++ b/externals/grill/vasp/source/obj_split.cpp @@ -0,0 +1,288 @@ +/* + +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 "classes.h" +#include "util.h" + + +/*! \class vasp_split + \remark \b vasp.split + \brief Splits a vasp into a number of vectors and the remainder. + \since 0.0.1 + \param cmdln.1 int - number of vectors to split vasp into (excl. one for the remainder vectors) + \param inlet.1 vasp - is stored and triggered + \param inlet.1 bang - triggers output + \param inlet.1 set - vasp to be stored + \retval outlet.n vasp - vector of stored vasp + \retval outlet.+ vasp - remainder of stored vasp + + \note if there is no remainder outputs a bang +*/ +class vasp_split: + public vasp_op +{ + FLEXT_HEADER(vasp_split,vasp_op) + +public: + vasp_split(I argc,t_atom *argv) + { + I cnt = -1; + if(argc) { + if(CanbeInt(argv[0])) cnt = GetAInt(argv[0]); + if(cnt <= 1) { + post("%s - integer argument invalid: set to 2",thisName()); + cnt = 2; + } + } + else cnt = 2; + + AddInAnything(); + AddOutAnything(cnt+1); + SetupInOut(); + } + + virtual V m_bang() + { + if(!ref.Ok()) { + post("%s - Invalid vasp!",thisName()); + return; + } + + I outs = CntOut()-1,rem = ref.Vectors()-outs; + for(I i = min(outs,ref.Vectors())-1; i >= 0; --i) { + Vasp v(ref.Frames(),ref.Vector(i)); + ToOutVasp(i,v); + } + if(rem > 0) { + Vasp v(ref.Frames(),ref.Vector(outs)); + for(I i = 1; i < rem; ++i) v += ref.Vector(outs+i); + ToOutVasp(outs,v); + } + else + ToOutBang(outs); + } + + virtual V m_help() { post("%s - Split a vasp into its vectors",thisName()); } +}; + +FLEXT_LIB_V("vasp, vasp.split",vasp_split) + + +/*! \class vasp_join + \remark \b vasp.join + \brief Joins several vasps into one. + \since 0.0.1 + \param cmdln.1 int - number of vasp slots + \param inlet.1 vasp - is stored and output triggered + \param inlet.1 bang - triggers output + \param inlet.1 set - vasp to be stored + \param inlet.1 reset - clears slots + \param inlet.+n vasp - is stored in this slot + \retval outlet vasp - joined vasp + + The several vectors of the several vasps are all joined into one vasp. + + \note On different vasp frame count the minmum frame count is taken. + \note The latest vector input to a slot is taken for the resulting vasp +*/ +class vasp_join: + public vasp_tx +{ + FLEXT_HEADER(vasp_join,vasp_tx) + +public: + vasp_join(I argc,t_atom *argv): + cnt(-1),vi(NULL) + { + if(argc) { + if(CanbeInt(argv[0])) cnt = GetAInt(argv[0]); + if(cnt <= 1) { + post("%s - integer argument invalid: set to 2",thisName()); + cnt = 2; + } + } + else cnt = 2; + + vi = new Vasp *[cnt-1]; + for(I i = 0; i < cnt-1; ++i) vi[i] = NULL; + + AddInAnything(cnt); + AddOutAnything(); + SetupInOut(); + + FLEXT_ADDMETHOD_(0,"reset",m_reset); + } + + ~vasp_join() { if(vi) delete[] vi; } + + virtual Vasp *x_work() { + Vasp *ret = new Vasp(ref); + for(I i = 0; i < cnt-1; ++i) if(vi[i]) *ret += *vi[i]; + return ret; + } + + V m_reset() + { + ref.Clear(); + for(I i = 0; i < cnt-1; ++i) if(vi[i]) { delete vi[i]; vi[i] = NULL; } + } + + virtual bool m_method_(I inlet,const t_symbol *s,I argc,t_atom *argv) + { + if(inlet > 0 && s == sym_vasp) { + if(vi[inlet-1]) delete vi[inlet-1]; + vi[inlet-1] = new Vasp(argc,argv); + return true; + } + else + return vasp_tx::m_method_(inlet,s,argc,argv); + } + + virtual V m_help() { post("%s - Join several vasps into one",thisName()); } +private: + I cnt; + Vasp **vi; + + FLEXT_CALLBACK(m_reset) +}; + +FLEXT_LIB_V("vasp, vasp.join",vasp_join) + + + +/*! \class vasp_spit + \remark \b vasp.spit + \brief Spit out vectors of a vasp consecutively. + \since 0.0.1 + \param inlet.1 vasp - is stored and triggered + \param inlet.1 bang - triggers output + \param inlet.1 set - vasp to be stored + \retval outlet.n vasp - vectors of stored vasp + \retval outlet.+ bang - triggered after last spit +*/ +class vasp_spit: + public vasp_op +{ + FLEXT_HEADER(vasp_spit,vasp_op) + +public: + vasp_spit(I argc,t_atom *argv) + { + I n = 1; + if(argc >= 1) n = GetAInt(argv[0]); + if(n < 1) { + post("%s - illegal outlet count (%i) -> set to 1",thisName(),n); + n = 1; + } + + AddInAnything(); + AddOutAnything(n); + AddOutBang(); + SetupInOut(); + } + + virtual V m_bang() + { + if(!ref.Ok()) { + post("%s - Invalid vasp!",thisName()); + return; + } + + I outs = CntOut()-1,rem = ref.Vectors(); + for(I vi = 0; rem;) { + I r = min(rem,outs); + for(I i = 0; i < r; ++i) { + Vasp v(ref.Frames(),ref.Vector(vi+i)); + ToOutVasp(r-1-i,v); + } + vi += r; + rem -= r; + } + ToOutBang(outs); + } + + virtual V m_help() { post("%s - Spit out vectors of a vasp",thisName()); } +}; + +FLEXT_LIB_V("vasp, vasp.spit",vasp_spit) + + +/*! \class vasp_gather + \remark \b vasp.gather + \brief Gathers several consecutive vasps into one. + \since 0.0.1 + \param cmdln.1 int - number of vasp slots + \param inlet.1 vasp - is stored and output triggered + \param inlet.1 bang - triggers output + \param inlet.1 set - sets result vasp + \param inlet.1 reset - clears result + \param inlet.2 vasp - add to result vasp + \retval outlet vasp - gathered vasp + + The several incoming vectors are all gathered into one vasp. + + \note On different vasp frame count the minimum frame count is taken. +*/ +class vasp_gather: + public vasp_tx +{ + FLEXT_HEADER(vasp_gather,vasp_tx) + +public: + vasp_gather(I argc,t_atom *argv) + { + cnt = 0; + if(argc >= 1) cnt = GetAInt(argv[0]); + if(cnt < 0) { + post("%s - illegal count (%i) -> set to 0 (triggered mode)",thisName(),cnt); + cnt = 0; + } + rem = cnt; + + AddInAnything(2); + AddOutAnything(); + SetupInOut(); + + FLEXT_ADDMETHOD_(0,"reset",m_reset); + FLEXT_ADDMETHOD_(1,"vasp",m_add); + } + + ~vasp_gather() { } + + virtual Vasp *x_work() + { + Vasp *ret = new Vasp(ref); + *ret += dst; + m_reset(); + return ret; + } + + V m_reset() { ref.Clear(); dst.Clear(); rem = cnt; } + + virtual I m_set(I argc,t_atom *argv) { rem = cnt; return vasp_tx::m_set(argc,argv); } + + V m_add(I argc,t_atom *argv) + { + dst += Vasp(argc,argv); + if(cnt && !--rem) m_bang(); + } + + virtual V m_help() { post("%s - Gather several vasps into one",thisName()); } +private: + I cnt,rem; + + FLEXT_CALLBACK(m_reset) + FLEXT_CALLBACK_V(m_add) +}; + +FLEXT_LIB_V("vasp, vasp.gather",vasp_gather) + + + diff --git a/externals/grill/vasp/source/obj_sync.cpp b/externals/grill/vasp/source/obj_sync.cpp new file mode 100644 index 00000000..35f81409 --- /dev/null +++ b/externals/grill/vasp/source/obj_sync.cpp @@ -0,0 +1,123 @@ +/* + +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 "classes.h" +#include "util.h" + + +/*! \class vasp_sync + \remark \b vasp.sync + \brief Waits for all inlets to be hit (by vasps/anything) to trigger output. + \since 0.0.1 + \param cmdln.1 int - number of sync inlets + \param inlet.1 vasp - is stored + \param inlet.1 bang - triggers output + \param inlet.1 set - vasp to be stored + \param inlet.1 reset - clear all hit flags + \param inlet.+n vasp/anything - sets hit flag + \retval outlet.* vasp - stored vasps + + \todo Message for selection if only vasp input triggers (or any one). + \todo Message for selection of manual or auto reset upon trigger +*/ +class vasp_sync: + public vasp_op +{ + FLEXT_HEADER(vasp_sync,vasp_op) + +public: + vasp_sync(I argc,t_atom *argv): + autoreset(true),vasponly(false) + { + I cnt = -1; + if(argc) { + if(CanbeInt(argv[0])) cnt = GetAInt(argv[0]); + if(cnt <= 1) { + post("%s - integer argument invalid: set to 2",thisName()); + cnt = 2; + } + } + else cnt = 2; + + flags = new BL[cnt]; + stored = new Vasp[cnt-1]; + + AddInAnything(cnt); + AddOutAnything(cnt); + SetupInOut(); + + FLEXT_ADDMETHOD_(0,"reset",m_reset); + + } + + virtual BL Init() { BL ret = vasp_op::Init(); m_reset(); return ret; } + + ~vasp_sync() + { + if(flags) delete[] flags; + if(stored) delete[] stored; + } + + V chkbang(I n,Vasp *a = NULL) + { + if(a && n > 0) { + stored[n-1] = *a; + delete a; + } + + BL f = flags[n]; + flags[n] = true; + if(!f) { // flags have changed + + BL all = true; + for(I i = 0; i < CntIn(); ++i) all = all && flags[i]; + + if(all) { + if(ref.Ok()) { + for(I i = CntIn()-1; i > 0; --i) ToOutVasp(i,stored[i-1]); + ToOutVasp(0,ref); + } + else ToOutBang(0); + + if(autoreset) m_reset(); + } + } + } + + virtual V m_bang() { chkbang(0); } + + V m_reset() + { + for(I i = 0; i < CntIn(); ++i) flags[i] = false; + } + + virtual bool m_method_(I inlet,const t_symbol *s,I argc,t_atom *argv) + { + if(inlet > 0 && (!vasponly || s == sym_vasp)) { + Vasp *a = new Vasp(argc,argv); + chkbang(inlet,a); + return true; + } + else + return vasp_op::m_method_(inlet,s,argc,argv); + } + + virtual V m_help() { post("%s - Synchronize a number of vasps (default 2)",thisName()); } +private: + BL autoreset,vasponly; + BL *flags; + Vasp *stored; + + FLEXT_CALLBACK(m_reset) +}; + +FLEXT_LIB_V("vasp, vasp.sync",vasp_sync) + + diff --git a/externals/grill/vasp/source/obj_vasp.cpp b/externals/grill/vasp/source/obj_vasp.cpp new file mode 100644 index 00000000..3b52d253 --- /dev/null +++ b/externals/grill/vasp/source/obj_vasp.cpp @@ -0,0 +1,200 @@ +/* + +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. + +*/ + +/*! \file obj_vasp.cpp + \brief basic vasp objects. +*/ + + +#include "classes.h" +#include "util.h" + + +/*! \class vasp_v + \remark \b vasp + \brief Stores vasp messages. + \since 0.0.1 + \param cmdln.* vasp - to be stored + \param inlet.1 vasp - is stored and output + \param inlet.1 list - if possible list is converted to vasp format + \param inlet.1 bang - triggers stored Vasp output + \param inlet.1 set vasp - Vasp is stored (and not immediately output) + \param inlet.2 vasp - Vasp is stored (and not immediately output) + \retval outlet vasp +*/ +class vasp_v: + public vasp_tx +{ + FLEXT_HEADER(vasp_v,vasp_tx) + +public: + + vasp_v(I argc,t_atom *argv) + { + m_set(argc,argv); + + AddInAnything(2); + AddOutAnything(); + + FLEXT_ADDMETHOD_(0,"list",m_vasp); + + FLEXT_ADDMETHOD_(1,"list",m_set); + FLEXT_ADDMETHOD_(1,"vasp",m_set); + FLEXT_ADDMETHOD_(1,"radio",a_radio); + } + + V a_radio(I,t_atom *) {} + + virtual Vasp *x_work() { return new Vasp(ref); } + + virtual V m_help() { post("%s - Store and output a vasp",thisName()); } +private: + FLEXT_CALLBACK_V(a_radio); +}; + +FLEXT_LIB_V("vasp, vasp",vasp_v) + + + +/*! \class vasp_update + \remark \b vasp.update + \brief Refreshes buffer graphics for a vasp. + \since 0.0.1 + \param inlet vasp - is stored and output + \param inlet bang - triggers stored vasp output + \param inlet set - vasp to be stored (and not immediately output) + \retval outlet vasp + + \note In MaxMSP only necessary when buffer is in another window. +*/ +class vasp_update: + public vasp_tx +{ + FLEXT_HEADER(vasp_update,vasp_tx) + +public: + vasp_update() + { + AddInAnything(); + AddOutAnything(); + } + + virtual Vasp *x_work() + { + ref.Refresh(); + return new Vasp(ref); + } + + virtual V m_help() { post("%s - Update graphics of a vasp",thisName()); } +}; + +FLEXT_LIB("vasp, vasp.update vasp.u",vasp_update) + + + +/*! \class vasp_check + \remark \b vasp.check + \brief Check vasp dimensions. + \since 0.0.1 + \param inlet vasp - is stored and output + \param inlet bang - triggers stored vasp output + \param inlet set - vasp to be stored (and not immediately output) + \retval outlet vasp + + \remark checks and corrects frame count + \remark checks channel index... no correction, no output on error! +*/ +class vasp_check: + public vasp_tx +{ + FLEXT_HEADER(vasp_check,vasp_tx) + +public: + vasp_check() + { + AddInAnything(); + AddOutAnything(); + } + + virtual Vasp *x_work() + { + Vasp *ret = new Vasp(ref); + I fr = ret->ChkFrames(); // maximum common frame length + ret->Frames(fr); + + BL chok = true; + + for(I i = 0; i < ret->Vectors(); ++i) { + VBuffer *buf = ret->Buffer(i); + chok = chok && buf->Ok() && buf->Channel() == ret->Vector(i).Channel(); + delete buf; + } + + if(chok) + return ret; + else { + delete ret; + return NULL; + } + } + + virtual V m_help() { post("%s - Check vasp dimensions",thisName()); } +}; + +FLEXT_LIB("vasp, vasp.check vasp.chk",vasp_check) + + + +/*! \class vasp_multi + \remark \b vasp.m + \brief Outputs multiple (identical) vasps. + \since 0.0.1 + \param cmdln.1 int - number of vasp outlets + \param inlet vasp - is stored and output + \param inlet bang - triggers stored Vasp output + \param inlet set - vasp to be stored (and not immediately output) + \retval outlet.* vasp + + \note Outputs in right to left order. +*/ +class vasp_multi: + public vasp_op +{ + FLEXT_HEADER(vasp_multi,vasp_op) + +public: + + vasp_multi(I argc,t_atom *argv) + { + I cnt = -1; + if(argc) { + if(CanbeInt(argv[0])) cnt = GetAInt(argv[0]); + if(cnt <= 1) { + post("%s - integer argument invalid: set to 2",thisName()); + cnt = 2; + } + } + else cnt = 2; + + AddInAnything(); + AddOutAnything(cnt); + } + + virtual V m_bang() + { + Vasp r(ref); + for(I i = CntOut()-1; i >= 0; --i) ToOutVasp(i,r); + } + + virtual V m_help() { post("%s - Output a vasp multiple times",thisName()); } +}; + +FLEXT_LIB_V("vasp, vasp.multi vasp.m",vasp_multi) + diff --git a/externals/grill/vasp/source/obj_vecs.cpp b/externals/grill/vasp/source/obj_vecs.cpp new file mode 100644 index 00000000..fd24d273 --- /dev/null +++ b/externals/grill/vasp/source/obj_vecs.cpp @@ -0,0 +1,106 @@ +/* + +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 "classes.h" +#include "util.h" + + +/*! \class vasp_vector + \remark \b vasp.vector + \brief Gets indexed vector of a vasp. + \since 0.0.1 + \param cmdln.1 int - index of vasp vector + \param inlet vasp - is stored and indexed vasp vector output + \param inlet bang - triggers indexed vasp vector output + \param inlet set - vasp to be stored (and not immediately output) + \retval outlet.1 vasp - single indexed vector of vasp + \retval outlet.2 vasp - remainder of vasp + + \note Outputs only on valid index + \todo Output remainder as vasp. +*/ +class vasp_vector: + public vasp_tx +{ + FLEXT_HEADER(vasp_vector,vasp_tx) + +public: + vasp_vector(I argc,t_atom *argv): + ix(0) + { + if(argc >= 1 && CanbeInt(argv[0])) + ix = GetAInt(argv[0]); + else if(argc) + post("%s - Index argument invalid -> set to 0",thisName()); + + AddInAnything(2); + AddOutAnything(); + SetupInOut(); + + FLEXT_ADDMETHOD(1,m_ix); + } + + V m_ix(I i) { ix = i; } + + virtual Vasp *x_work() { return ix < ref.Vectors()?new Vasp(ref.Frames(),ref.Vector(ix)):NULL; } + + virtual V m_help() { post("%s - Get one vector of a vasp",thisName()); } + +protected: + I ix; + +private: + FLEXT_CALLBACK_I(m_ix); +}; + +FLEXT_LIB_V("vasp, vasp.vector vasp.n",vasp_vector) + + + +/*! \class vasp_qn + \remark \b vasp.n? + \brief Gets number of vector of a vasp. + \since 0.0.1 + \param inlet vasp - is stored and output triggered + \param inlet bang - triggers output + \param inlet set - vasp to be stored + \retval outlet int - number of vectors in stored vasp + + \note Outputs 0 if vasp is undefined or invalid. + + \todo Should we disable output with invalid vasp? +*/ +class vasp_qvectors: + public vasp_op +{ + FLEXT_HEADER(vasp_qvectors,vasp_op) + +public: + vasp_qvectors() + { + AddInAnything(); +// AddOutAnything(); + AddOutInt(); + SetupInOut(); + } + + virtual V m_bang() + { +// ToOutVasp(0,ref); + ToOutInt(0,ref.Ok()?ref.Vectors():0); + } + + virtual V m_help() { post("%s - Get number of vectors of a vasp",thisName()); } +}; + +FLEXT_LIB("vasp, vasp.vectors? vasp.n?",vasp_qvectors) + + + diff --git a/externals/grill/vasp/source/opbase.cpp b/externals/grill/vasp/source/opbase.cpp new file mode 100644 index 00000000..2ea9a13c --- /dev/null +++ b/externals/grill/vasp/source/opbase.cpp @@ -0,0 +1,94 @@ +/* + +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 "opbase.h" +#include "opdefs.h" + +Vasp *VaspOp::m_run(OpParam &p,Vasp &src,Vasp *dst,VecOp::opfun *fun) +{ + Vasp *ret = NULL; + RVecBlock *vecs = GetRVecs(p.opname,src,dst); + if(vecs) { + ret = DoOp(vecs,fun,p); + delete vecs; + } + + return ret; +} + +Vasp *VaspOp::m_cun(OpParam &p,Vasp &src,Vasp *dst,VecOp::opfun *fun) +{ + Vasp *ret = NULL; + CVecBlock *vecs = GetCVecs(p.opname,src,dst); + if(vecs) { + ret = DoOp(vecs,fun,p); + delete vecs; + } + + return ret; +} + +Vasp *VaspOp::m_rbin(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst,VecOp::opfun *fun) +{ + Vasp *ret = NULL; + BL argvasp = arg.IsVasp(); + + RVecBlock *vecs = argvasp?GetRVecs(p.opname,src,arg.GetVasp(),dst):GetRVecs(p.opname,src,dst); + if(vecs) { + if(arg.CanbeDouble()) p.rbin.arg = arg.GetADouble(); + else if(arg.IsEnv()) { + if(p.args != 1) + ERRINTERNAL(); + else + p.arg[0].SetE(&arg.GetEnv()); + } + + ret = DoOp(vecs,fun,p); + delete vecs; + } + + return ret; +} + +Vasp *VaspOp::m_cbin(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst,VecOp::opfun *fun) +{ + Vasp *ret = NULL; + BL argvasp = arg.IsVasp(); + + CVecBlock *vecs = argvasp?GetCVecs(p.opname,src,arg.GetVasp(),dst):GetCVecs(p.opname,src,dst); + if(vecs) { + if(arg.CanbeComplex()) { + CX z = arg.GetAComplex(); + p.cbin.rarg = z.real; + p.cbin.iarg = z.imag; + } + else if(arg.IsEnv()) { + if(p.args != 1) + ERRINTERNAL(); + else + p.arg[0].SetE(&arg.GetEnv()); + } + + ret = DoOp(vecs,fun,p); + delete vecs; + } + + return ret; +} + + +BL VecOp::_d__run(V fun(S &v,S a),OpParam &p) { _D__run(fun,p); } +BL VecOp::_d__cun(V fun(S &rv,S &iv,S ra,S ia),OpParam &p) { _D__cun(fun,p); } +BL VecOp::_d__rbin(V fun(S &v,S a,S b),OpParam &p) { _D__rbin(fun,p); } +BL VecOp::_d__cbin(V fun(S &rv,S &iv,S ra,S ia,S rb,S ib),OpParam &p) { _D__cbin(fun,p); } +BL VecOp::_d__rop(V fun(S &v,S a,OpParam &p),OpParam &p) { _D__rop(fun,p); } +BL VecOp::_d__cop(V fun(S &rv,S &iv,S ra,S ia,OpParam &p),OpParam &p) { _D__cop(fun,p); } + + diff --git a/externals/grill/vasp/source/opbase.h b/externals/grill/vasp/source/opbase.h new file mode 100644 index 00000000..a4d1347b --- /dev/null +++ b/externals/grill/vasp/source/opbase.h @@ -0,0 +1,50 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPBASE_H +#define __VASP_OPBASE_H + +#include "main.h" +#include "classes.h" +#include "vecblk.h" +#include "opparam.h" + +namespace VecOp { + typedef BL opfun(OpParam &p); + + BL _d__run(V fun(S &v,S a),OpParam &p); + BL _d__cun(V fun(S &rv,S &iv,S ra,S ia),OpParam &p); + BL _d__rbin(V fun(S &v,S a,S b),OpParam &p); + BL _d__cbin(V fun(S &rv,S &iv,S ra,S ia,S rb,S ib),OpParam &p); + BL _d__rop(V fun(S &v,S a,OpParam &p),OpParam &p); + BL _d__cop(V fun(S &rv,S &iv,S ra,S ia,OpParam &p),OpParam &p); +} + + +namespace VaspOp { + RVecBlock *GetRVecs(const C *op,Vasp &src,Vasp *dst = NULL); + CVecBlock *GetCVecs(const C *op,Vasp &src,Vasp *dst = NULL,BL full = false); + RVecBlock *GetRVecs(const C *op,Vasp &src,const Vasp &arg,Vasp *dst = NULL,I multi = -1,BL ssize = true); + CVecBlock *GetCVecs(const C *op,Vasp &src,const Vasp &arg,Vasp *dst = NULL,I multi = -1,BL ssize = true,BL full = false); + + Vasp *DoOp(RVecBlock *vecs,VecOp::opfun *fun,OpParam &p,BL symm = false); + Vasp *DoOp(CVecBlock *vecs,VecOp::opfun *fun,OpParam &p,BL symm = false); + + // -------- transformations ----------------------------------- + + // unary functions + Vasp *m_run(OpParam &p,Vasp &src,Vasp *dst,VecOp::opfun *fun); // real unary (one vec or real) + Vasp *m_cun(OpParam &p,Vasp &src,Vasp *dst,VecOp::opfun *fun); // complex unary (one vec or complex) + // binary functions + Vasp *m_rbin(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst,VecOp::opfun *fun); // real binary (one vec or real) + Vasp *m_cbin(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst,VecOp::opfun *fun); // complex binary (one vec or complex) +} + +#endif diff --git a/externals/grill/vasp/source/opdefs.h b/externals/grill/vasp/source/opdefs.h new file mode 100644 index 00000000..bf9101f7 --- /dev/null +++ b/externals/grill/vasp/source/opdefs.h @@ -0,0 +1,364 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPDEFS_H +#define __VASP_OPDEFS_H + +#include "oploop.h" + +#ifdef VASP_CHN1 +#define _D_ALWAYS1 1 +#else +#define _D_ALWAYS1 0 +#endif + +/*! \brief skeleton for unary real operations +*/ +#define _D__run(fun,p) \ +{ \ + register const S *sr = p.rsdt; \ + register S *dr = p.rddt; \ + register I i; \ + if(sr == dr) \ + if(_D_ALWAYS1 || p.rds == 1) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*dr); dr++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*dr); dr += p.rds; } \ + _E_LOOP \ + else \ + if(_D_ALWAYS1 || (p.rss == 1 && p.rds == 1)) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*sr); sr++,dr++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*sr); sr += p.rss,dr += p.rds; } \ + _E_LOOP \ + return true; \ +} + +#define d__run(fun,p) { return _d__run(fun,p); } + +/*! \brief skeleton for unary complex operations +*/ +#define _D__cun(fun,p) \ +{ \ + register const S *sr = p.rsdt,*si = p.isdt; \ + register S *dr = p.rddt,*di = p.iddt; \ + register I i; \ + if(sr == dr && si == di) \ + if(_D_ALWAYS1 || (p.rds == 1 && p.ids == 1)) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*dr,*di); dr++,di++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*dr,*di); dr += p.rds,di += p.ids; } \ + _E_LOOP \ + else \ + if(_D_ALWAYS1 || (p.rss == 1 && p.iss == 1 && p.rds == 1 && p.ids == 1)) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*sr,*si); sr++,si++,dr++,di++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*sr,*si); sr += p.rss,si += p.iss,dr += p.rds,di += p.ids; } \ + _E_LOOP \ + return true; \ +} + +#define d__cun(fun,p) { return _d__cun(fun,p); } + + +/*! \brief skeleton for binary real operations +*/ +#define _D__rbin(fun,p) \ +{ \ + register const S *sr = p.rsdt; \ + register S *dr = p.rddt; \ + register I i; \ + if(p.HasArg() && p.arg[0].Is()) { \ + switch(p.arg[0].argtp) { \ + case OpParam::Arg::arg_v: { \ + register const S *ar = p.arg[0].v.rdt; \ + if(p.rsdt == p.rddt) \ + if(_D_ALWAYS1 || (p.rds == 1 && p.arg[0].v.rs == 1)) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*dr,*ar); dr++,ar++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*dr,*ar); dr += p.rds,ar += p.arg[0].v.rs; } \ + _E_LOOP \ + else \ + if(_D_ALWAYS1 || (p.rss == 1 && p.rds == 1 && p.arg[0].v.rs == 1)) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*sr,*ar); sr++,dr++,ar++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*sr,*ar); sr += p.rss,dr += p.rds,ar += p.arg[0].v.rs; } \ + _E_LOOP \ + break; \ + } \ + case OpParam::Arg::arg_env: { \ + Env::Iter it(*p.arg[0].e.env); it.Init(0); \ + if(p.rsdt == p.rddt) \ + if(_D_ALWAYS1 || p.rds == 1) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*dr,it.ValFwd(i)); dr++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*dr,it.ValFwd(i)); dr += p.rds; } \ + _E_LOOP \ + else \ + if(_D_ALWAYS1 || (p.rss == 1 && p.rds == 1)) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*sr,it.ValFwd(i)); sr++,dr++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*sr,it.ValFwd(i)); sr += p.rss,dr += p.rds; } \ + _E_LOOP \ + break; \ + } \ + case OpParam::Arg::arg_x: { \ + const R v = p.arg[0].x.r; \ + if(p.rsdt == p.rddt) \ + if(_D_ALWAYS1 || p.rds == 1) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*dr,v); dr++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*dr,v); dr += p.rds; } \ + _E_LOOP \ + else \ + if(_D_ALWAYS1 || (p.rss == 1 && p.rds == 1)) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*sr,v); sr++,dr++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*sr,v); sr += p.rss,dr += p.rds; } \ + _E_LOOP \ + break; \ + } \ + } \ + } \ + else { \ + register const S v = p.rbin.arg; \ + if(p.rsdt == p.rddt) \ + if(_D_ALWAYS1 || p.rds == 1) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*dr,v); dr++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*dr,v); dr += p.rds; } \ + _E_LOOP \ + else \ + if(_D_ALWAYS1 || (p.rss == 1 && p.rds == 1)) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*sr,v); sr++,dr++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*sr,v); sr += p.rss,dr += p.rds; } \ + _E_LOOP \ + } \ + return true; \ +} + +#define d__rbin(fun,p) { return _d__rbin(fun,p); } + + +/*! \brief skeleton for binary complex operations +*/ +#define _D__cbin(fun,p) \ +{ \ + register const S *sr = p.rsdt,*si = p.isdt; \ + register S *dr = p.rddt,*di = p.iddt; \ + register I i; \ + if(p.HasArg() && p.arg[0].Is()) { \ + switch(p.arg[0].argtp) { \ + case OpParam::Arg::arg_v: { \ + register const S *ar = p.arg[0].v.rdt,*ai = p.arg[0].v.idt; \ + if(ai) \ + if(sr == dr && si == di) \ + if(_D_ALWAYS1 || (p.rds == 1 && p.ids == 1 && p.arg[0].v.rs == 1 && p.arg[0].v.is == 1)) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*dr,*di,*ar,*ai); dr++,di++,ar++,ai++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*dr,*di,*ar,*ai); dr += p.rds,di += p.ids,ar += p.arg[0].v.rs,ai += p.arg[0].v.is; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*sr,*si,*ar,*ai); sr += p.rss,si += p.iss,dr += p.rds,di += p.ids,ar += p.arg[0].v.rs,ai += p.arg[0].v.is; } \ + _E_LOOP \ + else \ + if(sr == dr && si == di) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*dr,*di,*ar,0); dr += p.rds,di += p.ids,ar += p.arg[0].v.rs; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*sr,*si,*ar,0); sr += p.rss,si += p.iss,dr += p.rds,di += p.ids,ar += p.arg[0].v.rs; } \ + _E_LOOP \ + break; \ + } \ + case OpParam::Arg::arg_env: { \ + Env::Iter it(*p.arg[0].e.env); it.Init(0); \ + if(sr == dr && si == di) \ + if(_D_ALWAYS1 || (p.rds == 1 && p.ids == 1)) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*dr,*di,it.ValFwd(i),0); dr++,di++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*dr,*di,it.ValFwd(i),0); dr += p.rds,di += p.ids; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*sr,*si,it.ValFwd(i),0); sr += p.rss,si += p.iss,dr += p.rds,di += p.ids; } \ + _E_LOOP \ + break; \ + } \ + case OpParam::Arg::arg_x: { \ + register const R ar = p.arg[0].x.r,ai = p.arg[0].x.i; \ + if(sr == dr && si == di) \ + if(_D_ALWAYS1 || (p.rds == 1 && p.ids == 1)) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*dr,*di,ar,ai); dr++,di++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*dr,*di,ar,ai); dr += p.rds,di += p.ids; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*sr,*si,ar,ai); sr += p.rss,si += p.iss,dr += p.rds,di += p.ids; } \ + _E_LOOP \ + break; \ + } \ + } \ + } \ + else { \ + register const S rv = p.cbin.rarg,iv = p.cbin.iarg; \ + if(sr == dr && si == di) \ + if(_D_ALWAYS1 || (p.rds == 1 && p.ids == 1)) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*dr,*di,rv,iv); dr++,di++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*dr,*di,rv,iv); dr += p.rds,di += p.ids; } \ + _E_LOOP \ + else \ + if(_D_ALWAYS1 || (p.rds == 1 && p.ids == 1 && p.rss == 1 && p.iss == 1)) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*sr,*si,rv,iv); sr++,si++,dr++,di++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*sr,*si,rv,iv); sr += p.rss,si += p.iss,dr += p.rds,di += p.ids; } \ + _E_LOOP \ + } \ + return true; \ +} + +#define d__cbin(fun,p) { return _d__cbin(fun,p); } + + +/*! \brief skeleton for real operations with parameter block +*/ +#define _D__rop(fun,p) \ +{ \ + register const S *sr = p.rsdt; \ + register S *dr = p.rddt; \ + register I i; \ + if(sr == dr) \ + if(_D_ALWAYS1 || p.rds == 1) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*dr,p); dr++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*dr,p); dr += p.rds; } \ + _E_LOOP \ + else \ + if(_D_ALWAYS1 || (p.rss == 1 && p.rds == 1)) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*sr,p); sr++,dr++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*sr,p); sr += p.rss,dr += p.rds; } \ + _E_LOOP \ + return true; \ +} + +#define d__rop(fun,p) { return _d__rop(fun,p); } + + +/*! \brief skeleton for complex operations with parameter block +*/ +#define _D__cop(fun,p) \ +{ \ + register const S *sr = p.rsdt,*si = p.isdt; \ + register S *dr = p.rddt,*di = p.iddt; \ + register I i; \ + if(sr == dr && si == di) \ + if(_D_ALWAYS1 || (p.rds == 1 && p.ids == 1)) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*dr,*di,p); dr++,di++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*dr,*di,p); dr += p.rds,di += p.ids; } \ + _E_LOOP \ + else \ + if(_D_ALWAYS1 || (p.rss == 1 && p.iss == 1 && p.rds == 1 && p.ids == 1)) \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*sr,*si,p); sr++,si++,dr++,di++; } \ + _E_LOOP \ + else \ + _D_LOOP(i,p.frames) \ + { fun(*dr,*di,*sr,*si,p); sr += p.rss,si += p.iss,dr += p.rds,di += p.ids; } \ + _E_LOOP \ + return true; \ +} + +#define d__cop(fun,p) { return _d__cop(fun,p); } + + +#ifdef VASP_COMPACT +#define D__run(fun,p) d__run(fun,p) +#define D__cun(fun,p) d__cun(fun,p) +#define D__rbin(fun,p) d__rbin(fun,p) +#define D__cbin(fun,p) d__cbin(fun,p) +#define D__rop(fun,p) d__rop(fun,p) +#define D__cop(fun,p) d__cop(fun,p) +#else +#define D__run(fun,p) _D__run(fun,p) +#define D__cun(fun,p) _D__cun(fun,p) +#define D__rbin(fun,p) _D__rbin(fun,p) +#define D__cbin(fun,p) _D__cbin(fun,p) +#define D__rop(fun,p) _D__rop(fun,p) +#define D__cop(fun,p) _D__cop(fun,p) +#endif + +#endif diff --git a/externals/grill/vasp/source/oploop.h b/externals/grill/vasp/source/oploop.h new file mode 100755 index 00000000..6b268022 --- /dev/null +++ b/externals/grill/vasp/source/oploop.h @@ -0,0 +1,38 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPLOOP_H +#define __VASP_OPLOOP_H + +#define _D_BLOCK 1024 + +#define _D_MIN(a,b) ((a) < (b)?(a):(b)) + +#ifdef FLEXT_THREADS +#define _D_LOOP(VAR,LEN) { \ + register I __i__; \ + for(__i__ = 0; __i__ < LEN; flext_base::ThrYield()) { \ + I __m__ = _D_MIN(LEN,__i__+_D_BLOCK); for(; (VAR = __i__) < __m__; ++__i__) { +#define _E_LOOP } if(__i__ < __m__) break; }} +#define _D_WHILE(COND) { \ + for(; (COND) ; flext_base::ThrYield()) { \ + register I __i__ = 0; \ + for(; __i__ < _D_BLOCK && (COND); ++__i__) { +#define _E_WHILE } if(__i__ < _D_BLOCK) break; }} +#else +#define _D_LOOP(VAR,LEN) { \ + for(VAR = 0; VAR < LEN; ++VAR) { +#define _E_LOOP }} +#define _D_WHILE(COND) { \ + while(COND) { +#define _E_WHILE }} +#endif + +#endif diff --git a/externals/grill/vasp/source/opparam.cpp b/externals/grill/vasp/source/opparam.cpp new file mode 100644 index 00000000..9925e4dd --- /dev/null +++ b/externals/grill/vasp/source/opparam.cpp @@ -0,0 +1,223 @@ +#include "opparam.h" +//#include <math.h> + +/* +// Duplication of breakpoint lists should be avoided +OpParam::Arg &OpParam::Arg::operator =(const Arg &op) +{ + Clear(); + + switch(argtp = op.argtp) { + case arg_x: x = op.x; break; + case arg_v: v = op.v; break; + case arg_bp: { + // Copy breakpoint list (find a different way, e.g. store them in a pool) + bp.pts = op.bp.pts; + bp.pt = new R[bp.pts]; + for(I i = 0; i < bp.pts; ++i) + bp.pt[i] = op.bp.pt[i]; + break; + } + } + + return *this; +} +*/ +V OpParam::Arg::Clear() +{ +// if(argtp == arg_bp && bp.pt) delete[] bp.pt; + argtp = arg_; +} + +OpParam::Arg &OpParam::Arg::SetX(S r,S i) +{ + Clear(); + argtp = arg_x; + x.r = r,x.i = i; + return *this; +} + +OpParam::Arg &OpParam::Arg::SetV(S *r,I rs,S *i,I is) +{ + Clear(); + argtp = arg_v; + v.rdt = r,v.rs = rs; + v.idt = i,v.is = is; + return *this; +} + +/* +OpParam::Arg &OpParam::Arg::SetB(I pts,const R *pt) +{ + Clear(); + argtp = arg_bp; + bp.pts = pts; + bp.pt = new R[pts]; + for(I ix = 0; ix < pts; ix) bp.pt[ix] = pt[ix]; + return *this; +} +*/ + +OpParam::Arg &OpParam::Arg::SetE(const Env *env) +{ + Clear(); + argtp = arg_env; + e.env = env; + return *this; +} + + +/* +V OpParam::SDR_Rev() { SR_Rev(); DR_Rev(); } +V OpParam::SDI_Rev() { SI_Rev(); DI_Rev(); } +V OpParam::SDC_Rev() { SDR_Rev(); SDI_Rev(); } +V OpParam::ADR_Rev() { AR_Rev(); DR_Rev(); } +V OpParam::ADI_Rev() { AI_Rev(); DI_Rev(); } +V OpParam::ADC_Rev() { ADR_Rev(); ADI_Rev(); } +V OpParam::SADR_Rev() { SR_Rev(); AR_Rev(); DR_Rev(); } +V OpParam::SADI_Rev() { SI_Rev(); AI_Rev(); DI_Rev(); } +V OpParam::SADC_Rev() { SADR_Rev(); SADI_Rev(); } +*/ + +OpParam::OpParam(const C *opnm,I nargs): + opname(opnm),frames(0),args(0),arg(NULL), + /*part(false),*/ ovrlap(false),revdir(false),oddrem(false) +{ + InitArgs(nargs); +} + +OpParam::~OpParam() { Clear(); } + +V OpParam::InitArgs(I n) +{ + if(arg) Clear(); + args = n; + if(args) arg = new Arg[args]; +} + +V OpParam::Clear() +{ + if(arg) { delete[] arg; arg = NULL; } + args = 0; +} + + +/*! \brief Reverse direction of real vector operation + \todo Check for existence of vectors! +*/ +V OpParam::R_Rev() +{ + + SR_Rev(); + DR_Rev(); + AR_Rev(); + revdir = true; +} + +/*! \brief Reverse direction of complex vector operation + \todo Check for existence of vectors! +*/ +V OpParam::C_Rev() +{ + SR_Rev(); SI_Rev(); + DR_Rev(); DI_Rev(); + AR_Rev(); AI_Rev(); + revdir = true; +} + + +V OpParam::AR_Rev(I bl) +{ + if(arg[bl].argtp == Arg::arg_v && arg[bl].v.rdt) + arg[bl].v.rdt -= (frames-1)*(arg[bl].v.rs = -arg[bl].v.rs); +} + +V OpParam::AI_Rev(I bl) +{ + if(arg[bl].argtp == Arg::arg_v && arg[bl].v.idt) + arg[bl].v.idt -= (frames-1)*(arg[bl].v.is = -arg[bl].v.is); +} + +BL OpParam::AR_In(I bl) const { return arg[bl].argtp == Arg::arg_v && arg[bl].v.rdt && rddt > arg[bl].v.rdt && rddt < arg[bl].v.rdt+frames*arg[bl].v.rs; } +BL OpParam::AI_In(I bl) const { return arg[bl].argtp == Arg::arg_v && arg[bl].v.idt && iddt > arg[bl].v.idt && iddt < arg[bl].v.idt+frames*arg[bl].v.is; } + +BL OpParam::AR_Can(I bl) const { return arg[bl].argtp != Arg::arg_v || !arg[bl].v.rdt || arg[bl].v.rdt <= rddt || arg[bl].v.rdt >= rddt+frames*rds; } +BL OpParam::AI_Can(I bl) const { return arg[bl].argtp != Arg::arg_v || !arg[bl].v.idt || arg[bl].v.idt <= iddt || arg[bl].v.idt >= iddt+frames*ids; } + +BL OpParam::AR_Ovr(I bl) const { return arg[bl].argtp == Arg::arg_v && arg[bl].v.rdt && rddt != arg[bl].v.rdt && rddt < arg[bl].v.rdt+frames*arg[bl].v.rs && arg[bl].v.rdt < rddt+frames*rds; } +BL OpParam::AI_Ovr(I bl) const { return arg[bl].argtp == Arg::arg_v && arg[bl].v.idt && iddt != arg[bl].v.idt && iddt < arg[bl].v.idt+frames*arg[bl].v.is && arg[bl].v.idt < iddt+frames*ids; } + + + +BL OpParam::AR_In() const +{ + for(I i = 0; i < args; ++i) + if(AR_In(i)) return true; + return false; +} + +BL OpParam::AI_In() const +{ + for(I i = 0; i < args; ++i) + if(!AI_In(i)) return true; + return false; +} + +BL OpParam::AR_Can() const +{ + for(I i = 0; i < args; ++i) + if(!AR_Can(i)) return false; + return true; +} + +BL OpParam::AI_Can() const +{ + for(I i = 0; i < args; ++i) + if(!AI_Can(i)) return false; + return true; +} + +BL OpParam::AR_Ovr() const +{ + for(I i = 0; i < args; ++i) + if(!AR_Ovr(i)) return false; + return true; +} + +BL OpParam::AI_Ovr() const +{ + for(I i = 0; i < args; ++i) + if(!AI_Ovr(i)) return false; + return true; +} + + +V OpParam::AR_Rev() +{ + for(I i = 0; i < args; ++i) AR_Rev(i); +} + +V OpParam::AI_Rev() +{ + for(I i = 0; i < args; ++i) AI_Rev(i); +} + +V OpParam::SkipOddMiddle() +{ + if(symm == 0 && oddrem) { + // don't process middle sample! + if(revdir) rsdt += rss,rddt += rds; + frames--; + } +} + +V OpParam::SkipOddMiddle(S m) +{ + if(symm == 0 && oddrem) { + // set and skip middle sample! + frames--; + if(revdir) *rddt = m,rsdt += rss,rddt += rds; + else rddt[frames] = m; + } +} + diff --git a/externals/grill/vasp/source/opparam.h b/externals/grill/vasp/source/opparam.h new file mode 100644 index 00000000..0b6e5bd5 --- /dev/null +++ b/externals/grill/vasp/source/opparam.h @@ -0,0 +1,128 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPPARAM_H +#define __VASP_OPPARAM_H + +#include "vecblk.h" +#include "arg.h" + +class OpParam { +public: + OpParam(const C *opnm,I args); + ~OpParam(); + + V InitArgs(I nargs); + V Clear(); + + BL HasArg() const { return arg != NULL; } + + const C *opName() const { return opname; } + + // check for overlap + // \remark if on same vector, stride is the same for src, arg, dst! + inline BL SR_In() const { return rddt > rsdt && rddt < rsdt+frames*rss; } + inline BL SI_In() const { return iddt > isdt && iddt < isdt+frames*iss; } + BL AR_In(I bl) const; + BL AI_In(I bl) const; + BL AR_In() const; + BL AI_In() const; + + // Can we reverse direction? + inline BL SR_Can() const { return rsdt <= rddt || rsdt >= rddt+frames*rds; } + inline BL SI_Can() const { return isdt <= iddt || isdt >= iddt+frames*ids; } + BL AR_Can(I bl) const; + BL AI_Can(I bl) const; + BL AR_Can() const; + BL AI_Can() const; + + // does it overlap? (works only with rss,rds,ras.... > 0) + inline BL SR_Ovr() const { return rddt != rsdt && rddt < rsdt+frames*rss && rsdt < rddt+frames*rds; } + inline BL SI_Ovr() const { return iddt != isdt && iddt < isdt+frames*iss && isdt < iddt+frames*ids; } + BL AR_Ovr(I bl) const; + BL AI_Ovr(I bl) const; + BL AR_Ovr() const; + BL AI_Ovr() const; + + V AR_Rev(); + V AI_Rev(); + + V R_Rev(); + V C_Rev(); + + V SkipOddMiddle(); + V SkipOddMiddle(S m); + + const C *opname; + I frames,symm,args; + BL ovrlap,revdir,oddrem; + S *rsdt,*isdt; I rss,iss; + S *rddt,*iddt; I rds,ids; + + class Arg + { + public: + Arg(): argtp(arg_) {} +// Arg(const Arg &op) { operator =(op); } + ~Arg() { Clear(); } + V Clear(); + + BL Is() const { return argtp != arg_; } + +// Arg &operator =(const Arg &op); +// Arg &operator =(const Argument &arg); + + Arg &SetX(S r,S i = 0); + Arg &SetV(S *r,I rs,S *i = NULL,I is = 0); + Arg &SetE(const Env *bp); + + typedef struct env_t { const Env *env; }; + typedef struct v_t { S *rdt,*idt; I rs,is; }; + typedef struct x_t { R r,i; }; + + enum { arg_ = 0,arg_x,arg_v,arg_env } argtp; + union { + x_t x; + v_t v; + env_t e; + }; + }; + + Arg *arg; + + union { + struct { R coef,carry; I rep; } flt; + struct { R carry; I rep; } intdif; + struct { BL cx; R density; I cnt; } peaks; + struct { R ph,phinc; } gen; + struct { R factor,center; I mode,fill; } tilt; + struct { R cur,inc; } bvl; + struct { R sh; I ish; I fill; } sh; + struct { I wndtp; BL inv,mul; R p1,p2,p3; } wnd; + struct { R minmax,scl; } norm; + struct { I arg; } ibin; + struct { R arg; } rbin; + struct { R rarg,iarg; } cbin; + struct { I *order; } perm; + struct { R val; I offs,dif,dir,slope; } srch; + }; + +private: + // reverse direction + inline V SR_Rev() { rsdt -= (frames-1)*(rss = -rss); } + inline V SI_Rev() { isdt -= (frames-1)*(iss = -iss); } + V AR_Rev(I bl); + V AI_Rev(I bl); + inline V DR_Rev() { rddt -= (frames-1)*(rds = -rds); } + inline V DI_Rev() { iddt -= (frames-1)*(ids = -ids); } + +}; + +#endif diff --git a/externals/grill/vasp/source/oppermute.h b/externals/grill/vasp/source/oppermute.h new file mode 100644 index 00000000..c307a3ae --- /dev/null +++ b/externals/grill/vasp/source/oppermute.h @@ -0,0 +1,121 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPPERMUTE_H +#define __VASP_OPPERMUTE_H + +#include "opparam.h" +#include "oploop.h" + +#define PERMTMPL +#define MAXPERMDIM 2 + +template<class T> +inline void permswap(T &a,T &b) { register T t = a; a = b; b = t; } + +#ifdef PERMTMPL +template<class T,int origination(int pos, int sz,OpParam &p)> +void permutation1(OpParam &p) +#else +template<class T> +void permutation1(OpParam &p,int (*origination)(int pos, int sz,OpParam &p)) +#endif +{ + T *ddt = p.rddt; + const I ds = p.rds; + const I sz = p.frames; + + if(ddt != p.rsdt) { + // not in place + const T *sdt = p.rsdt; + const I ss = p.rss; + I i; + _D_LOOP(i,sz) ddt[origination(i,sz,p)*ds] = sdt[i*ss]; _E_LOOP + } + else { + // in place + // \todo try to come from both sides! + I i; + _D_LOOP(i,sz-1) + int cur = i; + do { cur = origination(cur,sz,p); } while(cur < i); + if(cur > i) { + // swap + permswap(ddt[cur*ds],ddt[i*ds]); + } + _E_LOOP + } +} + +#ifdef PERMTMPL +template<class T,int origination(int pos, int sz,OpParam &p)> +void permutation2(OpParam &p) +#else +template<class T> +void permutation2(OpParam &p,int (*origination)(int pos, int sz,OpParam &p)) +#endif +{ + T *rddt = p.rddt,*iddt = p.iddt; + const I rds = p.rds,ids = p.ids; + const I sz = p.frames; + bool rinpl = rddt == p.rsdt,iinpl = iddt == p.isdt; + + if(rinpl == iinpl) { + // re and im both in place + I i; + _D_LOOP(i,sz-1) + int cur = i; + do { cur = origination(cur,sz,p); } while(cur < i); + if(cur > i) { + // swap + permswap(rddt[cur*rds],rddt[i*rds]); + permswap(iddt[cur*ids],iddt[i*ids]); + } + _E_LOOP + } + else { + if(!rinpl) { + const T *sdt = p.rsdt; + const I ss = p.rss; + I i; + if(ss == 1 && rds == 1) + _D_LOOP(i,sz) *(rddt++) = *(sdt++); _E_LOOP + else + _D_LOOP(i,sz) *rddt = *sdt,rddt += rds,sdt += ss; _E_LOOP + rddt = p.rddt; + } + else permutation1<T>(p,origination); + + if(!iinpl) { + const T *sdt = p.isdt; + const I ss = p.iss; + I i; + if(ss == 1 && ids == 1) + _D_LOOP(i,sz) *(iddt++) = *(sdt++); _E_LOOP + else + _D_LOOP(i,sz) *iddt = *sdt,iddt += ids,sdt += ss; _E_LOOP + iddt = p.iddt; + } + else { + permswap(p.rddt,p.iddt); permswap(p.rds,p.ids); + permutation1<T>(p,origination); + permswap(p.rddt,p.iddt); permswap(p.rds,p.ids); + } + } +} + +#ifdef PERMTMPL +#define PERMUTATION(tp,dim,p,func) permutation ## dim <tp,func>(p) +#else +#define PERMUTATION(tp,dim,p,func) permutation ## dim <tp>(p,func) +#endif + +#endif + diff --git a/externals/grill/vasp/source/ops.h b/externals/grill/vasp/source/ops.h new file mode 100644 index 00000000..00dc8e44 --- /dev/null +++ b/externals/grill/vasp/source/ops.h @@ -0,0 +1,27 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPS_H +#define __VASP_OPS_H + +#include "ops_assign.h" +#include "ops_arith.h" +#include "ops_trnsc.h" +#include "ops_cmp.h" +#include "ops_cplx.h" +#include "ops_flt.h" +#include "ops_dft.h" +#include "ops_gen.h" +#include "ops_wnd.h" +#include "ops_rearr.h" +#include "ops_resmp.h" +#include "ops_feature.h" + +#endif diff --git a/externals/grill/vasp/source/ops_arith.cpp b/externals/grill/vasp/source/ops_arith.cpp new file mode 100644 index 00000000..5d62e2c6 --- /dev/null +++ b/externals/grill/vasp/source/ops_arith.cpp @@ -0,0 +1,64 @@ +/* + +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_arith.h" +#include "opdefs.h" +#include "util.h" +#include <math.h> + +template<class T> inline V f_radd(T &v,T a,T b) { v = a+b; } +template<class T> inline V f_rsub(T &v,T a,T b) { v = a-b; } +template<class T> inline V f_rsubr(T &v,T a,T b) { v = b-a; } +template<class T> inline V f_rmul(T &v,T a,T b) { v = a*b; } +template<class T> inline V f_rdiv(T &v,T a,T b) { v = a/b; } +template<class T> inline V f_rdivr(T &v,T a,T b) { v = b/a; } +template<class T> inline V f_rmod(T &v,T a,T b) { v = fmod(a,b); } + +BL VecOp::d_add(OpParam &p) { D__rbin(f_radd<S>,p); } +BL VecOp::d_sub(OpParam &p) { D__rbin(f_rsub<S>,p); } +BL VecOp::d_subr(OpParam &p) { D__rbin(f_rsubr<S>,p); } +BL VecOp::d_mul(OpParam &p) { D__rbin(f_rmul<S>,p); } +BL VecOp::d_div(OpParam &p) { D__rbin(f_rdiv<S>,p); } +BL VecOp::d_divr(OpParam &p) { D__rbin(f_rdivr<S>,p); } +BL VecOp::d_mod(OpParam &p) { D__rbin(f_rmod<S>,p); } + + +VASP_BINARY("vasp.+",add,true,VASP_ARG_R(0),"Adds a value, envelope or vasp") +VASP_BINARY("vasp.-",sub,true,VASP_ARG_R(0),"Subtracts a value, envelope or vasp") +VASP_BINARY("vasp.!-",subr,true,VASP_ARG_R(0),"Reverse subtracts a value, envelope or vasp") +VASP_BINARY("vasp.*",mul,true,VASP_ARG_R(1),"Multiplies with a value, envelope or vasp") +VASP_BINARY("vasp./",div,true,VASP_ARG_R(1),"Divides by a value, envelope or vasp") +VASP_BINARY("vasp.!/",divr,true,VASP_ARG_R(1),"Reverse divides by a value, envelope or vasp") +VASP_BINARY("vasp.%",mod,true,VASP_ARG_R(0),"Calculates the remainder of the division by a value, envelope or vasp") + +// ----------------------------------------------------- + +template<class T> inline V f_rsqr(T &v,T a) { v = a*a; } +template<class T> inline V f_rssqr(T &v,T a) { v = a*fabs(a); } + +BL VecOp::d_sqr(OpParam &p) { D__run(f_rsqr<S>,p); } +BL VecOp::d_ssqr(OpParam &p) { d__run(f_rssqr<S>,p); } + +VASP_UNARY("vasp.sqr",sqr,true,"Calculates the square") +VASP_UNARY("vasp.ssqr",ssqr,true,"Calculates the square with preservation of the sign") + + +// ----------------------------------------------------- + +template<class T> inline V f_rsign(T &v,T a) { v = (a == 0?0:(a < 0?-1.:1.)); } +template<class T> inline V f_rabs(T &v,T a) { v = fabs(a); } + +BL VecOp::d_sign(OpParam &p) { D__run(f_rsign<S>,p); } +BL VecOp::d_abs(OpParam &p) { D__run(f_rabs<S>,p); } + + +VASP_UNARY("vasp.sign",sign,true,"Calculates the sign (signum function)") +VASP_UNARY("vasp.abs",abs,true,"Calulates the absolute value") + diff --git a/externals/grill/vasp/source/ops_arith.h b/externals/grill/vasp/source/ops_arith.h new file mode 100644 index 00000000..6e2bb879 --- /dev/null +++ b/externals/grill/vasp/source/ops_arith.h @@ -0,0 +1,72 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPS_ARITH_H +#define __VASP_OPS_ARITH_H + +#include "opbase.h" + +// Arithmetic math functions + +namespace VecOp { + BL d_add(OpParam &p); + BL d_sub(OpParam &p); + BL d_subr(OpParam &p); + BL d_mul(OpParam &p); + BL d_div(OpParam &p); + BL d_divr(OpParam &p); + BL d_mod(OpParam &p); + + BL d_cadd(OpParam &p); + BL d_csub(OpParam &p); + BL d_csubr(OpParam &p); + BL d_cmul(OpParam &p); + BL d_cdiv(OpParam &p); + BL d_cdivr(OpParam &p); + + BL d_sqr(OpParam &p); + BL d_ssqr(OpParam &p); + BL d_csqr(OpParam &p); + BL d_cpowi(OpParam &p); + + BL d_sign(OpParam &p); + BL d_abs(OpParam &p); + BL d_cabs(OpParam &p); +} + +namespace VaspOp { + inline Vasp *m_add(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_add); } // add to (one vec or real) + inline Vasp *m_sub(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_sub); } // sub from (one vec or real) + inline Vasp *m_subr(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_subr); } // reverse sub from (one vec or real) + inline Vasp *m_mul(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_mul); } // mul with (one vec or real) + inline Vasp *m_div(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_div); } // div by (one vec or real) + inline Vasp *m_divr(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_divr); } // reverse div by (one vec or real) + inline Vasp *m_mod(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_mod); } // modulo by (one vec or real) + + inline Vasp *m_cadd(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_cbin(p,src,arg,dst,VecOp::d_cadd); } // complex add (pairs of vecs or complex) + inline Vasp *m_csub(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_cbin(p,src,arg,dst,VecOp::d_csub); } // complex sub (pairs of vecs or complex) + inline Vasp *m_csubr(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_cbin(p,src,arg,dst,VecOp::d_csubr); } // reverse complex sub (pairs of vecs or complex) + inline Vasp *m_cmul(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_cbin(p,src,arg,dst,VecOp::d_cmul); } // complex mul (pairs of vecs or complex) + inline Vasp *m_cdiv(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_cbin(p,src,arg,dst,VecOp::d_cdiv); } // complex div (pairs of vecs or complex) + inline Vasp *m_cdivr(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_cbin(p,src,arg,dst,VecOp::d_cdivr); } // complex reverse div (pairs of vecs or complex) + + inline Vasp *m_sqr(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_run(p,src,dst,VecOp::d_sqr); } // unsigned square + inline Vasp *m_ssqr(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_run(p,src,dst,VecOp::d_ssqr); } // signed square + inline Vasp *m_csqr(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_cun(p,src,dst,VecOp::d_csqr); } // complex square (with each two channels) +// inline Vasp *m_csqrt(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_cun(p,src,dst,VecOp::d_csqrt); } // complex square root (how about branches?) + + Vasp *m_cpowi(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL); // complex integer power (with each two channels) + + inline Vasp *m_sign(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_run(p,src,dst,VecOp::d_sign); } // sign function + inline Vasp *m_abs(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_run(p,src,dst,VecOp::d_abs); } // absolute values + inline Vasp *m_cabs(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_cun(p,src,dst,VecOp::d_cabs); } // absolute values +} + +#endif diff --git a/externals/grill/vasp/source/ops_assign.cpp b/externals/grill/vasp/source/ops_assign.cpp new file mode 100644 index 00000000..96061ce9 --- /dev/null +++ b/externals/grill/vasp/source/ops_assign.cpp @@ -0,0 +1,108 @@ +/* + +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_assign.h" +#include "opdefs.h" + + +template<class T> inline V f_rcopy(T &v,T a) { v = a; } +template<class T> inline V f_ccopy(T &rv,T &iv,T ra,T ia) { rv = ra,iv = ia; } + +template<class T> inline V f_rset(T &v,T,T b) { v = b; } +template<class T> inline V f_cset(T &rv,T &iv,T,T,T rb,T ib) { rv = rb,iv = ib; } + + +BL VecOp::d_copy(OpParam &p) { D__run(f_rcopy<S>,p); } +BL VecOp::d_ccopy(OpParam &p) { D__cun(f_ccopy<S>,p); } + +BL VecOp::d_set(OpParam &p) { D__rbin(f_rset<S>,p); } +BL VecOp::d_cset(OpParam &p) { D__cbin(f_cset<S>,p); } + + +VASP_BINARY("vasp.set vasp.=",set,false,VASP_ARG_R(0),"Assigns a value, envelope or vasp") +VASP_BINARY("vasp.cset vasp.c=",cset,false,VASP_ARG_R(0),"Assigns a complex value, real envelope or vasp") + + + +Vasp *VaspOp::m_copy(OpParam &p,Vasp &src,Vasp &arg) +{ + Vasp *s = NULL,*d = NULL; + RVecBlock *vecs = GetRVecs(p.opname,src,&arg); + if(vecs) { + d = DoOp(vecs,VecOp::d_copy,p); + s = vecs->SrcVasp(); + if(d) arg = *d; else { arg.Clear(); delete d; } + delete vecs; + } + return s; +} + +Vasp *VaspOp::m_ccopy(OpParam &p,Vasp &src,Vasp &arg) +{ + Vasp *s = NULL,*d = NULL; + CVecBlock *vecs = GetCVecs(p.opname,src,&arg); + if(vecs) { + d = DoOp(vecs,VecOp::d_ccopy,p); + s = vecs->SrcVasp(); + if(d) arg = *d; else { arg.Clear(); delete d; } + delete vecs; + } + return s; +} + + +class vasp_copy: + public vasp_anyop +{ + FLEXT_HEADER(vasp_copy,vasp_anyop) +public: + + vasp_copy(I argc,t_atom *argv): vasp_anyop(argc,argv,VASP_ARG(),true,XletCode(xlet::tp_any,0)) {} + + virtual V m_to(I,t_atom *) { post("s - destination vasp is ignored!",thisName()); } + + virtual Vasp *do_copy(OpParam &p,Vasp &dst) { return VaspOp::m_copy(p,ref,dst); } + + virtual Vasp *tx_work(const Argument &arg) + { + OpParam p(thisName(),0); + + if(arg.CanbeVasp()) { + Vasp dst = arg.GetAVasp(); + Vasp *ret = do_copy(p,dst); + ToOutVasp(1,dst); + return ret; + } + else { + post("%s - argument is not a valid vasp!",thisName()); // \todo check earlier! + return NULL; + } + } + + virtual V m_help() { post("%s - Copies the triggering vasp to the argument vasp",thisName()); } +}; +FLEXT_LIB_V("vasp, vasp.copy vasp.->",vasp_copy) + + +class vasp_ccopy: + public vasp_copy +{ + FLEXT_HEADER(vasp_ccopy,vasp_copy) +public: + + vasp_ccopy(I argc,t_atom *argv): vasp_copy(argc,argv) {} + + virtual Vasp *do_copy(OpParam &p,Vasp &dst) { return VaspOp::m_ccopy(p,ref,dst); } + + virtual V m_help() { post("%s - Copies complex pairs of the triggering vasp to the argument vasp",thisName()); } +}; +FLEXT_LIB_V("vasp, vasp.ccopy vasp.c->",vasp_ccopy) + + diff --git a/externals/grill/vasp/source/ops_assign.h b/externals/grill/vasp/source/ops_assign.h new file mode 100644 index 00000000..e80501f0 --- /dev/null +++ b/externals/grill/vasp/source/ops_assign.h @@ -0,0 +1,34 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPS_ASSIGN_H +#define __VASP_OPS_ASSIGN_H + +#include "opbase.h" + +// Assignment functions + +namespace VecOp { + BL d_copy(OpParam &p); + BL d_set(OpParam &p); + + BL d_ccopy(OpParam &p); + BL d_cset(OpParam &p); +} + +namespace VaspOp { + inline Vasp *m_set(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_set); } // copy to (one vec or real) + inline Vasp *m_cset(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_cbin(p,src,arg,dst,VecOp::d_cset); } // complex copy (pairs of vecs or complex) + + Vasp *m_copy(OpParam &p,Vasp &src,Vasp &dst); + Vasp *m_ccopy(OpParam &p,Vasp &src,Vasp &dst); +} + +#endif diff --git a/externals/grill/vasp/source/ops_carith.cpp b/externals/grill/vasp/source/ops_carith.cpp new file mode 100644 index 00000000..b2464ab2 --- /dev/null +++ b/externals/grill/vasp/source/ops_carith.cpp @@ -0,0 +1,125 @@ +/* + +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_carith.h" +#include "ops_assign.h" +#include "opdefs.h" +#include "util.h" +#include <math.h> + +template<class T> inline V f_cadd(T &rv,T &iv,T ra,T ia,T rb,T ib) { rv = ra+rb,iv = ia+ib; } +template<class T> inline V f_csub(T &rv,T &iv,T ra,T ia,T rb,T ib) { rv = ra-rb,iv = ia-ib; } +template<class T> inline V f_csubr(T &rv,T &iv,T ra,T ia,T rb,T ib) { rv = rb-ra,iv = ib-ia; } +template<class T> inline V f_cmul(T &rv,T &iv,T ra,T ia,T rb,T ib) { rv = ra*rb-ia*ib, iv = ra*ib+rb*ia; } + +template<class T> inline V f_cdiv(T &rv,T &iv,T ra,T ia,T rb,T ib) +{ + register const R den = sqabs(rb,ib); + rv = (ra*rb+ia*ib)/den; + iv = (ia*rb-ra*ib)/den; +} + +template<class T> inline V f_cdivr(T &rv,T &iv,T ra,T ia,T rb,T ib) +{ + register const R den = sqabs(ra,ia); + rv = (rb*ra+ib*ia)/den; + iv = (ib*ra-rb*ia)/den; +} + +BL VecOp::d_cadd(OpParam &p) { D__cbin(f_cadd<S>,p); } +BL VecOp::d_csub(OpParam &p) { D__cbin(f_csub<S>,p); } +BL VecOp::d_csubr(OpParam &p) { D__cbin(f_csubr<S>,p); } +BL VecOp::d_cmul(OpParam &p) { D__cbin(f_cmul<S>,p); } +BL VecOp::d_cdiv(OpParam &p) { d__cbin(f_cdiv<S>,p); } +BL VecOp::d_cdivr(OpParam &p) { d__cbin(f_cdivr<S>,p); } + + +VASP_BINARY("vasp.c+",cadd,true,VASP_ARG_R(0),"adds a complex value or vasp") +VASP_BINARY("vasp.c-",csub,true,VASP_ARG_R(0),"subtracts a complex value or vasp") +VASP_BINARY("vasp.c!-",csubr,true,VASP_ARG_R(0),"reverse subtracts a complex value or vasp") +VASP_BINARY("vasp.c*",cmul,true,VASP_ARG_R(1),"multiplies by a complex value or vasp") +VASP_BINARY("vasp.c/",cdiv,true,VASP_ARG_R(1),"divides by a complex value or vasp") +VASP_BINARY("vasp.c!/",cdivr,true,VASP_ARG_R(1),"reverse divides by a complex value or vasp") + + +// ----------------------------------------------------- + + +template<class T> inline V f_csqr(T &rv,T &iv,T ra,T ia) { rv = ra*ra-ia*ia; iv = ra*ia*2; } + +BL VecOp::d_csqr(OpParam &p) { D__cun(f_csqr<S>,p); } + +VASP_UNARY("vasp.csqr",csqr,true,"complex square") + +// ----------------------------------------------------- + +template<class T> V f_cpowi(T &rv,T &iv,T ra,T ia,OpParam &p) +{ + register const I powi = p.ibin.arg; + register S rt,it; f_csqr(rt,it,ra,ia); + for(I i = 2; i < powi; ++i) f_cmul(rt,it,rt,it,ra,ia); + rv = rt,iv = it; +} + +BL VecOp::d_cpowi(OpParam &p) { d__cop(f_cpowi<S>,p); } + +Vasp *VaspOp::m_cpowi(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst) +{ + Vasp *ret = NULL; + CVecBlock *vecs = GetCVecs(p.opname,src,dst); + if(vecs) { + I powi = 1; + if(arg.IsList() && arg.GetList().Count() >= 1 && flext::CanbeInt(arg.GetList()[0])) + powi = flext::GetAInt(arg.GetList()[0]); + else + post("%s - power arg is invalid -> set to 1",p.opname); + + if(powi < 0) { + post("%s - negative integer power is not allowed",p.opname); + } + else { + switch(powi) { + case 0: { + p.cbin.rarg = 1,p.cbin.iarg = 0; + ret = DoOp(vecs,VecOp::d_cset,p); + break; + } + case 1: { + // set arg to src + ret = DoOp(vecs,VecOp::d_ccopy,p); + break; + } + case 2: { + ret = DoOp(vecs,VecOp::d_csqr,p); + break; + } + default: { + p.ibin.arg = powi; + ret = DoOp(vecs,VecOp::d_cpowi,p); + break; + } + } + } + + delete vecs; + } + return ret; +} + +VASP_ANYOP("vasp.cpowi",cpowi,0,true,VASP_ARG_I(1),"complex integer power") + +// ----------------------------------------------------- + +template<class T> inline V f_cabs(T &rv,T &iv,T ra,T ia) { rv = sqrt(ra*ra+ia*ia),iv = 0; } + +BL VecOp::d_cabs(OpParam &p) { D__cun(f_cabs<S>,p); } + +VASP_UNARY("vasp.cabs",cabs,true,"set real part to complex absolute value, imaginary part becomes zero") + diff --git a/externals/grill/vasp/source/ops_carith.h b/externals/grill/vasp/source/ops_carith.h new file mode 100644 index 00000000..7f841750 --- /dev/null +++ b/externals/grill/vasp/source/ops_carith.h @@ -0,0 +1,48 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPS_CARITH_H +#define __VASP_OPS_CARITH_H + +#include "opbase.h" + +// Arithmetic math functions + +namespace VecOp { + BL d_cadd(OpParam &p); + BL d_csub(OpParam &p); + BL d_csubr(OpParam &p); + BL d_cmul(OpParam &p); + BL d_cdiv(OpParam &p); + BL d_cdivr(OpParam &p); + + BL d_csqr(OpParam &p); + BL d_cpowi(OpParam &p); + + BL d_cabs(OpParam &p); +} + +namespace VaspOp { + inline Vasp *m_cadd(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_cbin(p,src,arg,dst,VecOp::d_cadd); } // complex add (pairs of vecs or complex) + inline Vasp *m_csub(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_cbin(p,src,arg,dst,VecOp::d_csub); } // complex sub (pairs of vecs or complex) + inline Vasp *m_csubr(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_cbin(p,src,arg,dst,VecOp::d_csubr); } // reverse complex sub (pairs of vecs or complex) + inline Vasp *m_cmul(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_cbin(p,src,arg,dst,VecOp::d_cmul); } // complex mul (pairs of vecs or complex) + inline Vasp *m_cdiv(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_cbin(p,src,arg,dst,VecOp::d_cdiv); } // complex div (pairs of vecs or complex) + inline Vasp *m_cdivr(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_cbin(p,src,arg,dst,VecOp::d_cdivr); } // complex reverse div (pairs of vecs or complex) + + inline Vasp *m_csqr(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_cun(p,src,dst,VecOp::d_csqr); } // complex square (with each two channels) +// inline Vasp *m_csqrt(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_cun(p,src,dst,VecOp::d_csqrt); } // complex square root (how about branches?) + + Vasp *m_cpowi(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL); // complex integer power (with each two channels) + + inline Vasp *m_cabs(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_cun(p,src,dst,VecOp::d_cabs); } // absolute values +} + +#endif diff --git a/externals/grill/vasp/source/ops_cmp.cpp b/externals/grill/vasp/source/ops_cmp.cpp new file mode 100644 index 00000000..2f632a54 --- /dev/null +++ b/externals/grill/vasp/source/ops_cmp.cpp @@ -0,0 +1,99 @@ +/* + +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_cmp.h" +#include "opdefs.h" +#include "util.h" +#include <math.h> + +// -------------------------------------------------------------- + +template<class T> inline V f_rlwr(T &v,T a,T b) { v = a < b?1:0; } +template<class T> inline V f_rgtr(T &v,T a,T b) { v = a > b?1:0; } +template<class T> inline V f_ralwr(T &v,T a,T b) { v = fabs(a) < fabs(b)?1:0; } +template<class T> inline V f_ragtr(T &v,T a,T b) { v = fabs(a) > fabs(b)?1:0; } +template<class T> inline V f_rleq(T &v,T a,T b) { v = a <= b?1:0; } +template<class T> inline V f_rgeq(T &v,T a,T b) { v = a >= b?1:0; } +template<class T> inline V f_raleq(T &v,T a,T b) { v = fabs(a) <= fabs(b)?1:0; } +template<class T> inline V f_rageq(T &v,T a,T b) { v = fabs(a) >= fabs(b)?1:0; } +template<class T> inline V f_requ(T &v,T a,T b) { v = a == b?1:0; } +template<class T> inline V f_rneq(T &v,T a,T b) { v = a != b?1:0; } + +BL VecOp::d_lwr(OpParam &p) { D__rbin(f_rlwr<S>,p); } +BL VecOp::d_gtr(OpParam &p) { D__rbin(f_rgtr<S>,p); } +BL VecOp::d_alwr(OpParam &p) { D__rbin(f_ralwr<S>,p); } +BL VecOp::d_agtr(OpParam &p) { D__rbin(f_ragtr<S>,p); } +BL VecOp::d_leq(OpParam &p) { D__rbin(f_rleq<S>,p); } +BL VecOp::d_geq(OpParam &p) { D__rbin(f_rgeq<S>,p); } +BL VecOp::d_aleq(OpParam &p) { D__rbin(f_raleq<S>,p); } +BL VecOp::d_ageq(OpParam &p) { D__rbin(f_rageq<S>,p); } +BL VecOp::d_equ(OpParam &p) { D__rbin(f_requ<S>,p); } +BL VecOp::d_neq(OpParam &p) { D__rbin(f_rneq<S>,p); } + +VASP_BINARY("vasp.<",lwr,true,VASP_ARG_R(0),"set destination to 1 if source < argument, 0 otherwise") +VASP_BINARY("vasp.>",gtr,true,VASP_ARG_R(0),"set destination to 1 if source > argument, 0 otherwise") +VASP_BINARY("vasp.a<",alwr,true,VASP_ARG_R(0),"set destination to 1 if abs(source) < abs(argument), 0 otherwise") +VASP_BINARY("vasp.a>",agtr,true,VASP_ARG_R(0),"set destination to 1 if abs(source) > abs(argument), 0 otherwise") +VASP_BINARY("vasp.<=",leq,true,VASP_ARG_R(0),"set destination to 1 if source <= argument, 0 otherwise") +VASP_BINARY("vasp.>=",geq,true,VASP_ARG_R(0),"set destination to 1 if source >= argument, 0 otherwise") +VASP_BINARY("vasp.a<=",aleq,true,VASP_ARG_R(0),"set destination to 1 if abs(source) <= abs(argument), 0 otherwise") +VASP_BINARY("vasp.a>=",ageq,true,VASP_ARG_R(0),"set destination to 1 if abs(source) >= abs(argument), 0 otherwise") +VASP_BINARY("vasp.==",equ,true,VASP_ARG_R(0),"set destination to 1 if source == argument, 0 otherwise") +VASP_BINARY("vasp.!=",neq,true,VASP_ARG_R(0),"set destination to 1 if source != argument, 0 otherwise") + + +// -------------------------------------------------------------- + +template<class T> inline V f_min(T &v,T a,T b) { v = a < b?a:b; } +template<class T> inline V f_max(T &v,T a,T b) { v = a > b?a:b; } + +template<class T> inline V f_rmin(T &rv,T &iv,T ra,T ia,T rb,T ib) +{ + if(sqabs(ra,ia) < sqabs(rb,ib)) rv = ra,iv = ia; + else rv = rb,iv = ib; +} + +template<class T> inline V f_rmax(T &rv,T &iv,T ra,T ia,T rb,T ib) +{ + if(sqabs(ra,ia) > sqabs(rb,ib)) rv = ra,iv = ia; + else rv = rb,iv = ib; +} + +BL VecOp::d_min(OpParam &p) { D__rbin(f_min<S>,p); } +BL VecOp::d_max(OpParam &p) { D__rbin(f_max<S>,p); } +BL VecOp::d_rmin(OpParam &p) { d__cbin(f_rmin<S>,p); } +BL VecOp::d_rmax(OpParam &p) { d__cbin(f_rmax<S>,p); } + + +VASP_BINARY("vasp.min",min,true,VASP_ARG_R(0),"assigns the minimum of the comparison with a value or vasp") +VASP_BINARY("vasp.max",max,true,VASP_ARG_R(0),"assigns the maximum of the comparison with a value or vasp") + +VASP_BINARY("vasp.rmin",rmin,true,VASP_ARG_R(0),"assigns the minimum of the radius comparison with a complex value or vasp") +VASP_BINARY("vasp.rmax",rmax,true,VASP_ARG_R(0),"assigns the maximum of the radius comparison with a complex value or vasp") + + +// -------------------------------------------------------------- + +template<class T> inline V f_minmax(T &rv,T &iv,T ra,T ia) +{ + if(ra < ia) rv = ra,iv = ia; + else rv = ia,iv = ra; +} + +BL VecOp::d_minmax(OpParam &p) { d__cun(f_minmax<S>,p); } + +VASP_UNARY("vasp, vasp.minmax",minmax,true,"compare two vectors, assign the lower values to the first and the higher to the second one") + + + + + + + diff --git a/externals/grill/vasp/source/ops_cmp.h b/externals/grill/vasp/source/ops_cmp.h new file mode 100644 index 00000000..87af3a19 --- /dev/null +++ b/externals/grill/vasp/source/ops_cmp.h @@ -0,0 +1,86 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPS_CMP_H +#define __VASP_OPS_CMP_H + +#include "opbase.h" + +// Comparison functions + +namespace VecOp { + BL d_lwr(OpParam &p); + BL d_gtr(OpParam &p); + BL d_alwr(OpParam &p); + BL d_agtr(OpParam &p); + BL d_leq(OpParam &p); + BL d_geq(OpParam &p); + BL d_aleq(OpParam &p); + BL d_ageq(OpParam &p); + BL d_equ(OpParam &p); + BL d_neq(OpParam &p); + + BL d_min(OpParam &p); + BL d_max(OpParam &p); + + BL d_rmin(OpParam &p); + BL d_rmax(OpParam &p); + + BL d_minmax(OpParam &p); + + BL d_minq(OpParam &p); + BL d_maxq(OpParam &p); + BL d_aminq(OpParam &p); + BL d_amaxq(OpParam &p); + + BL d_rminq(OpParam &p); + BL d_rmaxq(OpParam &p); + + BL d_gate(OpParam &p); + BL d_igate(OpParam &p); + BL d_rgate(OpParam &p); + BL d_rigate(OpParam &p); +} + +namespace VaspOp { + inline Vasp *m_lwr(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_lwr); } // lower than + inline Vasp *m_gtr(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_gtr); } // greater than + inline Vasp *m_alwr(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_alwr); } // abs lower than + inline Vasp *m_agtr(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_agtr); } // abs greater than + inline Vasp *m_leq(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_leq); } // abs lower than + inline Vasp *m_geq(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_geq); } // abs greater than + inline Vasp *m_aleq(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_aleq); } // lower than + inline Vasp *m_ageq(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_ageq); } // greater than + inline Vasp *m_equ(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_equ); } // lower than + inline Vasp *m_neq(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_neq); } // greater than + + inline Vasp *m_min(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_min); } // min (one vec or real) + inline Vasp *m_max(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_max); } // max (one vec or real) + + inline Vasp *m_rmin(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_cbin(p,src,arg,dst,VecOp::d_rmin); } // complex (radius) min (pairs of vecs or complex) + inline Vasp *m_rmax(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_cbin(p,src,arg,dst,VecOp::d_rmax); } // complex (radius) max (pairs of vecs or complex) + + inline Vasp *m_minmax(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_cun(p,src,dst,VecOp::d_minmax); } // min/max + + inline Vasp *m_qmin(OpParam &p,Vasp &src) { return m_run(p,src,NULL,VecOp::d_minq); } // get minimum sample value + inline Vasp *m_qmax(OpParam &p,Vasp &src) { return m_run(p,src,NULL,VecOp::d_maxq); } // get maximum sample value + inline Vasp *m_qamin(OpParam &p,Vasp &src) { return m_run(p,src,NULL,VecOp::d_aminq); } // get minimum sample value + inline Vasp *m_qamax(OpParam &p,Vasp &src) { return m_run(p,src,NULL,VecOp::d_amaxq); } // get maximum sample value + + inline Vasp *m_qrmin(OpParam &p,Vasp &src) { return m_cun(p,src,NULL,VecOp::d_rminq); } // get minimum sample value + inline Vasp *m_qrmax(OpParam &p,Vasp &src) { return m_cun(p,src,NULL,VecOp::d_rmaxq); } // get maximum sample value + + Vasp *m_gate(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL); // gate + Vasp *m_igate(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL); // inverse gate + Vasp *m_rgate(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL); // radius gate + Vasp *m_rigate(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL); // inverse radius gate +} + +#endif diff --git a/externals/grill/vasp/source/ops_cplx.cpp b/externals/grill/vasp/source/ops_cplx.cpp new file mode 100644 index 00000000..70f8c6e2 --- /dev/null +++ b/externals/grill/vasp/source/ops_cplx.cpp @@ -0,0 +1,85 @@ +/* + +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_cplx.h" +#include "opdefs.h" +#include "util.h" +#include <math.h> + +// ----------------------------------------------------- + +template<class T> V f_polar(T &rv,T &iv,T ra,T ia) { rv = sqrt(sqabs(ra,ia)),iv = arg(ra,ia); } +template<class T> V f_rect(T &rv,T &iv,T ra,T ia) { rv = ra*cos(ia),iv = ra*sin(ia); } + +BL VecOp::d_polar(OpParam &p) { d__cun(f_polar<S>,p); } +BL VecOp::d_rect(OpParam &p) { d__cun(f_rect<S>,p); } + + +VASP_UNARY("vasp.polar",polar,true,"convert complex vector pair from rectangular to polar coordinates") +VASP_UNARY("vasp.rect",rect,true,"convert complex vector pair from polar to rectangular coordinates") + + +// ----------------------------------------------------- + + +template<class T> V f_radd(T &rv,T &iv,T ra,T ia,T rb,T) +{ + register const R _abs = sqrt(sqabs(ra,ia))+rb; + register const R _phi = arg(ra,ia); + + rv = _abs*cos(_phi),iv = _abs*sin(_phi); +} + +BL VecOp::d_radd(OpParam &p) { d__cbin(f_radd<S>,p); } + +Vasp *VaspOp::m_radd(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst) +{ + Vasp *ret = NULL; + CVecBlock *vecs = GetCVecs(p.opname,src,dst); + if(vecs) { + if(arg.IsList() && arg.GetList().Count() >= 1 && flext::CanbeFloat(arg.GetList()[0])) + p.cbin.rarg = flext::GetAFloat(arg.GetList()[0]); + else { + post("%s - argument is invalid -> set to 0",p.opname); + p.cbin.rarg = 0; + } + p.cbin.iarg = 0; // not used anyway + + ret = DoOp(vecs,VecOp::d_radd,p); + delete vecs; + } + return ret; +} + + +VASP_ANYOP("vasp.r+",radd,0,true,VASP_ARG_R(0),"add offset to complex radius (of complex vector pair)") + + +// ----------------------------------------------------- + +template<class T> V f_cnorm(T &rv,T &iv,T ra,T ia) +{ + register T f = sqabs(ra,ia); + if(f) { f = 1./sqrt(f); rv = ra*f,iv = ia*f; } + else rv = iv = 0; +} + +BL VecOp::d_cnorm(OpParam &p) { d__cun(f_cnorm<S>,p); } + +VASP_UNARY("vasp.cnorm",cnorm,true,"normalize complex radius to 1 (but preserve angle)") + +// ----------------------------------------------------- + +template<class T> inline V f_cconj(T &,T &iv,T,T ia) { iv = -ia; } + +BL VecOp::d_cconj(OpParam &p) { D__cun(f_cconj<S>,p); } + +VASP_UNARY("vasp.cconj",cconj,true,"complex conjugate: multiply imaginary part with -1") // should be replaced by an abstraction + diff --git a/externals/grill/vasp/source/ops_cplx.h b/externals/grill/vasp/source/ops_cplx.h new file mode 100644 index 00000000..de1426f2 --- /dev/null +++ b/externals/grill/vasp/source/ops_cplx.h @@ -0,0 +1,42 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPS_CPLX_H +#define __VASP_OPS_CPLX_H + +#include "opbase.h" + +// Complex functions + +namespace VecOp { + BL d_polar(OpParam &p); + BL d_rect(OpParam &p); + + BL d_radd(OpParam &p); + + BL d_cnorm(OpParam &p); + +// BL d_cswap(OpParam &p); + BL d_cconj(OpParam &p); +} + +namespace VaspOp { + inline Vasp *m_polar(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_cun(p,src,dst,VecOp::d_polar); } // cartesian -> polar (each two) + inline Vasp *m_rect(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_cun(p,src,dst,VecOp::d_rect); } // polar -> cartesian (each two) + + Vasp *m_radd(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL); // radius offset + + inline Vasp *m_cnorm(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_cun(p,src,dst,VecOp::d_cnorm); } // complex normalize + +// inline Vasp *m_cswap(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_cun(p,src,dst,VecOp::d_cswap); } // swap real and imaginary parts + inline Vasp *m_cconj(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_cun(p,src,dst,VecOp::d_cconj); } // complex conjugate +} + +#endif diff --git a/externals/grill/vasp/source/ops_dft.cpp b/externals/grill/vasp/source/ops_dft.cpp new file mode 100644 index 00000000..a83d80fc --- /dev/null +++ b/externals/grill/vasp/source/ops_dft.cpp @@ -0,0 +1,651 @@ +/* + +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. + +*/ + +/*! \file ops_dft.cpp + \brief Implementation of DFT routines + + \todo align temporary memory allocations + + All DFTs are normalized by 1/sqrt(n), hence the complex ones are repeatable + + - complex FFT radix-2: in-place + - real FFT radix-2 (split-radix): in-place + - complex DFT radix-n (split-radix): out-of-place + - real DFT radix-n: out-of-place / based on complex DFT radix-n (inefficient) + + In-place transformation is only possible for stride=1 +*/ + +#include "ops_dft.h" +#include <math.h> +#include <string.h> + +/////////////////////////////////////////////////////////////// + +BL mixfft(I n,F *xRe,F *xIm,F *yRe,F *yIm); + +#ifdef FLEXT_THREADS +static flext::ThrMutex mixmtx; +#endif + +//! Real forward DFT radix-n (managing routine) +static BL fft_fwd_real_any(I cnt,F *rsdt,I _rss,F *rddt,I _rds) +{ + if(!rddt) rddt = rsdt,_rds = _rss; + +#ifdef VASP_CHN1 + const I rds = 1,rss = 1; +#else + const I rds = _rds,rss = _rss; +#endif + + const BL rst = rss != 1; + const BL rdt = rsdt == rddt || rds != 1; + + F *rstmp,*istmp; + register I i; + + if(rst) { + rstmp = new F[cnt]; + // happens only if rss != 1, no optimization necessary + for(i = 0; i < cnt; ++i) rstmp[i] = rsdt[i*rss]; + } + else + rstmp = rsdt; + + istmp = new F[cnt]; + memset(istmp,0,cnt*sizeof(*istmp)); + + F *rdtmp = rdt?new F[cnt]:rddt; + F *idtmp = new F[cnt]; + + BL ret; + { + // mixfft is not thread-safe +#ifdef FLEXT_THREADS + mixmtx.Lock(); +#endif + ret = mixfft(cnt,rstmp,istmp,rdtmp,idtmp); +#ifdef FLEXT_THREADS + mixmtx.Unlock(); +#endif + } + if(ret) { + const F nrm = 1./sqrt(cnt); + const I n2 = cnt/2; + +#ifndef VASP_COMPACT + if(rds == 1) { + for(i = 0; i <= n2; ++i) rddt[i] = rdtmp[i]*nrm; + for(i = 1; i < cnt-n2; ++i) rddt[i+n2] = idtmp[i]*nrm; + } + else +#endif + { + for(i = 0; i <= n2; ++i) rddt[i*rds] = rdtmp[i]*nrm; + for(i = 1; i < cnt-n2; ++i) rddt[(i+n2)*rds] = idtmp[i]*nrm; + } + } + + if(rst) delete[] rstmp; + delete[] istmp; + if(rdt) delete[] rdtmp; + delete[] idtmp; + + return ret; +} + + +//! Real inverse DFT radix-n (managing routine) +static BL fft_inv_real_any(I cnt,F *rsdt,I _rss,F *rddt,I _rds) +{ + if(!rddt) rddt = rsdt,_rds = _rss; + +#ifdef VASP_CHN1 + const I rds = 1,rss = 1; +#else + const I rds = _rds,rss = _rss; +#endif + + const BL rst = rss != 1; + const BL rdt = rsdt == rddt || rds != 1; + + const I n2 = cnt/2; + F *rstmp,*istmp; + istmp = new F[cnt]; + register I i; + + if(rst) { + rstmp = new F[cnt]; + // happens only if rss != 1, no optimization necessary + for(i = 0; i <= n2; ++i) rstmp[i] = rsdt[i*rss]; + for(i = 1; i < cnt-n2; ++i) istmp[cnt-i] = rsdt[(n2+i)*rss]; + } + else { + rstmp = rsdt; + for(i = 1; i < cnt-n2; ++i) istmp[cnt-i] = rsdt[n2+i]; + } + + // make symmetric parts + for(i = 1; i < cnt-n2; ++i) { + istmp[i] = -istmp[cnt-i]; + rstmp[cnt-i] = rstmp[i]; + } + istmp[0] = 0; + if(cnt%2 == 0) istmp[n2] = 0; + + + F *rdtmp = rdt?new F[cnt]:rddt; + F *idtmp = new F[cnt]; + + BL ret; + { +#ifdef FLEXT_THREADS + mixmtx.Lock(); +#endif + // mixfft is not thread-safe + ret = mixfft(cnt,rstmp,istmp,rdtmp,idtmp); +#ifdef FLEXT_THREADS + mixmtx.Unlock(); +#endif + } + if(ret) { + const F nrm = 1./sqrt(cnt); +#ifndef VASP_COMPACT + if(rds == 1) + for(i = 0; i < cnt; ++i) + rddt[i] = rdtmp[i]*nrm; + else +#endif + for(i = 0; i < cnt; ++i) + rddt[i*rds] = rdtmp[i]*nrm; + } + + if(rst) delete[] rstmp; + delete[] istmp; + if(rdt) delete[] rdtmp; + delete[] idtmp; + + return ret; +} + +/////////////////////////////////////////////////////////////// + +//! Complex forward DFT radix-n (managing routine) +static BL fft_fwd_complex_any(I cnt,F *rsdt,I _rss,F *isdt,I _iss,F *rddt,I _rds,F *iddt,I _ids) +{ + if(!rddt) rddt = rsdt,_rds = _rss; + if(!iddt) iddt = isdt,_ids = _iss; + +#ifdef VASP_CHN1 + const I rds = 1,ids = 1,rss = 1,iss = 1; +#else + const I rds = _rds,ids = _ids,rss = _rss,iss = _iss; +#endif + + const BL rst = rss != 1; + const BL ist = iss != 1; + const BL rdt = rsdt == rddt || rds != 1; + const BL idt = isdt == iddt || ids != 1; + + F *rstmp,*istmp; + register I i; + + if(rst) { + rstmp = new F[cnt]; + // happens only if rss != 1, no optimization necessary + for(i = 0; i < cnt; ++i) rstmp[i] = rsdt[i*rss]; + } + else + rstmp = rsdt; + + if(ist) { + istmp = new F[cnt]; + // happens only if iss != 1, no optimization necessary + for(i = 0; i < cnt; ++i) istmp[i] = isdt[i*iss]; + } + else + istmp = isdt; + + F *rdtmp = rdt?new F[cnt]:rddt; + F *idtmp = idt?new F[cnt]:iddt; + + BL ret; + { +#ifdef FLEXT_THREADS + mixmtx.Lock(); +#endif + // mixfft is not thread-safe + ret = mixfft(cnt,rstmp,istmp,rdtmp,idtmp); +#ifdef FLEXT_THREADS + mixmtx.Unlock(); +#endif + } + if(ret) { + const F nrm = 1./sqrt(cnt); + +#ifdef VASP_COMPACT + for(i = 0; i < cnt; ++i) { + rddt[i*rds] = rdtmp[i]*nrm; + iddt[i*ids] = idtmp[i]*nrm; + } +#else + if(rdt) { + if(rds != 1) + for(i = 0; i < cnt; ++i) rddt[i*rds] = rdtmp[i]*nrm; + else + for(i = 0; i < cnt; ++i) rddt[i] = rdtmp[i]*nrm; + } + else // ok, this branch is not absolutely necessary + if(rds != 1) + for(i = 0; i < cnt; ++i) rddt[i*rds] *= nrm; + else + for(i = 0; i < cnt; ++i) rddt[i] *= nrm; + + if(idt) { + if(ids != 1) + for(i = 0; i < cnt; ++i) iddt[i*ids] = idtmp[i]*nrm; + else + for(i = 0; i < cnt; ++i) iddt[i] = idtmp[i]*nrm; + } + else // ok, this branch is not absolutely necessary + if(ids != 1) + for(i = 0; i < cnt; ++i) iddt[i*ids] *= nrm; + else + for(i = 0; i < cnt; ++i) iddt[i] *= nrm; +#endif + } + + if(rst) delete[] rstmp; + if(ist) delete[] istmp; + if(rdt) delete[] rdtmp; + if(idt) delete[] idtmp; + + return ret; +} + +//! Complex inverse DFT radix-n (managing routine) +static BL fft_inv_complex_any(I cnt,F *rsdt,I _rss,F *isdt,I _iss,F *rddt,I _rds,F *iddt,I _ids) +{ + I i; + + if(!rddt) rddt = rsdt,_rds = _rss; + if(!iddt) iddt = isdt,_ids = _iss; + +#ifdef VASP_CHN1 + const I rds = 1,ids = 1,rss = 1,iss = 1; +#else + const I rds = _rds,ids = _ids,rss = _rss,iss = _iss; +#endif + +#ifndef VASP_COMPACT + if(iss == 1) + for(i = 0; i < cnt; ++i) isdt[i] = -isdt[i]; + else +#endif + for(i = 0; i < cnt; ++i) isdt[i*iss] *= -1; + + BL ret = fft_fwd_complex_any(cnt,rsdt,rss,isdt,iss,rddt,rds,iddt,ids); + + if(ret) { +#ifndef VASP_COMPACT + if(ids == 1) + for(i = 0; i < cnt; ++i) iddt[i] = -iddt[i]; + else +#endif + for(i = 0; i < cnt; ++i) iddt[i*ids] *= -1; + } + + // reverse minus on input + if(isdt != iddt) { +#ifndef VASP_COMPACT + if(iss == 1) + for(i = 0; i < cnt; ++i) isdt[i] = -isdt[i]; + else +#endif + for(i = 0; i < cnt; ++i) isdt[i*iss] *= -1; + } + return ret; +} + +/////////////////////////////////////////////////////////////// + +bool fft_bidir_complex_radix2(int size,float *real,float *imag,int dir); + +//! Complex forward FFT radix-2 (managing routine) +static BL fft_complex_radix2(I cnt,F *rsdt,I _rss,F *isdt,I _iss,F *rddt,I _rds,F *iddt,I _ids,I dir) +{ + if(!rddt) rddt = rsdt,_rds = _rss; + if(!iddt) iddt = isdt,_ids = _iss; + +#ifdef VASP_CHN1 + const I rds = 1,ids = 1,rss = 1,iss = 1; +#else + const I rds = _rds,ids = _ids,rss = _rss,iss = _iss; +#endif + + BL rt = false,it = false; + F *rtmp,*itmp; + register I i; + + if(rss == 1) + rtmp = rsdt; + else { + if(rsdt == rddt || rds != 1) + rtmp = new F[cnt],rt = true; + else + rtmp = rddt; + for(i = 0; i < cnt; ++i) rtmp[i] = rsdt[i*rss]; + } + + if(iss == 1) + itmp = isdt; + else { + if(isdt == iddt || ids != 1) + itmp = new F[cnt],it = true; + else + itmp = iddt; + for(i = 0; i < cnt; ++i) itmp[i] = isdt[i*iss]; + } + + BL ret = fft_bidir_complex_radix2(cnt,rtmp,itmp,dir); + + if(ret) { + const F nrm = 1./sqrt(cnt); + +#ifndef VASP_COMPACT + if(rtmp == rddt) + for(i = 0; i < cnt; ++i) rddt[i] *= nrm; + else if(rds == 1) + for(i = 0; i < cnt; ++i) rddt[i] = rtmp[i]*nrm; + else +#endif + for(i = 0; i < cnt; ++i) rddt[i*rds] = rtmp[i]*nrm; + +#ifndef VASP_COMPACT + if(itmp == iddt) + for(i = 0; i < cnt; ++i) iddt[i] *= nrm; + else if(ids == 1) + for(i = 0; i < cnt; ++i) iddt[i] = itmp[i]*nrm; + else +#endif + for(i = 0; i < cnt; ++i) iddt[i*ids] = itmp[i]*nrm; + } + + if(rt) delete[] rtmp; + if(it) delete[] itmp; + + return ret; +} + +inline BL fft_fwd_complex_radix2(I cnt,F *rsdt,I _rss,F *isdt,I _iss,F *rddt,I _rds,F *iddt,I _ids) +{ + return fft_complex_radix2(cnt,rsdt,_rss,isdt,_iss,rddt,_rds,iddt,_ids,1); +} + +inline BL fft_inv_complex_radix2(I cnt,F *rsdt,I _rss,F *isdt,I _iss,F *rddt,I _rds,F *iddt,I _ids) +{ + return fft_complex_radix2(cnt,rsdt,_rss,isdt,_iss,rddt,_rds,iddt,_ids,-1); +} + +/////////////////////////////////////////////////////////////// + +void realfft_split(float *data,int n); +void irealfft_split(float *data,int n); + +// normalize and reverse imaginary part in-place +static void nrmirev(float *data,int n,float fn) +{ + int i; + const I n2 = n/2,n4 = n2/2; + for(i = 0; i <= n2; ++i) data[i] *= fn; + for(i = 1; i < n4; ++i) { + register F tmp = data[n2+i]; + data[n2+i] = data[n-i]*fn; + data[n-i] = tmp*fn; + } + if(n2%2 == 0) data[n2+n4] *= fn; +} + +//! Real forward FFT radix-2 (managing routine) +BL fft_fwd_real_radix2(I cnt,F *src,I _sstr,F *dst,I _dstr) +{ +#ifdef VASP_CHN1 + const I dstr = 1,sstr = 1; +#else + const I dstr = _dstr,sstr = _sstr; +#endif + + register I i; + const I n2 = cnt/2; + const F fn = (F)(1./sqrt(cnt)); + F *stmp; + if(!dst || src == dst) { + // in-place + + if(sstr == 1) + stmp = src; + else { + stmp = new F[cnt]; + for(i = 0; i < cnt; ++i) stmp[i] = src[i*sstr]; + } + + realfft_split(stmp,cnt); + + if(sstr == 1) { + // src == stmp !!! + nrmirev(stmp,cnt,fn); + } + else { + for(i = 0; i <= n2; ++i) src[i*sstr] = stmp[i]*fn; + for(i = 1; i < n2; ++i) src[(n2+i)*sstr] = stmp[cnt-i]*fn; + delete[] stmp; + } + } + else { + // out of place + + if(sstr == 1) + stmp = src; + else { + stmp = dstr == 1?dst:new F[cnt]; + for(i = 0; i < cnt; ++i) stmp[i] = src[i*sstr]; + } + + realfft_split(stmp,cnt); + + if(sstr == 1) { +#ifdef VASP_COMPACT + if(dstr == 1) { + for(i = 0; i <= n2; ++i) dst[i] = stmp[i]*fn; + for(i = 1; i < n2; ++i) dst[n2+i] = stmp[cnt-i]*fn; + } + else +#endif + { + for(i = 0; i <= n2; ++i) dst[i*dstr] = stmp[i]*fn; + for(i = 1; i < n2; ++i) dst[(n2+i)*dstr] = stmp[cnt-i]*fn; + } + } + else { + if(dstr == 1) { + // dst == stmp !!! + nrmirev(stmp,cnt,fn); + } + else { + for(i = 0; i <= n2; ++i) dst[i*dstr] = stmp[i]*fn; + for(i = 1; i < n2; ++i) dst[(n2+i)*dstr] = stmp[cnt-i]*fn; + delete[] dst; + } + } + } + + return true; +} + +//! Real inverse FFT radix-2 (managing routine) +BL fft_inv_real_radix2(I cnt,F *src,I _sstr,F *dst,I _dstr) +{ +#ifdef VASP_CHN1 + const I dstr = 1,sstr = 1; +#else + const I dstr = _dstr,sstr = _sstr; +#endif + + register I i; + const I n2 = cnt/2; + const F fn = (F)(1./sqrt(cnt)); + F *stmp; + if(!dst || src == dst) { + // in-place + + if(sstr == 1) { + stmp = src; + nrmirev(stmp,cnt,fn); + } + else { + stmp = new F[cnt]; + +#ifdef VASP_COMPACT + if(sstr == 1) { + for(i = 0; i <= n2; ++i) stmp[i] = src[i]*fn; + for(i = 1; i < n2; ++i) stmp[cnt-i] = src[n2+i]*fn; + } + else +#endif + { + for(i = 0; i <= n2; ++i) stmp[i] = src[i*sstr]*fn; + for(i = 1; i < n2; ++i) stmp[cnt-i] = src[(n2+i)*sstr]*fn; + } + } + + irealfft_split(stmp,cnt); + + if(sstr != 1) { + for(i = 0; i < cnt; ++i) src[i*sstr] = stmp[i]; + delete[] stmp; + } + } + else { + // out of place + + if(dstr == 1) { + stmp = dst; +#ifdef VASP_COMPACT + if(sstr == 1) { + for(i = 0; i <= n2; ++i) stmp[i] = src[i]*fn; + for(i = 1; i < n2; ++i) stmp[cnt-i] = src[n2+i]*fn; + } + else +#endif + { + for(i = 0; i <= n2; ++i) stmp[i] = src[i*sstr]*fn; + for(i = 1; i < n2; ++i) stmp[cnt-i] = src[(n2+i)*sstr]*fn; + } + } + else { + stmp = new F[cnt]; + if(sstr == 1) { + // dst == stmp !!! + nrmirev(stmp,cnt,fn); + } + else { + for(i = 0; i <= n2; ++i) stmp[i] = src[i*sstr]*fn; + for(i = 1; i < n2; ++i) stmp[cnt-i] = src[(n2+i)*sstr]*fn; + } + } + + irealfft_split(stmp,cnt); + + if(dstr != 1) { + for(i = 0; i < cnt; ++i) dst[i*dstr] = stmp[i]; + delete[] stmp; + } + } + + return true; +} + +/////////////////////////////////////////////////////////////// + +//! Determine if size is radix-2 +static I radix2(I size) +{ + I i,j; + for(i = j = 1; j < size; i++,j <<= 1) (void)0; + return j == size?i:-1; +} + +Vasp *VaspOp::m_rfft(OpParam &p,Vasp &src,Vasp *dst,BL inv) +{ + RVecBlock *vecs = GetRVecs(p.opname,src,dst); + if(vecs) { + BL ok = true; + for(I i = 0; ok && i < vecs->Vecs(); ++i) { + VBuffer *s = vecs->Src(i); + VBuffer *d = vecs->Dst(i); + if(!d) d = s; + + if(vecs->Frames() > 1) + if(radix2(vecs->Frames()) >= 1) + // radix-2 + if(inv) + ok = fft_inv_real_radix2(vecs->Frames(),s->Pointer(),s->Channels(),d->Pointer(),d->Channels()); + else + ok = fft_fwd_real_radix2(vecs->Frames(),s->Pointer(),s->Channels(),d->Pointer(),d->Channels()); + else + // radix-n + if(inv) + ok = fft_inv_real_any(vecs->Frames(),s->Pointer(),s->Channels(),d->Pointer(),d->Channels()); + else + ok = fft_fwd_real_any(vecs->Frames(),s->Pointer(),s->Channels(),d->Pointer(),d->Channels()); + } + return ok?vecs->ResVasp():NULL; + } + else + return NULL; +} + +Vasp *VaspOp::m_cfft(OpParam &p,Vasp &src,Vasp *dst,BL inv) +{ + CVecBlock *vecs = GetCVecs(p.opname,src,dst,true); + if(vecs) { + BL ok = true; + for(I i = 0; ok && i < vecs->Pairs(); ++i) { + VBuffer *sre = vecs->ReSrc(i),*sim = vecs->ImSrc(i); + VBuffer *dre = vecs->ReDst(i),*dim = vecs->ImDst(i); + if(!dre) dre = sre; + if(!dim) dim = sim; + + if(vecs->Frames() > 1) + if(radix2(vecs->Frames()) >= 1) + // radix-2 + if(inv) + ok = fft_inv_complex_radix2(vecs->Frames(),sre->Pointer(),sre->Channels(),sim?sim->Pointer():NULL,sim?sim->Channels():0,dre->Pointer(),dre->Channels(),dim->Pointer(),dim->Channels()); + else + ok = fft_fwd_complex_radix2(vecs->Frames(),sre->Pointer(),sre->Channels(),sim?sim->Pointer():NULL,sim?sim->Channels():0,dre->Pointer(),dre->Channels(),dim->Pointer(),dim->Channels()); + else + // radix-n + if(inv) + ok = fft_inv_complex_any(vecs->Frames(),sre->Pointer(),sre->Channels(),sim?sim->Pointer():NULL,sim?sim->Channels():0,dre->Pointer(),dre->Channels(),dim->Pointer(),dim->Channels()); + else + ok = fft_fwd_complex_any(vecs->Frames(),sre->Pointer(),sre->Channels(),sim?sim->Pointer():NULL,sim?sim->Channels():0,dre->Pointer(),dre->Channels(),dim->Pointer(),dim->Channels()); + } + return ok?vecs->ResVasp():NULL; + } + else + return NULL; +} + +VASP_UNARY("vasp.rfft",rfft,true,"Real DFT") +VASP_UNARY("vasp.r!fft",rifft,true,"Real inverse DFT") +VASP_UNARY("vasp.cfft",cfft,true,"Complex DFT") +VASP_UNARY("vasp.c!fft",cifft,true,"Complex inverse DFT") + diff --git a/externals/grill/vasp/source/ops_dft.h b/externals/grill/vasp/source/ops_dft.h new file mode 100644 index 00000000..f2f3fe40 --- /dev/null +++ b/externals/grill/vasp/source/ops_dft.h @@ -0,0 +1,25 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPS_DFT_H +#define __VASP_OPS_DFT_H + +#include "opbase.h" + +// Fourier transforms + +namespace VaspOp { + Vasp *m_rfft(OpParam &p,Vasp &src,Vasp *dst = NULL,BL inv = false); // real forward + inline Vasp *m_rifft(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_rfft(p,src,dst,true); } // real inverse + Vasp *m_cfft(OpParam &p,Vasp &src,Vasp *dst = NULL,BL inv = false); // complex forward + inline Vasp *m_cifft(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_cfft(p,src,dst,true); } // complex inverse +} + +#endif diff --git a/externals/grill/vasp/source/ops_feature.cpp b/externals/grill/vasp/source/ops_feature.cpp new file mode 100644 index 00000000..cb0f57c5 --- /dev/null +++ b/externals/grill/vasp/source/ops_feature.cpp @@ -0,0 +1,199 @@ +/* + +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_feature.h" +#include "oploop.h" +#include "util.h" +#include <math.h> + +// --- find peaks + +BL higher(S a,S b) { return a > b; } +BL lower(S a,S b) { return a < b; } + +/*! \brief Find peaks or valleys (depending on cmp function) + \param rep repetition count + + \remark real peak search is mangled into complex domain + + \todo how to treat <=, >= + \todo separate real and complex functionality +*/ + +static BL d_vlpk(OpParam &p,BL cmpf(S a,S b)) +{ + I dpeaks = (I)(p.frames*p.peaks.density); + if(dpeaks < 1) dpeaks = 1; + + I cnt; + do { + cnt = 0; + + I i; + S *rdst = p.rddt,*rsrc = p.rsdt; + S *idst = p.iddt,*isrc = p.isdt; + + if(!p.peaks.cx || !idst) idst = rdst,p.ids = p.rds; + if(!p.peaks.cx || !isrc) isrc = rsrc,p.iss = p.rss; + + // preset sample values + S d1 = -1,d0 = -1,dn = -1; + + // search first non-null sample + _D_LOOP(i,p.frames) + if((dn = sqabs(rsrc[i*p.rss],isrc[i*p.iss])) != 0) + break; // non-null -> break! + else + rdst[i*p.rds] = idst[i*p.ids] = 0; // copy null samples to dst + _E_LOOP + + // i points to first non-null sample + + _D_WHILE(i < p.frames) + // current samples -> previous samples + d1 = d0,d0 = dn; + + // save current index + I ci = i; + + // search next non-null sample + dn = -1; + while(++i < p.frames) + if((dn = sqabs(rsrc[i*p.rss],isrc[i*p.iss])) != 0) { + break; // non-null -> break! + } + else + rdst[i*p.rds] = idst[i*p.ids] = 0; + + if((d1 < 0 || cmpf(d0,d1)) && (dn < 0 || cmpf(d0,dn))) { + // is peak/valley + rdst[ci*p.rds] = rsrc[ci*p.rss]; + idst[ci*p.ids] = isrc[ci*p.iss]; + ++cnt; + } + else + rdst[ci*p.rds] = idst[ci*p.ids] = 0; + _E_WHILE + } while(cnt > dpeaks); + + p.peaks.density = p.frames?(R)cnt/p.frames:(cnt?1:0); + return true; +} + +inline BL d_peaks(OpParam &p) { return d_vlpk(p,higher); } +inline BL d_valleys(OpParam &p) { return d_vlpk(p,lower); } +inline BL d_rpeaks(OpParam &p) { return d_vlpk(p,higher); } +inline BL d_rvalleys(OpParam &p) { return d_vlpk(p,lower); } + +/*! \brief Finds peaks or valleys in a vasp. + + \param arg argument list + \param arg.rep repetition count + \param dst destination vasp (NULL for in-place operation) + \param inv true for valley operation + \return normalized destination vasp +*/ +Vasp *VaspOp::m_peaks(OpParam &p,Vasp &src,Vasp *dst,BL inv) +{ + Vasp *ret = NULL; + RVecBlock *vecs = GetRVecs(p.opname,src,dst); + if(vecs) { + p.peaks.cx = false; + ret = DoOp(vecs,inv?d_valleys:d_peaks,p); + delete vecs; + } + return ret; +} + + + +/*! \brief Finds peaks or valleys by radius in a complex vasp. + + \param arg argument list + \param arg.rep repetition count + \param dst destination vasp (NULL for in-place operation) + \param inv true for valley operation + \return normalized destination vasp +*/ +Vasp *VaspOp::m_rpeaks(OpParam &p,Vasp &src,Vasp *dst,BL inv) +{ + Vasp *ret = NULL; + CVecBlock *vecs = GetCVecs(p.opname,src,dst); + if(vecs) { + p.peaks.cx = true; + ret = DoOp(vecs,inv?d_rvalleys:d_rpeaks,p); + delete vecs; + } + return ret; +} + + +class vasp_peaks: + public vasp_anyop +{ + FLEXT_HEADER(vasp_peaks,vasp_anyop) +public: + + vasp_peaks(I argc,t_atom *argv): vasp_anyop(argc,argv,VASP_ARG(),true,XletCode(xlet::tp_float,0)) {} + + virtual Vasp *do_peaks(OpParam &p) { return VaspOp::m_peaks(p,ref,&dst); } + + virtual Vasp *tx_work(const Argument &arg) + { + OpParam p(thisName(),0); + + if(arg.IsList() && arg.GetList().Count() >= 1 && CanbeFloat(arg.GetList()[0])) { + p.peaks.density = GetAFloat(arg.GetList()[0]); + } + else { + if(!arg.IsNone()) post("%s - invalid density argument -> set to 1",p.opname); + p.peaks.density = 1; + } + + Vasp *ret = do_peaks(p); + ToOutFloat(1,p.peaks.density); + return ret; + } +}; +FLEXT_LIB_V("vasp, vasp.peaks",vasp_peaks) + + +class vasp_valleys: + public vasp_peaks +{ + FLEXT_HEADER(vasp_valleys,vasp_peaks) +public: + vasp_valleys(I argc,t_atom *argv): vasp_peaks(argc,argv) {} + virtual Vasp *do_peaks(OpParam &p) { return VaspOp::m_valleys(p,ref,&dst); } +}; +FLEXT_LIB_V("vasp, vasp.valleys",vasp_valleys) + + +class vasp_rpeaks: + public vasp_peaks +{ + FLEXT_HEADER(vasp_rpeaks,vasp_peaks) +public: + vasp_rpeaks(I argc,t_atom *argv): vasp_peaks(argc,argv) {} + virtual Vasp *do_peaks(OpParam &p) { return VaspOp::m_rpeaks(p,ref,&dst); } +}; +FLEXT_LIB_V("vasp, vasp.rpeaks",vasp_rpeaks) + + +class vasp_rvalleys: + public vasp_peaks +{ + FLEXT_HEADER(vasp_rvalleys,vasp_peaks) +public: + vasp_rvalleys(I argc,t_atom *argv): vasp_peaks(argc,argv) {} + virtual Vasp *do_peaks(OpParam &p) { return VaspOp::m_rvalleys(p,ref,&dst); } +}; +FLEXT_LIB_V("vasp, vasp.rvalleys",vasp_rvalleys) + diff --git a/externals/grill/vasp/source/ops_feature.h b/externals/grill/vasp/source/ops_feature.h new file mode 100644 index 00000000..05efc8b5 --- /dev/null +++ b/externals/grill/vasp/source/ops_feature.h @@ -0,0 +1,29 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPS_FEATURE_H +#define __VASP_OPS_FEATURE_H + +#include "opbase.h" + +// Feature extraction functions + +namespace VecOp { +} + +namespace VaspOp { + // extrema functions + Vasp *m_peaks(OpParam &p,Vasp &src,Vasp *dst = NULL,BL inv = false); //! find peaks + inline Vasp *m_valleys(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_peaks(p,src,dst,true); } //! find valleys + Vasp *m_rpeaks(OpParam &p,Vasp &src,Vasp *dst = NULL,BL inv = false); //! find radius peaks + inline Vasp *m_rvalleys(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_rpeaks(p,src,dst,true); } //! find radius valleys +} + +#endif 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") diff --git a/externals/grill/vasp/source/ops_flt.h b/externals/grill/vasp/source/ops_flt.h new file mode 100644 index 00000000..0ab37111 --- /dev/null +++ b/externals/grill/vasp/source/ops_flt.h @@ -0,0 +1,41 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPS_FLT_H +#define __VASP_OPS_FLT_H + +#include "opbase.h" + +// Filtering functions + +namespace VecOp { + BL d_flp(OpParam &p); + BL d_fhp(OpParam &p); + + BL d_int(OpParam &p); + BL d_dif(OpParam &p); + + BL d_fix(OpParam &p); +} + +namespace VaspOp { + // passive filters + Vasp *m_fhp(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL,BL hp = true); //! hi pass + inline Vasp *m_flp(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_fhp(p,src,arg,dst,false); } //! lo pass + + // int/dif functions + Vasp *m_int(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL,BL inv = false); //! integrate + inline Vasp *m_dif(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_int(p,src,arg,dst,true); } //! differentiate + + // fix denormals/NANs + inline Vasp *m_fix(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_run(p,src,dst,VecOp::d_fix); } // ! NAN/denormal filter +} + +#endif diff --git a/externals/grill/vasp/source/ops_gate.cpp b/externals/grill/vasp/source/ops_gate.cpp new file mode 100644 index 00000000..f8f9b3e3 --- /dev/null +++ b/externals/grill/vasp/source/ops_gate.cpp @@ -0,0 +1,88 @@ +/* + +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_cmp.h" +#include "opdefs.h" +#include "util.h" +#include <math.h> + +// -------------------------------------------------------------- + + +template<class T> V f_gate(T &rv,T ra,T rb) { rv = fabs(ra) >= rb?ra:0; } +template<class T> V f_igate(T &rv,T ra,T rb) { rv = fabs(ra) <= rb?ra:0; } + +template<class T> V f_rgate(T &rv,T &iv,T ra,T ia,T rb,T) +{ + register const T _abs = sqabs(ra,ia); + + if(_abs >= rb*rb) rv = ra,iv = ia; + else rv = iv = 0; +} + +template<class T> V f_rigate(T &rv,T &iv,T ra,T ia,T rb,T) +{ + register const T _abs = sqabs(ra,ia); + + if(_abs <= rb*rb) rv = ra,iv = ia; + else rv = iv = 0; +} + +BL VecOp::d_gate(OpParam &p) { D__rbin(f_gate<S>,p); } +BL VecOp::d_igate(OpParam &p) { d__rbin(f_igate<S>,p); } +BL VecOp::d_rgate(OpParam &p) { d__cbin(f_rgate<S>,p); } +BL VecOp::d_rigate(OpParam &p) { d__cbin(f_rigate<S>,p); } + + + +Vasp *VaspOp::m_gate(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst) +{ + Vasp *ret = NULL; + RVecBlock *vecs = GetRVecs(p.opname,src,dst); + if(vecs) { + if(arg.IsList() && arg.GetList().Count() >= 1 && flext::CanbeFloat(arg.GetList()[0])) + p.rbin.arg = flext::GetAFloat(arg.GetList()[0]); + else { + post("%s - argument is invalid -> set to 1",p.opname); + p.rbin.arg = 1; + } + + ret = DoOp(vecs,VecOp::d_gate,p); + delete vecs; + } + return ret; +} + + +Vasp *VaspOp::m_rgate(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst) +{ + Vasp *ret = NULL; + CVecBlock *vecs = GetCVecs(p.opname,src,dst); + if(vecs) { + if(arg.IsList() && arg.GetList().Count() >= 1 && flext::CanbeFloat(arg.GetList()[0])) + p.cbin.rarg = flext::GetAFloat(arg.GetList()[0]); + else { + post("%s - argument is invalid -> set to 1",p.opname); + p.cbin.rarg = 1; + } + p.cbin.iarg = 0; // not used anyway + + ret = DoOp(vecs,VecOp::d_rgate,p); + delete vecs; + } + return ret; +} + +VASP_ANYOP("vasp.gate",gate,1,true,VASP_ARG_R(1),"set destination to 0 if source < argument") +VASP_ANYOP("vasp.rgate",rgate,1,true,VASP_ARG_R(1),"complex radius gate: set destination to 0 if rad(complex source) < rad(complex argument)") + + +// -------------------------------------------------------------- + diff --git a/externals/grill/vasp/source/ops_gen.cpp b/externals/grill/vasp/source/ops_gen.cpp new file mode 100644 index 00000000..eec81701 --- /dev/null +++ b/externals/grill/vasp/source/ops_gen.cpp @@ -0,0 +1,265 @@ +/* + +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_gen.h" +#include "util.h" +#include <math.h> + +// --- osc --------------------------------------- + +/*! \brief Generator for real (cos) oscillations +*/ +BL VecOp::d_osc(OpParam &p) +{ + register R ph = p.gen.ph,phinc = p.gen.phinc; + if(p.revdir) ph -= (p.frames-1)*(phinc = -phinc); + + for(I i = 0; i < p.frames; ++i,ph += phinc,p.rddt += p.rds) *p.rddt = cos(ph); + return true; +} + +/*! \brief multiplicative generator for real (cos) oscillations +*/ +BL VecOp::d_mosc(OpParam &p) +{ + register R ph = p.gen.ph,phinc = p.gen.phinc; + if(p.revdir) ph -= (p.frames-1)*(phinc = -phinc); + + for(I i = 0; i < p.frames; ++i,ph += phinc,p.rsdt += p.rss,p.rddt += p.rds) + *p.rddt = *p.rsdt * cos(ph); + return true; +} + +/*! \brief Generator for real (cos) oscillations. + + \param arg argument list + \param arg.perlen Period length (in samples) + \param arg.stph Starting phase + \param mul true for multiplication to exisiting date + \return normalized destination vasp + + \todo Replace period length by frequency specification +*/ +Vasp *VaspOp::m_osc(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst,BL mul) +{ + Vasp *ret = NULL; + if(arg.IsList() && arg.GetList().Count() >= 1) { + RVecBlock *vecs = GetRVecs(p.opname,src,dst); + if(vecs) { + // period length + p.gen.phinc = 2*PI/flext::GetAFloat(arg.GetList()[0]); + // starting phase + p.gen.ph = arg.GetList().Count() >= 2?flext::GetAFloat(arg.GetList()[1]):0; + + ret = DoOp(vecs,mul?VecOp::d_mosc:VecOp::d_osc,p); + delete vecs; + } + } + else + post("%s - no arguments: no operation",p.opName()); + + return ret; +} + + +/*! \brief Generator for complex oscillations. +*/ +BL VecOp::d_cosc(OpParam &p) +{ + register R ph = p.gen.ph,phinc = p.gen.phinc; + if(p.revdir) ph -= (p.frames-1)*(phinc = -phinc); + + for(; p.frames--; ph += phinc,p.rddt += p.rds,p.iddt += p.ids) + *p.rddt = cos(ph),*p.iddt = sin(ph); + return true; +} + +/*! \brief Multiplicative generator for complex oscillations. +*/ +BL VecOp::d_mcosc(OpParam &p) +{ + register R ph = p.gen.ph,phinc = p.gen.phinc; + if(p.revdir) ph -= (p.frames-1)*(phinc = -phinc); + + for(; p.frames--; ph += phinc,p.rsdt += p.rss,p.isdt += p.iss,p.rddt += p.rds,p.iddt += p.ids) { + R zre = cos(ph),zim = sin(ph); + + register const R r = *p.rsdt * zre - *p.isdt * zim; + *p.iddt = *p.isdt * zre + *p.rsdt * zim; + *p.rddt = r; + } + return true; +} + +/*! \brief Generator for complex (cos+i sin) oscillations. + + \param arg argument list + \param arg.perlen Period length (in samples) + \param arg.stph Starting phase + \param mul true for multiplication to exisiting date + \return normalized destination vasp + + \todo Replace period length by frequency specification +*/ +Vasp *VaspOp::m_cosc(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst,BL mul) +{ + Vasp *ret = NULL; + if(arg.IsList() && arg.GetList().Count() >= 1) { + CVecBlock *vecs = GetCVecs(p.opname,src,dst); + if(vecs) { + // period length + p.gen.phinc = 2*PI/flext::GetAFloat(arg.GetList()[0]); + // starting phase + p.gen.ph = arg.GetList().Count() >= 2?flext::GetAFloat(arg.GetList()[1]):0; + + ret = DoOp(vecs,mul?VecOp::d_mcosc:VecOp::d_cosc,p); + delete vecs; + } + } + else + post("%s - no arguments: no operation",p.opName()); + + return ret; +} + + +VASP_ANYOP("vasp.osc",osc,1,false,VASP_ARG(),"Calculates a cosine wave") +VASP_ANYOP("vasp.*osc",mosc,1,true,VASP_ARG(),"Multiplies with a cosine wave") +VASP_ANYOP("vasp.cosc",cosc,1,false,VASP_ARG(),"Calculates a complex oscillation (cos + i sin)") +VASP_ANYOP("vasp.*cosc",mcosc,1,true,VASP_ARG(),"Multiplies with a complex oscillation (cos + i sin)") + +// --- phasor --------------------------------------- + +// ! look up Höldrich's pd phasor code + +/*! \brief Generator for saw wave oscillations. +*/ +BL VecOp::d_phasor(OpParam &p) +{ + register R ph = p.gen.ph,phinc = p.gen.phinc; + if(p.revdir) ph -= (p.frames-1)*(phinc = -phinc); + + for(; p.frames--; ph += phinc,p.rddt += p.rds) *p.rddt = fmod(ph,1.F); + return true; +} + +/*! \brief Multiplicative generator for saw wave oscillations. +*/ +BL VecOp::d_mphasor(OpParam &p) +{ + register R ph = p.gen.ph,phinc = p.gen.phinc; + if(p.revdir) ph -= (p.frames-1)*(phinc = -phinc); + + for(; p.frames--; ph += phinc,p.rddt += p.rds,p.rsdt += p.rss) *p.rddt = *p.rsdt * fmod(ph,1.F); + return true; +} + +/*! \brief Generator for sawtooth oscillations. + + \param arg argument list + \param arg.perlen Period length (in samples) + \param arg.stph Starting phase + \param mul true for multiplication to exisiting date + \return normalized destination vasp + + \todo Replace period length by frequency specification +*/ +Vasp *VaspOp::m_phasor(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst,BL mul) +{ + Vasp *ret = NULL; + if(arg.IsList() && arg.GetList().Count() >= 1) { + RVecBlock *vecs = GetRVecs(p.opname,src,dst); + if(vecs) { + // period length + p.gen.phinc = 1./flext::GetAFloat(arg.GetList()[0]); + // starting phase + p.gen.ph = arg.GetList().Count() >= 2?flext::GetAFloat(arg.GetList()[1]):0; + + ret = DoOp(vecs,mul?VecOp::d_mphasor:VecOp::d_phasor,p); + delete vecs; + } + } + else + post("%s - no arguments: no operation",p.opName()); + + return ret; +} + + +VASP_ANYOP("vasp.phasor",phasor,1,false,VASP_ARG(),"Calculates a sawtooth wave") +VASP_ANYOP("vasp.*phasor",mphasor,1,true,VASP_ARG(),"Multiplies with a sawtooth wave") + +// --- noise -------------------------------- + +static F rnd() +{ + static I val = 307*1319; + F ret = ((F)((val&0x7fffffff)-0x40000000))*(F)(1.0/0x40000000); + val = val * 435898247 + 382842987; + return ret; +} + +/*! \brief Vector function for pseudorandom noise. +*/ +BL VecOp::d_noise(OpParam &p) +{ + for(; p.frames--; p.rddt += p.rds) *p.rddt = rnd(); + return true; +} + + +/*! \brief Generator for real valued noise. + + \return normalized destination vasp +*/ +Vasp *VaspOp::m_noise(OpParam &p,Vasp &src,Vasp *dst) +{ + Vasp *ret = NULL; + RVecBlock *vecs = GetRVecs(p.opname,src,dst); + if(vecs) { + ret = DoOp(vecs,VecOp::d_noise,p); + delete vecs; + } + return ret; +} + +/*! \brief Vector function for pseudorandom complex noise. +*/ +BL VecOp::d_cnoise(OpParam &p) +{ + for(; p.frames--; p.rddt += p.rds,p.iddt += p.ids) { + R amp = rnd(); + R arg = rnd()*(2.*PI); + *p.rddt = amp*cos(arg); + *p.iddt = amp*sin(arg); + } + return true; +} + +/*! \brief Generator for complex noise (complex abs, complex arg). + + \return normalized destination vasp + + \todo Replace period length by frequency specification +*/ +Vasp *VaspOp::m_cnoise(OpParam &p,Vasp &src,Vasp *dst) +{ + Vasp *ret = NULL; + CVecBlock *vecs = GetCVecs(p.opname,src,dst); + if(vecs) { + ret = DoOp(vecs,VecOp::d_cnoise,p); + delete vecs; + } + return ret; +} + +VASP_UNARY("vasp.noise",noise,false,"Fills the vectors with white noise") +VASP_UNARY("vasp.cnoise",cnoise,false,"Fills the vectors with complex white noise (radius and angle are random)") + diff --git a/externals/grill/vasp/source/ops_gen.h b/externals/grill/vasp/source/ops_gen.h new file mode 100644 index 00000000..9d1902d5 --- /dev/null +++ b/externals/grill/vasp/source/ops_gen.h @@ -0,0 +1,40 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPS_GEN_H +#define __VASP_OPS_GEN_H + +#include "opbase.h" + +// Generator functions + +namespace VecOp { + BL d_osc(OpParam &p); + BL d_cosc(OpParam &p); + BL d_mosc(OpParam &p); + BL d_mcosc(OpParam &p); + BL d_phasor(OpParam &p); + BL d_mphasor(OpParam &p); + BL d_noise(OpParam &p); + BL d_cnoise(OpParam &p); +} + +namespace VaspOp { + Vasp *m_osc(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst,BL mul = false); // real osc + inline Vasp *m_mosc(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst) { return m_osc(p,src,arg,dst,true); } // * real osc + Vasp *m_cosc(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst,BL mul = false); // complex osc (phase rotates) + inline Vasp *m_mcosc(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst) { return m_cosc(p,src,arg,dst,true); } // * complex osc (phase rotates) + Vasp *m_phasor(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst,BL mul = false); // phasor + inline Vasp *m_mphasor(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst) { return m_phasor(p,src,arg,dst,true); } // * phasor + Vasp *m_noise(OpParam &p,Vasp &src,Vasp *dst); // real noise + Vasp *m_cnoise(OpParam &p,Vasp &src,Vasp *dst); // complex noise (arg and abs random) +} + +#endif diff --git a/externals/grill/vasp/source/ops_qminmax.cpp b/externals/grill/vasp/source/ops_qminmax.cpp new file mode 100644 index 00000000..05c0e8b5 --- /dev/null +++ b/externals/grill/vasp/source/ops_qminmax.cpp @@ -0,0 +1,276 @@ +/* + +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_cmp.h" +#include "opdefs.h" +#include "util.h" +#include <math.h> + +// -------------------------------------------------------------- + +template<class T> V f_maxq(T &,T ra,OpParam &p) +{ + if(ra > p.norm.minmax) p.norm.minmax = ra; +} + +template<class T> V f_minq(T &,T ra,OpParam &p) +{ + if(ra < p.norm.minmax) p.norm.minmax = ra; +} + +template<class T> V f_amaxq(T &,T ra,OpParam &p) +{ + register T s = fabs(ra); + if(s > p.norm.minmax) p.norm.minmax = s; +} + +template<class T> V f_aminq(T &,T ra,OpParam &p) +{ + register T s = fabs(ra); + if(s < p.norm.minmax) p.norm.minmax = s; +} + +template<class T> V f_rmaxq(T &,T &,T ra,T ia,OpParam &p) +{ + register T s = sqabs(ra,ia); + if(s > p.norm.minmax) p.norm.minmax = s; +} + +template<class T> V f_rminq(T &,T &,T ra,T ia,OpParam &p) +{ + register T s = sqabs(ra,ia); + if(s < p.norm.minmax) p.norm.minmax = s; +} + +BL VecOp::d_minq(OpParam &p) { D__rop(f_minq<S>,p); } +BL VecOp::d_maxq(OpParam &p) { D__rop(f_maxq<S>,p); } +BL VecOp::d_aminq(OpParam &p) { D__rop(f_aminq<S>,p); } +BL VecOp::d_amaxq(OpParam &p) { D__rop(f_amaxq<S>,p); } +BL VecOp::d_rminq(OpParam &p) { d__cop(f_rminq<S>,p); } +BL VecOp::d_rmaxq(OpParam &p) { d__cop(f_rmaxq<S>,p); } + +// -------------------------------------------------------------- + + +/*! \class vasp_qmin + \remark \b vasp.min? + \brief Get minimum sample value + \since 0.0.2 + \param inlet vasp - is stored and output triggered + \param inlet bang - triggers output + \param inlet set - vasp to be stored + \retval outlet float - minimum sample value + + \todo Should we provide a cmdln default vasp? + \todo Should we inhibit output for invalid vasps? + \remark Returns 0 for a vasp with 0 frames +*/ +class vasp_qmin: + public vasp_unop +{ + FLEXT_HEADER(vasp_qmin,vasp_unop) + +public: + vasp_qmin(): vasp_unop(true,XletCode(xlet::tp_float,0)) {} + + virtual Vasp *do_opt(OpParam &p) + { + p.norm.minmax = BIG; + Vasp *ret = VaspOp::m_qmin(p,ref); + if(p.norm.minmax == BIG) p.norm.minmax = 0; + return ret; + } + + virtual Vasp *tx_work() + { + OpParam p(thisName(),0); + Vasp *ret = do_opt(p); + ToOutFloat(1,p.norm.minmax); + return ret; + } + + virtual V m_help() { post("%s - Get a vasp's minimum sample value",thisName()); } +}; + +FLEXT_LIB("vasp, vasp.min?",vasp_qmin) + + +/*! \class vasp_qamin + \remark \b vasp.amin? + \brief Get minimum absolute sample value + \since 0.0.2 + \param inlet vasp - is stored and output triggered + \param inlet bang - triggers output + \param inlet set - vasp to be stored + \retval outlet float - minimum sample value + + \todo Should we provide a cmdln default vasp? + \todo Should we inhibit output for invalid vasps? + \remark Returns 0 for a vasp with 0 frames +*/ +class vasp_qamin: + public vasp_qmin +{ + FLEXT_HEADER(vasp_qamin,vasp_qmin) +public: + virtual Vasp *do_opt(OpParam &p) + { + p.norm.minmax = BIG; + Vasp *ret = VaspOp::m_qamin(p,ref); + if(p.norm.minmax == BIG) p.norm.minmax = 0; + return ret; + } + + virtual V m_help() { post("%s - Get a vasp's minimum absolute sample value",thisName()); } +}; + +FLEXT_LIB("vasp, vasp.amin?",vasp_qamin) + + + +/*! \class vasp_qmax + \remark \b vasp.max? + \brief Get maximum sample value + \since 0.0.2 + \param inlet vasp - is stored and output triggered + \param inlet bang - triggers output + \param inlet set - vasp to be stored + \retval outlet float - minimum sample value + + \todo Should we provide a cmdln default vasp? + \todo Should we inhibit output for invalid vasps? + \remark Returns 0 for a vasp with 0 frames +*/ +class vasp_qmax: + public vasp_qmin +{ + FLEXT_HEADER(vasp_qmax,vasp_qmin) +public: + virtual Vasp *do_opt(OpParam &p) + { + p.norm.minmax = -BIG; + Vasp *ret = VaspOp::m_qmax(p,ref); + if(p.norm.minmax == -BIG) p.norm.minmax = 0; + return ret; + } + + virtual V m_help() { post("%s - Get a vasp's maximum sample value",thisName()); } +}; + +FLEXT_LIB("vasp, vasp.max?",vasp_qmax) + + + +/*! \class vasp_qamax + \remark \b vasp.amax? + \brief Get minimum absolute sample value + \since 0.0.2 + \param inlet vasp - is stored and output triggered + \param inlet bang - triggers output + \param inlet set - vasp to be stored + \retval outlet float - minimum sample value + + \todo Should we provide a cmdln default vasp? + \todo Should we inhibit output for invalid vasps? + \remark Returns 0 for a vasp with 0 frames +*/ +class vasp_qamax: + public vasp_qmax +{ + FLEXT_HEADER(vasp_qamax,vasp_qmax) +public: + virtual Vasp *do_opt(OpParam &p) + { + p.norm.minmax = 0; + return VaspOp::m_qamax(p,ref); + } + + virtual V m_help() { post("%s - Get a vasp's maximum absolute sample value",thisName()); } +}; + +FLEXT_LIB("vasp, vasp.amax?",vasp_qamax) + + + + +/*! \class vasp_qrmin + \remark \b vasp.rmin? + \brief Get minimum complex radius of samples + \since 0.0.2 + \param inlet vasp - is stored and output triggered + \param inlet bang - triggers output + \param inlet set - vasp to be stored + \retval outlet float - minimum sample value + + \todo Should we provide a cmdln default vasp? + \todo Should we inhibit output for invalid vasps? + \remark Returns 0 for a vasp with 0 frames +*/ +class vasp_qrmin: + public vasp_unop +{ + FLEXT_HEADER(vasp_qrmin,vasp_unop) + +public: + vasp_qrmin(): vasp_unop(true,XletCode(xlet::tp_float,0)) {} + + virtual Vasp *do_opt(OpParam &p) + { + p.norm.minmax = BIG; + Vasp *ret = VaspOp::m_qrmin(p,ref); + if(p.norm.minmax == BIG) p.norm.minmax = 0; + return ret; + } + + virtual Vasp *tx_work() + { + OpParam p(thisName(),0); + Vasp *ret = do_opt(p); + ToOutFloat(1,sqrt(p.norm.minmax)); + return ret; + } + + virtual V m_help() { post("%s - Get a vasp's minimum complex radius",thisName()); } +}; + +FLEXT_LIB("vasp, vasp.rmin?",vasp_qrmin) + + + +/*! \class vasp_qrmax + \remark \b vasp.rmax? + \brief Get maximum complex radius of samples + \since 0.0.2 + \param inlet vasp - is stored and output triggered + \param inlet bang - triggers output + \param inlet set - vasp to be stored + \retval outlet float - minimum sample value + + \todo Should we provide a cmdln default vasp? + \todo Should we inhibit output for invalid vasps? + \remark Returns 0 for a vasp with 0 frames +*/ +class vasp_qrmax: + public vasp_qrmin +{ + FLEXT_HEADER(vasp_qrmax,vasp_qrmin) +public: + virtual Vasp *do_opt(OpParam &p) + { + p.norm.minmax = 0; + return VaspOp::m_qrmax(p,ref); + } + + virtual V m_help() { post("%s - Get a vasp's maximum complex radius",thisName()); } +}; + +FLEXT_LIB("vasp, vasp.rmax?",vasp_qrmax) + + diff --git a/externals/grill/vasp/source/ops_rearr.cpp b/externals/grill/vasp/source/ops_rearr.cpp new file mode 100644 index 00000000..2aa69aa2 --- /dev/null +++ b/externals/grill/vasp/source/ops_rearr.cpp @@ -0,0 +1,243 @@ +/* + +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_rearr.h" +#include "oploop.h" +#include "oppermute.h" + +/*! \brief vasp shift or rotation + \todo units for shift +*/ +Vasp *VaspOp::m_shift(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst,BL shift,BL symm) +{ + Vasp *ret = NULL; + RVecBlock *vecs = GetRVecs(p.opname,src,dst); + if(vecs) { + if(arg.IsList() && arg.GetList().Count() >= 1 && flext::CanbeFloat(arg.GetList()[0])) { + // shift length + p.sh.sh = flext::GetAFloat(arg.GetList()[0]); + } + else { + post("%s - invalid argument -> set to 0",p.opname); + p.sh.sh = 0; + } + + ret = DoOp(vecs,shift?VecOp::d_shift:VecOp::d_rot,p,symm); + delete vecs; + } + + return ret; +} + + +/*! \brief shift buffer +*/ +BL VecOp::d_shift(OpParam &p) +{ + if(p.ovrlap) { + post("%s - cannot operate on overlapped vectors",p.opname); + return false; + } + + I ish = (I)p.sh.sh; + if(p.sh.sh != ish) { // integer shift + // requires interpolation + post("non-integer shift not implemented - truncating to integer"); + p.sh.sh = ish; + } + + p.SkipOddMiddle(); + + if(p.symm == 1) ish = -ish; + + I aish = abs(ish); + if(aish > p.frames) aish = ish = p.frames; + + I i,cnt = p.frames-aish; + const S *sd = p.rsdt-ish*p.rss; + S *dd = p.rddt; + + if(ish > 0) { + sd += (p.frames-1)*p.rss,dd += (p.frames-1)*p.rds; + p.rss = -p.rss,p.rds = -p.rds; + } + + // do shift + if(cnt > 0) { + if(p.rss == 1 && p.rds == 1) + _D_LOOP(i,cnt) *(dd++) = *(sd++); _E_LOOP + else if(p.rss == -1 && p.rds == -1) + _D_LOOP(i,cnt) *(dd--) = *(sd--); _E_LOOP + else + _D_LOOP(i,cnt) *dd = *sd,sd += p.rss,dd += p.rds; _E_LOOP + } + + // fill spaces + if(p.sh.fill) { + S vfill = p.sh.fill == 1?0:dd[-p.rds]; + I aish = abs(ish); + if(p.rds == 1) + _D_LOOP(i,aish) *(dd++) = vfill; _E_LOOP + else if(p.rds == -1) + _D_LOOP(i,aish) *(dd--) = vfill; _E_LOOP + else + _D_LOOP(i,aish) *dd = vfill,dd += p.rds; _E_LOOP + } + + return true; +} + + +class vasp_shift: + public vasp_anyop +{ + FLEXT_HEADER(vasp_shift,vasp_anyop) +public: + + vasp_shift(I argc,t_atom *argv): + vasp_anyop(argc,argv,VASP_ARG_I(0),true), + fill(xsf_zero) + { + FLEXT_ADDMETHOD_E(0,"fill",m_fill); + } + + enum xs_fill { + xsf__ = -1, // don't change + xsf_none = 0,xsf_zero,xsf_edge + }; + + V m_fill(xs_fill f) { fill = f; } + + virtual Vasp *do_shift(OpParam &p) { return VaspOp::m_shift(p,ref,arg,&dst); } + + virtual Vasp *tx_work(const Argument &arg) + { + OpParam p(thisName(),0); + p.sh.fill = (I)fill; + + Vasp *ret = do_shift(p); + return ret; + } + + virtual V m_help() { post("%s - Shifts buffer data",thisName()); } + +protected: + xs_fill fill; + +private: + FLEXT_CALLBACK_1(m_fill,xs_fill) +}; +FLEXT_LIB_V("vasp, vasp.shift",vasp_shift) + + +class vasp_xshift: + public vasp_shift +{ + FLEXT_HEADER(vasp_xshift,vasp_shift) +public: + + vasp_xshift(I argc,t_atom *argv): vasp_shift(argc,argv) {} + + virtual Vasp *do_shift(OpParam &p) { return VaspOp::m_xshift(p,ref,arg,&dst); } + + virtual V m_help() { post("%s - Shifts buffer data symmetrically (in two halves)",thisName()); } +}; +FLEXT_LIB_V("vasp, vasp.xshift",vasp_xshift) + + +inline int rotation(int ij, int n,OpParam &p) { return (ij+n-p.sh.ish)%n; } + +#define ROTBLOCK 1024 + +/*! \brief rotate buffer + \todo implement temporary storage for faster transformation (use abstract permute algorithm) +*/ +BL VecOp::d_rot(OpParam &p) +{ + if(p.ovrlap) { + post("%s - cannot operate on overlapped vectors",p.opname); + return false; + } + + p.sh.ish = (I)p.sh.sh; + if(p.sh.sh != p.sh.ish) { + // requires interpolation + post("%s - non-integer shift not implemented - truncating to integer",p.opname); + } + + p.SkipOddMiddle(); + + p.sh.ish = p.sh.ish%p.frames; + if(p.symm == 1) p.sh.ish = -p.sh.ish; + +/* + if(p.frames >= ROTBLOCK) { + //use temporary space; + S *tmp = new S[ROTBLOCK]; + + delete[] tmp; + } + else +*/ + PERMUTATION(S,1,p,rotation); + return true; +} + +VASP_ANYOP("vasp.rot",rot,0,true,VASP_ARG_I(0),"Rotates buffer data") +VASP_ANYOP("vasp.xrot",xrot,0,true,VASP_ARG_I(0),"Rotates buffer data symmetrically (in two halves)") + + +/*! \brief mirror buffer +*/ +BL VecOp::d_mirr(OpParam &p) +{ + if(p.ovrlap) { + post("%s - cannot operate on overlapped vectors",p.opname); + return false; + } + + p.SkipOddMiddle(); + + if(p.rsdt == p.rddt) { + S *dl = p.rddt,*du = p.rddt+(p.frames-1)*p.rds; + _D_WHILE(dl < du) + register S t; + t = *dl; *dl = *du; *du = t; + dl += p.rds,du -= p.rds; + _E_WHILE + } + else { + I i; + const S *ds = p.rsdt; + S *dd = p.rddt+(p.frames-1)*p.rds; + _D_LOOP(i,p.frames) + *dd = *ds,ds += p.rss,dd -= p.rds; + _E_LOOP + } + return true; +} + +/*! \brief vasp mirror +*/ +Vasp *VaspOp::m_mirr(OpParam &p,Vasp &src,Vasp *dst,BL symm) +{ + Vasp *ret = NULL; + RVecBlock *vecs = GetRVecs(p.opname,src,dst); + if(vecs) { + ret = DoOp(vecs,VecOp::d_mirr,p,symm); + delete vecs; + } + return ret; +} + +VASP_UNARY("vasp.mirr",mirr,true,"Mirrors buffer data") +VASP_UNARY("vasp.xmirr",xmirr,true,"Mirrors buffer data symmetrically (in two halves)") + + diff --git a/externals/grill/vasp/source/ops_rearr.h b/externals/grill/vasp/source/ops_rearr.h new file mode 100644 index 00000000..d1c6ce73 --- /dev/null +++ b/externals/grill/vasp/source/ops_rearr.h @@ -0,0 +1,34 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPS_REARR_H +#define __VASP_OPS_REARR_H + +#include "opbase.h" + +// Rearrange buffer + +namespace VecOp { + BL d_shift(OpParam &p); + BL d_rot(OpParam &p); + BL d_mirr(OpParam &p); +} + +namespace VaspOp { + Vasp *m_shift(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL,BL sh = true,BL symm = false); // shift buffer + inline Vasp *m_xshift(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_shift(p,src,arg,dst,true,true); } // shift buffer (symmetrically) + inline Vasp *m_rot(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_shift(p,src,arg,dst,false,false); } // rotate buffer + inline Vasp *m_xrot(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_shift(p,src,arg,dst,false,true); } // rotate buffer (symmetrically) + Vasp *m_mirr(OpParam &p,Vasp &src,Vasp *dst = NULL,BL symm = false); //! mirror buffer + inline Vasp *m_xmirr(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_mirr(p,src,dst,true); } //! mirror buffer (symmetrically) + +} + +#endif diff --git a/externals/grill/vasp/source/ops_resmp.cpp b/externals/grill/vasp/source/ops_resmp.cpp new file mode 100644 index 00000000..fbeabc07 --- /dev/null +++ b/externals/grill/vasp/source/ops_resmp.cpp @@ -0,0 +1,266 @@ +/* + +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. + +*/ + +/*! \file vasp__resmp.cpp + \brief Routines for resampling +*/ + +#include "ops_resmp.h" + + +// --- resample --------------------- + +/*! \brief Subroutine for resampling. + + \param cnt frame count + \param src source data + \param sstr source data stride + \param dst destination data + \param dstr destination data stride + \param factor resampling factor + \param center resampling center (this will remain untouched by the transformation) + \param mode interpolation mode + \return true on success + + \todo implement averaging interpolation methods + \todo check for operation direction! + \todo check for src/dst overlap + \todo support different frame lengths for src and dst +*/ + +static V do_tilt(OpParam &p) +{ + I mode = p.tilt.mode; + if(mode == 0&& (p.tilt.factor < 0 || p.tilt.center < 0 || p.tilt.factor >= p.frames)) mode = 1; + + const R center = p.tilt.center; + const I icenter = (I)center; + S fll,flr; + if(p.tilt.fill) + fll = p.rsdt[0],flr = p.rsdt[p.frames-1]; + else + fll = flr = 0; + + if(mode >= 1 && mode <= 3) { + S *tmp; + I rss; + if(p.rsdt == p.rddt) { + tmp = new S[p.frames],rss = 1; + for(int i = 0; i < p.frames; ++i) tmp[i] = p.rsdt[i*p.rss]; + } + else tmp = p.rsdt,rss = p.rss; + + switch(mode) { + case 1: { + // no interpolation + for(int i = 0; i < p.frames; ++i) { + I pi = (I)(center+(i-center)*p.tilt.factor); + p.rddt[i*p.rds] = pi >= 0?(pi < p.frames?tmp[pi*rss]:flr):fll; + } + break; + } + case 2: { + // linear interpolation + for(int i = 0; i < p.frames; ++i) { + R pr = center+(i-center)*p.tilt.factor,v; + I ip = (I)pr; + if(ip >= 0) + if(ip < p.frames-1) { + R r = pr-ip; + v = (1-r)*tmp[ip*rss]+r*tmp[(ip+1)*rss]; + } + else + v = ip == p.frames-1?tmp[ip*rss]:flr; + else + v = fll; + p.rddt[i*p.rds] = v; + } + break; + } + case 3: { + // 4-point interpolation + R f[4]; + for(int i = 0; i < p.frames; ++i) { + R pr = center+(i-center)*p.tilt.factor; + const I ip = (I)pr; + const S *t = tmp+ip*rss; + const R r = pr-ip; + if(ip >= 1) + if(ip < p.frames-2) { + f[0] = t[-rss]; + f[1] = t[0]; + f[2] = t[rss]; + f[3] = t[rss*2]; + } + else { + f[0] = ip < p.frames+1?t[-rss]:flr; + f[1] = ip < p.frames?t[0]:flr; + f[2] = ip < p.frames-1?t[rss]:flr; + f[3] = flr; + } + else { + f[0] = fll; + f[1] = ip >= 0?t[0]:fll; + f[2] = ip >= -1?t[rss]:fll; + f[3] = ip >= -2?t[rss*2]:fll; + } + + const R cmb = f[2]-f[1]; + p.rddt[i*p.rds] = f[1]+r*(cmb-0.5*(r-1.)*((f[0]-f[3]+3.*cmb)*r+(f[1]-f[0]-cmb))); + } + break; + } + } + + if(p.rsdt == p.rddt) delete[] tmp; + } + else { + const R rem = center-icenter; // 0 <= rem < 1 + // quick and dirty... but in-place! + + if(p.tilt.factor > 1) { + I i; + for(i = 0; i <= icenter; ++i) { + I sp = (I)(center-(i+rem)*p.tilt.factor); + p.rddt[(icenter-i)*p.rds] = sp >= 0?(sp < p.frames?p.rsdt[sp*p.rss]:flr):fll; + } + for(i = 1; i < p.frames-icenter; ++i) { + I sp = (I)(center+(i-rem)*p.tilt.factor); + p.rddt[(icenter+i)*p.rds] = sp >= 0?(sp < p.frames?p.rsdt[sp*p.rss]:flr):fll; + } + } + else { + I i; + for(i = icenter; i >= 0; --i) { + I sp = (I)(center-(i+rem)*p.tilt.factor); + p.rddt[(icenter-i)*p.rds] = p.rsdt[sp*p.rss]; + } + for(i = p.frames-1-icenter; i > 0; --i) { + I sp = (I)(center+(i-rem)*p.tilt.factor); + p.rddt[(icenter+i)*p.rds] = p.rsdt[sp*p.rss]; + } + } + } +} + + +BL VecOp::d_tilt(OpParam &p) +{ + if(p.frames <= 1 || p.tilt.factor == 1) return true; + + // symmetric operation + if(p.symm == 1) + p.tilt.center = p.frames-1-p.tilt.center; + + do_tilt(p); + + return true; +} + + +/*! \brief Does vasp resampling. + + \param arg argument list + \param arg.factor factor for resampling + \param arg.center center of resampling + \param dst destination vasp (NULL for in-place operation) + \param symm true for symmetric operation + \param mode interpolation mode + \return normalized destination vasp +*/ +Vasp *VaspOp::m_tilt(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst,BL symm) +{ + Vasp *ret = NULL; + if(arg.IsList() && arg.GetList().Count() >= 1) { + RVecBlock *vecs = GetRVecs(p.opname,src,dst); + if(vecs) { + p.tilt.factor = flext::GetAFloat(arg.GetList()[0]); + p.tilt.center = arg.GetList().Count() >= 2?flext::GetAFloat(arg.GetList()[1]):0; + + ret = DoOp(vecs,VecOp::d_tilt,p,symm); + + delete vecs; + } + } + else + post("%s - no arguments: no operation",p.opName()); + + return ret; +} + + + +class vasp_tilt: + public vasp_anyop +{ + FLEXT_HEADER(vasp_tilt,vasp_anyop) +public: + + vasp_tilt(I argc,t_atom *argv): + vasp_anyop(argc,argv,VASP_ARG_R(1),true), + fill(xtf_zero),inter(xti_4p) + { + FLEXT_ADDMETHOD_E(0,"fill",m_fill); + FLEXT_ADDMETHOD_E(0,"inter",m_inter); + } + + enum xt_fill { + xtf__ = -1, // don't change + xtf_zero = 0,xtf_edge + }; + + enum xt_inter { + xti__ = -1, // don't change + xti_inpl = 0,xti_none,xti_lin,xti_4p + }; + + V m_fill(xt_fill f) { fill = f; } + V m_inter(xt_inter m) { inter = m; } + + virtual Vasp *do_shift(OpParam &p) { return VaspOp::m_tilt(p,ref,arg,&dst); } + + virtual Vasp *tx_work(const Argument &arg) + { + OpParam p(thisName(),1); + p.tilt.fill = (I)fill; + p.tilt.mode = (I)inter; + + Vasp *ret = do_shift(p); + return ret; + } + + virtual V m_help() { post("%s - Resamples buffer data",thisName()); } + +protected: + xt_fill fill; + xt_inter inter; + +private: + FLEXT_CALLBACK_1(m_fill,xt_fill) + FLEXT_CALLBACK_1(m_inter,xt_inter) +}; +FLEXT_LIB_V("vasp, vasp.tilt",vasp_tilt) + + +class vasp_xtilt: + public vasp_tilt +{ + FLEXT_HEADER(vasp_xtilt,vasp_tilt) +public: + + vasp_xtilt(I argc,t_atom *argv): vasp_tilt(argc,argv) {} + + virtual Vasp *do_shift(OpParam &p) { return VaspOp::m_xtilt(p,ref,arg,&dst); } + + virtual V m_help() { post("%s - Resamples buffer data symmetrically (in two halves)",thisName()); } +}; +FLEXT_LIB_V("vasp, vasp.xtilt",vasp_xtilt) + + diff --git a/externals/grill/vasp/source/ops_resmp.h b/externals/grill/vasp/source/ops_resmp.h new file mode 100644 index 00000000..9c4a8bde --- /dev/null +++ b/externals/grill/vasp/source/ops_resmp.h @@ -0,0 +1,28 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPS_RESMP_H +#define __VASP_OPS_RESMP_H + +#include "opbase.h" + +// Resampling (around center sample) + +namespace VecOp { + BL d_tilt(OpParam &p); +} + +namespace VaspOp { + Vasp *m_tilt(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL,BL symm = false); + // Symmetric resampling (around center sample) + inline Vasp *m_xtilt(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_tilt(p,src,arg,dst,true); } +} + +#endif diff --git a/externals/grill/vasp/source/ops_search.cpp b/externals/grill/vasp/source/ops_search.cpp new file mode 100644 index 00000000..7afc84c2 --- /dev/null +++ b/externals/grill/vasp/source/ops_search.cpp @@ -0,0 +1,187 @@ +/* + +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_search.h" +#include "util.h" +#include "oploop.h" + + +BL VecOp::d_search(OpParam &p) +{ + const I off = p.srch.offs; + const S val = p.srch.val; + const R cur = p.rsdt[off]; + + I i,ofl = -1,ofr = -1; + + if(p.srch.dir <= 0) { + BL y = cur >= val; + i = off-1; + _D_WHILE(i >= 0) + BL y2 = p.rsdt[i] >= val; + if(y != y2) { + if(p.srch.slope <= 0 && y2) break; + if(p.srch.slope >= 0 && !y2) break; + } + y = y2; + --i; + _E_WHILE + + if(i >= 0) ofl = i; + } + + if(p.srch.dir >= 0) { + BL y = cur >= val; + i = off+1; + _D_WHILE(i < p.frames) + BL y2 = p.rsdt[i] >= val; + if(y != y2) { + if(p.srch.slope <= 0 && !y2) break; + if(p.srch.slope >= 0 && y2) break; + } + y = y2; + ++i; + _E_WHILE + + if(i < p.frames) ofr = i; + } + + if(!p.srch.dir) { + if(ofl >= 0) { + p.srch.dif = ofl-off; + if(ofr >= 0 && abs(p.srch.dif) < abs(ofr-off)) p.srch.dif = ofr-off; + } + else + p.srch.dif = ofr >= 0?ofr-off:0; + } + else if(p.srch.dir > 0) + p.srch.dif = ofr >= 0?ofr-off:0; + else + p.srch.dif = ofl >= 0?ofl-off:0; + + return true; +} + +Vasp *VaspOp::m_search(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst,BL st) +{ + Vasp *ret = NULL; + if(src.Vectors() > 1) + post("%s - More than one vector in vasp!",p.opName()); + else if(arg.CanbeFloat() || (arg.IsList() && arg.GetList().Count() >= 1)) { + I fr = src.ChkFrames(); + I o = src.Vector(0).Offset(); + I sz = src.Buffer(0)->Frames(); + + Vasp all(src); + if(st) { + // search start point + p.srch.offs = o; + + // set bounds of search buffer + all.Offset(0); + all.Frames(fr+o); // all frames of buffer + } + else { + // search end point + p.srch.offs = o+fr; + // check if current offset is past buffer + if(p.srch.offs >= sz) p.srch.offs = sz-1; + + // set bounds of search buffer + all.Offset(o); + all.Frames(sz-o); // all frames of buffer + } + + RVecBlock *vecs = GetRVecs(p.opname,all,dst); + if(vecs) { + p.srch.val = arg.IsList()?flext::GetAFloat(arg.GetList()[0]):arg.GetAFloat(); + + ret = DoOp(vecs,VecOp::d_search,p); + + if(st) o += p.srch.dif,fr -= p.srch.dif; + else fr += p.srch.dif; + + if(ret) { + ret->Offset(o); + ret->Frames(fr); + ret->Frames(ret->ChkFrames()); + } + + delete vecs; + } + } + else + post("%s - no arguments: no operation",p.opName()); + + return ret; +} + + +class vasp_search: + public vasp_anyop +{ + FLEXT_HEADER(vasp_search,vasp_anyop) +public: + + vasp_search(I argc,t_atom *argv): + vasp_anyop(argc,argv,VASP_ARG_R(0),false,XletCode(xlet::tp_float,0)), + slope(0),dir(0) + { + FLEXT_ADDMETHOD_I(0,"dir",m_dir); + FLEXT_ADDMETHOD_I(0,"slope",m_slope); + } + + virtual Vasp *do_work(OpParam &p) = 0; + + virtual Vasp *tx_work(const Argument &arg) + { + OpParam p(thisName(),1); + p.srch.dir = dir; + p.srch.slope = slope; + + Vasp *ret = do_work(p); + if(ret) ToOutFloat(1,p.srch.dif); + return ret; + } + + V m_dir(I d) { dir = d; } + V m_slope(I sl) { slope = sl; } + +protected: + I dir,slope; + +private: + FLEXT_CALLBACK_I(m_dir) + FLEXT_CALLBACK_I(m_slope) +}; + + +class vasp_soffset: + public vasp_search +{ + FLEXT_HEADER(vasp_soffset,vasp_search) +public: + vasp_soffset(I argc,t_atom *argv): vasp_search(argc,argv) {} + virtual Vasp *do_work(OpParam &p) { return VaspOp::m_soffset(p,ref,arg,&dst); } +}; +FLEXT_LIB_V("vasp, vasp.offset= vasp.o=",vasp_soffset) + + +class vasp_sframes: + public vasp_search +{ + FLEXT_HEADER(vasp_sframes,vasp_search) +public: + vasp_sframes(I argc,t_atom *argv): vasp_search(argc,argv) {} + virtual Vasp *do_work(OpParam &p) { return VaspOp::m_sframes(p,ref,arg,&dst); } +}; +FLEXT_LIB_V("vasp, vasp.frames= vasp.f=",vasp_sframes) + + diff --git a/externals/grill/vasp/source/ops_search.h b/externals/grill/vasp/source/ops_search.h new file mode 100644 index 00000000..e7a04e5c --- /dev/null +++ b/externals/grill/vasp/source/ops_search.h @@ -0,0 +1,29 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPS_SEARCH_H +#define __VASP_OPS_SEARCH_H + +#include "opbase.h" + +// Sample search functions + +namespace VecOp { + BL d_search(OpParam &p); //! find values +} + +namespace VaspOp { + // search functions + Vasp *m_search(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst,BL st); //! find values + inline Vasp *m_soffset(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_search(p,src,arg,dst,true); } + inline Vasp *m_sframes(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_search(p,src,arg,dst,false); } +} + +#endif diff --git a/externals/grill/vasp/source/ops_trnsc.cpp b/externals/grill/vasp/source/ops_trnsc.cpp new file mode 100644 index 00000000..1b26f204 --- /dev/null +++ b/externals/grill/vasp/source/ops_trnsc.cpp @@ -0,0 +1,83 @@ +/* + +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_trnsc.h" +#include "opdefs.h" +#include "util.h" +#include <math.h> + +// -------------------------------------------------------------- + +template<class T> V f_rpow(T &v,T a,T b) { v = pow(fabs(a),b)*sgn(a); } + +BL VecOp::d_pow(OpParam &p) { d__rbin(f_rpow<S>,p); } + +template<class T> V f_crpow(T &rv,T &iv,T ra,T ia,T rb,T) +{ + register const R _abs = sqrt(sqabs(ra,ia)); + if(_abs) { + register const R _p = pow(_abs,rb)/_abs; + rv = _p*ra,iv = _p*ia; + } + else + rv = iv = 0; +} + +BL VecOp::d_rpow(OpParam &p) { d__cbin(f_crpow<S>,p); } + +Vasp *VaspOp::m_rpow(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst) +{ + Vasp *ret = NULL; + CVecBlock *vecs = GetCVecs(p.opname,src,dst); + if(vecs) { + if(arg.IsList() && arg.GetList().Count() >= 1 && flext::CanbeFloat(arg.GetList()[0])) + p.cbin.rarg = flext::GetAFloat(arg.GetList()[0]); + else { + post("%s - argument is invalid -> set to 1",p.opname); + p.cbin.rarg = 1; + } + p.cbin.iarg = 0; // not used anyway + + ret = DoOp(vecs,VecOp::d_rpow,p); + delete vecs; + } + return ret; +} + +VASP_BINARY("vasp.pow",pow,true,VASP_ARG_R(1),"Real power function") +VASP_ANYOP("vasp.rpow",rpow,0,true,VASP_ARG_R(1),"Power function acting on complex radius") + + +// -------------------------------------------------------------- + +template<class T> V f_rsqrt(T &v,T a) { v = sqrt(fabs(a)); } +template<class T> V f_rssqrt(T &v,T a) { v = sqrt(fabs(a))*sgn(a); } + +BL VecOp::d_sqrt(OpParam &p) { d__run(f_rsqrt<S>,p); } +BL VecOp::d_ssqrt(OpParam &p) { d__run(f_rssqrt<S>,p); } + + +VASP_UNARY("vasp.sqrt",sqrt,true,"Square root") +VASP_UNARY("vasp.ssqrt",ssqrt,true,"Square root preserving the sign") + +// -------------------------------------------------------------- + + +template<class T> V f_rexp(T &v,T a) { v = exp(a); } +template<class T> V f_rlog(T &v,T a) { v = log(a); } // \todo detect NANs + +BL VecOp::d_exp(OpParam &p) { d__run(f_rexp<S>,p); } +BL VecOp::d_log(OpParam &p) { d__run(f_rlog<S>,p); } + + +VASP_UNARY("vasp.exp",exp,true,"Exponential function") +VASP_UNARY("vasp.log",log,true,"Natural logarithm") + + diff --git a/externals/grill/vasp/source/ops_trnsc.h b/externals/grill/vasp/source/ops_trnsc.h new file mode 100644 index 00000000..81009298 --- /dev/null +++ b/externals/grill/vasp/source/ops_trnsc.h @@ -0,0 +1,47 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPS_TRNSC_H +#define __VASP_OPS_TRNSC_H + +#include "opbase.h" + +// Transcendent math functions + +namespace VecOp { + BL d_pow(OpParam &p); + + BL d_rpow(OpParam &p); + + BL d_sqrt(OpParam &p); + BL d_ssqrt(OpParam &p); + + + BL d_exp(OpParam &p); + BL d_log(OpParam &p); +} + +namespace VaspOp { + inline Vasp *m_pow(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL) { return m_rbin(p,src,arg,dst,VecOp::d_pow); } // power + + Vasp *m_rpow(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst = NULL); // radius power (with each two channels) + + inline Vasp *m_sqrt(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_run(p,src,dst,VecOp::d_sqrt); } // square root (from abs value) + inline Vasp *m_ssqrt(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_run(p,src,dst,VecOp::d_ssqrt); } // square root (from abs value) + + inline Vasp *m_exp(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_run(p,src,dst,VecOp::d_exp); } // exponential function + inline Vasp *m_log(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_run(p,src,dst,VecOp::d_log); } // natural logarithm + +// inline Vasp *m_cexp(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_cun(p,src,dst,VecOp::d_cexp); } // complex exponential function +// inline Vasp *m_clog(OpParam &p,Vasp &src,Vasp *dst = NULL) { return m_cun(p,src,dst,VecOp::d_clog); } // complex logarithm (how about branches?) + +} + +#endif diff --git a/externals/grill/vasp/source/ops_wnd.cpp b/externals/grill/vasp/source/ops_wnd.cpp new file mode 100644 index 00000000..232649aa --- /dev/null +++ b/externals/grill/vasp/source/ops_wnd.cpp @@ -0,0 +1,191 @@ +/* + +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_wnd.h" +#include "oploop.h" +#include <math.h> +#include <string.h> + +#ifndef PI +#define PI 3.1415926535897932384 +#endif + +// --- window -------------------------- + +typedef R (*wfunc)(R i,const OpParam &p); + +inline R wf_sin(R i,const OpParam &p) { return sin(i*p.wnd.p1+p.wnd.p2); } +inline R wf_hanning(R i,const OpParam &p) { return 0.5*(1+cos(i*p.wnd.p1+p.wnd.p2)); } +inline R wf_hamming(R i,const OpParam &p) { return 0.54 + 0.46 * cos(i*p.wnd.p1+p.wnd.p2); } +inline R wf_blackman(R i,const OpParam &p) { const R x = i*p.wnd.p1+p.wnd.p2; return 0.42+0.5*cos(x)+0.08*cos(2*x); } +inline R wf_connes(R i,const OpParam &p) { const R x = i*p.wnd.p1+p.wnd.p2,x2 = 1-x*x; return x2*x2; } +inline R wf_welch(R i,const OpParam &p) { const R x = i*p.wnd.p1+p.wnd.p2; return 1-x*x; } +inline R wf_lanczos(R i,const OpParam &p) { const R x = i*p.wnd.p1+p.wnd.p2; return x?sin(x)/x:1; } +//inline R wf_gaussian(R i,const OpParam &p) { const R x = i*p.wnd.p1+p.wnd.p2; return pow(2, (-1 * (x / p.wnd.p3) * (x / p.wnd.p3))); } +//inline R wf_kaiser(R i,const OpParam &p) { const R x = i*p.wnd.p1+p.wnd.p2; return i0(p.wnd.p3 * sqrt(1 - (x * x))) / i0(p.wnd.p3); } + + +static V WndOp(wfunc wf,OpParam &p) { + register I i; + + if(!p.wnd.mul) { + register S *dd = p.rddt; + _D_LOOP(i,p.frames) *dd = wf(i,p),dd += p.rds; _E_LOOP + } + else { + register const S *sd = p.rsdt; + register S *dd = p.rddt; + _D_LOOP(i,p.frames) *dd = *sd*wf(i,p),sd += p.rss,dd += p.rds; _E_LOOP + } +} + +#define WNDOP(WFUNC,OPP) WndOp(WFUNC,OPP) + + + +BL VecOp::d_window(OpParam &p) +{ + // reverse direction? + BL rev = ((p.revdir?1:0)^(p.symm == 1?1:0)^(p.wnd.inv?1:0)) != 0; + + // set middle sample (if existent) to 1 + if(p.oddrem) p.SkipOddMiddle(1); + + switch(p.wnd.wndtp) { + case 0: { // bevel (Bartlett) + register R inc,cur; + inc = (rev?-1.:1.)/p.frames; // increase + cur = rev?(1+inc/2):inc/2; // start + + if(!p.wnd.mul) { + register S *dd = p.rddt; + register I i; + if(p.rds == 1) + _D_LOOP(i,p.frames) *(dd++) = cur,cur += inc; _E_LOOP + else + _D_LOOP(i,p.frames) *dd = cur,dd += p.rds,cur += inc; _E_LOOP + } + else { + register const S *sd = p.rsdt; + register S *dd = p.rddt; + register I i; + if(sd == dd) + if(p.rss == 1 && p.rds == 1) + _D_LOOP(i,p.frames) *(dd++) *= cur,cur += inc; _E_LOOP + else + _D_LOOP(i,p.frames) *dd *= cur,dd += p.rds,cur += inc; _E_LOOP + else + if(p.rss == 1 && p.rds == 1) + _D_LOOP(i,p.frames) *(dd++) = *(sd++) * cur,cur += inc; _E_LOOP + else + _D_LOOP(i,p.frames) *dd = *sd * cur,sd += p.rss,dd += p.rds,cur += inc; _E_LOOP + } + break; + } + case 1: { // sine + p.wnd.p1 = (PI/2)/p.frames; + p.wnd.p2 = p.wnd.p1/2+(rev?PI/2:0); + WNDOP(wf_sin,p); + break; + } + case 2: { // Hanning + p.wnd.p1 = PI/p.frames; + p.wnd.p2 = p.wnd.p1/2+(rev?0:PI); + WNDOP(wf_hanning,p); + break; + } + case 3: { // Hamming + p.wnd.p1 = PI/p.frames; + p.wnd.p2 = p.wnd.p1/2+(rev?0:PI); + WNDOP(wf_hamming,p); + break; + } + case 4: { // Blackman + p.wnd.p1 = PI/p.frames; + p.wnd.p2 = p.wnd.p1/2+(rev?0:PI); + WNDOP(wf_blackman,p); + break; + } + case 5: { // Connes (xxx) + p.wnd.p1 = 1./p.frames; + p.wnd.p2 = p.wnd.p1/2+(rev?1:0); + WNDOP(wf_connes,p); + break; + } + case 6: { // Welch (xxx) + p.wnd.p1 = 1./p.frames; + p.wnd.p2 = p.wnd.p1/2+(rev?1:0); + WNDOP(wf_welch,p); + break; + } + case 7: { // Lanczos (xxx) + p.wnd.p1 = PI/p.frames; + p.wnd.p2 = p.wnd.p1/2+(rev?0:PI); + WNDOP(wf_lanczos,p); + break; + } + default: { + post("%s: Window function #%i not known",p.opname,p.wnd.wndtp); + return false; + } + } + + return true; +} + +Vasp *VaspOp::m_window(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst,BL inv,BL mul,BL symm) +{ + static const int wndnum = 8; + static const char *wndtps[wndnum] = {"lin","sin","hanning","hamming","blackman","connes","welch","lanczos" /*,"gaussian","kaiser"*/}; + + Vasp *ret = NULL; + RVecBlock *vecs = GetRVecs(p.opname,src,dst); + if(vecs) { + p.wnd.wndtp = -1; + + if(arg.IsList() && arg.GetList().Count() >= 1) { + // window mode + const flext::AtomList &l = arg.GetList(); + if(flext::IsSymbol(l[0])) { + I i; + const C *s = flext::GetString(l[0]); + p.wnd.wndtp = -1; + for(i = 0; i < wndnum; ++i) + if(!strcmp(wndtps[i],s)) { p.wnd.wndtp = i; break; } + } + else if(flext::CanbeInt(l[0])) { + p.wnd.wndtp = flext::GetAInt(l[0]); + } + else p.wnd.wndtp = -1; + } + + if(p.wnd.wndtp < 0) { + post("%s - invalid window type - using lin",p.opname); + p.wnd.wndtp = 0; + } + + p.wnd.inv = inv; + p.wnd.mul = mul; + ret = DoOp(vecs,VecOp::d_window,p,symm); + delete vecs; + } + + return ret; +} + +VASP_ANYOP("vasp.window vasp.wnd",window,0,false,VASP_ARG(),"Sets target vasp to window function") +VASP_ANYOP("vasp.*window vasp.*wnd",mwindow,0,true,VASP_ARG(),"Multiplies a vasp by window function") +VASP_ANYOP("vasp.!window vasp.!wnd",iwindow,0,false,VASP_ARG(),"Sets target vasp to reverse window function") +VASP_ANYOP("vasp.*!window vasp.!wnd",miwindow,0,true,VASP_ARG(),"Multiplies a vasp by reverse window function") +VASP_ANYOP("vasp.xwindow vasp.xwnd",xwindow,0,false,VASP_ARG(),"Sets target vasp to symmetrical window function") +VASP_ANYOP("vasp.*xwindow vasp.*xwnd",mxwindow,0,true,VASP_ARG(),"Multiplies a vasp by symmetrical window function") + + + diff --git a/externals/grill/vasp/source/ops_wnd.h b/externals/grill/vasp/source/ops_wnd.h new file mode 100644 index 00000000..21bafb59 --- /dev/null +++ b/externals/grill/vasp/source/ops_wnd.h @@ -0,0 +1,39 @@ +/* + +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. + +*/ + +#ifndef __VASP_OPS_WND_H +#define __VASP_OPS_WND_H + +#include "opbase.h" + +// Window functions + +namespace VecOp { + BL d_bevel(OpParam &p); + BL d_mbevel(OpParam &p); + + BL d_window(OpParam &p); +} + +namespace VaspOp { + Vasp *m_bevelup(OpParam &p,Vasp &src,Vasp *dst,BL up = true,BL mul = false); // bevel up + inline Vasp *m_mbevelup(OpParam &p,Vasp &src,Vasp *dst) { return m_bevelup(p,src,dst,true,true); } // * bevel up (fade in) + inline Vasp *m_beveldn(OpParam &p,Vasp &src,Vasp *dst) { return m_bevelup(p,src,dst,false,false); } // bevel down + inline Vasp *m_mbeveldn(OpParam &p,Vasp &src,Vasp *dst) { return m_bevelup(p,src,dst,false,true); } // * bevel down (fade out) + + Vasp *m_window(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst,BL inv = false,BL mul = false,BL symm = false); // window curve + inline Vasp *m_mwindow(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst) { return m_window(p,src,arg,dst,false,true,false); } // * window curve + inline Vasp *m_iwindow(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst) { return m_window(p,src,arg,dst,true,false,false); } // inverse window curve + inline Vasp *m_miwindow(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst) { return m_window(p,src,arg,dst,true,true,false); } // * inverse window curve + inline Vasp *m_xwindow(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst) { return m_window(p,src,arg,dst,false,false,true); } // symmetrical window curve + inline Vasp *m_mxwindow(OpParam &p,Vasp &src,const Argument &arg,Vasp *dst) { return m_window(p,src,arg,dst,false,true,true); } // * symmetrical window curve +} + +#endif diff --git a/externals/grill/vasp/source/opvecs.cpp b/externals/grill/vasp/source/opvecs.cpp new file mode 100644 index 00000000..0e476682 --- /dev/null +++ b/externals/grill/vasp/source/opvecs.cpp @@ -0,0 +1,630 @@ +/* + +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. + +*/ + +/*! \file vasp__ctrl.cpp + \brief Methods for handling of vector data for real, complex and multi-vector cases. + +*/ + +#include "opbase.h" +#include "classes.h" +#include "vecblk.h" +#include "util.h" + +/*! \brief Corrects for the common vector frame count + \param frms frame count to correct + \param bl new frame count + \return true if a correction was made +*/ +static BL corrlen(I &frms,I bl,I bf = -1,I bo = 0) +{ + if(bf < 0) bf = bl; + + BL corr = false; + BL all = frms < 0; + if(all) + frms = bl; + else if(frms > bl) { + // longer than vector length -> correct + frms = bl; + corr = true; + } + + if(bo+frms > bf) { + // now check if buffer size is exceeded +// post("%s - %s vector (%s) exceeds buffer size: cropped",op,bli == 0?"src":"dst",bref->Name()); + frms = bf-bo; + if(frms < 0) frms = 0; + corr = true; + } + + return corr; +} + + +inline BL corrlen(I &frms,VBuffer &b) +{ + return corrlen(frms,b.Length(),b.Frames(),b.Offset()); +} + + +/*! \brief Make real vector block for unary operations. + + \param op operation name + \param src source vasp + \param dst optional destination vasp + \return struct with vector data + + \remark working size is maximum common vector size +*/ +RVecBlock *VaspOp::GetRVecs(const C *op,Vasp &src,Vasp *dst) +{ + I nvecs = src.Vectors(); + if(dst && dst->Ok() && dst->Vectors() != nvecs) { + nvecs = min(nvecs,dst->Vectors()); + post("%s - src/dst vector number not equal -> taking minimum",op); + } + + RVecBlock *ret = new RVecBlock(nvecs); + + BL ok = true,dlens = false; + I tfrms = -1; + + Vasp *vbl[2] = {&src,dst}; + + for(I bli = 0; bli < 2; ++bli) + for(I ci = 0; ok && ci < nvecs; ++ci) { + VBuffer *bref = NULL; + if(vbl[bli] && vbl[bli]->Ok()) { + bref = vbl[bli]->Buffer(ci); + if(!bref->Data()) { + post("%s - %s vector (%s) is invalid",op,bli == 0?"src":"dst",bref->Name()); + delete bref; bref = NULL; + ok = false; + } + else + dlens = dlens || corrlen(tfrms,*bref); + } + + if(bli == 0) + ret->Src(ci,bref); + else + ret->Dst(ci,bref); + } + + if(dlens) post("%s - vector length has been limited to maximum common length (%i)",op,tfrms); + + ret->Frames(tfrms < 0?0:tfrms); + + if(ok) return ret; + else { delete ret; return NULL; } +} + +/*! \brief Make real vector block for unary operations. + + \param op operation name + \param src source vasp + \param dst optional destination vasp + \param full true if imaginary part is compulsory + \return struct with vector data +*/ +CVecBlock *VaspOp::GetCVecs(const C *op,Vasp &src,Vasp *dst,BL full) +{ + I nvecs = src.Vectors(); + if(dst && dst->Ok() && dst->Vectors() != nvecs) { + nvecs = min(nvecs,dst->Vectors()); + post("%s - src/dst vector number not equal -> taking minimum",op); + } + + I pairs = nvecs/2; + if(nvecs != pairs*2) + if(full) { + post("%s - number of vectors is odd - not allowed",op); + return NULL; + } + else { + post("%s - number of vectors is odd - omitting last vector",op); + } + + CVecBlock *ret = new CVecBlock(pairs); + BL ok = true,dlens = false; + I tfrms = -1; + + Vasp *vbl[2] = {&src,dst}; + + for(I bli = 0; bli < 2; ++bli) + for(I ci = 0; ci < pairs; ++ci) { + VBuffer *bre = NULL,*bim = NULL; // complex channels + if(vbl[bli] && vbl[bli]->Ok()) { + const C *vnm = bli == 0?"src":"dst"; + bre = vbl[bli]->Buffer(ci*2); + bim = vbl[bli]->Buffer(ci*2+1); // complex channels + + if(!bre->Data()) { + post("%s - real %s vector (%s) is invalid",op,vnm,bre->Name()); + delete bre; bre = NULL; + ok = false; + } + if(bim && !bim->Data()) { + post("%s - imag %s vector (%s) is invalid",op,vnm,bim->Name()); + delete bim; bim = NULL; + ok = false; + } + + // check against common vector length + if(bre) { + dlens = dlens || corrlen(tfrms,*bre); + } + if(bim) { + dlens = dlens || corrlen(tfrms,*bim); + } + + } + + if(bli == 0) + ret->Src(ci,bre,bim); + else + ret->Dst(ci,bre,bim); + } + + if(dlens) post("%s - vector src/dst length has been limited to maximum common length (%i)",op,tfrms); + + ret->Frames(tfrms < 0?0:tfrms); + + if(ok) return ret; + else { delete ret; return NULL; } +} + + +/*! \brief Make real vector block for binary operations. + + \param op operation name + \param src source vasp + \param arg argument vasp + \param dst optional destination vasp + \param multi 0 off/1 on/-1 auto... controls whether argument vector is single- or multi-vectored + \return struct with vector data +*/ +RVecBlock *VaspOp::GetRVecs(const C *op,Vasp &src,const Vasp &arg,Vasp *dst,I multi,BL ssize) +{ + if(!arg.Ok()) { + post("%s - invalid argument vasp detected and ignored",op); + return NULL; + } + + I nvecs = src.Vectors(); + if(dst && dst->Ok() && dst->Vectors() != nvecs) { + nvecs = min(nvecs,dst->Vectors()); + post("%s - src/dst vector number not equal -> taking minimum",op); + } + + RVecBlock *ret; + + if(multi < 0) { // auto mode + multi = arg.Vectors() > 1; + } + + if(multi) { + if(arg.Vectors() < nvecs) { + nvecs = arg.Vectors(); + post("%s - too few arg vectors, operating on only first %i vectors",op,nvecs); + } + ret = new RVecBlock(nvecs,nvecs,1); + for(I i = 0; i < nvecs; ++i) + ret->Arg(i,arg.Buffer(i)); + } + else { + if(arg.Vectors() > 1) { + post("%s - using only first arg vector for all operations",op); + } + ret = new RVecBlock(nvecs,nvecs,1); + for(I i = 0; i < nvecs; ++i) + ret->Arg(i,arg.Buffer(0)); + } + + BL ok = true,dlens = false,dalens = false; + I tfrms = -1,afrms = -1; + + for(I ci = 0; ok && ci < nvecs; ++ci) { + VBuffer *bref = src.Buffer(ci); + VBuffer *barg = ret->Arg(multi?ci:0); + VBuffer *bdst = dst && dst->Ok()?dst->Buffer(ci):NULL; + + if(barg && (multi || ci == 0) && !barg->Data()) { + post("%s - arg vector (%s) is invalid",op,barg->Name()); + ok = false; break; // really break? + } + else if(!bref->Data()) { + post("%s - src vector (%s) is invalid",op,bref->Name()); + ok = false; break; // really break? + } + + // check src/dst frame lengths + dlens = dlens || corrlen(tfrms,*bref); + if(bdst) dlens = dlens || corrlen(tfrms,*bdst); + + // check arg frame length + if(barg) dalens = dalens || corrlen(afrms,*barg); + + ret->Src(ci,bref); + if(bdst) ret->Dst(ci,bdst); + } + + if(dlens) post("%s - vector src/dst length has been limited to maximum common length (%i)",op,tfrms); + if(dalens) post("%s - vector arg length has been limited to maximum common length (%i)",op,afrms); + + if(ssize) { + if(corrlen(tfrms,afrms)) + post("%s - vector src/dst and arg lengths are unequal -> set to max. common length (%i)",op,tfrms); + afrms = tfrms; + } + + ret->Frames(tfrms < 0?0:tfrms); + ret->ArgFrames(afrms < 0?0:afrms); + + if(ok) return ret; + else { delete ret; return NULL; } +} + + +/*! \brief Make real complex block for binary operations. + + \param op operation name + \param src source vasp + \param arg argument vasp + \param dst optional destination vasp + \param multi 0 off/1 on/-1 auto... controls whether argument vector is single- or multi-vectored + \param full true if imaginary part is compulsory + \return struct with vector data +*/ +CVecBlock *VaspOp::GetCVecs(const C *op,Vasp &src,const Vasp &arg,Vasp *dst,I multi,BL ssize,BL full) +{ + if(!arg.Ok()) { + post("%s - invalid argument vasp detected and ignored",op); + return NULL; + } + + I nvecs = src.Vectors(); + if(dst && dst->Ok() && dst->Vectors() != nvecs) { + nvecs = min(nvecs,dst->Vectors()); + post("%s - src/dst vector number not equal -> taking minimum",op); + } + + I pairs = nvecs/2; + CVecBlock *ret; + + if(multi < 0) { // auto mode + multi = arg.Vectors() > 2; // more than one argument pair -> multi + } + + if(multi) { + I apairs = arg.Vectors()/2; + if(arg.Vectors() != apairs*2) + if(full) { + post("%s - number of arg vectors is odd - not allowed",op); + return NULL; + } + else { + post("%s - number of arg vectors is odd - assuming complex part as 0",op); + ++apairs; + } + + if(apairs < pairs) { + pairs = apairs; + post("%s - too few arg vectors, operating on only first %i vector pairs",op,pairs); + } + ret = new CVecBlock(pairs,pairs,1); + for(I i = 0; i < pairs; ++i) + ret->Arg(i,arg.Buffer(i*2),arg.Buffer(i*2+1)); + } + else { + if(arg.Vectors() > 2) { + post("%s - using only first arg vector pair for all operations",op); + } + ret = new CVecBlock(pairs,pairs,1); + for(I i = 0; i < pairs; ++i) + ret->Arg(i,arg.Buffer(0),arg.Buffer(1)); + } + + BL ok = true,dlens = false,dalens = false; + I tfrms = -1,afrms = -1; + + { + if(nvecs != pairs*2) { + post("%s - number of src vectors is odd - omitting last vector",op); + // clear superfluous vector? + } + + for(I ci = 0; ok && ci < pairs; ++ci) { + // --- arg stuff ---------------- + + VBuffer *brarg = ret->ReArg(ci),*biarg = ret->ImArg(ci); + + if(multi || ci == 0) { + if(!brarg->Data()) { + post("%s - real arg vector (%s) is invalid",op,brarg->Name()); + ok = false; break; + } + else if(biarg && !biarg->Data()) { + post("%s - imag arg vector (%s) is invalid",op,biarg->Name()); + ok = false; break; + } + } + + // check against common arg length + if(brarg) dalens = dalens || corrlen(afrms,*brarg); + if(biarg) dalens = dalens || corrlen(afrms,*biarg); + + // --- src/dst stuff ---------------- + + VBuffer *brref = src.Buffer(ci*2),*biref = src.Buffer(ci*2+1); + VBuffer *brdst,*bidst; + if(dst && dst->Ok()) brdst = dst->Buffer(ci*2),bidst = dst->Buffer(ci*2+1); + else brdst = bidst = NULL; + + if(!brref->Data()) { + post("%s - real src vector (%s) is invalid",op,brref->Name()); + ok = false; break; // really break? + } + else if(biref && !biref->Data()) { + post("%s - imag src vector (%s) is invalid",op,biref->Name()); + ok = false; break; // really break? + } + else { + dlens = dlens || corrlen(tfrms,*brref); + if(biref) dlens = dlens || corrlen(tfrms,*biref); + if(brdst) dlens = dlens || corrlen(tfrms,*brdst); + if(bidst) dlens = dlens || corrlen(tfrms,*bidst); + } + + ret->Src(ci,brref,biref); + if(brdst) ret->Dst(ci,brdst,bidst); + } + } + + if(dlens) post("%s - vector src/dst length has been limited to maximum common length (%i)",op,tfrms); + if(dalens) post("%s - vector arg length has been limited to maximum common length (%i)",op,afrms); + + if(ssize) { + if(corrlen(tfrms,afrms)) + post("%s - vector src/dst and arg lengths are unequal -> set to max. common length (%i)",op,tfrms); + afrms = tfrms; + } + + ret->Frames(tfrms < 0?0:tfrms); + ret->ArgFrames(afrms < 0?0:afrms); + + if(ok) return ret; + else { delete ret; return NULL; } +} + + +/*! \brief Run the operation on the various real vectors. + + \param vecs src/arg/dst vector block + \param fun operative function + \param p parameter block for operative function + \return normalized vasp or NULL on error + + \todo set overlap flag + + \remark operative function must be capable of handling reversed direction +*/ +Vasp *VaspOp::DoOp(RVecBlock *vecs,VecOp::opfun *fun,OpParam &p,BL symm) +{ + BL ok = true; + + if(vecs->ArgBlks() && (!p.arg || p.args < vecs->ArgBlks())) { + post("%s - not enough argument blocks",p.opname); + ok = false; + } + + const I scnt = symm?2:1; + for(I i = 0; ok && i < vecs->Vecs(); ++i) + for(I si = 0; ok && si < scnt; ++si) { + p.frames = vecs->Frames(); + + VBuffer *s = vecs->Src(i),*d = vecs->Dst(i); + p.rsdt = s->Pointer(),p.rss = s->Channels(); + + if(d) p.rddt = d->Pointer(),p.rds = d->Channels(); + else p.rddt = p.rsdt,p.rds = p.rss; + + for(I bi = 0; bi < vecs->ArgBlks(); ++bi) { + VBuffer *a = vecs->Arg(i,bi); + p.arg[bi].SetV(a?a->Pointer():NULL,a?a->Channels():0); + } + + if(!symm) + p.symm = -1; + else { + const I hcnt = p.frames/2; + p.oddrem = p.frames != 2*hcnt; + + if((p.symm = si) == 0) { + p.frames = hcnt+(p.oddrem?1:0); + } + else { + const I r = p.frames-hcnt; + p.frames = hcnt; + p.rsdt += r*p.rss,p.rddt += r*p.rds; + + // What to do with arguments in symmetric mode? + // let the object decide!! + } + } + + { // ---- Check out and try to resolve overlap situation ------------ + + BL sovr = p.SR_In(); // check whether dst is before src + if(p.HasArg()) { + // has argument + if(sovr) { + // src/dst needs reversal -> check if ok for arg/dst + p.ovrlap = true; + + if(p.AR_Can()) + p.R_Rev(); // Revert vectors + else { + post("%s - vector overlap situation can't be resolved",p.opname); + ok = false; + } + } + else if(p.AR_In()) { + // arg/dst needs reversal -> check if ok for src/dst + p.ovrlap = true; + + if(p.SR_Can()) + p.R_Rev(); // Revert vectors + else { + post("%s - vector overlap situation can't be resolved",p.opname); + ok = false; + } + } + } + else { // No arg + if(sovr) { + p.ovrlap = true; + p.R_Rev(); // if overlapping revert vectors + } + else + p.ovrlap = p.SR_Ovr(); + } + } + + ok = fun(p); + +#ifdef FLEXT_THREAD + flext_base::ThrYield(); +#endif + } + return ok?vecs->ResVasp():NULL; +} + + +/*! \brief Run the operation on the various complex vector pairs. + + \param vecs src/arg/dst vector block + \param fun operative function + \param p parameter block for operative function + \return normalized vasp or NULL on error + + \todo set overlap flag + + \remark operative function must be capable of handling reversed direction +*/ +Vasp *VaspOp::DoOp(CVecBlock *vecs,VecOp::opfun *fun,OpParam &p,BL symm) +{ + BL ok = true; + + if(vecs->ArgBlks() && (!p.arg || p.args < vecs->ArgBlks())) { + post("%s - not enough argument blocks",p.opname); + ok = false; + } + + const I scnt = symm?2:1; + for(I i = 0; ok && i < vecs->Pairs(); ++i) + for(I si = 0; ok && si < scnt; ++si) { + p.frames = vecs->Frames(); + + VBuffer *rsv = vecs->ReSrc(i),*isv = vecs->ImSrc(i); + p.rsdt = rsv->Pointer(),p.rss = rsv->Channels(); + p.isdt = isv->Pointer(),p.iss = isv->Channels(); + + VBuffer *rdv = vecs->ReDst(i),*idv = vecs->ImDst(i); + if(rdv) { + p.rddt = rdv->Pointer(),p.rds = rdv->Channels(); + if(idv) p.iddt = idv->Pointer(),p.ids = idv->Channels(); + else p.iddt = NULL; //,p.ids = 0; // Can that be NULL?? + } + else { + p.rddt = p.rsdt,p.rds = p.rss,p.iddt = p.isdt,p.ids = p.iss; + } + + for(I bi = 0; bi < vecs->ArgBlks(); ++bi) { + VBuffer *rav = vecs->ReArg(i,bi),*iav = vecs->ImArg(i,bi); + p.arg[bi].SetV(rav?rav->Pointer():NULL,rav?rav->Channels():0,iav?iav->Pointer():NULL,iav?iav->Channels():0); + } + + if(!symm) + p.symm = -1; + else { + const I hcnt = p.frames/2; + p.oddrem = p.frames != 2*hcnt; + + if((p.symm = si) == 0) { + p.frames = hcnt+(p.oddrem?1:0); + } + else { + const I r = p.frames-hcnt; + p.frames = hcnt; + p.rsdt += r*p.rss,p.isdt += r*p.iss; + p.rddt += r*p.rds; + if(p.iddt) p.iddt += r*p.ids; // Can that be NULL?? + + // What to do with arguments? + // let objects decide!! + } + } + + { // ---- Check out and try to resolve overlap situation ------------ + + BL sovr = p.SR_In(); // check whether dst is before src + if(sovr && !p.SI_Can()) { + post("%s - src/dst overlap of re/im vectors not resolvable",p.opname); + ok = false; + } + + if(ok && p.HasArg()) { + // has argument + if(sovr) { + // src/dst needs reversal -> check if ok for arg/dst + p.ovrlap = true; + + if(p.AR_Can() && p.AI_Can()) + p.C_Rev(); // Revert vectors + else { + post("%s - vector overlap situation can't be resolved",p.opname); + ok = false; + } + } + else if(p.AR_In() || p.AI_In()) { + // arg/dst needs reversal -> check if ok for src/dst + p.ovrlap = true; + + if(p.AR_Can() && p.AI_Can() && p.SR_Can() && p.SI_Can()) + p.C_Rev(); // Revert vectors + else { + post("%s - vector overlap situation can't be resolved",p.opname); + ok = false; + } + } + } + else { // No arg + if(sovr) { + p.ovrlap = true; + p.C_Rev(); // if overlapping revert vectors + } + else + p.ovrlap = p.SR_Ovr() || p.SI_Ovr(); + } + } + + ok = fun(p); + +#ifdef FLEXT_THREAD + flext_base::ThrYield(); +#endif + } + return ok?vecs->ResVasp():NULL; +} + + + diff --git a/externals/grill/vasp/source/rdx2fft.cpp b/externals/grill/vasp/source/rdx2fft.cpp new file mode 100644 index 00000000..b4ecf6c9 --- /dev/null +++ b/externals/grill/vasp/source/rdx2fft.cpp @@ -0,0 +1,82 @@ +#include <math.h> + +#define PI 3.1415926535897932384f + +////////////////////////////////////////////////////////////////////////// + +/* calculate bidirectional fourier transform of complex data radix 2 */ +/* adapted from subroutine FOUREA listed in */ +/* Programs for Digital Signal Processing */ +/* edited by Digital Signal Processing Committee */ +/* IEEE Acoustics Speech and Signal Processing Committee */ +/* Chapter 1 Section 1.1 Page 1.1-4,5 */ +/* direct -1 forward +1 reverse */ + +bool fft_bidir_complex_radix2(int size,float *real,float *imag,int direct) +{ + int i,j,m,mmax,istep; + float c,s,treal,timag,theta; + + /* compute transform */ + + j=1; + for(i=1;i<=size;i++) + { + if(i<j) + { + treal=real[j-1]; + timag=imag[j-1]; + real[j-1]=real[i-1]; + imag[j-1]=imag[i-1]; + real[i-1]=treal; + imag[i-1]=timag; + } + m=size/2; + while(j>m) + { + j-=m; + m=(m+1)/2; + } + j+=m; + } + mmax=1; + while(size>mmax) + { + istep=2*mmax; + for(m=1;m<=mmax;m++) + { + theta=PI*(float)direct*(float)(m-1)/(float)mmax; + c=(float)cos(theta); + s=(float)sin(theta); + for(i=m;i<=size;i+=istep) + { + j=i+mmax; + treal=real[j-1]*c-imag[j-1]*s; + timag=imag[j-1]*c+real[j-1]*s; + real[j-1]=real[i-1]-treal; + imag[j-1]=imag[i-1]-timag; + real[i-1]+=treal; + imag[i-1]+=timag; + } + } + mmax=istep; + } + + return true; +} + +#if 0 +/* calculate forward fourier transform of complex data radix 2 */ + +bool fft_fwd_complex_radix2(int size,float *real,float *imag) +{ + return fft_bidir_complex_radix2(size,real,imag,-1); +} + +/* calculate inverse fourier transform of complex data radix 2 */ + +bool fft_inv_complex_radix2(int size,float *real,float *imag) +{ + return fft_bidir_complex_radix2(size,real,imag,1); +} +#endif diff --git a/externals/grill/vasp/source/rvfft.cpp b/externals/grill/vasp/source/rvfft.cpp new file mode 100644 index 00000000..b7d81c93 --- /dev/null +++ b/externals/grill/vasp/source/rvfft.cpp @@ -0,0 +1,357 @@ +#include <math.h> + +#ifdef _MSC_VER +#pragma warning(disable: 4244) +#endif + +#define PI 3.14159265358979 + +///////////////////////////////////////////////////////// +// Sorensen in-place split-radix FFT for real values +// data: array of floats: +// re(0),re(1),re(2),...,re(size-1) +// +// output: +// re(0),re(1),re(2),...,re(size/2),im(size/2-1),...,im(1) +// normalized by array length +// +// Source: +// Sorensen et al: Real-Valued Fast Fourier Transform Algorithms, +// IEEE Trans. ASSP, ASSP-35, No. 6, June 1987 + +void realfft_split(float *data,int n) +{ + + int i,j,k,i5,i6,i7,i8,i0,id,i1,i2,i3,i4,n2,n4,n8; + float t1,t2,t3,t4,t5,t6,a3,ss1,ss3,cc1,cc3,a,e,sqrt2; + + sqrt2=sqrt(2.0); + n4=n-1; + + //data shuffling + for (i=0,j=0,n2=n/2; i<n4 ; i++){ + if (i<j){ + t1=data[j]; + data[j]=data[i]; + data[i]=t1; + } + k=n2; + while (k<=j){ + j-=k; + k>>=1; + } + j+=k; + } + +/*----------------------*/ + + //length two butterflies + i0=0; + id=4; + do{ + for (; i0<n4; i0+=id){ + i1=i0+1; + t1=data[i0]; + data[i0]=t1+data[i1]; + data[i1]=t1-data[i1]; + } + id<<=1; + i0=id-2; + id<<=1; + } while ( i0<n4 ); + + /*----------------------*/ + //L shaped butterflies +n2=2; +for(k=n;k>2;k>>=1){ + n2<<=1; + n4=n2>>2; + n8=n2>>3; + e = 2*PI/(n2); + i1=0; + id=n2<<1; + do{ + for (; i1<n; i1+=id){ + i2=i1+n4; + i3=i2+n4; + i4=i3+n4; + t1=data[i4]+data[i3]; + data[i4]-=data[i3]; + data[i3]=data[i1]-t1; + data[i1]+=t1; + if (n4!=1){ + i0=i1+n8; + i2+=n8; + i3+=n8; + i4+=n8; + t1=(data[i3]+data[i4])/sqrt2; + t2=(data[i3]-data[i4])/sqrt2; + data[i4]=data[i2]-t1; + data[i3]=-data[i2]-t1; + data[i2]=data[i0]-t2; + data[i0]+=t2; + } + } + id<<=1; + i1=id-n2; + id<<=1; + } while ( i1<n ); + a=e; + for (j=2; j<=n8; j++){ + a3=3*a; + cc1=cos(a); + ss1=sin(a); + cc3=cos(a3); + ss3=sin(a3); + a=j*e; + i=0; + id=n2<<1; + do{ + for (; i<n; i+=id){ + i1=i+j-1; + i2=i1+n4; + i3=i2+n4; + i4=i3+n4; + i5=i+n4-j+1; + i6=i5+n4; + i7=i6+n4; + i8=i7+n4; + t1=data[i3]*cc1+data[i7]*ss1; + t2=data[i7]*cc1-data[i3]*ss1; + t3=data[i4]*cc3+data[i8]*ss3; + t4=data[i8]*cc3-data[i4]*ss3; + t5=t1+t3; + t6=t2+t4; + t3=t1-t3; + t4=t2-t4; + t2=data[i6]+t6; + data[i3]=t6-data[i6]; + data[i8]=t2; + t2=data[i2]-t3; + data[i7]=-data[i2]-t3; + data[i4]=t2; + t1=data[i1]+t5; + data[i6]=data[i1]-t5; + data[i1]=t1; + t1=data[i5]+t4; + data[i5]-=t4; + data[i2]=t1; + } + id<<=1; + i=id-n2; + id<<=1; + } while(i<n); + } + } +} + + +///////////////////////////////////////////////////////// +// Sorensen in-place inverse split-radix FFT for real values +// data: array of doubles: +// re(0),re(1),re(2),...,re(size/2),im(size/2-1),...,im(1) +// +// output: +// re(0),re(1),re(2),...,re(size-1) +// NOT normalized by array length +// +// Source: +// Sorensen et al: Real-Valued Fast Fourier Transform Algorithms, +// IEEE Trans. ASSP, ASSP-35, No. 6, June 1987 + +void irealfft_split(float *data,int n){ + + int i,j,k,i5,i6,i7,i8,i0,id,i1,i2,i3,i4,n2,n4,n8,n1; + float t1,t2,t3,t4,t5,a3,ss1,ss3,cc1,cc3,a,e,sqrt2; + + sqrt2=sqrt(2.0); + +n1=n-1; +n2=n<<1; +for(k=n;k>2;k>>=1){ + id=n2; + n2>>=1; + n4=n2>>2; + n8=n2>>3; + e = 2*PI/(n2); + i1=0; + do{ + for (; i1<n; i1+=id){ + i2=i1+n4; + i3=i2+n4; + i4=i3+n4; + t1=data[i1]-data[i3]; + data[i1]+=data[i3]; + data[i2]*=2; + data[i3]=t1-2*data[i4]; + data[i4]=t1+2*data[i4]; + if (n4!=1){ + i0=i1+n8; + i2+=n8; + i3+=n8; + i4+=n8; + t1=(data[i2]-data[i0])/sqrt2; + t2=(data[i4]+data[i3])/sqrt2; + data[i0]+=data[i2]; + data[i2]=data[i4]-data[i3]; + data[i3]=2*(-t2-t1); + data[i4]=2*(-t2+t1); + } + } + id<<=1; + i1=id-n2; + id<<=1; + } while ( i1<n1 ); + a=e; + for (j=2; j<=n8; j++){ + a3=3*a; + cc1=cos(a); + ss1=sin(a); + cc3=cos(a3); + ss3=sin(a3); + a=j*e; + i=0; + id=n2<<1; + do{ + for (; i<n; i+=id){ + i1=i+j-1; + i2=i1+n4; + i3=i2+n4; + i4=i3+n4; + i5=i+n4-j+1; + i6=i5+n4; + i7=i6+n4; + i8=i7+n4; + t1=data[i1]-data[i6]; + data[i1]+=data[i6]; + t2=data[i5]-data[i2]; + data[i5]+=data[i2]; + t3=data[i8]+data[i3]; + data[i6]=data[i8]-data[i3]; + t4=data[i4]+data[i7]; + data[i2]=data[i4]-data[i7]; + t5=t1-t4; + t1+=t4; + t4=t2-t3; + t2+=t3; + data[i3]=t5*cc1+t4*ss1; + data[i7]=-t4*cc1+t5*ss1; + data[i4]=t1*cc3-t2*ss3; + data[i8]=t2*cc3+t1*ss3; + } + id<<=1; + i=id-n2; + id<<=1; + } while(i<n1); + } + } + + /*----------------------*/ + i0=0; + id=4; + do{ + for (; i0<n1; i0+=id){ + i1=i0+1; + t1=data[i0]; + data[i0]=t1+data[i1]; + data[i1]=t1-data[i1]; + } + id<<=1; + i0=id-2; + id<<=1; + } while ( i0<n1 ); + +/*----------------------*/ + +//data shuffling + for (i=0,j=0,n2=n/2; i<n1 ; i++){ + if (i<j){ + t1=data[j]; + data[j]=data[i]; + data[i]=t1; + } + k=n2; + while (k<=j){ + j-=k; + k>>=1; + } + j+=k; + } +} + + +#if 0 +///////////////////////////////////////////////////////// +// Sorensen in-place radix-2 FFT for real values +// data: array of floats: +// re(0),re(1),re(2),...,re(size-1) +// +// output: +// re(0),re(1),re(2),...,re(size/2),im(size/2-1),...,im(1) +// normalized by array length +// +// Source: +// Sorensen et al: Real-Valued Fast Fourier Transform Algorithms, +// IEEE Trans. ASSP, ASSP-35, No. 6, June 1987 + +void realfft_radix2(float *data,int n){ + + float xt,a,e, t1, t2, cc, ss; + int i, j, k, n1, n2, n3, n4, i1, i2, i3, i4; + + n4=n-1; + //data shuffling + for (i=0,j=0,n2=n/2; i<n4 ; i++){ + if (i<j){ + xt=data[j]; + data[j]=data[i]; + data[i]=xt; + } + k=n2; + while (k<=j){ + j-=k; + k>>=1; + } + j+=k; + } + +/* -------------------- */ + for (i=0; i<n; i += 2) + { + xt = data[i]; + data[i] = xt + data[i+1]; + data[i+1] = xt - data[i+1]; + } +/* ------------------------ */ + n2 = 1; + for (k=n;k>2;k>>=1){ + n4 = n2; + n2 = n4 << 1; + n1 = n2 << 1; + e = 2*PI/(n1); + for (i=0; i<n; i+=n1){ + xt = data[i]; + data[i] = xt + data[i+n2]; + data[i+n2] = xt-data[i+n2]; + data[i+n4+n2] = -data[i+n4+n2]; + a = e; + n3=n4-1; + for (j = 1; j <=n3; j++){ + i1 = i+j; + i2 = i - j + n2; + i3 = i1 + n2; + i4 = i - j + n1; + cc = cos(a); + ss = sin(a); + a += e; + t1 = data[i3] * cc + data[i4] * ss; + t2 = data[i3] * ss - data[i4] * cc; + data[i4] = data[i2] - t2; + data[i3] = -data[i2] - t2; + data[i2] = data[i1] - t1; + data[i1] += t1; + } + } + } +} +#endif diff --git a/externals/grill/vasp/source/util.cpp b/externals/grill/vasp/source/util.cpp new file mode 100644 index 00000000..c487e3d1 --- /dev/null +++ b/externals/grill/vasp/source/util.cpp @@ -0,0 +1,12 @@ +#include "util.h" +#include <math.h> + +R arg(R re,R im) +{ + if(re) + return fmod(atan(im/re)+(re < 0?2*PI:PI),2*PI)-PI; + else + if(im || re) return im > 0?PI/2:-PI/2; + else return 0; +} + diff --git a/externals/grill/vasp/source/util.h b/externals/grill/vasp/source/util.h new file mode 100644 index 00000000..1b41c447 --- /dev/null +++ b/externals/grill/vasp/source/util.h @@ -0,0 +1,33 @@ +/* + +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. + +*/ + +#ifndef __VASP_UTIL_H +#define __VASP_UTIL_H + +#include "main.h" + +#ifndef PI +#define PI 3.1415926535897932385 +#endif + +#define BIG 1.e10 + + +R arg(R re,R im); +inline R arg(const CX &c) { return arg(c.real,c.imag); } +inline F sqabs(F re,F im) { return re*re+im*im; } +inline F sqabs(const CX &c) { return sqabs(c.real,c.imag); } +inline F sgn(F x) { return x < 0.?-1.F:1.F; } +inline V swap(F &a,F &b) { F c = a; a = b; b = c; } + +inline I min(I a,I b) { return a < b?a:b; } +inline I max(I a,I b) { return a > b?a:b; } + +#endif diff --git a/externals/grill/vasp/source/vasp.cpp b/externals/grill/vasp/source/vasp.cpp new file mode 100644 index 00000000..35bbc5a2 --- /dev/null +++ b/externals/grill/vasp/source/vasp.cpp @@ -0,0 +1,353 @@ +/* + +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 "classes.h" +#include "util.h" +#include "buflib.h" + +/////////////////////////////////////////////////////////////////////////// +// Vasp class +/////////////////////////////////////////////////////////////////////////// + +Vasp::Ref::Ref(VBuffer &b): sym(b.Symbol()),chn(b.Channel()),offs(b.Offset()) {} +Vasp::Ref::Ref(VSymbol &s,I c,I o): sym(s),chn(c),offs(o) {} +Vasp::Ref::~Ref() {} + +Vasp::Ref &Vasp::Ref::operator =(const Ref &r) +{ + sym = r.sym,chn = r.chn,offs = r.offs; + return *this; +} + +V Vasp::Ref::Symbol(const VSymbol &s) { sym = s; } + + +Vasp::Vasp(): + refs(0),chns(0),ref(NULL), + frames(0) +{ +} + +Vasp::Vasp(I argc,const t_atom *argv): + refs(0),chns(0),ref(NULL), + frames(0) +{ + operator ()(argc,argv); +} + +Vasp::Vasp(const Vasp &v): + refs(0),chns(0),ref(NULL), + frames(0) +{ + operator =(v); +} + +Vasp::Vasp(I fr,const Ref &r): + refs(0),chns(0),ref(NULL), + frames(fr) +{ + operator +=(r); +} + + +Vasp::~Vasp() +{ + if(ref) delete[] ref; +} + + +BL Vasp::ChkArgs(I argc,const t_atom *argv) +{ + I ix = 0; + + // vasp keyword + t_symbol *v = ix < argc?flext::GetASymbol(argv[ix]):NULL; + if(v && v == vasp_base::sym_vasp) ix++; // if it is "vasp" ignore it + + // length argument + if(argc > ix && flext::CanbeInt(argv[ix])) ix++; + + while(argc > ix) { + // check for symbol + t_symbol *bsym = flext::GetASymbol(argv[ix]); + if(!bsym || !flext::GetString(bsym) || !flext::GetString(bsym)[0]) { // expect a symbol + // not symbol -> bail out + return false; + } + else + ix++; + + // check for offset + if(argc > ix && flext::CanbeInt(argv[ix])) ix++; + + // check for channel + if(argc > ix && flext::CanbeInt(argv[ix])) ix++; + } + + return true; +} + +V Vasp::Resize(I rcnt) { + if(!ref) { + ref = new Ref[refs = rcnt]; + chns = 0; + } + else if(rcnt > refs) { + Ref *rnew = new Ref[refs = rcnt]; + for(I ix = 0; ix < chns; ++ix) rnew[ix] = ref[ix]; + delete[] ref; + ref = rnew; + } +} + + + +Vasp &Vasp::operator =(const Vasp &v) +{ + if(!v.Ok()) + Clear(); + else { + frames = v.frames; + if(!ref || v.chns > refs) { + if(ref) delete[] ref; + ref = new Ref[refs = v.chns]; + } + + chns = v.chns; + for(I ix = 0; ix < chns; ++ix) { + ref[ix] = v.ref[ix]; + } + } + + return *this; +} + + +Vasp &Vasp::operator +=(const Ref &r) +{ + Resize(chns+1); + ref[chns++] = r; + return *this; +} + + +Vasp &Vasp::operator +=(const Vasp &v) +{ + if(v.Ok()) { + if(!Ok()) *this = v; + else { + if(Frames() != v.Frames()) { + post("vasp - Frame count of joined vasps is different - taking the minimum"); + Frames(min(Frames(),v.Frames())); + } + + Resize(Vectors()+v.Vectors()); + for(I i = 0; i < v.Vectors(); ++i) *this += v.Vector(i); + } + } + return *this; +} + +// parse argument list +Vasp &Vasp::operator ()(I argc,const t_atom *argv) +{ + BL lenset = false; + I ix = 0; + + I maxneeded = argc; // maximum number of ref'd buffers + // rather use a temp storage + if(!ref || refs < maxneeded) { + if(ref) delete[] ref; + ref = new Ref[refs = maxneeded]; + } + + t_symbol *v = ix < argc?flext::GetASymbol(argv[ix]):NULL; + if(v && v == vasp_base::sym_vasp) ix++; // if it is "vasp" ignore it + + if(argc > ix && flext::CanbeInt(argv[ix])) { + frames = flext::GetAInt(argv[ix]); + lenset = true; + ix++; + } + else + frames = -1; + + chns = 0; + while(argc > ix) { + t_symbol *bsym = flext::GetASymbol(argv[ix]); + if(!bsym || !flext::GetString(bsym) || !flext::GetString(bsym)[0]) { // expect a symbol + Clear(); + return *this; + } + else + ix++; + + // is a symbol! + Ref &r = ref[chns]; + r.Symbol(VSymbol(bsym)); + + if(argc > ix && flext::CanbeInt(argv[ix])) { + r.Offset((I)flext::GetAInt(argv[ix])); + ix++; + } + else + r.Offset(0); + + if(argc > ix && flext::CanbeInt(argv[ix])) { + r.Channel((I)flext::GetAInt(argv[ix])); + ix++; + } + else + r.Channel(0); + + chns++; + } + + if(!lenset) { + // set length to maximum! + // or let it be -1 to represent the maximum?! + frames = -1; + // if len is already set then where to check for oversize? + } + + return *this; +} + + +VBuffer *Vasp::Buffer(I ix) const +{ + if(ix >= Vectors()) + return NULL; + else { + const Ref &r = Vector(ix); + VBuffer *ret = BufLib::Get(r.Symbol(),r.Channel(),Frames(),r.Offset()); + return ret; + } +} + +// generate Vasp list of buffer references +flext::AtomList *Vasp::MakeList(BL withvasp) +{ + I voffs = withvasp?1:0; + I needed = voffs+1+Vectors()*3; + flext::AtomList *ret = new flext::AtomList(needed); + + if(withvasp) + flext::SetSymbol((*ret)[0],vasp_base::sym_vasp); // VASP + + flext::SetInt((*ret)[voffs],frames); // frames + + for(I ix = 0; ix < Vectors(); ++ix) { + Ref &r = Vector(ix); + flext::SetSymbol((*ret)[voffs+1+ix*3],r.Symbol().Symbol()); // buf + flext::SetInt((*ret)[voffs+2+ix*3],r.Offset()); // offs + flext::SetInt((*ret)[voffs+3+ix*3],r.Channel()); // chn + } + + return ret; +} + + +V Vasp::Refresh() +{ + for(I i = 0; i < Vectors(); ++i) { + VBuffer *vb = Buffer(i); + if(vb) { + vb->Refresh(); + delete vb; + } + } +} + +V Vasp::Offset(I o) +{ + for(I i = 0; i < Vectors(); ++i) Vector(i).Offset(o); +} + +V Vasp::OffsetD(I od) +{ + for(I i = 0; i < Vectors(); ++i) Vector(i).OffsetD(od); +} + + +V Vasp::Channel(I c) +{ + for(I i = 0; i < Vectors(); ++i) Vector(i).Channel(c); +} + + +V Vasp::Size(I s) +{ + for(I i = 0; i < Vectors(); ++i) { + VBuffer *buf = Buffer(i); + if(buf) { + buf->Frames(s,true); + delete buf; + } + } +} + +V Vasp::SizeD(I sd) +{ + for(I i = 0; i < Vectors(); ++i) { + VBuffer *buf = Buffer(i); + if(buf) { + I s = buf->Frames()+sd; + buf->Frames(s >= 0?s:0,true); + delete buf; + } + } +} + + +V Vasp::SizeM(R f) +{ + for(I i = 0; i < Vectors(); ++i) { + VBuffer *buf = Buffer(i); + if(buf) { + I s = (I)(buf->Frames()*f); + buf->Frames(s >= 0?s:0,true); + delete buf; + } + } +} + +BL Vasp::Check() const +{ + BL ok = true; + for(I i = 0; ok && i < Vectors(); ++i) { + VBuffer *buf = Buffer(i); + if(!buf) + ok = false; + else { + ok = buf->Data() != NULL; + delete buf; + } + } + return ok; +} + +I Vasp::ChkFrames() const +{ + if(Vectors() == 0) return 0; + + I frms = -1; + for(I i = 0; i < Vectors(); ++i) { + VBuffer *buf = Buffer(i); + if(buf) { + I f = buf->Length(); + if(frms < 0 || f < frms) frms = f; + delete buf; + } + } + + return frms < 0?0:frms; +} + diff --git a/externals/grill/vasp/source/vasp.h b/externals/grill/vasp/source/vasp.h new file mode 100644 index 00000000..ab4530c7 --- /dev/null +++ b/externals/grill/vasp/source/vasp.h @@ -0,0 +1,142 @@ +/* + +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. + +*/ + +#ifndef __VASP__H +#define __VASP__H + +#include "vbuffer.h" + +class Vasp +{ +public: + class Ref { + public: + Ref(): sym(NULL) {} + Ref(VBuffer &b); + Ref(VSymbol &s,I c,I o); + Ref(const Ref &r) { operator =(r); } + ~Ref(); + + Ref &operator =(const Ref &r); + + V Clear() { sym.Clear(); } + BL Ok() const { return sym.Ok(); } + + VSymbol &Symbol() { return sym; } + const VSymbol &Symbol() const { return sym; } + V Symbol(const VSymbol &s); + I Channel() const { return chn; } + V Channel(I c) { chn = c; } + I Offset() const { return offs; } + V Offset(I o) { offs = o; } + V OffsetD(I o) { offs += o; } + + protected: + VSymbol sym; + I chn; + I offs; // counted in frames + }; + + Vasp(); + Vasp(I argc,const t_atom *argv); + Vasp(const Vasp &v); + Vasp(I frames,const Ref &r); + ~Vasp(); + + static BL ChkArgs(I argc,const t_atom *argv); + + const C *thisName() const { return typeid(*this).name(); } + + // check if vasp reference is valid + BL Check() const; + + Vasp &operator =(const Vasp &v); + Vasp &operator ()(I argc,const t_atom *argv /*,BL withvasp = false*/); + + // add another vector + Vasp &operator +=(const Ref &r); + // add vectors of another vasp + Vasp &operator +=(const Vasp &v); + + // set used channels to 0 + Vasp &Clear() { frames = 0; chns = 0; return *this; } + + // used vectors + I Vectors() const { return chns; } + + // length of the vasp (in frames) + I Frames() const { return frames; } + // set frame count + V Frames(I fr) { frames = fr; } + // set frame count differentially + V FramesD(I frd) { if(frames >= 0) frames += frd; } + // set frame count + V FramesM(R f) { if(frames >= 0) frames = (int)(frames*f); } + // set frame count + V FramesR(R f) { if(f) FramesM(1./f); else Frames(0); } + + // set buffer sizes + V Size(I fr); + // set frame count differentially + V SizeD(I frd); + // set frame count + V SizeM(R f); + // set frame count + V SizeR(R f) { if(f) SizeM(1./f); else Size(0); } + + // actual length of the vasp (in frames) + I ChkFrames() const; + + // set offset(s) + V Offset(I fr); + // set offset(s) differentially + V OffsetD(I fr); + + // set channel(s) + V Channel(I ch); + + BL Ok() const { return ref && Vectors() > 0; } + BL IsComplex() const { return ref && Vectors() >= 2 && ref[1].Ok(); } + + // get any vector - test if in range 0..Vectors()-1! + const Ref &Vector(I ix) const { return ref[ix]; } + Ref &Vector(I ix) { return ref[ix]; } + + // get real part - be sure that Ok! + const Ref &Real() const { return Vector(0); } + Ref &Real() { return Vector(0); } + + // get imaginary part - be sure that Complex! + const Ref &Imag() const { return Vector(1); } + Ref &Imag() { return Vector(1); } + + // get buffer associated to a channel + VBuffer *Buffer(I ix) const; + + // Real/Complex + VBuffer *ReBuffer() const { return Buffer(0); } + VBuffer *ImBuffer() const { return Buffer(1); } + + // prepare and reference t_atom list for output + flext::AtomList *MakeList(BL withvasp = true); + + // make a graphical update of all buffers in vasp + V Refresh(); + +protected: + I frames; // length counted in frames + I chns; // used channels + I refs; // allocated channels (>= chns) + Ref *ref; + + V Resize(I rcnt); +}; + +#endif diff --git a/externals/grill/vasp/source/vbuffer.cpp b/externals/grill/vasp/source/vbuffer.cpp new file mode 100644 index 00000000..137e066c --- /dev/null +++ b/externals/grill/vasp/source/vbuffer.cpp @@ -0,0 +1,40 @@ +#include "vbuffer.h" +#include "buflib.h" + +V VSymbol::Inc() { if(sym) BufLib::IncRef(sym); } +V VSymbol::Dec() { if(sym) BufLib::DecRef(sym); } + +/////////////////////////////////////////////////////////////////////////// +// SysBuf class +/////////////////////////////////////////////////////////////////////////// + +SysBuf &SysBuf::Set(const VSymbol &s,I c,I l,I o) +{ + buf.Set(s.Symbol()); + + chn = c; + if(chn > Channels()) { + I chn1 = Channels()-1; + post("vasp - buffer %s: Channel index (%i) is out of range, set to highest (%i)",s.Name(),chn,chn1); + chn = chn1; // simply correct the channel?? + } + offs = o; + if(offs < 0) { + post("vasp - buffer %s: Offset (%i) is out of range, set to 0",s.Name(),offs); + offs = 0; + } + if(offs > Frames()) { +// post("vasp - buffer %s: Offset (%i) is out of range, set to %i",s.Name(),offs,Frames()); + offs = Frames(); + } + len = l >= 0?l:Frames(); + if(offs+len > Frames()) { + I len1 = Frames()-offs; + if(l >= 0) post("vasp - buffer %s: Length (%i) is out of range, corrected to %i",s.Name(),len,len1); + len = len1; + } + + return *this; +} + + diff --git a/externals/grill/vasp/source/vbuffer.h b/externals/grill/vasp/source/vbuffer.h new file mode 100644 index 00000000..c3303099 --- /dev/null +++ b/externals/grill/vasp/source/vbuffer.h @@ -0,0 +1,127 @@ +/* + +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. + +*/ + +#ifndef __VASP_VBUFFER_H +#define __VASP_VBUFFER_H + +#include "main.h" + +class VSymbol +{ +public: + VSymbol(t_symbol *s = NULL): sym(s) { Inc(); } + VSymbol(const VSymbol &s): sym(s.sym) { Inc(); } + ~VSymbol() { Dec(); } + + BL Ok() const { return sym != NULL; } + V Clear() { Dec(); sym = NULL; } + +// V *Thing() { return sym?flext_base::GetThing(sym):NULL; } +// V Thing(V *th) { if(sym) flext_base::GetThing(sym); } + + VSymbol &operator =(const VSymbol &s) { Dec(); sym = s.sym; Inc(); return *this; } + + t_symbol *Symbol() { return sym; } + const t_symbol *Symbol() const { return sym; } + const C *Name() const { return flext::GetAString(Symbol()); } + +protected: + V Inc(); + V Dec(); + + t_symbol *sym; +}; + +class VBuffer +{ +public: + virtual ~VBuffer() {} + + virtual BL Ok() const = 0; + virtual I Frames() const = 0; + virtual V Frames(I fr,BL keep) = 0; + + virtual I Channels() const = 0; + virtual S *Data() = 0; + + virtual V Refresh() {} + virtual V Dirty() {} + + S *Pointer() { return Data()+Offset()*Channels()+Channel(); } + + virtual VSymbol Symbol() const = 0; + const C *Name() const { return Symbol().Name(); } + + I Channel() const { return chn; } + V Channel(I c) { chn = c; } + + I Offset() const { return offs; } + V Offset(I o) { offs = o; } + + I Length() const { return len; } + V Length(I l) { len = l; } + +protected: + VBuffer(I c = 0,I l = 0,I o = 0): chn(c),offs(o),len(l) {} + + I chn,offs,len; +}; + + +class SysBuf: + public VBuffer +{ +public: + SysBuf(const VSymbol &s,I chn = 0,I len = -1,I offs = 0) { Set(s,chn,len,offs); } + + virtual BL Ok() const { return buf.Ok(); } + virtual V Refresh() { buf.Dirty(true); } + virtual V Dirty() { buf.Dirty(false); } + + virtual VSymbol Symbol() const { return buf.Symbol(); } + + SysBuf &Set(const VSymbol &s,I chn = 0,I len = -1,I offs = 0); + + virtual I Frames() const { return buf.Frames(); } + virtual V Frames(I fr,BL keep) { buf.Frames(fr,keep); } + + virtual I Channels() const { return buf.Channels(); } + virtual S *Data() { return buf.Data(); } + +protected: + flext::buffer buf; +}; + + +class BufEntry; + +class ImmBuf: + public VBuffer +{ +public: + ImmBuf(I len); + ImmBuf(BufEntry *e,I len = -1,I offs = 0); + + virtual BL Ok() const { return entry != NULL; } + + virtual VSymbol Symbol() const; + + virtual I Frames() const; + virtual V Frames(I fr,BL keep); + + virtual I Channels() const { return 1; } + virtual S *Data(); + +protected: + BufEntry *entry; +}; + + +#endif diff --git a/externals/grill/vasp/source/vecblk.cpp b/externals/grill/vasp/source/vecblk.cpp new file mode 100644 index 00000000..1efc3981 --- /dev/null +++ b/externals/grill/vasp/source/vecblk.cpp @@ -0,0 +1,49 @@ +#include "vecblk.h" +//#include <math.h> + + +/////////////////////////////////////////////////////////////////////////// +// VecBlock class +/////////////////////////////////////////////////////////////////////////// + +VecBlock::VecBlock(BL cx,I msrc,I mdst,I marg,I blarg): + cplx(cx),asrc(msrc),barg(blarg),aarg(marg*blarg),adst(mdst) +{ + I i,all = asrc+aarg*blarg+adst; + vecs = new VBuffer *[all]; + for(i = 0; i < all; ++i) vecs[i] = NULL; +} + +VecBlock::~VecBlock() +{ + if(vecs) { + I all = asrc+aarg*barg+adst; + for(I i = 0; i < all; ++i) + if(vecs[i]) delete vecs[i]; + delete[] vecs; + } +} + +Vasp *VecBlock::_DstVasp(I n) +{ + Vasp *ret = new Vasp; + ret->Frames(Frames()); + for(I i = 0; i < n; ++i) *ret += Vasp::Ref(*_Dst(i)); + return ret; +} + +Vasp *VecBlock::_SrcVasp(I n) +{ + Vasp *ret = new Vasp; + ret->Frames(Frames()); + for(I i = 0; i < n; ++i) *ret += Vasp::Ref(*_Src(i)); + return ret; +} + +Vasp *VecBlock::_ResVasp(I n) +{ + return _Dst(0)?_DstVasp(n):_SrcVasp(n); +} + + + diff --git a/externals/grill/vasp/source/vecblk.h b/externals/grill/vasp/source/vecblk.h new file mode 100644 index 00000000..a938558e --- /dev/null +++ b/externals/grill/vasp/source/vecblk.h @@ -0,0 +1,105 @@ +/* + +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. + +*/ + +#ifndef __VASP_VECBLK_H +#define __VASP_VECBLK_H + +#include "vasp.h" + +class VecBlock +{ +public: + + I Frames() const { return frms; } + V Frames(I fr) { frms = fr; } + I ArgFrames() const { return afrms; } + V ArgFrames(I fr) { afrms = fr; } + I ArgBlks() const { return barg; } + + BL Complex() { return cplx; } + +protected: + VecBlock(BL cplx,I msrc,I mdst,I marg,I blarg); + ~VecBlock(); + + Vasp *_SrcVasp(I n); + Vasp *_DstVasp(I n); + Vasp *_ResVasp(I n); // either Dst or Src + + VBuffer *_Src(I ix) { return vecs[ix]; } + VBuffer *_Dst(I ix) { return vecs[asrc+aarg*barg+ix]; } + V _Src(I ix,VBuffer *v) { vecs[ix] = v; } + V _Dst(I ix,VBuffer *v) { vecs[asrc+aarg*barg+ix] = v; } + + VBuffer *_Arg(I ix,I bl = 0) { return vecs[asrc+bl*aarg+ix]; } + V _Arg(I ix,VBuffer *v,I bl = 0) { vecs[asrc+bl*aarg+ix] = v; } + +private: + BL cplx; + I asrc,adst,aarg,barg; + VBuffer **vecs; + I frms,afrms; +}; + + +class RVecBlock: + public VecBlock +{ +public: + RVecBlock(I _n,I _a = 0,I _ba = 0): VecBlock(false,_n,_n,_a,_ba),n(_n),a(_a) {} + + VBuffer *Src(I ix) { return _Src(ix); } + VBuffer *Dst(I ix) { return _Dst(ix); } + V Src(I ix,VBuffer *v) { _Src(ix,v); } + V Dst(I ix,VBuffer *v) { _Dst(ix,v); } + + VBuffer *Arg(I ix,I bl = 0) { return _Arg(ix,bl); } + V Arg(I ix,VBuffer *v,I bl = 0) { _Arg(ix,v,bl); } + + I Vecs() const { return n; } + I Args() const { return a; } + + Vasp *SrcVasp() { return _SrcVasp(n); } + Vasp *DstVasp() { return _DstVasp(n); } + Vasp *ResVasp() { return _ResVasp(n); } + +protected: + I n,a; +}; + +class CVecBlock: + public VecBlock +{ +public: + CVecBlock(I _np,I _ap = 0,I _bap = 0): VecBlock(true,_np*2,_np*2,_ap*2,_bap),np(_np),ap(_ap) {} + + VBuffer *ReSrc(I ix) { return _Src(ix*2); } + VBuffer *ImSrc(I ix) { return _Src(ix*2+1); } + VBuffer *ReDst(I ix) { return _Dst(ix*2); } + VBuffer *ImDst(I ix) { return _Dst(ix*2+1); } + V Src(I ix,VBuffer *vre,VBuffer *vim) { _Src(ix*2,vre); _Src(ix*2+1,vim); } + V Dst(I ix,VBuffer *vre,VBuffer *vim) { _Dst(ix*2,vre); _Dst(ix*2+1,vim); } + + VBuffer *ReArg(I ix,I bl = 0) { return _Arg(ix*2,bl); } + VBuffer *ImArg(I ix,I bl = 0) { return _Arg(ix*2+1,bl); } + V Arg(I ix,VBuffer *vre,VBuffer *vim,I bl = 0) { _Arg(ix*2,vre,bl); _Arg(ix*2+1,vim,bl); } + + I Pairs() const { return np; } + I Args() const { return ap; } + + Vasp *SrcVasp() { return _SrcVasp(np*2); } + Vasp *DstVasp() { return _DstVasp(np*2); } + Vasp *ResVasp() { return _ResVasp(np*2); } + +protected: + I np,ap; +}; + +#endif |