Last active
February 27, 2019 19:10
-
-
Save badjano/3139071c3603cb39538c28bfbf81cf93 to your computer and use it in GitHub Desktop.
Music Generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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