DeepSeekOracle's picture
Update app.py
1571550 verified
Raw
History Blame
10.9 kB
#!/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()