diff options
Diffstat (limited to 'Util')
-rw-r--r-- | Util/CSoundClient.py | 8 | ||||
-rw-r--r--[-rwxr-xr-x] | Util/CSoundNote.py | 137 | ||||
-rw-r--r-- | Util/NoteLooper.py | 71 |
3 files changed, 85 insertions, 131 deletions
diff --git a/Util/CSoundClient.py b/Util/CSoundClient.py index b72ce92..a0bee81 100644 --- a/Util/CSoundClient.py +++ b/Util/CSoundClient.py @@ -25,8 +25,8 @@ class CSoundClientBase: def load_instruments( self ): for instrumentSoundFile in Config.INSTRUMENTS.keys(): fileName = Config.SOUNDS_DIR + "/" + instrumentSoundFile - instrumentID = Config.INSTRUMENT_TABLE_OFFSET + Config.INSTRUMENTS[ instrumentSoundFile ].instrumentID - mess = Config.LOAD_INSTRUMENT_COMMAND % ( instrumentID, fileName ) + instrumentId = Config.INSTRUMENT_TABLE_OFFSET + Config.INSTRUMENTS[ instrumentSoundFile ].instrumentId + mess = Config.LOAD_INSTRUMENT_COMMAND % ( instrumentId, fileName ) self.sendText( mess ) def startTime(self): @@ -47,8 +47,8 @@ class CSoundClientBase: class CSoundClientSocket( CSoundClientBase ): - def __init__( self, serverAddress, serverPort, clientID ): - self.clientID = clientID + def __init__( self, serverAddress, serverPort, clientId ): + self.clientId = clientId self.serverInfo = ( serverAddress, serverPort ) self.connected = False diff --git a/Util/CSoundNote.py b/Util/CSoundNote.py index 168d267..2632b45 100755..100644 --- a/Util/CSoundNote.py +++ b/Util/CSoundNote.py @@ -1,62 +1,35 @@ import Config from Util.CSoundClient import CSoundClient from Generation.GenerationConstants import GenerationConstants -#---------------------------------------------------------------------- -# TODO: extend this hierarchy to include a Note base class -# i.e. Event -> Note -> CSoundNote -# most classes should only deal with Events and Notes, -# and not CSoundNotes -#---------------------------------------------------------------------- -#---------------------------------------------------------------------- -# An Event subclass that represents a CSound note event -#---------------------------------------------------------------------- -class Event: +class CSoundNote : #----------------------------------- # initialization #----------------------------------- - def __init__( self, onset ): - self.onset = onset - - #----------------------------------- - # playback (must be implemented by subclasses) - #----------------------------------- - def play( self ): - raise NotImplementedError - - #----------------------------------- - # adjustment - #----------------------------------- - def adjustOnset( self, amount ): - self.onset += amount -class CSoundNote( Event ): - #----------------------------------- - # initialization - #----------------------------------- - def __init__( self, onset, - pitch, - amplitude, - pan, - duration, - trackID, - fullDuration = False, - instrument = Config.FLUTE, - attack = 0.002, - decay = 0.098, - reverbSend = 0.1, - filterType = 0, - filterCutoff = 1000, - tied = False, - overlap = False, - instrumentFlag = Config.FLUTE ): - Event.__init__( self, onset ) + def __init__( self, + onset, + pitch, + amplitude, + pan, + duration, + trackId, + fullDuration = False, + instrument = Config.FLUTE, + attack = 0.002, + decay = 0.098, + reverbSend = 0.1, + filterType = 0, + filterCutoff = 1000, + tied = False, + overlap = False, + instrumentFlag = Config.FLUTE ): self.onset = onset self.pitch = pitch self.amplitude = amplitude self.pan = pan self.duration = duration - self.trackID = trackID + self.trackId = trackId self.instrument = instrument self.fullDuration = fullDuration self.attack = attack @@ -72,11 +45,12 @@ class CSoundNote( Event ): self.instrumentFlag = self.instrument def __getstate__(self): - return {'pitch': self.pitch, + return {'onset': self.onset, + 'pitch': self.pitch, 'amplitude': self.amplitude, 'pan': self.pan, 'duration': self.duration, - 'trackID': self.trackID, + 'trackId': self.trackId, 'instrument': self.instrument, 'fullDuration': self.fullDuration, 'attack': self.attack, @@ -84,18 +58,17 @@ class CSoundNote( Event ): 'reverbSend': self.reverbSend, 'filterType': self.filterType, 'filterCutoff': self.filterCutoff, - 'onset': self.onset, 'tied': self.tied, 'overlap': self.overlap, 'instrumentFlag': self.instrumentFlag } def __setstate__(self,dict): - Event.__init__(self, dict['onset']) + self.onset = dict['onset'] self.pitch = dict['pitch'] self.amplitude = dict['amplitude'] self.pan = dict['pan'] self.duration = dict['duration'] - self.trackID = dict['trackID'] + self.trackId = dict['trackId'] self.instrument = dict['instrument'] self.fullDuration = dict['fullDuration'] self.attack = dict['attack'] @@ -109,16 +82,13 @@ class CSoundNote( Event ): def clone( self ): return CSoundNote( self.onset, self.pitch, self.amplitude, self.pan, - self.duration, self.trackID, self.fullDuration, self.instrument, + self.duration, self.trackId, self.fullDuration, self.instrument, self.attack, self.decay, self.reverbSend, self.filterType, self.filterCutoff, self.tied, self.overlap, self.instrumentFlag ) - def play( self ): - CSoundClient.sendText( self.getText(120, 0) ) - - def getText( self, tempo, delay ): + def getText( self, secs_per_tick, delay ): + if secs_per_tick > 1 : raise 'invalid secs_per_tick' if self.instrument == 'drum1kit': if GenerationConstants.DRUMPITCH.has_key( self.pitch ): - print self.pitch self.pitch = GenerationConstants.DRUMPITCH[ self.pitch ] self.instrumentFlag = Config.DRUM1INSTRUMENTS[ self.pitch ] @@ -127,19 +97,17 @@ class CSoundNote( Event ): self.instrumentFlag = self.instrument newPitch = pow( GenerationConstants.TWO_ROOT_TWELVE, self.pitch - 36 ) - oneTickDuration = (Constants.MS_PER_MINUTE / 1000) / tempo / Constants.TICKS_PER_BEAT - - newDuration = oneTickDuration * self.duration + newDuration = secs_per_tick * self.duration # condition for tied notes - if Config.INSTRUMENTS[ self.instrumentFlag ].csoundInstrumentID == 101 and self.tied and self.fullDuration: + if Config.INSTRUMENTS[ self.instrumentFlag ].csoundInstrumentId == 101 and self.tied and self.fullDuration: newDuration = -1 # condition for overlaped notes - if Config.INSTRUMENTS[ self.instrumentFlag ].csoundInstrumentID == 102 and self.overlap: + if Config.INSTRUMENTS[ self.instrumentFlag ].csoundInstrumentId == 102 and self.overlap: newDuration = oneTickDuration * self.duration + 1. if True: newAmplitude = self.amplitude * 0.8 - else : newAmplitude = self.amplitude * music_volume_get( self.trackID ) + else : newAmplitude = self.amplitude * music_volume_get( self.trackId ) newAttack = newDuration * self.attack if newAttack <= 0.002: @@ -149,29 +117,20 @@ class CSoundNote( Event ): if newDecay <= 0.002: newDecay = 0.002 - return Config.PLAY_NOTE_COMMAND % ( Config.INSTRUMENTS[ self.instrumentFlag ].csoundInstrumentID, - self.trackID, - delay, - newDuration, - newPitch, - self.reverbSend, - newAmplitude, - self.pan, - Config.INSTRUMENT_TABLE_OFFSET + Config.INSTRUMENTS[ self.instrumentFlag ].instrumentID, - newAttack, - newDecay, - self.filterType, - self.filterCutoff ) - - #----------------------------------- - # adjustment functions - #----------------------------------- - def adjustDuration( self, amount ): - self.duration += amount - - def adjustAmplitude( self, amount ): - self.amplitude += amount - - def adjustPitch( self, amount ): - self.pitch += amount - + return Config.PLAY_NOTE_COMMAND % ( \ + Config.INSTRUMENTS[ self.instrumentFlag ].csoundInstrumentId, + self.trackId, + delay, + newDuration, + newPitch, + self.reverbSend, + newAmplitude, + self.pan, + Config.INSTRUMENT_TABLE_OFFSET+Config.INSTRUMENTS[self.instrumentFlag].instrumentId, + newAttack, + newDecay, + self.filterType, + self.filterCutoff, + Config.INSTRUMENTS[ self.instrumentFlag ].loopStart, + Config.INSTRUMENTS[ self.instrumentFlag ].loopEnd, + Config.INSTRUMENTS[ self.instrumentFlag ].crossDur ) diff --git a/Util/NoteLooper.py b/Util/NoteLooper.py index 5f1f94f..bcb8e4a 100644 --- a/Util/NoteLooper.py +++ b/Util/NoteLooper.py @@ -8,8 +8,8 @@ import gtk import gobject import Config +from Util.CSoundNote import CSoundNote #maybe not actually used, but dependence is there. All notes are assumed to be CSoundNotes from Generation.GenerationConstants import GenerationConstants -from Util.Profiler import TP #------------------------------------------------------------------------------ # A base class used to play a collection of Events at their respective onsets @@ -22,25 +22,18 @@ class NoteLooper: def dirty_track(self, track): for i in range(len(self.notes)): (o,n,c) = self.notes[i] - if n['trackId'] == track: + if n.trackId == track: self.notes[i] = (o,n,'') #PUBLIC - def __init__( self, range_sec, ticks_per_sec, inst, tvol, mute ): + def __init__( self, range_sec, ticks_per_sec ): 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.inst = inst # instrument for each track - self.tvol = tvol # volume for each track - self.mute = mute # pre-amp for track volume - - if len(inst) != len(tvol): print 'ERROR: NoteLooper::__init__() invalid args' - if len(inst) != len(mute): print 'ERROR: NoteLooper::__init__() invalid args' - self.duration = 0 # number of ticks in playback loop self.prev_duration = 0 self.notes = [] # sorted list of (onset, noteptr, cache) @@ -75,20 +68,6 @@ class NoteLooper: 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 setVolume(self, track,vol): - if self.tvol[track] != vol: - self.tvol[track] = vol - self.dirty_track(track) - - def setInstrument(self, track, inst): - if self.inst[track] != inst: - self.inst[track] = inst - self.dirty_track(track) - def setMute(self, track, m): - if self.mute[track] != m: - self.mute[track] = m - self.dirty_track(track) - def next( self ) : time_time = time.time() tickhorizon = self.getCurrentTick( self.range_sec, False, time_time ) #tick where we'll be after range_sec @@ -136,20 +115,20 @@ class NoteLooper: if cache == '' : self.notes[i] = ( onset, note, cache_cmd( secs_per_tick, - note['amplitude'] * self.tvol[note['trackId']] * self.mute[note['trackId']], - 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.amplitude * self.tvol[note.trackId] * self.mute[note.trackId], + 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)) rval = self.notes[i][2] % float(onset * self.secs_per_tick + time_offset) return rval @@ -223,3 +202,19 @@ class NoteLooper: 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) + |