aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/vasp/source
diff options
context:
space:
mode:
authorThomas Grill <xovo@users.sourceforge.net>2002-12-02 19:21:08 +0000
committerThomas Grill <xovo@users.sourceforge.net>2002-12-02 19:21:08 +0000
commit9815096db22c73cacdbb65512d1b61d633db7fa8 (patch)
tree4a6582ead85b8efd031f68e717fbc8a5b3a3df3f /externals/grill/vasp/source
parent0a109da279e9df66fb5ea7d6bdaeffed16592f02 (diff)
"version 0.1.1"
svn path=/trunk/; revision=267
Diffstat (limited to 'externals/grill/vasp/source')
-rw-r--r--externals/grill/vasp/source/arg.cpp216
-rw-r--r--externals/grill/vasp/source/arg.h108
-rw-r--r--externals/grill/vasp/source/buflib.cpp258
-rw-r--r--externals/grill/vasp/source/buflib.h37
-rw-r--r--externals/grill/vasp/source/classes.cpp405
-rw-r--r--externals/grill/vasp/source/classes.h278
-rw-r--r--externals/grill/vasp/source/env.cpp144
-rw-r--r--externals/grill/vasp/source/env.h73
-rw-r--r--externals/grill/vasp/source/main.cpp209
-rw-r--r--externals/grill/vasp/source/main.h83
-rw-r--r--externals/grill/vasp/source/mixfft.cpp588
-rwxr-xr-xexternals/grill/vasp/source/obj_chns.cpp107
-rw-r--r--externals/grill/vasp/source/obj_frames.cpp228
-rw-r--r--externals/grill/vasp/source/obj_imm.cpp104
-rw-r--r--externals/grill/vasp/source/obj_offs.cpp174
-rw-r--r--externals/grill/vasp/source/obj_part.cpp102
-rw-r--r--externals/grill/vasp/source/obj_peaks.cpp111
-rw-r--r--externals/grill/vasp/source/obj_q.cpp121
-rw-r--r--externals/grill/vasp/source/obj_radio.cpp57
-rw-r--r--externals/grill/vasp/source/obj_size.cpp248
-rw-r--r--externals/grill/vasp/source/obj_split.cpp288
-rw-r--r--externals/grill/vasp/source/obj_sync.cpp123
-rw-r--r--externals/grill/vasp/source/obj_vasp.cpp200
-rw-r--r--externals/grill/vasp/source/obj_vecs.cpp106
-rw-r--r--externals/grill/vasp/source/opbase.cpp94
-rw-r--r--externals/grill/vasp/source/opbase.h50
-rw-r--r--externals/grill/vasp/source/opdefs.h364
-rwxr-xr-xexternals/grill/vasp/source/oploop.h38
-rw-r--r--externals/grill/vasp/source/opparam.cpp223
-rw-r--r--externals/grill/vasp/source/opparam.h128
-rw-r--r--externals/grill/vasp/source/oppermute.h121
-rw-r--r--externals/grill/vasp/source/ops.h27
-rw-r--r--externals/grill/vasp/source/ops_arith.cpp64
-rw-r--r--externals/grill/vasp/source/ops_arith.h72
-rw-r--r--externals/grill/vasp/source/ops_assign.cpp108
-rw-r--r--externals/grill/vasp/source/ops_assign.h34
-rw-r--r--externals/grill/vasp/source/ops_carith.cpp125
-rw-r--r--externals/grill/vasp/source/ops_carith.h48
-rw-r--r--externals/grill/vasp/source/ops_cmp.cpp99
-rw-r--r--externals/grill/vasp/source/ops_cmp.h86
-rw-r--r--externals/grill/vasp/source/ops_cplx.cpp85
-rw-r--r--externals/grill/vasp/source/ops_cplx.h42
-rw-r--r--externals/grill/vasp/source/ops_dft.cpp651
-rw-r--r--externals/grill/vasp/source/ops_dft.h25
-rw-r--r--externals/grill/vasp/source/ops_feature.cpp199
-rw-r--r--externals/grill/vasp/source/ops_feature.h29
-rw-r--r--externals/grill/vasp/source/ops_flt.cpp234
-rw-r--r--externals/grill/vasp/source/ops_flt.h41
-rw-r--r--externals/grill/vasp/source/ops_gate.cpp88
-rw-r--r--externals/grill/vasp/source/ops_gen.cpp265
-rw-r--r--externals/grill/vasp/source/ops_gen.h40
-rw-r--r--externals/grill/vasp/source/ops_qminmax.cpp276
-rw-r--r--externals/grill/vasp/source/ops_rearr.cpp243
-rw-r--r--externals/grill/vasp/source/ops_rearr.h34
-rw-r--r--externals/grill/vasp/source/ops_resmp.cpp266
-rw-r--r--externals/grill/vasp/source/ops_resmp.h28
-rw-r--r--externals/grill/vasp/source/ops_search.cpp187
-rw-r--r--externals/grill/vasp/source/ops_search.h29
-rw-r--r--externals/grill/vasp/source/ops_trnsc.cpp83
-rw-r--r--externals/grill/vasp/source/ops_trnsc.h47
-rw-r--r--externals/grill/vasp/source/ops_wnd.cpp191
-rw-r--r--externals/grill/vasp/source/ops_wnd.h39
-rw-r--r--externals/grill/vasp/source/opvecs.cpp630
-rw-r--r--externals/grill/vasp/source/rdx2fft.cpp82
-rw-r--r--externals/grill/vasp/source/rvfft.cpp357
-rw-r--r--externals/grill/vasp/source/util.cpp12
-rw-r--r--externals/grill/vasp/source/util.h33
-rw-r--r--externals/grill/vasp/source/vasp.cpp353
-rw-r--r--externals/grill/vasp/source/vasp.h142
-rw-r--r--externals/grill/vasp/source/vbuffer.cpp40
-rw-r--r--externals/grill/vasp/source/vbuffer.h127
-rw-r--r--externals/grill/vasp/source/vecblk.cpp49
-rw-r--r--externals/grill/vasp/source/vecblk.h105
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