Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/Util/Clooper/SoundClient.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Util/Clooper/SoundClient.cpp')
-rw-r--r--Util/Clooper/SoundClient.cpp762
1 files changed, 0 insertions, 762 deletions
diff --git a/Util/Clooper/SoundClient.cpp b/Util/Clooper/SoundClient.cpp
deleted file mode 100644
index a1bedd1..0000000
--- a/Util/Clooper/SoundClient.cpp
+++ /dev/null
@@ -1,762 +0,0 @@
-#include <python2.4/Python.h>
-
-#include <pthread.h>
-#include <stdio.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/time.h>
-
-#include <csound/csound.hpp>
-//#include "SoundClient.h"
-#include <vector>
-#include <map>
-#include <cmath>
-
-using namespace std;
-
-static double pytime(const struct timeval * tv)
-{
- return (double) tv->tv_sec + (double) tv->tv_usec / 1000000.0;
-}
-
-struct ev_t
-{
- char type;
- int onset;
- bool time_in_ticks;
- MYFLT prev_secs_per_tick;
- MYFLT duration, attack, decay;
- std::vector<MYFLT> param;
-
- ev_t(char type, MYFLT * p, int np, bool in_ticks)
- : type(type), onset(0), time_in_ticks(in_ticks), param(np)
- {
- assert(np >= 4);
- onset = (int) p[1];
- duration = p[2];
- attack = np > 8 ? p[8]: 0.0; //attack
- decay = np > 9 ? p[9]: 0.0; //decay
- prev_secs_per_tick = -1.0;
- for (int i = 0; i < np; ++i) param[i] = p[i];
-
- param[1] = 0.0; //onset
- }
- bool operator<(const ev_t &e) const
- {
- return onset < e.onset;
- }
- void ev_print(FILE *f)
- {
- fprintf(f, "INFO: scoreEvent %c ", type);
- for (size_t i = 0; i < param.size(); ++i) fprintf(f, "%lf ", param[i]);
- fprintf(f, "\n");
- }
- void update(int idx, MYFLT val)
- {
- if ( (unsigned)idx >= param.size())
- {
- fprintf(stderr, "ERROR: updateEvent request for too-high parameter %i\n", idx);
- return;
- }
- if (time_in_ticks)
- {
- switch(idx)
- {
- case 1: onset = (int) val; break;
- case 2: duration = val; break;
- case 8: attack = val; break;
- case 9: decay = val; break;
- default: param[idx] = val; break;
- }
- prev_secs_per_tick = -1.0; //force recalculation
- }
- else
- {
- param[idx] = val;
- }
- }
-
- void event(CSOUND * csound, MYFLT secs_per_tick)
- {
- if (time_in_ticks && (secs_per_tick != prev_secs_per_tick))
- {
- param[2] = duration * secs_per_tick;
- param[8] = max(0.002f, attack * secs_per_tick);
- param[9] = max(0.002f, decay * secs_per_tick);
- prev_secs_per_tick = secs_per_tick;
- if (0) fprintf(stdout, "setting duration to %f\n", param[5]);
- }
- csoundScoreEvent(csound, type, &param[0], param.size());
- }
-};
-struct EvLoop
-{
- FILE * _debug;
-
- int tick_prev;
- int tickMax;
- MYFLT rtick;
- MYFLT secs_per_tick;
- MYFLT ticks_per_ksmp;
- typedef std::pair<int, ev_t *> pair_t;
- typedef std::multimap<int, ev_t *>::iterator iter_t;
- typedef std::map<int, iter_t>::iterator idmap_t;
-
- std::multimap<int, ev_t *> ev;
- std::multimap<int, ev_t *>::iterator ev_pos;
- std::map<int, iter_t> idmap;
- CSOUND * csound;
- void * mutex;
-
- EvLoop(CSOUND * cs) : _debug(stderr), tick_prev(0), tickMax(1), rtick(0.0), ev(), ev_pos(ev.end()), csound(cs), mutex(NULL)
- {
- setTickDuration(0.05);
- mutex = csoundCreateMutex(0);
- }
- ~EvLoop()
- {
- csoundLockMutex(mutex);
- for (iter_t i = ev.begin(); i != ev.end(); ++i)
- {
- delete i->second;
- }
- csoundUnlockMutex(mutex);
- csoundDestroyMutex(mutex);
- }
- void clear()
- {
- csoundLockMutex(mutex);
- for (iter_t i = ev.begin(); i != ev.end(); ++i)
- {
- delete i->second;
- }
- ev.erase(ev.begin(), ev.end());
- ev_pos = ev.end();
- idmap.erase(idmap.begin(), idmap.end());
- csoundUnlockMutex(mutex);
- }
- int getTick()
- {
- return (int)rtick % tickMax;
- }
- void setNumTicks(int nticks)
- {
- tickMax = nticks;
- if ((int)rtick > nticks)
- {
- int t = (int)rtick % nticks;
- rtick = t;
- }
- }
- void setTick(int t)
- {
- t = t % tickMax;
- rtick = (MYFLT)(t % tickMax);
- //TODO: binary search would be faster
- csoundLockMutex(mutex);
- ev_pos = ev.lower_bound( t );
- csoundUnlockMutex(mutex);
- }
- void setTickDuration(MYFLT d)
- {
- if (!csound) {
- fprintf(stderr, "skipping setTickDuration, csound==NULL\n");
- return;
- }
- secs_per_tick = d;
- ticks_per_ksmp = 1.0 / (d * csoundGetKr(csound));
- if (0) fprintf(stderr, "INFO: duration %lf -> ticks_pr_skmp %lf\n", d, ticks_per_ksmp);
- }
- void step(FILE * logf)
- {
- rtick += ticks_per_ksmp;
- int tick = (int)rtick % tickMax;
- if (tick == tick_prev) return;
-
- csoundLockMutex(mutex);
- int events = 0;
- int loop0 = 0;
- int loop1 = 0;
- const int eventMax = 8; //NOTE: events beyond this number will be ignored!!!
- if (!ev.empty())
- {
- if (tick < tick_prev) // should be true only after the loop wraps (not after insert)
- {
- while (ev_pos != ev.end())
- {
- if (logf) ev_pos->second->ev_print(logf);
- if (events < eventMax) ev_pos->second->event(csound, secs_per_tick);
- ++ev_pos;
- ++events;
- ++loop0;
- }
- ev_pos = ev.begin();
- }
- while ((ev_pos != ev.end()) && (tick >= ev_pos->first))
- {
- if (logf) ev_pos->second->ev_print(logf);
- if (events < eventMax) ev_pos->second->event(csound, secs_per_tick);
- ++ev_pos;
- ++events;
- ++loop1;
- }
- }
- csoundUnlockMutex(mutex);
- tick_prev = tick;
- if (logf && (events >= eventMax)) fprintf(logf, "WARNING: %i/%i events at once (%i, %i)\n", events,ev.size(),loop0,loop1);
- }
- void addEvent(int id, char type, MYFLT * p, int np, bool in_ticks)
- {
- ev_t * e = new ev_t(type, p, np, in_ticks);
-
- idmap_t id_iter = idmap.find(id);
- if (id_iter == idmap.end())
- {
- //this is a new id
- csoundLockMutex(mutex);
-
- iter_t e_iter = ev.insert(pair_t(e->onset, e));
-
- //TODO: optimize by thinking about whether to do ev_pos = e_iter
- ev_pos = ev.upper_bound( tick_prev );
- idmap[id] = e_iter;
-
- csoundUnlockMutex(mutex);
- }
- else
- {
- if (_debug) fprintf(_debug, "ERROR: skipping request to add duplicate note %i\n", id);
- }
- }
- void delEvent(int id)
- {
- idmap_t id_iter = idmap.find(id);
- if (id_iter == idmap.end())
- {
- if (_debug) fprintf(_debug, "ERROR: delEvent request for unknown note %i\n", id);
- }
- else
- {
- csoundLockMutex(mutex);
- iter_t e_iter = id_iter->second;//idmap[id];
- if (e_iter == ev_pos) ++ev_pos;
-
- delete e_iter->second;
- ev.erase(e_iter);
- idmap.erase(id_iter);
-
- csoundUnlockMutex(mutex);
- }
- }
- void updateEvent(int id, int idx, float val)
- {
- idmap_t id_iter = idmap.find(id);
- if (id_iter == idmap.end())
- {
- if (_debug) fprintf(_debug, "ERROR: updateEvent request for unknown note %i\n", id);
- return;
- }
-
- //this is a new id
- csoundLockMutex(mutex);
- iter_t e_iter = id_iter->second;
- ev_t * e = e_iter->second;
- int onset = e->onset;
- e->update(idx, val);
- if (onset != e->onset)
- {
- ev.erase(e_iter);
-
- e_iter = ev.insert(pair_t(e->onset, e));
-
- //TODO: optimize by thinking about whether to do ev_pos = e_iter
- ev_pos = ev.upper_bound( tick_prev );
- idmap[id] = e_iter;
- }
- csoundUnlockMutex(mutex);
- }
-};
-struct TamTamSound
-{
- void * ThreadID;
- CSOUND * csound;
- char * csound_orc;
- enum {CONTINUE, STOP} PERF_STATUS;
- int verbosity;
- FILE * _debug;
- int thread_playloop;
- int thread_measurelag;
- EvLoop * loop;
-
- TamTamSound(char * orc)
- : ThreadID(NULL), csound(NULL), PERF_STATUS(STOP), verbosity(3), _debug(stderr), thread_playloop(0), thread_measurelag(0), loop(NULL)
- {
- if (1)
- {
- csound = csoundCreate(NULL);
- }
- else
- {
- csound = NULL;
- }
- csound_orc = strdup(orc);
-
- loop = new EvLoop(csound);
- }
- ~TamTamSound()
- {
- if (csound)
- {
- stop();
- delete loop;
- csoundDestroy(csound);
- }
- free(csound_orc);
- if (_debug) fclose(_debug);
- }
- uintptr_t thread_fn()
- {
- struct timeval tv;
- double t_prev = 0.0; //value will be ignored
- double m = 0.0;
-
- int loops = 0;
-
- while ( (csoundPerformKsmps(csound) == 0)
- && (PERF_STATUS == CONTINUE))
- {
- if (thread_measurelag)
- {
- gettimeofday(&tv, 0);
- double t_this = pytime(&tv);
- if (loops)
- {
- if (m < t_this - t_prev)
- {
- m = t_this - t_prev;
- if (_debug) fprintf(_debug, "maximum lag %lf\n", m);
- }
- }
- t_prev = t_this;
- }
- if (thread_playloop)
- {
- loop->step(NULL);
- }
- ++loops;
- }
- return 0;
- }
- static uintptr_t csThread(void *clientData)
- {
- return ((TamTamSound*)clientData)->thread_fn();
- }
- int start()
- {
- if (!csound) {
- fprintf(stderr, "skipping %s, csound==NULL\n", __FUNCTION__);
- return 1;
- }
- if (!ThreadID)
- {
- int argc=3;
- char **argv = (char**)malloc(argc*sizeof(char*));
- argv[0] = "csound";
- argv[1] ="-m0";
- argv[2] = csound_orc;
- if (_debug) fprintf(_debug, "loading file %s\n", csound_orc);
-
- csoundInitialize(&argc, &argv, 0);
- int result = csoundCompile(csound, argc, &(argv[0]));
- free(argv);
-
- if (!result)
- {
- PERF_STATUS = CONTINUE;
- ThreadID = csoundCreateThread(csThread, (void*)this);
- return 0;
- }
- else
- {
- if (_debug) fprintf(_debug, "ERROR: failed to compile orchestra\n");
- ThreadID = NULL;
- return 1;
- }
- }
- return 1;
- }
- int stop()
- {
- if (!csound) {
- fprintf(stderr, "skipping %s, csound==NULL\n", __FUNCTION__);
- return 1;
- }
- if (ThreadID)
- {
- PERF_STATUS = STOP;
- if (_debug) fprintf(_debug, "INFO: stop()");
- uintptr_t rval = csoundJoinThread(ThreadID);
- if (rval) if (_debug) fprintf(_debug, "WARNING: thread returned %zu\n", rval);
- ThreadID = NULL;
- csoundReset(csound);
- return 0;
- }
- return 1;
- }
-
- void scoreEvent(char type, MYFLT * p, int np)
- {
- if (!csound) {
- fprintf(stderr, "skipping %s, csound==NULL\n", __FUNCTION__);
- return ;
- }
- if ((verbosity > 2) && _debug)
- {
- fprintf(_debug, "INFO: scoreEvent %c ", type);
- for (int i = 0; i < np; ++i) fprintf(_debug, "%lf ", p[i]);
- fprintf(_debug, "\n");
- }
- csoundScoreEvent(csound, type, p, np);
- }
- void inputMessage(const char * msg)
- {
- if (!csound) {
- fprintf(stderr, "skipping %s, csound==NULL\n", __FUNCTION__);
- return ;
- }
- if (_debug && (verbosity > 2)) fprintf(_debug, "%s\n", msg);
- csoundInputMessage(csound, msg);
- }
- bool good()
- {
- return csound != NULL;
- }
-
- void setMasterVolume(MYFLT vol)
- {
- if (!csound) {
- fprintf(stderr, "skipping %s, csound==NULL\n", __FUNCTION__);
- return ;
- }
- MYFLT *p;
- if (!(csoundGetChannelPtr(csound, &p, "masterVolume", CSOUND_CONTROL_CHANNEL | CSOUND_INPUT_CHANNEL)))
- *p = (MYFLT) vol;
- else
- {
- if (_debug) fprintf(_debug, "ERROR: failed to set master volume\n");
- }
- }
-
- void setTrackpadX(MYFLT value)
- {
- if (!csound) {
- fprintf(stderr, "skipping %s, csound==NULL\n", __FUNCTION__);
- return ;
- }
- MYFLT *p;
- if (!(csoundGetChannelPtr(csound, &p, "trackpadX", CSOUND_CONTROL_CHANNEL | CSOUND_INPUT_CHANNEL)))
- *p = (MYFLT) value;
- else
- {
- fprintf(_debug, "ERROR: failed to set trackpad X value\n");
- }
- }
-
- void setTrackpadY(MYFLT value)
- {
- if (!csound) {
- fprintf(stderr, "skipping %s, csound==NULL\n", __FUNCTION__);
- return ;
- }
- MYFLT *p;
- if (!(csoundGetChannelPtr(csound, &p, "trackpadY", CSOUND_CONTROL_CHANNEL | CSOUND_INPUT_CHANNEL)))
- *p = (MYFLT) value;
- else
- {
- fprintf(_debug, "ERROR: failed to set trackpad Y value\n");
- }
- }
-};
-
-TamTamSound * sc_tt = NULL;
-
-static void cleanup(void)
-{
- if (sc_tt)
- {
- delete sc_tt;
- sc_tt = NULL;
- }
-}
-
-#define DECL(s) static PyObject * s(PyObject * self, PyObject *args)
-#define RetNone Py_INCREF(Py_None); return Py_None;
-
-//call once at end
-DECL(sc_destroy)
-{
- if (!PyArg_ParseTuple(args, ""))
- {
- return NULL;
- }
- if (sc_tt)
- {
- delete sc_tt;
- sc_tt = NULL;
- }
- RetNone;
-}
-//call once at startup, should return 0
-DECL(sc_initialize) //(char * csd)
-{
- char * str;
- if (!PyArg_ParseTuple(args, "s", &str ))
- {
- return NULL;
- }
- sc_tt = new TamTamSound(str);
- atexit(&cleanup);
- if (sc_tt->good())
- return Py_BuildValue("i", 0);
- else
- return Py_BuildValue("i", -1);
-}
-//compile the score, connect to device, start a sound rendering thread
-DECL(sc_start)
-{
- if (!PyArg_ParseTuple(args, "" ))
- {
- return NULL;
- }
- return Py_BuildValue("i", sc_tt->start());
-}
-//stop csound rendering thread, disconnect from sound device, clear tables.
-DECL(sc_stop)
-{
- if (!PyArg_ParseTuple(args, "" ))
- {
- return NULL;
- }
- return Py_BuildValue("i", sc_tt->stop());
-}
-DECL(sc_scoreEvent) //(char type, farray param)
-{
- char ev_type;
- PyObject *o;
- if (!PyArg_ParseTuple(args, "cO", &ev_type, &o ))
- {
- return NULL;
- }
- if (o->ob_type
- && o->ob_type->tp_as_buffer
- && (1 == o->ob_type->tp_as_buffer->bf_getsegcount(o, NULL)))
- {
- if (o->ob_type->tp_as_buffer->bf_getreadbuffer)
- {
- void * ptr;
- size_t len;
- len = o->ob_type->tp_as_buffer->bf_getreadbuffer(o, 0, &ptr);
- fprintf(stderr, "writeable buffer of length %zu at %p\n", len, ptr);
- float * fptr = (float*)ptr;
- size_t flen = len / sizeof(float);
- sc_tt->scoreEvent(ev_type, fptr, flen);
-
- Py_INCREF(Py_None);
- return Py_None;
- }
- else
- {
- assert(!"asdf");
- }
- }
- assert(!"not reached");
- return NULL;
-}
-DECL(sc_setMasterVolume) //(float v)
-{
- float v;
- if (!PyArg_ParseTuple(args, "f", &v))
- {
- return NULL;
- }
- sc_tt->setMasterVolume(v);
- Py_INCREF(Py_None);
- return Py_None;
-}
-DECL(sc_setTrackpadX) //(float v)
-{
- float v;
- if (!PyArg_ParseTuple(args, "f", &v))
- {
- return NULL;
- }
- sc_tt->setTrackpadX(v);
- Py_INCREF(Py_None);
- return Py_None;
-}
-DECL(sc_setTrackpadY) //(float v)
-{
- float v;
- if (!PyArg_ParseTuple(args, "f", &v))
- {
- return NULL;
- }
- sc_tt->setTrackpadY(v);
- Py_INCREF(Py_None);
- return Py_None;
-}
-DECL(sc_loop_getTick) // -> int
-{
- if (!PyArg_ParseTuple(args, "" ))
- {
- return NULL;
- }
- return Py_BuildValue("i", sc_tt->loop->getTick());
-}
-DECL(sc_loop_setNumTicks) //(int nticks)
-{
- int nticks;
- if (!PyArg_ParseTuple(args, "i", &nticks ))
- {
- return NULL;
- }
- sc_tt->loop->setNumTicks(nticks);
- RetNone;
-}
-DECL(sc_loop_setTick) // (int ctick)
-{
- int ctick;
- if (!PyArg_ParseTuple(args, "i", &ctick ))
- {
- return NULL;
- }
- sc_tt->loop->setTick(ctick);
- RetNone;
-}
-DECL(sc_loop_setTickDuration) // (MYFLT secs_per_tick)
-{
- float spt;
- if (!PyArg_ParseTuple(args, "f", &spt ))
- {
- return NULL;
- }
- sc_tt->loop->setTickDuration(spt);
- RetNone;
-}
-DECL(sc_loop_addScoreEvent) // (int id, int duration_in_ticks, char type, farray param)
-{
- int qid;
- int inticks;
- char ev_type;
- PyObject *o;
- if (!PyArg_ParseTuple(args, "iicO", &qid, &inticks, &ev_type, &o ))
- {
- return NULL;
- }
- if (o->ob_type
- && o->ob_type->tp_as_buffer
- && (1 == o->ob_type->tp_as_buffer->bf_getsegcount(o, NULL)))
- {
- if (o->ob_type->tp_as_buffer->bf_getreadbuffer)
- {
- void * ptr;
- size_t len;
- len = o->ob_type->tp_as_buffer->bf_getreadbuffer(o, 0, &ptr);
- fprintf(stderr, "writeable buffer of length %zu at %p\n", len, ptr);
- float * fptr = (float*)ptr;
- size_t flen = len / sizeof(float);
- sc_tt->loop->addEvent(qid, ev_type, fptr, flen, inticks);
-
- Py_INCREF(Py_None);
- return Py_None;
- }
- else
- {
- assert(!"asdf");
- }
- }
- assert(!"not reached");
- return NULL;
-}
-DECL(sc_loop_delScoreEvent) // (int id)
-{
- int id;
- if (!PyArg_ParseTuple(args, "i", &id ))
- {
- return NULL;
- }
- sc_tt->loop->delEvent(id);
- RetNone;
-}
-DECL(sc_loop_updateEvent) // (int id)
-{
- int id;
- int idx;
- float val;
- if (!PyArg_ParseTuple(args, "iif", &id, &idx, &val ))
- {
- return NULL;
- }
- sc_tt->loop->updateEvent(id, idx, val);
- RetNone;
-}
-DECL(sc_loop_clear)
-{
- if (!PyArg_ParseTuple(args, "" ))
- {
- return NULL;
- }
- sc_tt->loop->clear();
- RetNone;
-}
-DECL(sc_loop_playing) // (int tf)
-{
- int i;
- if (!PyArg_ParseTuple(args, "i", &i ))
- {
- return NULL;
- }
- sc_tt->thread_playloop = i;
- RetNone;
-}
-DECL (sc_inputMessage) //(const char *msg)
-{
- char * msg;
- if (!PyArg_ParseTuple(args, "s", &msg ))
- {
- return NULL;
- }
- sc_tt->inputMessage(msg);
- RetNone;
-}
-
-#define MDECL(s) {""#s, s, METH_VARARGS, "documentation of "#s"... nothing!"},
-static PyMethodDef SpamMethods[] = {
- {"sc_destroy", sc_destroy, METH_VARARGS,""},
- {"sc_initialize", sc_initialize, METH_VARARGS,""},
- {"sc_start", sc_start, METH_VARARGS,""},
- {"sc_stop", sc_stop, METH_VARARGS,""},
- {"sc_scoreEvent", sc_scoreEvent, METH_VARARGS, ""},
- {"sc_setMasterVolume", sc_setMasterVolume, METH_VARARGS, ""},
- {"sc_setTrackpadX", sc_setTrackpadX, METH_VARARGS, ""},
- {"sc_setTrackpadY", sc_setTrackpadY, METH_VARARGS, ""},
- MDECL(sc_loop_getTick)
- MDECL(sc_loop_setNumTicks)
- MDECL(sc_loop_setTick)
- MDECL(sc_loop_setTickDuration)
- MDECL(sc_loop_delScoreEvent)
- MDECL(sc_loop_addScoreEvent) // (int id, int duration_in_ticks, char type, farray param)
- MDECL(sc_loop_updateEvent) // (int id)
- MDECL(sc_loop_clear)
- MDECL(sc_loop_playing)
- MDECL(sc_inputMessage)
- {NULL, NULL, 0, NULL} /*end of list */
-};
-
-PyMODINIT_FUNC
-initsclient(void)
-{
- (void) Py_InitModule("sclient", SpamMethods);
-}
-
-