Browse Source

added a new method to create kick patterns, using weighted steps (each of the 16 steps in a bar has a likelihood it will generate an event, eg the 1st 16th note will ALWAYS have an event); some bug fixes

master
spoonietunes 7 months ago
parent
commit
d8242c6bca
  1. 149
      auto-techno.py
  2. 151
      deleteme.tidal
  3. 113
      kick.py

149
auto-techno.py

@ -56,7 +56,7 @@ percMidiChanStart = 0 # the starting MIDI channel for perc tracks @@ -56,7 +56,7 @@ percMidiChanStart = 0 # the starting MIDI channel for perc tracks
# perc track names
# a percussion track will be generated for each item in this list
percNames = ["kick", "hh","sd","ohh","rim","cp","tom","ride","cymbal"]
percNames = ["kick", "hh","sd","rim","cp","tom","ride","cymbal"]
# for use generating sequences of 0's and 1's
#
# perc notes
@ -232,6 +232,117 @@ def markovBinary(count): @@ -232,6 +232,117 @@ def markovBinary(count):
#print("fullpat: "+str(fullPat))
def genKicks():
"""
the idea:
generate kick drum patterns by weight
so it's most likely to play on 1-2-3-4
output: a series of 1's and 0's (struct)
and also a gain pattern
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
etc
arguments: bars = how many total bars to generate (1-4)
variation = the arrangement of the bars
"""
bars = 4
patternList = []
stepWeights = [100,
10,
15,
20,
######
85,
15,
25,
10,
######
85,
10,
10,
10,
######
80,
10,
10,
10]
fullKickPattern = ""
pat = ""
for bar in range(bars):
kickPattern = "["
currentStep = 0
# which bar are we generating?
if (bar == 0):
seq = "a"
elif (bar == 1):
seq = "b"
elif (bar == 2):
seq = "c"
elif (bar == 3):
seq = "d"
for i in stepWeights:
# every 4 steps, insert a space for easier reading
if (currentStep > 3):
currentStep = 0
kickPattern = str(kickPattern)+" "
# roll the dice to generate an event, or not
if (i >= random.randint(0,100)):
# event
kickPattern = str(kickPattern)+"1"
else:
# rest
kickPattern = str(kickPattern)+"0"
currentStep = currentStep + 1
kickPattern = kickPattern + "]"
patternList.append(str(kickPattern))
#return("kick pattern: "+str(kickPattern))
fullKickPattern = fullKickPattern + " " +kickPattern
#print("fullkickpat: "+fullKickPattern)
# ok at this point we have a list that contains (bars) items,
# where each item is a generated 16 steps of 1 or 0
# now we want to generate how to play them -
# just the first? just the first and second? or ABAC?
formChoices = ["A","AB","AB","AB","ABAC","AAAB","AAAB","ABCD"]
form = random.choice(formChoices)
#print("form: "+str(form))
# there is surely a better way to do this, but I don't know what it is
# so for now, here's a hack!
if (str(form) == "A"):
pat = str(patternList[0])
elif (str(form) == "AB"):
pat = str(patternList[0])+""+str(patternList[1])
elif (str(form) == "ABAC"):
pat = str(patternList[0])+""+str(patternList[1])+str(patternList[0])+""+str(patternList[2])
elif (str(form) == "AAAB"):
pat = str(patternList[0])+""+str(patternList[0])+str(patternList[0])+""+str(patternList[1])
elif (str(form) == "ABCD"):
pat = str(patternList[0])+""+str(patternList[1])+str(patternList[2])+""+str(patternList[3])
else:
pat = str(patternList[0])
#fullKickPattern = "<"+str(pat)+">/"+str(bars)
fullKickPattern = "<"+str(pat)+">"
return fullKickPattern
def swing(minSwing,maxSwing):
"""
Generate a swing value for the entire stack
@ -522,7 +633,7 @@ print("do") @@ -522,7 +633,7 @@ print("do")
#print("")
# create "let" statements
print(indent+"let fourToTheFloor = 0 -- set to 0 to hear it")
print(indent+"let fourToTheFloor = 1 -- set to 0 to hear it")
print(indent+" -- extra stuff")
print(indent+" extraCP = \"[0]\"")
print(indent+" extraHH = \"[0]\"")
@ -622,6 +733,7 @@ for i in percNames: @@ -622,6 +733,7 @@ for i in percNames:
# for the number of bars, do this:
fullRhythm = ""
for i in range(rhythmLength):
rhythm = ""
# choose between random, type-specific (bd,hh,etc),
# rhythm library, or euclidean rhythms
@ -630,7 +742,7 @@ for i in percNames: @@ -630,7 +742,7 @@ for i in percNames:
# 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,1,2,2,2,2,3,3,3,3,3,3,3,3,3,4])
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])
rhythm = "" # placeholder for the rhythm
if (rChoice == 0):
# if choice = 0, choose hardcoded rhythms
@ -638,20 +750,21 @@ for i in percNames: @@ -638,20 +750,21 @@ for i in percNames:
# choose from some hard-coded kick rhythms
# 2nd? same for hh
# 3rd? same for sd
if (i == 0):
if (i == 1):
rhythm = str(random.choice(bdPats))
elif (i == 1):
rhythm = str(random.choice(hhPats))
elif (i == 2):
rhythm = str(random.choice(sdPats))
rhythm = str(random.choice(hhPats))
elif (i == 3):
rhythm = str(random.choice(cpPats))
rhythm = str(random.choice(sdPats))
elif (i == 4):
rhythm = str(random.choice(cpPats))
elif (i == 5):
rhythm = str(random.choice(cyPats))
else:
# print("LIBRARY")
rhythm = str(random.choice(rhythmLibrary))
#rhythm = "struct \""+rhythm+"\""
#
elif (rChoice == 1):
# GENERATE A SERIES OF 0's and 1's
@ -669,12 +782,13 @@ for i in percNames: @@ -669,12 +782,13 @@ for i in percNames:
# 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"):
#if (percName == "kick"):
# busyness = random.randrange(1,3)
if (percName == "sd"):
busyness = random.randrange(0,4)
elif (percName == "cp"):
busyness = random.randrange(0,4)
busyness = random.randrange(0,1)
elif (percName == "hh"):
busyness = random.randrange(3,9)
elif (percName == "ride"):
@ -686,6 +800,11 @@ for i in percNames: @@ -686,6 +800,11 @@ for i in percNames:
generateBinary(busyness)
rhythm = str(genOnOff(percLength,busyness,1))
# if this is a kick, use the genKicks() function instead
if (percName == "kick"):
rhythm = str(genKicks())
elif (rChoice == 2):
# GENERATE EUCLIDEAN RHYTHMS
@ -709,11 +828,17 @@ for i in percNames: @@ -709,11 +828,17 @@ for i in percNames:
markovLength = 16
rhythm = "[{"+str(markovBinary(markovLength)).rstrip()+"}%"+str(markovLength)+"]"
# if this is a kick, use the genKicks() function instead
if (percName == "kick"):
rhythm = str(genKicks())
else:
# print("LIBRARY")
rhythm = str(random.choice(rhythmLibrary))
#rhythm = "struct \""+rhythm+"\""
fullRhythm = str(rhythm) + " " + fullRhythm
# remove the trailing space
fullRhythm = fullRhythm.rstrip()

151
deleteme.tidal

@ -1,146 +1,7 @@ @@ -1,146 +1,7 @@
-- raw input: -2212340095055708872
-- hex seed: -0x1EB3CF98502642C8
-- decimal seed: -2212340095055708872
-- generated at 1633725162.39
-- Auto-Techno Generator v0.1.2
do
let fourToTheFloor = 0 -- set to 0 to hear it
-- extra stuff
extraCP = "[0]"
extraHH = "[0]"
-- control density per track
kickM = "[1111]"
hhM = "[1111]"
sdM = "[1111]"
ohhM = "[1111]"
rimM = "[1111]"
cpM = "[1111]"
tomM = "[1111]"
rideM = "[1111]"
cymbalM = "[1111]"
p "techno"
$ swingBy 0.12 8
-- fills
$ whenmod 8 7 (rev)
$ whenmod 16 14 (bite 2 "{0}%2")
$ whenmod 16 15 (scramble 4)
$ whenmod 16 14 (rev)
$ whenmod 16 15 (rev)
$ whenmod 16 15 (scramble 4)
$ stack [
-- four to the floor
mask "t"
$ degradeBy "<1 0 0 0 0 1 0 1 0 0 0 1 0 0 0 0>/8"
$ degradeBy fourToTheFloor $ struct "[t*4]" $ n "0" # midichan 0,
-------------- kick ---------------
mask kickM
$ degradeBy "<0 0 0 1 1 1 1 1>/8"
$ every 4 (rev)
$ (0.125 ~>)
$ struct "<[t(3,16)] [t*4]>"
$ n 10
# gain "{0.85 0.85 1 0.9 0.9 0.9 0.85 1 0.85}%16"
# midichan 0,
-------------- hh ---------------
mask hhM
$ degradeBy "<0 0 1 1 0 0 0 0>/8"
$ every 8 (scramble 8)
$ every 3 (stut 4 1 "0.125")
$ every 4 (rev)
$ struct "<t(3,8)>"
$ n 0
# gain "{1 1 0.9 1 1 0.9}%16"
# midichan 1,
-------------- sd ---------------
mask sdM
$ degradeBy "<0 0 0 0 0 1 1 0>/8"
$ every 8 ((0.125 ~>))
$ every 6 (stut 4 1 "0.125")
$ every 14 ((0.125 ~>))
$ (0.125 ~>)
$ struct "<[{0 1 0 1 0 0 0 1 1 1 0 1 0 1 0 0}%16] [tttt*2]>"
$ n 11
# gain "{0.85 0.9 1 1 0.85 0.85 0.9 0.9 0.85 0.85 1 0.9 0.85}%16"
# midichan 2,
-------------- ohh ---------------
mask ohhM
$ every 9 (degradeBy 0.34)
$ struct "<[tttt*2]>"
$ n 10
# gain "{1 1 0.9 1 0.85 1 0.85 0.85 0.9 1 0.9}%16"
# midichan 3,
-------------- rim ---------------
mask rimM
$ every 11 (rev)
$ every 6 (scramble 8)
$ struct "<[{100001}%16]>"
$ n 8
# gain "{1 0.9 1 0.9 1 1 1 0.85 1}%16"
# midichan 4,
-------------- cp ---------------
mask cpM
$ degradeBy "<1 1 1 1 0 1 1 0>/8"
$ struct "<[{0 0 1 0 1 0 1 1 1 0 1 1 0 0 0 1}%16]>"
$ n 5
# gain "{1 0.85 0.9 1 0.85 1 0.85 1 1}%16"
# midichan 5,
-------------- tom ---------------
mask tomM
$ degradeBy "<1 0 0 0 1 0 1 0>/8"
$ every 14 (degradeBy 0.34)
$ (0.1875 ~>)
$ struct "<t(3,8)>"
$ n 9
# gain "{1 1 1 0.85 1 0.85}%16"
# midichan 6,
-------------- ride ---------------
mask rideM
$ degradeBy "<1 0 0 0 0 1 0 0 0 0 1 1 0 1 0 0>/8"
$ struct "<[{0 0 0 1 1 1 1 0 0 1 1 1 1 1 0 1}%16]>"
$ n 4
# gain "{0.85 0.9 0.9 1 1 0.85 0.9 0.9 1 0.85 0.9}%16"
# midichan 7,
-------------- cymbal ---------------
mask cymbalM
$ degradeBy "<0 0 0 0 1 0 1 0>/8"
$ every 16 (rev)
$ every 13 (stut 4 1 "0.125")
$ every 7 (degradeBy 0.34)
$ (0.125 ~>)
$ struct "<[{1 1 0 0 1 1 0 1 1 0 1 1 1 1 1 1}%16] [t(9,16)]>"
$ n 6
# gain "{0.9 1 0.85 0.85 1 1 0.9 0.85 0.9 0.85}%16"
# midichan 8,
------------ bassline {{{ACID MODE}}}-------
degradeBy 0
$ struct "[{110110001}%16]"
$ n "[{17 2 22 8 8 6 10 19 2 }%16]"
# midichan 10 + n (-24),
--------- bassline filter cutoff ----
struct "[t*16]" $ ccn 20 # ccv "{67 79 33 90 74 77 5 68 59 71 66 26 72 76 60 46}%16" # midichan 10,
------------ pad -------
degradeBy 1
$ degradeBy "<1 0 1 1 1 0 0 0 1 1 1 0 0 0 0 1>/8"
$ struct "[{0110111101111110}%16]"
$ n "<[19,2,8,2]>/1"
# midichan 11 + n (0),
--------- MIDI CC's ---------------
stack [
struct "t*1" $ ccn 0 # ccv "{0}%1",
struct "[t*2]" $ ccn 1 # ccv "{14 33 65 27 47 12 86 88 120 33 59 86 101 90}%2",
struct "t*1" $ ccn 2 # ccv "{0}%1",
struct "t*1" $ ccn 3 # ccv "{0}%1",
struct "t*1" $ ccn 4 # ccv "{0}%1",
struct "[t*3]" $ ccn 5 # ccv "{11 56 47 2 58 1 111 112 119 27}%3",
struct "t*1" $ ccn 6 # ccv "{0}%1",
ccn 126 # ccv 45] # 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
d1 $ struct "<[t*4] <[1000 1000 1000 1001][1001 1000 1000 1010]>/4>" $ s "bd"

113
kick.py

@ -0,0 +1,113 @@ @@ -0,0 +1,113 @@
#!/usr/bin/env python3
import random
def genKicks():
"""
the idea:
generate kick drum patterns by weight
so it's most likely to play on 1-2-3-4
output: a series of 1's and 0's (struct)
and also a gain pattern
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
etc
arguments: bars = how many total bars to generate (1-4)
variation = the arrangement of the bars
"""
bars = 4
patternList = []
stepWeights = [100,
10,
15,
20,
######
85,
15,
25,
10,
######
85,
10,
10,
10,
######
80,
10,
10,
10]
fullKickPattern = ""
pat = ""
for bar in range(bars):
kickPattern = "["
currentStep = 0
# which bar are we generating?
if (bar == 0):
seq = "a"
elif (bar == 1):
seq = "b"
elif (bar == 2):
seq = "c"
elif (bar == 3):
seq = "d"
for i in stepWeights:
# every 4 steps, insert a space for easier reading
if (currentStep > 3):
currentStep = 0
kickPattern = str(kickPattern)+" "
# roll the dice to generate an event, or not
if (i >= random.randint(0,100)):
# event
kickPattern = str(kickPattern)+"1"
else:
# rest
kickPattern = str(kickPattern)+"0"
currentStep = currentStep + 1
kickPattern = kickPattern + "]"
patternList.append(str(kickPattern))
#return("kick pattern: "+str(kickPattern))
fullKickPattern = fullKickPattern + " " +kickPattern
#print("fullkickpat: "+fullKickPattern)
# ok at this point we have a list that contains (bars) items,
# where each item is a generated 16 steps of 1 or 0
# now we want to generate how to play them -
# just the first? just the first and second? or ABAC?
formChoices = ["A","AB","AB","AB","ABAC","AAAB","AAAB","ABCD"]
form = random.choice(formChoices)
#print("form: "+str(form))
# there is surely a better way to do this, but I don't know what it is
# so for now, here's a hack!
if (str(form) == "A"):
pat = str(patternList[0])
elif (str(form) == "AB"):
pat = str(patternList[0])+""+str(patternList[1])
elif (str(form) == "ABAC"):
pat = str(patternList[0])+""+str(patternList[1])+str(patternList[0])+""+str(patternList[2])
elif (str(form) == "AAAB"):
pat = str(patternList[0])+""+str(patternList[0])+str(patternList[0])+""+str(patternList[1])
elif (str(form) == "ABCD"):
pat = str(patternList[0])+""+str(patternList[1])+str(patternList[2])+""+str(patternList[3])
else:
pat = str(patternList[0])
fullKickPattern = "<"+str(pat)+">/"+str(bars)
return fullKickPattern
print(genKicks())
Loading…
Cancel
Save