import pretty_midi import random import tkinter as tk from tkinter import ttk, filedialog import pygame import pypianoroll # type: ignore from icecream import ic # type: ignore class midgen: def __init__(self, status_label: ttk.Label): self.status_label = status_label self.scales = self.scales() def scales(self): scales = { "Major": [0, 2, 4, 5, 7, 9, 11], "Minor": [0, 2, 3, 5, 7, 8, 10], "Pentatonic": [0, 2, 4, 7, 9], "Blues": [0, 3, 5, 6, 7, 10], "Whole Tone": [0, 2, 4, 6, 8, 10], "Chromatic": [i for i in range(12)], "Octatonic": [0, 1, 3, 4, 6, 7, 9, 10], "Harmonic Minor": [0, 2, 3, 5, 7, 8, 11], "Melodic Minor": [0, 2, 3, 5, 7, 9, 11], "Dorian": [0, 2, 3, 5, 7, 9, 10], "Phrygian": [0, 1, 3, 5, 7, 8, 10], "Lydian": [0, 2, 4, 6, 7, 9, 11], "Mixolydian": [0, 2, 4, 5, 7, 9, 10], "Locrian": [0, 1, 3, 5, 6, 8, 10], "Diminished": [0, 2, 3, 5, 6, 8, 9, 11], "Whole Half Diminished": [0, 2, 3, 5, 6, 8, 9, 11], "Arabian": [0, 2, 4, 5, 6, 8, 10], "Hungarian Minor": [0, 2, 3, 6, 7, 8, 11], "Enigmatic": [0, 1, 4, 6, 8, 10, 11], "Neapolitan Major": [0, 1, 3, 5, 7, 9, 11], "Neapolitan Minor": [0, 1, 3, 5, 7, 8, 11], "Bluesy": [0, 3, 5, 6, 7, 10], "Hawaiian": [0, 2, 3, 7, 9], "Japanese": [0, 1, 5, 7, 8], "Chinese": [0, 4, 6, 7, 11], "Gypsy": [0, 2, 3, 6, 7, 8, 10], "Hirojoshi": [0, 2, 3, 7, 8], "In Sen": [0, 1, 5, 7, 10], "Iwato": [0, 1, 5, 6, 10], "Kumoi": [0, 2, 3, 7, 9], "Pelog": [0, 1, 3, 7, 8], "Ryukyu": [0, 4, 5, 7, 11], "Spanish": [0, 1, 3, 4, 5, 6, 8, 10], "Todi": [0, 1, 3, 6, 7, 8, 11], "Yo": [0, 2, 5, 7, 9] } return scales def generate_midi(self): self.status_label.config(text='Generating MIDI...') try: midi = pretty_midi.PrettyMIDI() instrument = pretty_midi.Instrument(0) scale = random.choice(list(self.scales.keys())) scale_notes = self.scales[scale] ic(f"Using scale: {scale}") ic(f"Using notes: {scale_notes}") for start, end in zip(range(0, 100, 10), range(10, 110, 10)): note = pretty_midi.Note( velocity=100, pitch=random.choice(scale_notes), start=start, end=end ) instrument.notes.append(note) midi.instruments.append(instrument) filepath = filedialog.asksaveasfilename(defaultextension='.mid') if filepath: midi.write(filepath) track = pypianoroll.Multitrack(filepath) track.plot() self.status_label.config(text='MIDI generated successfully!') except Exception as e: self.status_label.config(text=f"Error generating MIDI: {e}") class MidPlay: """A class to handle MIDI file playback.""" def __init__(self): self.playlist = [] self.current_midi = None self.playing = False pygame.mixer.init() def load_midi(self, filepath: str) -> None: try: self.current_midi = pretty_midi.PrettyMIDI(filepath) pygame.mixer.music.load(filepath) except Exception as e: print(f"Error loading MIDI: {e}") def add_to_playlist(self, filepath: str) -> None: """Adds a MIDI file to the playlist. Args: filepath: The path to the MIDI file. """ self.playlist.append(filepath) def clear_playlist(self) -> None: """Clears the playlist.""" self.playlist = [] def play_midi(self) -> None: """Starts or resumes playback of the current MIDI file.""" if self.current_midi: self.current_midi.instruments[0].synthesize() pygame.mixer.music.play() self.playing = True else: print("No MIDI file loaded") def pause(self) -> None: """Pauses playback.""" pygame.mixer.music.pause() self.playing = False def stop(self) -> None: """Stops playback.""" pygame.mixer.music.stop() self.playing = False class UserInterface: def __init__(self): self.root = tk.Tk() self.root.title("MIDI Generator") self.root.geometry("400x200") self.root.resizable(True, True) self.status_label = ttk.Label(self.root, text="") self.status_label.pack() self.midi_generator = midgen(self.status_label) self.midi_player = MidPlay() self.filepath = None self.midi = None self.generate_button = ttk.Button(self.root, text="Generate MIDI", command=self.midi_generator.generate_midi) self.generate_button.pack() self.load_button = ttk.Button(self.root, text="Load MIDI", command=lambda: self.midi_player.load_midi(self.filepath)) self.load_button.pack() self.play_button = ttk.Button(self.root, text="Play MIDI", command=lambda: self.midi_player.play_midi()) self.play_button.pack() self.exit_button = ttk.Button(self.root, text="Exit", command=self.root.quit) self.exit_button.pack() window = tk.Tk() window.title("MIDI Generator") self.root.mainloop() if __name__ == "__main__": ui = UserInterface()