diff --git a/auto-techno.py b/auto-techno.py index d40f36d..c3f17e0 100644 --- a/auto-techno.py +++ b/auto-techno.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 scriptName = "Auto-Techno Generator" -version = "0.1.2" +version = "0.1.3" author = "Chris Beckstrom" author_email = "chris@chrisbeckstrom.com" # a deterministic techno generator for tidalcycles @@ -36,8 +36,12 @@ minSwing = 0 maxSwing = 0.1 # force everything to happen within 1 bar +oneBar = random.choice([0,1,1,1,1,1]) + +# style - techno, electro +styleChoices = ["techno","techno","electro"] +style = random.choice(styleChoices) -oneBar = random.choice([0,1]) # stack name # this doesn't matter, can be any string @@ -64,7 +68,7 @@ percNames = ["kick", "hh","sd","rim","cp","tom","ride","cymbal"] # these notes correspond to notes (C3, C#3, etc) # each percussion track will pick one of these notes # and send note on/off messages to that note -percNotes = [0,1,2,3,4,5,6,7,8,9,10,11] +percNotes = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] # ####### MELODY ################################# @@ -168,6 +172,7 @@ decimalSeed = int(seed,16) print("-- raw input: " + str(rawinput)) print("-- hex seed: "+seed) print("-- decimal seed: "+str(decimalSeed)) +print("-- style: "+str(style)) print("-- generated at "+str(time.time())) print("-- "+scriptName+" v"+str(version)) print("") @@ -232,7 +237,7 @@ def markovBinary(count): #print("fullpat: "+str(fullPat)) -def genKicks(): +def genPats(style,track): """ the idea: generate kick drum patterns by weight @@ -240,6 +245,9 @@ def genKicks(): output: a series of 1's and 0's (struct) and also a gain pattern + style = techno, electro + track = kick, sd + 100 = always always always play an event on this 16th note 0 = NEVER play an event on this 16th note 50 = play an event on this step half the time @@ -252,27 +260,112 @@ def genKicks(): bars = 4 patternList = [] - stepWeights = [100, - 10, - 15, - 20, - ###### - 85, - 15, - 25, - 10, - ###### - 85, - 10, - 10, - 10, - ###### - 80, - 10, - 10, - 10] - - fullKickPattern = "" + # change the weights of each step depending on the style and instrument + if (style == "techno"): + if(track == "kick"): + stepWeights = [100, + 10, + 15, + 20, + ###### + 85, + 15, + 25, + 10, + ###### + 85, + 10, + 10, + 10, + ###### + 80, + 10, + 10, + 10] + else: + #(track == "sd"): + stepWeights = [6, + 6, + 6, + 6, + ###### + 6, + 6, + 6, + 6, + ###### + 6, + 6, + 6, + 6, + ###### + 6, + 6, + 6, + 6] + else: # if style !== techno + if(track == "kick"): + stepWeights = [100, + 6, + 6, + 6, + ###### + 6, + 6, + 91, + 6, + ###### + 6, + 6, + 61, + 6, + ###### + 6, + 91, + 6, + 6] + if(track == "sd"): + stepWeights = [0, + 30, + 0, + 0, + ###### + 100, + 0, + 0, + 0, + ###### + 0, + 0, + 0, + 30, + ###### + 100, + 0, + 0, + 20] + + if(track == "cp"): + stepWeights = [0, + 30, + 0, + 0, + ###### + 100, + 0, + 0, + 0, + ###### + 0, + 0, + 0, + 30, + ###### + 100, + 0, + 0, + 20] + fullPatPattern = "" pat = "" for bar in range(bars): kickPattern = "[" @@ -307,8 +400,8 @@ def genKicks(): kickPattern = kickPattern + "]" patternList.append(str(kickPattern)) #return("kick pattern: "+str(kickPattern)) - fullKickPattern = fullKickPattern + " " +kickPattern - #print("fullkickpat: "+fullKickPattern) + fullPatPattern = fullPatPattern + " " +kickPattern + #print("fullkickpat: "+fullPatPattern) # ok at this point we have a list that contains (bars) items, # where each item is a generated 16 steps of 1 or 0 @@ -337,9 +430,9 @@ def genKicks(): else: pat = str(patternList[0]) - #fullKickPattern = "<"+str(pat)+">/"+str(bars) - fullKickPattern = "<"+str(pat)+">" - return fullKickPattern + #fullPatPattern = "<"+str(pat)+">/"+str(bars) + fullPatPattern = "<"+str(pat)+">" + return fullPatPattern @@ -598,14 +691,14 @@ def sometimesBeQuiet(): """ #def genOnOff(limit,busyness,struct): # decide whether to do this at all - if (random.randint(0,10) > 1): + if (random.randint(0,10) > 3): # for now, 8 bar phrases # (# gain "[0 1 0 0 1]/8") # how many cycles to make? - quietCycles = random.choice([8,16]) + quietCycles = random.choice([4,8,16]) # this generates a sequence like 011010110 - quietBinary = genOnOff(quietCycles,4,0) + quietBinary = genOnOff(quietCycles,1,0) # split 001001 into 0 0 1 0 0 1 quietBinary = list(quietBinary) finalQuietBinary = "" @@ -620,8 +713,8 @@ def sometimesBeQuiet(): # a collection of typical-ish kick drum patterns bdPats=["[t*4]","[tttt*2]","[tttt*2?]","t(3,8)","[t~~~~~<~t~~>~~~t~~<~t>~~]"] hhPats=["[t*16]","[tt*2]*4","[~t]*4","[t*16]"] -sdPats=["[~t]*2","[t(3,8)]","[[~~~t][~t]]*2"] -cpPats=["[~t]*2","[t(3,8)]","[[~~~t][~t]]*2"] +sdPats=["[~t]*2","[t(3,8)]","[[~~~t][~t]]*2","[~t~t]","[~t~t]","[~~~t]","[~~~t]"] +cpPats=["[~t]*2","[t(3,8)]","[[~~~t][~t]]*2","[~t~t]","[~t~t]","[[~~~t]~~~]"] cyPats=["[t*4]","[t*8]","[t~~~]","[t~~[~~~t]]","[~~~]"] # a collection of misc rhythms @@ -650,7 +743,7 @@ print(indent+"p \""+stackName+"\" ") # swing? # roll the dice to see if there will be any swing at all -if (random.randint(0,10) > 7): +if (random.randint(0,10) > 6): print(indent+indent+"$ "+str(swing(minSwing,maxSwing))) # stack stuff like bite, scramble, etc. will go here @@ -738,11 +831,17 @@ for i in percNames: # choose between random, type-specific (bd,hh,etc), # rhythm library, or euclidean rhythms # 0 = prebaked hard-coded rhythms - # 1 = totally random 0's and 1's + # 1 = totally random 0's and 1's (or for some tracks, weighted gen.) # 2 = euclidean rhythms # 3 = markov chain-based rhythms # 4 = something random from the rhythm library - rChoice = random.choice([0,0,0,0,0,0,0,0,0,2,2,2,2,3,3,3,3,3,3,3,3,3,4]) + + # change the rChoice weights based on style + if (style == "techno"): + rChoice = random.choice([0,0,0,0,0,0,0,0,0,2,2,2,2,3,3,3,3,3,3,3,3,3,4]) + else: # style == "electro" + rChoice = random.choice([1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,2,4]) + rhythm = "" # placeholder for the rhythm if (rChoice == 0): # if choice = 0, choose hardcoded rhythms @@ -800,10 +899,12 @@ for i in percNames: generateBinary(busyness) rhythm = str(genOnOff(percLength,busyness,1)) - # if this is a kick, use the genKicks() function instead + # if this is a kick, use the genPats() function instead if (percName == "kick"): - rhythm = str(genKicks()) - + rhythm = str(genPats(style,"kick")) + # same thing with sd + if (percName == "sd"): + rhythm = str(genPats(style,"sd")) elif (rChoice == 2): # GENERATE EUCLIDEAN RHYTHMS @@ -828,9 +929,11 @@ for i in percNames: markovLength = 16 rhythm = "[{"+str(markovBinary(markovLength)).rstrip()+"}%"+str(markovLength)+"]" - # if this is a kick, use the genKicks() function instead + # if this is a kick, use the genPats() function instead if (percName == "kick"): - rhythm = str(genKicks()) + rhythm = str(genPats(style,"kick")) + if (percName == "sd"): + rhythm = str(genPats(style,"sd")) else: @@ -943,6 +1046,7 @@ for i in range(padCount): padNotes = padNotes.replace('}','') padNotes = padNotes.replace('"','') padNotes = padNotes.replace('%16','') + padNotes = padNotes.replace('%8','') padNotes = padNotes.replace('n ','') padNotes = padNotes.rstrip() @@ -968,7 +1072,7 @@ for i in range(padCount): pads = "["+ random.choice(padNotesList)+","+random.choice(padNotesList)+","+random.choice(padNotesList)+","+random.choice(padNotesList)+"]"+str(pads) # should we even play the pads? - if (random.randint(0,10) > 6): + if (random.randint(0,10) > 2): print(indent+indent+"degradeBy 0 ") else: print(indent+indent+"degradeBy 1 ") diff --git a/deleteme.tidal b/deleteme.tidal index 9c869a7..00397c9 100644 --- a/deleteme.tidal +++ b/deleteme.tidal @@ -1,7 +1,133 @@ +-- raw input: 1431850643693044900 +-- hex seed: 0x13DEF492FCBD04A4 +-- decimal seed: 1431850643693044900 +-- style: techno +-- generated at 1633801547.93 +-- Auto-Techno Generator v0.1.3 - - - - - -d1 $ struct "<[t*4] <[1000 1000 1000 1001][1001 1000 1000 1010]>/4>" $ s "bd" +do + let fourToTheFloor = 1 -- set to 0 to hear it + -- extra stuff + extraCP = "[0]" + extraHH = "[0]" + -- control density per track + kickM = "[1111]" + hhM = "[1111]" + sdM = "[1111]" + rimM = "[1111]" + cpM = "[1111]" + tomM = "[1111]" + rideM = "[1111]" + cymbalM = "[1111]" + p "techno" + -- fills + $ whenmod 16 14 (bite 4 "{4}%4") + $ whenmod 32 30 (bite 2 "{0}%2") + $ whenmod 32 30 (rev) + $ whenmod 32 31 (scramble 8) + $ whenmod 32 31 (scramble 4) + $ whenmod 16 14 (bite 2 "{0}%2") + $ stack [ + -- four to the floor + mask "t" + $ degradeBy "<1 0 0 1 0 0 1 1>/8" + $ degradeBy fourToTheFloor $ struct "[t*4]" $ n "0" # midichan 0, + -------------- kick --------------- + mask kickM + $ every 9 (stut 1 1 "0.125") + $ every 7 (scramble 8) + $ every 8 (rev) + $ struct "<[{10101001010}%16]>" + $ n 9 + # gain "{0.9 1 0.85 0.9 1 0.85}%16" + # midichan 0, + -------------- hh --------------- + mask hhM + $ every 16 (degradeBy 0.64) + $ struct "<[t(4,16)]>" + $ n 12 + # gain "{0.85 0.85}%16" + # midichan 1, + -------------- sd --------------- + mask sdM + $ degradeBy "<0 0 1 1 0 0 0 1 0 1 0 0 1 0 1 0>/8" + $ every 10 (stut 1 1 "0.125") + $ every 15 (degradeBy 0.64) + $ every 9 ((0.1875 ~>)) + $ struct "<<[0000 0000 0000 0000][0000 0000 0000 0000][0000 0000 0000 0000][0000 0010 0000 1000]>>" + $ n 11 + # gain "{0.85 0.9 1 0.9 0.85 1 0.85 0.85 1 1 0.9 1 1}%16" + # midichan 2, + -------------- rim --------------- + mask rimM + $ struct "<[{0 0 1 0 0 1 1 0 1 1 0 1 1 0 0 0}%16] [{10101001010}%16]>" + $ n 9 + # gain "{0.85 1 1 0.9 1 0.85 1 1 0.85}%16" + # midichan 3, + -------------- cp --------------- + mask cpM + $ degradeBy "<0 0 0 0>/8" + $ every 16 (scramble 8) + $ every 14 (rev) + $ struct "<[{1011010}%16]>" + $ n 2 + # gain "{0.9 1 0.85 0.9 0.85 0.9 0.9 1 0.9 0.85}%16" + # midichan 4, + -------------- tom --------------- + mask tomM + $ degradeBy "<0 0 0 0>/8" + $ every 13 (rev) + $ every 3 (degradeBy 0.64) + $ struct "<[1*16]>" + $ n 10 + # gain "{0.9 0.9 1 0.85 0.85}%16" + # midichan 5, + -------------- ride --------------- + mask rideM + $ every 2 (rev) + $ every 16 (rev) + $ every 9 (degradeBy 0.64) + $ (0.125 ~>) + $ struct "<[{1 0 0 0 1 1 1 1 1 0 1 1 1 0 1 0}%16]>" + $ n 12 + # gain "{1 0.9 1 0.85 0.85 1 1}%16" + # midichan 6, + -------------- cymbal --------------- + mask cymbalM + $ degradeBy "<0 0 0 0>/8" + $ every 13 (rev) + $ (0.1875 ~>) + $ struct "<[{0 1 0 1 1 0 1 0 0 1 1 1 1 1 0 0}%16]>" + $ n 10 + # gain "{0.9 0.85 1}%16" + # midichan 7, + ------------ bassline ------- + degradeBy 0 + $ struct "[{10011}%16]" + $ n "[{3 0 1 11 16 4 4 18 }%16]" + # midichan 10 + n (-24), + ------------ pad ------- + degradeBy 0 + $ degradeBy "<1 0 0 0 0 1 1 1>/8" + $ struct "[{0010001000100000}%16]" + $ n "<[18,1,4,3]>/4" + # midichan 11 + n (0), + --------- MIDI CC's --------------- + stack [ + struct "[t*2]" $ ccn 0 # ccv "{28 101 2 33}%2", + struct "[t*4]" $ ccn 1 # ccv "{23 27}%4", + struct "[t*1]" $ ccn 2 # ccv "{12 100 95 67}%1", + struct "[t*1]" $ ccn 3 # ccv "{17 14}%1", + struct "t*1" $ ccn 4 # ccv "{0}%1", + struct "[t*4]" $ ccn 5 # ccv "{31 0 7 23 28 26 85}%4", + struct "[t*5]" $ ccn 6 # ccv "{94 101 104 88 54 112 110 114 87 41 44 55 93 66 119}%5", + ccn 126 # ccv 4] # midichan 15, + ------- bass patch ---- + struct "t" $ ccn 101 # ccv 100 # midichan 10, + ------- pads patch ---- + struct "t" $ ccn 102 # ccv 127 # midichan 11, + -- EXTRA STUFF --- + stack [ + (# gain extraCP) $ struct "[~ t ~ t]" $ n "0", + (# gain extraHH) $ struct "[~t~t~t~t]" $ n "1"] # midichan 12 + ] # sunvox