Create 8bitapp.py
Browse files- 8bitapp.py +690 -0
8bitapp.py
ADDED
|
@@ -0,0 +1,690 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import torch
|
| 3 |
+
import torchaudio
|
| 4 |
+
import psutil
|
| 5 |
+
import time
|
| 6 |
+
import sys
|
| 7 |
+
import numpy as np
|
| 8 |
+
import gc
|
| 9 |
+
import gradio as gr
|
| 10 |
+
from pydub import AudioSegment
|
| 11 |
+
from audiocraft.models import MusicGen
|
| 12 |
+
from torch.cuda.amp import autocast
|
| 13 |
+
import warnings
|
| 14 |
+
import random
|
| 15 |
+
from bitsandbytes.nn import Linear8bitLt
|
| 16 |
+
from transformers import AutoModel
|
| 17 |
+
|
| 18 |
+
# Suppress warnings for cleaner output
|
| 19 |
+
warnings.filterwarnings("ignore")
|
| 20 |
+
|
| 21 |
+
# Set PYTORCH_CUDA_ALLOC_CONF to manage memory fragmentation
|
| 22 |
+
os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "max_split_size_mb:128"
|
| 23 |
+
|
| 24 |
+
# Check critical dependencies
|
| 25 |
+
if np.__version__ != "1.23.5":
|
| 26 |
+
print(f"WARNING: NumPy version {np.__version__} is being used. Tested with numpy==1.23.5.")
|
| 27 |
+
if not torch.__version__.startswith(("2.1.0", "2.3.1")):
|
| 28 |
+
print(f"WARNING: PyTorch version {torch.__version__} may not be compatible. Expected torch==2.1.0 or 2.3.1.")
|
| 29 |
+
|
| 30 |
+
# 1) DEVICE SETUP
|
| 31 |
+
device = "cuda" if torch.cuda.is_available() else "cpu"
|
| 32 |
+
if device != "cuda":
|
| 33 |
+
print("ERROR: CUDA is required for GPU rendering. CPU rendering is disabled.")
|
| 34 |
+
sys.exit(1)
|
| 35 |
+
print(f"CUDA is available. Using GPU: {torch.cuda.get_device_name(0)}")
|
| 36 |
+
|
| 37 |
+
# Pre-run memory cleanup
|
| 38 |
+
torch.cuda.empty_cache()
|
| 39 |
+
gc.collect()
|
| 40 |
+
torch.cuda.ipc_collect()
|
| 41 |
+
torch.cuda.synchronize()
|
| 42 |
+
|
| 43 |
+
# 2) LOAD MUSICGEN WITH 8-BIT QUANTIZATION
|
| 44 |
+
try:
|
| 45 |
+
print("Loading MusicGen medium model with 8-bit quantization into VRAM...")
|
| 46 |
+
local_model_path = "./models/musicgen-medium"
|
| 47 |
+
if not os.path.exists(local_model_path):
|
| 48 |
+
print(f"ERROR: Local model path {local_model_path} does not exist.")
|
| 49 |
+
print("Please download the MusicGen medium model weights and place them in the correct directory.")
|
| 50 |
+
sys.exit(1)
|
| 51 |
+
|
| 52 |
+
# Load MusicGen model in FP16
|
| 53 |
+
musicgen_model = MusicGen.get_pretrained(local_model_path, device=device)
|
| 54 |
+
|
| 55 |
+
# Apply 8-bit quantization to linear layers
|
| 56 |
+
def quantize_to_8bit(model):
|
| 57 |
+
for name, module in model.named_modules():
|
| 58 |
+
if isinstance(module, torch.nn.Linear):
|
| 59 |
+
# Replace with 8-bit linear layer
|
| 60 |
+
parent = model
|
| 61 |
+
for part in name.split('.')[:-1]:
|
| 62 |
+
parent = getattr(parent, part)
|
| 63 |
+
setattr(parent, name.split('.')[-1], Linear8bitLt(
|
| 64 |
+
module.in_features,
|
| 65 |
+
module.out_features,
|
| 66 |
+
bias=module.bias is not None,
|
| 67 |
+
has_fp16_weights=False,
|
| 68 |
+
threshold=6.0
|
| 69 |
+
))
|
| 70 |
+
return model
|
| 71 |
+
|
| 72 |
+
# Quantize the model (apply to relevant transformer layers)
|
| 73 |
+
musicgen_model = quantize_to_8bit(musicgen_model)
|
| 74 |
+
musicgen_model.to(device)
|
| 75 |
+
|
| 76 |
+
# Set generation parameters
|
| 77 |
+
musicgen_model.set_generation_params(
|
| 78 |
+
duration=10, # Default chunk duration
|
| 79 |
+
two_step_cfg=False # Disable two-step CFG for stability
|
| 80 |
+
)
|
| 81 |
+
print("Model successfully quantized to 8-bit and loaded.")
|
| 82 |
+
except Exception as e:
|
| 83 |
+
print(f"ERROR: Failed to load or quantize MusicGen model: {e}")
|
| 84 |
+
print("Ensure model weights and bitsandbytes are installed correctly.")
|
| 85 |
+
sys.exit(1)
|
| 86 |
+
|
| 87 |
+
# 3) RESOURCE MONITORING FUNCTION
|
| 88 |
+
def print_resource_usage(stage: str):
|
| 89 |
+
"""Log GPU and CPU resource usage at a given stage."""
|
| 90 |
+
print(f"--- {stage} ---")
|
| 91 |
+
print(f"GPU Memory Allocated: {torch.cuda.memory_allocated() / (1024**3):.2f} GB")
|
| 92 |
+
print(f"GPU Memory Reserved: {torch.cuda.memory_reserved() / (1024**3):.2f} GB")
|
| 93 |
+
print(f"CPU Memory Used: {psutil.virtual_memory().percent}%")
|
| 94 |
+
print("---------------")
|
| 95 |
+
|
| 96 |
+
# Check available GPU memory
|
| 97 |
+
def check_vram_availability(required_gb=3.5):
|
| 98 |
+
"""Check if sufficient VRAM is available for audio generation."""
|
| 99 |
+
total_vram = torch.cuda.get_device_properties(0).total_memory / (1024**3)
|
| 100 |
+
allocated_vram = torch.cuda.memory_allocated() / (1024**3)
|
| 101 |
+
available_vram = total_vram - allocated_vram
|
| 102 |
+
if available_vram < required_gb:
|
| 103 |
+
print(f"WARNING: Low VRAM available ({available_vram:.2f} GB). Reduce total_duration or chunk_duration.")
|
| 104 |
+
return available_vram >= required_gb
|
| 105 |
+
|
| 106 |
+
# 4) GENRE PROMPT FUNCTIONS
|
| 107 |
+
def set_red_hot_chili_peppers_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
|
| 108 |
+
"""Generate a Red Hot Chili Peppers-inspired funk rock prompt."""
|
| 109 |
+
rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("strong rhythmic steps" if bpm > 120 else "groovy rhythmic flow")
|
| 110 |
+
drum = f", {drum_beat} drums" if drum_beat != "none" else ""
|
| 111 |
+
synth = f", {synthesizer} accents" if synthesizer != "none" else ""
|
| 112 |
+
bass = f", {bass_style}" if bass_style != "none" else ", groovy basslines"
|
| 113 |
+
guitar = f", {guitar_style} guitar riffs" if guitar_style != "none" else ", syncopated guitar riffs"
|
| 114 |
+
return f"Instrumental funk rock{bass}{guitar}{drum}{synth}, Red Hot Chili Peppers-inspired vibe with dynamic energy and funky breakdowns, {rhythm} at {bpm} BPM."
|
| 115 |
+
|
| 116 |
+
def set_nirvana_grunge_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
|
| 117 |
+
"""Generate a Nirvana-inspired grunge prompt."""
|
| 118 |
+
rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("intense rhythmic steps" if bpm > 120 else "grungy rhythmic pulse")
|
| 119 |
+
drum = f", {drum_beat} drums" if drum_beat != "none" else ""
|
| 120 |
+
synth = f", {synthesizer} accents" if synthesizer != "none" else ""
|
| 121 |
+
bass = f", {bass_style}" if bass_style != "none" else ", melodic basslines"
|
| 122 |
+
guitar = f", {guitar_style} guitar riffs" if guitar_style != "none" else ", raw distorted guitar riffs"
|
| 123 |
+
return f"Instrumental grunge{bass}{guitar}{drum}{synth}, Nirvana-inspired angst-filled sound with quiet-loud dynamics, {rhythm} at {bpm} BPM."
|
| 124 |
+
|
| 125 |
+
def set_pearl_jam_grunge_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
|
| 126 |
+
"""Generate a Pearl Jam-inspired grunge prompt."""
|
| 127 |
+
rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("soulful rhythmic steps" if bpm > 120 else "driving rhythmic flow")
|
| 128 |
+
drum = f", {drum_beat} drums" if drum_beat != "none" else ""
|
| 129 |
+
synth = f", {synthesizer} accents" if synthesizer != "none" else ""
|
| 130 |
+
bass = f", {bass_style}" if bass_style != "none" else ", deep bass"
|
| 131 |
+
guitar = f", {guitar_style} guitar leads" if guitar_style != "none" else ", soulful guitar leads"
|
| 132 |
+
return f"Instrumental grunge{bass}{guitar}{drum}{synth}, Pearl Jam-inspired emotional intensity with soaring choruses, {rhythm} at {bpm} BPM."
|
| 133 |
+
|
| 134 |
+
def set_soundgarden_grunge_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
|
| 135 |
+
"""Generate a Soundgarden-inspired grunge prompt."""
|
| 136 |
+
rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("heavy rhythmic steps" if bpm > 120 else "sludgy rhythmic groove")
|
| 137 |
+
drum = f", {drum_beat} drums" if drum_beat != "none" else ""
|
| 138 |
+
synth = f", {synthesizer} accents" if synthesizer != "none" else ""
|
| 139 |
+
bass = f", {bass_style}" if bass_style != "none" else ""
|
| 140 |
+
guitar = f", {guitar_style} guitar riffs" if guitar_style != "none" else ", heavy sludgy guitar riffs"
|
| 141 |
+
return f"Instrumental grunge{bass}{guitar}{drum}{synth}, Soundgarden-inspired dark, psychedelic edge, {rhythm} at {bpm} BPM."
|
| 142 |
+
|
| 143 |
+
def set_foo_fighters_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
|
| 144 |
+
"""Generate a Foo Fighters-inspired alternative rock prompt."""
|
| 145 |
+
styles = ["anthemic", "gritty", "melodic", "fast-paced", "driving"]
|
| 146 |
+
tempos = ["upbeat", "mid-tempo", "high-energy"]
|
| 147 |
+
moods = ["energetic", "introspective", "rebellious", "uplifting"]
|
| 148 |
+
style = random.choice(styles)
|
| 149 |
+
tempo = random.choice(tempos)
|
| 150 |
+
mood = random.choice(moods)
|
| 151 |
+
rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("powerful rhythmic steps" if bpm > 120 else "catchy rhythmic groove")
|
| 152 |
+
drum = f", {drum_beat} drums" if drum_beat != "none" else ""
|
| 153 |
+
synth = f", {synthesizer} accents" if synthesizer != "none" else ""
|
| 154 |
+
bass = f", {bass_style}" if bass_style != "none" else ""
|
| 155 |
+
guitar = f", {guitar_style} guitar riffs" if guitar_style != "none" else f", {style} guitar riffs"
|
| 156 |
+
return f"Instrumental alternative rock{bass}{guitar}{drum}{synth}, Foo Fighters-inspired {mood} vibe with powerful choruses, {rhythm} at {bpm} BPM."
|
| 157 |
+
|
| 158 |
+
def set_smashing_pumpkins_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
|
| 159 |
+
"""Generate a Smashing Pumpkins-inspired alternative rock prompt."""
|
| 160 |
+
rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("dynamic rhythmic steps" if bpm > 120 else "dreamy rhythmic flow")
|
| 161 |
+
drum = f", {drum_beat} drums" if drum_beat != "none" else ""
|
| 162 |
+
synth = f", {synthesizer} accents" if synthesizer != "none" else ""
|
| 163 |
+
bass = f", {bass_style}" if bass_style != "none" else ""
|
| 164 |
+
guitar = f", {guitar_style} guitar textures" if guitar_style != "none" else ", dreamy guitar textures"
|
| 165 |
+
return f"Instrumental alternative rock{bass}{guitar}{drum}{synth}, Smashing Pumpkins-inspired blend of melancholy and aggression, {rhythm} at {bpm} BPM."
|
| 166 |
+
|
| 167 |
+
def set_radiohead_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
|
| 168 |
+
"""Generate a Radiohead-inspired experimental rock prompt."""
|
| 169 |
+
rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("complex rhythmic steps" if bpm > 120 else "intricate rhythmic pulse")
|
| 170 |
+
drum = f", {drum_beat} drums" if drum_beat != "none" else ""
|
| 171 |
+
synth = f", {synthesizer} accents" if synthesizer != "none" else ", atmospheric synths"
|
| 172 |
+
bass = f", {bass_style}" if bass_style != "none" else ""
|
| 173 |
+
guitar = f", {guitar_style} guitar layers" if guitar_style != "none" else ", intricate guitar layers"
|
| 174 |
+
return f"Instrumental experimental rock{bass}{guitar}{drum}{synth}, Radiohead-inspired blend of introspective and innovative soundscapes, {rhythm} at {bpm} BPM."
|
| 175 |
+
|
| 176 |
+
def set_classic_rock_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
|
| 177 |
+
"""Generate a Led Zeppelin-inspired classic rock prompt."""
|
| 178 |
+
rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("bluesy rhythmic steps" if bpm > 120 else "steady rhythmic groove")
|
| 179 |
+
drum = f", {drum_beat} drums" if drum_beat != "none" else ""
|
| 180 |
+
synth = f", {synthesizer} accents" if synthesizer != "none" else ""
|
| 181 |
+
bass = f", {bass_style}" if bass_style != "none" else ", groovy bass"
|
| 182 |
+
guitar = f", {guitar_style} electric guitars" if guitar_style != "none" else ", bluesy electric guitars"
|
| 183 |
+
return f"Instrumental classic rock{bass}{guitar}{drum}{synth}, Led Zeppelin-inspired raw energy with dynamic solos, {rhythm} at {bpm} BPM."
|
| 184 |
+
|
| 185 |
+
def set_alternative_rock_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
|
| 186 |
+
"""Generate a Pixies-inspired alternative rock prompt."""
|
| 187 |
+
rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("quirky rhythmic steps" if bpm > 120 else "energetic rhythmic flow")
|
| 188 |
+
drum = f", {drum_beat} drums" if drum_beat != "none" else ""
|
| 189 |
+
synth = f", {synthesizer} accents" if synthesizer != "none" else ""
|
| 190 |
+
bass = f", {bass_style}" if bass_style != "none" else ", melodic basslines"
|
| 191 |
+
guitar = f", {guitar_style} guitar riffs" if guitar_style != "none" else ", distorted guitar riffs"
|
| 192 |
+
return f"Instrumental alternative rock{bass}{guitar}{drum}{synth}, Pixies-inspired quirky, energetic vibe, {rhythm} at {bpm} BPM."
|
| 193 |
+
|
| 194 |
+
def set_post_punk_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
|
| 195 |
+
"""Generate a Joy Division-inspired post-punk prompt."""
|
| 196 |
+
rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("sharp rhythmic steps" if bpm > 120 else "moody rhythmic pulse")
|
| 197 |
+
drum = f", {drum_beat} drums" if drum_beat != "none" else ""
|
| 198 |
+
synth = f", {synthesizer} accents" if synthesizer != "none" else ""
|
| 199 |
+
bass = f", {bass_style}" if bass_style != "none" else ", driving basslines"
|
| 200 |
+
guitar = f", {guitar_style} guitars" if guitar_style != "none" else ", jangly guitars"
|
| 201 |
+
return f"Instrumental post-punk{bass}{guitar}{drum}{synth}, Joy Division-inspired moody, atmospheric sound, {rhythm} at {bpm} BPM."
|
| 202 |
+
|
| 203 |
+
def set_indie_rock_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
|
| 204 |
+
"""Generate an Arctic Monkeys-inspired indie rock prompt."""
|
| 205 |
+
rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("catchy rhythmic steps" if bpm > 120 else "jangly rhythmic flow")
|
| 206 |
+
drum = f", {drum_beat} drums" if drum_beat != "none" else ""
|
| 207 |
+
synth = f", {synthesizer} accents" if synthesizer != "none" else ""
|
| 208 |
+
bass = f", {bass_style}" if bass_style != "none" else ""
|
| 209 |
+
guitar = f", {guitar_style} guitars" if guitar_style != "none" else ", jangly guitars"
|
| 210 |
+
return f"Instrumental indie rock{bass}{guitar}{drum}{synth}, Arctic Monkeys-inspired blend of catchy riffs, {rhythm} at {bpm} BPM."
|
| 211 |
+
|
| 212 |
+
def set_funk_rock_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
|
| 213 |
+
"""Generate a Rage Against the Machine-inspired funk rock prompt."""
|
| 214 |
+
rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("aggressive rhythmic steps" if bpm > 120 else "funky rhythmic groove")
|
| 215 |
+
drum = f", {drum_beat} drums" if drum_beat != "none" else ""
|
| 216 |
+
synth = f", {synthesizer} accents" if synthesizer != "none" else ""
|
| 217 |
+
bass = f", {bass_style}" if bass_style != "none" else ", slap bass"
|
| 218 |
+
guitar = f", {guitar_style} guitar chords" if guitar_style != "none" else ", funky guitar chords"
|
| 219 |
+
return f"Instrumental funk rock{bass}{guitar}{drum}{synth}, Rage Against the Machine-inspired mix of groove and aggression, {rhythm} at {bpm} BPM."
|
| 220 |
+
|
| 221 |
+
def set_detroit_techno_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
|
| 222 |
+
"""Generate a Juan Atkins-inspired Detroit techno prompt."""
|
| 223 |
+
rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("pulsing rhythmic steps" if bpm > 120 else "deep rhythmic groove")
|
| 224 |
+
drum = f", {drum_beat} drums" if drum_beat != "none" else ", crisp hi-hats"
|
| 225 |
+
synth = f", {synthesizer} accents" if synthesizer != "none" else ", deep pulsing synths"
|
| 226 |
+
bass = f", {bass_style}" if bass_style != "none" else ", driving basslines"
|
| 227 |
+
guitar = f", {guitar_style} guitars" if guitar_style != "none" else ""
|
| 228 |
+
return f"Instrumental Detroit techno{bass}{guitar}{drum}{synth}, Juan Atkins-inspired rhythmic groove, {rhythm} at {bpm} BPM."
|
| 229 |
+
|
| 230 |
+
def set_deep_house_prompt(bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style):
|
| 231 |
+
"""Generate a Larry Heard-inspired deep house prompt."""
|
| 232 |
+
rhythm = f" with {rhythmic_steps}" if rhythmic_steps != "none" else ("soulful rhythmic steps" if bpm > 120 else "laid-back rhythmic flow")
|
| 233 |
+
drum = f", {drum_beat} drums" if drum_beat != "none" else ""
|
| 234 |
+
synth = f", {synthesizer} accents" if synthesizer != "none" else ", warm analog synth chords"
|
| 235 |
+
bass = f", {bass_style}" if bass_style != "none" else ", deep basslines"
|
| 236 |
+
guitar = f", {guitar_style} guitars" if guitar_style != "none" else ""
|
| 237 |
+
return f"Instrumental deep house{bass}{guitar}{drum}{synth}, Larry Heard-inspired laid-back groove, {rhythm} at {bpm} BPM."
|
| 238 |
+
|
| 239 |
+
# 5) AUDIO PROCESSING FUNCTIONS
|
| 240 |
+
def apply_eq(segment):
|
| 241 |
+
"""Apply basic equalization to the audio segment."""
|
| 242 |
+
# Low-pass filter to cut high frequencies above 8kHz
|
| 243 |
+
segment = segment.low_pass_filter(8000)
|
| 244 |
+
# High-pass filter to cut low frequencies below 80Hz
|
| 245 |
+
segment = segment.high_pass_filter(80)
|
| 246 |
+
return segment
|
| 247 |
+
|
| 248 |
+
def apply_fade(segment, fade_in_duration=1000, fade_out_duration=1000):
|
| 249 |
+
"""Apply fade-in and fade-out effects to the audio segment."""
|
| 250 |
+
segment = segment.fade_in(fade_in_duration)
|
| 251 |
+
segment = segment.fade_out(fade_out_duration)
|
| 252 |
+
return segment
|
| 253 |
+
|
| 254 |
+
# 6) GENERATION & I/O FUNCTIONS
|
| 255 |
+
def generate_music(instrumental_prompt: str, cfg_scale: float, top_k: int, top_p: float, temperature: float, total_duration: int, chunk_duration: int, crossfade_duration: int, bpm: int, drum_beat: str, synthesizer: str, rhythmic_steps: str, bass_style: str, guitar_style: str):
|
| 256 |
+
"""Generate instrumental audio with 8-bit quantized model, ensuring controlled volume."""
|
| 257 |
+
global musicgen_model
|
| 258 |
+
# Validate input prompt
|
| 259 |
+
if not instrumental_prompt.strip():
|
| 260 |
+
return None, "β οΈ Please enter a valid instrumental prompt!"
|
| 261 |
+
|
| 262 |
+
try:
|
| 263 |
+
start_time = time.time()
|
| 264 |
+
|
| 265 |
+
# Validate total_duration (restricted to radio button choices)
|
| 266 |
+
if total_duration not in {30, 60, 90, 120}:
|
| 267 |
+
raise ValueError(f"Invalid total_duration: {total_duration}. Must be 30, 60, 90, or 120 seconds.")
|
| 268 |
+
|
| 269 |
+
# Clamp chunk_duration between 5 and 15 seconds
|
| 270 |
+
chunk_duration = min(max(chunk_duration, 5), 15)
|
| 271 |
+
num_chunks = max(1, total_duration // chunk_duration)
|
| 272 |
+
chunk_duration = total_duration / num_chunks # Adjust for even splitting
|
| 273 |
+
overlap_duration = min(1.0, crossfade_duration / 1000.0) # Convert ms to seconds, cap at 1s
|
| 274 |
+
generation_duration = chunk_duration + overlap_duration
|
| 275 |
+
|
| 276 |
+
# Validate sample rate from model
|
| 277 |
+
sample_rate = getattr(musicgen_model, 'sample_rate', None)
|
| 278 |
+
if not isinstance(sample_rate, int) or sample_rate <= 0:
|
| 279 |
+
raise ValueError("Invalid sample_rate from musicgen_model.")
|
| 280 |
+
|
| 281 |
+
audio_segments = []
|
| 282 |
+
|
| 283 |
+
# Check VRAM availability (increased to 4.0GB due to 8-bit quantization)
|
| 284 |
+
if not check_vram_availability(required_gb=4.0):
|
| 285 |
+
return None, "β οΈ Insufficient VRAM for generation. Reduce total_duration or chunk_duration."
|
| 286 |
+
|
| 287 |
+
print("Generating audio with 8-bit quantized model...")
|
| 288 |
+
seed = 42 # Fixed seed for reproducibility
|
| 289 |
+
torch.manual_seed(seed)
|
| 290 |
+
np.random.seed(seed)
|
| 291 |
+
|
| 292 |
+
# Generate audio chunks
|
| 293 |
+
for i in range(num_chunks):
|
| 294 |
+
chunk_prompt = instrumental_prompt
|
| 295 |
+
print(f"Generating chunk {i+1}/{num_chunks} on GPU (prompt: {chunk_prompt})...")
|
| 296 |
+
|
| 297 |
+
# Set model generation parameters
|
| 298 |
+
musicgen_model.set_generation_params(
|
| 299 |
+
duration=generation_duration,
|
| 300 |
+
use_sampling=True,
|
| 301 |
+
top_k=top_k,
|
| 302 |
+
top_p=top_p,
|
| 303 |
+
temperature=temperature,
|
| 304 |
+
cfg_coef=cfg_scale
|
| 305 |
+
)
|
| 306 |
+
|
| 307 |
+
print_resource_usage(f"Before Chunk {i+1} Generation")
|
| 308 |
+
|
| 309 |
+
# Generate audio with mixed precision
|
| 310 |
+
with torch.no_grad():
|
| 311 |
+
with autocast():
|
| 312 |
+
audio_chunk = musicgen_model.generate([chunk_prompt], progress=True)[0]
|
| 313 |
+
|
| 314 |
+
# Move to CPU and ensure float32 dtype
|
| 315 |
+
audio_chunk = audio_chunk.cpu().to(dtype=torch.float32)
|
| 316 |
+
|
| 317 |
+
# Ensure audio is stereo (2 channels)
|
| 318 |
+
if audio_chunk.dim() == 1:
|
| 319 |
+
audio_chunk = torch.stack([audio_chunk, audio_chunk], dim=0)
|
| 320 |
+
elif audio_chunk.dim() == 2 and audio_chunk.shape[0] == 1:
|
| 321 |
+
audio_chunk = torch.cat([audio_chunk, audio_chunk], dim=0)
|
| 322 |
+
elif audio_chunk.dim() == 2 and audio_chunk.shape[0] != 2:
|
| 323 |
+
audio_chunk = audio_chunk[:1, :]
|
| 324 |
+
audio_chunk = torch.cat([audio_chunk, audio_chunk], dim=0)
|
| 325 |
+
elif audio_chunk.dim() > 2:
|
| 326 |
+
audio_chunk = audio_chunk.view(2, -1)
|
| 327 |
+
|
| 328 |
+
# Strict validation of audio shape
|
| 329 |
+
if audio_chunk.dim() != 2 or audio_chunk.shape[0] != 2:
|
| 330 |
+
raise ValueError(f"Chunk {i+1}: Expected stereo audio with shape (2, samples), got {audio_chunk.shape}")
|
| 331 |
+
|
| 332 |
+
# Save temporary WAV file and load with pydub
|
| 333 |
+
temp_wav_path = f"temp_chunk_{i}.wav"
|
| 334 |
+
torchaudio.save(temp_wav_path, audio_chunk, sample_rate, bits_per_sample=24)
|
| 335 |
+
segment = AudioSegment.from_wav(temp_wav_path)
|
| 336 |
+
os.remove(temp_wav_path)
|
| 337 |
+
audio_segments.append(segment)
|
| 338 |
+
|
| 339 |
+
# Clean up GPU memory
|
| 340 |
+
torch.cuda.empty_cache()
|
| 341 |
+
gc.collect()
|
| 342 |
+
torch.cuda.ipc_collect()
|
| 343 |
+
torch.cuda.synchronize()
|
| 344 |
+
time.sleep(0.5) # Brief pause to stabilize resources
|
| 345 |
+
print_resource_usage(f"After Chunk {i+1} Generation")
|
| 346 |
+
|
| 347 |
+
# Combine audio chunks
|
| 348 |
+
print("Combining audio chunks...")
|
| 349 |
+
if not audio_segments:
|
| 350 |
+
raise ValueError("No audio segments generated.")
|
| 351 |
+
|
| 352 |
+
final_segment = audio_segments[0]
|
| 353 |
+
for i in range(1, len(audio_segments)):
|
| 354 |
+
next_segment = audio_segments[i]
|
| 355 |
+
next_segment = next_segment + 1 # Adjust amplitude if needed
|
| 356 |
+
final_segment = final_segment.append(next_segment, crossfade=crossfade_duration)
|
| 357 |
+
|
| 358 |
+
# Trim to exact total duration
|
| 359 |
+
final_segment = final_segment[:total_duration * 1000]
|
| 360 |
+
|
| 361 |
+
# Post-processing
|
| 362 |
+
print("Post-processing final track...")
|
| 363 |
+
final_segment = apply_eq(final_segment)
|
| 364 |
+
|
| 365 |
+
# Volume adjustment: Set peak to -12 dBFS (significantly quieter than 0 dBFS)
|
| 366 |
+
desired_peak = -12.0 # Target peak level in dBFS
|
| 367 |
+
if not isinstance(desired_peak, (int, float)) or desired_peak >= 0:
|
| 368 |
+
raise ValueError(f"Invalid desired_peak: {desired_peak}. Must be negative dBFS.")
|
| 369 |
+
|
| 370 |
+
current_peak = final_segment.max_dBFS
|
| 371 |
+
if current_peak is None or not isinstance(current_peak, (int, float)):
|
| 372 |
+
raise ValueError("Failed to compute current peak level.")
|
| 373 |
+
|
| 374 |
+
print(f"Current peak level: {current_peak:.2f} dBFS")
|
| 375 |
+
gain_needed = desired_peak - current_peak
|
| 376 |
+
|
| 377 |
+
# Validate gain adjustment
|
| 378 |
+
if not -100 <= gain_needed <= 100: # Reasonable range to prevent extreme adjustments
|
| 379 |
+
raise ValueError(f"Gain adjustment out of bounds: {gain_needed} dB")
|
| 380 |
+
|
| 381 |
+
print(f"Applying gain adjustment: {gain_needed:.2f} dB")
|
| 382 |
+
final_segment = final_segment.apply_gain(gain_needed)
|
| 383 |
+
|
| 384 |
+
# Verify new peak level
|
| 385 |
+
new_peak = final_segment.max_dBFS
|
| 386 |
+
if new_peak is None or not isinstance(new_peak, (int, float)):
|
| 387 |
+
raise ValueError("Failed to compute new peak level after gain adjustment.")
|
| 388 |
+
|
| 389 |
+
print(f"New peak level: {new_peak:.2f} dBFS")
|
| 390 |
+
|
| 391 |
+
# Check if new peak is within 0.1 dB of desired peak
|
| 392 |
+
if abs(new_peak - desired_peak) > 0.1:
|
| 393 |
+
print(f"Warning: New peak {new_peak:.2f} dBFS deviates from desired {desired_peak:.2f} dBFS")
|
| 394 |
+
|
| 395 |
+
final_segment = apply_fade(final_segment)
|
| 396 |
+
|
| 397 |
+
# Export to MP3 (increased to 320kbps for higher quality)
|
| 398 |
+
mp3_path = "output_cleaned.mp3"
|
| 399 |
+
final_segment.export(
|
| 400 |
+
mp3_path,
|
| 401 |
+
format="mp3",
|
| 402 |
+
bitrate="320k", # Increased from 128k to 320k for better audio quality
|
| 403 |
+
tags={"title": "GhostAI Instrumental", "artist": "GhostAI"}
|
| 404 |
+
)
|
| 405 |
+
print(f"Saved final audio to {mp3_path}")
|
| 406 |
+
|
| 407 |
+
# Optional: Export to WAV for lossless quality (uncomment if desired)
|
| 408 |
+
# wav_path = "output_cleaned.wav"
|
| 409 |
+
# final_segment.export(wav_path, format="wav")
|
| 410 |
+
# print(f"Saved lossless audio to {wav_path}")
|
| 411 |
+
|
| 412 |
+
print_resource_usage("After Final Generation")
|
| 413 |
+
print(f"Total Generation Time: {time.time() - start_time:.2f} seconds")
|
| 414 |
+
|
| 415 |
+
return mp3_path, "β
Done! Generated instrumental audio."
|
| 416 |
+
|
| 417 |
+
except Exception as e:
|
| 418 |
+
print(f"Error during generation: {e}")
|
| 419 |
+
return None, f"β Generation failed: {e}"
|
| 420 |
+
|
| 421 |
+
finally:
|
| 422 |
+
# Clean up GPU memory
|
| 423 |
+
torch.cuda.empty_cache()
|
| 424 |
+
gc.collect()
|
| 425 |
+
torch.cuda.ipc_collect()
|
| 426 |
+
torch.cuda.synchronize()
|
| 427 |
+
|
| 428 |
+
# Function to clear inputs
|
| 429 |
+
def clear_inputs():
|
| 430 |
+
"""Reset all input fields to default values."""
|
| 431 |
+
return "", 3.0, 250, 0.9, 1.0, 30, 10, 1000, 120, "none", "none", "none", "none", "none"
|
| 432 |
+
|
| 433 |
+
# 7) CUSTOM CSS
|
| 434 |
+
css = """
|
| 435 |
+
body {
|
| 436 |
+
background: linear-gradient(135deg, #0A0A0A 0%, #1C2526 100%);
|
| 437 |
+
color: #E0E0E0;
|
| 438 |
+
font-family: 'Orbitron', sans-serif;
|
| 439 |
+
}
|
| 440 |
+
.header-container {
|
| 441 |
+
text-align: center;
|
| 442 |
+
padding: 10px 20px;
|
| 443 |
+
background: rgba(0, 0, 0, 0.9);
|
| 444 |
+
border-bottom: 1px solid #00FF9F;
|
| 445 |
+
}
|
| 446 |
+
#ghost-logo {
|
| 447 |
+
font-size: 40px;
|
| 448 |
+
animation: glitch-ghost 1.5s infinite;
|
| 449 |
+
}
|
| 450 |
+
h1 {
|
| 451 |
+
color: #A100FF;
|
| 452 |
+
font-size: 24px;
|
| 453 |
+
animation: glitch-text 2s infinite;
|
| 454 |
+
}
|
| 455 |
+
p {
|
| 456 |
+
color: #E0E0E0;
|
| 457 |
+
font-size: 12px;
|
| 458 |
+
}
|
| 459 |
+
.input-container, .settings-container, .output-container {
|
| 460 |
+
max-width: 1200px;
|
| 461 |
+
margin: 20px auto;
|
| 462 |
+
padding: 20px;
|
| 463 |
+
background: rgba(28, 37, 38, 0.8);
|
| 464 |
+
border-radius: 10px;
|
| 465 |
+
}
|
| 466 |
+
.textbox {
|
| 467 |
+
background: #1A1A1A;
|
| 468 |
+
border: 1px solid #A100FF;
|
| 469 |
+
color: #E0E0E0;
|
| 470 |
+
}
|
| 471 |
+
.genre-buttons {
|
| 472 |
+
display: flex;
|
| 473 |
+
justify-content: center;
|
| 474 |
+
flex-wrap: wrap;
|
| 475 |
+
gap: 15px;
|
| 476 |
+
}
|
| 477 |
+
.genre-btn, button {
|
| 478 |
+
background: linear-gradient(45deg, #A100FF, #00FF9F);
|
| 479 |
+
border: none;
|
| 480 |
+
color: #0A0A0A;
|
| 481 |
+
padding: 10px 20px;
|
| 482 |
+
border-radius: 5px;
|
| 483 |
+
}
|
| 484 |
+
.gradio-container {
|
| 485 |
+
padding: 20px;
|
| 486 |
+
}
|
| 487 |
+
.group-container {
|
| 488 |
+
margin-bottom: 20px;
|
| 489 |
+
padding: 15px;
|
| 490 |
+
border: 1px solid #00FF9F;
|
| 491 |
+
border-radius: 8px;
|
| 492 |
+
}
|
| 493 |
+
@keyframes glitch-ghost {
|
| 494 |
+
0% { transform: translate(0, 0); opacity: 1; }
|
| 495 |
+
20% { transform: translate(-5px, 2px); opacity: 0.8; }
|
| 496 |
+
100% { transform: translate(0, 0); opacity: 1; }
|
| 497 |
+
}
|
| 498 |
+
@keyframes glitch-text {
|
| 499 |
+
0% { transform: translate(0, 0); }
|
| 500 |
+
20% { transform: translate(-2px, 1px); }
|
| 501 |
+
100% { transform: translate(0, 0); }
|
| 502 |
+
}
|
| 503 |
+
@font-face {
|
| 504 |
+
font-family: 'Orbitron';
|
| 505 |
+
src: url('https://fonts.gstatic.com/s/orbitron/v29/yMJRMIlzdpvBhQQL_Qq7dy0.woff2') format('woff2');
|
| 506 |
+
}
|
| 507 |
+
"""
|
| 508 |
+
|
| 509 |
+
# 8) BUILD WITH BLOCKS
|
| 510 |
+
with gr.Blocks(css=css) as demo:
|
| 511 |
+
gr.Markdown("""
|
| 512 |
+
<div class="header-container">
|
| 513 |
+
<div id="ghost-logo">π»</div>
|
| 514 |
+
<h1>GhostAI Music Generator πΉ</h1>
|
| 515 |
+
<p>Summon the Sound of the Unknown</p>
|
| 516 |
+
</div>
|
| 517 |
+
""")
|
| 518 |
+
|
| 519 |
+
with gr.Column(elem_classes="input-container"):
|
| 520 |
+
gr.Markdown("### πΈ Prompt Settings")
|
| 521 |
+
instrumental_prompt = gr.Textbox(
|
| 522 |
+
label="Instrumental Prompt βοΈ",
|
| 523 |
+
placeholder="Click a genre button or type your own instrumental prompt",
|
| 524 |
+
lines=4,
|
| 525 |
+
elem_classes="textbox"
|
| 526 |
+
)
|
| 527 |
+
with gr.Row(elem_classes="genre-buttons"):
|
| 528 |
+
rhcp_btn = gr.Button("Red Hot Chili Peppers πΆοΈ", elem_classes="genre-btn")
|
| 529 |
+
nirvana_btn = gr.Button("Nirvana Grunge πΈ", elem_classes="genre-btn")
|
| 530 |
+
pearl_jam_btn = gr.Button("Pearl Jam Grunge π¦ͺ", elem_classes="genre-btn")
|
| 531 |
+
soundgarden_btn = gr.Button("Soundgarden Grunge π", elem_classes="genre-btn")
|
| 532 |
+
foo_fighters_btn = gr.Button("Foo Fighters π€", elem_classes="genre-btn")
|
| 533 |
+
smashing_pumpkins_btn = gr.Button("Smashing Pumpkins π", elem_classes="genre-btn")
|
| 534 |
+
radiohead_btn = gr.Button("Radiohead π§ ", elem_classes="genre-btn")
|
| 535 |
+
classic_rock_btn = gr.Button("Classic Rock πΈ", elem_classes="genre-btn")
|
| 536 |
+
alternative_rock_btn = gr.Button("Alternative Rock π΅", elem_classes="genre-btn")
|
| 537 |
+
post_punk_btn = gr.Button("Post-Punk π€", elem_classes="genre-btn")
|
| 538 |
+
indie_rock_btn = gr.Button("Indie Rock π€", elem_classes="genre-btn")
|
| 539 |
+
funk_rock_btn = gr.Button("Funk Rock πΊ", elem_classes="genre-btn")
|
| 540 |
+
detroit_techno_btn = gr.Button("Detroit Techno ποΈ", elem_classes="genre-btn")
|
| 541 |
+
deep_house_btn = gr.Button("Deep House π ", elem_classes="genre-btn")
|
| 542 |
+
|
| 543 |
+
with gr.Column(elem_classes="settings-container"):
|
| 544 |
+
gr.Markdown("### βοΈ API Settings")
|
| 545 |
+
with gr.Group(elem_classes="group-container"):
|
| 546 |
+
cfg_scale = gr.Slider(
|
| 547 |
+
label="CFG Scale π―",
|
| 548 |
+
minimum=1.0,
|
| 549 |
+
maximum=10.0,
|
| 550 |
+
value=3.0,
|
| 551 |
+
step=0.1,
|
| 552 |
+
info="Controls how closely the music follows the prompt."
|
| 553 |
+
)
|
| 554 |
+
top_k = gr.Slider(
|
| 555 |
+
label="Top-K Sampling π’",
|
| 556 |
+
minimum=10,
|
| 557 |
+
maximum=500,
|
| 558 |
+
value=250,
|
| 559 |
+
step=10,
|
| 560 |
+
info="Limits sampling to the top k most likely tokens."
|
| 561 |
+
)
|
| 562 |
+
top_p = gr.Slider(
|
| 563 |
+
label="Top-P Sampling π°",
|
| 564 |
+
minimum=0.0,
|
| 565 |
+
maximum=1.0,
|
| 566 |
+
value=0.9,
|
| 567 |
+
step=0.05,
|
| 568 |
+
info="Keeps tokens with cumulative probability above p."
|
| 569 |
+
)
|
| 570 |
+
temperature = gr.Slider(
|
| 571 |
+
label="Temperature π₯",
|
| 572 |
+
minimum=0.1,
|
| 573 |
+
maximum=2.0,
|
| 574 |
+
value=1.0,
|
| 575 |
+
step=0.1,
|
| 576 |
+
info="Controls randomness; higher values increase diversity."
|
| 577 |
+
)
|
| 578 |
+
total_duration = gr.Radio(
|
| 579 |
+
label="Song Length β³ (seconds)",
|
| 580 |
+
choices=[30, 60, 90, 120],
|
| 581 |
+
value=30,
|
| 582 |
+
info="Select the total duration of the track."
|
| 583 |
+
)
|
| 584 |
+
chunk_duration = gr.Slider(
|
| 585 |
+
label="Chunk Duration β±οΈ (seconds)",
|
| 586 |
+
minimum=5,
|
| 587 |
+
maximum=15,
|
| 588 |
+
value=10,
|
| 589 |
+
step=1,
|
| 590 |
+
info="Duration of each chunk to render (5 to 15 seconds)."
|
| 591 |
+
)
|
| 592 |
+
crossfade_duration = gr.Slider(
|
| 593 |
+
label="Crossfade Duration πΆ (ms)",
|
| 594 |
+
minimum=100,
|
| 595 |
+
maximum=2000,
|
| 596 |
+
value=1000,
|
| 597 |
+
step=100,
|
| 598 |
+
info="Crossfade duration between chunks."
|
| 599 |
+
)
|
| 600 |
+
|
| 601 |
+
gr.Markdown("### π΅ Musical Controls")
|
| 602 |
+
with gr.Group(elem_classes="group-container"):
|
| 603 |
+
bpm = gr.Slider(
|
| 604 |
+
label="Tempo π΅ (BPM)",
|
| 605 |
+
minimum=60,
|
| 606 |
+
maximum=180,
|
| 607 |
+
value=120,
|
| 608 |
+
step=1,
|
| 609 |
+
info="Beats per minute to set the track's tempo."
|
| 610 |
+
)
|
| 611 |
+
drum_beat = gr.Dropdown(
|
| 612 |
+
label="Drum Beat οΏ½οΏ½οΏ½οΏ½",
|
| 613 |
+
choices=["none", "standard rock", "funk groove", "techno kick", "jazz swing"],
|
| 614 |
+
value="none",
|
| 615 |
+
info="Select a drum beat style to influence the rhythm."
|
| 616 |
+
)
|
| 617 |
+
synthesizer = gr.Dropdown(
|
| 618 |
+
label="Synthesizer πΉ",
|
| 619 |
+
choices=["none", "analog synth", "digital pad", "arpeggiated synth"],
|
| 620 |
+
value="none",
|
| 621 |
+
info="Select a synthesizer style for electronic accents."
|
| 622 |
+
)
|
| 623 |
+
rhythmic_steps = gr.Dropdown(
|
| 624 |
+
label="Rhythmic Steps π£",
|
| 625 |
+
choices=["none", "syncopated steps", "steady steps", "complex steps"],
|
| 626 |
+
value="none",
|
| 627 |
+
info="Select a rhythmic step style to enhance the beat."
|
| 628 |
+
)
|
| 629 |
+
bass_style = gr.Dropdown(
|
| 630 |
+
label="Bass Style πΈ",
|
| 631 |
+
choices=["none", "slap bass", "deep bass", "melodic bass"],
|
| 632 |
+
value="none",
|
| 633 |
+
info="Select a bass style to shape the low end."
|
| 634 |
+
)
|
| 635 |
+
guitar_style = gr.Dropdown(
|
| 636 |
+
label="Guitar Style πΈ",
|
| 637 |
+
choices=["none", "distorted", "clean", "jangle"],
|
| 638 |
+
value="none",
|
| 639 |
+
info="Select a guitar style to define the riffs."
|
| 640 |
+
)
|
| 641 |
+
|
| 642 |
+
with gr.Row(elem_classes="action-buttons"):
|
| 643 |
+
gen_btn = gr.Button("Generate Music π")
|
| 644 |
+
clr_btn = gr.Button("Clear Inputs π§Ή")
|
| 645 |
+
|
| 646 |
+
with gr.Column(elem_classes="output-container"):
|
| 647 |
+
gr.Markdown("### π§ Output")
|
| 648 |
+
out_audio = gr.Audio(label="Generated Instrumental Track π΅", type="filepath")
|
| 649 |
+
status = gr.Textbox(label="Status π’", interactive=False)
|
| 650 |
+
|
| 651 |
+
rhcp_btn.click(set_red_hot_chili_peppers_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
|
| 652 |
+
nirvana_btn.click(set_nirvana_grunge_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
|
| 653 |
+
pearl_jam_btn.click(set_pearl_jam_grunge_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
|
| 654 |
+
soundgarden_btn.click(set_soundgarden_grunge_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
|
| 655 |
+
foo_fighters_btn.click(set_foo_fighters_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
|
| 656 |
+
smashing_pumpkins_btn.click(set_smashing_pumpkins_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
|
| 657 |
+
radiohead_btn.click(set_radiohead_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
|
| 658 |
+
classic_rock_btn.click(set_classic_rock_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
|
| 659 |
+
alternative_rock_btn.click(set_alternative_rock_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
|
| 660 |
+
post_punk_btn.click(set_post_punk_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
|
| 661 |
+
indie_rock_btn.click(set_indie_rock_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
|
| 662 |
+
funk_rock_btn.click(set_funk_rock_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
|
| 663 |
+
detroit_techno_btn.click(set_detroit_techno_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
|
| 664 |
+
deep_house_btn.click(set_deep_house_prompt, inputs=[bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style], outputs=instrumental_prompt)
|
| 665 |
+
gen_btn.click(
|
| 666 |
+
generate_music,
|
| 667 |
+
inputs=[instrumental_prompt, cfg_scale, top_k, top_p, temperature, total_duration, chunk_duration, crossfade_duration, bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style],
|
| 668 |
+
outputs=[out_audio, status]
|
| 669 |
+
)
|
| 670 |
+
clr_btn.click(
|
| 671 |
+
clear_inputs,
|
| 672 |
+
inputs=None,
|
| 673 |
+
outputs=[instrumental_prompt, cfg_scale, top_k, top_p, temperature, total_duration, chunk_duration, crossfade_duration, bpm, drum_beat, synthesizer, rhythmic_steps, bass_style, guitar_style]
|
| 674 |
+
)
|
| 675 |
+
|
| 676 |
+
# 9) TURN OFF OPENAPI/DOCS
|
| 677 |
+
app = demo.launch(
|
| 678 |
+
server_name="0.0.0.0",
|
| 679 |
+
server_port=9999,
|
| 680 |
+
share=True,
|
| 681 |
+
inbrowser=False,
|
| 682 |
+
show_error=True
|
| 683 |
+
)
|
| 684 |
+
try:
|
| 685 |
+
fastapi_app = demo._server.app
|
| 686 |
+
fastapi_app.docs_url = None
|
| 687 |
+
fastapi_app.redoc_url = None
|
| 688 |
+
fastapi_app.openapi_url = None
|
| 689 |
+
except Exception:
|
| 690 |
+
pass
|