Download factory_engine.py from DeepSeekOracle/LYGO-Resonance-Engine: direct link, hf CLI and curl.
- Browser
- Download file 15.7 kB
-
https://huggingface.co/spaces/DeepSeekOracle/LYGO-Resonance-Engine/resolve/main/factory_engine.py
- Command line
-
hf download hf://spaces/DeepSeekOracle/LYGO-Resonance-Engine/factory_engine.py
-
curl -L -o factory_engine.py https://huggingface.co/spaces/DeepSeekOracle/LYGO-Resonance-Engine/resolve/main/factory_engine.py
15.7 kB
| #!/usr/bin/env python3 | |
| """ | |
| FACTORY DEFAULT RESONANCE ENGINE (Isolated Pure Gradio Factory) | |
| This is the ORIGINAL working 4-layer sonification engine, completely separate from LYGO/LDQ. | |
| - NO LDQ imports, NO use_ldq, NO sidechain, NO genre manifold, NO perceptual, NO fingerprint. | |
| - Pure image-driven stereo soundscapes using only the classic layers: | |
| 1. Texture Floor (filtered noise from edge density) | |
| 2. Drones (saw from structural lines) | |
| 3. Melody (sine from contours) | |
| 4. Glitch (short tones from FAST keypoints) | |
| Goal: Reliable "industry quality beats / musical" output as the default factory experience. | |
| This file is the drop-in clean factory. The LYGO tab continues to use the other engine. | |
| Based on the clean original implementations that produced good musical results (historical working versions). | |
| """ | |
| import cv2 | |
| import numpy as np | |
| import soundfile as sf | |
| import math | |
| from pathlib import Path | |
| from typing import Optional, Dict, Any | |
| __version__ = "factory-1.0.0-isolated" | |
| # Artistic Presets tuned for musical / "industry beats" factory output | |
| # (balanced noise, strong drones + contour melodies for rhythmic feel, tasteful glitch) | |
| PRESETS = { | |
| "raw": { | |
| "noise_vol": 0.06, | |
| "drone_vol": 0.07, | |
| "note_vol": 0.12, | |
| "glitch_vol": 0.02, | |
| "noise_lowpass_hz": 800, | |
| }, | |
| "ambient": { | |
| "noise_vol": 0.04, | |
| "drone_vol": 0.09, | |
| "note_vol": 0.10, | |
| "glitch_vol": 0.008, | |
| "drone_attack": 5.0, | |
| "drone_decay": 6.0, | |
| "note_decay": 0.55, | |
| "noise_lowpass_hz": 450, | |
| }, | |
| "glitch": { | |
| "noise_vol": 0.07, | |
| "drone_vol": 0.05, | |
| "note_vol": 0.09, | |
| "glitch_vol": 0.06, | |
| "max_glitches": 25, | |
| "noise_lowpass_hz": 2200, | |
| }, | |
| "ethereal": { | |
| "noise_vol": 0.03, | |
| "drone_vol": 0.08, | |
| "note_vol": 0.11, | |
| "glitch_vol": 0.01, | |
| "note_decay": 0.6, | |
| "noise_lowpass_hz": 380, | |
| }, | |
| "cinematic": { | |
| "noise_vol": 0.05, | |
| "drone_vol": 0.08, | |
| "note_vol": 0.13, | |
| "glitch_vol": 0.025, | |
| "drone_attack": 4.0, | |
| "drone_decay": 5.5, | |
| "note_attack": 0.05, | |
| "note_decay": 0.38, | |
| "max_glitches": 18, | |
| "noise_lowpass_hz": 720, | |
| "root_freq_range": (28, 72), | |
| }, | |
| # Strong musical factory default - "industry quality" feel | |
| "musical": { | |
| "noise_vol": 0.045, | |
| "drone_vol": 0.085, | |
| "note_vol": 0.135, | |
| "glitch_vol": 0.022, | |
| "noise_lowpass_hz": 680, | |
| "drone_attack": 3.8, | |
| "drone_decay": 5.2, | |
| "note_decay": 0.36, | |
| "max_notes": 9, | |
| "max_glitches": 16, | |
| }, | |
| } | |
| class FactoryResonanceEngine: | |
| """Completely isolated factory default engine. No LYGO/LDQ dependencies.""" | |
| def __init__(self, config: Optional[Dict[str, Any]] = None): | |
| self.config = { | |
| "sr": 44100, | |
| "duration": 15.0, | |
| "global_fade": 0.65, | |
| "soft_clip": True, | |
| "soft_clip_amount": 1.35, | |
| "max_drones": 5, | |
| "max_notes": 8, | |
| "max_glitches": 14, | |
| "noise_vol": 0.05, | |
| "drone_vol": 0.07, | |
| "note_vol": 0.12, | |
| "glitch_vol": 0.018, | |
| "root_freq_range": (32, 68), | |
| "theta_lock_range": (4.8, 10.5), | |
| "drone_attack": 3.8, | |
| "drone_decay": 5.0, | |
| "note_attack": 0.045, | |
| "note_decay": 0.34, | |
| "glitch_attack": 0.004, | |
| "glitch_decay": 0.014, | |
| "noise_lowpass_hz": 650, | |
| "random_seed": None, | |
| "verbose": True, | |
| "export_stems": False, | |
| "export_midi": False, | |
| } | |
| if config: | |
| self.config.update(config) | |
| def _log(self, msg: str): | |
| if self.config.get("verbose", True): | |
| print(msg) | |
| def analyze_image(self, image_path: str) -> Dict[str, Any]: | |
| """Standard computer vision analysis β unchanged from original working versions.""" | |
| img = cv2.imread(str(image_path)) | |
| if img is None: | |
| raise FileNotFoundError(f"Could not load image: {image_path}") | |
| if len(img.shape) == 2: | |
| img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) | |
| gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |
| h, w = gray.shape | |
| avg_blue, avg_green, avg_red, _ = cv2.mean(img) | |
| edges = cv2.Canny(gray, 50, 150) | |
| edge_density = np.sum(edges > 0) / (h * w) | |
| contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) | |
| lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 50, minLineLength=28, maxLineGap=12) | |
| fast = cv2.FastFeatureDetector_create(threshold=38) | |
| keypoints = fast.detect(gray, None) | |
| return { | |
| "width": w, "height": h, | |
| "avg_red": avg_red, "avg_green": avg_green, "avg_blue": avg_blue, | |
| "edge_density": edge_density, | |
| "contours": contours, | |
| "lines": lines if lines is not None else [], | |
| "keypoints": keypoints, | |
| } | |
| def _generate_tone(self, freq: float, duration: float, wave_type: str = "sine") -> np.ndarray: | |
| sr = self.config["sr"] | |
| n = int(sr * duration) | |
| if n <= 0: | |
| return np.zeros(1, dtype=np.float32) | |
| t = np.linspace(0, duration, n, dtype=np.float32) | |
| if wave_type == "sine": | |
| return np.sin(freq * t * 2 * np.pi).astype(np.float32) | |
| elif wave_type == "sawtooth": | |
| return (2 * (t * freq - np.floor(0.5 + t * freq)) * 0.58).astype(np.float32) | |
| elif wave_type == "noise": | |
| return np.random.uniform(-0.32, 0.32, n).astype(np.float32) | |
| return np.zeros(n, dtype=np.float32) | |
| def _apply_envelope(self, audio: np.ndarray, attack: float, decay: float) -> np.ndarray: | |
| sr = self.config["sr"] | |
| n = len(audio) | |
| if n <= 0: | |
| return audio | |
| a = max(1, int(attack * sr)) | |
| d = max(1, int(decay * sr)) | |
| env = np.ones(n, dtype=np.float32) | |
| if n > a + d: | |
| env[:a] = np.linspace(0, 1, a, dtype=np.float32) | |
| env[-d:] = np.linspace(1, 0, d, dtype=np.float32) | |
| return (audio * env).astype(np.float32) | |
| def _stereo_pan(self, mono: np.ndarray, pan: float) -> np.ndarray: | |
| if mono.ndim == 1: | |
| mono = mono[:, np.newaxis] | |
| pan = max(-1.0, min(1.0, pan)) | |
| left = math.cos((pan + 1) * math.pi / 4) | |
| right = math.sin((pan + 1) * math.pi / 4) | |
| return np.column_stack((mono * left, mono * right)).astype(np.float32) | |
| def _fft_lowpass(self, audio: np.ndarray, cutoff_hz: float) -> np.ndarray: | |
| if cutoff_hz <= 0 or len(audio) < 32: | |
| return audio | |
| sr = self.config["sr"] | |
| n = len(audio) | |
| fft = np.fft.rfft(audio) | |
| freqs = np.fft.rfftfreq(n, 1.0 / sr) | |
| fft[freqs > cutoff_hz] = 0 | |
| return np.fft.irfft(fft, n=n).real.astype(np.float32) | |
| def _soft_limit(self, audio: np.ndarray) -> np.ndarray: | |
| if self.config["soft_clip"]: | |
| amt = self.config["soft_clip_amount"] | |
| return (np.tanh(audio * amt) / np.tanh(amt)).astype(np.float32) | |
| return audio | |
| def synthesize(self, features: Dict[str, Any], output_path: str): | |
| cfg = self.config | |
| if cfg["random_seed"] is not None: | |
| np.random.seed(cfg["random_seed"]) | |
| sr = cfg["sr"] | |
| duration = cfg["duration"] | |
| n_total = int(sr * duration) | |
| if n_total <= 0: | |
| sf.write(output_path, np.zeros((1, 2)), sr) | |
| return | |
| audio = np.zeros((n_total, 2), dtype=np.float32) | |
| root = np.interp(features["avg_red"], [0, 255], cfg["root_freq_range"]) | |
| theta = np.interp(features["avg_green"], [0, 255], cfg["theta_lock_range"]) | |
| w, h = features["width"], features["height"] | |
| self._log("π΅ FACTORY ENGINE β Pure 4-layer (no LYGO/LDQ)") | |
| # Collections for stems | |
| audio_noise = np.zeros((n_total, 2), dtype=np.float32) | |
| audio_drone = np.zeros((n_total, 2), dtype=np.float32) | |
| audio_melody = np.zeros((n_total, 2), dtype=np.float32) | |
| audio_glitch = np.zeros((n_total, 2), dtype=np.float32) | |
| melody_events = [] | |
| # Layer 1: Texture Floor (Noise) β filtered for musicality | |
| if features["edge_density"] > 0.006: | |
| noise = self._generate_tone(0, duration, "noise") | |
| if cfg.get("noise_lowpass_hz", 650) > 0: | |
| noise = self._fft_lowpass(noise, cfg["noise_lowpass_hz"]) | |
| noise = self._apply_envelope(noise, cfg["drone_attack"], cfg["drone_decay"]) | |
| vol = min(features["edge_density"] * 1.35, cfg["noise_vol"]) | |
| stereo_noise = self._stereo_pan(noise, 0.0) * vol | |
| audio += stereo_noise | |
| audio_noise += stereo_noise | |
| self._log(f" Layer1 noise vol={vol:.3f} lowpass={cfg.get('noise_lowpass_hz')}") | |
| # Layer 2: Drones (Lines) β rhythmic backbone | |
| for i, line in enumerate(features["lines"][:cfg["max_drones"]]): | |
| x1, _, x2, _ = line[0] | |
| length = math.hypot(x2 - x1, 0) | |
| detune = (i * 0.65) if cfg["random_seed"] is not None else 0 | |
| freq = root + (max(1, int(length / 46)) * theta * 0.58) + detune | |
| tone = self._generate_tone(freq, duration, "sawtooth") | |
| tone = self._apply_envelope(tone, cfg["drone_attack"], cfg["drone_decay"]) | |
| pan = (x1 / w) * 2 - 1 | |
| stereo_drone = self._stereo_pan(tone, pan) * cfg["drone_vol"] | |
| audio += stereo_drone | |
| audio_drone += stereo_drone | |
| # Layer 3: Contours β Melody (main musical/rhythmic content) | |
| valid = [c for c in features["contours"] if 85 < cv2.contourArea(c) < (w * h * 0.62)] | |
| valid.sort(key=lambda c: cv2.boundingRect(c)[0]) | |
| for i, cnt in enumerate(valid[:cfg["max_notes"]]): | |
| area = cv2.contourArea(cnt) | |
| verts = len(cv2.approxPolyDP(cnt, 0.04 * cv2.arcLength(cnt, True), True)) | |
| freq = (root * 3.65) + (verts * theta * 1.55) | |
| dur = min(2.8, 0.18 + (area / 12800)) | |
| tone = self._generate_tone(freq, dur, "sine") | |
| tone = self._apply_envelope(tone, cfg["note_attack"], cfg["note_decay"]) | |
| M = cv2.moments(cnt) | |
| cx = int(M["m10"] / M["m00"]) if M["m00"] != 0 else cv2.boundingRect(cnt)[0] | |
| start = (cx / w) * (duration - dur) | |
| idx = int(start * sr) | |
| end = min(idx + len(tone), n_total) | |
| pan = (cx / w) * 2 - 1 | |
| stereo_note = self._stereo_pan(tone[:end-idx], pan) * cfg["note_vol"] | |
| audio[idx:end] += stereo_note | |
| audio_melody[idx:end] += stereo_note | |
| melody_events.append((freq, dur, start)) | |
| # Layer 4: Glitch / Micro events (adds percussive "beat" character) | |
| for i, kp in enumerate(features["keypoints"][:cfg["max_glitches"]]): | |
| x, y = kp.pt | |
| freq = root * 13.2 + (y % 82) * 1.35 | |
| tone = self._generate_tone(freq, 0.048, "sine") | |
| tone = self._apply_envelope(tone, cfg["glitch_attack"], cfg["glitch_decay"]) | |
| start = (y / h) * (duration - 0.048) | |
| idx = int(start * sr) | |
| end = min(idx + len(tone), n_total) | |
| pan = (x / w) * 2 - 1 | |
| stereo_glitch = self._stereo_pan(tone[:end-idx], pan) * cfg["glitch_vol"] | |
| audio[idx:end] += stereo_glitch | |
| audio_glitch[idx:end] += stereo_glitch | |
| # Final factory polish (safe, no LDQ) | |
| audio = self._soft_limit(audio) | |
| fade = int(cfg["global_fade"] * sr) | |
| if fade > 0 and n_total > fade * 2: | |
| audio[:fade] *= np.linspace(0, 1, fade)[:, np.newaxis] | |
| audio[-fade:] *= np.linspace(1, 0, fade)[:, np.newaxis] | |
| peak = np.max(np.abs(audio)) | |
| if peak > 0: | |
| audio = audio / peak * 0.965 | |
| sf.write(output_path, audio, sr) | |
| self._log(f"β FACTORY Saved: {output_path} | Peak: {peak:.3f}") | |
| # Stems (factory feature) | |
| if cfg.get("export_stems"): | |
| base = output_path.replace(".wav", "") | |
| for stem, name in [(audio_noise, "noise"), (audio_drone, "drone"), | |
| (audio_melody, "melody"), (audio_glitch, "glitch")]: | |
| mv = np.max(np.abs(stem)) | |
| if mv > 0: | |
| stem = stem / mv * 0.965 | |
| sf.write(f"{base}_{name}.wav", stem, sr) | |
| self._log(f"β Stem: {base}_{name}.wav") | |
| # MIDI (factory feature) | |
| if cfg.get("export_midi") and melody_events: | |
| try: | |
| from mido import MidiFile, MidiTrack, Message | |
| mid = MidiFile() | |
| track = MidiTrack() | |
| mid.tracks.append(track) | |
| ticks_per_beat = 480 | |
| tempo = 128 | |
| tick_offset = 0 | |
| for freq, dur, start in melody_events: | |
| midi_note = max(0, min(127, int(12 * math.log2(max(20, freq) / 440) + 69))) | |
| duration_ticks = int(dur * ticks_per_beat * (tempo / 60)) | |
| start_ticks = int(start * ticks_per_beat * (tempo / 60)) | |
| track.append(Message('note_on', note=midi_note, velocity=62, time=start_ticks - tick_offset)) | |
| track.append(Message('note_off', note=midi_note, velocity=62, time=duration_ticks)) | |
| tick_offset = start_ticks + duration_ticks | |
| mid_path = output_path.replace(".wav", ".mid") | |
| mid.save(mid_path) | |
| self._log(f"β MIDI: {mid_path}") | |
| except Exception as e: | |
| self._log(f"MIDI export skipped: {e}") | |
| def process(self, image_path: str, output_path: str): | |
| self._log(f"\nββββββββββββββββββββββββββββββββββββββββββββββ") | |
| self._log(f"β FACTORY DEFAULT RESONANCE ENGINE v{__version__} β") | |
| self._log(f"β Pure image β musical stereo soundscape β") | |
| self._log(f"ββββββββββββββββββββββββββββββββββββββββββββββ\n") | |
| self._log(f"Analyzing: {image_path}") | |
| features = self.analyze_image(image_path) | |
| self.synthesize(features, output_path) | |
| def main(): | |
| import argparse | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("image") | |
| parser.add_argument("-o", "--output", default=None) | |
| parser.add_argument("--duration", type=float, default=15.0) | |
| parser.add_argument("--style", choices=list(PRESETS.keys()), default="cinematic") | |
| parser.add_argument("--seed", type=int, default=None) | |
| parser.add_argument("--noise-filter", type=float, default=None) | |
| parser.add_argument("--stems", action="store_true") | |
| parser.add_argument("--midi", action="store_true") | |
| parser.add_argument("--quiet", action="store_true") | |
| args = parser.parse_args() | |
| config = { | |
| "duration": args.duration, | |
| "random_seed": args.seed, | |
| "verbose": not args.quiet, | |
| "export_stems": args.stems, | |
| "export_midi": args.midi, | |
| } | |
| if args.noise_filter is not None: | |
| config["noise_lowpass_hz"] = args.noise_filter | |
| preset = PRESETS.get(args.style, {}) | |
| config.update(preset) | |
| out_path = args.output or f"factory_{Path(args.image).stem}.wav" | |
| engine = FactoryResonanceEngine(config) | |
| engine.process(args.image, out_path) | |
| if __name__ == "__main__": | |
| main() | |