|
import os |
|
import json |
|
import numpy as np |
|
import music21 as m21 |
|
import streamlit as st |
|
import tensorflow.keras as keras |
|
|
|
|
|
MAPPING_PATH = "mapping.json" |
|
SEQUENCE_LENGTH = 64 |
|
|
|
|
|
|
|
class MelodyGenerator: |
|
|
|
def __init__( self, model_path = "model.keras" ): |
|
|
|
self.model_path = model_path |
|
self.model = keras.models.load_model(model_path) |
|
|
|
|
|
with open(MAPPING_PATH , "r") as fp: |
|
self._mappings = json.load(fp) |
|
|
|
self._start_symbol = ["/"] * SEQUENCE_LENGTH |
|
|
|
|
|
|
|
def generate_melody(self, seed, num_steps, max_sequence_length, temperature): |
|
|
|
|
|
seed = seed.split() |
|
melody = seed |
|
seed = self._start_symbol + seed |
|
|
|
|
|
seed = [self._mappings[symbol] for symbol in seed] |
|
|
|
|
|
|
|
for _ in range( num_steps ): |
|
|
|
|
|
seed = seed[-max_sequence_length :] |
|
|
|
|
|
|
|
onehot_seed = keras.utils.to_categorical( seed, num_classes=len(self._mappings)+1) |
|
|
|
|
|
|
|
onehot_seed = onehot_seed[np.newaxis , ...] |
|
|
|
|
|
|
|
probabilities = self.model.predict( onehot_seed )[0] |
|
|
|
|
|
output_int = self._sample_with_temperature(probabilities , temperature) |
|
|
|
|
|
seed.append(output_int) |
|
|
|
|
|
output_symbol = [ k for k,v in self._mappings.items() if v == output_int ][0] |
|
|
|
|
|
if output_symbol == "/": |
|
break |
|
|
|
|
|
else : |
|
melody.append(output_symbol) |
|
|
|
|
|
|
|
|
|
return melody |
|
|
|
|
|
|
|
def _sample_with_temperature( self, probabilities , temperature ): |
|
|
|
|
|
|
|
|
|
|
|
predictions = np.log(probabilities) / temperature |
|
probabilities = np.exp( predictions ) / np.sum(np.exp(predictions)) |
|
|
|
|
|
choices = range(len(probabilities)) |
|
index = np.random.choice(choices , p = probabilities) |
|
|
|
return index |
|
|
|
|
|
|
|
def save_melody( self, melody ,step_duration = 0.25, format = "midi" , file_name = "mel.mid") : |
|
|
|
|
|
stream = m21.stream.Stream() |
|
|
|
|
|
|
|
|
|
start_symbol = None |
|
step_counter = 1 |
|
|
|
|
|
for i, symbol in enumerate(melody) : |
|
|
|
|
|
if symbol != "_" or i + 1 == len(melody): |
|
|
|
|
|
if start_symbol is not None: |
|
|
|
quarter_length_duration = step_duration * step_counter |
|
|
|
|
|
if start_symbol == "r": |
|
m21_event = m21.note.Rest( quarterLength = quarter_length_duration) |
|
|
|
|
|
else : |
|
m21_event = m21.note.Note( int(start_symbol) , quaterLegth = quarter_length_duration ) |
|
|
|
|
|
stream.append(m21_event) |
|
|
|
|
|
step_counter = 1 |
|
|
|
|
|
start_symbol = symbol |
|
|
|
|
|
|
|
else : |
|
step_counter = step_counter + 1 |
|
|
|
|
|
|
|
|
|
stream.write( format , file_name ) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
st.markdown( |
|
""" |
|
<style> |
|
/* Define keyframes for the animation */ |
|
@keyframes glow { |
|
0% { text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 30px #fff, 0 0 40px #ff00e4, 0 0 70px #ff00e4, 0 0 80px #ff00e4, 0 0 100px #ff00e4, 0 0 150px #ff00e4; } |
|
50% { text-shadow: 0 0 20px #fff, 0 0 30px #fff, 0 0 40px #ff00e4, 0 0 50px #ff00e4, 0 0 80px #ff00e4, 0 0 90px #ff00e4, 0 0 110px #ff00e4, 0 0 160px #ff00e4; } |
|
100% { text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 30px #fff, 0 0 40px #ff00e4, 0 0 70px #ff00e4, 0 0 80px #ff00e4, 0 0 100px #ff00e4, 0 0 150px #ff00e4; } |
|
} |
|
|
|
/* Apply animation to the title */ |
|
.glowing-title { |
|
font-size: 6rem; |
|
font-weight: bold; |
|
color: #ff00e4; |
|
animation: glow 2s ease-in-out infinite; |
|
} |
|
</style> |
|
""" |
|
, unsafe_allow_html=True |
|
) |
|
st.markdown('<h1 class="glowing-title">Tune Genie</h1>', unsafe_allow_html=True) |
|
|
|
|
|
|
|
seeds ={ 'seed1' : "60 _ _ _ _ _ _ _ 60 _ _ _ _ _ _ _ 60 _ _ _ _ _ _ _ 62",'seed2' : "69 _ _ _ _ _ _ _",'seed3' : "69 _ _ _ 69 _ _ _ 69 _ _ _ 72 _ _ _ 72 _ _ _ 69",'seed4' : "76 _ _ _ 76 _ _ _ _ _ 76 _ 76 _ _ _ 79 _ _ _ 74 ",'seed5': "71 _ _ _ 69 _" } |
|
|
|
|
|
seed = st.selectbox( 'choose seed ' , ('seed1','seed2','seed3','seed4','seed5','Try your own seed' )) |
|
|
|
|
|
if seed == "Try your own seed": |
|
seed = st.text_input("Enter your custom seed:") |
|
else: |
|
seed = seeds[seed] |
|
|
|
|
|
if st.button('GENERATE'): |
|
mg = MelodyGenerator() |
|
melody = mg.generate_melody( seed , 200, SEQUENCE_LENGTH , 0.4) |
|
print(melody) |
|
mg.save_melody(melody) |
|
st.download_button( |
|
label="Download Midi File", |
|
data=open("mel.mid", "rb").read(), |
|
file_name="example.midi", |
|
mime="audio/midi" |
|
) |
|
|