File size: 10,948 Bytes
7998bb1 1571550 7998bb1 1571550 7998bb1 91902a5 7998bb1 91902a5 7998bb1 91902a5 7998bb1 1571550 7998bb1 91902a5 7998bb1 1571550 7998bb1 91902a5 7998bb1 91902a5 7998bb1 91902a5 7998bb1 1571550 7998bb1 1571550 7998bb1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | #!/usr/bin/env python3
"""
LYGO RESONANCE - Cloud App Interface (app.py)
Designed for Hugging Face Spaces SDK (Gradio).
Bridges the visual front-end directly to the Resonance Engine and Profile Generator.
"""
import gradio as gr
import os
import json
from pathlib import Path
from resonance_engine import ResonanceEngine, PRESETS
from lygo_profile import LYGOProfileGenerator
def process_image(image_path, engine_type, style, seed, duration, noise_filter,
export_stems, export_midi, export_brief, use_batch, batch_folder,
# LDQ parameters
enable_ldq, genre_manifold, percussion_mode, perceptual_polish):
# 1. Validation guardrails
if not image_path and not use_batch:
return "โ ๏ธ Error: Please upload an image or enable batch processing mode.", None, None
# 2. Setup output collections for file download components
downloadable_files = []
playback_audio = None
try:
# --- BATCH PROCESSING MODE ---
if use_batch and batch_folder:
folder = Path(batch_folder)
if not folder.is_dir():
return f"โ Error: Batch folder path '{batch_folder}' does not exist or is invalid.", None, None
images = sorted(folder.glob("*.jpg")) + sorted(folder.glob("*.png")) + sorted(folder.glob("*.jpeg"))
if not images:
return f"โน๏ธ Notice: No compatible images (.jpg, .jpeg, .png) found in '{batch_folder}'.", None, None
results = []
for img in images:
try:
if engine_type == "Resonance Engine (Audio)":
out_path = f"resonance_{img.stem}.wav"
config = {
"duration": duration,
"random_seed": int(seed) if seed != 0 else None,
"verbose": False,
"export_stems": export_stems,
"export_midi": export_midi,
# LDQ config
"use_ldq": enable_ldq,
"genre_manifold": genre_manifold,
"percussion_mode": percussion_mode,
"perceptual_polish": perceptual_polish,
}
if noise_filter > 0:
config["noise_lowpass_hz"] = noise_filter
preset = PRESETS.get(style, {})
config.update(preset)
engine = ResonanceEngine(config)
engine.process(str(img), out_path)
results.append(f"โ {img.name} โ {out_path}")
if os.path.exists(out_path):
downloadable_files.append(out_path)
else:
out_json = f"lygo_profile_{img.stem}.json"
generator = LYGOProfileGenerator(verbose=False)
generator.generate(str(img), out_json, create_brief=export_brief)
results.append(f"โ {img.name} โ {out_json}")
if os.path.exists(out_json):
downloadable_files.append(out_json)
if export_brief:
brief_file = out_json.replace(".json", ".brief.txt")
if os.path.exists(brief_file):
downloadable_files.append(brief_file)
except Exception as batch_err:
results.append(f"โ {img.name} โ Error: {str(batch_err)}")
return "๐ฆ Batch Processing Logs:\n" + "\n".join(results), None, downloadable_files
# --- SINGLE IMAGE MODE ---
img_p = Path(image_path)
if engine_type == "Resonance Engine (Audio)":
out_path = f"resonance_{img_p.stem}.wav"
config = {
"duration": duration,
"random_seed": int(seed) if seed != 0 else None,
"verbose": False,
"export_stems": export_stems,
"export_midi": export_midi,
# LDQ config
"use_ldq": enable_ldq,
"genre_manifold": genre_manifold,
"percussion_mode": percussion_mode,
"perceptual_polish": perceptual_polish,
}
if noise_filter > 0:
config["noise_lowpass_hz"] = noise_filter
preset = PRESETS.get(style, {})
config.update(preset)
engine = ResonanceEngine(config)
engine.process(image_path, out_path)
if os.path.exists(out_path):
downloadable_files.append(out_path)
playback_audio = out_path # Feed directly to audio player
# Catch accompanying files if checked
if export_midi:
mid_file = out_path.replace(".wav", ".mid")
if os.path.exists(mid_file):
downloadable_files.append(mid_file)
if export_stems:
for stem in ["noise", "drone", "melody", "glitch"]:
stem_file = out_path.replace(".wav", f"_{stem}.wav")
if os.path.exists(stem_file):
downloadable_files.append(stem_file)
log_msg = f"โ
Resonance Engine Matrix Complete.\nGenerated Stereo Mixdown: {out_path}"
if enable_ldq:
log_msg += "\n๐ฌ LDQ Protocol Active"
return log_msg, playback_audio, downloadable_files
else:
# LYGO Profile Mode
out_json = f"lygo_profile_{img_p.stem}.json"
generator = LYGOProfileGenerator(verbose=False)
generator.generate(image_path, out_json, create_brief=export_brief)
if os.path.exists(out_json):
downloadable_files.append(out_json)
# Read profile payload back to show the user the prompt data directly
try:
with open(out_json, "r", encoding="utf-8") as f:
payload = json.load(f)
ai_prompt = payload.get("LYGO_PROFILE", {}).get("ai_music_prompt", "Profile created.")
except Exception:
ai_prompt = "Profile created successfully."
log_msg = f"โ
LYGO DNA Profile Compiled Successfully!\nSaved Destination: {out_json}\n\n๐ AI Music Prompt Copy-Ready:\n\"{ai_prompt}\""
if export_brief:
brief_file = out_json.replace(".json", ".brief.txt")
if os.path.exists(brief_file):
downloadable_files.append(brief_file)
return log_msg, None, downloadable_files
except Exception as global_err:
return f"โ System Error executing core logic: {str(global_err)}", None, None
# --- DESIGN & LAYOUT THE INTERFACE ---
with gr.Blocks() as demo:
gr.Markdown("# ๐ LYGO RESONANCE")
gr.Markdown("### Core SDK Deployment โ Visual-to-Audio Translation & Structural DNA Engine")
with gr.Row():
with gr.Column(scale=1):
# Input block
img_input = gr.Image(type="filepath", label="๐ธ Upload Source Image (Single File)")
engine_choice = gr.Radio(
["Resonance Engine (Audio)", "LYGO Profile Generator"],
value="Resonance Engine (Audio)",
label="โ๏ธ Active Core Engine"
)
with gr.Accordion("๐จ Audio Synth Parameters (Resonance Engine)", open=True):
preset_style = gr.Dropdown(
["cinematic", "ambient", "glitch", "ethereal", "raw"],
value="cinematic",
label="Artistic Preset Blueprint"
)
duration_slider = gr.Slider(5, 60, value=15, step=1, label="Track Duration Length (Seconds)")
seed_num = gr.Number(value=0, label="Mathematical Seed Lock (0 = Generative Continuous)")
filter_hz = gr.Number(value=0, label="Noise Layer Lowpass Filter (Hz, 0 = Off)")
stem_check = gr.Checkbox(label="Export Separated Audio Stems (.wav split)")
midi_check = gr.Checkbox(label="Export Extracted Melodic MIDI Sequence")
with gr.Accordion("๐ Analytical Parameters (Profile Engine)", open=False):
brief_check = gr.Checkbox(value=True, label="Generate Human-Readable Brief (.brief.txt)")
with gr.Accordion("๐ Automated Batch Processing Cluster", open=False):
batch_check = gr.Checkbox(label="Activate Mass Batch Folder Mode")
batch_dir = gr.Textbox(
label="Local Server Input Folder Directory",
placeholder="e.g., ./input_folder"
)
with gr.Accordion("๐ฌ LDQ Protocol Settings (Advanced)", open=False):
enable_ldq = gr.Checkbox(label="Enable LDQ Protocol (Fingerprinting + Advanced Synthesis)")
genre_manifold = gr.Dropdown(
["None", "Dubstep", "Phonk", "Industrial"],
value="None",
label="Genre Manifold Projection"
)
percussion_mode = gr.Dropdown(
["standard", "ldq"],
value="standard",
label="Percussion Engine Mode"
)
perceptual_polish = gr.Slider(0.0, 1.0, value=0.0, step=0.1, label="Perceptual Polish Amount")
submit_btn = gr.Button("๐ฎ Execute Spectral Scan", variant="primary")
with gr.Column(scale=1):
# Output block
text_output = gr.Textbox(label="๐ฅ๏ธ Core Diagnostics Log & Text Prompts", lines=10, interactive=False)
audio_player = gr.Audio(label="๐ง Real-Time Stereo Mix Down Preview", interactive=False)
file_download = gr.Files(label="๐ฆ Download Output Manifest (WAV, JSON, MID, TXT)", interactive=False)
# Attach event processing hook
submit_btn.click(
fn=process_image,
inputs=[
img_input, engine_choice, preset_style, seed_num, duration_slider, filter_hz,
stem_check, midi_check, brief_check, batch_check, batch_dir,
enable_ldq, genre_manifold, percussion_mode, perceptual_polish
],
outputs=[text_output, audio_player, file_download]
)
if __name__ == "__main__":
demo.launch() |