import streamlit as st import base64 import os import time from moonarch import MusicToChordsConverter from mido import MidiFile, MidiTrack, Message import pretty_midi # Set the home directory path for moonarch home_directory = os.getcwd() # Your app content st.title("Moonarch Chords Analyzer: Chords") st.write("Extract chords from any given music.") # Set the title of the app st.title("Your Music, Perfected by AI") # Display the header text st.header("Experience the Future of Sound") st.write(""" Everything you need to create and release your music, including samples, plugins, unlimited distribution, and the world's best AI mastering engine. """) # Display the Start button if st.button("Start using Monaarch"): st.write("Welcome to Monaarch! Let's start creating amazing music.") # Add upload option audio_file = st.file_uploader("Upload a song", type=["mp3", "wav"]) if audio_file is not None: st.write("File uploaded successfully.") # Placeholder for progress bar progress_bar = st.progress(0) # Simulate file processing for percent_complete in range(100): time.sleep(0.01) progress_bar.progress(percent_complete + 1) st.write("File processing complete.") if st.button('Find Chords'): with st.spinner('Extracting chords and generating MIDI...'): # Convert the uploaded file to a file path file_name_without_ext = os.path.splitext(audio_file.name)[0] audio_file_path = os.path.join('/tmp', audio_file.name) with open(audio_file_path, 'wb') as f: f.write(audio_file.getbuffer()) # Convert music to chords and save as MIDI output_midi_file = f'{file_name_without_ext}.mid' converter = MusicToChordsConverter(audio_file_path) converter.recognize_chords() converter.generate_midi() # Updated save_midi method to handle PrettyMIDI object and proper message formatting def save_midi(self, output_file): midi = MidiFile() track = MidiTrack() midi.tracks.append(track) # Ensure self.midi_chords is a PrettyMIDI object if not isinstance(self.midi_chords, pretty_midi.PrettyMIDI): raise TypeError(f"self.midi_chords is not a PrettyMIDI object: {type(self.midi_chords)}") # Iterate over instruments and notes in the PrettyMIDI object for instrument in self.midi_chords.instruments: for note in instrument.notes: # Ensure note, velocity, and time are within valid MIDI data byte range midi_note = min(max(note.pitch, 0), 127) velocity = min(max(note.velocity, 0), 127) start_time = max(int(note.start * 1000), 0) # Convert to milliseconds end_time = max(int(note.end * 1000), 0) # Convert to milliseconds duration = end_time - start_time # Calculate duration # Add note_on and note_off messages with correct formatting track.append(Message('note_on', note=midi_note, velocity=velocity, time=start_time)) track.append(Message('note_off', note=midi_note, velocity=0, time=duration)) midi.save(output_file) # Assign the updated method to the converter instance converter.save_midi = save_midi.__get__(converter, MusicToChordsConverter) converter.save_midi(output_midi_file) st.success('Chords extraction and MIDI generation complete!') # Provide a button to download the MIDI file with open(output_midi_file, 'rb') as f: st.download_button( label="Download MIDI file", data=f, file_name=output_midi_file, mime='audio/midi' )