Spaces:
Sleeping
Sleeping
Upload 3 files
Browse files- app.py +146 -0
- best2.h5 +3 -0
- final_notes +0 -0
app.py
ADDED
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import numpy as np
|
3 |
+
import requests
|
4 |
+
import time
|
5 |
+
import pickle
|
6 |
+
import tensorflow as tf
|
7 |
+
from music21 import *
|
8 |
+
from midi2audio import FluidSynth
|
9 |
+
from streamlit_lottie import st_lottie
|
10 |
+
import hydralit_components as hc
|
11 |
+
|
12 |
+
# Set page config
|
13 |
+
st.set_page_config(page_title="Music Generation", page_icon=":tada:", layout="wide")
|
14 |
+
|
15 |
+
def load_lottieurl(url):
|
16 |
+
r = requests.get(url)
|
17 |
+
if r.status_code != 200:
|
18 |
+
return None
|
19 |
+
return r.json()
|
20 |
+
|
21 |
+
# Load Lottie animation
|
22 |
+
lottie_coding = load_lottieurl("https://assets5.lottiefiles.com/private_files/lf30_fjln45y5.json")
|
23 |
+
|
24 |
+
# Header section
|
25 |
+
with st.container():
|
26 |
+
left_column, right_column = st.columns(2)
|
27 |
+
with left_column:
|
28 |
+
st.subheader("Music Generation :musical_keyboard:")
|
29 |
+
st.write(
|
30 |
+
"Our website is an application of piano music generation, you can listen to new musical notes generated by LSTM artificial neural network, which is used in fields of AI and deep learning. Let's get it started :notes:"
|
31 |
+
)
|
32 |
+
with right_column:
|
33 |
+
st_lottie(lottie_coding, height=300, key="coding")
|
34 |
+
|
35 |
+
# Sidebar for user input
|
36 |
+
with st.sidebar:
|
37 |
+
len_notes = st.slider('Please Choose The Notes Length', 20, 750, 20, 4)
|
38 |
+
st.write("Notes Length = ", len_notes)
|
39 |
+
|
40 |
+
# Music generation functionality
|
41 |
+
if st.sidebar.button('Generate My Music'):
|
42 |
+
if len_notes:
|
43 |
+
with st.container():
|
44 |
+
st.write("---")
|
45 |
+
with hc.HyLoader('✨ Your music is now under processing ✨', hc.Loaders.standard_loaders, index=[3, 0, 5]):
|
46 |
+
time.sleep(10)
|
47 |
+
generate(10, len_notes)
|
48 |
+
|
49 |
+
fs = FluidSynth('font.sf2', sample_rate=44100)
|
50 |
+
fs.midi_to_audio('test_output2.mid', 'output.wav')
|
51 |
+
|
52 |
+
st.audio('output.wav')
|
53 |
+
st.markdown("Here you are! You can download your music by right-clicking on the media player.")
|
54 |
+
|
55 |
+
####################### Music Generation Functions #######################
|
56 |
+
def generate(seq_len, x):
|
57 |
+
""" Generate a piano midi file """
|
58 |
+
with open('final_notes', 'rb') as filepath:
|
59 |
+
notes = pickle.load(filepath)
|
60 |
+
|
61 |
+
pitchnames = sorted(set(item for item in notes))
|
62 |
+
n_vocab = len(set(notes))
|
63 |
+
|
64 |
+
network_input, normalized_input = prepare_sequences(notes, pitchnames, n_vocab, seq_length=seq_len)
|
65 |
+
model = create_network(normalized_input, n_vocab)
|
66 |
+
prediction_output = generate_notes(model, network_input, pitchnames, n_vocab, x)
|
67 |
+
create_midi(prediction_output)
|
68 |
+
|
69 |
+
def prepare_sequences(notes, pitchnames, n_vocab, seq_length):
|
70 |
+
note_to_int = dict((note, number) for number, note in enumerate(pitchnames))
|
71 |
+
network_input = []
|
72 |
+
normalized_input = []
|
73 |
+
output = []
|
74 |
+
for i in range(0, len(notes) - seq_length, 1):
|
75 |
+
sequence_in = notes[i:i + seq_length]
|
76 |
+
sequence_out = notes[i + sequence_length]
|
77 |
+
network_input.append([note_to_int[char] for char in sequence_in])
|
78 |
+
output.append(note_to_int[sequence_out])
|
79 |
+
|
80 |
+
n_patterns = len(network_input)
|
81 |
+
normalized_input = np.reshape(network_input, (n_patterns, seq_length, 1))
|
82 |
+
normalized_input = normalized_input / float(n_vocab)
|
83 |
+
|
84 |
+
return (network_input, normalized_input)
|
85 |
+
|
86 |
+
def create_network(network_input, n_vocab):
|
87 |
+
model = tf.keras.Sequential()
|
88 |
+
model.add(tf.keras.layers.LSTM(512, input_shape=(network_input.shape[1], network_input.shape[2]), return_sequences=True, recurrent_dropout=0.3))
|
89 |
+
model.add(tf.keras.layers.LSTM(512, return_sequences=True, recurrent_dropout=0.3))
|
90 |
+
model.add(tf.keras.layers.LSTM(256))
|
91 |
+
model.add(tf.keras.layers.BatchNormalization())
|
92 |
+
model.add(tf.keras.layers.Dropout(0.2))
|
93 |
+
model.add(tf.keras.layers.Dense(256, activation='relu'))
|
94 |
+
model.add(tf.keras.layers.BatchNormalization())
|
95 |
+
model.add(tf.keras.layers.Dropout(0.2))
|
96 |
+
model.add(tf.keras.layers.Dense(n_vocab, activation='softmax'))
|
97 |
+
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
|
98 |
+
model.load_weights('best2.h5')
|
99 |
+
return model
|
100 |
+
|
101 |
+
def generate_notes(model, network_input, pitchnames, n_vocab, x):
|
102 |
+
start = np.random.randint(0, len(network_input)-1)
|
103 |
+
int_to_note = dict((number, note) for number, note in enumerate(pitchnames))
|
104 |
+
pattern = network_input[start]
|
105 |
+
prediction_output = []
|
106 |
+
|
107 |
+
for note_index in range(x):
|
108 |
+
prediction_input = np.reshape(pattern, (1, len(pattern), 1))
|
109 |
+
prediction_input = prediction_input / float(n_vocab)
|
110 |
+
prediction = model.predict(prediction_input, verbose=0)
|
111 |
+
index = np.argmax(prediction)
|
112 |
+
result = int_to_note[index]
|
113 |
+
prediction_output.append(result)
|
114 |
+
pattern.append(index)
|
115 |
+
pattern = pattern[1:len(pattern)]
|
116 |
+
|
117 |
+
return prediction_output
|
118 |
+
|
119 |
+
def create_midi(prediction_output):
|
120 |
+
offset = 0
|
121 |
+
output_notes = []
|
122 |
+
for pattern in prediction_output:
|
123 |
+
if ('.' in pattern) or pattern.isdigit():
|
124 |
+
notes_in_chord = pattern.split('.')
|
125 |
+
notes = []
|
126 |
+
for current_note in notes_in_chord:
|
127 |
+
new_note = note.Note(int(current_note))
|
128 |
+
new_note.storedInstrument = instrument.Piano()
|
129 |
+
notes.append(new_note)
|
130 |
+
new_chord = chord.Chord(notes)
|
131 |
+
new_chord.offset = offset
|
132 |
+
output_notes.append(new_chord)
|
133 |
+
elif pattern == 'r':
|
134 |
+
new_note = note.Rest(pattern)
|
135 |
+
new_note.offset = offset
|
136 |
+
new_note.storedInstrument = instrument.Piano()
|
137 |
+
output_notes.append(new_note)
|
138 |
+
else:
|
139 |
+
new_note = note.Note(pattern)
|
140 |
+
new_note.offset = offset
|
141 |
+
new_note.storedInstrument = instrument.Piano()
|
142 |
+
output_notes.append(new_note)
|
143 |
+
offset += 0.5
|
144 |
+
|
145 |
+
midi_stream = stream.Stream(output_notes)
|
146 |
+
midi_stream.write('midi', fp='test_output2.mid')
|
best2.h5
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:56c1163e8731fbc7f5f3b76a1829943e16a691b18083c8263cbedd460dac74bf
|
3 |
+
size 48765328
|
final_notes
ADDED
Binary file (142 kB). View file
|
|