From 37d5b1c8b1248eb86db2dc8d0550569cd08b8535 Mon Sep 17 00:00:00 2001 From: James Date: Mon, 29 Jan 2007 11:14:17 +0000 Subject: merged new notelooper into edit --- diff --git a/Config.py b/Config.py index 0b8f86a..abfb296 100644 --- a/Config.py +++ b/Config.py @@ -338,6 +338,7 @@ RECORDABLE_INSTRUMENT_CSOUND_IDS = { MIC1 : 7, CSOUND_LOAD_INSTRUMENT = 'f%d 0 0 -1 "%s" 0 0 0' CSOUND_MIC_RECORD = 'i5201 0 5 %d' CSOUND_UNLOAD_TABLES = 'i%d 0 0.1 %d' % (INST_FREE, len(INSTRUMENTS)) +CSOUND_NOTE_OFF = 'i %s.%s .2 0.01 1. 0. 0. 0.5 %d 0 0 0 0' %('%d','%d',INSTRUMENT_TABLE_OFFSET) #CSOUND COMMANDS - DEPRECATED diff --git a/Edit/MainWindow.py b/Edit/MainWindow.py index 5b34381..5790f51 100644 --- a/Edit/MainWindow.py +++ b/Edit/MainWindow.py @@ -19,29 +19,6 @@ from Util.Profiler import TP from Generation.Generator import generator1, variate -from Util.NoteLooper import * - -def note_from_CSoundNote( csnote ): - note = {} - note['onset'] = csnote.onset - note['pitch'] = csnote.pitch - note['amplitude'] = csnote.amplitude - note['pan'] = csnote.pan - note['duration'] = csnote.duration - note['noteId'] = csnote.noteId - note['trackId'] = csnote.trackId - note['pageId'] = csnote.pageId - note['fullDuration'] = csnote.fullDuration - note['attack'] = csnote.attack - note['decay'] = csnote.decay - note['reverbSend'] = csnote.reverbSend - note['filterType'] = csnote.filterType - note['filterCutoff'] = csnote.filterCutoff - note['tied'] = csnote.tied - note['overlap'] = csnote.overlap - note['instrumentFlag'] = csnote.instrumentFlag - - return note #----------------------------------- # The main TamTam window #----------------------------------- @@ -269,7 +246,6 @@ class MainWindow( gtk.EventBox ): self._data['volume'] = Config.DEFAULT_VOLUME self._data['page_beats'] = [nbeats for p in range(npages)] self._data['tempo'] = Config.PLAYER_TEMPO - self._data['ticks_per_sec'] = self._data['tempo'] * 0.2 # 12 BPM / 60 SPM self._data['tune'] = [] self._data['notebin'] = [] self._noteId = {} @@ -467,14 +443,6 @@ class MainWindow( gtk.EventBox ): setupGUI() #above #TEMP init_GUI() #above - self.noteLooper = NoteLooper( - 0.2, - Config.PLAYER_TEMPO * 0.2 #0.2 currently converts beats per second to seconds_per_tick - ) - self.csnd.startTime() - self.noteLooper.startTime() - time.sleep(0.001) - self.csnd.setMasterVolume( self.getVolume() ) #for pageId in range( GUIConfig.NUMBER_OF_PAGE_BANK_ROWS * GUIConfig.NUMBER_OF_PAGE_BANK_COLUMNS ): @@ -507,54 +475,49 @@ class MainWindow( gtk.EventBox ): #----------------------------------- def handlePlay( self, widget, data ): - def shutOffCSound(): - for track in range( Config.NUMBER_OF_TRACKS ): - for i in range( 3 ): - csoundInstrument = i + 5001 - self.csnd.sendText( Config.PLAY_NOTE_OFF_COMMAND % ( csoundInstrument, track ) ) - if widget.get_active(): #play #TODO: check for track activation, to not take all - trackset = set(range(Config.NUMBER_OF_TRACKS)) - - self.noteLooper.clear() #erase all loaded notes - notes = [] - - pagedelay = 0 self.pages_playing = self.tuneInterface.getSelectedIds() - for p in self.pages_playing: - notes += [(n['onset'] + pagedelay, n) for n in self._data['notebin'] \ - if n['pageId']==p and n['trackId'] in trackset ] - pagedelay += self._data['page_beats'][p] * Config.TICKS_PER_BEAT - - self.noteLooper.insert(notes) - self.noteLooper.setDuration( pagedelay ) - self.noteLooper.setTick(0) #TODO: get playback head position - self.noteLooper.setRate( self._data['ticks_per_sec'] ) - - cmds = self.noteLooper.next() - for c in cmds: self.csnd.sendText( c ) - time.sleep(0.001) - self.playbackTimeout = gobject.timeout_add( 100, self.onTimeout ) + trackset = set(range(Config.NUMBER_OF_TRACKS)) + pageset = set(self.pages_playing) + notes = [n for n in self._data['notebin'] if n.pageId in pageset and n.trackId in trackset] self.playing = True + self.playbackTimeout = gobject.timeout_add( 100, self.onTimeout ) + + numticks = sum([self._data["pages"][id]["beats"] for id in self.pages_playing ] ) * Config.TICKS_PER_BEAT + print 'play!' + print 'pageset : ', pageset + print 'trackset : ', trackset + print 'numticks : ', numticks + print 'notes : ', len(notes), 'notes' + self.csnd.loopClear() + self.csnd.loopAdd(notes) + self.csnd.loopSetTick(0) + self.csnd.loopSetNumTicks( numticks ) + self.csnd.loopSetTempo(self._data['tempo']) + self.csnd.loopStart() else: #stop gobject.source_remove( self.playbackTimeout ) - shutOffCSound() + if False: + #This is causing csound to stop working... + # reimplement this with real CSoundNotes and it should be ok. + # I suspect the problem is related to the different in the way + # tracks are handled in this old message, and in CSoundNote.CSound_playNote() + for track in range( Config.NUMBER_OF_TRACKS ): + for i in [Config.INST_TIED, Config.INST_PERC, Config.INST_SIMP]: + self.csnd.inputMessage(Config.CSOUND_NOTE_OFF % (i,track)) + self.csnd.loopStop() self.playing = False self.kb_record = self.playButton.get_active() and self.keyboardRecordButton.get_active() and self.keyboardButton.get_active() def onTimeout(self): - - cmds = self.noteLooper.next() - for c in cmds: self.csnd.sendText( c ) - self.updateFPS() - curtick = self.noteLooper.getCurrentTick(0,True, time.time()) + curtick = self.csnd.loopGetTick() curIdx = curtick / ( 4 * Config.TICKS_PER_BEAT) #TODO handle each pages_playing length self.tuneInterface.displayPage( self.pages_playing[curIdx], 0 ) self.trackInterface.displayPage(self.pages_playing[curIdx], 4 ) #TODO: use page_beats @@ -600,8 +563,6 @@ class MainWindow( gtk.EventBox ): def handleTempo( self, widget ): self._data['tempo'] = round( widget.get_value() ) - self._data['ticks_per_sec'] = self._data['tempo'] * 0.2 # 12 BPM / 60 SPM - self.noteLooper.setRate(self._data['ticks_per_sec']) 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" ) @@ -623,10 +584,8 @@ class MainWindow( gtk.EventBox ): def onTrackInterfaceNoteDrag( self, dragList ): for (id, pitch, onset, duration) in dragList: - n = self._noteId[id] - n['pitch'] = pitch - n['onset'] = onset - n['duration'] = duration + print "ERROR: ignoring note drag" + return #----------------------------------- # generation functions @@ -649,11 +608,11 @@ class MainWindow( gtk.EventBox ): beatList = [] for n in notes: - pageList.append( n["pageId"] ) - trackList.append( n["trackId"] ) - noteList.append( n["noteId"] ) + pageList.append( n.pageId ) + trackList.append( n.trackId ) + noteList.append( n.noteId ) csnoteList.append( n ) - beatList.append( p["beats"] for p in self._data["pages"] if p["pageId"] == n["pageId"] ) + beatList.append( p["beats"] for p in self._data["pages"] if p["pageId"] == n.pageId ) self.trackInterface.addNotes( { "page":pageList, @@ -669,9 +628,9 @@ class MainWindow( gtk.EventBox ): noteList = [] for n in notes: - pageList.append( n["pageId"] ) - trackList.append( n["trackId"] ) - noteList.append( n["noteId"] ) + pageList.append( n.pageId ) + trackList.append( n.trackId ) + noteList.append( n.noteId ) self.trackInterface.deleteNotes( { "page":pageList, @@ -704,45 +663,32 @@ class MainWindow( gtk.EventBox ): newpages, dict) - # filter for invalid input + # filter & fix input for track in dict: for page in dict[track]: for note in dict[track][page]: intdur = int(note.duration) - if intdur != note.duration: - print "Invalid note duration!" note.duration = intdur note.pageId = page note.trackId = track - self._noteIdBase = self._noteIdBase + 1 - while self._noteIdBase in self._noteId: self._noteIdBase = self._noteIdBase + 1 - note.noteId = self._noteIdBase #add notes to self._data newnotes = [] for tid in dict: for pid in dict[tid]: - newnotes += [note_from_CSoundNote(n) for n in dict[tid][pid]] - - for n in newnotes: - self._noteId[n['noteId']] = n + newnotes += dict[tid][pid] #delete the old pages & tracks! - togo = [n for n in self._data['notebin'] if (n['trackId'] in newtracks and n['pageId'] in newpages) ] + togo = [n for n in self._data['notebin'] if (n.trackId in newtracks and n.pageId in newpages) ] self.trackInterface.deleteNotes( - { "page": [n['pageId'] for n in togo], - "track":[n['trackId'] for n in togo] , - "note": [n['noteId'] for n in togo]}, + { "page": [n.pageId for n in togo], + "track":[n.trackId for n in togo] , + "note": [n.noteId for n in togo]}, len(togo)) - for n in togo: - del self._noteId[n['noteId']] - - self._data['notebin'] = \ - [n for n in self._data['notebin'] if not (n['trackId'] in newtracks and n['pageId'] in newpages) ] \ - + newnotes - self.addNotesToTrackInterface( newnotes ) + self._data['notebin'] = [n for n in self._data['notebin'] if not (n.noteId in togo)] + newnotes + self.handleCloseGenerateWindow( None, None ) #self.handleConfigureEvent( None, None ) @@ -817,8 +763,8 @@ class MainWindow( gtk.EventBox ): nextDisplay = pageId nextBeats = page["beats"] - newnotes = [ n.copy() for n in self._data["notebin"] if n["pageId"] == id ] - for n in newnotes: n["pageId"] = pageId + newnotes = [ n.clone() for n in self._data["notebin"] if n.pageId == id ] + for n in newnotes: n.pageId = pageId self._data["notebin"].extend( newnotes ) self.addNotesToTrackInterface( newnotes ) @@ -858,9 +804,9 @@ class MainWindow( gtk.EventBox ): self._data["pages"].remove(page) - notes = [ n for n in self._data["notebin"] if n["pageId"] == id ] + notes = [ n for n in self._data["notebin"] if n.pageId == id ] self.removeNotesFromTrackInterface( notes ) - self._data["notebin"] = [ n for n in self._data["notebin"] if n["pageId"] != id ] + self._data["notebin"] = [ n for n in self._data["notebin"] if n.pageId != id ] def movePages( self, insert = -1, pageIds = -1 ): @@ -891,9 +837,7 @@ class MainWindow( gtk.EventBox ): # load and save functions #----------------------------------- def handleSave(self, widget, data): - #gtk.main_quit() - self.csnd.initialize(False) - return + pass chooser = gtk.FileChooserDialog(title=None,action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK)) @@ -909,9 +853,6 @@ class MainWindow( gtk.EventBox ): chooser.destroy() def handleLoad(self, widget, data): - #gtk.main_quit() - self.csnd.initialize(True) - return chooser = gtk.FileChooserDialog(title=None,action=gtk.FILE_CHOOSER_ACTION_OPEN, buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) if chooser.run() == gtk.RESPONSE_OK: @@ -923,7 +864,7 @@ class MainWindow( gtk.EventBox ): print 'ERROR: failed to unserialize from file %s' % chooser.get_filename() chooser.destroy() - print 'TODO: update misc. program state to new music' + print 'ERROR: MainWindow::handleLoad() not implemented' #----------------------------------- # Record functions @@ -981,7 +922,7 @@ class MainWindow( gtk.EventBox ): duration = 100 # Create and play the note - self.kb_keydict[key] = Note.note_new(onset = 0, + self.kb_keydict[key] = CSoundNote(onset = 0, pitch = pitch, amplitude = 1, pan = 0.5, @@ -990,7 +931,7 @@ class MainWindow( gtk.EventBox ): fullDuration = False, instrument = instrument, instrumentFlag = instrument) - Note.note_play(self.kb_keydict[key]) + self.kb_keydict[key].playNow() def onKeyRelease(self,widget,event): @@ -1001,17 +942,17 @@ class MainWindow( gtk.EventBox ): key = event.hardware_keycode if KEY_MAP.has_key(key): - self.kb_keydict[key]['duration'] = 0 - self.kb_keydict[key]['amplitude'] = 0 - self.kb_keydict[key]['dirty'] = True - Note.note_play(self.kb_keydict[key]) - self.kb_keydict[key]['duration'] = self.getCurrentTick() - self.kb_keydict[key]['onset'] - #print "onset",self.kb_keydict[key].onset - #print "dur",self.kb_keydict[key].duration + self.kb_keydict[key].duration = 0 + self.kb_keydict[key].amplitude = 0 + self.kb_keydict[key].nchanges += 1 + self.kb_keydict[key].playNow() if self.kb_record and len( self.getSelectedtrackIds() ) != 0: - self.kb_keydict[key]['amplitude'] = 1 - self.getTrackDictionary()[min(self.getSelectedtrackIds())][self.getCurrentpageIdCallback()].append(self.kb_keydict[key]) - print 'ERROR: keyboard release... callbacks?' + print "ERROR: discarding recorded note " + if False: + curtick = something + self.kb_keydict[key].duration = curtick - self.kb_keydict[key].onset + self.kb_keydict[key].amplitude = 1.0 + self.kb_keydict[key].nchanges += 1 del self.kb_keydict[key] def delete_event( self, widget, event, data = None ): diff --git a/Edit/TrackInterface.py b/Edit/TrackInterface.py index b51c093..a689dea 100644 --- a/Edit/TrackInterface.py +++ b/Edit/TrackInterface.py @@ -168,36 +168,31 @@ class TrackInterface( gtk.EventBox ): t = noteParams["track"][i] if p not in at: at[p] = [0] * Config.NUMBER_OF_TRACKS - #at[p] = [] - #for j in range(Config.NUMBER_OF_TRACKS): at[p].append(0) if p not in self.note: self.note[p] = map(lambda x:[], range(Config.NUMBER_OF_TRACKS)) - #self.note[p] = [] - #for j in range(Config.NUMBER_OF_TRACKS): - #self.note[p].append( [] ) self.pageBeatCount[p] = noteParams["beatCount"][i] self.pageNoteCount[p] = 0 csnote = noteParams["csnote"][i] if noteParams["track"][i] == self.drumIndex: note = HitInterface( self, p, noteParams["track"][i], noteParams["note"][i], \ - csnote["pitch"], csnote["onset"], csnote["duration"], csnote["amplitude"], \ + csnote.pitch, csnote.onset, csnote.duration, csnote.amplitude, \ self.image["hit"], self.image["hitSelected"], self.trackColors[noteParams["track"][i]] ) else: note = NoteInterface( self, p, noteParams["track"][i], noteParams["note"][i], \ - csnote["pitch"], csnote["onset"], csnote["duration"], csnote["amplitude"], \ + csnote.pitch, csnote.onset, csnote.duration, csnote.amplitude, \ self.image["note"], self.image["noteSelected"], self.trackColors[noteParams["track"][i]] ) while at[p][t] > 0: startT = self.note[p][t][at[p][t]-1].getStartTick() - if startT <= csnote["onset"]: - if startT < csnote["onset"]: break - elif self.note[p][t][at[p][t]-1].getPitch <= csnote["pitch"]: break + if startT <= csnote.onset: + if startT < csnote.onset: break + elif self.note[p][t][at[p][t]-1].getPitch <= csnote.pitch: break at[p][t] -= 1 last = len(self.note[p][t]) while at[p][t] < last: startT = self.note[p][t][at[p][t]].getStartTick() - if startT >= csnote["onset"]: - if startT > csnote["onset"]: break - elif self.note[p][t][at[p][t]].getPitch >= csnote["pitch"]: break + if startT >= csnote.onset: + if startT > csnote.onset: break + elif self.note[p][t][at[p][t]].getPitch >= csnote.pitch: break at[p][t] += 1 self.note[p][t].insert( at[p][t], note ) self.pageNoteCount[p] += 1 @@ -213,8 +208,8 @@ class TrackInterface( gtk.EventBox ): t = noteParams["track"][i] id = noteParams["note"] csnote = noteParams["csnote"] - self.resortNote( p, t, id, csnote["pitch"], csnote["onset"] ) - self.note[p][t][self.noteMap[p][id]].updateParams( csnote["pitch"], csnote["onset"], csnote["duration"], csnote["amplitude"] ) + self.resortNote( p, t, id, csnote.pitch, csnote.onset ) + self.note[p][t][self.noteMap[p][id]].updateParams( csnote.pitch, csnote.onset, csnote.duration, csnote.amplitude ) # noteParams: { "page":pagelist, "track":tracklist, "note":noteIDlist } def deleteNotes( self, noteParams, noteCount ): diff --git a/Util/CSoundClient.py b/Util/CSoundClient.py index 3da180a..c40efb1 100644 --- a/Util/CSoundClient.py +++ b/Util/CSoundClient.py @@ -234,6 +234,16 @@ class CSoundClientPlugin( CSoundClientBase ): for (o,n) in onset_note: n.playLoop() # a special non-documented CSoundNote function! + def loopAdd(self, notelist ): + for n in notelist: + n.playLoop() # a special non-documented CSoundNote function! + + def loopClear(self): + sc_loop_clear() + def loopDel( self, notelist ): + print 'ERROR: CSoundClient::loopDel() note removing is not implemented, clearing instead' + sc_loop_clear() + def loopStart(self): sc_loop_playing(1) def loopStop(self): diff --git a/Util/CSoundNote.py b/Util/CSoundNote.py index bf215ca..77ea459 100644 --- a/Util/CSoundNote.py +++ b/Util/CSoundNote.py @@ -47,6 +47,7 @@ def CSound_playNote( loopMode, secs_per_tick, if instr == 'drum3kit': instr = Config.DRUM3INSTRUMENTS[ key ] pitch = 1 + time_in_ticks = 0 else: pitch = GenerationConstants.TRANSPOSE[ pitch - 24 ] @@ -56,6 +57,7 @@ def CSound_playNote( loopMode, secs_per_tick, # condition for overlaped notes if Config.INSTRUMENTS[ instr ].csoundInstrumentId == 102 and overlap: duration += 1.0 + time_in_ticks = 1 # condition for tied notes if Config.INSTRUMENTS[ instr].csoundInstrumentId == Config.INST_TIED and tied and fullDuration: @@ -64,7 +66,7 @@ def CSound_playNote( loopMode, secs_per_tick, if Config.INSTRUMENTS[ instr ].csoundInstrumentId == Config.INST_PERC and overlap: duration = duration + 1.0 if loopMode : - sc_loop_addScoreEvent15( 'i', + sc_loop_addScoreEvent15( time_in_ticks, 'i', Config.INSTRUMENTS[ instr ].csoundInstrumentId + trackId * 0.01, onset, duration, @@ -73,15 +75,15 @@ def CSound_playNote( loopMode, secs_per_tick, amplitude, pan, Config.INSTRUMENT_TABLE_OFFSET + Config.INSTRUMENTS[instr].instrumentId, - max(attack*duration, 0.002), - max(decay *duration, 0.002), + attack, + decay, filterType, filterCutoff, Config.INSTRUMENTS[ instr ].loopStart, Config.INSTRUMENTS[ instr ].loopEnd, Config.INSTRUMENTS[ instr ].crossDur ) else: - sc_scoreEvent15( 'i', + sc_scoreEvent15( 0, 'i', Config.INSTRUMENTS[ instr ].csoundInstrumentId + trackId * 0.01, onset * secs_per_tick, duration, @@ -99,6 +101,7 @@ def CSound_playNote( loopMode, secs_per_tick, Config.INSTRUMENTS[ instr ].crossDur ) class CSoundNote : + NOTE_ID_COUNTER = 0 #----------------------------------- # initialization #----------------------------------- @@ -140,6 +143,8 @@ class CSoundNote : else: self.instrumentFlag = self.instrument self.nchanges = 0 + self.noteId = self.NOTE_ID_COUNTER + self.NOTE_ID_COUNTER += 1 def __getstate__(self): return {'onset': self.onset, diff --git a/Util/Clooper/SoundClient.cpp b/Util/Clooper/SoundClient.cpp index 116e8c6..3b5f90a 100644 --- a/Util/Clooper/SoundClient.cpp +++ b/Util/Clooper/SoundClient.cpp @@ -8,32 +8,43 @@ #include "SoundClient.h" #include #include +#include + +using namespace std; struct ev_t { - int onset; char type; + int onset; + bool time_in_ticks; + MYFLT prev_secs_per_tick; + MYFLT duration, attack, decay; std::vector param; - ev_t(char type, MYFLT p1, MYFLT p2, MYFLT p3, MYFLT p4, MYFLT p5, MYFLT p6, MYFLT p7, MYFLT p8, MYFLT p9, MYFLT p10, MYFLT p11, MYFLT p12, MYFLT p13, MYFLT p14, MYFLT p15) - : onset(onset), type(type), param(15) + ev_t(char type, bool in_ticks, MYFLT p1, MYFLT p2, MYFLT p3, MYFLT p4, MYFLT p5, MYFLT p6, MYFLT p7, MYFLT p8, MYFLT p9, MYFLT p10, MYFLT p11, MYFLT p12, MYFLT p13, MYFLT p14, MYFLT p15) + : type(type), onset(0), time_in_ticks(in_ticks), param(15) { onset = (int) p2; + duration = p3; + attack = p9; + decay = p10; + prev_secs_per_tick = -1.0; + param[0] = p1; - param[1] = 0.0; - param[2] = p3; - param[3] = p4; - param[4] = p5; - param[5] = p6; - param[6] = p7; - param[7] = p8; - param[8] = p9; - param[9] = p10; - param[10] = p11; - param[11] = p12; - param[12] = p13; - param[13] = p14; - param[14] = p15; + param[1] = 0.0; //onset + param[2] = p3; //duration + param[3] = p4; //pitch + param[4] = p5; //reverbSend + param[5] = p6; //amplitude + param[6] = p7; //pan + param[7] = p8; //table + param[8] = p9; //attack + param[9] = p10; //decay + param[10] = p11;//filterType + param[11] = p12;//filterCutoff + param[12] = p13;//loopStart + param[13] = p14;//loopEnd + param[14] = p15;//crossDur } bool operator<(const ev_t &e) const { @@ -46,8 +57,16 @@ struct ev_t fprintf(f, "\n"); } - void event(CSOUND * csound) + 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; + fprintf(stdout, "setting duration to %f\n", param[5]); + } csoundScoreEvent(csound, type, ¶m[0], param.size()); } }; @@ -55,8 +74,9 @@ struct EvLoop { int tick_prev; int tickMax; - double rtick; - double ticks_per_ksmp; + MYFLT rtick; + MYFLT secs_per_tick; + MYFLT ticks_per_ksmp; typedef std::pair pair_t; typedef std::multimap::iterator iter_t; std::multimap ev; @@ -64,8 +84,9 @@ struct EvLoop CSOUND * csound; void * mutex; - EvLoop(CSOUND * cs) : tick_prev(0), tickMax(1), rtick(0.0), ticks_per_ksmp(0.3333), ev_pos(ev.end()), csound(cs), mutex(NULL) + EvLoop(CSOUND * cs) : tick_prev(0), tickMax(1), rtick(0.0), ev(), ev_pos(ev.end()), csound(cs), mutex(NULL) { + setTickDuration(0.05); mutex = csoundCreateMutex(0); } ~EvLoop() @@ -105,14 +126,15 @@ struct EvLoop void setTick(int t) { t = t % tickMax; - rtick = (double)(t % tickMax); + rtick = (MYFLT)(t % tickMax); //TODO: binary search would be faster csoundLockMutex(mutex); ev_pos = ev.lower_bound( t ); csoundUnlockMutex(mutex); } - void setTickDuration(double d) + void setTickDuration(MYFLT d) { + 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); } @@ -134,7 +156,7 @@ struct EvLoop while (ev_pos != ev.end()) { if (f) ev_pos->second->print(f); - if (events < eventMax) ev_pos->second->event(csound); + if (events < eventMax) ev_pos->second->event(csound, secs_per_tick); ++ev_pos; ++events; ++loop0; @@ -144,7 +166,7 @@ struct EvLoop while ((ev_pos != ev.end()) && (tick >= ev_pos->first)) { if (f) ev_pos->second->print(f); - if (events < eventMax) ev_pos->second->event(csound); + if (events < eventMax) ev_pos->second->event(csound, secs_per_tick); ++ev_pos; ++events; ++loop1; @@ -354,7 +376,7 @@ int sc_stop() return sc_tt->stop(); } //set the output volume to given level. max volume is 100.0 -void sc_setMasterVolume(double v) +void sc_setMasterVolume(MYFLT v) { sc_tt->setMasterVolume(v); } @@ -405,13 +427,13 @@ void sc_loop_setTick(int ctick) { sc_tt->loop->setTick(ctick); } -void sc_loop_setTickDuration(double secs_per_tick) +void sc_loop_setTickDuration(MYFLT secs_per_tick) { sc_tt->loop->setTickDuration(secs_per_tick); } -void sc_loop_addScoreEvent15(char type, MYFLT p1, MYFLT p2, MYFLT p3, MYFLT p4, MYFLT p5, MYFLT p6, MYFLT p7, MYFLT p8, MYFLT p9, MYFLT p10, MYFLT p11, MYFLT p12, MYFLT p13, MYFLT p14, MYFLT p15) +void sc_loop_addScoreEvent15(int in_ticks, char type, MYFLT p1, MYFLT p2, MYFLT p3, MYFLT p4, MYFLT p5, MYFLT p6, MYFLT p7, MYFLT p8, MYFLT p9, MYFLT p10, MYFLT p11, MYFLT p12, MYFLT p13, MYFLT p14, MYFLT p15) { - sc_tt->loop->addEvent( new ev_t(type, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); + sc_tt->loop->addEvent( new ev_t(type, in_ticks, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15)); } void sc_loop_clear() { diff --git a/Util/Clooper/SoundClient.h b/Util/Clooper/SoundClient.h index fd1b4bd..a946ced 100644 --- a/Util/Clooper/SoundClient.h +++ b/Util/Clooper/SoundClient.h @@ -12,18 +12,18 @@ extern "C" int sc_initialize(char * csd); int sc_start(); int sc_stop(); - void sc_setMasterVolume(double); + void sc_setMasterVolume(float); void sc_inputMessage(const char *msg); void sc_scoreEvent4(char type, MYFLT p0, MYFLT p1, MYFLT p2, MYFLT p3); void sc_scoreEvent15(char type, MYFLT p1, MYFLT p2, MYFLT p3, MYFLT p4, MYFLT p5, MYFLT p6, MYFLT p7, MYFLT p8, MYFLT p9, MYFLT p10, MYFLT p11, MYFLT p12, MYFLT p13, MYFLT p14, MYFLT p15); - void sc_loop_addScoreEvent15(char type, MYFLT p1, MYFLT p2, MYFLT p3, MYFLT p4, MYFLT p5, MYFLT p6, MYFLT p7, MYFLT p8, MYFLT p9, MYFLT p10, MYFLT p11, MYFLT p12, MYFLT p13, MYFLT p14, MYFLT p15); + void sc_loop_addScoreEvent15(int in_ticks, char type, MYFLT p1, MYFLT p2, MYFLT p3, MYFLT p4, MYFLT p5, MYFLT p6, MYFLT p7, MYFLT p8, MYFLT p9, MYFLT p10, MYFLT p11, MYFLT p12, MYFLT p13, MYFLT p14, MYFLT p15); void sc_loop_clear(); int sc_loop_getTick(); void sc_loop_playing(int tf); void sc_loop_setNumTicks(int nticks); void sc_loop_setTick(int ctick); - void sc_loop_setTickDuration(double secs_per_tick); + void sc_loop_setTickDuration(MYFLT secs_per_tick); #ifdef __cplusplus } #endif diff --git a/Util/Clooper/_SClient.so b/Util/Clooper/_SClient.so index 594ebe3..90f73ca 100755 --- a/Util/Clooper/_SClient.so +++ b/Util/Clooper/_SClient.so Binary files differ -- cgit v0.9.1