diff options
author | amartin <olpc@xo-05-28-21.localdomain> | 2007-08-27 07:41:39 (GMT) |
---|---|---|
committer | amartin <olpc@xo-05-28-21.localdomain> | 2007-08-27 07:41:39 (GMT) |
commit | 4cb29f386d4fe7a8873a5d8a917599c9ebb23a1f (patch) | |
tree | 6938fbf1e02d662f0b6e6b8e0f51db2abbf8387a | |
parent | 7eb4faf55a3935217f24bff9fd1f1ff2618c93ec (diff) | |
parent | 80eae82c46a9b2bcd85e0bbf5821c08323bf7c38 (diff) |
Merge branch 'master' of git+ssh://amartin@dev.laptop.org/git/projects/tamtam
-rw-r--r-- | Edit/EditToolbars.py | 4 | ||||
-rw-r--r-- | Edit/MainWindow.py | 6 | ||||
-rw-r--r-- | Jam/JamMain.py | 2 | ||||
-rw-r--r--[-rwxr-xr-x] | Resources/Images/pageThumbnailBG0.png | bin | 1084 -> 1068 bytes | |||
-rw-r--r--[-rwxr-xr-x] | Resources/Images/pageThumbnailBG1.png | bin | 1069 -> 1073 bytes | |||
-rw-r--r--[-rwxr-xr-x] | Resources/Images/pageThumbnailBG2.png | bin | 1083 -> 1037 bytes | |||
-rw-r--r--[-rwxr-xr-x] | Resources/Images/pageThumbnailBG3.png | bin | 1075 -> 1094 bytes | |||
-rw-r--r-- | Util/CSoundClient.py | 272 | ||||
-rw-r--r-- | Util/Clooper/aclient.cpp | 724 | ||||
-rwxr-xr-x | Util/Clooper/aclient.so | bin | 49464 -> 59030 bytes | |||
-rw-r--r-- | Util/Clooper/audio.cpp | 5 | ||||
-rw-r--r-- | Util/Clooper/log.cpp | 4 | ||||
-rw-r--r-- | miniTamTam/miniTamTamMain.py | 6 |
13 files changed, 524 insertions, 499 deletions
diff --git a/Edit/EditToolbars.py b/Edit/EditToolbars.py index 10c47e8..76264e4 100644 --- a/Edit/EditToolbars.py +++ b/Edit/EditToolbars.py @@ -828,8 +828,8 @@ class propertiesPalette(Palette): self.pageColorBox = gtk.HBox() self.pageColorLabel = gtk.Label(_('Page color: ')) self.pageColorComboBox = BigComboBox() - for color in self.colors: - self.pageColorComboBox.append_item(self.colors.index(color), color) + for color in (0,1,2,3): + self.pageColorComboBox.append_item(color, text = None, icon_name = Config.IMAGE_ROOT + 'pageThumbnailBG' + str(color) + '.png', size = (30,40)) self.pageColorComboBox.set_active(0) self.pageColorComboBox.connect('changed', self.handleColor) self.pageColorBox.pack_start(self.pageColorLabel, False, False, padding = 5) diff --git a/Edit/MainWindow.py b/Edit/MainWindow.py index 1be07df..76c85ae 100644 --- a/Edit/MainWindow.py +++ b/Edit/MainWindow.py @@ -702,7 +702,7 @@ class MainWindow( SubActivity ): self.csnd.loopSetNumTicks( numticks ) self.csnd.loopSetTick( self.page_onset[startPage] + startTick ) - self.csnd.loopSetTempo(self._data['tempo']) + self.csnd.setTempo(self._data['tempo']) if (Config.DEBUG > 3): print "starting from tick", startTick, 'at tempo', self._data['tempo'] self.csnd.loopStart() @@ -865,7 +865,7 @@ class MainWindow( SubActivity ): img = min(7,int(8*(self._data["tempo"]-widget.lower)/(widget.upper-widget.lower)))+1# tempo 1-8 #self.GUI["2tempoImage"].set_from_file( Config.IMAGE_ROOT+"tempo"+str(img)+".png" ) if self.playing: - self.csnd.loopSetTempo(self._data['tempo']) + self.csnd.setTempo(self._data['tempo']) def handleToolClick( self, widget, mode ): if widget.get_active(): self.trackInterface.setInterfaceMode( mode ) @@ -1415,7 +1415,7 @@ class MainWindow( SubActivity ): def waitToSet(self): self.csnd.setMasterVolume(self._data['volume']) - self.csnd.loopSetTempo(self._data['tempo']) + self.csnd.setTempo(self._data['tempo']) self.initTrackVolume() def handleSave(self, widget): diff --git a/Jam/JamMain.py b/Jam/JamMain.py index 8751c74..9ef3fc3 100644 --- a/Jam/JamMain.py +++ b/Jam/JamMain.py @@ -46,7 +46,7 @@ class JamMain(SubActivity): for i in range(1,9): self.csnd.setTrackVolume( 100, i ) self.csnd.setMasterVolume( self.volume ) - self.csnd.loopSetTempo( self.tempo ) + self.csnd.setTempo( self.tempo ) #-- Drawing ------------------------------------------- def darken( colormap, hex ): diff --git a/Resources/Images/pageThumbnailBG0.png b/Resources/Images/pageThumbnailBG0.png Binary files differindex d40b7e8..db2c684 100755..100644 --- a/Resources/Images/pageThumbnailBG0.png +++ b/Resources/Images/pageThumbnailBG0.png diff --git a/Resources/Images/pageThumbnailBG1.png b/Resources/Images/pageThumbnailBG1.png Binary files differindex eb57c00..f0c14ce 100755..100644 --- a/Resources/Images/pageThumbnailBG1.png +++ b/Resources/Images/pageThumbnailBG1.png diff --git a/Resources/Images/pageThumbnailBG2.png b/Resources/Images/pageThumbnailBG2.png Binary files differindex 080027c..4969241 100755..100644 --- a/Resources/Images/pageThumbnailBG2.png +++ b/Resources/Images/pageThumbnailBG2.png diff --git a/Resources/Images/pageThumbnailBG3.png b/Resources/Images/pageThumbnailBG3.png Binary files differindex d444c5f..839b741 100755..100644 --- a/Resources/Images/pageThumbnailBG3.png +++ b/Resources/Images/pageThumbnailBG3.png diff --git a/Util/CSoundClient.py b/Util/CSoundClient.py index 0555929..2bab169 100644 --- a/Util/CSoundClient.py +++ b/Util/CSoundClient.py @@ -12,6 +12,16 @@ from Generation.GenerationConstants import GenerationConstants from Util.Clooper.aclient import * from Util import NoteDB + +_note_template = array.array('f', [0] * 19 ) +def _new_note_array(): + return _note_template.__copy__() + +def _noteid(dbnote): + return (dbnote.page << 16) + dbnote.id + +_loop_default=0 + class _CSoundClientPlugin: #array index constants for csound @@ -37,31 +47,27 @@ class _CSoundClientPlugin: self.on = False #self.masterVolume = 80.0 self.periods_per_buffer = 2 + global _loop_default + _loop_default = self.loopCreate() def __del__(self): self.connect(False) sc_destroy() def setChannel(self, name, val): - if self.on: - sc_setChannel(name, val) + sc_setChannel(name, val) def setMasterVolume(self, volume): - #self.masterVolume = volume - if self.on: - sc_setMasterVolume(volume) + sc_setChannel( 'masterVolume', volume) def setTrackVolume( self, volume, trackId ): - self.trackVolume = volume - sc_setTrackVolume(volume, trackId+1) + sc_setChannel( 'trackVolume' + str(trackId + 1), volume ) def setTrackpadX( self, value ): - trackpadX = value - sc_setTrackpadX(trackpadX) + sc_setChannel( 'trackpadX', value) def setTrackpadY( self, value ): - trackpadY = value - sc_setTrackpadY(trackpadY) + sc_setChannel( 'trackpadY', value) def micRecording( self, table ): sc_inputMessage( Config.CSOUND_MIC_RECORD % table ) @@ -113,37 +119,61 @@ class _CSoundClientPlugin: def inputMessage(self,msg): sc_inputMessage(msg) - def loopClear(self): - sc_loop_clear() - def loopDelete(self, dbnote): - sc_loop_delScoreEvent( (dbnote.page << 16) + dbnote.id) - def loopDelete1(self, page, id): - sc_loop_delScoreEvent( (page << 16) + id) - def loopStart(self): - sc_loop_playing(1) - def loopPause(self): - sc_loop_playing(0) - def loopSetTick(self,t): - sc_loop_setTick(t) - def loopGetTick(self): - return sc_loop_getTick() - def loopSetNumTicks(self,n): - sc_loop_setNumTicks(n) - def loopSetTickDuration(self,d): - sc_loop_setTickDuration(d) - def loopAdjustTick(self,d): - sc_loop_adjustTick(d) - def loopSetTempo(self,t): + def getTick( self ): + return sc_getTickf() + + def adjustTick( self, amt ): + sc_adjustTick(amt) + + def setTempo(self,t): if (Config.DEBUG > 3) : print 'INFO: loop tempo: %f -> %f' % (t, 60.0 / (Config.TICKS_PER_BEAT * t)) - sc_loop_setTickDuration( 60.0 / (Config.TICKS_PER_BEAT * t)) + sc_setTickDuration( 60.0 / (Config.TICKS_PER_BEAT * t)) + + + def loopCreate(self): + return sc_loop_new() + + def loopDestroy(self, loopId): + sc_loop_delete(loopId) + + def loopClear(self): + global _loop_default + sc_loop_delete(_loop_default) + _loop_default = sc_loop_new() + + # this is function deletes an Event from a loop + # TODO: rename this function + def loopDelete(self, dbnote, loopId=_loop_default): + sc_loop_delScoreEvent( loopId, _noteid(dbnote)) + + def loopDelete1(self, page, id, loopId=_loop_default): + sc_loop_delScoreEvent( loopId, (page << 16) + id) + + def loopStart(self, loopId=_loop_default): + sc_loop_playing(loopId, 1) - def loopDeactivate(self, note = None): - if note == None: - sc_loop_deactivate_all() + def loopPause(self, loopId=_loop_default): + sc_loop_playing(loopId, 0) + + def loopSetTick(self,t, loopId=_loop_default): + sc_loop_setTickf(loopId, t) + + def loopGetTick(self, loopId=_loop_default): + return sc_loop_getTickf(loopId) + + def loopSetNumTicks(self,n, loopId=_loop_default): + sc_loop_setNumTicks(loopId, n) + + def loopSetTickDuration(self,d, loopId=_loop_default): + sc_loop_setTickDuration(loopId, d) + + def loopDeactivate(self, note = 'all', loopId=_loop_default): + if note == 'all': + sc_loop_deactivate_all(loopId) else: if (Config.DEBUG > 0) : print 'ERROR: deactivating a single note is not implemented' - def loopUpdate(self, note, parameter, value,cmd): + def loopUpdate(self, note, parameter, value,cmd, loopId=_loop_default): page = note.page track = note.track id = note.id @@ -156,7 +186,7 @@ class _CSoundClientPlugin: instrument_id_offset = 100 if (parameter == NoteDB.PARAMETER.ONSET): if (Config.DEBUG > 2): print 'INFO: updating onset', (page<<16)+id, value - sc_loop_updateEvent( (page<<16)+id, 1, value, cmd) + sc_loop_updateEvent( loopId, (page<<16)+id, 1, value, cmd) elif (parameter == NoteDB.PARAMETER.PITCH): if (Config.DEBUG > 2): print 'INFO: updating pitch', (page<<16)+id, value pitch = value @@ -165,18 +195,18 @@ class _CSoundClientPlugin: csoundInstId = instrument.csoundInstrumentId csoundTable = Config.INSTRUMENT_TABLE_OFFSET + instrument.instrumentId if (Config.DEBUG > 2): print 'INFO: updating drum instrument (pitch)', (page<<16)+id, instrument.name, csoundInstId - sc_loop_updateEvent( (page<<16)+id, 0, (csoundInstId + instrument_id_offset) + note.track * 0.01, -1 ) - sc_loop_updateEvent( (page<<16)+id, 7, csoundTable , -1 ) + sc_loop_updateEvent( loopId, (page<<16)+id, 0, (csoundInstId + instrument_id_offset) + note.track * 0.01, -1 ) + sc_loop_updateEvent( loopId, (page<<16)+id, 7, csoundTable , -1 ) pitch = 1 else: pitch = GenerationConstants.TRANSPOSE[ pitch - 24 ] - sc_loop_updateEvent( (page<<16)+id, 3, pitch, cmd) + sc_loop_updateEvent( loopId, (page<<16)+id, 3, pitch, cmd) elif (parameter == NoteDB.PARAMETER.AMPLITUDE): if (Config.DEBUG > 2): print 'INFO: updating amp', (page<<16)+id, value - sc_loop_updateEvent( (page<<16)+id, 5, value, cmd) + sc_loop_updateEvent( loopId, (page<<16)+id, 5, value, cmd) elif (parameter == NoteDB.PARAMETER.DURATION): if (Config.DEBUG > 2): print 'INFO: updating duration', (page<<16)+id, value - sc_loop_updateEvent( (page<<16)+id, self.DURATION, value, cmd) + sc_loop_updateEvent( loopId, (page<<16)+id, self.DURATION, value, cmd) elif (parameter == NoteDB.PARAMETER.INSTRUMENT): pitch = note.cs.pitch instrument = Config.INSTRUMENTSID[value] @@ -188,42 +218,43 @@ class _CSoundClientPlugin: loopEnd = instrument.loopEnd crossDur = instrument.crossDur if (Config.DEBUG > 2): print 'INFO: updating instrument', (page<<16)+id, instrument.name, csoundInstId - sc_loop_updateEvent( (page<<16)+id, 0, (csoundInstId + (track+1) + instrument_id_offset) + note.track * 0.01, cmd ) - sc_loop_updateEvent( (page<<16)+id, 7, csoundTable, -1 ) - sc_loop_updateEvent( (page<<16)+id, 12, loopStart, -1 ) - sc_loop_updateEvent( (page<<16)+id, 13, loopEnd, -1 ) - sc_loop_updateEvent( (page<<16)+id, 14, crossDur , -1 ) + sc_loop_updateEvent( loopId, (page<<16)+id, 0, (csoundInstId + (track+1) + instrument_id_offset) + note.track * 0.01, cmd ) + sc_loop_updateEvent( loopId, (page<<16)+id, 7, csoundTable, -1 ) + sc_loop_updateEvent( loopId, (page<<16)+id, 12, loopStart, -1 ) + sc_loop_updateEvent( loopId, (page<<16)+id, 13, loopEnd, -1 ) + sc_loop_updateEvent( loopId, (page<<16)+id, 14, crossDur , -1 ) elif (parameter == NoteDB.PARAMETER.PAN): - sc_loop_updateEvent( (page<<16)+id, self.PAN, value, cmd) + sc_loop_updateEvent( loopId, (page<<16)+id, self.PAN, value, cmd) elif (parameter == NoteDB.PARAMETER.REVERB): - sc_loop_updateEvent( (page<<16)+id, self.REVERBSEND, value, cmd) + sc_loop_updateEvent( loopId, (page<<16)+id, self.REVERBSEND, value, cmd) elif (parameter == NoteDB.PARAMETER.ATTACK): - sc_loop_updateEvent( (page<<16)+id, self.ATTACK, value, cmd) + sc_loop_updateEvent( loopId, (page<<16)+id, self.ATTACK, value, cmd) elif (parameter == NoteDB.PARAMETER.DECAY): - sc_loop_updateEvent( (page<<16)+id, self.DECAY, value, cmd) + sc_loop_updateEvent( loopId, (page<<16)+id, self.DECAY, value, cmd) elif (parameter == NoteDB.PARAMETER.FILTERTYPE): - sc_loop_updateEvent( (page<<16)+id, self.FILTERTYPE, value, cmd) + sc_loop_updateEvent( loopId, (page<<16)+id, self.FILTERTYPE, value, cmd) elif (parameter == NoteDB.PARAMETER.FILTERCUTOFF): - sc_loop_updateEvent( (page<<16)+id, self.FILTERCUTOFF, value, cmd) + sc_loop_updateEvent( loopId, (page<<16)+id, self.FILTERCUTOFF, value, cmd) elif (parameter == NoteDB.PARAMETER.INSTRUMENT2): - sc_loop_updateEvent( (page<<16)+id, self.INSTRUMENT2, value, cmd) + sc_loop_updateEvent( loopId, (page<<16)+id, self.INSTRUMENT2, value, cmd) else: if (Config.DEBUG > 0): print 'ERROR: loopUpdate(): unsupported parameter change' - - def loopPlay(self, dbnote, active): + def loopPlay(self, dbnote, active, storage=_new_note_array(), + loopId=_loop_default ): qid = (dbnote.page << 16) + dbnote.id - sc_loop_addScoreEvent( qid, 1, active, 'i', self.csnote_to_array(dbnote.cs)) + sc_loop_addScoreEvent( loopId, qid, 1, active, 'i', + self.csnote_to_array( dbnote.cs, storage)) - def play(self, csnote, secs_per_tick): - a = self.csnote_to_array(csnote) + def play(self, csnote, secs_per_tick, storage=_new_note_array()): + a = self.csnote_to_array(csnote, storage) a[self.DURATION] = a[self.DURATION] * secs_per_tick a[self.ATTACK] = max(a[self.ATTACK]*a[self.DURATION], 0.002) a[self.DECAY] = max(a[self.DECAY]*a[self.DURATION], 0.002) sc_scoreEvent( 'i', a) - def csnote_to_array(self, csnote): - return self.csnote_to_array1( + def csnote_to_array(self, csnote, storage): + return self._csnote_to_array1(storage, csnote.onset, csnote.pitch, csnote.amplitude, @@ -240,22 +271,11 @@ class _CSoundClientPlugin: csnote.mode, csnote.instrumentId2 ) - def csnote_to_array1( self, onset, - pitch, - amplitude, - pan, - duration, - trackId, - attack = 0.002, - decay = 0.098, - reverbSend = 0.1, - filterType = 0, - filterCutoff = 1000, - tied = False, - instrumentId = Config.INSTRUMENTS["flute"].instrumentId, - mode = 'edit', - instrumentId2 = -1 ): + def _csnote_to_array1( self, storage, onset, pitch, amplitude, pan, duration, + trackId, attack, decay, reverbSend, filterType, filterCutoff, + tied, instrumentId, mode, instrumentId2 = -1): + rval=storage instrument = Config.INSTRUMENTSID[instrumentId] if instrument.kit != None: instrument = instrument.kit[pitch] @@ -267,63 +287,61 @@ class _CSoundClientPlugin: instrument_id_offset = 0 # condition for tied notes - if instrument.csoundInstrumentId == Config.INST_TIED and tied and mode == 'mini': - duration = -1 - instrument_id_offset = 0 - elif instrument.csoundInstrumentId == Config.INST_TIED and not tied and mode == 'mini': - instrument_id_offset = 0 - elif instrument.csoundInstrumentId == Config.INST_TIED and tied and mode == 'edit' and duration < 0: - duration = -1 - instrument_id_offset = 0 - elif instrument.csoundInstrumentId == Config.INST_TIED and tied and mode == 'edit' and duration > 0: - instrument_id_offset = 0 - elif instrument.csoundInstrumentId == Config.INST_TIED and not tied and mode == 'edit': - instrument_id_offset = 100 - - if instrument.csoundInstrumentId == Config.INST_SIMP and mode == 'mini': - instrument_id_offset = 0 - elif instrument.csoundInstrumentId == Config.INST_SIMP and mode == 'edit': - if instrument.soundClass == 'drum': - instrument_id_offset = 0 + if instrument.csoundInstrumentId == Config.INST_TIED: + if tied: + if mode == 'mini': + duration = -1 + instrument_id_offset = 0 + elif mode == 'edit': + instrument_id_offset = 0 + if duration < 0: + duration = -1 else: - instrument_id_offset = 100 + if mode == 'mini': + instrument_id_offset = 0 + elif mode == 'edit': + instrument_id_offset = 100 + + if instrument.csoundInstrumentId == Config.INST_SIMP: + if mode == 'mini': + instrument_id_offset = 0 + elif mode == 'edit': + if instrument.soundClass == 'drum': + instrument_id_offset = 0 + else: + instrument_id_offset = 100 + + rval[0] = (instrument.csoundInstrumentId + \ + (trackId+1) + instrument_id_offset) + trackId * 0.01 + rval[1] = onset + rval[2] = duration + rval[3] = pitch + rval[4] = reverbSend + rval[5] = amplitude + rval[6] = pan + rval[7] = Config.INSTRUMENT_TABLE_OFFSET + instrument.instrumentId + rval[8] = attack + rval[9] = decay + rval[10]= filterType + rval[11]= filterCutoff + rval[12]= instrument.loopStart + rval[13]= instrument.loopEnd + rval[14]= instrument.crossDur if instrumentId2 != -1: instrument2 = Config.INSTRUMENTSID[instrumentId2] csInstrumentId2 = (instrument2.csoundInstrumentId + 100) * 0.0001 - secondInstrument = Config.INSTRUMENT_TABLE_OFFSET + instrumentId2 + csInstrumentId2 - loopStart2 = instrument2.loopStart - loopEnd2 = instrument2.loopEnd - crossDur2 = instrument2.crossDur + rval[15] = Config.INSTRUMENT_TABLE_OFFSET + instrumentId2 + csInstrumentId2 + rval[16] = instrument2.loopStart + rval[17] = instrument2.loopEnd + rval[18] = instrument2.crossDur else: - secondInstrument = -1 - loopStart2 = 0 - loopEnd2 = 0 - crossDur2 = 0 - - a = array.array('f') - a.extend( [ - (instrument.csoundInstrumentId + (trackId+1) + instrument_id_offset) + trackId * 0.01, - onset, - duration, - pitch, - reverbSend, - amplitude, - pan, - Config.INSTRUMENT_TABLE_OFFSET + instrument.instrumentId, - attack, - decay, - filterType, - filterCutoff, - instrument.loopStart, - instrument.loopEnd, - instrument.crossDur, - secondInstrument, - loopStart2, - loopEnd2, - crossDur2]) - return a + rval[15] = -1 + rval[16] = 0 + rval[17] = 0 + rval[18] = 0 + return rval _Client = None diff --git a/Util/Clooper/aclient.cpp b/Util/Clooper/aclient.cpp index 1755438..1146c3b 100644 --- a/Util/Clooper/aclient.cpp +++ b/Util/Clooper/aclient.cpp @@ -27,22 +27,22 @@ static double pytime(const struct timeval * tv) #include "log.cpp" #include "audio.cpp" -#define ERROR_HERE if (_debug && (VERBOSE > 0)) fprintf(_debug, "ERROR: %s:%i\n", __FILE__, __LINE__) - -#define IF_DEBUG(N) if (_debug && (VERBOSE > N)) #define FLOAT_TO_SHORT(in,out) __asm__ __volatile__ ("fistps %0" : "=m" (out) : "t" (in) : "st") ; int VERBOSE = 3; FILE * _debug = NULL; struct TamTamSound; -TamTamSound * sc_tt = NULL; +struct Music; +TamTamSound * g_tt = NULL; +Music * g_music = NULL; log_t * g_log = NULL; +const int STEP_eventMax = 16; //this is the most events that will be queued by a loop per step() /** - * ev_t is the type of event that Clooper puts in the loop buffer. + * Event is the type of event that Clooper puts in the loop buffer. * It corresponds to a line of csound that starts with an 'i' */ -struct ev_t +struct Event { char type; ///< if this event were listed in a csound file, the line would begin with this letter int onset; ///< the onset time of this event (its temporal position) @@ -52,7 +52,7 @@ struct ev_t MYFLT duration, attack, decay;///< canonical values of some tempo-dependent parameters std::vector<MYFLT> param; ///< parameter buffer for csound - ev_t(char type, MYFLT * p, int param_count, bool in_ticks, bool active) + Event(char type, MYFLT * p, int param_count, bool in_ticks, bool active) : type(type), onset(0), time_in_ticks(in_ticks), active(active), param(param_count) { assert(param_count >= 4); @@ -66,7 +66,7 @@ struct ev_t param[1] = 0.0; //onset } /* - bool operator<(const ev_t &e) const + bool operator<(const Event &e) const { return onset < e.onset; } @@ -111,9 +111,9 @@ struct ev_t } } /** - * An ev_t instance can be in an active or inactive state. If an ev_t instance + * An Event instance can be in an active or inactive state. If an Event instance * is active, then event() will call a corresponding csoundScoreEvent(). If an - * ev_t instance is inactive, then event() is a noop. + * Event instance is inactive, then event() is a noop. */ void activate_cmd(int cmd) { @@ -150,117 +150,80 @@ struct ev_t /** * - * EvLoop is a repeat-able loop of ev_t instances. + * Loop is a repeat-able loop of Event instances. * */ -struct EvLoop +struct Loop { + typedef int onset_t; + typedef int id_t; + typedef std::pair<onset_t, Event *> pair_t; + typedef std::multimap<onset_t, Event *>::iterator iter_t; + typedef std::map<id_t, iter_t>::iterator idmap_t; + int tick_prev; int tickMax; MYFLT rtick; - MYFLT secs_per_tick; - 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; + // a container of all events, sorted by onset time + // used for efficient playback + std::multimap<onset_t, Event *> ev; + // the playback head + std::multimap<onset_t, Event *>::iterator ev_pos; + // a container of pointers into ev, indexed by note id + // used for deleting, updating notes + std::map<id_t, iter_t> idmap; int steps; - TamTamSound * tt; + int playing; //true means that step() works, else step() is no-op - EvLoop(CSOUND * cs, TamTamSound * tt) : tick_prev(0), tickMax(1), rtick(0.0), ev(), ev_pos(ev.end()), csound(cs), mutex(NULL), steps(0), tt(tt) + Loop() : tick_prev(0), tickMax(1), rtick(0.0), ev(), ev_pos(ev.end()), steps(0), playing(0) { - 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() + ~Loop() { - csoundLockMutex(mutex); + //TODO: send these events to a recycling queue, don't erase them 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); } void deactivateAll() { - csoundLockMutex(mutex); for (iter_t i = ev.begin(); i != ev.end(); ++i) { i->second->activate_cmd(0); } - csoundUnlockMutex(mutex); } - int getTick() + MYFLT getTickf() { - return (int)rtick % tickMax; - } - float getTickf(bool mod) - { - if (mod) - { - return fmod(rtick, (MYFLT)tickMax); - } - else - { - return rtick; - } + return fmod(rtick, (MYFLT)tickMax); } void setNumTicks(int nticks) { tickMax = nticks; - if ((int)rtick > nticks) + MYFLT fnticks = nticks; + if (rtick > fnticks) { - int t = (int)rtick % nticks; - rtick = t; + rtick = fmodf(rtick, fnticks); } } - void setTick(int t) + void setTickf(float 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) { - if (_debug && (VERBOSE > 1)) fprintf(_debug, "skipping setTickDuration, csound==NULL\n"); - return; - } - secs_per_tick = d; + rtick = fmodf(t, (MYFLT) tickMax); + ev_pos = ev.lower_bound( (int) rtick ); } /** advance in play loop by rtick_inc ticks, possibly generate some * csoundScoreEvent calls. */ - void step(MYFLT rtick_inc ) + void step(MYFLT rtick_inc, MYFLT secs_per_tick , CSOUND * csound) { + if (!playing) return; rtick += rtick_inc; 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 (steps && (tick < tick_prev)) // should be true only after the loop wraps (not after insert) @@ -268,7 +231,7 @@ struct EvLoop while (ev_pos != ev.end()) { if (_debug && (VERBOSE > 3)) ev_pos->second->ev_print(_debug); - if (events < eventMax) ev_pos->second->event(csound, secs_per_tick); + if (events < STEP_eventMax) ev_pos->second->event(csound, secs_per_tick); ++ev_pos; ++events; ++loop0; @@ -278,92 +241,250 @@ struct EvLoop while ((ev_pos != ev.end()) && (tick >= ev_pos->first)) { if (_debug && (VERBOSE > 3)) ev_pos->second->ev_print(_debug); - if (events < eventMax) ev_pos->second->event(csound, secs_per_tick); + if (events < STEP_eventMax) ev_pos->second->event(csound, secs_per_tick); ++ev_pos; ++events; ++loop1; } } - csoundUnlockMutex(mutex); tick_prev = tick; - if (_debug && (VERBOSE>1) && (events >= eventMax)) fprintf(_debug, "WARNING: %i/%i events at once (%i, %i)\n", events,ev.size(),loop0,loop1); + if (_debug && (VERBOSE>1) && (events >= STEP_eventMax)) fprintf(_debug, "WARNING: %i/%i events at once (%i, %i)\n", events,ev.size(),loop0,loop1); ++steps; } void addEvent(int id, char type, MYFLT * p, int np, bool in_ticks, bool active) { - ev_t * e = new ev_t(type, p, np, in_ticks, active); + Event * e = new Event(type, p, np, in_ticks, active); 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 && (VERBOSE > 0)) fprintf(_debug, "ERROR: skipping request to add duplicate note %i\n", id); + g_log->printf(1, "%s duplicate note %i\n", __FUNCTION__, id); } } void delEvent(int id) { idmap_t id_iter = idmap.find(id); - if (id_iter == idmap.end()) - { - if (_debug && (VERBOSE > 0)) fprintf(_debug, "ERROR: delEvent request for unknown note %i\n", id); - } - else + if (id_iter != idmap.end()) { - 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); + } + else + { + g_log->printf( 1, "%s unknown note %i\n", __FUNCTION__, id); } } void updateEvent(int id, int idx, float val, int activate_cmd) { idmap_t id_iter = idmap.find(id); - if (id_iter == idmap.end()) + if (id_iter != idmap.end()) { - if (_debug && (VERBOSE > 0)) fprintf(_debug, "ERROR: updateEvent request for unknown note %i\n", id); - return; - } + //this is a new id + iter_t e_iter = id_iter->second; + Event * e = e_iter->second; + int onset = e->onset; + e->update(idx, val); + e->activate_cmd(activate_cmd); + if (onset != e->onset) + { + ev.erase(e_iter); - //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); - e->activate_cmd(activate_cmd); - if (onset != e->onset) + 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; + } + } + else { - ev.erase(e_iter); + g_log->printf(1, "%s unknown note %i\n", __FUNCTION__, id); + } + } + void reset() + { + steps = 0; + } + void setPlaying(int tf) + { + playing = tf; + } +}; - e_iter = ev.insert(pair_t(e->onset, e)); +/** management of loops */ +struct Music +{ + typedef int loopIdx_t; + typedef std::map<int, Loop * > eventMap_t; - //TODO: optimize by thinking about whether to do ev_pos = e_iter - ev_pos = ev.upper_bound( tick_prev ); - idmap[id] = e_iter; + eventMap_t loop; + int loop_nextIdx; + void * mutex; //modification and playing of loops cannot be interwoven + + Music() : + loop(), + loop_nextIdx(0), + mutex(csoundCreateMutex(0)) + { + } + ~Music() + { + for (eventMap_t::iterator i = loop.begin(); i != loop.end(); ++i) + { + delete i->second; + } + csoundDestroyMutex(mutex); + } + + void step(MYFLT amt, MYFLT secs_per_tick, CSOUND * csound) + { + csoundLockMutex(mutex); + for (eventMap_t::iterator i = loop.begin(); i != loop.end(); ++i) + { + i->second->step(amt, secs_per_tick, csound); } csoundUnlockMutex(mutex); } - void reset() + + /** allocate a new loop, and return its index */ + loopIdx_t alloc() { - steps = 0; + csoundLockMutex(mutex); + //find a loop_nextIdx that isn't in loop map already + while ( loop.find( loop_nextIdx) != loop.end()) ++loop_nextIdx; + loop[loop_nextIdx] = new Loop(); + csoundUnlockMutex(mutex); + return loop_nextIdx; + } + /** de-allocate a loop */ + void destroy(loopIdx_t loopIdx) + { + if (loop.find(loopIdx) != loop.end()) + { + csoundLockMutex(mutex); + //TODO: save the note events to a cache for recycling + delete loop[loopIdx]; + loop.erase(loopIdx); + csoundUnlockMutex(mutex); + } + else + { + g_log->printf(1, "%s() called on non-existant loop %i\n", __FUNCTION__ , loopIdx); + } + } + /** set the playing flag of the given loop */ + void playing(loopIdx_t loopIdx, int tf) + { + if (loop.find(loopIdx) != loop.end()) + { + csoundLockMutex(mutex); + loop[loopIdx]->setPlaying(tf); + csoundUnlockMutex(mutex); + } + else + { + g_log->printf(1, "%s() called on non-existant loop %i\n", __FUNCTION__ , loopIdx); + } + } + /** set the playing flag of the given loop */ + void addEvent(loopIdx_t loopIdx, int eventId, char type, MYFLT * p, int np, bool in_ticks, bool active) + { + if (loop.find(loopIdx) != loop.end()) + { + csoundLockMutex(mutex); + loop[loopIdx]->addEvent(eventId, type, p, np, in_ticks, active); + csoundUnlockMutex(mutex); + } + else + { + g_log->printf(1, "%s() called on non-existant loop %i\n", __FUNCTION__ , loopIdx); + } + } + void delEvent(loopIdx_t loopIdx, int eventId) + { + if (loop.find(loopIdx) != loop.end()) + { + csoundLockMutex(mutex); + loop[loopIdx]->delEvent(eventId); + csoundUnlockMutex(mutex); + } + else + { + g_log->printf(1, "%s() called on non-existant loop %i\n", __FUNCTION__ , loopIdx); + } + } + void updateEvent(loopIdx_t loopIdx, int eventId, int pIdx, float pVal, int activate_cmd) + { + if (loop.find(loopIdx) != loop.end()) + { + csoundLockMutex(mutex); + loop[loopIdx]->updateEvent(eventId, pIdx, pVal, activate_cmd); + csoundUnlockMutex(mutex); + } + else + { + g_log->printf(1, "%s() called on non-existant loop %i\n", __FUNCTION__ , loopIdx); + } + } + MYFLT getTickf(loopIdx_t loopIdx) + { + if (loop.find(loopIdx) != loop.end()) + { + return loop[loopIdx]->getTickf(); + } + else + { + g_log->printf(1, "%s() called on non-existant loop %i\n", __FUNCTION__ , loopIdx); + return 0.0; + } } + void setTickf(loopIdx_t loopIdx, MYFLT tickf) + { + if (loop.find(loopIdx) != loop.end()) + { + loop[loopIdx]->setTickf(tickf); + } + else + { + g_log->printf(1, "%s() called on non-existant loop %i\n", __FUNCTION__ , loopIdx); + } + } + void setNumTicks(loopIdx_t loopIdx, int numTicks) + { + if (loop.find(loopIdx) != loop.end()) + { + loop[loopIdx]->setNumTicks(numTicks); + } + else + { + g_log->printf(1, "%s() called on non-existant loop %i\n", __FUNCTION__ , loopIdx); + } + } + void deactivateAll(loopIdx_t loopIdx) + { + if (loop.find(loopIdx) != loop.end()) + { + loop[loopIdx]->deactivateAll(); + } + else + { + g_log->printf(1, "%s() called on non-existant loop %i\n", __FUNCTION__ , loopIdx); + } + } + }; /** @@ -381,10 +502,13 @@ struct TamTamSound enum {CONTINUE, STOP} PERF_STATUS; /** our csound object, NULL iff there was a problem creating it */ CSOUND * csound; + /** our note sources */ + Music music; - EvLoop * loop; - /** a flag, true iff the thread should play&advance the loop */ - int thread_playloop; + MYFLT secs_per_tick; + MYFLT ticks_per_period; + MYFLT tick_adjustment; //the default time increment in thread_fn + MYFLT tick_total; /** the upsampling ratio from csound */ unsigned int csound_ksmps; @@ -394,21 +518,20 @@ struct TamTamSound unsigned int period_per_buffer; //should be 2 int up_ratio; //if the hardware only supports a small integer multiple of our effective samplerate, do a real-time conversion - MYFLT ticks_per_period, tick_adjustment; //the default time increment in thread_fn - log_t * ll; SystemStuff * sys_stuff; TamTamSound(log_t * ll, char * orc, snd_pcm_uframes_t period0, unsigned int ppb, int ksmps, int framerate ) : ThreadID(NULL), PERF_STATUS(STOP), csound(NULL), - loop(NULL), thread_playloop(0), + music(), + ticks_per_period(0.0), + tick_adjustment(0.0), + tick_total(0.0), csound_ksmps(ksmps), //must agree with the orchestra file csound_frame_rate(framerate), //must agree with the orchestra file period0(period0), period_per_buffer(ppb), up_ratio(1), - ticks_per_period(1.0), - tick_adjustment(0.0), ll( ll ), sys_stuff(NULL) { @@ -441,14 +564,13 @@ struct TamTamSound ll->printf( "ERROR: csoundCompile of orchestra %s failed with code %i\n", orc, result); } free(argv); - loop = new EvLoop(csound, this); + setTickDuration(0.05); } ~TamTamSound() { if (csound) { stop(); - delete loop; ll->printf(2, "Going for csoundDestroy\n"); csoundDestroy(csound); } @@ -456,6 +578,11 @@ struct TamTamSound if (sys_stuff) delete sys_stuff; delete ll; } + bool good() + { + return csound != NULL; + } + uintptr_t thread_fn() { assert(csound); @@ -482,6 +609,8 @@ struct TamTamSound int up_pos = 0; int ratio_pos = 0; + tick_total = 0.0f; + while (PERF_STATUS == CONTINUE) { if ( do_upsample ) //fill one period of audio buffer data by 0 or more calls to csound @@ -528,17 +657,16 @@ struct TamTamSound if (0 > sys_stuff->writebuf(csound_nframes,upbuf)) break; } - if (thread_playloop) + if (tick_adjustment > - ticks_per_period) { - if (tick_adjustment > - ticks_per_period) - { - loop->step(ticks_per_period + tick_adjustment); - tick_adjustment = 0.0; - } - else - { - tick_adjustment += ticks_per_period; - } + MYFLT tick_inc = ticks_per_period + tick_adjustment; + music.step( tick_inc, secs_per_tick, csound); + tick_adjustment = 0.0; + tick_total += tick_inc; + } + else + { + tick_adjustment += ticks_per_period; } ++nloops; } @@ -587,6 +715,7 @@ struct TamTamSound return 1; } + /** pass an array event straight through to csound. only works if perf. thread is running */ void scoreEvent(char type, MYFLT * p, int np) { if (!csound) { @@ -606,6 +735,7 @@ struct TamTamSound } csoundScoreEvent(csound, type, p, np); } + /** pass a string event straight through to csound. only works if perf. thread is running */ void inputMessage(const char * msg) { if (!csound) { @@ -620,11 +750,7 @@ struct TamTamSound if (_debug &&(VERBOSE > 3)) fprintf(_debug, "%s\n", msg); csoundInputMessage(csound, msg); } - bool good() - { - return csound != NULL; - } - + /** pass a setChannel command through to csound. only works if perf. thread is running */ void setChannel(const char * name, MYFLT vol) { if (!csound) { @@ -645,113 +771,30 @@ struct TamTamSound } } - void setMasterVolume(MYFLT vol) - { - if (!csound) { - ll->printf(1, "skipping %s, csound==NULL\n", __FUNCTION__); - return; - } - if (!ThreadID) - { - if (_debug && (VERBOSE > 1)) fprintf(_debug, "skipping %s, ThreadID==NULL\n", __FUNCTION__); - return ; - } - MYFLT *p; - if (!(csoundGetChannelPtr(csound, &p, "masterVolume", CSOUND_CONTROL_CHANNEL | CSOUND_INPUT_CHANNEL))) - *p = (MYFLT) vol; - else - { - if (_debug && (VERBOSE >0)) fprintf(_debug, "ERROR: failed to set master volume\n"); - } - } - - void setTrackVolume(MYFLT vol, int Id) - { - if (!csound) { - ll->printf(1, "skipping %s, csound==NULL\n", __FUNCTION__); - return; - } - if (!ThreadID) - { - if (_debug && (VERBOSE > 1)) fprintf(_debug, "skipping %s, ThreadID==NULL\n", __FUNCTION__); - return ; - } - MYFLT *p; - char buf[128]; - sprintf( buf, "trackVolume%i", Id); - if (_debug && (VERBOSE > 10)) fprintf(_debug, "DEBUG: setTrackvolume string [%s]\n", buf); - if (!(csoundGetChannelPtr(csound, &p, buf, CSOUND_CONTROL_CHANNEL | CSOUND_INPUT_CHANNEL))) - *p = (MYFLT) vol; - else - { - if (_debug) fprintf(_debug, "ERROR: failed to set track volume\n"); - } - } - - void setTrackpadX(MYFLT value) - { - if (!csound) { - ll->printf(1, "skipping %s, csound==NULL\n", __FUNCTION__); - return; - } - if (!ThreadID) - { - if (_debug && (VERBOSE > 1)) fprintf(_debug, "skipping %s, ThreadID==NULL\n", __FUNCTION__); - return ; - } - MYFLT *p; - if (!(csoundGetChannelPtr(csound, &p, "trackpadX", CSOUND_CONTROL_CHANNEL | CSOUND_INPUT_CHANNEL))) - *p = (MYFLT) value; - else - { - if (_debug && (VERBOSE > 0)) fprintf(_debug, "ERROR: failed to set trackpad X value\n"); - } - } - - void setTrackpadY(MYFLT value) - { - if (!csound) { - ll->printf(1, "skipping %s, csound==NULL\n", __FUNCTION__); - return; - } - if (!ThreadID) - { - if (_debug && (VERBOSE > 1)) fprintf(_debug, "skipping %s, ThreadID==NULL\n", __FUNCTION__); - return ; - } - MYFLT *p; - if (!(csoundGetChannelPtr(csound, &p, "trackpadY", CSOUND_CONTROL_CHANNEL | CSOUND_INPUT_CHANNEL))) - *p = (MYFLT) value; - else - { - if (_debug && (VERBOSE >0)) fprintf(_debug, "ERROR: failed to set trackpad Y value\n"); - } - } - void loopPlaying(int tf) + /** adjust the global tick value by this much */ + void adjustTick(MYFLT dtick) { - thread_playloop= tf; - if (tf) loop->reset(); + tick_adjustment += dtick; } - - void setTickDuration(MYFLT secs_per_tick ) + void setTickDuration(MYFLT d ) { - if (loop) loop->setTickDuration( secs_per_tick); + secs_per_tick = d; ticks_per_period = csound_period_size / ( secs_per_tick * csound_frame_rate); ll->printf( 3, "INFO: duration %lf := ticks_per_period %lf\n", secs_per_tick , ticks_per_period); } - void adjustTick(MYFLT dtick) + MYFLT getTickf() { - tick_adjustment += dtick; + return tick_total + tick_adjustment; } }; static void cleanup(void) { - if (sc_tt) + if (g_tt) { - delete sc_tt; - sc_tt = NULL; + delete g_tt; + g_tt = NULL; } } @@ -765,10 +808,10 @@ DECL(sc_destroy) { return NULL; } - if (sc_tt) + if (g_tt) { - delete sc_tt; - sc_tt = NULL; + delete g_tt; + g_tt = NULL; if (_debug) fclose(_debug); } RetNone; @@ -798,9 +841,10 @@ DECL(sc_initialize) //(char * csd) fprintf(stderr, "Logging disabled on purpose\n"); } g_log = new log_t(_debug, VERBOSE); - sc_tt = new TamTamSound(g_log, str, period, ppb, ksmps, framerate); + g_tt = new TamTamSound(g_log, str, period, ppb, ksmps, framerate); + g_music = & g_tt->music; atexit(&cleanup); - if (sc_tt->good()) + if (g_tt->good()) return Py_BuildValue("i", 0); else return Py_BuildValue("i", -1); @@ -813,7 +857,7 @@ DECL(sc_start) { return NULL; } - return Py_BuildValue("i", sc_tt->start(ppb)); + return Py_BuildValue("i", g_tt->start(ppb)); } //stop csound rendering thread, disconnect from sound device, clear tables. DECL(sc_stop) @@ -822,7 +866,7 @@ DECL(sc_stop) { return NULL; } - return Py_BuildValue("i", sc_tt->stop()); + return Py_BuildValue("i", g_tt->stop()); } DECL(sc_scoreEvent) //(char type, farray param) { @@ -843,7 +887,7 @@ DECL(sc_scoreEvent) //(char type, farray param) len = o->ob_type->tp_as_buffer->bf_getreadbuffer(o, 0, &ptr); float * fptr = (float*)ptr; size_t flen = len / sizeof(float); - sc_tt->scoreEvent(ev_type, fptr, flen); + g_tt->scoreEvent(ev_type, fptr, flen); Py_INCREF(Py_None); return Py_None; @@ -856,120 +900,100 @@ DECL(sc_scoreEvent) //(char type, farray param) assert(!"not reached"); return NULL; } -DECL(sc_setChannel) //(float v) +DECL (sc_inputMessage) //(const char *msg) { - const char * str; - float v; - if (!PyArg_ParseTuple(args, "sf", &str,&v)) + char * msg; + if (!PyArg_ParseTuple(args, "s", &msg )) { return NULL; } - sc_tt->setChannel(str,v); - Py_INCREF(Py_None); - return Py_None; + g_tt->inputMessage(msg); + RetNone; } -DECL(sc_setMasterVolume) //(float v) +DECL(sc_setChannel) //(string name, float value) { + const char * str; float v; - if (!PyArg_ParseTuple(args, "f", &v)) + if (!PyArg_ParseTuple(args, "sf", &str,&v)) { return NULL; } - sc_tt->setMasterVolume(v); + g_tt->setChannel(str,v); Py_INCREF(Py_None); return Py_None; } -DECL(sc_setTrackVolume) //(float v) +DECL(sc_getTickf) // () -> float { - float v; - int i; - if (!PyArg_ParseTuple(args, "fi", &v, &i)) + if (!PyArg_ParseTuple(args, "")) { return NULL; } - sc_tt->setTrackVolume(v,i); - Py_INCREF(Py_None); - return Py_None; + return Py_BuildValue("f", g_tt->getTickf()); } -DECL(sc_setTrackpadX) //(float v) +DECL(sc_adjustTick) // (MYFLT ntick) { - float v; - if (!PyArg_ParseTuple(args, "f", &v)) + float spt; + if (!PyArg_ParseTuple(args, "f", &spt )) { return NULL; } - sc_tt->setTrackpadX(v); - Py_INCREF(Py_None); - return Py_None; + g_tt->adjustTick(spt); + RetNone; } -DECL(sc_setTrackpadY) //(float v) +DECL(sc_setTickDuration) // (MYFLT secs_per_tick) { - float v; - if (!PyArg_ParseTuple(args, "f", &v)) + float spt; + if (!PyArg_ParseTuple(args, "f", &spt )) { return NULL; } - sc_tt->setTrackpadY(v); - Py_INCREF(Py_None); - return Py_None; + g_tt->setTickDuration(spt); + RetNone; } -DECL(sc_loop_getTick) // -> float +DECL(sc_loop_new) // () -> int { - if (!PyArg_ParseTuple(args, "" )) - { - return NULL; - } - return Py_BuildValue("f", sc_tt->loop ? sc_tt->loop->getTickf(true):-1.0f); + if (!PyArg_ParseTuple(args, "" )) return NULL; + return Py_BuildValue("i", g_music->alloc()); } -DECL(sc_loop_setNumTicks) //(int nticks) +DECL(sc_loop_delete) // (int loopIdx) { - int nticks; - if (!PyArg_ParseTuple(args, "i", &nticks )) - { - return NULL; - } - if (sc_tt->loop) sc_tt->loop->setNumTicks(nticks); + int loopIdx; + if (!PyArg_ParseTuple(args, "i", &loopIdx )) return NULL; + g_music->destroy(loopIdx); RetNone; } -DECL(sc_loop_setTick) // (int ctick) +DECL(sc_loop_getTickf) // (int loopIdx) -> float { - int ctick; - if (!PyArg_ParseTuple(args, "i", &ctick )) + int idx; + if (!PyArg_ParseTuple(args, "i", &idx )) { return NULL; } - if (sc_tt->loop) sc_tt->loop->setTick(ctick); - RetNone; + return Py_BuildValue("f", g_music->getTickf(idx)); } -DECL(sc_loop_setTickDuration) // (MYFLT secs_per_tick) +DECL(sc_loop_setNumTicks) //(int loopIdx, int nticks) { - float spt; - if (!PyArg_ParseTuple(args, "f", &spt )) - { - return NULL; - } - sc_tt->setTickDuration(spt); + int loopIdx; + int nticks; + if (!PyArg_ParseTuple(args, "ii", &loopIdx, &nticks )) return NULL; + g_music->setNumTicks(loopIdx, nticks); RetNone; } -DECL(sc_loop_adjustTick) // (MYFLT ntick) +DECL(sc_loop_setTickf) // (int loopIdx, float pos) { - float spt; - if (!PyArg_ParseTuple(args, "f", &spt )) - { - return NULL; - } - sc_tt->adjustTick(spt); + int loopIdx; + MYFLT pos; + if (!PyArg_ParseTuple(args, "if", &loopIdx, &pos )) return NULL; + g_music->setTickf(loopIdx, pos); RetNone; } -DECL(sc_loop_addScoreEvent) // (int id, int duration_in_ticks, char type, farray param) +DECL(sc_loop_addScoreEvent) // (int loopIdx, int id, int duration_in_ticks, char type, farray param) { - int qid, inticks, active; + int loopIdx, qid, inticks, active; char ev_type; PyObject *o; - if (!PyArg_ParseTuple(args, "iiicO", &qid, &inticks, &active, &ev_type, &o )) - { - return NULL; - } + if (!PyArg_ParseTuple(args, "iiiicO", &loopIdx, &qid, &inticks, &active, &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))) @@ -981,10 +1005,10 @@ DECL(sc_loop_addScoreEvent) // (int id, int duration_in_ticks, char type, farray len = o->ob_type->tp_as_buffer->bf_getreadbuffer(o, 0, &ptr); float * fptr = (float*)ptr; size_t flen = len / sizeof(float); - if (sc_tt->loop) sc_tt->loop->addEvent(qid, ev_type, fptr, flen, inticks, active); - Py_INCREF(Py_None); - return Py_None; + g_music->addEvent(loopIdx, qid, ev_type, fptr, flen, inticks, active); + + RetNone; } else { @@ -994,65 +1018,38 @@ DECL(sc_loop_addScoreEvent) // (int id, int duration_in_ticks, char type, farray assert(!"not reached"); return NULL; } -DECL(sc_loop_delScoreEvent) // (int id) +DECL(sc_loop_delScoreEvent) // (int loopIdx, int id) { - int id; - if (!PyArg_ParseTuple(args, "i", &id )) + int loopIdx, id; + if (!PyArg_ParseTuple(args, "ii", &loopIdx, &id )) { return NULL; } - if (sc_tt->loop) sc_tt->loop->delEvent(id); + g_music->delEvent(loopIdx, id); RetNone; } -DECL(sc_loop_updateEvent) // (int id) +DECL(sc_loop_updateEvent) // (int loopIdx, int id, int paramIdx, float paramVal, int activate_cmd)) { - int id; + int loopIdx, eventId; int idx; float val; int cmd; - if (!PyArg_ParseTuple(args, "iifi", &id, &idx, &val, &cmd)) - { - return NULL; - } - if (sc_tt->loop) sc_tt->loop->updateEvent(id, idx, val, cmd); + if (!PyArg_ParseTuple(args, "iiifi", &loopIdx, &eventId, &idx, &val, &cmd)) return NULL; + g_music->updateEvent(loopIdx, eventId, idx, val, cmd); RetNone; } DECL(sc_loop_deactivate_all) // (int id) { - if (!PyArg_ParseTuple(args, "")) - { - return NULL; - } - if (sc_tt->loop) sc_tt->loop->deactivateAll(); + int loopIdx; + if (!PyArg_ParseTuple(args, "i", &loopIdx)) return NULL; + g_music->deactivateAll(loopIdx); RetNone; } -DECL(sc_loop_clear) +DECL(sc_loop_playing) // (int loopIdx, int tf) { - if (!PyArg_ParseTuple(args, "" )) - { - return NULL; - } - if (sc_tt->loop) sc_tt->loop->clear(); - RetNone; -} -DECL(sc_loop_playing) // (int tf) -{ - int i; - if (!PyArg_ParseTuple(args, "i", &i )) - { - return NULL; - } - if (sc_tt->loop) sc_tt->loopPlaying(i); - RetNone; -} -DECL (sc_inputMessage) //(const char *msg) -{ - char * msg; - if (!PyArg_ParseTuple(args, "s", &msg )) - { - return NULL; - } - sc_tt->inputMessage(msg); + int loopIdx, tf; + if (!PyArg_ParseTuple(args, "ii", &loopIdx, &tf )) return NULL; + g_music->playing(loopIdx, tf); RetNone; } @@ -1062,24 +1059,25 @@ static PyMethodDef SpamMethods[] = { MDECL(sc_initialize), MDECL(sc_start), MDECL(sc_stop), - MDECL(sc_scoreEvent), + MDECL(sc_setChannel), - MDECL(sc_setMasterVolume), - MDECL(sc_setTrackVolume), - MDECL(sc_setTrackpadX), - MDECL(sc_setTrackpadY), - MDECL(sc_loop_getTick), + MDECL(sc_inputMessage), + MDECL(sc_scoreEvent), + + MDECL(sc_getTickf), + MDECL(sc_adjustTick), + MDECL(sc_setTickDuration), + + MDECL(sc_loop_new), + MDECL(sc_loop_delete), + MDECL(sc_loop_getTickf), + MDECL(sc_loop_setTickf), MDECL(sc_loop_setNumTicks), - MDECL(sc_loop_setTick), - MDECL(sc_loop_setTickDuration), - MDECL(sc_loop_adjustTick), MDECL(sc_loop_delScoreEvent), MDECL(sc_loop_addScoreEvent), MDECL(sc_loop_updateEvent), - MDECL(sc_loop_clear), MDECL(sc_loop_deactivate_all), MDECL(sc_loop_playing), - MDECL(sc_inputMessage), {NULL, NULL, 0, NULL} /*end of list */ }; diff --git a/Util/Clooper/aclient.so b/Util/Clooper/aclient.so Binary files differindex 97c9cbb..996e9e3 100755 --- a/Util/Clooper/aclient.so +++ b/Util/Clooper/aclient.so diff --git a/Util/Clooper/audio.cpp b/Util/Clooper/audio.cpp index e93ea54..343bc99 100644 --- a/Util/Clooper/audio.cpp +++ b/Util/Clooper/audio.cpp @@ -1,3 +1,6 @@ +#ifndef AUDIO_HXX +#define AUDIO_HXX + /* * Latency test program * @@ -216,3 +219,5 @@ open_error: } }; #undef ERROR_HERE + +#endif diff --git a/Util/Clooper/log.cpp b/Util/Clooper/log.cpp index 269433d..d4a8c72 100644 --- a/Util/Clooper/log.cpp +++ b/Util/Clooper/log.cpp @@ -1,3 +1,5 @@ +#ifndef LOG_HXX +#define LOG_HXX #include <stdarg.h> #include <stdio.h> @@ -46,3 +48,5 @@ struct log_t } } }; + +#endif diff --git a/miniTamTam/miniTamTamMain.py b/miniTamTam/miniTamTamMain.py index f8e3232..ac134d6 100644 --- a/miniTamTam/miniTamTamMain.py +++ b/miniTamTam/miniTamTamMain.py @@ -70,7 +70,7 @@ class miniTamTamMain(SubActivity): self.drumFillin = Fillin( self.beat, self.tempo, self.rythmInstrument, self.reverb, self.drumVolume ) self.sequencer= MiniSequencer(self.recordStateButton, self.recordOverSensitivity) self.loop = Loop(self.beat, sqrt( self.instVolume*0.01 )) - self.csnd.loopSetTempo(self.tempo) + self.csnd.setTempo(self.tempo) self.noteList = [] time.sleep(0.001) # why? self.trackpad = Trackpad( self ) @@ -503,7 +503,7 @@ class miniTamTamMain(SubActivity): self.tempo = val self.beatDuration = 60.0/self.tempo self.ticksPerSecond = Config.TICKS_PER_BEAT*self.tempo/60.0 - self.csnd.loopSetTempo(self.tempo) + self.csnd.setTempo(self.tempo) self.sequencer.tempo = self.tempo self.drumFillin.setTempo(self.tempo) @@ -831,7 +831,7 @@ class miniTamTamMain(SubActivity): correct += ticksPerLoop #print "correct:: %f ticks, %f ticks in, %f expected, %f err, correct %f" % (curTick, curTicksIn, ticksIn, err, correct) if abs(err) > 0.25: - self.csnd.loopAdjustTick(-err) + self.csnd.adjustTick(-err) if __name__ == "__main__": |