Home / Audio / Production and Craft
Updated Jun 21, 2026 · Affirmology_LayeredStemEngine_OptionB_Spec_v1.md
Status: spec. Studio only. The locked demo never changes. Proposed new queue item C30. Depends on: C26 (adds Structure.bed_profile, section markers, target length) and C3 (refactors the mix into a stage we can extend). Build order: C26, then C3, then this. Answers: Jeff 2026-06-21, "how can we build Option B (layered stems mixed by the engine) with Suno?"
Instead of one finished music file per track, the engine assembles the bed at render time from a LIBRARY of loopable layer files (a drone, a pad, a texture, an optional pulse, an optional motif), tagged by state, key, and tempo. At render time the engine picks the palette for the structure's bed_profile, loops or stretches the layers to the actual script length, and AUTOMATES each layer's volume across the script's sections (sparse in the induction, fuller through the install, resolving at the close), ducks the whole bed under the voice, and lays the C3 entrainment tone on top tuned to the palette's key. One small library then produces an arc-matched, evolving bed for every person and every length.
Suno generates FINISHED songs, not clean designed layers. So you do not get "a drone stem" by asking nicely for a normal track. There are two real ways to get layers out of Suno, and we use both:
GENERATE ISOLATED ELEMENTS (best for ambient/deep states). Prompt Suno for ONE element at a time, forcing everything else off ("solo sustained low drone, no percussion, no melody, no chord changes, minimal"). Each generation IS a clean layer. Because ambient layers have no strict beat, independent generations sit together fine even if they were made separately. This is the primary path for sleep, journey, and morning beds, and it works today.
SPLIT A FINISHED TRACK INTO STEMS (best for rhythmic/activation states). For anything with a beat, independently generated layers will not lock to the same grid, so instead generate ONE rich track and separate it into parts that all share the same key, tempo, and grid. Two ways to split: Suno's own stem feature on paid plans, OR Demucs, a free open-source separator that runs locally in Python (so we are not dependent on Suno's paid tier and can even automate it). The trade-off is some separation artifacts, acceptable for a bed sitting under a voice.
Recommendation: start with path 1 for the deep/ambient states (cleanest, easiest, highest value), add path 2 later for activation beds.
A folder tree the engine reads:
stems/
sleep/
palette_warm_c/
drone.wav
pad.wav
texture.wav
manifest.json
journey/
palette_dmin_60/
...
manifest.json per palette: - state: sleep | journey | morning | activation - palette_id, key, bpm - layers: a list of {role: drone|pad|texture|pulse|motif, file, loopable: true/false, base_gain_db, intensity: low|med|high, lufs} - notes: any headphone/loop caveats The manifest is the contract between the content (Suno) side and the engine side. If a file is tagged correctly, the engine can use it.
A new function in the same mix stage as the C3 tones. Inputs: the structure's bed_profile (C26) to pick the palette, the script's section markers + target length (C26), and the QC gate (unchanged). Logic: 1. SELECT the palette for the bed_profile (fallback to a single preset bed if no stem palette exists, so nothing breaks). 2. BUILD THE BED ARC per pace. A small declarative map of which layers are active in which section and at what gain. Example deep arc: induction = drone only, low; deepen = drone + pad rising; install = drone + pad + texture swell at the section boundary; emerge = texture fades, drone resolves to silence. 3. LOOP / STRETCH each active layer seamlessly to the section's duration (ambient layers loop cleanly at their tagged loop points; lengths come from the script's actual timing, so it always fits). 4. PLACE SWELLS / TRANSITIONS at the section boundaries (which are the same markers C26 uses for pauses, so pacing and bed automation share one cue map). 5. SUM the layers, DUCK the bed under the voice (sidechain), then add the C3 tone tuned to palette key. 6. RUN audio_qc.py on the final mix. Reject on dropout or clipping, exactly as today.
Because section markers and target length already exist after C26, the engine has everything it needs to make the bed follow the words.
DRONE: "Solo sustained low ambient drone, single evolving low tone, no percussion, no melody, no chord changes, very minimal and warm, key of C, 2 to 3 minutes, seamless." PAD: "Solo warm analog pad, slow swelling chords, no drums, no melody lead, no bass, spacious and soft, key of C, 60 BPM feel, 2 to 3 minutes." TEXTURE / ATMOSPHERE: "Solo ambient texture, airy shimmer and distant atmosphere, no rhythm, no melody, no bass, very quiet and wide, key of C, 2 minutes." OPTIONAL MOTIF: "Solo sparse felt-piano motif, a few gentle notes with space between them, no drums, no pads, intimate, key of C, 2 minutes." OPTIONAL PULSE (activation only, or split from a full track): "Solo soft rhythmic synth pulse, steady gentle beat, no melody, no vocals, key of E minor, 90 BPM, 2 minutes." Keep every element in the palette's key so they stack cleanly and the C3 tone can match.
Read Affirmology_PROJECT_STATE.md, Affirmology_LayeredStemEngine_OptionB_Spec_v1.md, Affirmology_AudioPacingActivation_C26_BuildBrief_v1.md, and Affirmology_FrequencySoundLayer_C3_Spec_v1.md.
Implement C30 the layered stem bed engine per the spec: a stems/ library with per-palette manifest.json, and a bed-assembler in audio_mix.py (same stage as the C3 tones) that selects a palette by Structure.bed_profile, builds a per-pace bed arc, loops/stretches layers to the script's section markers and target length, places swells at section boundaries, ducks under voice, normalizes layers to tagged LUFS, then adds the C3 tone tuned to the palette key. Graceful fallback to the current single preset bed when no palette exists. Keep audio_qc.py on the final mix. Studio only; demo untouched; no em dashes; vendor into affirmology-studio.
Add the five acceptance tests from the spec and a tiny sample palette (synthesized placeholder layers are fine for the test) so the suite runs without real Suno files. Show me diffs, test output, and one real evolving-bed render to listen to before deploying.
Yes, Suno can build Option B, but its job is to produce ISOLATED ELEMENTS (or splittable full tracks), not finished beds. Sol generates clean single-element layers per state in a locked key, we tag them into a small library, and the engine does the evolving and the matching to each script. Start with the ambient states where it works beautifully today, and the same machinery later absorbs the professional stems we commission after funding, no rework.