Browse Source

created a 'markov chain' option for generating binary patterns - so events (1) are more likely to be followed by other events than silence (0). This makes things sound a little more organic. Also added MIDI CC messages to send to the DAW/Host to choose from 4 different bass patches and synth patches

master
spoonietunes 7 months ago
parent
commit
23e7151a86
  1. 134
      auto-techno.py
  2. 159
      deleteme.tidal

134
auto-techno.py

@ -1,11 +1,11 @@ @@ -1,11 +1,11 @@
#!/usr/bin/env python3
scriptName = "Auto-Techno Generator"
version = "0.1.1"
version = "0.1.2"
author = "Chris Beckstrom"
author_email = "chris@chrisbeckstrom.com"
# a deterministic techno generator for tidalcycles
# input an integer value as a seed
# and it spits out some techno ready to play
# and it spits out some techno ready to play in tidalcycles
#
# use it in emacs like this:
# it will generate a random seed
@ -15,6 +15,15 @@ author_email = "chris@chrisbeckstrom.com" @@ -15,6 +15,15 @@ author_email = "chris@chrisbeckstrom.com"
# (insert (shell-command-to-string (concat "/usr/bin/python ~/tidal-auto-techno/auto-techno.py " (number-to-string(random))))))
#
##################################################
################# SETUP #################
## import stuff
import sys
import random
import math
import re
import time
import decimal
from decimal import Decimal
########### SETTINGS #############################
# what are the lowest and highest bpm values you want?
lowestBpm = 92
@ -24,10 +33,11 @@ highestBpm = 135 @@ -24,10 +33,11 @@ highestBpm = 135
# swing
# see https://tidalcycles.org/docs/patternlib/tour/time/#swing
minSwing = 0
maxSwing = 0.2
maxSwing = 0.1
# force everything to happen within 1 bar
oneBar = 1
oneBar = random.choice([0,1])
# stack name
# this doesn't matter, can be any string
@ -116,15 +126,6 @@ midiCCChannel = 15 @@ -116,15 +126,6 @@ midiCCChannel = 15
midiCCs = [0,1,2,3,4,5,6]
################# SETUP #################
## import stuff
import sys
import random
import math
import re
import time
import decimal
from decimal import Decimal
############## PARSE ARGUMENT(S) ###############
@ -187,6 +188,50 @@ bpm = "setcps ("+str(random.randrange(lowestBpm, highestBpm, 1))+"/60/4)" @@ -187,6 +188,50 @@ bpm = "setcps ("+str(random.randrange(lowestBpm, highestBpm, 1))+"/60/4)"
####################### FUNCTIONS ###################
def markovBinary(count):
"""
argument: how many values to generate
output: a string like 0 1 1 0 0 0 1 1 1 1 0 0
trying to figure out how to use markov chains
to make more organic rhythms
where the on/off aren't evenly distributed,
if there is an event, it's more likely to be
followed by another event
"""
# choose a random starting value
startingValue = random.choice([0,1])
#print("start: "+str(startingValue))
# now that we have a starting value, the likelihood
# of getting that same value next should be higher
# than a different value
value = startingValue
fullPat = ""
for i in range(count):
#print("value: "+str(value))
# this is a bit of a hack, but it works!
# basically if the value is 0, there's more of a chance
# the next value will also be zero
# and if the value is 1, there's an extremely big change
# the next value will also be one
if (value == 0):
value = random.choice([0,0,0,1])
elif (value == 1):
value = random.choice([1,1,1,1,1,1,0,0])
fullPat = str(value)+" "+str(fullPat)
value = random.choice([0,1])
return fullPat
#print("fullpat: "+str(fullPat))
def swing(minSwing,maxSwing):
"""
Generate a swing value for the entire stack
@ -196,7 +241,7 @@ def swing(minSwing,maxSwing): @@ -196,7 +241,7 @@ def swing(minSwing,maxSwing):
#print("We will swing!!")
# choose the first value
#firstSwing = (decimal.Decimal(random.range())).quantize(Decimal('.001'))
firstSwing = str(decimal.Decimal(random.randrange(0, 20))/100)
firstSwing = str(decimal.Decimal(random.randrange(0, 12))/100)
secondSwing = 8 # if 8: swing 16th notes, if 4: swing 8th notes
return "swingBy "+str(firstSwing)+" "+str(secondSwing)
@ -333,6 +378,7 @@ def genNotes(melodicOneBar): @@ -333,6 +378,7 @@ def genNotes(melodicOneBar):
melodyLength = random.randrange(shortestMelodic,longestMelodic)
melody = ""
for i in range(melodyLength):
melody = str(random.randrange(0,random.choice(noteRange))) + " " + str(melody)
return ("n "+"\"[{"+melody+"}%"+str(random.choice(melodicDivisions))+"]\"")
@ -441,11 +487,11 @@ def sometimesBeQuiet(): @@ -441,11 +487,11 @@ def sometimesBeQuiet():
"""
#def genOnOff(limit,busyness,struct):
# decide whether to do this at all
if (random.randint(0,10) > 0):
if (random.randint(0,10) > 1):
# for now, 8 bar phrases
# (# gain "[0 1 0 0 1]/8")
# how many cycles to make?
quietCycles = random.choice([8])
quietCycles = random.choice([8,16])
# this generates a sequence like 011010110
quietBinary = genOnOff(quietCycles,4,0)
@ -476,7 +522,10 @@ print("do") @@ -476,7 +522,10 @@ print("do")
#print("")
# create "let" statements
print(indent+"let fourToTheFloor = 0")
print(indent+"let fourToTheFloor = 0 -- set to 0 to hear it")
print(indent+" -- extra stuff")
print(indent+" extraCP = \"[0]\"")
print(indent+" extraHH = \"[0]\"")
print(indent+" -- control density per track")
for i in percNames:
#print("let "+i+"M = \"["+genOnOff(4,5,0)+"]\"")
@ -524,7 +573,9 @@ print(indent+indent+"$ stack [") @@ -524,7 +573,9 @@ print(indent+indent+"$ stack [")
# this is an empty track to make dealing with commas easier
# just 4 to the floor in case you want it
print(indent+indent+"-- four to the floor")
print(indent+indent+"degradeBy fourToTheFloor $ struct \"[t*4]\" $ n \"0\" # midichan 0,")
print(indent+indent+"mask \"t\"")
sometimesBeQuiet()
print(indent+indent+"$ degradeBy fourToTheFloor $ struct \"[t*4]\" $ n \"0\" # midichan 0,")
# generate rhythm tracks
# set the starting midi channel
@ -549,6 +600,7 @@ for i in percNames: @@ -549,6 +600,7 @@ for i in percNames:
#if (i != "kick"):
# sometimesBeQuiet()
sometimesBeQuiet()
#### VARIATIONS #####
# insert some funStuff, maybe
if (random.randint(0,10) > 3):
@ -573,7 +625,12 @@ for i in percNames: @@ -573,7 +625,12 @@ for i in percNames:
# choose between random, type-specific (bd,hh,etc),
# rhythm library, or euclidean rhythms
rChoice = random.choice([0,1,1,1,2,3])
# 0 = prebaked hard-coded rhythms
# 1 = totally random 0's and 1's
# 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])
rhythm = "" # placeholder for the rhythm
if (rChoice == 0):
# if choice = 0, choose hardcoded rhythms
@ -646,6 +703,12 @@ for i in percNames: @@ -646,6 +703,12 @@ for i in percNames:
rhythm = str(euclid(random.choice(dividers),maxEuclidEvents))
#print(indent+indent+euclid(random.choice(dividers)))
#
elif (rChoice == 3):
# generate a pattern using a markov chain
# basically make it more likely for an ON value (1) to repeat
markovLength = 16
rhythm = "[{"+str(markovBinary(markovLength)).rstrip()+"}%"+str(markovLength)+"]"
else:
# print("LIBRARY")
rhythm = str(random.choice(rhythmLibrary))
@ -862,29 +925,30 @@ for i in midiCCs: @@ -862,29 +925,30 @@ for i in midiCCs:
ccFinalPattern = ccPatStart+ccPattern+ccPatEnd
#ccs = ccPatStart+ccFinalPattern+ccPatEnd+str(ccEndNumber)+"\" # midichan "+str(midiChannel)+","
ccs = ccFinalPattern+str(ccEndNumber)+"\","
print(indent+indent+indent+str(ccs))
midiChannel = midiChannel + 1
# end result like
# ccn 0 # ccv "{0 1 0 1 1 0 0 1 0}%N"
# make one more line so we don't have to worry about the trailing comma
# in the last ccs line
# make one more line so we don't have to worry about the trailing comma
# in the last ccs line
print(indent+indent+indent+"ccn 126 # ccv "+str(random.randint(0,126))+"] # midichan "+str(midiCCChannel)+",")
############ SEND SOME MIDI CC TO CHANGE SOUNDS ########
# a sort of way for the algorithm to choose presets
# the bass patch
# sends MIDI cc to a chooser on the bassline track in Bitwig
# chooses between 4 bass patches
bassPatch = str(random.choice([30,60,100,127]))
print(indent+indent+indent+"------- bass patch ----")
print(indent+indent+indent+"struct \"t\" $ ccn 101 # ccv "+bassPatch+" # midichan 10,")
# pads/chords patch
padsPatch = str(random.choice([30,60,100,127]))
print(indent+indent+indent+"------- pads patch ----")
print(indent+indent+indent+"struct \"t\" $ ccn 102 # ccv "+padsPatch+" # midichan 11,")
############### EXTRA STUFF #################
# sometimes this will generate a great groove
# that could be perfect with one or two extra things,
@ -895,8 +959,8 @@ print(indent+indent+indent+"ccn 126 # ccv "+str(random.randint(0,126))+"] # midi @@ -895,8 +959,8 @@ print(indent+indent+indent+"ccn 126 # ccv "+str(random.randint(0,126))+"] # midi
print(indent+indent+"-- EXTRA STUFF ---")
print(indent+indent+"stack [")
print(indent+indent+indent+"(# gain 0) $ struct \"[~ t ~ t]\" $ n \"0\",")
print(indent+indent+indent+"(# gain 0) $ struct \"[~t~t~t~t]\" $ n \"1\"] # midichan 12")
print(indent+indent+indent+"(# gain extraCP) $ struct \"[~ t ~ t]\" $ n \"0\",")
print(indent+indent+indent+"(# gain extraHH) $ struct \"[~t~t~t~t]\" $ n \"1\"] # midichan 12")
## put the finishing touches on the beautiful stack! :-) :-)
print(indent+indent+"] # sunvox")

159
deleteme.tidal

@ -1,11 +1,14 @@ @@ -1,11 +1,14 @@
-- raw input: -995834641349709608
-- hex seed: -0xDD1EA5484AD8F28
-- decimal seed: -995834641349709608
-- generated at 1633709399.6
-- Auto-Techno Generator v0.1.1
-- raw input: -2212340095055708872
-- hex seed: -0x1EB3CF98502642C8
-- decimal seed: -2212340095055708872
-- generated at 1633725162.39
-- Auto-Techno Generator v0.1.2
do
let fourToTheFloor = 0
let fourToTheFloor = 0 -- set to 0 to hear it
-- extra stuff
extraCP = "[0]"
extraHH = "[0]"
-- control density per track
kickM = "[1111]"
hhM = "[1111]"
@ -17,113 +20,127 @@ do @@ -17,113 +20,127 @@ do
rideM = "[1111]"
cymbalM = "[1111]"
p "techno"
$ swingBy 0.18 8
$ swingBy 0.12 8
-- fills
$ whenmod 64 63 (bite 4 "{4}%4")
$ whenmod 16 14 (scramble 4)
$ whenmod 32 31 (bite 4 "{0}%4")
$ whenmod 32 31 (scramble 8)
$ 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
degradeBy fourToTheFloor $ struct "[t*4]" $ n "0" # midichan 0,
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 "<[0101]>"
$ n 5
# gain "{0.9 0.85 0.85 0.85 0.9 0.85 0.9 0.85 0.85 0.9 0.85 0.9 1 0.85 0.9}%16"
$ 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
$ every 2 (stut 4 1 "0.125")
$ struct "<[t(5,16)] t(3,8)>"
$ n 2
# gain "{0.85 0.9 1 0.9 0.85 1 1 0.9 0.9 1}%16"
$ 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
$ every 2 ((0.1875 ~>))
$ degradeBy "<0 0 0 0 0 1 1 0>/8"
$ every 8 ((0.125 ~>))
$ every 6 (stut 4 1 "0.125")
$ struct "<[11*2]*4 t(3,8)>"
$ n 6
# gain "{1 1 0.9 0.85 0.85 0.85 0.85 0.85 0.9 0.9 1}%16"
$ 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
$ struct "<[t(3,16)] [t*4]>"
$ n 7
# gain "{0.85 0.9 0.85 0.85 1 0.9 0.85 0.9 1}%16"
$ 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 5 (stut 4 1 "0.125")
$ every 12 (degradeBy 0.49)
$ every 4 (stut 4 1 "0.125")
$ struct "<[{00001010}%16]>"
$ n 1
# gain "{1 0.85 0.9 0.85 0.9 0.9 0.9 0.85 1 0.9 0.85 0.85}%16"
$ 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
$ every 7 (rev)
$ every 5 (scramble 8)
$ struct "<[{000000000}%16]>"
$ n 3
# gain "{1 1 0.85 0.85 0.85 0.9 0.9}%16"
$ 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
$ every 12 (scramble 8)
$ every 10 (stut 4 1 "0.125")
$ every 8 (stut 4 1 "0.125")
$ (0.125 ~>)
$ struct "<[t(6,16)]>"
$ n 0
# gain "{0.9 1 0.9 1 0.9 1 1 0.9 0.9 0.85 0.9 1 0.85 1 0.9}%16"
$ 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
$ every 13 (rev)
$ every 7 (scramble 8)
$ every 15 (degradeBy 0.49)
$ struct "<[{000001000}%16] [tttt*2]>"
$ n 6
# gain "{0.85 0.85 0.85 0.85 0.9 1}%16"
$ 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
$ every 14 (stut 4 1 "0.125")
$ every 2 ((0.1875 ~>))
$ every 15 (scramble 8)
$ 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 "<[0101]>"
$ n 5
# gain "{1 1 0.9 1 0.85}%16"
$ 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 "[{1101111111101100}%16]"
$ n "[{3 4 9 0 8 10 9 2 9 4 11 8 10 9 1 19 }%16]"
$ 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 "{82 1 21 17 53 88 21 4 88 71 15 76 10 84 48 7}%16" # midichan 10,
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 "<0 1 0 1 1 0 0 1>/8"
$ n "<[9,19,11,19]>/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*5]" $ ccn 0 # ccv "{39 45 50 100 13 79 5 55 112 31 93}%5",
struct "[t*3]" $ ccn 1 # ccv "{127 16 42 96 59 86 95 5 40 86 98 119 5}%3",
struct "[t*2]" $ ccn 2 # ccv "{110 21 70}%2",
struct "[t*2]" $ ccn 3 # ccv "{113 41 105 26 46 3 104 100 59}%2",
struct "[t*2]" $ ccn 4 # ccv "{25 44 68 42}%2",
struct "t*1" $ ccn 5 # ccv "{0}%1",
struct "[t*4]" $ ccn 6 # ccv "{104 26 10 119 64 17}%4",
ccn 126 # ccv 84] # midichan 15,
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 0) $ struct "[~ t ~ t]" $ n "0",
(# gain 0) $ struct "[~t~t~t~t]" $ n "1"] # midichan 12
(# gain extraCP) $ struct "[~ t ~ t]" $ n "0",
(# gain extraHH) $ struct "[~t~t~t~t]" $ n "1"] # midichan 12
] # sunvox

Loading…
Cancel
Save