Depends on #54 (the SA3 audio-to-audio / init-audio plumbing).
Problem
The two engines never touch. The Magenta decks improvise a live groove; SA3 generates from a text prompt with no knowledge of what is playing. But once #54 threads --init-audio, the freeze captures off the live stream (M13, ADR-0009) and the library samples (ADR-0022) — both already WAV — can be fed into SA3 as a starting point. That makes a new move possible: take a slice of what the booth is actually playing and reskin it into a different sound-world ("make this dub techno", "acid 303", "vaporwave pad") while keeping its rhythmic/harmonic skeleton. Magenta owns the performance; SA3 owns the timbre/production. For "Latent Space Disc Jockey" this is the signature bridge between the two engines.
Proposed approach
A per-deck reskin action on a filled loop slot (or a Samples-tab entry): capture the slot's PCM (read_loop_slot / capture_sample, src-tauri/src/commands.rs:565,758), post it as #54's init_audio with a text prompt and a strength knob mapped to --init-noise-level (low = keep more of the original, high = freer reinterpretation), then land the result as a new layered loop slot (ADR-0022 layering, useDeck.ts:1330) — the source slot is untouched, so reskin is non-destructive and A/B-able. Auto-save to the samples library with the recipe (prompt + noise level + source) the way generated pads already do (useDeck.ts:1339).
Use the small DiT + same-s decoder (the encoder is paired to the decoder). Respect the measured floor: sm-music breaks up below ~4 s (ADR-0012), so very short captures are reskinned at the floor or refused with an honest message.
Acceptance criteria
- From a filled loop slot (or a Samples-tab entry), a user reskins it with a prompt + strength; the result audibly carries the source's rhythm/phrasing in a new timbre and lands as a layer without overwriting the source.
- Strength maps to
init_noise_level: at low strength the source is clearly recognizable, at high strength it is a loose reinterpretation.
- The reskin auto-saves with its recipe (source, prompt, strength) to the library (ADR-0022).
- Sources below the sm-music quality floor are floored or refused honestly — no garbled output (ADR-0012).
- Generation stays serialized (one CLI at a time,
sa3.py:59); a reskin in flight shows pending like a generate.
- Strings via i18n (
rules/localisation.md); house style; npx tsc -p tsconfig.app.json --noEmit clean.
Scope & non-goals
In scope: the reskin action from a slot/sample, the strength control, a layered non-destructive result, the recipe save. Non-goals: the plumbing (#54); the prompt-palette UI (separate issue); restyling the live stream continuously (that is a stream effect, not this); BPM/key-matching the result (separate issue).
Depends on #54 (the SA3 audio-to-audio / init-audio plumbing).
Problem
The two engines never touch. The Magenta decks improvise a live groove; SA3 generates from a text prompt with no knowledge of what is playing. But once #54 threads
--init-audio, the freeze captures off the live stream (M13, ADR-0009) and the library samples (ADR-0022) — both already WAV — can be fed into SA3 as a starting point. That makes a new move possible: take a slice of what the booth is actually playing and reskin it into a different sound-world ("make this dub techno", "acid 303", "vaporwave pad") while keeping its rhythmic/harmonic skeleton. Magenta owns the performance; SA3 owns the timbre/production. For "Latent Space Disc Jockey" this is the signature bridge between the two engines.Proposed approach
A per-deck reskin action on a filled loop slot (or a Samples-tab entry): capture the slot's PCM (
read_loop_slot/capture_sample,src-tauri/src/commands.rs:565,758), post it as #54'sinit_audiowith a text prompt and a strength knob mapped to--init-noise-level(low = keep more of the original, high = freer reinterpretation), then land the result as a new layered loop slot (ADR-0022 layering,useDeck.ts:1330) — the source slot is untouched, so reskin is non-destructive and A/B-able. Auto-save to the samples library with the recipe (prompt + noise level + source) the way generated pads already do (useDeck.ts:1339).Use the small DiT + same-s decoder (the encoder is paired to the decoder). Respect the measured floor: sm-music breaks up below ~4 s (ADR-0012), so very short captures are reskinned at the floor or refused with an honest message.
Acceptance criteria
init_noise_level: at low strength the source is clearly recognizable, at high strength it is a loose reinterpretation.sa3.py:59); a reskin in flight showspendinglike a generate.rules/localisation.md); house style;npx tsc -p tsconfig.app.json --noEmitclean.Scope & non-goals
In scope: the reskin action from a slot/sample, the strength control, a layered non-destructive result, the recipe save. Non-goals: the plumbing (#54); the prompt-palette UI (separate issue); restyling the live stream continuously (that is a stream effect, not this); BPM/key-matching the result (separate issue).