4 changed files with 127 additions and 425 deletions
@ -1,382 +0,0 @@
@@ -1,382 +0,0 @@
|
||||
#!/usr/bin/env python3 |
||||
# a deterministic techno generator for tidalcycles |
||||
# input an integer value as a seed |
||||
# and it spits out some techno ready to play |
||||
# |
||||
# use it in emacs like this: |
||||
# it will generate a random seed |
||||
# |
||||
# (defun autotechno() |
||||
# (interactive) |
||||
# (insert (shell-command-to-string (concat "/usr/bin/python ~/tidal-auto-techno/auto-techno.py " (number-to-string(random)))))) |
||||
# |
||||
################################################## |
||||
########### SETTINGS ############################# |
||||
# what are the lowest and highest bpm values you want? |
||||
lowestBpm = 92 |
||||
highestBpm = 135 |
||||
|
||||
# force everything to happen within 1 bar |
||||
oneBar = 1 |
||||
|
||||
# stack name |
||||
# this doesn't matter, can be any string |
||||
stackName = "techno" |
||||
|
||||
|
||||
####### PERCUSSION ############################## |
||||
# for euclidean rhythms, define the choices for the 2nd number |
||||
# eg "[t(3,NN)]" |
||||
dividers = [4,8,16] |
||||
# how many percussive/rhythmic elements to generate? |
||||
percCount = 5 |
||||
percMidiChanStart = 0 |
||||
|
||||
|
||||
|
||||
# perc note |
||||
# set a static note for percussion tracks |
||||
percNote = 0 |
||||
# perc track names |
||||
percNames = ["kick", "hh", "sd", "cp", "?", "?", "bassline", "?", "?"] |
||||
# for use generating sequences of 0's and 1's |
||||
# |
||||
# |
||||
# |
||||
####### MELODY ################################# |
||||
# NOTE about melodic sequences: |
||||
# as of October 04, 2021 all melodic sequences are all notes |
||||
# ie no rests. the rhythm/rests is determined by a "struct" value |
||||
# just like with percussion |
||||
|
||||
# for melodic sequences, define the choices for range of the notes |
||||
# eg 12 is one octave, 24 is two, etc |
||||
noteRange = [12,24,36] |
||||
# define the shortest and longest sequence you want |
||||
# eg if shortest is 7, there will be no melodic sequences shorter than 7 |
||||
shortestMelodic = 4 |
||||
longestMelodic = 16 |
||||
|
||||
# for melodic lines, what divisions do you want to choose from? |
||||
# eg 4 = quarter notes, 8 = eighth notes |
||||
# tip: adding more of the same number will weight the randomness toward that |
||||
melodicDivisions = [8,16,16,16] |
||||
|
||||
# keep melodies within 1 bar |
||||
#melodicOneBar = 1 |
||||
# how many |
||||
# how many melodic elements to generate? |
||||
melodyCount = 1 |
||||
melodyMidiChanStart = 7 |
||||
|
||||
|
||||
## import stuff |
||||
import sys |
||||
import random |
||||
import math |
||||
|
||||
|
||||
################################################## |
||||
# this is the 1st argument given via command line |
||||
# this is used to calculate everything |
||||
# seeds should be 6 digits or longer |
||||
input = sys.argv[1] |
||||
|
||||
print("-- seed: " + str(input)) |
||||
|
||||
|
||||
########### THIS CHANGES EVERYTHING! ############# |
||||
# set the random seed based on user input |
||||
random.seed(input) |
||||
################################################## |
||||
|
||||
# generate a bpm between lowest and highest |
||||
# looks like: cps = (BPM/60/4) |
||||
bpm = "cps = ("+str(random.randrange(lowestBpm, highestBpm, 1))+"/60/4)" |
||||
print(bpm+"\n") |
||||
|
||||
|
||||
|
||||
def generateBinary(busyness): |
||||
""" |
||||
busy-ness (sic) |
||||
Create a list of 0's and 1's from which patterns can be |
||||
created. The higher the busyness, the more 1's in the list, |
||||
which in turn creates more events in the generated sequence |
||||
busyness range from 0 to 9, where 9 is most busy, |
||||
and 0 is no activity at all |
||||
""" |
||||
if (busyness == 0): |
||||
binary = [0] |
||||
elif (busyness == 1): |
||||
binary = [0,0,0,0,0,0,0,0,1] |
||||
elif (busyness == 2): |
||||
binary = [0,0,0,0,0,0,0,1,1] |
||||
elif (busyness == 3): |
||||
binary = [0,0,0,0,0,0,1,1,1] |
||||
elif (busyness == 4): |
||||
binary = [0,0,0,0,0,1,1,1,1] |
||||
elif (busyness == 5): |
||||
binary = [0,0,0,0,1,1,1,1,1] |
||||
elif (busyness == 6): |
||||
binary = [0,0,0,1,1,1,1,1,1] |
||||
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] |
||||
elif (busyness == 9): |
||||
binary = [0,0,1,1,1,1,1,1,1,1,1] |
||||
return binary |
||||
|
||||
#binary = [0,0,0,1] |
||||
|
||||
def genOnOff(limit,busyness): |
||||
"generate a series of 0's and 1's" |
||||
zeroesOnes = "" |
||||
|
||||
# here we can change the list of 0's and 1's |
||||
# the more 1's, the busier the rhythm will be |
||||
# and we want to set this per-track |
||||
# so... |
||||
# |
||||
for i in range(limit): |
||||
zeroesOnes = zeroesOnes + str(random.choice(generateBinary(busyness))) |
||||
zeroesOnes = "$ struct \"{"+zeroesOnes+"}%16\"" |
||||
print(zeroesOnes) |
||||
|
||||
def euclid(divider): |
||||
"generate a euclidean rhythm for tidalcycles" |
||||
# like struct "[t(3,8)]" |
||||
# 3,8 10,16 4,16 |
||||
#secondEuclid = str(random.choice(dividers)) |
||||
secondEuclid = divider |
||||
firstEuclid = str(random.randrange(2,divider)) |
||||
#print("firstEuclid:"+firstEuclid) |
||||
#print("secondEuclid:"+str(secondEuclid)) |
||||
|
||||
euclidSeed = random.random() |
||||
# decide whether there are going to be changes in the euclid seq |
||||
#if (random.random() < random.random()): |
||||
if (1 > 0): |
||||
# the first and the second euclid numbers will stay the same |
||||
# eg no <3 6 5> |
||||
firstEuclid = firstEuclid |
||||
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))+">" |
||||
# decide whether the second number will seq |
||||
if (random.random() > random.random()): |
||||
# we will do like [t(??,<16,8>)] |
||||
secondEuclid = "<"+str(random.choice(dividers))+" "+str(random.choice(dividers))+">" |
||||
# [t(<3 8>,16)] |
||||
|
||||
print("$ struct \"[t("+str(firstEuclid)+","+str(secondEuclid)+")]\"") |
||||
|
||||
def genNotes(melodicOneBar): |
||||
""" |
||||
Generate a series of numbers for use as midi notes |
||||
accepts 1 or 0, where 1 limits the melody to 16 16th notes |
||||
and 0 sets the melody to somewhere between the values |
||||
of shortestMelodic and longestMelodic |
||||
""" |
||||
# between let's say 4 notes and 16 notes |
||||
if (melodicOneBar == 1): |
||||
melodyLength = 16 |
||||
else: |
||||
melodyLength = random.randrange(shortestMelodic,longestMelodic) |
||||
|
||||
melody = "" |
||||
for i in range(melodyLength): |
||||
melody = str(random.randrange(0,random.choice(noteRange))) + " " + str(melody) |
||||
print("n "+"\"{"+melody+"}%"+str(random.choice(melodicDivisions))+"\"") |
||||
|
||||
|
||||
def every(): |
||||
bars = random.randint(2,16) |
||||
print("$ every "+str(bars)+" ") |
||||
|
||||
def whenmod(): |
||||
limit = 16 |
||||
lower = random.randint(4,limit) |
||||
print("$ whenmod "+str(limit)+" "+str(lower)+" ") |
||||
|
||||
def bite(): |
||||
""" |
||||
Generate something like |
||||
bite 16 "{2*4 1*2 10*4 8*8}%16 |
||||
""" |
||||
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,16)) |
||||
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 , |
||||
print("bite "+number+ " \"{"+bit+"}%"+number+"\"") |
||||
|
||||
|
||||
def funStuff(): |
||||
""" |
||||
Generate variations like `whenmod 8 7 (scramble 4)` |
||||
""" |
||||
# here are some conditions: |
||||
# https://tidalcycles.org/docs/reference/conditions |
||||
# every N - whenmod N N - sometimesBy N - someCyclesBy N |
||||
|
||||
|
||||
|
||||
# actually assemble the stack! |
||||
print("p \""+stackName+"\" ") |
||||
|
||||
# stack stuff like bite, scramble, etc. will go here |
||||
|
||||
print("$ whenmod 8 7 (scramble 4)") # |
||||
|
||||
# how many "fun" things to add? |
||||
def funThings(): |
||||
funThings = random.randint(0,4) |
||||
for i in range(funThings): |
||||
#print(str(every) + "$ " + str(output)) |
||||
every() |
||||
print(" (") |
||||
bite() |
||||
print(") ") |
||||
|
||||
# uncomment this for some wildness |
||||
#funThings() |
||||
|
||||
# the top of the stack |
||||
print("$ stack [") |
||||
|
||||
# this is an empty track to make dealing with commas easier |
||||
# just 4 to the floor in case you want it |
||||
print("-- four to the floor") |
||||
print(" (#gain 1) $ struct \"[t*4]\" $ n \"0\" # midichan 0,") |
||||
|
||||
#print(",struct \"[t*4]\" $ n 0 # midichan 0") |
||||
|
||||
# generate rhythm tracks |
||||
percMidiChan = 0 |
||||
for i in range(percCount): |
||||
|
||||
print("-- "+percNames[percMidiChan]+" -----------------") |
||||
# this is here so there is the same thing at the start of |
||||
# each new track (so we know "whenmod" for instance always |
||||
# starts with $ and not ,) |
||||
print("degradeBy 0 ") |
||||
# insert some funStuff, maybe |
||||
if (random.choice([0,1]) > 0): |
||||
funThings() |
||||
|
||||
# choose between regular or euclidean rhythms |
||||
if (random.choice([0,1]) == 0): |
||||
# GENERATE A SERIES OF 0's and 1's |
||||
# choose how long the rhythm will be |
||||
if (oneBar == 1): |
||||
percLength = 16 |
||||
else: |
||||
percLength = int(random.randrange(4,16)) |
||||
#percSequence = genOnOff(percLength) |
||||
#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) |
||||
generateBinary(busyness) |
||||
genOnOff(percLength,busyness) |
||||
else: |
||||
# GENERATE EUCLIDEAN RHYTHMS |
||||
euclid(random.choice(dividers)) |
||||
|
||||
print (" $ n "+str(percNote)+" # midichan "+str(percMidiChan)+",") |
||||
percMidiChan = percMidiChan + 1 |
||||
|
||||
|
||||
|
||||
# generate melodic tracks |
||||
melodicMidiChan = melodyMidiChanStart |
||||
#melodyMidiChanStart = 7 |
||||
for i in range(melodyCount): |
||||
print("-----------------------") |
||||
print("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): |
||||
genOnOff(16,(busyness)) |
||||
print("$") |
||||
genNotes(1) |
||||
else: |
||||
genOnOff(32,(busyness)) |
||||
print("$") |
||||
genNotes(1) |
||||
print("# midichan "+str(melodicMidiChan)+" + n (-36)") |
||||
melodicMidiChan = melodicMidiChan + 1 |
||||
|
||||
print("] # sunvox") |
||||
some seeds I've liked: |
||||
1493546251137461290 |
||||
1781197463452869364 |
||||
14959707246264745 |
||||
1411204103099713935 |
||||
1157315305561367902 |
||||
2275918688827233254 |
||||
2209526836267835322 -- electro-ish |
||||
644793890351458335 |
||||
803051260356546356 |
||||
1061676950143263647 |
||||
|
||||
-- seed: -1061676950143263647 |
||||
cps = (114/60/4) |
||||
|
||||
p "techno" |
||||
$ whenmod 8 7 (scramble 4) |
||||
$ stack [ |
||||
-- four to the floor |
||||
(#gain 1) $ struct "[t*4]" $ n "0" # midichan 0, |
||||
-- kick ----------------- |
||||
degradeBy 0 |
||||
$ every 3 |
||||
( |
||||
bite 8 "{6*4 0*2 5*2 5*2 }%8" |
||||
) |
||||
$ struct "[t(2,4)]" |
||||
$ n 0 # midichan 0, |
||||
-- hh ----------------- |
||||
degradeBy 0 |
||||
$ struct "{1001110110100101}%16" |
||||
$ n 0 # midichan 1, |
||||
-- sd ----------------- |
||||
degradeBy 0 |
||||
$ struct "[t(5,8)]" |
||||
$ n 0 # midichan 2, |
||||
-- cp ----------------- |
||||
degradeBy 0 |
||||
$ struct "[t(7,8)]" |
||||
$ n 0 # midichan 3, |
||||
-- ? ----------------- |
||||
degradeBy 0 |
||||
$ every 3 |
||||
( |
||||
bite 4 "{0*2 0*2 0*1 1*4 0*1 0*4 0*1 2*4 0*1 3*1 1*4 0*4 4*1 }%4" |
||||
) |
||||
$ every 4 |
||||
( |
||||
bite 4 "{3*2 3*4 2*4 3*1 0*4 3*1 3*1 4*1 4*2 3*4 0*1 1*4 1*4 }%4" |
||||
) |
||||
$ struct "{1111000101111000}%16" |
||||
$ n 0 # midichan 4, |
||||
----------------------- |
||||
degradeBy 0 |
||||
$ struct "{1101111111110111}%16" |
||||
$ |
||||
n "{22 8 22 10 2 9 11 12 8 2 0 0 10 17 3 4 }%16" |
||||
# midichan 7 + n (-36) |
||||
] # sunvox |
Loading…
Reference in new issue