08-24-2021, 08:49 PM
Code:
import random
keySignature = 'Minor' # Options: 'Minor', 'Major', None
noteVarianceFactor = 30 # This will be divided by 10, but still don't set it too high
octave = 5 # Starting octave
note = 1 # Starting note. Keep under 7 even for undefined key
swing = False # Options: True, False
beatCount = 16 # Specifies how many beats you want the melody to be
# Value limit checks for particularly stupid users
while octave > 7: octave -= 1
while octave < 2: octave += 1
while noteVarianceFactor < 10: noteVarianceFactor += 5
while note < 1: note += 1
while note > 12: note -= 1
while beatCount < 1: beatCount += 1
if keySignature is None: noteDict = {1: 'C', 2: 'C#', 3: 'D', 4: 'D#', 5: 'E', 6: 'F', 7: 'F#', 8: 'G', 9: 'G#', 10: 'A', 11: 'A#', 12: 'B'}
elif keySignature == 'Major': noteDict = {1: 'C', 2: 'D', 3:'E', 4: 'F', 5: 'G', 6: 'A', 7: 'B'}
elif keySignature == 'Minor': noteDict = {1: 'C', 2: 'D', 3:'D#', 4: 'F', 5: 'G', 6: 'G#', 7: 'A#'}
else:
print("Invalid key signature entered. Values can be None, 'Major', or 'Minor'")
raise ValueError # The users can shift the output to whatever key they want afterward
octaves = {2,3,4,5,6,7} # wait, is this dictionary really necessary? w/e
midTendencyFactor = {2:10,3:7,4:4,5:0,6:-5,7:-10}
master = f'Online Sequencer:000000:'
def createNote(time, pitch, length, ID):
global master # Thank god my textbook taught me this even though this is apparently very dangerous
master += f'{time} {pitch} {length} {ID};'
def randomlyShiftPitch(n,o): # Arguments should be note, octave
n += round(random.randint(-noteVarianceFactor+midTendencyFactor[o],noteVarianceFactor-midTendencyFactor[o])/10)
while n > len(noteDict): # I really hate one letter variable names. I can't *****ing read them
if o == 7: n = 12 # but I already made this and it works
else: # so my hand has been forced
n -= len(noteDict)
o += 1 # at least it works. i was really worried it wouldn't
while n < 1:
if o == 2: n = 1
else:
n += len(noteDict)
o -= 1
return n, o # After running the function you should immediately assign these to note and octave
quarterBased = {1:(0, 2), 2:(1,3), 3:(0,1,2), 4:(0,2,3), 5:0, 6:2, 7:(0,3), 8:()}
thirdBased = {1:0, 2:2.666666, 3:(0, 2.666666), 4:(0, 1.333333, 2.666666)}
riff = {1:(0,1,2,3), 2:(0,1,2,2.666666,3.333333), 3:(0,0.666666,1.333333,2,2.666666,3.333333), 4:(0,0.666666,1.333333,2,3)}
riffChancemaker = 0
if not swing: riffing = True
else: riffing = False
beatCounter = 0
def generateBeat(): # This can probably be simplified, but it works for now
global beatCounter
global note
global octave
global riffChancemaker
if not swing: beatNotes = quarterBased[random.randint(1, len(quarterBased))]
else: beatNotes = thirdBased[random.randint(1, len(thirdBased))]
if type(beatNotes) == tuple:
for x in beatNotes:
note,octave = randomlyShiftPitch(note,octave)
if type(x) == float: noteLength = 0.666666
else: noteLength = 1
createNote(x+(beatCounter*4),f'{noteDict[note]}{octave}',noteLength,0)
else:
note,octave = randomlyShiftPitch(note,octave)
if type(beatNotes) == float: noteLength = 0.666666
else: noteLength = 1
createNote(beatNotes+(beatCounter*4),f'{noteDict[note]}{octave}',noteLength,0)
beatCounter += 1
if random.randint(0, 1): riffChancemaker += random.randint(0, 1)
if riffChancemaker == 4: generateRiff()
def generateRiff():
global note
global octave
global beatCounter
global riffChancemaker
if not riffing: pass
else:
while riffChancemaker > 0:
beatNotes = riff[random.randint(1, len(riff))]
for x in beatNotes:
note,octave = randomlyShiftPitch(note,octave)
if type(x) == float: noteLength = 0.666666
else: noteLength = 1
createNote(x+(beatCounter*4),f'{noteDict[note]}{octave}',noteLength,0)
riffChancemaker -= 2
beatCounter += 1
if riffChancemaker < 0: break
while beatCounter != beatCount: generateBeat()
master += ':'
print(master)
How to use:
1. Open online-python.com in your browser of choice (or, if you have a python editor installed, use that)
2. Paste this code into the editor
3. [Optional] Tweak the variables at the very top, following the annotations at each line
4. Run the code
5. If it infinitely loops, stop it and rerun
6. Copy the output and paste into OS.
if something goes seriously *****y, contact me over discord. otherwise, have fun with this script
pseudoname