aboutsummaryrefslogtreecommitdiff
path: root/externals
diff options
context:
space:
mode:
Diffstat (limited to 'externals')
-rw-r--r--externals/grill/flext/readme.txt2
-rw-r--r--externals/grill/flext/source/flclass.h31
-rw-r--r--externals/grill/flext/source/fldefs.h20
-rw-r--r--externals/grill/flext/source/flext.cpp31
-rw-r--r--externals/grill/flext/source/flthr.cpp164
-rw-r--r--externals/grill/vasp/pd-ex/freeze1.pd347
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;