diff options
author | amartin <olpc@localhost.localdomain> | 2007-03-20 19:07:20 (GMT) |
---|---|---|
committer | amartin <olpc@localhost.localdomain> | 2007-03-20 19:07:20 (GMT) |
commit | 5a688c51e8b59c7db4d9156c9b804a5fc8f01577 (patch) | |
tree | 5b26bce1932e843ffe2e848e26bf75a99bb00669 | |
parent | 5f29f86ef43b756ccdd8c7001a7093ce54b38745 (diff) | |
parent | 631d817f5491db467f6184ec49fa34e235e82d8d (diff) |
Merge branch 'master' of git+ssh://amartin@dev.laptop.org/git/projects/tamtam
-rw-r--r-- | Config.py | 3 | ||||
-rw-r--r-- | Edit/MainWindow.py | 61 | ||||
-rw-r--r-- | Edit/TrackInterface.py | 2 | ||||
-rw-r--r-- | Generation/GenerationPitch.py | 7 | ||||
-rw-r--r-- | Generation/GenerationRythm.py | 70 | ||||
-rwxr-xr-x | Generation/Generator.py | 41 | ||||
-rw-r--r-- | Resources/univorc.csd | 6 | ||||
-rw-r--r-- | Util/CSoundClient.py | 3 | ||||
-rw-r--r-- | Util/CSoundNote.py | 15 | ||||
-rw-r--r-- | Util/Clooper/aclient.cpp | 2 | ||||
-rwxr-xr-x | Util/Clooper/aclient.so | bin | 0 -> 169404 bytes | |||
-rw-r--r-- | Util/NoteDB.py | 63 | ||||
-rw-r--r-- | mini.py | 231 | ||||
-rw-r--r-- | miniTamTam/MiniSequencer.py | 30 | ||||
-rw-r--r-- | miniTamTam/miniTamTamMain.py | 7 | ||||
-rw-r--r-- | scripts/pull_aclient.sh | 2 |
16 files changed, 302 insertions, 241 deletions
@@ -32,12 +32,13 @@ else: #PLUGIN PLUGIN_DEBUG = os.getenv('HOME')+"/tamtam.aclient.log" +PLUGIN_VERBOSE = 4 PLUGIN_UNIVORC = TAM_TAM_ROOT + "/Resources/univorc.csd" ## PLUGIN ALSA PARAMETERS: ## for macbook pro #PLUGIN_PERIOD = 1024 -#PLUGIN_NPERIODS = 3 +#PLUGIN_NPERIODS = 4 ## for XO with root #PLUGIN_PERIOD = 256 diff --git a/Edit/MainWindow.py b/Edit/MainWindow.py index 1b9ffe7..e4e0ad1 100644 --- a/Edit/MainWindow.py +++ b/Edit/MainWindow.py @@ -7,6 +7,7 @@ import gobject from Util.ThemeWidgets import * from Util.Profiler import TP from Util import NoteDB +from Util import ControlStream from Util.CSoundClient import new_csound_client from Util.InstrumentPanel import InstrumentPanel from Util.InstrumentPanel import DrumPanel @@ -293,6 +294,7 @@ class MainWindow( SubActivity ): # + + transport box self.GUI["2transportBox"] = formatRoundBox( RoundHBox(), Config.BG_COLOR ) self.GUI["2recordButton"] = ImageButton( Config.IMAGE_ROOT+"recordGray.png", Config.IMAGE_ROOT+"recordGray.png", Config.IMAGE_ROOT+"recordGray.png", backgroundFill = Config.BG_COLOR ) + self.GUI["2recordButton"].connect("clicked", self.handleSave ) self.GUI["2transportBox"].pack_start( self.GUI["2recordButton"] ) self.GUI["2playpauseBox"] = gtk.HBox() self.GUI["2playpauseBox"].set_size_request( 90, -1 ) @@ -461,7 +463,7 @@ class MainWindow( SubActivity ): for tid in range(Config.NUMBER_OF_TRACKS): self.handleInstrumentChanged( ( tid, self.trackInstrument[tid] ) ) - first = self.noteDB.addPage( 4 ) + first = self.noteDB.addPage( -1, NoteDB.Page(4) ) self.displayPage( first ) self.show_all() #gtk command @@ -482,6 +484,8 @@ class MainWindow( SubActivity ): def onActivate( self, arg ): SubActivity.onActivate( self,arg ) # whatever needs to be done on initialization + self.csnd.loopPause() + self.csnd.loopClear() for n in self.noteDB.getNotes( ): self.csnd.loopPlay(n, 0) #adds all notes to c client in inactive state @@ -489,6 +493,7 @@ class MainWindow( SubActivity ): SubActivity.onDeactivate( self ) # clean up things like popups etc self.releaseInstrumentPanel() + self.csnd.loopPause() self.csnd.loopClear() def setInstrumentPanel( self, instrumentPanel ): @@ -1184,7 +1189,8 @@ class MainWindow( SubActivity ): if after == -1: after = self.tuneInterface.getLastSelected() if not beats: beats = self.noteDB.getPage( self.displayedPage ).beats - self.displayPage( self.noteDB.addPage( beats, after ) ) + # TODO think about network mode here... + self.displayPage( self.noteDB.addPage( -1, NoteDB.Page(beats), after ) ) def pageBeats( self, pageIds = -1 ): @@ -1227,21 +1233,42 @@ class MainWindow( SubActivity ): #----------------------------------- # load and save functions #----------------------------------- - def handleSave(self, widget, data): - 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)) - - if chooser.run() == gtk.RESPONSE_OK: - try: - print 'INFO: serialize to file %s' % chooser.get_filename() - f = open( chooser.get_filename(), 'w') - pickle.dump( self._data, f ) - f.close() - except IOError: - print 'ERROR: failed to serialize to file %s' % chooser.get_filename() - - chooser.destroy() + def handleSave(self, widget): + try: + if (self.handleSaveCount == 1): + print 'DEBUG: clearing noteDB' + self.noteDB.deletePages( self.noteDB.pages.keys() ) + # still leaves an empty page at start... grrr + print 'DEBUG: loading ofile.tam' + ifile = open('ofile.tam', 'r') + ttt = ControlStream.TamTamTable ( self.noteDB ) + ttt.parseFile(ifile) + ifile.close() + self.handleSaveCount = 0 + return + except AttributeError: + pass + + print 'DEBUG: saving to ofile.tam' + ofile = open('ofile.tam', 'w') + ofilestream = ControlStream.TamTamOStream (ofile) + self.noteDB.dumpToStream(ofilestream) + ofile.close() + self.handleSaveCount = 1 + + if False: + chooser = gtk.FileChooserDialog(title=None,action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK)) + + if chooser.run() == gtk.RESPONSE_OK: + try: + print 'INFO: serialize to file %s' % chooser.get_filename() + f = open( chooser.get_filename(), 'w') + pickle.dump( self._data, f ) + f.close() + except IOError: + print 'ERROR: failed to serialize to file %s' % chooser.get_filename() + + chooser.destroy() def handleLoad(self, widget, data): chooser = gtk.FileChooserDialog(title=None,action=gtk.FILE_CHOOSER_ACTION_OPEN, buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) diff --git a/Edit/TrackInterface.py b/Edit/TrackInterface.py index fbd9e7d..5db645d 100644 --- a/Edit/TrackInterface.py +++ b/Edit/TrackInterface.py @@ -371,7 +371,7 @@ class TrackInterface( gtk.EventBox ): i, instrumentId = self.owner.getTrackInstrument(i).instrumentId ) cs.pageId = self.curPage - id = self.noteDB.addNote( self.curPage, i, cs ) + id = self.noteDB.addNote( -1, self.curPage, i, cs ) n = self.noteDB.getNote( self.curPage, i, id, self ) self.selectNotes( { i:[n] }, True ) n.playSampleNote( False ) diff --git a/Generation/GenerationPitch.py b/Generation/GenerationPitch.py index 7bfe2ff..99fceaa 100644 --- a/Generation/GenerationPitch.py +++ b/Generation/GenerationPitch.py @@ -34,8 +34,10 @@ class GenerationPitch: numberOfPitch = int( ( 1 - (parameters.pitchRegularity*.8) ) * 10 + 1 ) step = -(8 - (int(parameters.step * 8))) max = len(table_pitch)-1 + nextValue = self.pitchMethod.getNextValue + tonique = GenerationConstants.DEFAULT_TONIQUE for i in range(numberOfPitch): - append((table_pitch[self.pitchMethod.getNextValue(step, max)]) + GenerationConstants.DEFAULT_TONIQUE) + append((table_pitch[nextValue(step, max)]) + tonique) restOfNotes = range( length - numberOfPitch ) for i in restOfNotes: position = i % numberOfPitch @@ -46,8 +48,9 @@ class GenerationPitch: pitchSequence = [] append = pitchSequence.append max = len(drumPitch) - 1 + rand = random.randint for i in range(length): - append(drumPitch[ random.randint( 0, max ) ] ) + append(drumPitch[ rand( 0, max ) ] ) return pitchSequence # def harmonicPitchSequence( self, rythmSequence, parameters, table_pitch, harmonicSequence ): diff --git a/Generation/GenerationRythm.py b/Generation/GenerationRythm.py index 06dc1ab..56e9199 100644 --- a/Generation/GenerationRythm.py +++ b/Generation/GenerationRythm.py @@ -95,70 +95,76 @@ class GenerationRythm: countDown = 0 onsetTime = None beatsPerPage = int( barLength / Config.TICKS_PER_BEAT ) + randInt = random.randint + + upBeatsAppend = upBeats.append if Config.INSTRUMENTS[ trackInstrument ].instrumentRegister == Config.PUNCH: registerDensity = 0.5 downBeatRecurence = 4 + upBeatOffset = Config.TICKS_PER_BEAT / 2 downBeats = [x for x in GenerationConstants.DRUM_PUNCH_ACCENTS[ beatsPerPage ]] for downBeat in downBeats: - upBeats.append( downBeat + Config.TICKS_PER_BEAT / 2 ) - #upBeats.append( ( downBeat[ 0 ] + Config.TICKS_PER_BEAT , downBeat[ 1 ] ) ) + upBeatsAppend( downBeat + upBeatOffset ) - if Config.INSTRUMENTS[ trackInstrument ].instrumentRegister == Config.LOW: - registerDensity =1.5 + elif Config.INSTRUMENTS[ trackInstrument ].instrumentRegister == Config.LOW: + registerDensity = 1.5 downBeatRecurence = 4 + upBeatOffset = Config.TICKS_PER_BEAT / 2 downBeats = [x for x in GenerationConstants.DRUM_LOW_ACCENTS[ beatsPerPage ]] for downBeat in downBeats: - upBeats.append( downBeat + Config.TICKS_PER_BEAT / 2 ) - #upBeats.append( ( downBeat[ 0 ] + Config.TICKS_PER_BEAT / 2 , downBeat[ 1 ] ) ) + upBeatsAppend( downBeat + upBeatOffset ) - if Config.INSTRUMENTS[ trackInstrument ].instrumentRegister == Config.MID: + elif Config.INSTRUMENTS[ trackInstrument ].instrumentRegister == Config.MID: registerDensity = 1 downBeatRecurence = 1 + upBeatOffset = Config.TICKS_PER_BEAT / 4 downBeats = [x for x in GenerationConstants.DRUM_MID_ACCENTS[ beatsPerPage ]] for downBeat in downBeats: - upBeats.append( downBeat + Config.TICKS_PER_BEAT / 4 ) - #upBeats.append( ( downBeat[ 0 ] + Config.TICKS_PER_BEAT / 4 , downBeat[ 1 ] ) ) + upBeatsAppend( downBeat + upBeatOffset ) - if Config.INSTRUMENTS[ trackInstrument ].instrumentRegister == Config.HIGH: + elif Config.INSTRUMENTS[ trackInstrument ].instrumentRegister == Config.HIGH: registerDensity = 1.5 downBeatRecurence = 1 + upBeatOffset = Config.TICKS_PER_BEAT / 4 downBeats = [x for x in GenerationConstants.DRUM_HIGH_ACCENTS[ beatsPerPage ]] for downBeat in downBeats: - upBeats.append( downBeat + Config.TICKS_PER_BEAT / 4 ) - #upBeats.append( ( downBeat[ 0 ] + Config.TICKS_PER_BEAT / 4 , downBeat[ 1 ] ) ) - - for i in range( int( density * registerDensity * len( downBeats ) ) ): - if random.random() < ( parameters.rythmRegularity * downBeatRecurence ) and binSelection.count( 1 ) < len( downBeats ): - binSelection.append( 1 ) + upBeatsAppend( downBeat + upBeatOffset ) + + list = range( int( density * registerDensity * len( downBeats ) ) ) + rand = random.random + binCount = binSelection.count + binAppend = binSelection.append + for i in list: + if rand() < ( parameters.rythmRegularity * downBeatRecurence ) and binCount( 1 ) < len( downBeats ): + binAppend( 1 ) else: - if binSelection.count( 0 ) < len( downBeats ): - binSelection.append( 0 ) + if binCount( 0 ) < len( downBeats ): + binAppend( 0 ) else: - binSelection.append( 1 ) + binAppend( 1 ) - countDown = binSelection.count( 1 ) + countDown = binCount( 1 ) + seqAppend = rythmSequence.append length = len(downBeats) - 1 + downPop = downBeats.pop for i in range( countDown ): -# while onsetTime in rythmSequence or onsetTime == None: -# onsetTime = Utils.prob2( downBeats ) - ran1 = random.randint(0, length) - ran2 = random.randint(0, length) + ran1 = randInt(0, length) + ran2 = randInt(0, length) randMin = min(ran1, ran2) - onsetTime = downBeats.pop(randMin) - rythmSequence.append( onsetTime ) + onsetTime = downPop(randMin) + seqAppend( onsetTime ) length -= 1 length = len(upBeats) - 1 + upPop = upBeats.pop for i in range( len( binSelection ) - countDown ): -# while onsetTime in rythmSequence or onsetTime == None: -# onsetTime = Utils.prob2( upBeats ) - ran1 = random.randint(0, length) - ran2 = random.randint(0, length) + ran1 = randInt(0, length) + ran2 = randInt(0, length) randMin = min(ran1, ran2) - onsetTime = upBeats.pop(randMin) - rythmSequence.append( onsetTime ) + onsetTime = upPop(randMin) + seqAppend( onsetTime ) length -= 1 rythmSequence.sort() diff --git a/Generation/Generator.py b/Generation/Generator.py index 22c23de..066aab7 100755 --- a/Generation/Generator.py +++ b/Generation/Generator.py @@ -52,16 +52,19 @@ def generator1( def makeGainSequence( onsetList ): gainSequence = [] + append = gainSequence.append + rand = random.uniform max = GenerationConstants.GAIN_MAX_BOUNDARY midMax = GenerationConstants.GAIN_MID_MAX_BOUNDARY + midMin = GenerationConstants.GAIN_MID_MIN_BOUNDARY + min = GenerationConstants.GAIN_MIN_BOUNDARY for onset in onsetList: if onset == 0: - gain = random.uniform(GenerationConstants.GAIN_MID_MAX_BOUNDARY, GenerationConstants.GAIN_MAX_BOUNDARY) + append(rand(midMax, max)) elif ( onset % Config.TICKS_PER_BEAT) == 0: - gain = random.uniform(GenerationConstants.GAIN_MID_MIN_BOUNDARY, GenerationConstants.GAIN_MID_MAX_BOUNDARY) + append(rand(midMin, midMax)) else: - gain = random.uniform(GenerationConstants.GAIN_MIN_BOUNDARY, GenerationConstants.GAIN_MID_MIN_BOUNDARY) - gainSequence.append(gain) + append(rand(min, midMin)) return gainSequence def makeDurationSequence( onsetList, parameters, table_duration, barLength, currentInstrument ): @@ -71,13 +74,14 @@ def generator1( durationSequence = [duration] * len(onsetList) return durationSequence + append = durationSequence.append + proba = Utils.prob2 if len( onsetList ) > 1: for i in range(len(onsetList) - 1): - duration = (onsetList[i+1] - onsetList[i]) * Utils.prob2( table_duration ) - durationSequence.append(duration) - durationSequence.append(( barLength - onsetList[-1]) * Utils.prob2( table_duration )) + append((onsetList[i+1] - onsetList[i]) * proba( table_duration )) + append(( barLength - onsetList[-1]) * proba( table_duration )) elif len( onsetList ) == 1: - durationSequence.append( ( barLength - onsetList[0] ) * Utils.prob2( table_duration )) + append( ( barLength - onsetList[0] ) * proba( table_duration )) return durationSequence def pageGenerate( parameters, trackId, pageId, trackOfNotes, drumPitch = None ): @@ -98,17 +102,21 @@ def generator1( durationSequence = makeDurationSequence(rythmSequence, parameters, table_duration, barLength, currentInstrument) numOfNotes = range(len(rythmSequence)) + rand = random.random + append = trackNotes.append + pan = GenerationConstants.DEFAULT_PAN + instrument_id = Config.INSTRUMENTS[instrument[trackId]].instrumentId for i in numOfNotes: if drumPitch: - if ( random.random() * fillDrum ) > ( parameters.silence * .7 ): + if ( rand() * fillDrum ) > ( parameters.silence * .5 ): if fillDrum != 1: if rythmSequence[i] not in trackOnsets or pitchSequence[i] not in trackPitchs: - trackNotes.append( CSoundNote( rythmSequence[i], pitchSequence[i], gainSequence[i], GenerationConstants.DEFAULT_PAN, durationSequence[i], trackId, Config.INSTRUMENTS[instrument[ trackId ]].instrumentId, 0.002, 0.098, 0.1, 0, 1000, False, 'edit' ) ) + append( CSoundNote( rythmSequence[i], pitchSequence[i], gainSequence[i], pan, durationSequence[i], trackId, instrument_id, 0.002, 0.098, 0.1, 0, 1000, False, 'edit' ) ) else: - trackNotes.append( CSoundNote( rythmSequence[i], pitchSequence[i], gainSequence[i], GenerationConstants.DEFAULT_PAN, durationSequence[i], trackId, Config.INSTRUMENTS[instrument[ trackId ]].instrumentId, 0.002, 0.098, 0.1, 0, 1000, False, 'edit' ) ) + append( CSoundNote( rythmSequence[i], pitchSequence[i], gainSequence[i], pan, durationSequence[i], trackId, instrument_id, 0.002, 0.098, 0.1, 0, 1000, False, 'edit' ) ) else: - if random.random() > parameters.silence: - trackNotes.append( CSoundNote( rythmSequence[i], pitchSequence[i], gainSequence[i], GenerationConstants.DEFAULT_PAN, durationSequence[i], trackId, Config.INSTRUMENTS[instrument[ trackId ]].instrumentId, 0.002, 0.098, 0.1, 0, 1000, False, 'edit' ) ) + if rand() > parameters.silence: + append( CSoundNote( rythmSequence[i], pitchSequence[i], gainSequence[i], pan, durationSequence[i], trackId, instrument_id, 0.002, 0.1, 0.1, 0, 1000, False, 'edit' ) ) trackDictionary[ trackId ][ pageId ] = trackNotes @@ -137,10 +145,11 @@ def generator1( for pageId in pageIds: barLength = Config.TICKS_PER_BEAT * nbeats[ pageId ] trackOfNotes = [] + pageCycle = selectedPageCount % 4 # this should be fix in the meta algo if instrument[ trackId ][0:4] == 'drum': - if ( selectedPageCount % 4 ) in [1,2]: + if pageCycle in [1,2]: trackDictionary[ trackId ][ pageId ] = [ n for n in trackDictionary[ trackId ][ lastPageId ] ] - elif ( selectedPageCount % 4 ) == 3: + elif pageCycle == 3: trackOfNotes = [ n for n in trackDictionary[ trackId ][ lastPageId ] ] trackOnsets = [n.onset for n in trackOfNotes] trackPitchs = [n.pitch for n in trackOfNotes] @@ -150,7 +159,7 @@ def generator1( for drumPitch in GenerationConstants.DRUM_COMPLEXITY4: pageGenerate( parameters, trackId, pageId, trackOfNotes, drumPitch ) parameters.rythmRegularity = rythmRegTemp - elif ( selectedPageCount % 4 ) == 0: + elif pageCycle == 0: fillDrum = 1 for drumPitch in streamOfPitch: pageGenerate( parameters, trackId, pageId, trackOfNotes, drumPitch ) diff --git a/Resources/univorc.csd b/Resources/univorc.csd index 501dba7..79fdf21 100644 --- a/Resources/univorc.csd +++ b/Resources/univorc.csd @@ -708,7 +708,7 @@ kvibrato oscil .006, ivibRand, 1 tigoto tieskip -kpitch portk p4, igliss, p4 +kpitch portk p4, igliss, p4 kpan portk p7, igliss, p7 krg portk p5, igliss, p5 kcutoff portk p12, igliss, p12 @@ -763,8 +763,8 @@ a1 bqrez a1, p12, 6, p11-1 a1 balance a1, acomp endif -kenv adsr p9, 0.05, p6, p10 -a1 = a1*kenv*kvol +aenv adsr p9*p3, 0.005, p6, p10*p3 +a1 = a1*aenv*kvol gaoutL = a1*(1-p7)+gaoutL gaoutR = a1*p7+gaoutR diff --git a/Util/CSoundClient.py b/Util/CSoundClient.py index 12bd698..7fd7a41 100644 --- a/Util/CSoundClient.py +++ b/Util/CSoundClient.py @@ -15,7 +15,8 @@ from Util import NoteDB class _CSoundClientPlugin: def __init__(self): sc_initialize( Config.PLUGIN_UNIVORC, Config.PLUGIN_DEBUG, - Config.PLUGIN_PERIOD, Config.PLUGIN_NPERIODS) + Config.PLUGIN_PERIOD, Config.PLUGIN_NPERIODS, + Config.PLUGIN_VERBOSE) self.on = False #self.masterVolume = 80.0 self.periods_per_buffer = 2 diff --git a/Util/CSoundNote.py b/Util/CSoundNote.py index 77e85d7..d41fc11 100644 --- a/Util/CSoundNote.py +++ b/Util/CSoundNote.py @@ -2,10 +2,6 @@ import Config from Generation.GenerationConstants import GenerationConstants class CSoundNote : - NOTE_ID_COUNTER = 0 - #----------------------------------- - # initialization - #----------------------------------- def __init__( self, onset, pitch, @@ -38,11 +34,8 @@ class CSoundNote : self.filterCutoff = filterCutoff self.tied = tied self.mode = mode - self.nchanges = 0 - self.noteId = self.NOTE_ID_COUNTER - self.NOTE_ID_COUNTER += 1 - def __getstate__(self): + def __getstate__unused(self): return {'onset': self.onset, 'pitch': self.pitch, 'amplitude': self.amplitude, @@ -58,7 +51,7 @@ class CSoundNote : 'tied': self.tied, 'mode': self.mode } - def __setstate__(self,dict): + def __setstate__unused(self,dict): self.onset = dict['onset'] self.pitch = dict['pitch'] self.amplitude = dict['amplitude'] @@ -78,7 +71,9 @@ class CSoundNote : def clone( self ): return CSoundNote( self.onset, self.pitch, self.amplitude, self.pan, self.duration, self.trackId, self.instrumentId, - self.attack, self.decay, self.reverbSend, self.filterType, self.filterCutoff, self.tied, self.mode ) + self.attack, self.decay, self.reverbSend, + self.filterType, self.filterCutoff, self.tied, + self.mode ) diff --git a/Util/Clooper/aclient.cpp b/Util/Clooper/aclient.cpp index c9e298b..0d73c7e 100644 --- a/Util/Clooper/aclient.cpp +++ b/Util/Clooper/aclient.cpp @@ -849,7 +849,7 @@ DECL(sc_initialize) //(char * csd) char * str; char * log_file; int period, ppb; - if (!PyArg_ParseTuple(args, "ssii", &str, &log_file, &period, &ppb )) + if (!PyArg_ParseTuple(args, "ssiii", &str, &log_file, &period, &ppb, &VERBOSE )) { return NULL; } diff --git a/Util/Clooper/aclient.so b/Util/Clooper/aclient.so Binary files differnew file mode 100755 index 0000000..2df6327 --- /dev/null +++ b/Util/Clooper/aclient.so diff --git a/Util/NoteDB.py b/Util/NoteDB.py index a3b7bc3..6679446 100644 --- a/Util/NoteDB.py +++ b/Util/NoteDB.py @@ -82,6 +82,15 @@ class NoteDB: self.clipboard = [] # stores copied cs notes self.clipboardArea = [] # stores the limits and tracks for each page in the clipboard + def dumpToStream(self, ostream): + for pid in self.pages: + ostream.page_add(pid, self.pages[pid]) + for pid in self.noteD: + for tid in xrange( len( self.noteD[pid])): + for nid in self.noteD[pid][tid]: + ostream.note_add(self.noteD[pid][tid][nid]) + ostream.tune_set(self.tune) + #-- private -------------------------------------------- def _genId( self ): self.nextId += 1 @@ -93,14 +102,14 @@ class NoteDB: #======================================================= # Page Functions - def addPage( self, beats, after = False ): - id = self._newPage( beats ) - at = self._insertPage( id, after ) + def addPage( self, pid, page, after = False ): + pid = self._newPage( pid, page ) + at = self._insertPage( pid, after ) for l in self.pageListeners: - l.notifyPageAdd( id, at ) + l.notifyPageAdd( pid, at ) - return id + return pid def deletePages( self, which ): beats = self.pages[self.tune[0]].beats @@ -125,7 +134,7 @@ class NoteDB: self.tune.pop(at) if not len(self.tune): - self.addPage( beats ) # always have at least one page + self.addPage( -1, Page(beats) ) # always have at least one page safe = self.tune[0] else: safe = self.tune[max(ind-1,0)] @@ -147,7 +156,7 @@ class NoteDB: new = {} for cp in sorted: - id = self._newPage( self.pages[cp].beats ) + id = self._newPage( -1, Page(self.pages[cp].beats) ) self._insertPage( id, after ) after = id new[cp] = id @@ -186,23 +195,23 @@ class NoteDB: l.notifyPageMove( sorted, low, high ) #-- private -------------------------------------------- - def _newPage( self, beats ): - id = self._genId() - self.pages[id] = Page( beats ) - self.noteD[id] = [ {} for i in range(Config.NUMBER_OF_TRACKS) ] - self.noteS[id] = [ [] for i in range(Config.NUMBER_OF_TRACKS) ] - self.parasiteD[id] = [ {} for i in range(Config.NUMBER_OF_TRACKS) ] - self.parasiteS[id] = [ {} for i in range(Config.NUMBER_OF_TRACKS) ] + def _newPage( self, pid, page ): + if pid == -1 : pid = self._genId() + self.pages[pid] = page + self.noteD[pid] = [ {} for i in range(Config.NUMBER_OF_TRACKS) ] + self.noteS[pid] = [ [] for i in range(Config.NUMBER_OF_TRACKS) ] + self.parasiteD[pid] = [ {} for i in range(Config.NUMBER_OF_TRACKS) ] + self.parasiteS[pid] = [ {} for i in range(Config.NUMBER_OF_TRACKS) ] for i in range(Config.NUMBER_OF_TRACKS): for par in self.parasiteList.keys(): - self.parasiteD[id][i][par] = {} - self.parasiteS[id][i][par] = [] - return id + self.parasiteD[pid][i][par] = {} + self.parasiteS[pid][i][par] = [] + return pid - def _insertPage( self, id, after ): + def _insertPage( self, pid, after ): if not after: at = 0 else: at = self.tune.index(after)+1 - self.tune.insert( at, id ) + self.tune.insert( at, pid ) return at @@ -218,9 +227,9 @@ class NoteDB: #======================================================= # Note Functions - def addNote( self, page, track, cs, hint = False ): - id = self.pages[page].genId() - n = self.noteD[page][track][id] = Note( page, track, id, cs ) + def addNote( self, nid, page, track, cs, hint = False ): + if nid == -1: nid = self.pages[page].genId() + n = self.noteD[page][track][nid] = Note( page, track, nid, cs ) if not hint: at = 0 else: at = hint[0] @@ -242,15 +251,15 @@ class NoteDB: for par in self.parasiteList.keys(): parasite = self.parasiteList[par]( self, par, n ) - self.parasiteD[page][track][par][id] = parasite.attach() # give parasites the option of return something other than themselves + self.parasiteD[page][track][par][nid] = parasite.attach() # give parasites the option of return something other than themselves self.parasiteS[page][track][par].insert( at, parasite.attach() ) if hint: hint[0] = at + 1 # assume the next note will fall after this one for l in self.noteListeners: - l.notifyNoteAdd( page, track, id ) + l.notifyNoteAdd( page, track, nid ) - return id + return nid # stream format: # page id @@ -270,7 +279,7 @@ class NoteDB: N = self._readstream(stream,i) hint = [0] for j in range(N): - new[p][t].append( self.addNote( p, t, self._readstream(stream,i), hint ) ) + new[p][t].append( self.addNote( -1, p, t, self._readstream(stream,i), hint ) ) p = self._readstream(stream,i) return new @@ -323,7 +332,7 @@ class NoteDB: if cs.onset + cs.duration > ticks: cs.duration = ticks - cs.onset - return self.addNote( toPage, toTrack, cs ) + return self.addNote( -1, toPage, toTrack, cs ) # stream format: # page id @@ -1,123 +1,116 @@ -from Framework.CSound.CSoundClient import CSoundClient -from Framework.NoteLooper import NoteLooper as NL - -import time -import math - -lookahead = 0.2 -nl = NL( lookahead, 20.0, ['drum1kit'], [1.0], [1.0] ) - -nl.notes = [ - #(0, {'fullDuration': False, 'pageID': 0, 'decay': 0.098000000000000004, 'trackID': 0, 'instrumentFlag': 'drum1kick', 'filterType': 0, 'tied': False, 'onset': 0, 'filterCutoff': 1000, 'attack': 0.002, 'reverbSend': 0.10000000000000001, 'overlap': False, 'amplitude': 0.92029484351363555, 'pitch': 24, 'duration': 1, 'noteID': 36, 'pan': 0.5}, ''), - #( 0, {'fullDuration': False, 'pageID': 0, 'decay': 0.098000000000000004, 'trackID': 0, 'instrumentFlag': 'flute', 'filterType': 0, 'tied': False, 'onset': 0, 'filterCutoff': 1000, 'attack': 0.002, 'reverbSend': 0.10000000000000001, 'overlap': False, 'amplitude': 0.92525578482634807, 'pitch': 29, 'duration': 4, 'noteID': 1, 'pan': 0.5}, ''), - #(0, {'fullDuration': False, 'pageID': 0, 'decay': 0.098000000000000004, 'trackID': 0, 'instrumentFlag': 'koto', 'filterType': 0, 'tied': False, 'onset': 0, 'filterCutoff': 1000, 'attack': 0.002, 'reverbSend': 0.10000000000000001, 'overlap': False, 'amplitude': 0.939434987358156, 'pitch': 38, 'duration': 5, 'noteID': 8, 'pan': 0.5}, ''), - (0, {'fullDuration': False, 'pageID': 0, 'decay': 0.098000000000000004, 'trackID': 0, 'instrumentFlag': 'gam', 'filterType': 0, 'tied': False, 'onset': 0, 'filterCutoff': 1000, 'attack': 0.002, 'reverbSend': 0.10000000000000001, 'overlap': False, 'amplitude': 0.94494314329224738, 'pitch': 24, 'duration': 5, 'noteID': 22, 'pan': 0.5}, ''), - #(0, {'fullDuration': False, 'pageID': 0, 'decay': 0.098000000000000004, 'trackID': 0, 'instrumentFlag': 'guit', 'filterType': 0, 'tied': False, 'onset': 0, 'filterCutoff': 1000, 'attack': 0.002, 'reverbSend': 0.10000000000000001, 'overlap': False, 'amplitude': 0.94691792606223446, 'pitch': 35, 'duration': 5, 'noteID': 29, 'pan': 0.5}, ''), - #(6, {'fullDuration': False, 'pageID': 0, 'decay': 0.098000000000000004, 'trackID': 0, 'instrumentFlag': 'gam', 'filterType': 0, 'tied': False, 'onset': 6, 'filterCutoff': 1000, 'attack': 0.002, 'reverbSend': 0.10000000000000001, 'overlap': False, 'amplitude': 0.65465607337722664, 'pitch': 26, 'duration': 7, 'noteID': 23, 'pan': 0.5}, ''), - #(6, {'fullDuration': False, 'pageID': 0, 'decay': 0.098000000000000004, 'trackID': 0, 'instrumentFlag': 'gam', 'filterType': 0, 'tied': False, 'onset': 6, 'filterCutoff': 1000, 'attack': 0.002, 'reverbSend': 0.10000000000000001, 'overlap': False, 'amplitude': 0.66382312969855872, 'pitch': 28, 'duration': 5, 'noteID': 16, 'pan': 0.5}, ''), - #(6, {'fullDuration': False, 'pageID': 0, 'decay': 0.098000000000000004, 'trackID': 0, 'instrumentFlag': 'koto', 'filterType': 0, 'tied': False, 'onset': 6, 'filterCutoff': 1000, 'attack': 0.002, 'reverbSend': 0.10000000000000001, 'overlap': False, 'amplitude': 0.69112283960585841, 'pitch': 33, 'duration': 5, 'noteID': 9, 'pan': 0.5}, ''), - #(6, {'fullDuration': False, 'pageID': 0, 'decay': 0.098000000000000004, 'trackID': 0, 'instrumentFlag': 'drum1hatshoulder', 'filterType': 0, 'tied': False, 'onset': 6, 'filterCutoff': 1000, 'attack': 0.002, 'reverbSend': 0.10000000000000001, 'overlap': False, 'amplitude': 0.70739520974639736, 'pitch': 46, 'duration': 1, 'noteID': 46, 'pan': 0.5}, ''), - #(6, {'fullDuration': False, 'pageID': 0, 'decay': 0.098000000000000004, 'trackID': 0, 'instrumentFlag': 'flute', 'filterType': 0, 'tied': False, 'onset': 6, 'filterCutoff': 1000, 'attack': 0.002, 'reverbSend': 0.10000000000000001, 'overlap': False, 'amplitude': 0.72961742679087493, 'pitch': 31, 'duration': 5, 'noteID': 2, 'pan': 0.5}, '') - (0, {'fullDuration': True, 'pageID': 0, 'decay': 0.098000000000000004, 'trackID': 0, 'instrumentFlag': 'gam', 'filterType': 0, 'tied': False, 'onset': 0, 'filterCutoff': 1000, 'attack': 0.002, 'reverbSend': 0.10000000000000001, 'overlap': False, 'amplitude': 0.98273554224748583, 'pitch': 33, 'duration': 6, 'noteID': 15, 'pan': 0.5}, '') - ] - - -cmdEvent = [ - "perf.InputMessage('i 5777 0.0 0.001 5003.5 %f 0.050000 1.000000 0.100000 0.773 0.500000 5019 0.002 0.004 0 1000.000000')", - "perf.InputMessage('i 5777 0.0 0.001 5003.5 %f 0.050000 1.000000 0.100000 0.773 0.500000 5020 0.002 0.004 0 1000.000000')", - "perf.InputMessage('i 5777 0.0 0.001 5003.5 %f 0.050000 1.000000 0.100000 0.773 0.500000 5021 0.002 0.004 0 1000.000000')", - "perf.InputMessage('i 5777 0.0 0.001 5003.5 %f 0.050000 1.000000 0.100000 0.773 0.500000 5028 0.002 0.004 0 1000.000000')", - "perf.InputMessage('i 5777 0.0 0.001 5003.5 %f 0.050000 1.000000 0.100000 0.773 0.500000 5017 0.002 0.004 0 1000.000000')", - "perf.InputMessage('i 5777 0.0 0.001 5003.5 %f 0.050000 1.000000 0.100000 0.773 0.500000 5011 0.002 0.004 0 1000.000000')", - "perf.InputMessage('i 5777 0.0 0.001 5003.5 %f 0.050000 1.000000 0.100000 0.773 0.500000 5012 0.002 0.004 0 1000.000000')", - "perf.InputMessage('i 5777 0.0 0.001 5003.5 %f 0.050000 1.000000 0.100000 0.773 0.500000 5013 0.002 0.004 0 1000.000000')", - "perf.InputMessage('i 5777 0.0 0.001 5003.5 %f 0.050000 1.000000 0.100000 0.773 0.500000 5012 0.002 0.004 0 1000.000000')" - ] -cmdStraight = [ - "perf.InputMessage('i 5003.5 %f 0.050000 1.000000 0.100000 0.773 0.500000 5019 0.002 0.004 0 1000.000000')", - "perf.InputMessage('i 5003.5 %f 0.050000 1.000000 0.100000 0.773 0.500000 5020 0.002 0.004 0 1000.000000')", - "perf.InputMessage('i 5003.5 %f 0.050000 1.000000 0.100000 0.773 0.500000 5021 0.002 0.004 0 1000.000000')", - "perf.InputMessage('i 5003.5 %f 0.050000 1.000000 0.100000 0.773 0.500000 5028 0.002 0.004 0 1000.000000')", - "perf.InputMessage('i 5003.5 %f 0.050000 1.000000 0.100000 0.773 0.500000 5017 0.002 0.004 0 1000.000000')", - "perf.InputMessage('i 5003.5 %f 0.050000 1.000000 0.100000 0.773 0.500000 5011 0.002 0.004 0 1000.000000')", - "perf.InputMessage('i 5003.5 %f 0.050000 1.000000 0.100000 0.773 0.500000 5012 0.002 0.004 0 1000.000000')", - "perf.InputMessage('i 5003.5 %f 0.050000 1.000000 0.100000 0.773 0.500000 5013 0.002 0.004 0 1000.000000')", - "perf.InputMessage('i 5003.5 %f 0.050000 1.000000 0.100000 0.773 0.500000 5012 0.002 0.004 0 1000.000000')" - ] - -CSoundClient.initialize() -CSoundClient.setMasterVolume(100.0) - - - -i = 0 -t1 = time.time() -m = v = vv = 0.0 - -loopsleep = 0.05 -loopdelay = 0.1 - - -time0 = time.time() -nl.setDuration(12) -nl.setTick(0) -CSoundClient.startTime() - -while True : - - t0 = t1 - i = i + 1 - now = time.time() - if True: - next = nl.next() - for n in next: - CSoundClient.sendText(n) - - elif True: - j = i % 4 - if j == 0: - CSoundClient.sendText( cmdEvent[1] % ( (now - time0) + loopdelay, )) - CSoundClient.sendText( cmdEvent[3] % ( (now - time0) + loopdelay, ) ) - pass - elif j == 1: - CSoundClient.sendText( cmdEvent[4] % ( (now - time0) + loopdelay, ) ) - CSoundClient.sendText( cmdEvent[5] % ( (now - time0) + loopdelay, ) ) - pass - elif j == 2: - CSoundClient.sendText( cmdEvent[2] % ( (now - time0) + loopdelay, ) ) - CSoundClient.sendText( cmdEvent[5] % ( (now - time0) + loopdelay, ) ) - pass - else: - CSoundClient.sendText( cmdEvent[1] % ( (now - time0) + loopdelay, )) - CSoundClient.sendText( cmdEvent[4] % ( (now - time0) + loopdelay, ) ) - elif True: - j = i % 4 - if j == 0: - CSoundClient.sendText( cmdStraight[1] % (loopdelay, )) - CSoundClient.sendText( cmdStraight[3] % (loopdelay, ) ) - pass - elif j == 1: - CSoundClient.sendText( cmdStraight[4] % (loopdelay, ) ) - CSoundClient.sendText( cmdStraight[5] % (loopdelay, ) ) - pass - elif j == 2: - CSoundClient.sendText( cmdStraight[2] % (loopdelay, ) ) - CSoundClient.sendText( cmdStraight[5] % (loopdelay, ) ) - pass - else: - CSoundClient.sendText( cmdStraight[1] % (loopdelay, )) - CSoundClient.sendText( cmdStraight[4] % (loopdelay, ) ) - time.sleep(loopsleep) - t1 = time.time() +from Util.CSoundClient import new_csound_client +from Util.NoteDB import PARAMETER, NoteDB +from Util.ControlStream import * + + +class MiniPlayer: + def __init__(self, ndb): + self.csnd = new_csound_client() + self.csnd.connect(True) + self.csnd.loopSetNumTicks(50) + self.csnd.loopStart() + self.csnd.setMasterVolume(1.0) + self.csnd.setTrackVolume(1.0, 1) - r = 1.0 / i - d = t1 - t0 - m = r * d + (1.0 - r) * m - v = r * d * d + (1.0 - r) * v - vv = r * d * d * d + (1.0 - r) * v + self.noteDB = ndb + ndb.addListener( self, page=True, note=True ) - #print m, math.sqrt(v - m * m ), math.pow( vv - m*m*m, 0.333333) - break -CSoundClient.initialize(False) + def recompose( self, algo, params, genOrVar): + + newtracks = set(range(Config.NUMBER_OF_TRACKS)) + newpages = self.tuneInterface.getSelectedIds() + + if genOrVar == 0: + dict = {} + for t in newtracks: + dict[t] = {} + for p in newpages: + dict[t][p] = self.noteDB.getCSNotesByTrack( p, t ) + else: + dict = {} + for t in newtracks: + dict[t] = {} + dict[t][1] = self.noteDB.getCSNotesByTrack( 1, t ) + + beatsOfPages = {} + for pageId in newpages: + beatsOfPages[pageId] = self.noteDB.pages[pageId].beats + + algo( + params, + self._data['track_volume'][:], + [ i.name for i in self.trackInstrument ], + self._data['tempo'], + beatsOfPages, + newtracks, + newpages, + dict) + + # filter & fix input ...WTF!? + for track in dict: + for page in dict[track]: + for note in dict[track][page]: + intdur = int(note.duration) + note.duration = intdur + note.pageId = page + note.trackId = track + + # prepare the new notes + newnotes = [] + for tid in dict: + for pid in dict[tid]: + newnotes += dict[tid][pid] + + # delete the notes and add the new + self.noteDB.deleteNotesByTrack( newpages, newtracks ) + + stream = [] + for page in newpages: + for track in newtracks: + stream += [ page, track, len(dict[track][page]) ] + stream += dict[track][page] + stream += [-1] + self.noteDB.addNotes( stream ) + def notifyPageAdd( self, id, at ): + return + + def notifyPageDelete( self, which, safe ): + pass + + def notifyPageDuplicate( self, new, at ): + return + + def notifyPageMove( self, which, low, high ): + return + + def notifyNoteAdd( self, page, track, id ): + print 'INFO: adding note to loop', page, track, id + n = self.noteDB.getNote(page, track, id) + self.csnd.loopPlay(n,0) + onset = n.cs.onset + 0 #self.page_onset[n.page] + self.csnd.loopUpdate(n, PARAMETER.ONSET, onset, 1) #set onset + activate + + def notifyNoteDelete( self, page, track, id ): + print 'INFO: deleting note from loop', page, track, id + self.csnd.loopDelete1(page,id) + def notifyNoteUpdate( self, page, track, id, parameter, value ): + print 'INFO: updating note ', page, id, parameter, value + note = self.noteDB.getNote(page, track, id) + self.csnd.loopUpdate(note, parameter, value, -1) + +if __name__ == '__main__': + ndb = NoteDB() + mplayer = MiniPlayer(ndb) + + ttt = TamTamTable(ndb) + table = ttt.parseTable() + while True: + l = sys.stdin.readline() + if l == '\n': break + cmdlist = l.split() + if cmdlist[0] not in table: + print 'ERROR: command %s not defined by parse table' % cmdlist[0] + else: + table[cmdlist[0]](cmdlist[1:]) diff --git a/miniTamTam/MiniSequencer.py b/miniTamTam/MiniSequencer.py index 8a99606..45ed16b 100644 --- a/miniTamTam/MiniSequencer.py +++ b/miniTamTam/MiniSequencer.py @@ -15,11 +15,13 @@ class MiniSequencer: self.pitchs = [] self.beat = 4 self.tempo = Config.PLAYER_TEMPO - self.tick = 15 + self.checkOk = 0 + self.tick = 0 self.id = 1000 self.csnd = new_csound_client() self.startLooking = 0 self.recordState = 0 + self.startPoint = 0 self.recordButtonState = recordButtonState self.playbackTimeout = None self.playState = 0 @@ -61,6 +63,13 @@ class MiniSequencer: self.playState = 0 def recording( self, note ): + if self.startLooking: + self.sequencer = [] + self.pitchs = [] + self.recordState = 1 + self.startLooking = 0 + self.recordButtonState(True) + self.startPoint = self.csnd.loopGetTick() if self.recordState: self.pitchs.append( note.pitch ) self.sequencer.append( note ) @@ -91,7 +100,8 @@ class MiniSequencer: self.pitchs.remove( pitch ) def handleClock( self ): - t = self.csnd.loopGetTick() / 3 + currentTick = self.csnd.loopGetTick() + t = currentTick / 3 if self.tick != t: self.tick = t if self.startLooking: @@ -99,16 +109,14 @@ class MiniSequencer: self.recordButtonState(True) if self.tick in self.upBeats: self.recordButtonState(False) - if self.tick == 0: - self.sequencer = [] - self.pitchs = [] - self.recordState = 1 - self.startLooking = 0 - if self.tick >= (4 * self.beat - 1): - if self.recordState: - self.recordState = 0 - self.recordButtonState(False) + if self.recordState: + if currentTick < self.startPoint: + self.checkOk = 1 + if currentTick >= self.startPoint and self.checkOk: + self.checkOk = 0 + self.recordState = 0 + self.recordButtonState(False) return True diff --git a/miniTamTam/miniTamTamMain.py b/miniTamTam/miniTamTamMain.py index 82dce2a..b8bf123 100644 --- a/miniTamTam/miniTamTamMain.py +++ b/miniTamTam/miniTamTamMain.py @@ -406,12 +406,19 @@ class miniTamTamMain(SubActivity): cleanInstrumentList.sort(lambda g,l: cmp(Config.INSTRUMENTS[g].category, Config.INSTRUMENTS[l].category) ) return cleanInstrumentList + ['drum1kit', 'drum2kit', 'drum3kit'] + def onActivate( self ): + self.csnd.loopPause() + self.csnd.loopClear() + def onDeactivate( self ): SubActivity.onDeactivate( self ) self.releaseInstrumentPanel() + self.csnd.loopPause() + self.csnd.loopClear() def onDestroy( self ): #this gets called when the whole app is being destroyed + #QUESTION is this called before or after onDeactivate() pass def scale(self, input,input_min,input_max,output_min,output_max): diff --git a/scripts/pull_aclient.sh b/scripts/pull_aclient.sh new file mode 100644 index 0000000..c6edac1 --- /dev/null +++ b/scripts/pull_aclient.sh @@ -0,0 +1,2 @@ +#!/bin/sh +wget http://www-etud.iro.umontreal.ca/~bergstrj/tamtam/aclient.so -o Util/Clooper/aclient.so |