Browse Source

lots of tweaks; added pad generator that makes chords based on the bassline

master
spoonietunes 8 months ago
parent
commit
5018e12d76
  1. 5
      .gitignore
  2. BIN
      .sunvox_clipboard.sunsynth
  3. BIN
      .sunvox_prev_session.sunvox
  4. 231
      auto-techno.py
  5. 128
      deleteme.tidal
  6. BIN
      sunvox-techno.sunvox
  7. 9
      sunvox_config.ini
  8. 3
      test.tidal

5
.gitignore vendored

@ -2,3 +2,8 @@ @@ -2,3 +2,8 @@
*.jpeg
*.wav
*.mp3
delete*
*delete
scratch*
test*
*test

BIN
.sunvox_clipboard.sunsynth

Binary file not shown.

BIN
.sunvox_prev_session.sunvox

Binary file not shown.

231
auto-techno.py

@ -21,7 +21,7 @@ lowestBpm = 92 @@ -21,7 +21,7 @@ lowestBpm = 92
highestBpm = 135
# force everything to happen within 1 bar
oneBar = 0
oneBar = 1
# stack name
# this doesn't matter, can be any string
@ -39,12 +39,14 @@ percMidiChanStart = 0 @@ -39,12 +39,14 @@ percMidiChanStart = 0
# perc note
# perc notes
# set some notes for percussion tracks
percNotes = [0,1,2,3]
# these notes correspond to notes (C3, C#3, etc)
percNotes = [0,1,2,3,4,5,6,7]
# perc track names
# a percussion track will be generated for each item in this list
percNames = ["kick", "hh", "sd", "cp", "ohh","ride","cymbal"]
percNames = ["kick", "hh","sd","ohh","rim","cp","tom","ride","cymbal"]
# for use generating sequences of 0's and 1's
#
#
@ -57,7 +59,7 @@ percNames = ["kick", "hh", "sd", "cp", "ohh","ride","cymbal"] @@ -57,7 +59,7 @@ percNames = ["kick", "hh", "sd", "cp", "ohh","ride","cymbal"]
# for melodic sequences, define the choices for range of the notes
# eg 12 is one octave, 24 is two, etc
noteRange = [12,24,36]
noteRange = [12,24]
# define the shortest and longest sequence you want
# eg if shortest is 7, there will be no melodic sequences shorter than 7
shortestMelodic = 3
@ -73,7 +75,15 @@ melodicDivisions = [8,16,16,16] @@ -73,7 +75,15 @@ melodicDivisions = [8,16,16,16]
# how many
# how many melodic elements to generate?
melodyCount = 1
melodyMidiChanStart = 7
melodyMidiChanStart = 10
############### PADS ###########################
padCount = 1
padMidiChanStart = melodyMidiChanStart + 1
## import stuff
@ -119,9 +129,11 @@ else: @@ -119,9 +129,11 @@ else:
seed = seed.replace("X","x")
#print("seed: "+seed)
# here is the seed in decimal format (eg 3892423)
decimalSeed = int(seed,16)
### FRONTMATTER ###
# put some stuff at the top of the tidal code
print("-- raw input: " + str(rawinput))
print("-- hex seed: "+seed)
print("-- decimal seed: "+str(decimalSeed))
@ -170,9 +182,9 @@ def generateBinary(busyness): @@ -170,9 +182,9 @@ def generateBinary(busyness):
elif (busyness == 7):
binary = [0,0,1,1,1,1,1,1,1]
elif (busyness == 8):
binary = [0,0,1,1,1,1,1,1,1,1]
binary = [0,0,0,0,0,0,1,1,1,1,1,1,1]
elif (busyness == 9):
binary = [0,0,1,1,1,1,1,1,1,1,1]
binary = [0,0,0,0,1,1,1,1,1,1,1,1,1]
return binary
def genOnOff(limit,busyness,struct):
@ -205,16 +217,36 @@ def genOnOff(limit,busyness,struct): @@ -205,16 +217,36 @@ def genOnOff(limit,busyness,struct):
else:
return(zeroesOnes)
def genVelocity(limit):
"""
Generate a series of decimals < 1 to control velocity
"""
velocities = ""
for i in range(limit):
#velocities = str((decimal.Decimal(random.choice([0.5,0.75,1],[0.5,75,1]]))).quantize(Decimal('.01')))+" "+str(velocities)
velocities = str(random.choice([0.85,0.9,1]))+" "+velocities
degradeAmt = (decimal.Decimal(random.random())).quantize(Decimal('.01'))
# remove trailing space
velocities = str(velocities).rstrip()
return velocities
def euclid(divider):
"generate a euclidean rhythm for tidalcycles"
def euclid(divider,max):
"""
generate a euclidean rhythm for tidalcycles
the "divider" argument is the 2nd number, and
the "max" argument is the maximum integer of the 1st number
... because we don't always want a super dense rhythm!
"""
# like struct "[t(3,8)]"
# 3,8 10,16 4,16
#secondEuclid = str(random.choice(dividers))
secondEuclid = divider
firstEuclid = str(random.randrange(2,divider))
firstEuclid = str(random.randrange(2,max))
#print("firstEuclid:"+firstEuclid)
#print("secondEuclid:"+str(secondEuclid))
@ -228,7 +260,9 @@ def euclid(divider): @@ -228,7 +260,9 @@ def euclid(divider):
else:
# the first euclid number WILL sequence (eg <4,8>)
#firstEuclid = "<"+str(random.randrange(2,int(random.choice(dividers)))+" "+str(random.randrange(2,int(random.choice(dividers))))+">"
firstEuclid = "<"+str(random.randrange(2,divider))+" "+str(random.randrange(2,16))+">"
if (percName == "kick"):
divider = 5 # limit kicks to 5
firstEuclid = "<"+str(random.randrange(2,max))+" "+str(random.randrange(2,16))+">"
# decide whether the second number will seq
if (random.random() > random.random()):
# we will do like [t(??,<16,8>)]
@ -291,26 +325,43 @@ def stut(): @@ -291,26 +325,43 @@ def stut():
time = random.choice([0.125,0.125,0.125,0.0625,0.0625])
return("stut "+str(repeats)+" 1 \""+str(time)+"\"")
def bite():
def bite(style):
"""
Generate something like
bite 16 "{2*4 1*2 10*4 8*8}%16
if style = nice, just do quarter note repeats
if style = wild, do whatever
"""
divisions = [4,8]
number = str(random.choice(divisions))
# generate like 1*4 8*4 2*2 1*2 9*1
repeatChoices = [1,2,4]
# how long should it be?
length = int(random.randint(4,8))
bit = ""
for i in range(length):
bit = str(random.randint(0,int(number)))+"*"+str(random.choice(repeatChoices))+" "+bit
# since bite will always be encapsulated by ( )
# eg whenmod 8 7 (bite 4 "2*4")
# we don't need to prepend with $ or ,
return ("bite "+number+ " \"{"+bit+"}%"+number+"\"")
if (style == "nice"):
# do something nice here
# either repeat half notes or quarter notes
number = random.choice([2,4])
# which beat to repeat?
beat = random.choice([0,1,2,3])
# the goal is something like
# bite 4 "{0 0 0 0}%4"
bit = beat+beat+beat+beat
bit = str(bit)
else:
divisions = [4,8]
# number = the divisions to use
# like 'bite 16' where 16 is the 'number'
number = str(random.choice(divisions))
# generate like 1*4 8*4 2*2 1*2 9*1
repeatChoices = [1,2,4]
# how long should it be?
length = int(random.randint(4,8))
bit = ""
for i in range(length):
bit = str(random.randint(0,int(number)))+"*"+str(random.choice(repeatChoices))+" "+bit
# since bite will always be encapsulated by ( )
# eg whenmod 8 7 (bite 4 "2*4")
# we don't need to prepend with $ or
return ("bite "+str(number)+ " \"{"+bit+"}%"+str(number)+"\"")
def offset():
offsetChoices = [0.125,0.125,0.125,0.125,0.1875,0.1875,0.1875]
@ -327,12 +378,12 @@ def fills(): @@ -327,12 +378,12 @@ def fills():
But nothing too intense
"""
# like whenmod 8 7
fillChoices = [stut(),"rev",scramble()]
fillChoices = ["rev","rev",scramble(),bite("nice"),bite("nice")]
# how many filles do we want?
fills = ""
for i in range(1,10):
# roll the dice
whenmods = ["8 7","16 15","16 14","32 31","64 62","64 63","32 30"]
whenmods = ["8 7","16 15","16 14","32 31","64 63","32 30","8 7"]
fills = str(random.choice(fillChoices))+" "+fills
return "whenmod "+str(random.choice(whenmods))+" ("+fills.rstrip()+")"
@ -343,17 +394,21 @@ def sometimesBeQuiet(): @@ -343,17 +394,21 @@ def sometimesBeQuiet():
"""
#def genOnOff(limit,busyness,struct):
# decide whether to do this at all
if (random.randint(0,10) > 5):
if (random.randint(0,10) > 0):
# for now, 8 bar phrases
# (# gain "[0 1 0 0 1]/8")
# how many cycles to make?
quietCycles = random.choice([2,3,4])
quietBinary = genOnOff(quietCycles,2,0)
quietCycles = random.choice([8])
# this generates a sequence like 011010110
quietBinary = genOnOff(quietCycles,4,0)
# split 001001 into 0 0 1 0 0 1
quietBinary = list(quietBinary)
finalQuietBinary = ""
for i in quietBinary:
finalQuietBinary = i + " " + finalQuietBinary
# now the pattern looks like 0 1 0 0 1 0 0 1
print(indent+indent+"$ degradeBy \"<"+str(finalQuietBinary).rstrip()+">/8\"")
########################### LISTS ##########################
@ -366,7 +421,7 @@ cpPats=["[~t]*2","[t(3,8)]","[[~~~t][~t]]*2"] @@ -366,7 +421,7 @@ cpPats=["[~t]*2","[t(3,8)]","[[~~~t][~t]]*2"]
cyPats=["[t*4]","[t*8]","[t~~~]","[t~~[~~~t]]","[<t~~~>~~~]"]
# a collection of misc rhythms
rhythmLibrary = ["[1*4]","[1*8]","[1*9]","[01]*2","[0101]","[1*16]","[1*16?]","[111111[1001][01]]/2","[{100}%16]","[{101011010101}%16]","[{10100}%16]","[{10001}%16]","[{10101}%16]","[{1001010}%16]","[{1011010}%16]","[{10101000100}%16]","[{10101001010}%16]","[{10010010010}%16]","[{1010101001010}%16]","[{1001001001010}%16]","[11*2]*4","[100000<0100>000100<01>00]","[1[10000001]]","[1111*2]","[[0001][01]]*2","[0010000100000001]","[[0001][01]]*2","[[01]1[1001][01]]","[[01]1[1001][0001]]","[11000010]*2","[[0001]000]","[[0001]]*4"]
rhythmLibrary = ["[1*4]","[1*8]","[1*16]","[01]*2","[0101]","[1*16]","[1*16?]","[111111[1001][01]]/2","[{100}%16]","[{101011010101}%16]","[{10100}%16]","[{10001}%16]","[{10101}%16]","[{1001010}%16]","[{1011010}%16]","[{10101000100}%16]","[{10101001010}%16]","[{10010010010}%16]","[{1010101001010}%16]","[{1001001001010}%16]","[11*2]*4","[100000<0100>000100<01>00]","[1[10000001]]","[1111*2]","[[0001][01]]*2","[0010000100000001]","[[0001][01]]*2","[[01]1[1001][01]]","[[01]1[1001][0001]]","[11000010]*2","[[0001]000]","[[0001]]*4"]
############### It's assemble time!! ###################
@ -390,7 +445,7 @@ print(indent+"p \""+stackName+"\" ") @@ -390,7 +445,7 @@ print(indent+"p \""+stackName+"\" ")
print(indent+indent+"-- fills")
# roll the dice up to N times
for i in range(1,8):
if (random.randint(0,10) > 4):
if (random.randint(0,10) > 3):
print(indent+indent+"$ "+fills())
# how many "fun" things to add?
@ -429,6 +484,8 @@ percMidiChan = 0 @@ -429,6 +484,8 @@ percMidiChan = 0
## will be created
for i in percNames:
percName = i
# print the name of the track (from the percNames list)
print(indent+indent+"-------------- "+i+" ---------------")
@ -499,14 +556,42 @@ for i in percNames: @@ -499,14 +556,42 @@ for i in percNames:
#print(","+str(genOnOff(10)))
#print(str(percSequence))
# how busy will it be?a
# choose a random value between 0 and 9
busyness = random.randrange(0,7)
# choose a random value
# guide the random value based on the name
# since we don't really want a kick on every 16th note
# lots of hh = good, lots of cymbal = maybe not
if (percName == "kick"):
busyness = random.randrange(1,3)
elif (percName == "sd"):
busyness = random.randrange(0,4)
elif (percName == "cp"):
busyness = random.randrange(0,4)
elif (percName == "hh"):
busyness = random.randrange(3,9)
elif (percName == "ride"):
busyness = random.randrange(0,6)
elif (percName == "cymbal"):
busyness = random.randrange(0,1)
else:
busyness = random.randrange(0,7)
generateBinary(busyness)
rhythm = str(genOnOff(percLength,busyness,1))
elif (rChoice == 2):
# GENERATE EUCLIDEAN RHYTHMS
rhythm = str(euclid(random.choice(dividers)))
# treating the kick like the other tracks often generates
# way too many events (like [t(11,16)]) which is usually
# way too much for a techno kick!
# here's I'm trying to moderate that
if (percName == "kick"):
# do something
maxEuclidEvents = 5
else:
maxEuclidEvents = 13
#print("MAX EUCLID EVENTS: "+str(maxEuclidEvents))
rhythm = str(euclid(random.choice(dividers),maxEuclidEvents))
#print(indent+indent+euclid(random.choice(dividers)))
#
else:
@ -521,27 +606,87 @@ for i in percNames: @@ -521,27 +606,87 @@ for i in percNames:
# add "struct" to the beginning
# and enclose in < >
print(indent+indent+"$ struct \"<"+fullRhythm+">\"")
print (indent+indent+"$ n "+str(random.choice(percNotes))+" # midichan "+str(percMidiChan)+",")
# roll the dice to get a length of the velocity pattern
velocityLength = random.randint(2,16)
notes = indent+indent+"$ n "+str(random.choice(percNotes))
velocity = indent+indent+"# gain \"{"+genVelocity(int(random.randrange(2,16)))+"}%16\""
midi = indent+indent+"# midichan "+str(percMidiChan)
#print (# midichan "+str(percMidiChan)+" \n"+indent+indent"# gain \"{"+genVelocity(int(random.randrange(2,16)))+"}%16"+",")
print(notes+"\n"+velocity+"\n"+midi+",")
percMidiChan = percMidiChan + 1
# generate melodic tracks
melodicMidiChan = melodyMidiChanStart
#melodyMidiChanStart = 7
for i in range(melodyCount):
print(indent+indent+"-----------------------")
print(indent+indent+"------------ bassline -------")
print(indent+indent+"degradeBy 0 ")
#print(", ")
busyness = random.choice([0,1,2,3,4,5,6,6,6,6,7,7,7,7,8,8,8,9,9])
if (oneBar == 1):
print(indent+indent+"$ struct \""+genOnOff(16,(busyness),1)+"\"")
print(indent+indent+"$ "+genNotes(1))
notes = genNotes(1)
print(indent+indent+"$ "+notes)
else:
# how many 16th notes?
thisLength = random.randint(3,16)
#genOnOff(8,(busyness))
print(indent+indent+"$ struct \""+genOnOff(thisLength,(busyness),1)+"\"")
print(indent+indent+"$ "+genNotes(0))
print(indent+indent+"# midichan "+str(melodicMidiChan)+" + n (-42)")
notes = genNotes(0)
print(indent+indent+"$ "+str(notes))
print(indent+indent+"# midichan "+str(melodicMidiChan)+" + n (-24),")
melodicMidiChan = melodicMidiChan + 1
#### generate pads/chords
# method: grab some of the notes from the last melodic/bassline
# and build some chords with them that go with the bassline
# sort of like the reverb trick, to create a pad from any melodic material
# after we're done making the bassline, the melodicMidiChan will be
# the last midi channel +1, so we can use that for the pad channel
padMidiChan = melodicMidiChan
for i in range(padCount):
print(indent+indent+"------------ pad -------")
# the goal:
# n "[3,12,20,34]"
# where all those numbers are played by the bassline
# get the numbers from the bassline
# it's already stored in the variable "notes"
# but with brackets like this: [{23 6 5 23}%16]
# we'll use regex to remove the extra stuff
padNotes = notes.replace('[{','')
padNotes = padNotes.replace(']','')
padNotes = padNotes.replace('}','')
padNotes = padNotes.replace('"','')
padNotes = padNotes.replace('%16','')
padNotes = padNotes.replace('n ','')
padNotes = padNotes.rstrip()
#print("notes:"+str(padNotes))
# now that we have the notes, as strings, put them into a list
padNotesList = padNotes.split(" ")
# convert this list to a dictionary so there aren't duplicates
# https://www.w3schools.com/python/python_howto_remove_duplicates.asp
padNotes = list(dict.fromkeys(padNotes))
#print(str(padNotesList))
# make a chord
chord = "\"["+random.choice(padNotesList)+","+random.choice(padNotesList)+","+random.choice(padNotesList)+","+random.choice(padNotesList)+"]\""
# build the track
print(indent+indent+"degradeBy 0 ")
print(indent+indent+"$ n "+chord)
print(indent+indent+"# midichan "+str(padMidiChan)+" + n (0)")
## put the finishing touches on the beautiful stack
print(indent+indent+"] # sunvox")

