diff options
-rw-r--r-- | externals/grill/flext/readme.txt | 2 | ||||
-rw-r--r-- | externals/grill/flext/source/flclass.h | 31 | ||||
-rw-r--r-- | externals/grill/flext/source/fldefs.h | 20 | ||||
-rw-r--r-- | externals/grill/flext/source/flext.cpp | 31 | ||||
-rw-r--r-- | externals/grill/flext/source/flthr.cpp | 164 | ||||
-rw-r--r-- | externals/grill/vasp/pd-ex/freeze1.pd | 347 |
6 files changed, 549 insertions, 46 deletions
diff --git a/externals/grill/flext/readme.txt b/externals/grill/flext/readme.txt index 4a83e225..b58df39c 100644 --- a/externals/grill/flext/readme.txt +++ b/externals/grill/flext/readme.txt @@ -109,6 +109,8 @@ Version history: - also FLEXT_DEBUG for debug build - SndObjs: virtual FreeObject routine is now called at destruction (by parent class), derived class doesn't need to call it! - SndObjs: fixed typo (numbers of output slots was wrong) and init bug +- introduced a helper thread for launching flext threads in the background +- threads are now handled on class (as opposed to object) level 0.4.0: - the use of the const keyword is enforced (e.g. the preferred type for symbols is now "const t_symbol *") diff --git a/externals/grill/flext/source/flclass.h b/externals/grill/flext/source/flclass.h index 12efeb82..6f74b5fe 100644 --- a/externals/grill/flext/source/flclass.h +++ b/externals/grill/flext/source/flclass.h @@ -467,20 +467,19 @@ protected: class thr_entry { public: - thr_entry(pthread_t id = pthread_self()): thrid(id),nxt(NULL) {} + thr_entry(flext_base *t,void *(*m)(thr_params *),thr_params *p,pthread_t id = pthread_self()): th(t),meth(m),params(p),thrid(id),active(false),nxt(NULL) {} //! \brief Check if this class represents the current thread bool Is(pthread_t id = pthread_self()) const { return pthread_equal(thrid,id) != 0; } + bool active; pthread_t thrid; + void *(*meth)(thr_params *); + thr_params *params; + flext_base *th; thr_entry *nxt; }; - /*! \brief Start a method thread - \internal - */ - static bool StartThread(void *(*meth)(thr_params *p),thr_params *p,char *methname); - /*! \brief Add current thread to list of active threads \return true on success \internal @@ -491,6 +490,13 @@ protected: \internal */ void PopThread(); + +public: + /*! \brief Start a method thread + \internal + */ + bool StartThread(void *(*meth)(thr_params *p),thr_params *p,char *methname); + #endif protected: @@ -657,11 +663,18 @@ private: bool shouldexit; int thrcount; - pthread_t thrid; // the thread that created the object (the system thread) + static pthread_t thrid; // the thread that created the object (the system thread) ThrMutex qmutex; - thr_entry *thrhead,*thrtail; - ThrMutex tlmutex; + static thr_entry *thrhead,*thrtail; + static ThrMutex tlmutex; + + static pthread_t thrhelpid; + static bool StartHelper(); + static bool StopHelper(); + static void ThrHelper(void *); + + void TermThreads(); #endif class qmsg; diff --git a/externals/grill/flext/source/fldefs.h b/externals/grill/flext/source/fldefs.h index 10c7bf93..f7488fe0 100644 --- a/externals/grill/flext/source/fldefs.h +++ b/externals/grill/flext/source/fldefs.h @@ -413,7 +413,7 @@ FLEXT_CALLBACK_1(M_FUN,t_symptr) #define FLEXT_THREAD(M_FUN) \ static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c) { \ thr_params *p = new thr_params(c); \ - return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ + return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ } \ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \ thisType *th = FLEXT_CAST<thisType *>(p->cl); \ @@ -430,7 +430,7 @@ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \ #define FLEXT_THREAD_A(M_FUN) \ static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,t_symbol *s,int argc,t_atom *argv) { \ thr_params *p = new thr_params(c); p->set_any(s,argc,argv); \ - return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ + return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ } \ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \ thisType *th = FLEXT_CAST<thisType *>(p->cl); \ @@ -449,7 +449,7 @@ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \ #define FLEXT_THREAD_V(M_FUN) \ static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,int argc,t_atom *argv) { \ thr_params *p = new thr_params(c); p->set_list(argc,argv); \ - return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ + return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ } \ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \ thisType *th = FLEXT_CAST<thisType *>(p->cl); \ @@ -470,7 +470,7 @@ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \ #define FLEXT_THREAD_X(M_FUN) \ static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,void *data) { \ thr_params *p = new thr_params(c); p->var[0]._ext.data = data; \ - return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ + return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ } \ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \ thisType *th = FLEXT_CAST<thisType *>(p->cl); \ @@ -489,7 +489,7 @@ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \ #define FLEXT_THREAD_B(M_FUN) \ static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,int &arg1) { \ thr_params *p = new thr_params(c); p->var[0]._bool = arg1 != 0; \ - return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ + return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ } \ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \ thisType *th = FLEXT_CAST<thisType *>(p->cl); \ @@ -508,7 +508,7 @@ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \ static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1) { \ thr_params *p = new thr_params(c,1); \ p->var[0]._ ## TP1 = arg1; \ - return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ + return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ } \ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \ thisType *th = FLEXT_CAST<thisType *>(p->cl); \ @@ -528,7 +528,7 @@ static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2) { \ thr_params *p = new thr_params(c,2); \ p->var[0]._ ## TP1 = arg1; \ p->var[1]._ ## TP2 = arg2; \ - return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ + return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ } \ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \ thisType *th = FLEXT_CAST<thisType *>(p->cl); \ @@ -550,7 +550,7 @@ static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2,TP3 &arg3) { p->var[0]._ ## TP1 = arg1; \ p->var[1]._ ## TP2 = arg2; \ p->var[2]._ ## TP3 = arg3; \ - return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ + return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ } \ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \ thisType *th = FLEXT_CAST<thisType *>(p->cl); \ @@ -574,7 +574,7 @@ static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2,TP3 &arg3,TP p->var[1]._ ## TP2 = arg2; \ p->var[2]._ ## TP3 = arg3; \ p->var[3]._ ## TP4 = arg4; \ - return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ + return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ } \ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \ thisType *th = FLEXT_CAST<thisType *>(p->cl); \ @@ -600,7 +600,7 @@ static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2,TP3 &arg3,TP p->var[2]._ ## TP3 = arg3; \ p->var[3]._ ## TP4 = arg4; \ p->var[4]._ ## TP5 = arg5; \ - return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ + return c->StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \ } \ static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \ thisType *th = FLEXT_CAST<thisType *>(p->cl); \ diff --git a/externals/grill/flext/source/flext.cpp b/externals/grill/flext/source/flext.cpp index dedf7c49..d0fdb766 100644 --- a/externals/grill/flext/source/flext.cpp +++ b/externals/grill/flext/source/flext.cpp @@ -130,10 +130,8 @@ flext_base::flext_base(): LOG1("%s - flext logging is on",thisName()); #ifdef FLEXT_THREADS - thrid = pthread_self(); - shouldexit = false; - thrhead = thrtail = NULL; +// thrhead = thrtail = NULL; #endif qhead = qtail = NULL; qclk = (t_qelem *)(qelem_new(this,(t_method)QTick)); @@ -147,26 +145,7 @@ flext_base::flext_base(): flext_base::~flext_base() { #ifdef FLEXT_THREADS - // wait for thread termination - shouldexit = true; - for(int wi = 0; thrhead && wi < 100; ++wi) Sleep(0.01f); - -//#ifdef _POSIX_THREADS - qmutex.Lock(); // Lock message queue - tlmutex.Lock(); - // timeout -> hard termination - while(thrhead) { - thr_entry *t = thrhead; - if(pthread_cancel(t->thrid)) post("%s - Thread could not be terminated!",thisName()); - thrhead = t->nxt; - t->nxt = NULL; delete t; - } - tlmutex.Unlock(); - qmutex.Unlock(); -//#else -//#pragma message ("No tread cancelling") -//#endif - + TermThreads(); #endif // send remaining pending messages @@ -482,6 +461,12 @@ void flext_base::Setup(t_class *c) ADD_IN_FT(7); ADD_IN_FT(8); ADD_IN_FT(9); + +#ifdef FLEXT_THREADS + thrid = pthread_self(); + + StartHelper(); +#endif } void flext_base::cb_help(t_class *c) { thisObject(c)->m_help(); } diff --git a/externals/grill/flext/source/flthr.cpp b/externals/grill/flext/source/flthr.cpp index f23eb38f..97da5584 100644 --- a/externals/grill/flext/source/flthr.cpp +++ b/externals/grill/flext/source/flthr.cpp @@ -23,16 +23,146 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include <errno.h> +//! Thread id of system thread +pthread_t flext_base::thrid; + +//! Thread id of helper thread +pthread_t flext_base::thrhelpid; + +flext_base::thr_entry *flext_base::thrhead = NULL,*flext_base::thrtail = NULL; +flext::ThrMutex flext_base::tlmutex; + +//! Helper thread should terminate +bool thrhelpexit = false; + +flext::ThrCond *thrhelpcond = NULL; + +//! Start helper thread +bool flext_base::StartHelper() +{ + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); + + thrhelpexit = false; + int ret = pthread_create (&thrhelpid,&attr,(void *(*)(void *))ThrHelper,NULL); + if(ret) { + error((char *)("flext - Could not launch helper thread!")); + return false; + } + else + return true; +} + +#if 0 +/*! \brief Stop helper thread + \note not called! +*/ +bool flext_base::StopHelper() +{ + thrhelpexit = true; + if(thrhelpcond) thrhelpcond->Signal(); +} +#endif + +//! Static helper thread function +void flext_base::ThrHelper(void *) +{ + // set prototype thread attributes + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); + + // set thread priority one point below normal + // so thread construction won't disturb real-time audio + sched_param parm; + int policy; + pthread_getschedparam(thrhelpid,&policy,&parm); + int prio = parm.sched_priority; + int schmin = sched_get_priority_min(policy); + if(prio > schmin) { + parm.sched_priority = prio-1; + pthread_setschedparam(thrhelpid,policy,&parm); + } + + thrhelpcond = new ThrCond; + + // helper loop + for(;;) { + thrhelpcond->Wait(); + if(thrhelpexit) break; + + tlmutex.Lock(); + + // start all inactive threads in queue + thr_entry *prv = NULL,*ti; + for(ti = thrhead; ti; prv = ti,ti = ti->nxt) { + if(!ti->active) { + int ret = pthread_create (&ti->thrid,&attr,(void *(*)(void *))ti->meth,ti->params); + if(ret) { + error((char *)("flext - Could not launch thread!")); + + // delete from queue + if(prv) + prv->nxt = ti->nxt; + else + thrhead = ti->nxt; + if(thrtail == ti) thrtail = prv; + + ti->nxt = NULL; + delete ti; + } + else { + // set active flag + ti->active = true; + } + } + } + + tlmutex.Unlock(); + } + + delete thrhelpcond; + thrhelpcond = NULL; +} + + +bool flext_base::StartThread(void *(*meth)(thr_params *p),thr_params *p,char *methname) +{ +#ifdef FLEXT_DEBUG + if(!p || !thrhelpcond) { + ERRINTERNAL(); + return false; + } +#endif + + tlmutex.Lock(); + + // make an entry into thread list + thr_entry *nt = new thr_entry(this,meth,p); + if(thrtail) thrtail->nxt = nt; + else thrhead = nt; + thrtail = nt; + + // signal thread helper + thrhelpcond->Signal(); + + tlmutex.Unlock(); + return true; +} + +/* bool flext_base::StartThread(void *(*meth)(thr_params *p),thr_params *p,char *methname) { - static bool init = false; - static pthread_attr_t attr; #ifdef FLEXT_DEBUG if(!p) { ERRINTERNAL(); return false; } #endif + + static bool init = false; + static pthread_attr_t attr; if(!init) { pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); @@ -62,8 +192,9 @@ bool flext_base::StartThread(void *(*meth)(thr_params *p),thr_params *p,char *me if(ret) { #ifdef FLEXT_DEBUG error((char *)(ret == EAGAIN?"%s - Unsufficient resources to launch thread!":"%s - Could not launch method!"),methname); -#endif +#else error((char *)("%s - Could not launch method!"),methname); +#endif delete p; return false; @@ -71,6 +202,7 @@ bool flext_base::StartThread(void *(*meth)(thr_params *p),thr_params *p,char *me else return true; } +*/ bool flext_base::PushThread() { @@ -78,12 +210,13 @@ bool flext_base::PushThread() // post("Push thread"); +/* // make an entry into thread list thr_entry *nt = new thr_entry; if(thrtail) thrtail->nxt = nt; else thrhead = nt; thrtail = nt; - +*/ { #if FLEXT_OS == FLEXT_OS_WIN // set detached thread to lower priority class @@ -151,6 +284,29 @@ void flext_base::PopThread() tlmutex.Unlock(); } +void flext_base::TermThreads() +{ + // wait for thread termination + shouldexit = true; + for(int wi = 0; thrhead && wi < 100; ++wi) Sleep(0.01f); + + qmutex.Lock(); // Lock message queue + tlmutex.Lock(); + + // timeout -> hard termination + for(thr_entry *t = thrhead; t; ) + if(t->th == this) { + if(pthread_cancel(t->thrid)) post("%s - Thread could not be terminated!",thisName()); + thr_entry *tn = t->nxt; + t->nxt = NULL; delete t; + t = tn; + } + else t = t->nxt; + + tlmutex.Unlock(); + qmutex.Unlock(); +} + flext_base::thrid_t flext_base::GetThreadId() { return pthread_self(); diff --git a/externals/grill/vasp/pd-ex/freeze1.pd b/externals/grill/vasp/pd-ex/freeze1.pd new file mode 100644 index 00000000..d3aba0f8 --- /dev/null +++ b/externals/grill/vasp/pd-ex/freeze1.pd @@ -0,0 +1,347 @@ +#N canvas 30 168 943 479 12;
+#X obj 18 361 vasp.u;
+#N canvas 387 42 535 624 freeze 0;
+#X obj 26 130 vasp.split 2;
+#X obj 27 404 vasp.join 2;
+#X obj 27 74 vasp.cfft @detach 1;
+#X obj 27 461 vasp.c!fft @detach 1;
+#X obj 25 13 inlet;
+#X obj 27 567 outlet;
+#X obj 173 236 * 0.01;
+#X obj 302 17 inlet;
+#X obj 26 100 vasp.polar @detach 1;
+#X obj 27 432 vasp.rect @detach 1;
+#X obj 26 261 vasp.gate @detach 1;
+#X obj 92 319 vasp.noise @detach 1;
+#X obj 26 371 vasp.sync;
+#X obj 25 209 vasp.max? @detach 1;
+#X obj 381 17 inlet;
+#X obj 162 569 outlet;
+#X obj 29 536 vasp.opt;
+#N canvas 0 0 456 306 non0 0;
+#X obj 26 162 outlet;
+#X obj 27 105 length;
+#X obj 28 133 / 1;
+#X obj 26 21 inlet;
+#X obj 26 49 t a a;
+#X obj 179 80 vasp.f?;
+#X obj 26 80 vasp.?? @detach 1;
+#X connect 1 0 2 0;
+#X connect 2 0 0 0;
+#X connect 3 0 4 0;
+#X connect 4 0 6 0;
+#X connect 4 1 5 0;
+#X connect 5 0 2 1;
+#X connect 6 0 1 0;
+#X restore 161 498 pd non0;
+#X obj 29 509 vasp.n 0;
+#X obj 302 45 + 100;
+#X obj 326 117 expr pow(2. \, -$f1/1200);
+#X obj 300 76 dbtorms;
+#N canvas 445 282 454 304 cplx 0;
+#X obj 87 181 vasp.!;
+#X obj 19 229 vasp.join;
+#X obj 19 73 t a b a;
+#X obj 129 138 vasp.f?;
+#X obj 21 14 inlet;
+#X obj 19 258 outlet;
+#X text 196 136 get length of source;
+#X text 143 178 make immediate;
+#X text 143 193 initialized to 0;
+#X text 101 230 make complex vasp;
+#X obj 19 44 vasp.chk;
+#X connect 0 0 1 1;
+#X connect 1 0 5 0;
+#X connect 2 0 1 0;
+#X connect 2 1 0 0;
+#X connect 2 2 3 0;
+#X connect 3 0 0 1;
+#X connect 4 0 10 0;
+#X connect 10 0 2 0;
+#X restore 27 43 pd cplx;
+#X text 280 169 resample;
+#X text 185 211 find spectral peak;
+#X text 188 260 gate spectrum below threshold;
+#X text 107 371 wait for threads to finish;
+#X obj 92 344 vasp.* 3.14159 @detach 1;
+#X text 193 75 FFT;
+#X text 195 100 -> polar;
+#X text 188 432 -> cartesian;
+#X text 198 460 inverse FFT;
+#X text 263 316 randomize complex arguments;
+#X text 225 496 get spectral density;
+#X text 100 536 normalize result;
+#X obj 25 171 vasp.xtilt 1 @detach 1 @inter 2;
+#X obj 27 290 vasp.pow @detach 1;
+#X obj 441 21 inlet;
+#X text 181 289 treat spectrum exponentially;
+#X connect 0 0 35 0;
+#X connect 0 1 11 0;
+#X connect 1 0 9 0;
+#X connect 2 0 8 0;
+#X connect 3 0 18 0;
+#X connect 4 0 22 0;
+#X connect 6 0 10 1;
+#X connect 7 0 19 0;
+#X connect 8 0 0 0;
+#X connect 9 0 3 0;
+#X connect 10 0 36 0;
+#X connect 11 0 27 0;
+#X connect 12 0 1 0;
+#X connect 12 0 17 0;
+#X connect 12 1 1 1;
+#X connect 13 0 10 0;
+#X connect 13 1 6 0;
+#X connect 14 0 20 0;
+#X connect 16 0 5 0;
+#X connect 17 0 15 0;
+#X connect 18 0 16 0;
+#X connect 19 0 21 0;
+#X connect 20 0 35 1;
+#X connect 21 0 6 1;
+#X connect 22 0 2 0;
+#X connect 27 0 12 1;
+#X connect 35 0 13 0;
+#X connect 36 0 12 0;
+#X connect 37 0 36 1;
+#X restore 18 331 pd freeze;
+#X obj 104 214 nbx 6 18 -100 0 0 1 empty empty noise_rejection(dB)
+0 -8 0 12 -225271 -1 -1 -61 256;
+#X obj 104 257 nbx 7 18 -10000 10000 0 1 empty empty transpose(cents)
+0 -8 0 12 -225271 -1 -1 0 256;
+#X obj 448 278 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 729 279 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#N canvas 0 0 468 318 save 0;
+#X obj 30 198 soundfiler;
+#X obj 30 134 symbol;
+#X obj 29 106 savepanel;
+#X obj 32 8 inlet;
+#X obj 27 232 outlet;
+#X obj 30 42 route new again;
+#X obj 29 73 t b;
+#X obj 84 73 t b;
+#X msg 27 169 write -bytes 3 -wave \$1 dst;
+#X connect 0 0 4 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 0;
+#X connect 3 0 5 0;
+#X connect 5 0 6 0;
+#X connect 5 1 7 0;
+#X connect 6 0 2 0;
+#X connect 7 0 1 0;
+#X connect 8 0 0 0;
+#X restore 729 250 pd save;
+#N canvas 205 58 331 468 open 0;
+#X obj 18 192 soundfiler;
+#X obj 19 96 openpanel;
+#X obj 21 6 inlet;
+#X obj 15 390 outlet;
+#X obj 20 123 symbol;
+#X obj 15 313 vasp.opt;
+#X obj 17 345 vasp.u;
+#X obj 17 233 t b;
+#X obj 22 33 route new again;
+#X obj 19 66 t b;
+#X obj 74 66 t b;
+#X msg 19 152 read -resize \$1 src;
+#X msg 16 281 vasp src;
+#X obj 74 230 s \$0-srclen;
+#X connect 0 0 7 0;
+#X connect 0 0 13 0;
+#X connect 1 0 4 0;
+#X connect 2 0 8 0;
+#X connect 4 0 11 0;
+#X connect 5 0 6 0;
+#X connect 6 0 3 0;
+#X connect 7 0 12 0;
+#X connect 8 0 9 0;
+#X connect 8 1 10 0;
+#X connect 9 0 1 0;
+#X connect 10 0 4 0;
+#X connect 11 0 0 0;
+#X connect 12 0 5 0;
+#X restore 448 250 pd open;
+#X msg 381 222 stop;
+#N canvas 0 0 450 300 graph10 0;
+#X array src 1.23699e+006 float 0;
+#X coords 0 1 1.23699e+006 -1 600 150 1;
+#X restore 322 20 graph;
+#X msg 447 222 new;
+#X msg 482 222 again;
+#X msg 728 222 new;
+#X msg 761 222 again;
+#X msg 332 222 play;
+#X obj 8 9 cnv 15 300 48 empty empty freeze 5 14 0 20 -233017 -66577
+0;
+#X text 128 13 make static sound;
+#X obj 18 108 bng 25 250 50 0 empty empty empty 0 -6 0 8 -24198 -1
+-1;
+#X obj 105 115 nbx 12 18 0 1e+008 0 1 empty empty length(frames) 0
+-8 0 12 -225271 -1 -1 1e+006 256;
+#X obj 85 368 nbx 9 14 -1e+037 1e+037 0 0 empty empty spectral_density
+0 -6 0 10 -262131 -1 -1 0.18217 256;
+#X obj 332 197 cnv 15 100 20 empty empty play_src 5 8 0 10 -261681
+-66577 0;
+#X obj 447 197 cnv 15 100 20 empty empty read_src 5 8 0 10 -261681
+-66577 0;
+#X obj 727 197 cnv 15 100 20 empty empty write_dst 5 8 0 10 -261681
+-66577 0;
+#N canvas 0 0 450 300 graph10 0;
+#X array dst 1e+006 float 0;
+#X coords 0 1 999999 -1 600 150 1;
+#X restore 325 304 graph;
+#X msg 663 223 stop;
+#X msg 614 223 play;
+#X obj 614 198 cnv 15 100 20 empty empty play_dst 5 8 0 10 -261681
+-66577 0;
+#N canvas 0 0 495 347 playsrc 0;
+#X obj 18 245 dac~;
+#X obj 19 21 inlet;
+#X obj 17 49 route play;
+#X obj 18 197 tabplay~ src;
+#X obj 338 23 r \$0-srclen;
+#X obj 166 22 r \$0-offs;
+#X obj 249 22 r \$0-len;
+#X obj 338 48 t b f;
+#X obj 166 94 *;
+#X obj 248 93 *;
+#X obj 75 132 pack 0 0;
+#X obj 19 81 t b;
+#X obj 19 159 lister;
+#X obj 77 105 loadbang;
+#X connect 1 0 2 0;
+#X connect 2 0 11 0;
+#X connect 2 1 3 0;
+#X connect 3 0 0 0;
+#X connect 3 0 0 1;
+#X connect 4 0 7 0;
+#X connect 5 0 8 0;
+#X connect 6 0 9 0;
+#X connect 7 0 8 0;
+#X connect 7 0 9 0;
+#X connect 7 1 8 1;
+#X connect 7 1 9 1;
+#X connect 8 0 10 0;
+#X connect 9 0 10 1;
+#X connect 10 0 12 1;
+#X connect 11 0 12 0;
+#X connect 12 0 3 0;
+#X connect 13 0 10 0;
+#X restore 332 250 pd playsrc;
+#N canvas 0 0 481 333 playdst 0;
+#X obj 21 118 dac~;
+#X obj 19 21 inlet;
+#X obj 22 51 route play;
+#X obj 21 83 tabplay~ dst;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 2 1 3 0;
+#X connect 3 0 0 0;
+#X connect 3 0 0 1;
+#X restore 614 251 pd playdst;
+#N canvas 249 202 495 438 copy 0;
+#X obj 27 26 inlet;
+#X obj 27 51 t b b;
+#X obj 316 19 inlet;
+#X obj 25 361 outlet;
+#X obj 26 81 vasp src;
+#X obj 26 229 vasp.f;
+#X obj 26 201 vasp.o;
+#X obj 128 31 r \$0-offs;
+#X obj 211 31 r \$0-len;
+#X obj 316 87 f 1e+006;
+#X obj 187 174 vasp.s @ref dst;
+#X obj 366 21 loadbang;
+#X obj 84 169 *;
+#X obj 117 169 *;
+#X obj 82 139 vasp.f?;
+#X obj 125 366 print;
+#X obj 27 109 t a a;
+#X obj 27 259 vasp.sync;
+#X obj 26 328 vasp.f -1;
+#X text 167 288 copy src to dst;
+#X text 108 328 take all dst;
+#X text 316 175 resize dst buffer;
+#X text 341 201 set to zero;
+#X obj 185 202 vasp.= 0 @detach 1;
+#X obj 26 287 vasp.-> @detach 1;
+#X connect 0 0 1 0;
+#X connect 1 0 4 0;
+#X connect 1 1 10 0;
+#X connect 2 0 9 0;
+#X connect 4 0 16 0;
+#X connect 5 0 17 0;
+#X connect 6 0 5 0;
+#X connect 7 0 12 1;
+#X connect 8 0 13 1;
+#X connect 9 0 10 1;
+#X connect 10 0 23 0;
+#X connect 11 0 9 0;
+#X connect 12 0 6 1;
+#X connect 13 0 5 1;
+#X connect 14 0 12 0;
+#X connect 14 0 13 0;
+#X connect 16 0 6 0;
+#X connect 16 1 14 0;
+#X connect 17 0 24 0;
+#X connect 17 1 24 1;
+#X connect 18 0 3 0;
+#X connect 18 1 15 0;
+#X connect 23 0 17 1;
+#X connect 24 1 18 0;
+#X restore 18 159 pd copy;
+#X text 85 160 copy and resize;
+#X obj 323 170 hsl 600 15 0 1 0 1 \$0-r2 empty empty -2 -6 1152 8 -262131
+-1 -1 59900 1;
+#X obj 323 5 hsl 600 15 0 1 0 1 \$0-r1 empty empty -2 -6 1152 8 -262131
+-1 -1 0 1;
+#N canvas 148 330 297 257 sel 0;
+#X obj 30 25 r \$0-r1;
+#X obj 110 25 r \$0-r2;
+#X obj 30 100 min;
+#X obj 113 100 max;
+#X obj 30 53 t f f;
+#X obj 110 50 t b b f;
+#X obj 113 130 -;
+#X obj 27 190 s \$0-offs;
+#X obj 113 190 s \$0-len;
+#X obj 114 161 * -1;
+#X connect 0 0 4 0;
+#X connect 1 0 5 0;
+#X connect 2 0 6 0;
+#X connect 2 0 7 0;
+#X connect 3 0 6 1;
+#X connect 4 0 2 0;
+#X connect 4 1 3 0;
+#X connect 5 0 2 0;
+#X connect 5 1 3 0;
+#X connect 5 2 3 1;
+#X connect 5 2 2 1;
+#X connect 6 0 9 0;
+#X connect 9 0 8 0;
+#X restore 871 198 pd sel;
+#X text 125 31 (C)2002 Thomas Grill;
+#X text 19 89 do!;
+#X obj 104 301 nbx 7 18 0 3 0 1 empty empty power 0 -8 0 12 -225271
+-1 -1 1 256;
+#X text 10 35 (needs zexy!);
+#X connect 1 0 0 0;
+#X connect 1 1 19 0;
+#X connect 2 0 1 1;
+#X connect 3 0 1 2;
+#X connect 6 0 5 0;
+#X connect 7 0 4 0;
+#X connect 8 0 27 0;
+#X connect 10 0 7 0;
+#X connect 11 0 7 0;
+#X connect 12 0 6 0;
+#X connect 13 0 6 0;
+#X connect 14 0 27 0;
+#X connect 17 0 29 0;
+#X connect 18 0 29 1;
+#X connect 24 0 28 0;
+#X connect 25 0 28 0;
+#X connect 29 0 1 0;
+#X connect 36 0 1 3;
|