Spaces:
Running
Running
Upload app.py
Browse files
app.py
CHANGED
|
@@ -129,44 +129,53 @@ def generate_midi(temperature, top_k):
|
|
| 129 |
|
| 130 |
midi_events = round_bars
|
| 131 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
return midi_events
|
| 133 |
|
| 134 |
|
| 135 |
-
def
|
| 136 |
midi_data = pretty_midi.PrettyMIDI(initial_tempo=bpm, resolution=96)
|
| 137 |
midi_data.time_signature_changes.append(pretty_midi.containers.TimeSignature(4, 4, 0))
|
| 138 |
instrument = pretty_midi.Instrument(0)
|
| 139 |
midi_data.instruments.append(instrument)
|
| 140 |
|
| 141 |
-
for
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
instrument.notes.append(note)
|
| 149 |
|
| 150 |
midi_path = os.path.join(temp_dir, 'output.mid')
|
| 151 |
midi_data.write(midi_path)
|
| 152 |
print(f"Generated: {midi_path}")
|
| 153 |
|
| 154 |
|
| 155 |
-
def render_wav(midi_file, uploaded_sf2=None):
|
| 156 |
sf2_dir = 'sf2_kits'
|
| 157 |
audio_format = 's16'
|
| 158 |
sample_rate = '44100'
|
| 159 |
-
gain =
|
| 160 |
|
| 161 |
if uploaded_sf2:
|
| 162 |
sf2_file = uploaded_sf2
|
| 163 |
else:
|
| 164 |
-
sf2_files = [f for f in os.listdir(sf2_dir) if f.endswith('.sf2')]
|
| 165 |
if not sf2_files:
|
| 166 |
raise ValueError("No SoundFont (.sf2) file found in directory.")
|
| 167 |
sf2_file = os.path.join(sf2_dir, random.choice(sf2_files))
|
| 168 |
|
| 169 |
-
print(f"Using SoundFont: {sf2_file}")
|
| 170 |
output_wav = os.path.join(temp_dir, 'output.wav')
|
| 171 |
|
| 172 |
with open(os.devnull, 'w') as devnull:
|
|
@@ -179,15 +188,15 @@ def render_wav(midi_file, uploaded_sf2=None):
|
|
| 179 |
return output_wav
|
| 180 |
|
| 181 |
|
| 182 |
-
def generate_and_return_files(bpm, temperature, top_k, uploaded_sf2=None):
|
| 183 |
midi_events = generate_midi(temperature, top_k)
|
| 184 |
if not midi_events:
|
| 185 |
return "Error generating MIDI.", None, None
|
| 186 |
|
| 187 |
-
|
| 188 |
|
| 189 |
midi_file = os.path.join(temp_dir, 'output.mid')
|
| 190 |
-
wav_raw = render_wav(midi_file, uploaded_sf2)
|
| 191 |
wav_fx = os.path.join(temp_dir, 'output_fx.wav')
|
| 192 |
|
| 193 |
sfx_settings = [
|
|
@@ -213,40 +222,60 @@ def generate_and_return_files(bpm, temperature, top_k, uploaded_sf2=None):
|
|
| 213 |
|
| 214 |
|
| 215 |
custom_css = """
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 216 |
#generate-btn {
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
cursor: pointer;
|
| 224 |
}
|
|
|
|
| 225 |
#generate-btn:hover {
|
| 226 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 227 |
}
|
| 228 |
"""
|
| 229 |
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
|
| 234 |
with gr.Row():
|
| 235 |
with gr.Column(scale=1):
|
| 236 |
-
bpm = gr.Slider(minimum=50, maximum=200, step=1, value=
|
| 237 |
temperature = gr.Slider(minimum=0.1, maximum=2.0, step=0.1, value=1.0, label="Temperature")
|
| 238 |
-
top_k = gr.Slider(minimum=4, maximum=
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
midi_file = gr.File(label="MIDI File Output")
|
| 243 |
-
audio_file = gr.Audio(label="Generated Audio Output", type="filepath")
|
| 244 |
generate_button = gr.Button("Generate", elem_id="generate-btn")
|
|
|
|
| 245 |
|
| 246 |
generate_button.click(
|
| 247 |
fn=generate_and_return_files,
|
| 248 |
-
inputs=[bpm, temperature, top_k, soundfont],
|
| 249 |
outputs=[midi_file, audio_file]
|
| 250 |
)
|
| 251 |
|
|
|
|
|
|
|
| 252 |
iface.launch(share=True)
|
|
|
|
| 129 |
|
| 130 |
midi_events = round_bars
|
| 131 |
|
| 132 |
+
# remove duplciates
|
| 133 |
+
for track in midi_events:
|
| 134 |
+
track.sort(key=lambda x: x['start'])
|
| 135 |
+
unique_notes = []
|
| 136 |
+
|
| 137 |
+
for note in track:
|
| 138 |
+
if not any(abs(note['start'] - n['start']) < 12 and note['pitch'] == n['pitch'] for n in unique_notes):
|
| 139 |
+
unique_notes.append(note)
|
| 140 |
+
|
| 141 |
+
track[:] = unique_notes
|
| 142 |
+
|
| 143 |
return midi_events
|
| 144 |
|
| 145 |
|
| 146 |
+
def write_single_midi(midi_events, bpm):
|
| 147 |
midi_data = pretty_midi.PrettyMIDI(initial_tempo=bpm, resolution=96)
|
| 148 |
midi_data.time_signature_changes.append(pretty_midi.containers.TimeSignature(4, 4, 0))
|
| 149 |
instrument = pretty_midi.Instrument(0)
|
| 150 |
midi_data.instruments.append(instrument)
|
| 151 |
|
| 152 |
+
for event in midi_events[0]:
|
| 153 |
+
pitch = event['pitch']
|
| 154 |
+
velocity = event['velocity']
|
| 155 |
+
start = midi_data.tick_to_time(event['start'])
|
| 156 |
+
end = midi_data.tick_to_time(event['end'])
|
| 157 |
+
note = pretty_midi.Note(pitch=pitch, velocity=velocity, start=start, end=end)
|
| 158 |
+
instrument.notes.append(note)
|
|
|
|
| 159 |
|
| 160 |
midi_path = os.path.join(temp_dir, 'output.mid')
|
| 161 |
midi_data.write(midi_path)
|
| 162 |
print(f"Generated: {midi_path}")
|
| 163 |
|
| 164 |
|
| 165 |
+
def render_wav(midi_file, uploaded_sf2=None, output_level='2.0'):
|
| 166 |
sf2_dir = 'sf2_kits'
|
| 167 |
audio_format = 's16'
|
| 168 |
sample_rate = '44100'
|
| 169 |
+
gain = str(output_level)
|
| 170 |
|
| 171 |
if uploaded_sf2:
|
| 172 |
sf2_file = uploaded_sf2
|
| 173 |
else:
|
| 174 |
+
sf2_files = [f for f in os.listdir(os.path.join(sf2_dir)) if f.endswith('.sf2')]
|
| 175 |
if not sf2_files:
|
| 176 |
raise ValueError("No SoundFont (.sf2) file found in directory.")
|
| 177 |
sf2_file = os.path.join(sf2_dir, random.choice(sf2_files))
|
| 178 |
|
|
|
|
| 179 |
output_wav = os.path.join(temp_dir, 'output.wav')
|
| 180 |
|
| 181 |
with open(os.devnull, 'w') as devnull:
|
|
|
|
| 188 |
return output_wav
|
| 189 |
|
| 190 |
|
| 191 |
+
def generate_and_return_files(bpm, temperature, top_k, uploaded_sf2=None, output_level='2.0'):
|
| 192 |
midi_events = generate_midi(temperature, top_k)
|
| 193 |
if not midi_events:
|
| 194 |
return "Error generating MIDI.", None, None
|
| 195 |
|
| 196 |
+
write_single_midi(midi_events, bpm)
|
| 197 |
|
| 198 |
midi_file = os.path.join(temp_dir, 'output.mid')
|
| 199 |
+
wav_raw = render_wav(midi_file, uploaded_sf2, output_level)
|
| 200 |
wav_fx = os.path.join(temp_dir, 'output_fx.wav')
|
| 201 |
|
| 202 |
sfx_settings = [
|
|
|
|
| 222 |
|
| 223 |
|
| 224 |
custom_css = """
|
| 225 |
+
.gradio-container {
|
| 226 |
+
max-width: 1200px !important;
|
| 227 |
+
margin: 0 auto;
|
| 228 |
+
}
|
| 229 |
+
|
| 230 |
+
input[type="range"] {
|
| 231 |
+
background-image: linear-gradient(#7c4dff, #7c4dff);
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
#generate-btn {
|
| 235 |
+
font-size: 18px;
|
| 236 |
+
padding: 10px 20px;
|
| 237 |
+
border-radius: 5px;
|
| 238 |
+
cursor: pointer;
|
| 239 |
+
background: linear-gradient(90deg, hsla(268, 90%, 68%, 1) 0%, hsla(260, 72%, 70%, 1) 50%, hsla(247, 73%, 65%, 1) 100%);
|
| 240 |
+
transition: background 1s ease;
|
|
|
|
| 241 |
}
|
| 242 |
+
|
| 243 |
#generate-btn:hover {
|
| 244 |
+
background: linear-gradient(90deg, hsla(268, 90%, 78%, 1) 0%, hsla(260, 72%, 80%, 1) 50%, hsla(247, 73%, 75%, 1) 100%);
|
| 245 |
+
}
|
| 246 |
+
|
| 247 |
+
#component-11 .download a {
|
| 248 |
+
font-size: 16px;
|
| 249 |
}
|
| 250 |
"""
|
| 251 |
|
| 252 |
+
waveform_opts = gr.WaveformOptions(
|
| 253 |
+
waveform_color="#888888",
|
| 254 |
+
waveform_progress_color="#7c4dff",
|
| 255 |
+
trim_region_color="#7c4dff"
|
| 256 |
+
)
|
| 257 |
+
|
| 258 |
+
with gr.Blocks(css=custom_css, theme=gr.themes.Monochrome(font=gr.themes.GoogleFont("Roboto"))) as iface:
|
| 259 |
+
gr.Markdown("<h1 style='font-weight: bold; text-align: center; font-size: 40px; margin: 0px;'>nanoMPC</h1>")
|
| 260 |
+
gr.Markdown("<p style='text-align: center; font-size: 18px;'>nanoMPC is a MIDI transformer model that generates lo-fi and boom bap beats.</p>")
|
| 261 |
|
| 262 |
with gr.Row():
|
| 263 |
with gr.Column(scale=1):
|
| 264 |
+
bpm = gr.Slider(minimum=50, maximum=200, step=1, value=100, label="BPM")
|
| 265 |
temperature = gr.Slider(minimum=0.1, maximum=2.0, step=0.1, value=1.0, label="Temperature")
|
| 266 |
+
top_k = gr.Slider(minimum=4, maximum=16, step=1, value=8, label="Top-k")
|
| 267 |
+
output_level = gr.Slider(minimum=0, maximum=3, step=0.10, value=2.0, label="Output Gain")
|
| 268 |
+
midi_file = gr.File(label="MIDI Output")
|
| 269 |
+
audio_file = gr.Audio(label="Audio Output", type="filepath", waveform_options=waveform_opts)
|
|
|
|
|
|
|
| 270 |
generate_button = gr.Button("Generate", elem_id="generate-btn")
|
| 271 |
+
soundfont = gr.File(label="Optional: Upload SoundFont (preset=0, bank=0)")
|
| 272 |
|
| 273 |
generate_button.click(
|
| 274 |
fn=generate_and_return_files,
|
| 275 |
+
inputs=[bpm, temperature, top_k, soundfont, output_level],
|
| 276 |
outputs=[midi_file, audio_file]
|
| 277 |
)
|
| 278 |
|
| 279 |
+
gr.Markdown("<p style='text-align: center; font-size: 14px;'>Developed by <a href='https://www.patchbanks.com/' target='_blank'><strong>Patchbanks</strong></a></p>")
|
| 280 |
+
|
| 281 |
iface.launch(share=True)
|