128
deleteme.tidal

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
-- raw input: 268982558670766555
-- hex seed: 0x3BB9E364458C1DB
-- decimal seed: 268982558670766555
-- generated at 1633539511.09
-- raw input: -1654319963628270068
-- hex seed: -0x16F5533DF0E671F4
-- decimal seed: -1654319963628270068
-- generated at 1633644744.38
-- Auto-Techno Generator v0.1
do
@ -10,65 +10,107 @@ do @@ -10,65 +10,107 @@ do
kickM = "[1111]"
hhM = "[1111]"
sdM = "[1111]"
cpM = "[1111]"
ohhM = "[1111]"
rimM = "[1111]"
cpM = "[1111]"
tomM = "[1111]"
rideM = "[1111]"
cymbalM = "[1111]"
p "techno"
-- fills
$ whenmod 32 30 (rev)
$ whenmod 32 31 (stut 2 1 "0.125")
$ whenmod 32 30 (scramble 16)
$ whenmod 16 15 (rev)
$ whenmod 64 62 (rev)
$ whenmod 32 31 (rev)
$ whenmod 16 15 (scramble 8)
$ whenmod 16 15 (bite 4 "{4}%4")
$ whenmod 8 7 (bite 2 "{8}%2")
$ whenmod 32 31 (rev)
$ whenmod 32 30 (bite 2 "{8}%2")
$ whenmod 32 31 (rev)
$ stack [
-- four to the floor
degradeBy fourToTheFloor $ struct "[t*4]" $ n "0" # midichan 0,
-------------- kick ---------------
mask kickM
$ every 6 ((0.125 ~>))
$ (0.125 ~>)
$ struct "<[{0101011}%16]>"
$ n 1 # midichan 0,
$ every 9 ((0.125 ~>))
$ every 9 ((0.125 ~>))
$ struct "<[{101000010}%16]>"
$ n 5
# gain "{0.85 1 0.85}%16"
# midichan 0,
-------------- hh ---------------
mask hhM
$ every 16 (scramble 8)
$ every 15 ((0.125 ~>))
$ struct "<[1*16]>"
$ n 3 # midichan 1,
$ degradeBy "<0 1 0 0 0 0 0 0>/8"
$ struct "<[t*4]>"
$ n 3
# gain "{0.9 0.85 0.9}%16"
# midichan 1,
-------------- sd ---------------
mask sdM
$ every 15 (stut 5 1 "0.0625")
$ degradeBy "<0 0 0 0 0 1 1 0>/8"
$ every 11 ((0.125 ~>))
$ every 12 ((0.125 ~>))
$ every 8 (scramble 8)
$ struct "<[t(7,16)]>"
$ n 6
# gain "{0.85 0.9 1}%16"
# midichan 2,
-------------- ohh ---------------
mask ohhM
$ degradeBy "<0 0 0 0 0 1 0 0>/8"
$ every 6 ((0.125 ~>))
$ struct "<[{0000}%16] [{00001}%16]>"
$ n 4
# gain "{0.85 0.85 0.85 0.9 0.85 1 1 0.9 1 1 1}%16"
# midichan 3,
-------------- rim ---------------
mask rimM
$ degradeBy "<0 1 0 1 0 1 0 0>/8"
$ every 14 ((0.125 ~>))
$ every 5 (scramble 8)
$ (0.125 ~>)
$ struct "<[t(15,16)]>"
$ n 2 # midichan 2,
$ struct "<[{111010}%16]>"
$ n 1
# gain "{0.9 1 0.85}%16"
# midichan 4,
-------------- cp ---------------
mask cpM
$ degradeBy "[0 0 1]/8"
$ struct "<[{0000100}%16]>"
$ n 3 # midichan 3,
-------------- ohh ---------------
mask ohhM
$ struct "<[tt*2]*4 [[0001]]*4>"
$ n 0 # midichan 4,
$ every 3 ((0.125 ~>))
$ every 11 (scramble 8)
$ every 10 (stut 1 1 "0.0625")
$ (0.125 ~>)
$ struct "<[{0000}%16] [{10010010010}%16]>"
$ n 2
# gain "{0.9 0.9 0.9 1 0.9 0.9 1}%16"
# midichan 5,
-------------- tom ---------------
mask tomM
$ every 12 (stut 1 1 "0.0625")
$ (0.1875 ~>)
$ struct "<[{10011100}%16] [t(11,16)]>"
$ n 0
# gain "{0.9 0.85 0.85 0.9 0.9 1 1 0.85 0.9 1 1 0.85 0.9 0.85}%16"
# midichan 6,
-------------- ride ---------------
mask rideM
$ every 10 (scramble 8)
$ every 5 (rev)
$ every 13 (scramble 8)
$ (0.1875 ~>)
$ struct "<[t(4,16)]>"
$ n 0 # midichan 5,
$ degradeBy "<0 0 0 0 0 0 0 0>/8"
$ every 15 (stut 1 1 "0.0625")
$ struct "<[t(10,16)]>"
$ n 7
# gain "{0.9 1 0.9 0.85 0.85 0.9 0.85 1 0.9 0.9 1 0.9 0.9}%16"
# midichan 7,
-------------- cymbal ---------------
mask cymbalM
$ every 8 (rev)
$ every 7 (rev)
$ every 12 (stut 5 1 "0.0625")
$ struct "<[{10011000}%16]>"
$ n 3 # midichan 6,
-----------------------
$ degradeBy "<1 0 0 0 0 0 0 1>/8"
$ struct "<[{1011010}%16]>"
$ n 5
# gain "{0.85 1 0.9 0.85 0.9 0.85 1 0.9}%16"
# midichan 8,
------------ bassline -------
degradeBy 0
$ struct "[{00111110101011110000}%16]"
$ n "[{4 11 0 22 3 10 10 3 11 1 5 10 5 10 4 4 }%16]"
# midichan 10 + n (-24),
------------ pad -------
degradeBy 0
$ struct "[{0010100000000000}%16]"
$ n "[{18 6 8 7 19 35 8 24 11 7 7 8 3 23 8 33 }%16]"
# midichan 7 + n (-42)
$ n "[1,4,3,3]"
# midichan 11 + n (0)
] # sunvox

BIN
sunvox-techno.sunvox

Binary file not shown.

9
sunvox_config.ini

@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
midi_kbd "Midi Through Port-0"
midi_kbd_ch 1
audiodriver jack
hdiv1_y 0
hdiv2_y 805
vdiv1_x 481
width 1554
height 831
builtin_theme 17

3
test.tidal

@ -18,7 +18,8 @@ some seeds I've liked: @@ -18,7 +18,8 @@ some seeds I've liked:
1014891741240181557 -- pretty funky
850750894594826640 -- great if the kick is t(3,8) instead of t(3,4)
2195224328517994763 -- funnnnkkky
-- seed: -2138151558308434562
0x508DFAD3954D1C9 -- cooool
seed: -2138151558308434562
setcps = (18/60/4)

Loading…
Cancel
Save