Compare commits

...

2 Commits

  1. 200
      auto-techno.py
  2. 131
      deleteme.tidal
  3. 2
      test.tidal

200
auto-techno.py

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
#!/usr/bin/env python3
scriptName = "Auto-Techno Generator"
version = 0.1
version = "0.1.1"
author = "Chris Beckstrom"
author_email = "chris@chrisbeckstrom.com"
# a deterministic techno generator for tidalcycles
@ -20,6 +20,12 @@ author_email = "chris@chrisbeckstrom.com" @@ -20,6 +20,12 @@ author_email = "chris@chrisbeckstrom.com"
lowestBpm = 92
highestBpm = 135
# swing
# see https://tidalcycles.org/docs/patternlib/tour/time/#swing
minSwing = 0
maxSwing = 0.2
# force everything to happen within 1 bar
oneBar = 1
@ -29,27 +35,27 @@ stackName = "techno" @@ -29,27 +35,27 @@ stackName = "techno"
####### PERCUSSION ##############################
# some settings for rhythm generation
# for euclidean rhythms, define the choices for the 2nd number
# eg "[t(3,NN)]"
#dividers = [4,8,16]
dividers = [16]
# how many percussive/rhythmic elements to generate?
percCount = 5
percMidiChanStart = 0
# perc notes
# set some notes for percussion tracks
# these notes correspond to notes (C3, C#3, etc)
percNotes = [0,1,2,3,4,5,6,7]
percCount = 5 # this setting doesn't do anything right now, use "percNames" instead
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"]
# for use generating sequences of 0's and 1's
#
#
# perc notes
# set some notes for percussion tracks
# these notes correspond to notes (C3, C#3, etc)
# each percussion track will pick one of these notes
# and send note on/off messages to that note
percNotes = [0,1,2,3,4,5,6,7]
#
####### MELODY #################################
# NOTE about melodic sequences:
@ -78,14 +84,32 @@ melodyCount = 1 @@ -78,14 +84,32 @@ melodyCount = 1
melodyMidiChanStart = 10
############### PADS ###########################
# how many pad tracks to generate
padCount = 1
# how long should the pad pattern be?
# tip: add more of the same number to weight that choice
padBars = [1,1,1,2,4]
# at what speed should the pad chord change?
# every bar = 1, every 2 bars = 2, etc
padSpeed = [1,2,2,2,4]
# what MIDI channel should it start on?
# padMidiChanStart = melodyMidiChanStart + 1 will start it right after the last melody track
padMidiChanStart = melodyMidiChanStart + 1
################ MIDI #####################
# on what channel should we send MIDI CC messages?
midiCCChannel = 15
# list of MIDI CC's:
midiCCs = [0,1,2,3,4,5,6]
################# SETUP #################
## import stuff
import sys
import random
@ -96,7 +120,7 @@ import decimal @@ -96,7 +120,7 @@ import decimal
from decimal import Decimal
##################################################
############## PARSE ARGUMENT(S) ###############
# this is the 1st argument given via command line
# this is used to calculate everything
rawinput = sys.argv[1]
@ -105,7 +129,6 @@ rawinput = sys.argv[1] @@ -105,7 +129,6 @@ rawinput = sys.argv[1]
# convert to decimal
#input = int(hex,int(89))
################ SEED HEX #####################
# make sure the seed is a hex value
# why? it doesn't really matter technically
@ -132,7 +155,7 @@ seed = seed.replace("X","x") @@ -132,7 +155,7 @@ seed = seed.replace("X","x")
# here is the seed in decimal format (eg 3892423)
decimalSeed = int(seed,16)
### FRONTMATTER ###
#################### FRONTMATTER ###
# put some stuff at the top of the tidal code
print("-- raw input: " + str(rawinput))
print("-- hex seed: "+seed)
@ -148,6 +171,7 @@ random.seed(decimalSeed) @@ -148,6 +171,7 @@ random.seed(decimalSeed)
##################################################
indent = " "
# generate a bpm between lowest and highest
# looks like: cps = (BPM/60/4)
bpm = "setcps ("+str(random.randrange(lowestBpm, highestBpm, 1))+"/60/4)"
@ -156,6 +180,20 @@ bpm = "setcps ("+str(random.randrange(lowestBpm, highestBpm, 1))+"/60/4)" @@ -156,6 +180,20 @@ bpm = "setcps ("+str(random.randrange(lowestBpm, highestBpm, 1))+"/60/4)"
####################### FUNCTIONS ###################
def swing(minSwing,maxSwing):
"""
Generate a swing value for the entire stack
"""
# the goal is something like this:
# swingBy 0.2 8
#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)
secondSwing = 8 # if 8: swing 16th notes, if 4: swing 8th notes
return "swingBy "+str(firstSwing)+" "+str(secondSwing)
def generateBinary(busyness):
"""
busy-ness (sic)
@ -220,6 +258,8 @@ def genOnOff(limit,busyness,struct): @@ -220,6 +258,8 @@ def genOnOff(limit,busyness,struct):
def genVelocity(limit):
"""
Generate a series of decimals < 1 to control velocity
This adds a more organic feel to the rhythms, and makes
them about 20% funkier
"""
velocities = ""
for i in range(limit):
@ -441,6 +481,11 @@ for i in percNames: @@ -441,6 +481,11 @@ for i in percNames:
# actually assemble the stack!
print(indent+"p \""+stackName+"\" ")
# swing?
# roll the dice to see if there will be any swing at all
if (random.randint(0,10) > 7):
print(indent+indent+"$ "+str(swing(minSwing,maxSwing)))
# stack stuff like bite, scramble, etc. will go here
print(indent+indent+"-- fills")
# roll the dice up to N times
@ -494,8 +539,8 @@ for i in percNames: @@ -494,8 +539,8 @@ for i in percNames:
print(indent+indent+"mask "+i+"M")
# sometimes be quiet
if (i != "kick"):
sometimesBeQuiet()
#if (i != "kick"):
# sometimesBeQuiet()
#### VARIATIONS #####
# insert some funStuff, maybe
@ -680,13 +725,126 @@ for i in range(padCount): @@ -680,13 +725,126 @@ for i in range(padCount):
#print(str(padNotesList))
# make a chord
chord = "\"["+random.choice(padNotesList)+","+random.choice(padNotesList)+","+random.choice(padNotesList)+","+random.choice(padNotesList)+"]\""
padsStart = "\"<"
padsEnd = ">"
# generate a sequence of chords
pads = ""
for i in range(random.choice(padBars)):
pads = "["+ random.choice(padNotesList)+","+random.choice(padNotesList)+","+random.choice(padNotesList)+","+random.choice(padNotesList)+"]"+str(pads)
# build the track
print(indent+indent+"degradeBy 0 ")
print(indent+indent+"$ n "+chord)
print(indent+indent+"# midichan "+str(padMidiChan)+" + n (0)")
sometimesBeQuiet()
# roll the dice, choose between a long steady pad
# or more rhythmic hits
#if (random.choice([1,1]) == 1):
if (random.choice([0,1]) == 1):
print(indent+indent+"$ struct \""+genOnOff(16,(busyness),1)+"\"")
print(indent+indent+"$ n "+padsStart+pads+padsEnd+"/"+str(random.choice(padSpeed))+"\"")
print(indent+indent+"# midichan "+str(padMidiChan)+" + n (0),")
############## MIDI CCS #############
# the goal:
# do reverb/delay throws
# basically create step sequences that modulate CC values
# this assumes that midi cc 0-N are mapped to effects wherever
# the output of this script is being sent
# eg delay sends, reverb sends, etc
print(indent+indent+"--------- MIDI CC's ---------------")
print(indent+indent+"stack [")
# the kick is on midi channel 0
# don't do midi CC's for that track, start at 1
midiChannel = 1
for i in midiCCs:
# generate MIDI ccs rhythmically or over time
# how many steps?
ccLength = random.randint(2,16)
if (random.randint(0,1) == 0):
# don't do any CC value > 0
ccFinalPattern = "struct \"t*1\" $ ccn "+str(i)+" # ccv \"{0}%"
ccEndNumber = 1
else:
ccPattern = str(genOnOff(ccLength,5,0))
ccPattern = ""
for v in range(ccLength):
ccPattern = str(random.randint(0,127))+" "+str(ccPattern)
# how fast should these change?
ccSpeed = random.choice([0,0,0,0,0,0,0])
if (ccSpeed == 0):
# slow
ccEndNumber = random.choice([1,2,3,4,5])
else:
# fast
ccEndNumber = random.choice([8,16])
ccPattern = ccPattern.rstrip()
# right now ccPattern looks like this:
# 0 12 78 127 45 60
#ccPattern = list(ccPattern)
#
ccPatStruct = "struct \"[t*"+str(ccEndNumber)+"]\" $ "
# how likely is it that we'll actually send MIDI cc's for this value?
if (random.randint(0,10) > 4):
ccPatStart = ccPatStruct+"ccn "+str(i)+" # ccv \"{"
else:
#ccPatStart = "-- "+ccPatStruct+"ccn "+str(i)+" # ccv \"{"
ccPatStart = ""+ccPatStruct+"ccn "+str(i)+" # ccv \"{"
ccPatEnd = "}%"
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
print(indent+indent+indent+"ccn 126 # ccv "+str(random.randint(0,126))+"] # midichan "+str(midiCCChannel))
############### EXTRA STUFF #################
# sometimes this will generate a great groove
# that could be perfect with one or two extra things,
# like a handclap or extra kick
# This section creates an area to easily add that
# extra something
# hardcoded to midi channel 12
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")
## put the finishing touches on the beautiful stack
## put the finishing touches on the beautiful stack! :-) :-)
print(indent+indent+"] # sunvox")

131
deleteme.tidal

@ -1,8 +1,8 @@ @@ -1,8 +1,8 @@
-- raw input: -1654319963628270068
-- hex seed: -0x16F5533DF0E671F4
-- decimal seed: -1654319963628270068
-- generated at 1633644744.38
-- Auto-Techno Generator v0.1
-- raw input: -1432897721833003170
-- hex seed: -0x13E2ACE2DD5298A2
-- decimal seed: -1432897721833003170
-- generated at 1633706019.61
-- Auto-Techno Generator v0.1.1
do
let fourToTheFloor = 0
@ -18,99 +18,102 @@ do @@ -18,99 +18,102 @@ do
cymbalM = "[1111]"
p "techno"
-- fills
$ 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)
$ whenmod 8 7 (rev)
$ whenmod 64 63 (scramble 8)
$ whenmod 32 31 (bite 4 "{0}%4")
$ whenmod 64 63 (rev)
$ whenmod 8 7 (bite 4 "{4}%4")
$ stack [
-- four to the floor
degradeBy fourToTheFloor $ struct "[t*4]" $ n "0" # midichan 0,
-------------- kick ---------------
mask kickM
$ every 9 ((0.125 ~>))
$ every 9 ((0.125 ~>))
$ struct "<[{101000010}%16]>"
$ n 5
# gain "{0.85 1 0.85}%16"
$ every 8 (scramble 8)
$ every 16 (scramble 8)
$ struct "<[t*4]>"
$ n 7
# gain "{1 0.9 1}%16"
# midichan 0,
-------------- hh ---------------
mask hhM
$ degradeBy "<0 1 0 0 0 0 0 0>/8"
$ struct "<[t*4]>"
$ n 3
# gain "{0.9 0.85 0.9}%16"
$ (0.125 ~>)
$ struct "<[{111111011}%16]>"
$ n 1
# gain "{0.9 0.9}%16"
# midichan 1,
-------------- sd ---------------
mask sdM
$ degradeBy "<0 0 0 0 0 1 1 0>/8"
$ every 11 ((0.125 ~>))
$ every 12 ((0.125 ~>))
$ every 8 (scramble 8)
$ every 4 (scramble 8)
$ every 5 ((0.125 ~>))
$ (0.125 ~>)
$ struct "<[t(7,16)]>"
$ n 6
# gain "{0.85 0.9 1}%16"
$ n 5
# gain "{1 1 1 1 1 0.85 0.85 0.9}%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"
$ every 16 (stut 5 1 "0.0625")
$ struct "<[t(6,16)]>"
$ n 5
# gain "{1 0.9}%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 "<[{111010}%16]>"
$ n 1
# gain "{0.9 1 0.85}%16"
$ every 7 ((0.125 ~>))
$ every 2 (stut 5 1 "0.0625")
$ struct "<[t(3,16)] [{00000}%16]>"
$ n 7
# gain "{1 1 1 0.9 0.85 0.85 0.85 0.9 0.85 0.9 1 0.85}%16"
# midichan 4,
-------------- cp ---------------
mask cpM
$ 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"
$ struct "<[{01000}%16]>"
$ n 6
# gain "{0.85 0.9 0.9 0.85 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"
$ every 13 (scramble 8)
$ struct "<[t(11,16)] [{0001000}%16]>"
$ n 2
# gain "{0.9 0.85}%16"
# midichan 6,
-------------- ride ---------------
mask rideM
$ 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"
$ struct "<t(3,8)>"
$ n 2
# gain "{1 0.9 0.9 0.9 0.9 0.9 0.85 1 0.85 0.9}%16"
# midichan 7,
-------------- cymbal ---------------
mask cymbalM
$ 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"
$ struct "<[t(3,16)]>"
$ n 4
# gain "{0.9 0.9 0.9 1 0.9 0.9 0.9 0.9 0.85 0.85 0.85 1 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]"
$ struct "[{1010000011011111}%16]"
$ n "[{18 11 0 14 23 7 1 0 6 8 6 4 2 4 6 5 }%16]"
# midichan 10 + n (-24),
------------ pad -------
degradeBy 0
$ n "[1,4,3,3]"
# midichan 11 + n (0)
$ degradeBy "<0 1 0 0 0 1 1 0>/8"
$ struct "[{1110011100000010}%16]"
$ n "<[2,11,6,7]>/2"
# midichan 11 + n (0),
--------- MIDI CC's ---------------
stack [
struct "[t*5]" $ ccn 0 # ccv "{62 99 97 95 111 60 51 24}%5",
struct "t*1" $ ccn 1 # ccv "{0}%1",
struct "[t*3]" $ ccn 2 # ccv "{79 124 39 94 52 57 17 40 35 8 41 14 3 30 53 54}%3",
struct "t*1" $ ccn 3 # ccv "{0}%1",
struct "t*1" $ ccn 4 # ccv "{0}%1",
struct "t*1" $ ccn 5 # ccv "{0}%1",
struct "[t*2]" $ ccn 6 # ccv "{4 33 118 44 10 94 49 99 110 92}%2",
ccn 126 # ccv 71] # midichan 15,
-- extra stuff
stack [
struct "[~ t ~ t]" $ n "0" # midichan 12
]
] # sunvox

2
test.tidal

@ -20,6 +20,8 @@ some seeds I've liked: @@ -20,6 +20,8 @@ some seeds I've liked:
2195224328517994763 -- funnnnkkky
0x508DFAD3954D1C9 -- cooool
seed: -2138151558308434562
82408580741001929 -- cool bassline
1432897721833003170 -- very chill, cool, rolling
setcps = (18/60/4)

Loading…
Cancel
Save