diff options
author | jaberg <james@localhost.localdomain> | 2007-01-08 11:18:20 (GMT) |
---|---|---|
committer | jaberg <james@localhost.localdomain> | 2007-01-08 11:18:20 (GMT) |
commit | 7478ebeda0b5cc2a101a3808e64323684ae8ef91 (patch) | |
tree | 1e6613a2c76ea2896622311a71138669ecaf8cd6 /Util/NoteLooper.py | |
parent | c2cd65e519cd77b4d8575ca130213c9cbdc439a6 (diff) |
new and improved notelooper
Diffstat (limited to 'Util/NoteLooper.py')
-rw-r--r-- | Util/NoteLooper.py | 158 |
1 files changed, 65 insertions, 93 deletions
diff --git a/Util/NoteLooper.py b/Util/NoteLooper.py index 3b31416..7ee264a 100644 --- a/Util/NoteLooper.py +++ b/Util/NoteLooper.py @@ -17,14 +17,7 @@ from Generation.GenerationConstants import GenerationConstants class NoteLooper: #PRIVATE - DRIFT = 0.01 - - def dirty_track(self, track): - for i in range(len(self.notes)): - (o,n,c) = self.notes[i] - if n.trackId == track: - self.notes[i] = (o,n,'') - + DRIFT = 0.01 #careful about changing this... coordinate with instrument 5777 #PUBLIC @@ -32,47 +25,55 @@ class NoteLooper: self.ticks_per_sec = ticks_per_sec # ticks last this long self.secs_per_tick = 1.0 / ticks_per_sec # precomputed inverse self.range_sec = range_sec # notes are checked-for, this many seconds in advance - self.range_tick = int( range_sec * ticks_per_sec ) # same, but in ticks self.duration = 0 # number of ticks in playback loop - self.prev_duration = 0 + self.loops = 0 # number of elapsed loops self.notes = [] # sorted list of (onset, noteptr, cache) - self.tick0 = 0 # the tick at which playback started - self.time0 = time.time() + 1000000 # the real time at which playback started + self.time0 = time.time() + 1000000 # the real time at which tick == 0 (sometimes retro-active) + #self.time_start # remember to call NoteLooper.startTime + # at the same time as you call + # CSoundClient.startTime() def setTick( self, tick ): - self.time0 = time.time() - self.tick0 = tick % self.duration - self.hIdx = bisect.bisect_left(self.notes, self.tick0) - self.prev_duration = 0 + time_time = time.time() + self.time0 = time_time - tick * self.secs_per_tick + self.loops = tick // self.duration + self.hIdx = bisect.bisect_left(self.notes, tick - self.duration * self.loops ) def setRate( self, ticks_per_sec): if ticks_per_sec != self.ticks_per_sec: - t = time.time() secs_per_tick = 1.0 / ticks_per_sec - if t > self.time0: - self.tick0 += int( (t - self.time0) * ticks_per_sec) - self.time0 = t + time_time = time.time() + curtick = self.getTick( 0.0, False, time_time ) + curticktime = curtick * self.secs_per_tick + self.time0 + self.ticks_per_sec = ticks_per_sec self.secs_per_tick = secs_per_tick - self.range_tick = ticks_per_sec * self.range_sec - self.notes = [ (o,n,'') for (o,n,c) in self.notes ] #clear cache - self.prev_duration = 0 + self.time0 = curticktime - curtick * secs_per_tick + self.notes = [ (o,n,'',z) for (o,n,c,z) in self.notes ] #clear cache + self.loops = 0 def setDuration( self, duration ): + self.time0 += self.loops * self.duration * self.secs_per_tick + self.loops = 0 self.duration = duration - def getCurrentTick(self, future , domod , t): #t is for time - if domod : return ( self.tick0 + int( ( t + future - self.time0 ) * self.ticks_per_sec ) ) % self.duration - else : return ( self.tick0 + int( ( t + future - self.time0 ) * self.ticks_per_sec ) ) + def getTick(self, future , domod , t): #t is for time + if domod : + return ( int( ( t + future - self.time0 ) * self.ticks_per_sec ) ) % self.duration + else : + return ( int( ( t + future - self.time0 ) * self.ticks_per_sec ) ) def next( self ) : time_time = time.time() - tickhorizon = self.getCurrentTick( self.range_sec, False, time_time ) #tick where we'll be after range_sec + #tickhorizon is tick where we'll be after range_sec + tickhorizon = self.getTick( self.range_sec, False, time_time ) + time0_time = self.time0 - self.time_start + self.DRIFT - if tickhorizon < self.tick0 : return [] + if tickhorizon < 0 : return [] + if len(self.notes) == 0 : return [] def cache_cmd(secs_per_tick, amplitude, pitch, inst, trackId, duration, tied, fullDuration, overlap, attack, decay, reverbSend, filterType, filterCutoff, pan ): if inst[0:4] == 'drum': @@ -118,75 +119,60 @@ class NoteLooper: return rval def getText(i, secs_per_tick, time_offset): - (onset,note,cache) = self.notes[i] - if cache == '' : - self.notes[i] = ( onset, note, - cache_cmd( secs_per_tick, - note.amplitude, # * track-level mixer rate - note.pitch, - note.instrumentFlag, - note.trackId, - note.duration * self.secs_per_tick, - note.tied, - note.fullDuration, - note.overlap, - note.attack, - note.decay, - note.reverbSend, - note.filterType, - note.filterCutoff, - note.pan)) + (onset,note,cache,z) = self.notes[i] + if cache == '' or note.nchanges != z : + self.notes[i] = \ + ( + onset, + note, + cache_cmd( + secs_per_tick, + note.amplitude, # * track-level mixer rate + note.pitch, + note.instrumentFlag, + note.trackId, + note.duration * self.secs_per_tick, + note.tied, + note.fullDuration, + note.overlap, + note.attack, + note.decay, + note.reverbSend, + note.filterType, + note.filterCutoff, + note.pan), + note.nchanges + ) rval = self.notes[i][2] % float(onset * self.secs_per_tick + time_offset) return rval - if self.tick0 != 0: - print self.tick0 - raise 'tick0 != 0' - - prev_secs = self.prev_duration * self.secs_per_tick + prev_secs = (self.loops * self.duration) * self.secs_per_tick rval = [] - while self.notes[self.hIdx][0] + self.prev_duration < tickhorizon: - rval.append ( getText(self.hIdx, self.secs_per_tick, prev_secs + self.DRIFT ) ) + while self.notes[self.hIdx][0] + self.loops * self.duration < tickhorizon: + rval.append ( getText(self.hIdx, self.secs_per_tick, prev_secs + time0_time ) ) self.hIdx += 1 if self.hIdx == len(self.notes): - self.hIdx = 0 - self.prev_duration += self.duration - prev_secs += self.secs_per_tick + self.hIdx = 0 + self.loops += 1 + prev_secs += self.duration * self.secs_per_tick - - if False: - if tickhorizon <= self.duration + self.prev_duration: - hIdx = self.hIdx - self.hIdx = hIdxMax = bisect.bisect_left(self.notes, (tickhorizon - self.prev_duration,)) - rlist = [(i, self.prev_duration * self.secs_per_tick) for i in range(hIdx, hIdxMax)] - else: - self.hIdx = hIdxMax = bisect.bisect_left(self.notes, (self.duration,)) - rlist = [(i, self.prev_duration * self.secs_per_tick) for i in range(self.hIdx, hIdxMax)] - - while tickhorizon > self.duration + self.prev_duration: #loop back to tick0 == 0 - self.prev_duration += self.duration - tickhorizon -= self.duration - self.hIdx = hIdxMax = bisect.bisect_left(self.notes, (min(tickhorizon - self.prev_duration, self.duration), 0)) - rlist += [(i,self.prev_duration * self.secs_per_tick) for i in range(hIdxMax)] - - rval = [ getText(i, self.secs_per_tick, looplag) for (i,looplag) in rlist ] return rval def insert( self, notes): def insertMany(): - self.notes += [ ( notes[i][0], notes[i][1], '' ) for i in xrange(len(notes)) ] + self.notes += [ ( notes[i][0], notes[i][1], '', 0 ) for i in xrange(len(notes)) ] self.notes.sort() def insertFew(): for i in xrange(len(notes)): - t = (notes[i][0], notes[i][1],'') + t = (notes[i][0], notes[i][1],'',0) l = bisect.bisect_left(self.notes, t ) self.notes.insert(l, t) - print 't',t if len(notes) > 6: insertMany() else: insertFew() + self.hIdx = bisect.bisect_left(self.notes, self.getTick(self.range_sec, True, time.time())) def remove(self, note): def removeFew(): @@ -204,24 +190,10 @@ class NoteLooper: removeMany() else: removeFew() + self.hIdx = bisect.bisect_left(self.notes, self.getTick(self.range_sec, True, time.time())) def clear(self): self.notes = [] - - def setVolume(self, track,vol): - raise 'dont call' - if self.tvol[track] != vol: - self.tvol[track] = vol - self.dirty_track(track) - def setInstrument(self, track, inst): - raise 'dont call' - if self.inst[track] != inst: - self.inst[track] = inst - self.dirty_track(track) - def setMute(self, track, m): - raise 'dont call' - if self.mute[track] != m: - self.mute[track] = m - self.dirty_track(track) - + def startTime(self): + self.time_start = time.time() |