Skip to content

Instantly share code, notes, and snippets.

@badjano
Last active February 27, 2019 19:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save badjano/3139071c3603cb39538c28bfbf81cf93 to your computer and use it in GitHub Desktop.
Save badjano/3139071c3603cb39538c28bfbf81cf93 to your computer and use it in GitHub Desktop.
Music Generator
from math import floor
import random
from midiutil.MidiFile import MIDIFile
MyMIDI = MIDIFile(1)
track = 0
time = 0
tempo = 130
MyMIDI.addTrackName(track, time, "Sample Track")
MyMIDI.addTempo(track, time, tempo)
scales = [{"name": "Major", "intervals": [2, 2, 1, 2, 2, 2, 1], "indices": [0, 2, 4, 5, 7, 9, 11]},
{"name": "Dorian", "intervals": [2, 1, 2, 2, 2, 1, 2], "indices": [0, 2, 3, 5, 7, 9, 10]},
{"name": "Harmonic Minor", "intervals": [2, 1, 2, 2, 2, 1, 2], "indices": [0, 2, 3, 5, 7, 9, 10]},
{"name": "Melodic Minor", "intervals": [2, 1, 2, 2, 2, 2], "indices": [0, 2, 3, 5, 7, 9, 11]},
{"name": "Aeolian", "intervals": [2, 1, 2, 2, 1, 2, 2], "indices": [0, 2, 3, 5, 7, 8, 10]},
{"name": "Algerian", "intervals": [2, 1, 2, 1, 1, 1, 3, 1], "indices": [0, 2, 3, 5, 6, 7, 8, 11]},
{"name": "Arabian (a)", "intervals": [2, 1, 2, 1, 2, 1, 2, 1], "indices": [0, 2, 3, 5, 6, 8, 9, 11]},
{"name": "Arabian (b)", "intervals": [2, 2, 1, 1, 2, 2, 2], "indices": [0, 2, 4, 5, 6, 8, 10]},
{"name": "Theta, Asavari", "intervals": [2, 1, 2, 2, 1, 2, 2], "indices": [0, 2, 3, 5, 7, 8, 10]},
{"name": "Balinese", "intervals": [1, 2, 4, 1, 4], "indices": [0, 1, 3, 7, 8]},
{"name": "Theta, Bilaval", "intervals": [2, 2, 1, 2, 2, 2, 1], "indices": [0, 2, 4, 5, 7, 9, 11]},
{"name": "Theta, Bhairav", "intervals": [1, 3, 1, 2, 1, 3, 1], "indices": [0, 1, 4, 5, 7, 8, 11]},
{"name": "Theta, Bhairavi", "intervals": [1, 2, 2, 2, 1, 2, 2], "indices": [0, 1, 3, 5, 7, 8, 10]},
{"name": "Byzantine", "intervals": [1, 3, 1, 2, 1, 3, 1], "indices": [0, 1, 4, 5, 7, 8, 11]},
{"name": "Chinese", "intervals": [4, 2, 1, 4, 1], "indices": [0, 4, 6, 7, 11]},
{"name": "Chinese Mongolian", "intervals": [2, 2, 3, 2, 3], "indices": [0, 2, 4, 7, 9]},
{"name": "Diminished", "intervals": [2, 1, 2, 1, 2, 1, 2, 1], "indices": [0, 2, 3, 5, 6, 8, 9, 11]},
{"name": "Egyptian", "intervals": [2, 3, 2, 3, 2], "indices": [0, 2, 5, 7, 10]},
{"name": "Ethiopian (A raray)", "intervals": [2, 2, 1, 2, 2, 2, 1], "indices": [0, 2, 4, 5, 7, 9, 11]},
{"name": "Ethiopian (Geez & Ezel)", "intervals": [2, 1, 2, 2, 1, 2, 2], "indices": [0, 2, 3, 5, 7, 8, 10]},
{"name": "Hawiian", "intervals": [2, 1, 2, 2, 2, 2, 1], "indices": [0, 2, 3, 5, 7, 9, 11]},
{"name": "Hindustan", "intervals": [2, 2, 1, 2, 1, 2, 2], "indices": [0, 2, 4, 5, 7, 8, 10]},
{"name": "Hungarian Major", "intervals": [3, 1, 2, 1, 2, 1, 2], "indices": [0, 3, 4, 6, 7, 9, 10]},
{"name": "Hungarian Gypsy", "intervals": [2, 1, 3, 1, 1, 3, 1], "indices": [0, 2, 3, 6, 7, 8, 11]},
{"name": "Hungarian Gypsy Persian", "intervals": [1, 3, 1, 2, 1, 3, 1], "indices": [0, 1, 4, 5, 7, 8, 11]},
{"name": "Hungarian Minor", "intervals": [2, 1, 3, 1, 1, 3, 1], "indices": [0, 2, 3, 6, 7, 8, 11]},
{"name": "Ionian", "intervals": [2, 2, 1, 2, 2, 2, 1], "indices": [0, 2, 4, 5, 7, 9, 11]},
{"name": "Japanese (A)", "intervals": [1, 4, 2, 1, 4], "indices": [0, 1, 5, 7, 8]},
{"name": "Japanese (B)", "intervals": [2, 3, 2, 1, 4], "indices": [0, 2, 5, 7, 8]},
{"name": "Japanese (Ichikosucho)", "intervals": [2, 2, 1, 1, 1, 2, 2, 1],
"indices": [0, 2, 4, 5, 6, 7, 9, 11]},
{"name": "Japanese (Taishikicho)", "intervals": [2, 2, 1, 1, 1, 2, 1, 1, 1],
"indices": [0, 2, 4, 5, 6, 7, 9, 10, 11]},
{"name": "Javaneese", "intervals": [1, 2, 2, 2, 2, 1, 2], "indices": [0, 1, 3, 5, 7, 9, 10]},
{"name": "Jewish (Adonai Malakh)", "intervals": [1, 1, 1, 2, 2, 2, 1, 2],
"indices": [0, 1, 2, 3, 5, 7, 9, 10]},
{"name": "Jewish (Ahaba Rabba)", "intervals": [1, 3, 1, 2, 1, 2, 2], "indices": [0, 1, 4, 5, 7, 8, 10]},
{"name": "Jewish (Magen Abot)", "intervals": [1, 1, 1, 1, 2, 2, 2, 2], "indices": [0, 1, 2, 3, 4, 6, 8, 10]},
{"name": "Theta, Kafi", "intervals": [2, 1, 2, 2, 2, 1, 2], "indices": [0, 2, 3, 5, 7, 9, 10]},
{"name": "Theta, Kalyan", "intervals": [2, 2, 2, 1, 2, 2, 1], "indices": [0, 2, 4, 6, 7, 9, 11]},
{"name": "Theta, Khamaj", "intervals": [2, 2, 1, 2, 2, 1, 2], "indices": [0, 2, 4, 5, 7, 9, 10]},
{"name": "Locrian", "intervals": [1, 2, 2, 1, 2, 2, 2], "indices": [0, 1, 3, 5, 6, 8, 10]},
{"name": "Lydian", "intervals": [2, 2, 2, 1, 2, 2, 1], "indices": [0, 2, 4, 6, 7, 9, 11]},
{"name": "Theta, Marva", "intervals": [1, 3, 2, 1, 2, 2, 1], "indices": [0, 1, 4, 6, 7, 9, 11]},
{"name": "Mela Bhavapriya (44)", "intervals": [1, 1, 3, 2, 1, 1, 3], "indices": [0, 1, 2, 5, 7, 8, 9]},
{"name": "Mela Chakravakam (16)", "intervals": [1, 3, 1, 2, 2, 1, 2], "indices": [0, 1, 4, 5, 7, 9, 10]},
{"name": "Mela Chalanata (36)", "intervals": [3, 1, 1, 2, 3, 1, 1], "indices": [0, 3, 4, 5, 7, 10, 11]},
{"name": "Mela Charukesi (26)", "intervals": [2, 2, 1, 2, 1, 2, 2], "indices": [0, 2, 4, 5, 7, 8, 10]},
{"name": "Mela Chitrambari (66)", "intervals": [2, 2, 2, 1, 3, 1, 1], "indices": [0, 2, 4, 6, 7, 10, 11]},
{"name": "Mela Dharmavati (59)", "intervals": [2, 1, 3, 1, 2, 2, 1], "indices": [0, 2, 3, 6, 7, 9, 11]},
{"name": "Mela Dhatuvardhani (69)", "intervals": [3, 1, 2, 1, 1, 3, 1], "indices": [0, 3, 4, 6, 7, 8, 11]},
{"name": "Mela Dhavalambari (49)", "intervals": [1, 3, 2, 1, 1, 1, 3], "indices": [0, 1, 4, 6, 7, 8, 9]},
{"name": "Mela Dhenuka (9)", "intervals": [1, 2, 2, 2, 1, 3, 1], "indices": [0, 1, 3, 5, 7, 8, 11]},
{"name": "Mela Dhirasankarabharana (29) 1234567", "intervals": [1, 1, 2, 2, 2, 2, 2],
"indices": [0, 1, 2, 4, 6, 8, 10]},
{"name": "Mela Divyamani (48)", "intervals": [1, 2, 3, 1, 3, 1, 1], "indices": [0, 1, 3, 6, 7, 10, 11]},
{"name": "Mela Gamanasrama (53)", "intervals": [1, 3, 2, 1, 2, 2, 1], "indices": [0, 1, 4, 6, 7, 9, 11]},
{"name": "Mela Ganamurti (3)", "intervals": [1, 1, 3, 2, 1, 3, 1], "indices": [0, 1, 2, 5, 7, 8, 11]},
{"name": "Mela Gangeyabhusani (33)", "intervals": [3, 1, 1, 2, 1, 3, 1], "indices": [0, 3, 4, 5, 7, 8, 11]},
{"name": "Mela Gaurimanohari (23)", "intervals": [2, 1, 2, 2, 2, 2, 1], "indices": [0, 2, 3, 5, 7, 9, 11]},
{"name": "Mela Gavambodhi (43)", "intervals": [1, 2, 3, 1, 1, 1, 3], "indices": [0, 1, 3, 6, 7, 8, 9]},
{"name": "Mela Gayakapriya (13)", "intervals": [1, 3, 1, 2, 1, 1, 3], "indices": [0, 1, 4, 5, 7, 8, 9]},
{"name": "Mela Hanumattodi (8)", "intervals": [1, 2, 2, 2, 1, 2, 2], "indices": [0, 1, 3, 5, 7, 8, 10]},
{"name": "Mela Harikambhoji (28)", "intervals": [2, 2, 1, 2, 2, 1, 2], "indices": [0, 2, 4, 5, 7, 9, 10]},
{"name": "Mela Hatakambari (18)", "intervals": [1, 3, 1, 2, 3, 1, 1], "indices": [0, 1, 4, 5, 7, 10, 11]},
{"name": "Mela Hemavati (58)", "intervals": [2, 1, 3, 1, 2, 1, 2], "indices": [0, 2, 3, 6, 7, 9, 10]},
{"name": "Mela Jalarnavam (38)", "intervals": [1, 1, 4, 1, 1, 2, 2], "indices": [0, 1, 2, 6, 7, 8, 10]},
{"name": "Mela Jhalavarali (39)", "intervals": [1, 1, 4, 1, 1, 3, 1], "indices": [0, 1, 2, 6, 7, 8, 11]},
{"name": "Mela Jhankaradhvani (19)", "intervals": [2, 1, 2, 2, 1, 1, 3], "indices": [0, 2, 3, 5, 7, 8, 9]},
{"name": "Mela Jyotisvarupini (68)", "intervals": [3, 1, 2, 1, 1, 2, 2], "indices": [0, 3, 4, 6, 7, 8, 10]},
{"name": "Mela Kamavardhani (51)", "intervals": [1, 3, 2, 1, 1, 3, 1], "indices": [0, 1, 4, 6, 7, 8, 11]},
{"name": "Mela Kanakangi (1)", "intervals": [1, 1, 3, 2, 1, 1, 3], "indices": [0, 1, 2, 5, 7, 8, 9]},
{"name": "Mela Kantamani (61)", "intervals": [2, 2, 2, 1, 1, 1, 3], "indices": [0, 2, 4, 6, 7, 8, 9]},
{"name": "Mela Kharaharapriya (22)", "intervals": [2, 1, 2, 2, 2, 1, 2], "indices": [0, 2, 3, 5, 7, 9, 10]},
{"name": "Mela Kiravani (21)", "intervals": [2, 1, 2, 2, 1, 3, 1], "indices": [0, 2, 3, 5, 7, 8, 11]},
{"name": "Mela Kokilapriya (11)", "intervals": [1, 2, 2, 2, 2, 2, 1], "indices": [0, 1, 3, 5, 7, 9, 11]},
{"name": "Mela Kosalam (71)", "intervals": [3, 1, 2, 1, 2, 2, 1], "indices": [0, 3, 4, 6, 7, 9, 11]},
{"name": "Mela Latangi (63)", "intervals": [2, 2, 2, 1, 1, 3, 1], "indices": [0, 2, 4, 6, 7, 8, 11]},
{"name": "Mela Manavati (5)", "intervals": [1, 1, 3, 2, 2, 2, 1], "indices": [0, 1, 2, 5, 7, 9, 11]},
{"name": "Mela Mararanjani (25)", "intervals": [2, 2, 1, 2, 1, 1, 3], "indices": [0, 2, 4, 5, 7, 8, 9]},
{"name": "Mela Mayamalavagaula (15)", "intervals": [1, 3, 1, 2, 1, 1, 3], "indices": [0, 1, 4, 5, 7, 8, 9]},
{"name": "Mela Mechakalyani (65)", "intervals": [2, 2, 2, 1, 2, 2, 1], "indices": [0, 2, 4, 6, 7, 9, 11]},
{"name": "Mela Naganandini (30)", "intervals": [2, 2, 1, 2, 3, 1, 1], "indices": [0, 2, 4, 5, 7, 10, 11]},
{"name": "Mela Namanarayani (50)", "intervals": [1, 3, 2, 1, 1, 2, 2], "indices": [0, 1, 4, 6, 7, 8, 10]},
{"name": "Mela Nasikabhusani (70)", "intervals": [3, 1, 2, 1, 2, 1, 2], "indices": [0, 3, 4, 6, 7, 9, 10]},
{"name": "Mela Natabhairavi (20)", "intervals": [2, 1, 2, 2, 1, 2, 2], "indices": [0, 2, 3, 5, 7, 8, 10]},
{"name": "Mela Natakapriya (10)", "intervals": [1, 2, 2, 2, 2, 1, 2], "indices": [0, 1, 3, 5, 7, 9, 10]},
{"name": "Mela Navanitam (40)", "intervals": [1, 1, 4, 1, 2, 1, 2], "indices": [0, 1, 2, 6, 7, 9, 10]},
{"name": "Mela Nitimati (60)", "intervals": [2, 1, 3, 1, 3, 1, 1], "indices": [0, 2, 3, 6, 7, 10, 11]},
{"name": "Mela Pavani (41)", "intervals": [1, 1, 4, 1, 2, 2, 1], "indices": [0, 1, 2, 6, 7, 9, 11]},
{"name": "Mela Ragavardhani (32)", "intervals": [3, 1, 1, 2, 1, 2, 2], "indices": [0, 3, 4, 5, 7, 8, 10]},
{"name": "Mela Raghupriya (42)", "intervals": [1, 1, 4, 1, 3, 1, 1], "indices": [0, 1, 2, 6, 7, 10, 11]},
{"name": "Mela Ramapriya (52)", "intervals": [1, 3, 2, 1, 2, 1, 2], "indices": [0, 1, 4, 6, 7, 9, 10]},
{"name": "Mela Rasikapriya (72)", "intervals": [3, 1, 2, 1, 3, 1, 1], "indices": [0, 3, 4, 6, 7, 10, 11]},
{"name": "Mela Ratnangi (2)", "intervals": [1, 1, 3, 2, 1, 2, 2], "indices": [0, 1, 2, 5, 7, 8, 10]}
]
random_scale = random.choice(scales)
scale = random_scale["indices"] + [a + 12 for a in random_scale["indices"]]
notes_names = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
class Note:
def __init__(self, time, pitch, duration):
self.time = time
self.pitch = pitch
self.duration = duration
def create_note_sequence(key=36, total_duration=4, min_duration=1.0, max_duration=4):
start = 0
chord_start = 0
notes = []
max_duration = max_duration / min_duration
chord_options = [
[0, 2, 4, 6],
[0, 2, 5, 7],
[0, 3, 5, 7],
]
chord_notes = random.choice(chord_options)
octave = random.choice([0,12])
# bass chord
while chord_start < total_duration:
chord_duration = min(total_duration / random.choice([1,2,4]), total_duration - chord_start)
random.shuffle(chord_notes[:3])
chord = chord_notes[0:random.randint(1, 3)]
for index in chord:
note = Note(chord_start, key + scale[index] + octave, total_duration)
notes.append(note)
chord_start += chord_duration
# notes
while start < total_duration:
duration = min(random.randint(1, int(max_duration)) * min_duration, 4 - start)
random.shuffle(chord_notes)
chord = chord_notes[0:random.randint(1, 3)]
chord_name = []
pitch_index = random.randint(0, len(scale))
for chord_index in chord:
index = pitch_index + chord_index
pitch = key + scale[index % len(scale)] + 24
note = Note(start, pitch, duration)
chord_name.append(notes_names[pitch % len(notes_names)])
notes.append(note)
start += duration
print(chord_name)
return notes
def play_random_notes_inside_scale():
bars = 24
total_duration = 0
all_notes = []
key = random.randint(36, 48)
for i in range(bars):
time = i * 4
notes = create_note_sequence(key=key, min_duration=0.5, max_duration=4)
for note in notes:
p = note.pitch
t = time + note.time
d = note.duration
total_duration = max(t + d, total_duration)
all_notes.append(notes_names[p % 12])
MyMIDI.addNote(track, 0, p, t, d, 100)
print(notes_names[key % 12], random_scale["name"], set(all_notes), total_duration, "seconds")
# play_chords()
play_random_notes_inside_scale()
with open("output.mid", 'wb') as binfile:
MyMIDI.writeFile(binfile)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment