You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

191 lines
5.4 KiB

#!/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
#
##################################################
########### SETTINGS #############################
# what are the lowest and highest bpm values you want?
lowestBpm = 90
highestBpm = 135
# stack name
stackName = "techno"
# force everything to happen within 1 bar
oneBar = 1
# for euclidean rhythms, define the choices for the 2nd number
# eg "[t(3,NN)]"
dividers = [4,8,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
# 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
# how many
# how many percussive/rhythmic elements to generate?
percCount = 5
percMidiChanStart = 0
# how many melodic elements to generate?
melodyCount = 1
melodyMidiChanStart = 7
# perc note
# set a static note for percussion tracks
percNote = 0
# perc track names
percNames = ["kick", "hh", "sd", "cp", "cymbal", "?", "?", "?", "?"]
# for use generating sequences of 0's and 1's
binary = [0,0,0,1]
## 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 genOnOff(limit):
"generate a series of 0's and 1's"
zeroesOnes = ""
for i in range(limit):
zeroesOnes = zeroesOnes + str(random.choice(binary))
zeroesOnes = ", struct \"{"+zeroesOnes+"}%16\""
print(zeroesOnes)
def euclid(divider):
"generate a euclidean rhythm for tidalcycles" #struct "[t(3,8)]"
# 3,8 10,16 4,16
#secondEuclid = str(random.choice(dividers))
secondEuclid = divider
firstEuclid = str(random.randrange(2,int(secondEuclid)))
#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()):
# the first and the second euclid numbers will stay the same
# eg no <3 6 5>
#print("")
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,16))+" "+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))+"\"")
# actually assemble the stack!
print("p \""+stackName+"\" ")
# stack stuff like bite, scramble, etc. will go here
print("$ whenmod 8 7 (scramble 4)") #
# the top of the stack
print("$ stack [")
# this is an empty track to make dealing with commas easier
print(" n \"0\"")
print(",struct \"[t*4]\" $ n 0 # midichan 0")
# generate percussion tracks
percMidiChan = 1
for i in range(percCount):
# 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))
print("-- "+percNames[percMidiChan])
genOnOff(percLength)
print (" $ n "+str(percNote))
print(" # midichan "+str(percMidiChan))
percMidiChan = percMidiChan + 1
# generate melodic tracks
melodicMidiChan = melodyMidiChanStart
#melodyMidiChanStart = 7
for i in range(melodyCount):
print("-- ?")
#print(", ")
if (oneBar == 1):
genOnOff(16)
print("$")
genNotes(1)
else:
genOnOff(16)
print("$")
genNotes(1)
print("# midichan "+str(melodicMidiChan)+" + n (-36)")
melodicMidiChan = melodicMidiChan + 1
print("]")
print("# sunvox")