python generating random midi

Published: 29 May 2023
on channel: Claire Sawyer
1,145
38

ChatGPT is seriously amazing. It assisted me in a random idea of "can i make white midi files on the fly and play them?"... Then then scope creepy inevitably jumped in and I made it choose from musical scales and tried to add a percussion track, but i don't really know much about midi.


def get_scales():
return {
'major': [60,62,64,65,67,69,71,72],
'natural_minor': [60,62,63,65,67,68,70,72],
'harmonic_minor': [60,62,63,65,67,68,71,72],
'melodic_minor': [60,62,63,65,67,69,71,72],
'dorian': [60,62,63,65,67,69,70,72],
'mixolydian': [60,62,64,65,67,69,70,72],
'lydian': [60,62,64,66,67,69,71,72],
'phrygian': [60,61,63,65,67,68,70,72],
'locrian': [60,61,63,64,66,68,70,72],
'pentatonic_major': [60,62,64,67,69,72],
'pentatonic_minor': [60,63,65,67,70,72],
'blues': [60,63,65,66,67,70,72],
'chromatic': [60,61,62,63,64,65,66,67,68,69,70,71,72]
}



def create_random_midi(duration_in_seconds,filename,tempo=500000):
mid = MidiFile()
track = MidiTrack()
mid.tracks.append(track)
track.append(mido.MetaMessage('set_tempo',tempo=tempo))
current_time = 0
beats_per_minute = mido.tempo2bpm(tempo)
seconds_per_beat = 60.0 / beats_per_minute
scales = get_scales()
scale_name = random.choice(list(scales.keys()))
scale = scales[scale_name]
root_note = random.randint(60,72)
scale = [(note - 60) + root_note for note in scale]
if random.choice([True,True,True,False]):
range_increased = True
lower_scale = [note - 12 for note in scale]
higher_scale = [note + 12 for note in scale]
scale = lower_scale + scale + higher_scale
else:
range_increased = False

num_channels = random.randint(2,18)

note_duration_options = [0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.15,0.15,0.15,0.15,0.15,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.5,0.5,0.5,0.5,1.0,1.0,1.5,1.5,2.0,2.5]
silence_after_note_options = [0.05,0.05,0.10,0.10,0.15,0.20,0.20,0.25,0.25,0.40,0.50,0.5,0.75]

for channel in range(16):
track = MidiTrack()
if channel != 1: instrument = random.randint(0,127)
track.append(Message('program_change',program=instrument,time=0,channel=channel))
mid.tracks.append(track)
for channel in range(16):
channel_index = channel
while current_time < duration_in_seconds:
num_notes = random.choice([1,2,2,3,3,3,3,4,4])
notes = random.sample(scale,num_notes)
velocity = random.randint(40,120)
note_duration,silence_after_note = random.choice(note_duration_options),random.choice(silence_after_note_options)

for note in notes:
message = Message('note_on',note=note,velocity=velocity,time=0,channel=channel)
mid.tracks[channel_index].append(message)

for note in notes:
message = Message('note_off',note=note,velocity=velocity,time=int(seconds_per_beat * mido.second2tick(note_duration,mid.ticks_per_beat,tempo)),channel=channel)
mid.tracks[channel_index].append(message)
current_time += note_duration

mid.tracks[channel_index].append(Message('note_off',note=0,velocity=0,time=int(seconds_per_beat * mido.second2tick(silence_after_note,mid.ticks_per_beat,tempo))))
current_time += silence_after_note

mid = add_random_drums(mid,duration_in_seconds,tempo)
mid.save(filename)


def add_random_drums(midi_file,duration_in_seconds,tempo=500000):

if len(midi_file.tracks) > 9:
track = midi_file.tracks[9]
track.clear()
else:
track = MidiTrack()
midi_file.tracks.append(track)

beats_per_minute = mido.tempo2bpm(tempo)
seconds_per_beat = 60.0 / beats_per_minute

drum_notes = [36,36,36,38,42,42,42,42,46,46,46,46,]
drum_pattern_duration_options = [0.25,0.5,1.0]

current_time = 0
while current_time < duration_in_seconds:
drum_note = random.choice(drum_notes)
velocity = random.randint(40,120)
pattern_duration = random.choice(drum_pattern_duration_options)
message_on = Message('note_on',note=drum_note,velocity=velocity,time=0,channel=10)
track.append(message_on)
message_off = Message('note_off',note=drum_note,velocity=velocity,time=int(seconds_per_beat * mido.second2tick(pattern_duration,midi_file.ticks_per_beat,tempo)),channel=10)
track.append(message_off)
current_time += pattern_duration
return midi_file

def main():
if len(sys.argv) < 2: raise Exception("Usage: python script.py <output_filename> [<song_length_in_seconds>]")
filename = sys.argv[1]

length = ""
if len(sys.argv) > 2: length = int(sys.argv[2])
create_random_midi(length,filename)


On this page of the site you can watch the video online python generating random midi with a duration of hours minute second in good quality, which was uploaded by the user Claire Sawyer 29 May 2023, share the link with friends and acquaintances, this video has already been watched 1,145 times on youtube and it was liked by 38 viewers. Enjoy your viewing!