floriangardin's picture
update message and tempo warning
4b77a87
raw
history blame
6.29 kB
import gradio as gr
from musiclang_predict import MusicLangPredictor
from musiclang import Score
from midi2audio import FluidSynth
import os
import tempfile
def inner_loop(nb_tokens, temperature, chord_progression, tempo, midi_file, bar_range):
top_p = 0.98
seed = 0
print(midi_file)
# Initialize the MusicLangPredictor
ml = MusicLangPredictor('musiclang/musiclang-v2')
tempo_message = "" # Default message if no MIDI file is uploaded
time_signature = (4, 4)
if midi_file is not None:
# Load the MIDI file and use it as the score prompt
filepath = midi_file
start_bar, end_bar = map(int, bar_range.split("-"))
score = Score.from_midi(filepath, chord_range=(start_bar, end_bar))
tempo = score.config['tempo'] # Use the tempo from the MIDI file and change input
time_signature = score.config['time_signature']
time_signature = (time_signature[1], time_signature[2])
tempo_message = f"Warning : real tempo of file is : {int(tempo)} BPM." # Update message based on MIDI file
else:
score = None # Default score is None if no MIDI file is uploaded
# Generate the score based on provided inputs and the uploaded MIDI file if available
if chord_progression.strip() == "" and score is None:
# Generate without specific chord progression or MIDI prompt
generated_score = ml.predict(
nb_tokens=int(nb_tokens),
temperature=float(temperature),
topp=top_p,
rng_seed=seed
)
elif score is not None and chord_progression.strip() == "":
# Generate using the uploaded MIDI file as a prompt
generated_score = ml.predict(
score=score, # Use the uploaded MIDI as the score prompt
nb_tokens=int(nb_tokens),
temperature=float(temperature),
topp=top_p,
rng_seed=seed
)
else:
# Generate with specific chord progression
generated_score = ml.predict_chords(
chord_progression,
score=score, # Use the uploaded MIDI as the score prompt
time_signature=time_signature,
temperature=temperature,
topp=top_p,
rng_seed=seed
)
chord_repr = generated_score.to_chord_repr()
# Save the generated score as a MIDI file
temp_midi_file = tempfile.NamedTemporaryFile(suffix=".mid", delete=False)
midi_path = temp_midi_file.name
generated_score.to_midi(midi_path, tempo=tempo, time_signature=time_signature)
# Convert MIDI to WAV then WAV to MP3 for playback
temp_wav_file = tempfile.NamedTemporaryFile(suffix=".wav", delete=False)
temp_mp3_file = tempfile.NamedTemporaryFile(suffix=".mp3", delete=False)
wav_path = temp_wav_file.name
mp3_path = temp_mp3_file.name
FluidSynth("/usr/share/sounds/sf2/FluidR3_GM.sf2").midi_to_audio(midi_path, wav_path)
os.system(f'ffmpeg -i {wav_path} -acodec libmp3lame -y -loglevel quiet -stats {mp3_path}')
# Remove the temporary WAV file
os.remove(wav_path)
return mp3_path, midi_path, chord_repr, tempo_message
def musiclang(nb_tokens, temperature, chord_progression, tempo, midi_file, bar_range):
exception = None
mp3_path, midi_path, chord_repr, tempo_message = None, None, None, ""
try:
mp3_path, midi_path, chord_repr, tempo_message = inner_loop(nb_tokens, temperature, chord_progression, tempo,
midi_file, bar_range)
except Exception as e:
exception = "Error : " + e.__class__.__name__ + " " + str(e)
# Return the MP3 path for Gradio to display and the MIDI file path for download
return mp3_path, midi_path, chord_repr, tempo_message, exception
# Update Gradio interface to include MIDI file upload and bar range selection
iface = gr.Interface(
fn=musiclang,
inputs=[
gr.Number(label="Number of Tokens", value=1024, minimum=256, maximum=2048, step=256),
gr.Slider(label="Temperature", value=0.95, minimum=0.1, maximum=1.0, step=0.1),
gr.Textbox(label="Chord Progression (Optional)", placeholder="Am CM Dm/F E7 Am", lines=2, value=""),
gr.Slider(label="Tempo", value=120, minimum=60, maximum=240, step=1),
gr.File(label="Upload MIDI File", type="filepath", file_types=[".mid", ".midi"]),
gr.Textbox(label="Bar Range of input file", placeholder="0-4", value="0-4")
],
outputs=[
gr.Audio(label="Generated Music"),
gr.File(label="Download MIDI"),
gr.Textbox(label="Inferred output Chord Progression", lines=2, value=""),
gr.Textbox(label="Tempo Used", value=""), # Display the tempo used for generation
gr.Textbox(label="Info Message") # Initially hidden, shown only if there's an error
],
title="Controllable Symbolic Music Generation with MusicLang Predict",
description="""
\n This is the demo for MusicLang Predict, which offers advanced controllability features and high-quality music generation by manipulating symbolic music. Control your music generation by :
\n - Specifying the number of tokens
\n - <b>The temperature</b>: the level of creativity of MusicLang. The higher the temperature, the more creative the generation. We suggest you test different levels to find the one that suits your needs
\n - <b>Chord progression</b> : Available chord qualities include: M, m, 7, m7b5, sus2, sus4, m7, M7, dim, dim0. You can also specify the bass if it belongs to the chord (e.g., Bm/D)
\n - <b>The tempo</b>
\n - <b>Uploading a MIDI</b> file to use as a prompt
\n - Selecting a bar range of the input file (For example 0-4 means first four bars)
\n Note: The model generates a score file, not an audio one. Therefore, the audio rendering in this notebook serves as a quick preview of the generated music. For an optimized experience, we recommend downloading the midi file and opening it in your favorite Digital Audio Workstation (DAW).”
\n If no chord progression or MIDI file is given, it generates a free sample with the specified number of tokens.
\n Need more info ? Visit <a href="https://github.com/musiclang/musiclang_predict">our Github</a>"""
)
iface.launch()