Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames <olpc@localhost.localdomain>2007-01-29 11:14:17 (GMT)
committer James <olpc@localhost.localdomain>2007-01-29 11:14:17 (GMT)
commit37d5b1c8b1248eb86db2dc8d0550569cd08b8535 (patch)
treedee858c8c92be50f742b4c85d30cbee0a24c4c35
parent9b3d8e0a679913b29390fab8f2da7c68acc9bd1c (diff)
merged new notelooper into edit
-rw-r--r--Config.py1
-rw-r--r--Edit/MainWindow.py183
-rw-r--r--Edit/TrackInterface.py25
-rw-r--r--Util/CSoundClient.py10
-rw-r--r--Util/CSoundNote.py13
-rw-r--r--Util/Clooper/SoundClient.cpp80
-rw-r--r--Util/Clooper/SoundClient.h6
-rwxr-xr-xUtil/Clooper/_SClient.sobin126467 -> 131293 bytes
8 files changed, 146 insertions, 172 deletions
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 <vector>
#include <map>
+#include <cmath>
+
+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<MYFLT> 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, &param[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<int, ev_t *> pair_t;
typedef std::multimap<int, ev_t *>::iterator iter_t;
std::multimap<int, ev_t *> 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