/* 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 "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.incl && cur == val) { // if @incl attribute is set and current sample matches ofl = ofr = off; } else { 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,CVasp &src,const Argument &arg,CVasp *dst,BL st) { Vasp *ret = NULL; if(src.Vectors() != 1) post("%s - Need exactly one vector in vasp!",p.opName()); else if(arg.CanbeFloat() || (arg.IsList() && arg.GetList().Count() >= 1)) { I fr = src.Frames(); I o = src.Vector(0).Offset(); VBuffer *buf = src.Buffer(0); I sz = buf->Frames(); delete buf; CVasp 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()); // What's that???? } delete vecs; } } else post("%s - no arguments: no operation",p.opName()); return ret; } class vasp_search: public vasp_anyop { FLEXT_HEADER_S(vasp_search,vasp_anyop,Setup) 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),incl(false) {} static V Setup(t_classid c) { FLEXT_CADDATTR_VAR1(c,"dir",dir); FLEXT_CADDATTR_VAR1(c,"slope",slope); FLEXT_CADDATTR_VAR1(c,"incl",incl); } 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; p.srch.incl = incl; Vasp *ret = do_work(p); if(ret) ToOutFloat(1,p.srch.dif); return ret; } protected: I dir,slope; BL incl; private: FLEXT_ATTRVAR_I(dir) FLEXT_ATTRVAR_I(slope) FLEXT_ATTRVAR_B(incl) }; 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) { CVasp cdst(dst),cref(ref); return VaspOp::m_soffset(p,cref,arg,&cdst); } }; 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) { CVasp cdst(dst),cref(ref); return VaspOp::m_sframes(p,cref,arg,&cdst); } }; FLEXT_LIB_V("vasp, vasp.frames= vasp.f=",vasp_sframes)