/* 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 "main.h" #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) { AddVector(r); } Vasp::~Vasp() { Clear(); } Vasp &Vasp::Clear() { refs = frames = chns = 0; if(ref) { delete[] ref; ref = NULL; } return *this; } 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::AddVector(const Ref &r) { Resize(chns+1); ref[chns++] = r; 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 V Vasp::MakeList(flext::AtomList &ret,BL withvasp) const { I voffs = withvasp?1:0; I needed = voffs+1+Vectors()*3; ret(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) { const 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 } } // generate Vasp list of buffer references flext::AtomList *Vasp::MakeList(BL withvasp) const { flext::AtomList *ret = new flext::AtomList; MakeList(*ret,withvasp); 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,BL keep,BL zero) { for(I i = 0; i < Vectors(); ++i) { VBuffer *buf = Buffer(i); if(buf) { buf->Frames(s,keep,zero); delete buf; } } } V Vasp::SizeD(I sd,BL keep,BL zero) { for(I i = 0; i < Vectors(); ++i) { VBuffer *buf = Buffer(i); if(buf) { I s = buf->Frames()+sd; buf->Frames(s >= 0?s:0,keep,zero); delete buf; } } } V Vasp::SizeM(R f,BL keep,BL zero) { 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,keep,zero); 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; } // ------------------------------------ CVasp::CVasp() {} CVasp::CVasp(const Vasp &v): Vasp(v) { if(!Check()) Clear(); else Frames(ChkFrames()); } CVasp &CVasp::operator +=(const CVasp &v) { if(v.Ok()) { if(!Ok()) *this = v; else { I f = Frames(),vf = v.Frames(); if(f != vf) { post("vasp - Frame count of joined vasps is different - taking the minimum"); Frames(min(f,vf)); } Resize(Vectors()+v.Vectors()); for(I i = 0; i < v.Vectors(); ++i) AddVector(v.Vector(i)); } } return *this; }