ghostai1 commited on
Commit
ca48103
·
verified ·
1 Parent(s): a50352d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +145 -84
app.py CHANGED
@@ -42,7 +42,7 @@ try:
42
  sys.exit(1)
43
  musicgen_model = MusicGen.get_pretrained(local_model_path, device=device)
44
  musicgen_model.set_generation_params(
45
- duration=15, # Default chunk duration
46
  two_step_cfg=False # Disable two-step CFG for stability
47
  )
48
  except Exception as e:
@@ -59,53 +59,67 @@ def print_resource_usage(stage: str):
59
  print("---------------")
60
 
61
  # 4) GENRE PROMPT FUNCTIONS
62
- def set_red_hot_chili_peppers_prompt():
63
- return "Funk rock with groovy basslines, syncopated guitar riffs, energetic drums, and a Red Hot Chili Peppers-inspired vibe with dynamic vocal energy and funky breakdowns."
 
64
 
65
- def set_nirvana_grunge_prompt():
66
- return "Grunge with raw distorted guitar riffs, heavy drums, melodic basslines, and a Nirvana-inspired angst-filled sound with quiet-loud dynamics."
 
67
 
68
- def set_pearl_jam_grunge_prompt():
69
- return "Grunge with soulful guitar leads, driving rhythms, deep bass, and a Pearl Jam-inspired emotional intensity with soaring choruses."
 
70
 
71
- def set_soundgarden_grunge_prompt():
72
- return "Grunge with heavy, sludgy guitar riffs, complex drum patterns, and a Soundgarden-inspired dark, psychedelic edge with powerful vocals."
 
73
 
74
- def set_foo_fighters_prompt():
75
  styles = ["anthemic", "gritty", "melodic", "fast-paced", "driving"]
76
  tempos = ["upbeat", "mid-tempo", "high-energy"]
77
  moods = ["energetic", "introspective", "rebellious", "uplifting"]
78
  style = random.choice(styles)
79
  tempo = random.choice(tempos)
80
  mood = random.choice(moods)
81
- return f"Alternative rock with {style} guitar riffs, {tempo} drums, melodic hooks, and a Foo Fighters-inspired {mood} vibe with powerful choruses."
 
82
 
83
- def set_smashing_pumpkins_prompt():
84
- return "Alternative rock with dreamy guitar textures, heavy distortion, dynamic drums, and a Smashing Pumpkins-inspired blend of melancholy and aggression."
 
85
 
86
- def set_radiohead_prompt():
87
- return "Experimental rock with atmospheric synths, intricate guitar layers, complex rhythms, and a Radiohead-inspired blend of introspective and innovative soundscapes."
 
88
 
89
- def set_classic_rock_prompt():
90
- return "Classic rock with bluesy electric guitars, steady drums, groovy bass, and a Led Zeppelin-inspired raw energy with dynamic solos."
 
91
 
92
- def set_alternative_rock_prompt():
93
- return "Alternative rock with distorted guitar riffs, punchy drums, melodic basslines, and a Pixies-inspired quirky, energetic vibe."
 
94
 
95
- def set_post_punk_prompt():
96
- return "Post-punk with jangly guitars, driving basslines, sharp drums, and a Joy Division-inspired moody, atmospheric sound."
 
97
 
98
- def set_indie_rock_prompt():
99
- return "Indie rock with jangly guitars, heartfelt vocals, steady drums, and an Arctic Monkeys-inspired blend of witty lyrics and catchy riffs."
 
100
 
101
- def set_funk_rock_prompt():
102
- return "Funk rock with slap bass, funky guitar chords, upbeat drums, and a Rage Against the Machine-inspired mix of groove and aggression."
 
103
 
104
- def set_detroit_techno_prompt():
105
- return "Detroit techno with deep pulsing synths, driving basslines, crisp hi-hats, and a Juan Atkins-inspired rhythmic groove."
 
106
 
107
- def set_deep_house_prompt():
108
- return "Deep house with warm analog synth chords, soulful vocal chops, deep basslines, and a Larry Heard-inspired laid-back groove."
 
109
 
110
  # 5) AUDIO PROCESSING FUNCTIONS
111
  def apply_chorus(segment):
@@ -133,7 +147,7 @@ def apply_fade(segment, fade_in_duration=2000, fade_out_duration=2000):
133
  return segment
134
 
