| |
| """ |
| 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, |
| |
| enable_ldq, genre_manifold, percussion_mode, perceptual_polish): |
| |
| |
| if not image_path and not use_batch: |
| return "โ ๏ธ Error: Please upload an image or enable batch processing mode.", None, None |
|
|
| |
| downloadable_files = [] |
| playback_audio = None |
|
|
| try: |
| |
| 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, |
| |
| "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 |
|
|
| |
| 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, |
| |
| "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 |
| |
| |
| 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: |
| |
| 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) |
| |
| |
| 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 |
|
|
| |
| 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): |
| |
| 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): |
| |
| 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) |
|
|
| |
| 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() |