YongkangZOU commited on
Commit
d68bfe0
Β·
verified Β·
1 Parent(s): c2b658c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +43 -26
app.py CHANGED
@@ -17,14 +17,12 @@ VEROVIO_API_URL = os.getenv("VEROVIO_API_URL")
17
  # Ensure output directory exists
18
  Path("output").mkdir(exist_ok=True)
19
 
20
- def wav_to_musicxml(wav_path: str, timestamp: str) -> Path:
 
21
  output_dir = Path("output")
22
-
23
- # Clean old MIDI files
24
  for f in output_dir.glob("*_basic_pitch.mid"):
25
  f.unlink()
26
 
27
- # Generate MIDI using basic-pitch
28
  predict_and_save(
29
  audio_path_list=[wav_path],
30
  output_directory=str(output_dir),
@@ -39,15 +37,15 @@ def wav_to_musicxml(wav_path: str, timestamp: str) -> Path:
39
  if not midi_files:
40
  raise FileNotFoundError("❌ Failed to generate MIDI file")
41
 
42
- # Convert MIDI to MusicXML
43
  midi_path = midi_files[0]
44
  score = converter.parse(midi_path)
45
  musicxml_path = output_dir / f"generated_{timestamp}.musicxml"
46
  score.write("musicxml", fp=musicxml_path)
47
 
48
- return musicxml_path
49
 
50
- def render_musicxml_via_verovio_api(musicxml_path: Path) -> str:
 
51
  if not VEROVIO_API_URL:
52
  return "❌ VEROVIO_API_URL is not configured"
53
 
@@ -73,6 +71,7 @@ def render_musicxml_via_verovio_api(musicxml_path: Path) -> str:
73
  except Exception as e:
74
  return f"⚠️ Failed to parse SVG: {e}"
75
 
 
76
  def generate_music_and_score(melody_file, prompt):
77
  if not MUSICGEN_API_URL:
78
  return None, "❌ MUSICGEN_API_URL is not configured. Please check your .env file"
@@ -80,7 +79,6 @@ def generate_music_and_score(melody_file, prompt):
80
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
81
  wav_out_path = f"output/generated_{timestamp}.wav"
82
 
83
- # Step 1: Call MusicGen API
84
  try:
85
  with open(melody_file, "rb") as f:
86
  files = {"melody": ("hum.wav", f, "audio/wav")}
@@ -95,29 +93,48 @@ def generate_music_and_score(melody_file, prompt):
95
  with open(wav_out_path, "wb") as out:
96
  out.write(response.content)
97
 
98
- # Step 2: Convert to MusicXML
99
  try:
100
  musicxml_path = wav_to_musicxml(wav_out_path, timestamp)
101
  except Exception as e:
102
  return wav_out_path, f"⚠️ Music generated, but score conversion failed: {e}"
103
 
104
- # Step 3: Render score using Verovio API
105
  html = render_musicxml_via_verovio_api(musicxml_path)
106
  return wav_out_path, html
107
 
108
- demo = gr.Interface(
109
- fn=generate_music_and_score,
110
- inputs=[
111
- gr.Audio(type="filepath", label="Upload your humming (.wav)"),
112
- gr.Textbox(label="Describe your desired music style (prompt)")
113
- ],
114
- outputs=[
115
- gr.Audio(type="filepath", label="🎡 Generated Music"),
116
- gr.HTML(label="🎼 Score Preview (Rendered by Verovio)")
117
- ],
118
- title="🎡 Vibe Jamming: Your AI melody and sheet music companion",
119
- description="Upload a humming audio and a prompt. This app generates music and renders a musical score using Verovio."
120
- )
121
-
122
- if __name__ == "__main__":
123
- demo.launch(mcp_server=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  # Ensure output directory exists
18
  Path("output").mkdir(exist_ok=True)
19
 
20
+ # === Tool 1: Convert WAV to MusicXML ===
21
+ def wav_to_musicxml(wav_path: str, timestamp: str) -> str:
22
  output_dir = Path("output")
 
 
23
  for f in output_dir.glob("*_basic_pitch.mid"):
24
  f.unlink()
25
 
 
26
  predict_and_save(
27
  audio_path_list=[wav_path],
28
  output_directory=str(output_dir),
 
37
  if not midi_files:
38
  raise FileNotFoundError("❌ Failed to generate MIDI file")
39
 
 
40
  midi_path = midi_files[0]
41
  score = converter.parse(midi_path)
42
  musicxml_path = output_dir / f"generated_{timestamp}.musicxml"
43
  score.write("musicxml", fp=musicxml_path)
44
 
45
+ return str(musicxml_path)
46
 
47
+ # === Tool 2: Render MusicXML to HTML via Verovio ===
48
+ def render_musicxml_via_verovio_api(musicxml_path: str) -> str:
49
  if not VEROVIO_API_URL:
50
  return "❌ VEROVIO_API_URL is not configured"
51
 
 
71
  except Exception as e:
72
  return f"⚠️ Failed to parse SVG: {e}"
73
 
74
+ # === Tool 3: Melody + Prompt => Music + Score ===
75
  def generate_music_and_score(melody_file, prompt):
76
  if not MUSICGEN_API_URL:
77
  return None, "❌ MUSICGEN_API_URL is not configured. Please check your .env file"
 
79
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
80
  wav_out_path = f"output/generated_{timestamp}.wav"
81
 
 
82
  try:
83
  with open(melody_file, "rb") as f:
84
  files = {"melody": ("hum.wav", f, "audio/wav")}
 
93
  with open(wav_out_path, "wb") as out:
94
  out.write(response.content)
95
 
 
96
  try:
97
  musicxml_path = wav_to_musicxml(wav_out_path, timestamp)
98
  except Exception as e:
99
  return wav_out_path, f"⚠️ Music generated, but score conversion failed: {e}"
100
 
 
101
  html = render_musicxml_via_verovio_api(musicxml_path)
102
  return wav_out_path, html
103
 
104
+ # === MCP Tool App ===
105
+ with gr.Blocks(title="🎡 Vibe Jamming Tools") as demo:
106
+
107
+ # Tool 1: WAV to MusicXML
108
+ gr.Interface(
109
+ fn=wav_to_musicxml,
110
+ inputs=[
111
+ gr.Audio(type="filepath", label="🎀 WAV Audio File"),
112
+ gr.Textbox(label="Timestamp (e.g. 20250609_123000)")
113
+ ],
114
+ outputs=gr.Textbox(label="πŸ“„ MusicXML File Path"),
115
+ title="Tool 1: Convert WAV to MusicXML"
116
+ ).render()
117
+
118
+ # Tool 2: Render MusicXML to HTML
119
+ gr.Interface(
120
+ fn=render_musicxml_via_verovio_api,
121
+ inputs=gr.Textbox(label="πŸ“„ MusicXML File Path"),
122
+ outputs=gr.HTML(label="🎼 Rendered Score Preview"),
123
+ title="Tool 2: Render MusicXML via Verovio"
124
+ ).render()
125
+
126
+ # Tool 3: Melody + Prompt β†’ Music + Score
127
+ gr.Interface(
128
+ fn=generate_music_and_score,
129
+ inputs=[
130
+ gr.Audio(type="filepath", label="Upload your humming (.wav)"),
131
+ gr.Textbox(label="Describe your desired music style (prompt)")
132
+ ],
133
+ outputs=[
134
+ gr.Audio(type="filepath", label="🎡 Generated Music"),
135
+ gr.HTML(label="🎼 Score Preview (Rendered by Verovio)")
136
+ ],
137
+ title="Tool 3: Melody2Music+Score"
138
+ ).render()
139
+
140
+ demo.launch(mcp_server=True)