135
  # 6) GENERATION & I/O FUNCTIONS
136
- def generate_music(instrumental_prompt: str, cfg_scale: float, top_k: int, top_p: float, temperature: float, total_duration: int, crossfade_duration: int, num_variations: int, use_chunks: bool):
137
  global musicgen_model
138
  if not instrumental_prompt.strip():
139
  return None, "⚠️ Please enter a valid instrumental prompt!"
@@ -142,6 +156,11 @@ def generate_music(instrumental_prompt: str, cfg_scale: float, top_k: int, top_p
142
  total_duration = min(max(total_duration, 10), 90)
143
  sample_rate = musicgen_model.sample_rate
144
  output_files = []
 
 
 
 
 
145
 
146
  for var in range(num_variations):
147
  print(f"Generating variation {var+1}/{num_variations}...")
@@ -151,22 +170,21 @@ def generate_music(instrumental_prompt: str, cfg_scale: float, top_k: int, top_p
151
 
152
  if use_chunks:
153
  # Chunked generation
154
- chunk_duration = 15
155
- num_chunks = max(1, total_duration // chunk_duration)
156
  chunk_duration = total_duration / num_chunks
157
  overlap_duration = min(1.0, crossfade_duration / 1000.0)
158
  generation_duration = chunk_duration + overlap_duration
159
  audio_chunks = []
160
 
161
  for i in range(num_chunks):
162
- chunk_prompt = instrumental_prompt
163
  print(f"Generating chunk {i+1}/{num_chunks} for variation {var+1} on GPU (prompt: {chunk_prompt})...")
164
  musicgen_model.set_generation_params(
165
  duration=generation_duration,
166
  use_sampling=True,
167
  top_k=top_k,
168
  top_p=top_p,
169
- temperature=temperature,
170
  cfg_coef=cfg_scale
171
  )
172
 
@@ -211,6 +229,10 @@ def generate_music(instrumental_prompt: str, cfg_scale: float, top_k: int, top_p
211
  final_segment = final_segment.append(next_segment, crossfade=crossfade_duration)
212
 
213
  final_segment = final_segment[:total_duration * 1000]
 
 
 
 
214
  else:
215
  # Single-shot generation
216
  print(f"Generating full track for variation {var+1} on GPU (prompt: {instrumental_prompt})...")
@@ -219,7 +241,7 @@ def generate_music(instrumental_prompt: str, cfg_scale: float, top_k: int, top_p
219
  use_sampling=True,
220
  top_k=top_k,
221
  top_p=top_p,
222
- temperature=temperature,
223
  cfg_coef=cfg_scale
224
  )
225
 
@@ -227,7 +249,7 @@ def generate_music(instrumental_prompt: str, cfg_scale: float, top_k: int, top_p
227
 
228
  with torch.no_grad():
229
  with autocast():
230
- audio_chunk = musicgen_model.generate([instrumental_prompt], progress=True)[0]
231
 
232
  audio_chunk = audio_chunk.cpu().to(dtype=torch.float32)
233
  if audio_chunk.dim() == 1:
@@ -247,50 +269,60 @@ def generate_music(instrumental_prompt: str, cfg_scale: float, top_k: int, top_p
247
  torchaudio.save(temp_wav_path, audio_chunk, sample_rate, bits_per_sample=24)
248
  final_segment = AudioSegment.from_wav(temp_wav_path)
249
  os.remove(temp_wav_path)
 
250
 
251
  torch.cuda.empty_cache()
252
  gc.collect()
253
  time.sleep(0.5)
254
  print_resource_usage(f"After Full Track Generation (Variation {var+1})")
255
 
256
- print(f"Post-processing final track for variation {var+1}...")
257
- final_segment = apply_eq(final_segment)
258
- final_segment = apply_chorus(final_segment)
259
- final_segment = apply_limiter(final_segment, max_db=-6.0)
260
- final_segment = final_segment.normalize(headroom=-9.0)
261
- final_segment = apply_final_gain(final_segment, target_db=-18.0)
262
-
263
- mp3_path = f"output_cleaned_variation_{var+1}.mp3"
264
- final_segment.export(
265
- mp3_path,
266
- format="mp3",
267
- bitrate="320k",
268
- tags={"title": f"GhostAI Instrumental Variation {var+1}", "artist": "GhostAI"}
269
- )
270
- print(f"Saved final audio to {mp3_path}")
271
- output_files.append(mp3_path)
272
-
273
- if use_chunks:
274
- for chunk_path in audio_chunks:
275
- os.remove(chunk_path)
 
 
 
 
 
276
 
277
  print_resource_usage("After Final Generation")
278
  print(f"Total Generation Time: {time.time() - start_time:.2f} seconds")
279
 
280
- # Return the first variation for Gradio display; others are saved to disk
281
- return output_files[0], f"✅ Done! Generated {num_variations} variations."
282
  except Exception as e:
283
  return None, f"❌ Generation failed: {e}"
284
  finally:
285
  torch.cuda.empty_cache()
286
  gc.collect()
287
 
288
- # Function to toggle crossfade_duration interactivity
289
- def toggle_crossfade_interactivity(use_chunks):
290
- return gr.update(interactive=use_chunks)
 
 
 
 
291
 
292
  def clear_inputs():
293
- return "", 3.0, 250, 0.9, 1.0, 30, 500, 1, True
294
 
295
  # 7) CUSTOM CSS
296
  css = """
@@ -434,13 +466,21 @@ with gr.Blocks(css=css) as demo:
434
  info="Total duration of the track (10 to 90 seconds)."
435
  )
436
  crossfade_duration = gr.Slider(
437
- label="Crossfade Duration (ms)",
438
  minimum=100,
439
  maximum=2000,
440
- value=500,
441
  step=100,
442
  info="Crossfade duration between chunks (only used if chunking is enabled)."
443
  )
 
 
 
 
 
 
 
 
444
  num_variations = gr.Slider(
445
  label="Number of Variations",
446
  minimum=1,
@@ -449,10 +489,26 @@ with gr.Blocks(css=css) as demo:
449
  step=1,
450
  info="Number of different versions to generate with varying random seeds."
451
  )
 
 
 
 
 
 
 
 
452
  use_chunks = gr.Checkbox(
453
  label="Generate in Chunks",
454
  value=True,
455
- info="Enable to generate in 15-second chunks (safer for GPU memory). Disable for single-shot generation (higher VRAM usage)."
 
 
 
 
 
 
 
 
456
  )
457
  with gr.Row(elem_classes="action-buttons"):
458
  gen_btn = gr.Button("Generate Music")
@@ -462,32 +518,37 @@ with gr.Blocks(css=css) as demo:
462
  out_audio = gr.Audio(label="Generated Stereo Instrumental Track", type="filepath")
463
  status = gr.Textbox(label="Status", interactive=False)
464
 
465
- # Toggle crossfade_duration interactivity
466
- use_chunks.change(fn=toggle_crossfade_interactivity, inputs=use_chunks, outputs=crossfade_duration)
467
-
468
- rhcp_btn.click(set_red_hot_chili_peppers_prompt, inputs=None, outputs=[instrumental_prompt])
469
- nirvana_btn.click(set_nirvana_grunge_prompt, inputs=None, outputs=[instrumental_prompt])
470
- pearl_jam_btn.click(set_pearl_jam_grunge_prompt, inputs=None, outputs=[instrumental_prompt])
471
- soundgarden_btn.click(set_soundgarden_grunge_prompt, inputs=None, outputs=[instrumental_prompt])
472
- foo_fighters_btn.click(set_foo_fighters_prompt, inputs=None, outputs=[instrumental_prompt])
473
- smashing_pumpkins_btn.click(set_smashing_pumpkins_prompt, inputs=None, outputs=[instrumental_prompt])
474
- radiohead_btn.click(set_radiohead_prompt, inputs=None, outputs=[instrumental_prompt])
475
- classic_rock_btn.click(set_classic_rock_prompt, inputs=None, outputs=[instrumental_prompt])
476
- alternative_rock_btn.click(set_alternative_rock_prompt, inputs=None, outputs=[instrumental_prompt])
477
- post_punk_btn.click(set_post_punk_prompt, inputs=None, outputs=[instrumental_prompt])
478
- indie_rock_btn.click(set_indie_rock_prompt, inputs=None, outputs=[instrumental_prompt])
479
- funk_rock_btn.click(set_funk_rock_prompt, inputs=None, outputs=[instrumental_prompt])
480
- detroit_techno_btn.click(set_detroit_techno_prompt, inputs=None, outputs=[instrumental_prompt])
481
- deep_house_btn.click(set_deep_house_prompt, inputs=None, outputs=[instrumental_prompt])
 
 
 
 
 
482
  gen_btn.click(
483
  generate_music,
484
- inputs=[instrumental_prompt, cfg_scale, top_k, top_p, temperature, total_duration, crossfade_duration, num_variations, use_chunks],
485
  outputs=[out_audio, status]
486
  )
487
  clr_btn.click(
488
  clear_inputs,
489
  inputs=None,
490
- outputs=[instrumental_prompt, cfg_scale, top_k, top_p, temperature, total_duration, crossfade_duration, num_variations, use_chunks]
491
  )
492
 
493
  # 9) TURN OFF OPENAPI/DOCS
 
42
  sys.exit(1)
43
  musicgen_model = MusicGen.get_pretrained(local_model_path, device=device)
44
  musicgen_model.set_generation_params(
45
+ duration=25, # Default chunk duration
46
  two_step_cfg=False # Disable two-step CFG for stability
47
  )
48
  except Exception as e:
 
59
  print("---------------")
60
 
61
  # 4) GENRE PROMPT FUNCTIONS
62
+ def set_red_hot_chili_peppers_prompt(bpm):
63
+ rhythm = "strong rhythmic steps" if bpm > 120 else "groovy rhythmic flow"
64
+ return f"Funk rock with groovy basslines, syncopated guitar riffs, energetic drums, and a Red Hot Chili Peppers-inspired vibe with dynamic vocal energy and funky breakdowns, {rhythm} at {bpm} BPM."
65
 
66
+ def set_nirvana_grunge_prompt(bpm):
67
+ rhythm = "intense rhythmic steps" if bpm > 120 else "grungy rhythmic pulse"
68
+ return f"Grunge with raw distorted guitar riffs, heavy drums, melodic basslines, and a Nirvana-inspired angst-filled sound with quiet-loud dynamics, {rhythm} at {bpm} BPM."
69
 
70
+ def set_pearl_jam_grunge_prompt(bpm):
71
+ rhythm = "soulful rhythmic steps" if bpm > 120 else "driving rhythmic flow"
72
+ return f"Grunge with soulful guitar leads, driving rhythms, deep bass, and a Pearl Jam-inspired emotional intensity with soaring choruses, {rhythm} at {bpm} BPM."
73
 
74
+ def set_soundgarden_grunge_prompt(bpm):
75
+ rhythm = "heavy rhythmic steps" if bpm > 120 else "sludgy rhythmic groove"
76
+ return f"Grunge with heavy, sludgy guitar riffs, complex drum patterns, and a Soundgarden-inspired dark, psychedelic edge with powerful vocals, {rhythm} at {bpm} BPM."
77
 
78
+ def set_foo_fighters_prompt(bpm):
79
  styles = ["anthemic", "gritty", "melodic", "fast-paced", "driving"]
80
  tempos = ["upbeat", "mid-tempo", "high-energy"]
81
  moods = ["energetic", "introspective", "rebellious", "uplifting"]
82
  style = random.choice(styles)
83
  tempo = random.choice(tempos)
84
  mood = random.choice(moods)
85
+ rhythm = "powerful rhythmic steps" if bpm > 120 else "catchy rhythmic groove"
86
+ return f"Alternative rock with {style} guitar riffs, {tempo} drums, melodic hooks, and a Foo Fighters-inspired {mood} vibe with powerful choruses, {rhythm} at {bpm} BPM."
87
 
88
+ def set_smashing_pumpkins_prompt(bpm):
89
+ rhythm = "dynamic rhythmic steps" if bpm > 120 else "dreamy rhythmic flow"
90
+ return f"Alternative rock with dreamy guitar textures, heavy distortion, dynamic drums, and a Smashing Pumpkins-inspired blend of melancholy and aggression, {rhythm} at {bpm} BPM."
91
 
92
+ def set_radiohead_prompt(bpm):
93
+ rhythm = "complex rhythmic steps" if bpm > 120 else "intricate rhythmic pulse"
94
+ return f"Experimental rock with atmospheric synths, intricate guitar layers, complex rhythms, and a Radiohead-inspired blend of introspective and innovative soundscapes, {rhythm} at {bpm} BPM."
95
 
96
+ def set_classic_rock_prompt(bpm):
97
+ rhythm = "bluesy rhythmic steps" if bpm > 120 else "steady rhythmic groove"
98
+ return f"Classic rock with bluesy electric guitars, steady drums, groovy bass, and a Led Zeppelin-inspired raw energy with dynamic solos, {rhythm} at {bpm} BPM."
99
 
100
+ def set_alternative_rock_prompt(bpm):
101
+ rhythm = "quirky rhythmic steps" if bpm > 120 else "energetic rhythmic flow"
102
+ return f"Alternative rock with distorted guitar riffs, punchy drums, melodic basslines, and a Pixies-inspired quirky, energetic vibe, {rhythm} at {bpm} BPM."
103
 
104
+ def set_post_punk_prompt(bpm):
105
+ rhythm = "sharp rhythmic steps" if bpm > 120 else "moody rhythmic pulse"
106
+ return f"Post-punk with jangly guitars, driving basslines, sharp drums, and a Joy Division-inspired moody, atmospheric sound, {rhythm} at {bpm} BPM."
107
 
108
+ def set_indie_rock_prompt(bpm):
109
+ rhythm = "catchy rhythmic steps" if bpm > 120 else "jangly rhythmic flow"
110
+ return f"Indie rock with jangly guitars, heartfelt vocals, steady drums, and an Arctic Monkeys-inspired blend of witty lyrics and catchy riffs, {rhythm} at {bpm} BPM."
111
 
112
+ def set_funk_rock_prompt(bpm):
113
+ rhythm = "aggressive rhythmic steps" if bpm > 120 else "funky rhythmic groove"
114
+ return f"Funk rock with slap bass, funky guitar chords, upbeat drums, and a Rage Against the Machine-inspired mix of groove and aggression, {rhythm} at {bpm} BPM."
115
 
116
+ def set_detroit_techno_prompt(bpm):
117
+ rhythm = "pulsing rhythmic steps" if bpm > 120 else "deep rhythmic groove"
118
+ return f"Detroit techno with deep pulsing synths, driving basslines, crisp hi-hats, and a Juan Atkins-inspired rhythmic groove, {rhythm} at {bpm} BPM."
119
 
120
+ def set_deep_house_prompt(bpm):
121
+ rhythm = "soulful rhythmic steps" if bpm > 120 else "laid-back rhythmic flow"
122
+ return f"Deep house with warm analog synth chords, soulful vocal chops, deep basslines, and a Larry Heard-inspired laid-back groove, {rhythm} at {bpm} BPM."
123
 
124
  # 5) AUDIO PROCESSING FUNCTIONS
125
  def apply_chorus(segment):
 
147
  return segment
148
 
149
  # 6) GENERATION & I/O FUNCTIONS
150
+ def generate_music(instrumental_prompt: str, cfg_scale: float, top_k: int, top_p: float, temperature: float, total_duration: int, crossfade_duration: int, variation_crossfade_duration: int, num_variations: int, chunk_count: int, use_chunks: bool, bpm: int):
151
  global musicgen_model
152
  if not instrumental_prompt.strip():
153
  return None, "⚠️ Please enter a valid instrumental prompt!"
 
156
  total_duration = min(max(total_duration, 10), 90)
157
  sample_rate = musicgen_model.sample_rate
158
  output_files = []
159
+ variation_segments = []
160
+
161
+ # Adjust temperature based on BPM for energy
162
+ adjusted_temperature = temperature + (bpm - 120) / 600.0 # Scale temperature slightly
163
+ adjusted_temperature = min(max(adjusted_temperature, 0.1), 2.0)
164
 
165
  for var in range(num_variations):
166
  print(f"Generating variation {var+1}/{num_variations}...")
 
170
 
171
  if use_chunks:
172
  # Chunked generation
173
+ num_chunks = max(1, min(chunk_count, total_duration // 25)) # Cap at 25 seconds per chunk
 
174
  chunk_duration = total_duration / num_chunks
175
  overlap_duration = min(1.0, crossfade_duration / 1000.0)
176
  generation_duration = chunk_duration + overlap_duration
177
  audio_chunks = []
178
 
179
  for i in range(num_chunks):
180
+ chunk_prompt = f"{instrumental_prompt}, at {bpm} BPM"
181
  print(f"Generating chunk {i+1}/{num_chunks} for variation {var+1} on GPU (prompt: {chunk_prompt})...")
182
  musicgen_model.set_generation_params(
183
  duration=generation_duration,
184
  use_sampling=True,
185
  top_k=top_k,
186
  top_p=top_p,
187
+ temperature=adjusted_temperature,
188
  cfg_coef=cfg_scale
189
  )
190
 
 
229
  final_segment = final_segment.append(next_segment, crossfade=crossfade_duration)
230
 
231
  final_segment = final_segment[:total_duration * 1000]
232
+ variation_segments.append(final_segment)
233
+
234
+ for chunk_path in audio_chunks:
235
+ os.remove(chunk_path)
236
  else:
237
  # Single-shot generation
238
  print(f"Generating full track for variation {var+1} on GPU (prompt: {instrumental_prompt})...")
 
241
  use_sampling=True,
242
  top_k=top_k,
243
  top_p=top_p,
244
+ temperature=adjusted_temperature,
245
  cfg_coef=cfg_scale
246
  )
247
 
 
249
 
250
  with torch.no_grad():
251
  with autocast():
252
+ audio_chunk = musicgen_model.generate([f"{instrumental_prompt}, at {bpm} BPM"], progress=True)[0]
253
 
254
  audio_chunk = audio_chunk.cpu().to(dtype=torch.float32)
255
  if audio_chunk.dim() == 1:
 
269
  torchaudio.save(temp_wav_path, audio_chunk, sample_rate, bits_per_sample=24)
270
  final_segment = AudioSegment.from_wav(temp_wav_path)
271
  os.remove(temp_wav_path)
272
+ variation_segments.append(final_segment)
273
 
274
  torch.cuda.empty_cache()
275
  gc.collect()
276
  time.sleep(0.5)
277
  print_resource_usage(f"After Full Track Generation (Variation {var+1})")
278
 
279
+ # Combine variations with crossfade
280
+ print("Combining variations with crossfade...")
281
+ combined_segment = variation_segments[0]
282
+ for i in range(1, len(variation_segments)):
283
+ next_segment = variation_segments[i]
284
+ next_segment = next_segment + 1
285
+ combined_segment = combined_segment.append(next_segment, crossfade=variation_crossfade_duration)
286
+
287
+ # Post-process combined track
288
+ print("Post-processing final track...")
289
+ combined_segment = apply_eq(combined_segment)
290
+ combined_segment = apply_chorus(combined_segment)
291
+ combined_segment = apply_limiter(combined_segment, max_db=-6.0)
292
+ combined_segment = combined_segment.normalize(headroom=-9.0)
293
+ combined_segment = apply_final_gain(combined_segment, target_db=-18.0)
294
+
295
+ mp3_path = "output_cleaned.mp3"
296
+ combined_segment.export(
297
+ mp3_path,
298
+ format="mp3",
299
+ bitrate="320k",
300
+ tags={"title": "GhostAI Instrumental", "artist": "GhostAI"}
301
+ )
302
+ print(f"Saved final audio to {mp3_path}")
303
+ output_files.append(mp3_path)
304
 
305
  print_resource_usage("After Final Generation")
306
  print(f"Total Generation Time: {time.time() - start_time:.2f} seconds")
307
 
308
+ # Return the combined track for Gradio display
309
+ return mp3_path, f"✅ Done! Generated {num_variations} variations."
310
  except Exception as e:
311
  return None, f"❌ Generation failed: {e}"
312
  finally:
313
  torch.cuda.empty_cache()
314
  gc.collect()
315
 
316
+ # Function to toggle interactivity of chunk-related sliders
317
+ def toggle_chunk_interactivity(use_chunks):
318
+ return (
319
+ gr.update(interactive=use_chunks), # crossfade_duration
320
+ gr.update(interactive=use_chunks), # variation_crossfade_duration
321
+ gr.update(interactive=use_chunks) # chunk_count
322
+ )
323
 
324
  def clear_inputs():
325
+ return "", 3.0, 250, 0.9, 1.0, 30, 1000, 1000, 1, 2, True, 120
326
 
327
  # 7) CUSTOM CSS
328
  css = """
 
466
  info="Total duration of the track (10 to 90 seconds)."
467
  )
468
  crossfade_duration = gr.Slider(
469
+ label="Chunk Crossfade Duration (ms)",
470
  minimum=100,
471
  maximum=2000,
472
+ value=1000,
473
  step=100,
474
  info="Crossfade duration between chunks (only used if chunking is enabled)."
475
  )
476
+ variation_crossfade_duration = gr.Slider(
477
+ label="Variation Crossfade Duration (ms)",
478
+ minimum=100,
479
+ maximum=2000,
480
+ value=1000,
481
+ step=100,
482
+ info="Crossfade duration between variations (only used if chunking is enabled)."
483
+ )
484
  num_variations = gr.Slider(
485
  label="Number of Variations",
486
  minimum=1,
 
489
  step=1,
490
  info="Number of different versions to generate with varying random seeds."
491
  )
492
+ chunk_count = gr.Slider(
493
+ label="Chunk Count",
494
+ minimum=1,
495
+ maximum=8,
496
+ value=2,
497
+ step=1,
498
+ info="Number of chunks to split the track into (only used if chunking is enabled)."
499
+ )
500
  use_chunks = gr.Checkbox(
501
  label="Generate in Chunks",
502
  value=True,
503
+ info="Enable to generate in chunks (safer for GPU memory). Disable for single-shot generation (higher VRAM usage)."
504
+ )
505
+ bpm = gr.Slider(
506
+ label="Tempo (BPM)",
507
+ minimum=60,
508
+ maximum=180,
509
+ value=120,
510
+ step=1,
511
+ info="Beats per minute to influence the track's tempo."
512
  )
513
  with gr.Row(elem_classes="action-buttons"):
514
  gen_btn = gr.Button("Generate Music")
 
518
  out_audio = gr.Audio(label="Generated Stereo Instrumental Track", type="filepath")
519
  status = gr.Textbox(label="Status", interactive=False)
520
 
521
+ # Toggle chunk-related sliders' interactivity
522
+ use_chunks.change(
523
+ fn=toggle_chunk_interactivity,
524
+ inputs=use_chunks,
525
+ outputs=[crossfade_duration, variation_crossfade_duration, chunk_count]
526
+ )
527
+
528
+ # Bind genre buttons with BPM
529
+ rhcp_btn.click(set_red_hot_chili_peppers_prompt, inputs=bpm, outputs=instrumental_prompt)
530
+ nirvana_btn.click(set_nirvana_grunge_prompt, inputs=bpm, outputs=instrumental_prompt)
531
+ pearl_jam_btn.click(set_pearl_jam_grunge_prompt, inputs=bpm, outputs=instrumental_prompt)
532
+ soundgarden_btn.click(set_soundgarden_grunge_prompt, inputs=bpm, outputs=instrumental_prompt)
533
+ foo_fighters_btn.click(set_foo_fighters_prompt, inputs=bpm, outputs=instrumental_prompt)
534
+ smashing_pumpkins_btn.click(set_smashing_pumpkins_prompt, inputs=bpm, outputs=instrumental_prompt)
535
+ radiohead_btn.click(set_radiohead_prompt, inputs=bpm, outputs=instrumental_prompt)
536
+ classic_rock_btn.click(set_classic_rock_prompt, inputs=bpm, outputs=instrumental_prompt)
537
+ alternative_rock_btn.click(set_alternative_rock_prompt, inputs=bpm, outputs=instrumental_prompt)
538
+ post_punk_btn.click(set_post_punk_prompt, inputs=bpm, outputs=instrumental_prompt)
539
+ indie_rock_btn.click(set_indie_rock_prompt, inputs=bpm, outputs=instrumental_prompt)
540
+ funk_rock_btn.click(set_funk_rock_prompt, inputs=bpm, outputs=instrumental_prompt)
541
+ detroit_techno_btn.click(set_detroit_techno_prompt, inputs=bpm, outputs=instrumental_prompt)
542
+ deep_house_btn.click(set_deep_house_prompt, inputs=bpm, outputs=instrumental_prompt)
543
  gen_btn.click(
544
  generate_music,
545
+ inputs=[instrumental_prompt, cfg_scale, top_k, top_p, temperature, total_duration, crossfade_duration, variation_crossfade_duration, num_variations, chunk_count, use_chunks, bpm],
546
  outputs=[out_audio, status]
547
  )
548
  clr_btn.click(
549
  clear_inputs,
550
  inputs=None,
551
+ outputs=[instrumental_prompt, cfg_scale, top_k, top_p, temperature, total_duration, crossfade_duration, variation_crossfade_duration, num_variations, chunk_count, use_chunks, bpm]
552
  )
553
 
554
  # 9) TURN OFF OPENAPI/DOCS