VIRTUAL_ORCHESTRATION_AND_MOCKUP_REALISM.md

music/VIRTUAL_ORCHESTRATION_AND_MOCKUP_REALISM.md

Virtual Orchestration and Mockup Realism

CANON SUBORDINATION — this document is PROPOSAL-TIER: it serves canon and never outranks it.
Canon served: the melody-first / thirty-year-bar music direction (memory
music-direction-melody-first-30-year-bar), the composed-never-prompted rule, and the standing
observation that our sfizz CC0 renders read as "noise". This lane owns the REALISATION half of
that complaint — the distance between a correct score and a performance a listener believes.
If this document disagrees with canon, CANON WINS and this document is the defect.

TIER: RESEARCH SYNTHESIS — PROPOSAL-TIER. This document is HOW, never WHAT. It sets no canon, names

no region content, and changes no spine or registry row. Every substantive claim carries a source

(URL, or manual plus publisher, or paper plus authors and DOI); where sources disagree the

disagreement is stated; where a statement is craft consensus rather than evidence it is labelled

CRAFT CONSENSUS. Every principle carries a PIPELINE HOOK line marked CODE-ABLE or MEASURE-ONLY,

naming the file and the operation. Every number attributed to OUR stack in section 1 and in GAP

NOTES was measured on this box during this pass, not recalled.

WHAT THIS LANE ANSWERS. The craft series so far has taught the pipeline what to WRITE — counterpoint,

counter-melody, motivic development, ornament, texture. All of it is symbolic. A cue can satisfy

every rule in every one of those documents and still arrive at the ear as a MIDI file, because the

symbolic layer stops at the note list and the note list is not a performance. This document is about

the layer below: what a sampler is given, how a real ensemble differs from a note list, how the

result is placed in a room, and at what level it is delivered. It is the layer where our renders

currently do essentially nothing, and it is measurable.

1. The measured diagnosis, read off our own renderer

Every number in this section was produced during this pass by running our own code and our own

palette. The three pass-5 plans (build/audio/pass5/plans/PASS5_FLORES_ROAD.json, _FALLS,

_ROUNDS) were compiled through harness/music_gen/pass2_realise.py, which is the renderer

harness/music_gen/pass5_realise.py re-points and calls; the SFZ probes were rendered through the

same sfizz_render invocation the pipeline uses.

1.1 Zero continuous controller data ever reaches the sampler

pass2_realise._write_midi builds a pretty_midi.Instrument, appends notes, and writes the file.

It appends no control_changes and no pitch_bends. A grep for controller emission across

harness/music_gen/*.py returns hits only in complete_track.py — and there the split is exact and

instructive: _write_part_midi, which produces the MIDI that is actually rendered, writes notes and

optional pitch bends only; write_score_midi, which writes the CC11 dynamic envelope, is documented

in its own docstring as "THE NOTATION SEAM… readable in any notation program", and its output is

never handed to sfizz. So across both realisation lanes, the audio a listener hears is produced from

note-on, note-off, pitch and velocity, and nothing else.

This is the single largest structural difference between our renders and every mockup practice

described in sections 2 and 3, all of which treat continuous dynamic data as the primary vehicle of

realism rather than an ornament on top of it.

1.2 Every simultaneity is mathematically perfect

compile_layer computes each onset as abs_beat * beat_s from integer cycle and beat arithmetic.

Notes from different layers that share a nominal beat therefore share an identical floating-point

timestamp. Measured across the three cues:

cuenotesdistinct onset TIMESnotes inside a multi-layer clusterlargest clustermeasured inter-layer spread
FLORES_FALLS18388481367 (74.4%)9 layers0.000 ms
FLORES_ROAD405810283787 (93.3%)17 layers0.000 ms
FLORES_ROUNDS470512674305 (91.5%)17 layers0.000 ms

Between 74% and 93% of every note in a cue is struck at the same instant as at least one other layer,

to the sample. Section 3.1 gives the measured norm for real ensembles, which is not zero and is not

close to zero.

1.3 The dynamic vocabulary is a per-section step function

Velocity is computed once per note as base_vel * vscale * (0.55 + 0.65 * inten), where base_vel

is a per-layer constant from the plan, vscale is the pattern's accent multiplier for that position

in the cycle, and inten is the section's declared intensity. Nothing in that expression varies from

one statement of a figure to the next statement of the same figure inside the same section.

Measured: consecutive notes within a layer carry an IDENTICAL velocity 91.3%, 89.4% and 90.8% of the

time in the three cues. The variation that does exist is entirely the accent pattern and the section

map — it is compositional structure, not performance. Three layers in every cue carry three or fewer

distinct velocities across the whole piece.

1.4 The palette's instruments speak at very different times, and nothing compensates

Every sustained orchestral sample in a real library begins before it is audible; producers keep the

attack intact, so the perceived note arrives late (section 2.6). Measured directly on our own CC0

sample files — time from file start to the point the envelope first reaches half of the sample's

peak, median over up to ten samples per instrument:

instrumentto 10% peakto 50% peak
clarinet.sus90.3 ms151.9 ms
horn.sus30.1 ms94.2 ms
flute.sus_vib46.8 ms88.8 ms
trombone.sus17.1 ms84.0 ms
bassoon.sus32.5 ms80.8 ms
oboe.sus_vib19.0 ms59.2 ms
trumpet.sus18.9 ms46.4 ms
harp25.2 ms33.9 ms
timpani.hit1.5 ms5.6 ms
bass_drum1.1 ms6.0 ms
conga0.5 ms3.3 ms

Across the 22 instruments probed, the median time-to-half-peak is 47.6 ms and the spread between the

fastest and slowest speaker is 148.6 ms. pass2_realise applies no per-instrument offset of any

kind. A downbeat written for conga and clarinet together therefore arrives as a conga followed, most

of a fifth of a second later, by a clarinet — and the clarinet is usually the one carrying the tune.

The perfect simultaneity of section 1.2 is perfect in the score and audibly wrong in the render.

1.5 Round robin: live on the percussion, absent from the carriers, and the code's claim is stale

orchestrate.py and pass2_realise.determinism both assert that "the palette's SFZ files do not

use" round-robin and random opcodes. Measured across the 85 palette entries: 20 declare

seq_position, and 10 declare lorand. The claim is false, and the determinism check does not

catch it because sfizz resets its sequence counter at the start of each render, so a repeated render

is still bit-identical while the round robin is cycling inside it.

Rendered probe, eight repeats of one key at a fixed velocity: conga, bass drum and woodblock all

alternate between two distinct recordings, with zero identical repeats out of seven comparisons.

The palette declares seq_length=2 on 202 regions, seq_length=6 on 6, seq_length=3 on 3.

The coverage, however, is inverted relative to need. Round robin by family: drum 7 of 9, rattle 2 of

2, struck_wood 1 of 2 — against woodwind 1 of 13, brass 1 of 7, strings 4 of 21, voice 0 of 4,

plucked 0 of 3, tuned_perc 1 of 7. Across the three pass-5 cues, 11 of 28 melodic and figural layers

(39%) are carried by an instrument with no round robin at all. The machine-gun effect (section 2.5)

is therefore live on exactly the material a listener follows.

1.6 CC1 is a no-op on our palette; CC7 and CC11 work

Rendered probe through sfizz_render, one three-second note with a CC ramp from 10 to 127 across the

note, compared sample-by-sample against the same note with no controller data:

instrumentCC1 max differenceCC7 max differenceCC11 max difference
horn.sus0.00e+003.48e-023.62e-02
clarinet.sus0.00e+005.07e-025.46e-02
trombone.sus0.00e+001.61e-021.70e-02

CC1 changes nothing, exactly, because no file in the palette declares locc1, xfin_locc1 or any

_oncc1 modulation — zero of 85. CC7 and CC11 both act as gain, because sfizz implements the

registered MIDI volume and expression controllers itself. So the industry's primary realism tool

(section 2.1) is unavailable to us as shipped, and the secondary one is available and unused.

Velocity, by contrast, does reach real dynamic layers: comparing velocity 40 against velocity 110 on

the same note, the peak ratio is 3.4x (clarinet), 5.6x (horn) and 15.1x (trombone), and the

level-normalised envelope difference is 0.17 to 0.19 — far from zero, so the timbre genuinely

changes and not merely the level. Velocity layering across the palette: 5 instruments carry 6 bands,

13 carry 4, 8 carry 3, 27 carry 2, 12 carry 1 and 20 carry none. The vocabulary exists, it is

coarse, and — decisively — it can only be addressed at note-on, so no crescendo inside a held note is

reachable by any means our renderer currently possesses.

1.7 The mix is one global diffuse field on the sum, with no EQ and no early reflections

mix_policy.apply_space convolves the finished stereo mixdown with a single synthetic impulse

response chosen by cue class. The docstring is honest about what that is: "a DIFFUSE FIELD with no

early-reflection geometry, so it gives distance and decay and it does not give a room shape." There

is one room per cue, applied identically to every instrument; per-part processing amounts to a

static gain_db and a constant-power _pan. A grep for filter design across pass2_realise.py,

orchestrate.py and mix_policy.py finds biquads only inside the loudness meter's K-weighting.

There is no EQ anywhere in the signal path, no high-frequency roll-off with distance, no per-section

reverb, and no pre-delay differentiation between a front-desk soloist and a back-row instrument.

Section 5 is what the practice does instead.

1.8 The loudness target has one declared denominator, and three are actually in play

mix_policy.derive measures the acquired exemplar corpus and takes the per-class median as the

target: BATTLE −9.84 LUFS (n=5), EXPLORATION −12.18 (n=8), MELANCHOLIC −13.95 (n=4, and SANCTUARY

borrows it), overall default −11.55 (n=30). The three published pass-5 cues land at −18.81, −17.71

and −17.41 LUFS and all three fail clears_target. LIMITER._why_it_exists reads that gap as a

defect and probes a limiter to close it.

Section 6 argues the gap is largely an artefact of the denominator. Those corpus numbers are

commercial ALBUM masters. ASWG-R001 is a WHOLE-PROGRAMME number. The published measurements of

shipped games put the in-game music BED between −23 and −40 LUFS. Three different quantities, three

different meanings, and MIX_POLICY.json currently declares only the first while clears_target

reads as though it were the delivery bar.

2. Why mockups sound fake — the practitioner diagnosis

2.1 The controller triad, and why the names are not interchangeable

The professional vocabulary is stable across forums, manufacturers and courses, and it distinguishes

three things our pipeline collapses into one.

only act at note-on. On performance patches it also selects articulation and transition type:

Spitfire Chamber Strings documents velocity 1–9 as a smooth attack and 10–127 as three to four

layers of spiccato/staccato attack, and on slower transitions velocity 1–19 gives portamento,

20–84 the fingered slur, 85–127 the heavier bowed change (Spitfire Chamber Strings User Manual,

"PERFORMANCE LEGATO").

to CC1, controls the dynamic of the sound, and "this smoothly crossfades between very soft (or

'pp') recordings, through to very loud (or 'ff')". That is, it changes TIMBRE continuously,

mid-note, which velocity cannot do. CRAFT CONSENSUS: the community restatement that CC1 changes

the sample dynamics "on the fly" comes from VI-Control threads that cannot be fetched (see

SOURCES), so it is carried here as consensus, not as cited text.

changes level and nothing else.

The Spitfire manual reduces its own instruction set to two rules for a new user, and the second is

"On long notes make sure you always use your Modwheel" — verified verbatim on the manual's welcome

page, where it is printed as rule 2 of 2.

PIPELINE HOOK — CODE-ABLE. pass2_realise._write_midi must gain a controller-emission stage. The

palette forces the assignment: CC1 is dead on our files (1.6), so the continuous lane is CC11, and

the timbral lane stays velocity-at-note-on until a palette carries CC1 crossfades (see GAP-VO-02).

2.2 The two named failure modes: flat CC, and linked CC

The first failure is a static controller. A held note whose dynamic data never moves is the acoustic

signature of a sampler, because no player sustains a note at a fixed pressure. This is the failure

our renders exhibit in its pure form — not a flat curve but no curve at all.

The second failure is subtler and is worth naming before we build the fix, because the naive

implementation lands straight in it: moving CC1 and CC11 together in lockstep. Riding both in the

same direction compounds them — the soft dynamic layer is also attenuated and the loud layer also

boosted — so the dynamic range is exaggerated beyond anything a player produces, and the result

reads as level-riding rather than as performance. The associated rule is a physical-plausibility

constraint: never program a loud dynamic layer (CC1 90–127) against a low expression value (CC11

1–40), because no instrument produces a fortissimo timbre at a pianissimo level.

CRAFT CONSENSUS, and flagged as such. This subsection was previously written around two direct

quotations attributed to practitioner sources. Neither survived verification — they are not in the

Evenant dynamics article and the VI-Control threads that plausibly carry them return HTTP 403 to

automated fetching. The MECHANISM above is sound and is corroborated in substance by Production

Expert, which warns against unnatural CC1/CC11 curve combinations and treats the two controllers as

doing different jobs. The quotations are withdrawn; the rule they supported stands on the

physical-plausibility argument, which needs no citation.

The usual professional resolution is a division of labour: CC7 set and forget; CC11 used for

correction, for fades the library's own softest layer cannot reach, and for divisi or unison

transitions; CC1 in constant motion as the actual dynamic.

PIPELINE HOOK — CODE-ABLE. A validator on the emitted controller stream: reject any frame where the

declared dynamic level and the expression scalar move in opposite senses by more than a declared

tolerance, and reject any layer whose controller stream has zero variance across a sustained note

longer than a declared length.

2.3 Breath, bow, and the phrase envelope

The concrete shapes practitioners program are all physical rather than decorative.

remedy is literal: insert small pauses and rests between phrases so a wind line is not asked to

play continuously in a way no lungs could sustain. Production Expert reaches the same place

through the controller rather than the note list, citing "an oboist or a singer who needs to

breathe between phrases" as a reason to shape CC11. Note the correction: the sources support a

GAP at the phrase seam and an expression shape around it; neither source lists "simulate

breathing" as a discrete named technique, and the earlier draft of this line overstated that.

is to fade in at the start of a bow, drop slightly through its middle, and lift again at the change

of direction; and, at the note level, to vary staccato velocities according to whether the stroke

is up-bow or down-bow, since the pressures differ. The physical premise — that bow pressure and

speed are not constant across a stroke — is not in dispute, but this lane has no primary source for

the specific envelope shape, so the bow-ripple hook below is proposed as a SHAPE TO TUNE BY EAR

rather than as a documented curve to reproduce.

crescendo, and finishing them with a decrescendo", using "the modwheel (or the expression

controller depending on the library) to create these dynamic swells and releases in your longer

notes and phrases." Production Expert adds the separate vibrato lane, noting that some libraries

put vibrato on its own controller (CC14) independent of the dynamic one.

a direct quotation about phrase ends slowing and tempos accelerating at building moments, and that

quotation could not be located in any source cited here. Rubato at phrase boundaries is

uncontroversial craft, but this lane has no verified citation for it and it grounds no rule below.

Note what the second and fourth of these imply for us. Both are PHRASE-INDEXED. Our plan schema knows

sections, cycles and patterns; it does not currently know where a phrase begins and ends, so the

breath dip has no anchor to attach to. The phrase grammar built in

docs/proposals/music/craft_research/MOTIVIC_DEVELOPMENT_AND_PHRASE_GRAMMAR.md is the natural

supplier of that anchor and is the reason this hook is cheap rather than expensive.

PIPELINE HOOK — CODE-ABLE. A per-layer expression_envelope derived from the layer's phrase

boundaries: a rise over the first fraction of the phrase, a decline over the last, a declared dip at

each phrase seam for wind and brass families, and a bow-cycle ripple for bowed strings whose period

comes from the notated slur length rather than from a clock.

2.4 Articulation poverty, and the counter-intuitive "less legato" finding

The realism ceiling of a mockup is set by how many different real playing actions it can call on.

Alex Ball's stated first criterion when choosing a library is "as many variations of articulations

as possible", and he cites libraries with three distinct short-note lengths under dynamic control.

Evenant's third tip inverts the beginner's instinct: use MORE articulations and LESS legato — marcato,

détaché, runs, ricochet, portato — and observes that the brass in Star Wars, the Captain America

march and Back to the Future is played marcato and staccato most of the time with legato rare.

Spitfire Chamber Strings ships 244 articulations across 38 shorts, 53 longs, 19 FX and 45 legatos, and

supports layering articulations, switching by CC range, by keyswitch, by velocity range, by MIDI

channel and "By Speed Of Playing" with a configurable millisecond window. That last one is a machine

rule and therefore directly portable: an interval played inside a declared time window selects a

different transition.

CRAFT CONSENSUS, with a caveat for us. Our palette is CC0 and small: 85 entries, largely one or two

articulations per instrument (.sus, .stac, .pizz, .trem, .mute). We cannot buy our way to

244 articulations, so the leverage is in choosing among what we have by rule rather than fixing one

patch per layer for a whole cue — which is what the plan schema does today.

PIPELINE HOOK — CODE-ABLE. Articulation selection per NOTE rather than per layer: a rule that picks

between the .sus and .stac members of the same instrument by notated duration and by the

inter-onset interval, in the manner of Spitfire's speed-of-playing trigger. This requires the layer's

instrument field to become an instrument FAMILY with a per-note resolution, which is a schema change

in pass2_plan.py and a compile-branch change in pass2_realise.py.

2.5 The machine gun, and what our palette actually gives us

The failure mode has a fixed name and a fixed cause. MusicRadar describes it as "the repetitive,

'inhuman' sound of the same sample being used over and over again", which "sounds obviously fake when

played repeatedly". The standard remedy is round robin — several takes of the same note cycled

sequentially or randomly. Spitfire's performance-legato attack layer carries 6 RR specifically to

avoid "the 'machine gun effect' or hearing the same sample again and again", verified verbatim in

the SCS manual's performance-legato section.

MusicRadar adds a rule that is directly portable to a generator and that we would otherwise have

missed: prefer an ODD round-robin count. It recommends "five or seven samples in a 4/4 piece", so the

cycle does not lock in phase with the metre — a 2- or 4-deep round robin on a 4/4 ostinato lands the

same take on the same beat every bar and reads as a deliberate accent pattern rather than as

variation. Our palette declares seq_length=2 on 202 regions, which is exactly the phase-locking

case.

Sound on Sound names the cost, which matters for us more than for anyone else: round robins are

useful but "one potential problem is that they can cause arrangements to never sound the same way

twice". This is why libraries ship a round-robin reset — the SCS manual's Expert View exposes SKIP

THIS RR, and Sound on Sound describes the general mechanism as a reset button that "resets the

instrument's round robin sequence to its start", automatable "by assigning a MIDI note outside the

playable range of the instrument to activate the button, then inserting that MIDI note at the top of

your arrangement", with the further advice to "insert the 'RR reset' note immediately before each

main section in your piece".

Our determinism guarantee survives only because sfizz resets its counter per render; that is a

property we depend on and do not currently assert, and it should become an explicit control rather

than a lucky default. Note that the practice's own reset mechanism is an AUTHORING convenience for a

DAW, while ours is a correctness dependency — which is the stronger reason to assert it.

CORRECTION LOGGED. An earlier draft of this subsection attributed to Sound on Sound the claims that a

fully-featured orchestral instrument "could easily have half a dozen round robins" and that some

EastWest string instruments carry 16. Neither statement appears in Sampled Orchestra Part 9 or Part 3,

and no round-robin count of any kind appears in either. Both were withdrawn. The surviving

deep-sampling evidence for RR counts is Spitfire's own documented 6 RR on the performance-legato

attack layer, above.

Our position, measured (1.5): round robin is present on percussion and absent on the carriers, which

is the wrong way round. Two mitigations are available without acquiring anything. The first is the

lorand/hirand and seq_position machinery already in the format, which we could add in our own

overlay SFZ files where a single instrument has multiple usable samples per key. The second is

cheaper and is what section 3.4 recommends: vary velocity note to note so that repeated notes at

least select different velocity layers where the instrument has them, which converts a machine gun

into an alternation on the 46 palette entries carrying two or more velocity bands.

PIPELINE HOOK — CODE-ABLE. A repeated-note detector on the compiled note list, plus a

velocity-alternation rule when the instrument declares more than one velocity band and no

seq_position. MEASURE-ONLY companion: a per-layer count of immediate same-pitch same-velocity

repeats, reported per cue.

2.6 Sample latency, and the tightness control every library ships

Sound on Sound states the cause exactly: "Orchestral samples almost always 'speak' late, because the

producers (quite rightly) want to preserve the initial, faint stirrings of each sample's note

attack." Every serious library therefore exposes a correction. Spitfire's Expert View calls it SAMPLE

START — "If it feels loose adjust to the right, tight adjust to the left" — and the same manual's

Tightness control makes the trade explicit, noting that cutting into the note "does detract from

realism" and recommending you tighten while playing in, then loosen and put "a negative delay into

your DAW to compensate for ultimate reality". That is the DAW-side equivalent, named by the

manufacturer. The practitioner advice is to "try applying 10, 20, 30 and 40 millisecond advances to

your MIDI regions until the part sounds right", and to note that "expressive strings styles played

with a slow attack often require a surprisingly large amount of timing advancement to sit right in a

track". The correction differs per library and per articulation.

Berklee Online's twelve-week Orchestral Mockups in Film Scoring course teaches "Legato Sample

Pre-Delay" and "Sample Latency and Negative Track Delay/Offset" in Lesson 7, Strings (Part 2) — the

same lesson as long-note string technique, which is a fair statement of how routine the correction

is.

The measured spread on our palette (1.4) is 148.6 ms between the fastest and slowest speaker, which

is larger than the manual advances quoted above because those are corrections for a single library's

house latency and ours is a cross-set correction between percussion and winds.

PIPELINE HOOK — CODE-ABLE. A per-instrument speak_offset_ms, MEASURED from the palette's own

samples rather than declared, subtracted from every onset for that instrument at MIDI-write time.

The measurement is the probe already written for section 1.4 and belongs beside sfz_palette.py as a

derived table with the denominator recorded, in the same style mix_policy.derive already uses.

3. Humanisation: what the evidence actually supports

This is the section where craft folklore and measurement disagree most, so it is built on papers.

3.1 Real ensembles are not together, and the amount is known

Between-player asynchrony in professional ensembles playing at 40–130 bpm is in the tens of

milliseconds, decreasing as tempo rises. Rasch (1979, 1988) measured standard deviations of

between-player asynchrony of 24–73 ms; a string trio averaged 49 ms SD at about 79 bpm and a wind

ensemble 32 ms at 88 bpm. Wing et al. (2014) reported 24 and 28 ms SD for two string quartets at 157

bpm.

The perceptual side bounds the other end, and the sourcing here is weaker than above, so it is

labelled. CRAFT CONSENSUS: onset-discrimination and temporal-order thresholds for musical tones are

conventionally quoted in the region of 20 ms and of roughly 15–35 ms respectively. Those figures are

NOT carried by the Wing et al. article cited for the asynchrony SDs — that paper reports the

ensemble measurements only — and this pass did not locate a primary source for them. Treat them as

an order-of-magnitude bound, not as a measured number. What the verified evidence does support

without them is the comparison that matters: professional ensembles play tens of milliseconds apart

and we play zero milliseconds apart.

Our measured spread is 0.000 ms on three quarters to nine tenths of every note in a cue.

PIPELINE HOOK — CODE-ABLE. A per-note onset perturbation whose scale is declared per stratum and per

tempo, seeded from the cue id so a render stays reproducible. The correct magnitude is NOT the

literature's raw SD — see 3.3.

3.2 Perceptual attack time is the deeper reason quantised is not together

Gordon (1987) defined perceptual attack time as the moment a sound's rhythmic emphasis is heard,

distinct from both its physical onset and the moment it is first audible (the perceptual onset time

of Vos and Rasch, 1981). The size of the effect is large and instrument-dependent: a closed hi-hat's

PAT is a few milliseconds after physical onset, while a slowly bowed violin note can be 50–100 ms

after it.

Bechtold and Senn (2018) measured saxophone PATs between 23 and 83 ms after physical onset across

nine sounds, with a mean per-stimulus standard deviation of 27 ms; tongue-articulated notes had

significantly earlier PAT than untongued ones (large effect), and loud sounds earlier PAT than

medium. Their negative result is the useful one for a pipeline: onset RISE TIME correlated only

weakly with PAT (r = 0.143), so PAT cannot be predicted from an envelope slope alone and must be

measured or approximated from the envelope's ARRIVAL AT A LEVEL rather than its slope.

This is why section 1.4 measured time-to-half-peak rather than time-to-onset: half-peak is a crude

but defensible proxy for the moment the note is heard to happen, and it is derivable from the sample

files we already have.

PIPELINE HOOK — CODE-ABLE. The speak_offset_ms table of 2.6 should be built from a PAT proxy

(time to a declared fraction of peak, per velocity layer) rather than from first non-silence, and the

choice of fraction declared and defended in the emitting file.

3.3 Microtiming is systematic, not random — and less is more than the literal amount

The temptation is to add jitter. The evidence does not support it, and groove.py is already right

to describe its displacement rules as "a rule that displaces, never a random jitter" — that instinct

should be preserved, not overridden, when 3.1 is implemented.

Kilchenmann and Senn (2015) took real swing and funk recordings whose participatory discrepancies

ranged from −67 to +85 ms (swing) and −46 to +58 ms (funk), and rescaled those deviations from full

quantisation to double magnitude in 20% steps, measuring expert listeners' body movement. Full

quantisation was not the best condition, but neither was the original: listeners moved MOST when the

deviations were downscaled by 60%, and the effect was small to moderate and present in experts only.

The operational reading for us is threefold. Deviation should exist. Its magnitude should be well

under the measured ensemble figures — on the order of 40% of them, which lands a 24–49 ms literature

SD at roughly 10–20 ms. And it should be structured, since the deviations that were rescaled in that

study were the systematic discrepancies of a real performance, not noise.

The structure worth encoding, and this is CRAFT CONSENSUS supported by the asynchrony literature's

leader-follower findings rather than proven by it: melody leads or lags the accompaniment

consistently rather than randomly; the bass and the timekeeping layer are the most stable; the

outer voices of a chord are laid slightly around its inner voices rather than all at once.

PIPELINE HOOK — CODE-ABLE. A deterministic per-layer timing profile — a small signed offset per

stratum plus a seeded low-magnitude per-note perturbation bounded by a declared cap — rather than a

uniform random jitter. MEASURE-ONLY companion: report the realised inter-layer onset spread

distribution per cue, so the number in 1.2 stops being 0.000 and becomes a graded axis.

3.4 Velocity variance: vary the repetition, not the shape

Velocity carries two jobs in our stack at once — it is the accent structure AND the only timbral

dynamic control — so humanising it naively would corrupt the composition. The discipline is to

perturb it where it is currently a literal repeat and to leave the composed contour alone.

The measured target is precise: 89–91% of consecutive notes within a layer currently carry an

identical velocity (1.3). Real players do not repeat a dynamic exactly, and on our palette an

identical velocity on a repeated pitch also guarantees the identical SAMPLE, which is the machine gun

of 2.5. A bounded perturbation that never crosses the accent hierarchy — never letting an off-beat

note exceed its own downbeat, never crossing a velocity-layer boundary in a way that inverts the

composed accent — converts a literal repeat into a variant while leaving the shape intact.

PIPELINE HOOK — CODE-ABLE. A post-compile pass over compile_layer's note list: seeded, bounded,

accent-preserving velocity perturbation, with the pre- and post-perturbation accent ordering asserted

identical as a must-fire control.

3.5 Determinism is a constraint, not an obstacle

pass2_realise.determinism requires two renders of the same plan to be bit-identical, and

pass5_realise inherits it. Every humanisation operation above is compatible with that, provided the

randomness is a seeded PRNG keyed on the cue id and the layer id — the same discipline

mix_policy.synth_ir already uses for the impulse response ("Deterministic on seed, so a render is

reproducible"). The determinism check must be preserved and, per 1.5, extended to assert that round

robin actually resets, since we now know the palette uses it.

PIPELINE HOOK — CODE-ABLE. A humanise_seed field on the plan; every perturbation draws from a PRNG

constructed from that seed plus the layer id, never from an unseeded default.

4. Layering, doubling and the orchestral stack

4.1 What doubling actually costs, from the manufacturer

Spitfire's own orchestration page makes two points a generator can be held to. Strings have only five

real voices, and writing more harmonic lines forces divisi — "a smaller, thinner, and quieter

harmonic line" — which is why sampled strings sound implausibly massive: a five-note chord in a

sampled section is "likely to be producing the noise a band of 200 players would make". And octave

doubling of firsts and seconds "gives an emotional epic scale to top lines" and helps sections tune

against each other, at the cost of harmonic richness.

The generator-facing rule is that a section layer playing N simultaneous pitches is asserting a

divisi of N, and the loudness and weight of that layer should fall accordingly rather than rise.

PIPELINE HOOK — CODE-ABLE. A divisi penalty in the layer gain model: a section instrument's effective

gain per pitch scales down with simultaneous pitch count, and a declared cap refuses divisi beyond

what the named ensemble size supports.

4.2 Layering libraries, and the alignment costs

Practitioner practice is to layer more than one library, adding principal-chair close-mic samples

under a section for a live feel, doubling with chamber strings for divisi, and switching library per

passage. The cost is alignment: stereo-field adjustments between blended string libraries are held to

about 10%, because larger corrections break the shared image, and each library's sample latency is

different, which is why 2.6 exists.

We have four CC0 sets (vsco2_ce, vcsl, legato_vocal, body_percussion) and no equivalent of a

second full orchestra, so the transferable part is the DISCIPLINE rather than the practice: when two

sets are layered on one line, their speak offsets must be equalised first and their pans aligned

within a small declared bound.

4.3 What samples should be asked to do

Spitfire's own recommendation is to get "samples to do what they do well (ie hold a high tremolando

ad nauseum, or play complex pizzicato passages) so you can use your live forces for stuff that

matters, like big sweeping melodies." We have no live forces, which makes this a warning rather than

a workflow: the big sweeping melody is the hardest thing to fake and it is precisely what our

melody-first direction demands, so the realism budget belongs disproportionately on the carrier

layers rather than being spread evenly across 32 of them.

CRAFT CONSENSUS. PIPELINE HOOK — CODE-ABLE. A realism budget that is layer-weighted by melodic role:

the layers holding primary melody get controller envelopes, articulation switching and speak-offset

correction first, and a cue is not "realised" until its carriers are.

5. Orchestral mix practice

5.1 Depth is at least four independent cues, and we currently supply one

Sonible's depth rules, which restate standard practice, are: level (inverse-square); relativity, since

depth is only perceived when elements occupy a VARIETY of distances rather than one; high-frequency

attenuation with distance, applied both to the source and additionally to that source's reverb send;

early reflections carrying distance information while late reflections describe the room; pre-delay,

which reads as intimacy in a small space and as distance in a large one; narrowness reading as

distance and width as proximity; and compression revealing transient detail and therefore reading as

proximity.

Our chain supplies level and a shared tail. It supplies no HF attenuation, no early reflections, no

per-element pre-delay, no width variation and no per-element dynamics. mix_policy.SPACE declares

one hf_damp per class, applied to the room and not to the sources, and one predelay_ms per class,

applied to everything equally — which by rule 2 above means it contributes no depth at all, because

depth is a difference and a constant is not one.

PIPELINE HOOK — CODE-ABLE. A per-layer distance scalar in the plan, driving four coupled

quantities at mix time: gain trim, a high-shelf attenuation, the layer's send level into the room,

and its pre-delay. One number the writer can reason about, four consequences a listener can hear.

5.2 Reverb as a send, per section, and the Meyerson model

The score-mixing practice is consistent. Alan Meyerson works with multiple reverbs per stem and

independent reverb sets for strings, brass and percussion, which "gives him space to play with and

build movement", and when choosing a reverb he is "not trying to match the original recording room

but rather build an extension" so that everything reads as one place. Berklee's mockup course

introduces "reverb as send effect" in its first two lessons and returns to routing, bussing and

multi-mic blending in lessons 8–10.

Feazelle's practitioner formulation adds the ordering and the split: convolution first to establish

early reflections, algorithmic after for tail and cohesion; shorter reverb on strings, brass and

winds, longer on percussion; and a single shared subtle bus at around 9% wet under everything to glue

it.

Our chain has one room, applied once, to the sum, at a per-class wet fraction between 0.11 and 0.26.

PIPELINE HOOK — CODE-ABLE. Restructure mix_policy.apply_space from a master-bus insert into a set

of sends: a per-stratum (or per-family) send into a per-family room, plus one shared glue send, with

the sum still measured by the same meter. The synthetic-IR licence position is unaffected — more

sends, same generator.

5.3 Position: pan is not the only tool, and may not be the main one

Meyerson uses inter-channel delay as a placement and width tool: "One of my favorite tricks is to

make use of the Haas Effect. So, if I have an instrument that is stereo in track but a bit mono in

sound, I delay one channel of that track by usually between 150 and 250 samples." At 48 kHz that is

roughly 3.1 to 5.2 ms — comfortably inside the precedence-effect window, which is the property that

makes it read as position and width rather than as an echo.

CORRECTION LOGGED, and it narrows the claim. An earlier draft of this subsection stated that Meyerson

requests separate high, mid and low string stems and that he uses delay "instead of panning to

simulate section positions". Neither survives verification. The interview describes stem reverbs

split by SECTION (strings, brass, percussion), not by register, and the Haas trick is described as a

fix for a stereo track that sounds mono — a width treatment — not as a declared substitute for

panning. The transferable finding is narrower than the withdrawn one but still decides our rule: a

first-call score mixer places and widens with small inter-channel delays in the low-single-digit

milliseconds, so amplitude pan is demonstrably not the only tool in professional practice.

Spitfire records its players in situ — "Recorded in situ (ie: in the positions they would sit as a

section)" — and its Expert View exposes a STEREO WIDTH control and a CLOSE PAN MIC COLLAPSER rather

than a simple pan knob, precisely because the position is already in the recording. The manual is

explicit that the in-situ seating gives "a fantastic spectral spread when putting all the elements

together, which helps define the detail."

Our palette is CC0 mono-ish material with no in-situ imaging, so the position has to be synthesised.

Constant-power amplitude panning, which is what _pan does, is the weakest of the available tools; a

small inter-channel delay plus a level difference is closer to how the ear locates a source in a

hall.

CRAFT CONSENSUS. PIPELINE HOOK — CODE-ABLE. Replace the pure amplitude pan with a combined

level-plus-delay placement, bounded so the delay stays inside the precedence-effect window, and

derive both from a declared seating position per family rather than from a free-floating pan number.

5.4 EQ discipline

The practitioner numbers are conservative and consistent: avoid boosting or cutting more than 3–4 dB

and typically use 1–2 dB; cut low-frequency build-up on mid-range instruments (violins, violas,

clarinets) so the cellos, trombones and basses stay clear; and roll the low end off reverb sends to

stop the room turning to mud.

We do none of this, and we currently sum up to 34 parts with no low-end management whatsoever, which

is the most likely single contributor to a render reading as congested.

PIPELINE HOOK — CODE-ABLE. A per-family corrective EQ table with a hard bound on the permitted

magnitude, plus a high-pass on every reverb send, declared as numbers a reader can argue with in the

same style mix_policy.SPACE already uses.

5.5 Gain staging and the limiter

Feazelle records individual parts at −12 to −6 dB so tutti passages do not overwhelm the master, and

applies subtle compression at multiple stages before the master bus rather than heavy compression at

the end. Berklee's final block is "mixbus processing, stem mastering, gain staging, limiting, dither".

mix_policy.LIMITER is well reasoned and its probe is exemplary — 6, 9 and 12 dB tested with the

whole floor battery re-run at each, and the arc unchanged to two decimals at 9 dB. Its _why_this_shape

note is also correct that the residual is a doctrine limit. What section 6 adds is that the residual

may not need closing at all.

6. Loudness: three denominators, and only one of them is ours

6.1 The primary standard, verbatim

ASWG-R001 v1.10 (August 2013), the Sony Worldwide Studios Audio Standards Working Group

recommendation, is the industry's reference document and its numbered recommendations are exact:

"and that this tolerance is acceptable considering the non-linear nature of interactive

entertainment audio content" (rec. 4).

ITU-R BS.1770-3 and EBU Tech 3341 (rec. 7).

(recs. 2 and 3).

music specifically" (rec. 9).

over a representative cross-section of gameplay (rec. 10).

filtering and surround-to-stereo downmix as processes that raise peak levels.

ARIB, and that LKFS and LUFS "are identical and interchangeable".

Recommendation 9 is the one that decides our case: the ASWG number is a property of the WHOLE

programme, not of a music asset. A music stem authored at −24 LUFS would be wrong, because at runtime

it is one of several buses summing to that figure.

Note a source disagreement, resolved in favour of the primary. Wang's 2023 master's thesis states the

Sony standard as −23 LUFS with a −2 dBTP ceiling; the ASWG document itself says −24 (±2) LKFS and −1

dBTP. The primary document is authoritative and the thesis appears to be quoting the pre-2013 revision

for the target and to be in error on the ceiling.

6.2 What shipped games actually measure, per section

Wang (2023) measured nine shipped titles per audio section (LUFS):

titlemain dialogueweapon / attack SFXbackground music (combat)background music (exploring)
Assassin's Creed Odyssey−23−25−35−38
Assassin's Creed Syndicate−23−26−35−37
Cyberpunk 2077−20−24−26−30
Final Fantasy VII Remake−20−21−25−30
Ghost of Tsushima−21−20−26−30
Hogwarts Legacy−20−21−23−30
The Last of Us Part II−20−20−30−38
The Witcher 3−23−25−30−35
Uncharted 4−20−20−35−40
average−21.1−22.4−29.4−34.2

The thesis's derived hypothesis is main dialogue −21 (±3), sound effects −23 (±3), combat music −29

(±6) and exploration music −35 (±6). Treat the exact figures with the caution the method deserves —

these are measurements of gameplay capture, not of asset files — but the STRUCTURE is the robust

finding and it is large: in shipped AAA games the music bed sits roughly 8 LU below dialogue in

combat and roughly 13 LU below it in exploration, and exploration music sits about 5 LU below combat

music.

6.3 Why our corpus target is the wrong bar for a cue file

mix_policy.derive measures commercial soundtrack ALBUM masters. Those are mastered for standalone

listening and for streaming normalisation, and the file's own note already concedes that the corpus

median "is a median of commercial masters shaped by multiband compression, saturation and clipping —

none of which this chain does". A BATTLE target of −9.84 LUFS is a plausible album number and is

about 20 LU above where combat music actually sits inside a game.

So clears_target: false on all three published cues, and the limiter built to chase it, are

answering a question about album delivery. The right question for an asset is different and has two

parts: is the cue at a stable, declared house reference so that a hundred cues sit consistently

against each other, and does it leave enough headroom that the runtime music bus can be pulled down

to its in-game level and pushed back up for a stinger without either clipping or running out of

resolution.

RECOMMENDATION, and it is a recommendation rather than a finding. Keep the corpus measurement as a

published diagnostic — it is honest evidence about what loved tracks do — and stop treating it as the

pass/fail bar for an asset. Author cue files to a single declared house reference with the true-peak

ceiling held at −1 dBTP per ASWG rec. 7, keep the corpus deviation as a reported number, and move the

in-game placement to a runtime mix document that owns the relationship between dialogue, SFX and the

music bus. The limiter then becomes an option rather than a corrective, which is the position its own

_why_this_shape note argues for anyway.

6.4 Loudness range

ASWG requires LRA to be reported per EBU Tech 3342. Our corpus medians run from 2.98 LU (BATTLE) to

10.66 LU (TENSION), and our published cues measure 8.45, 11.91 and 12.25 LU — wider than the corpus

in every class. That is a real and probably good property of a cue with composed drops, and it is

exactly the property a limiter chasing an album target would erode. It is another argument for

holding the limiter to the bounded, arc-verified role mix_policy already gives it.

7. What can actually be graded

Ordered by how much a measurement can be trusted.

layer carries continuous controller data; variance of that data per phrase; count of

physical-implausibility violations per 2.2. All computable from the emitted MIDI before a sample is

loaded.

simultaneity, in milliseconds, against the 3.1 band. Currently 0.000 everywhere.

has been corrected by the instrument's measured PAT proxy.

layer and per minute — the machine-gun index of 2.5.

every layer is at one distance scores zero by construction, which is the current state.

controlled against ffmpeg's ebur128, and already carrying LRA and true peak. Nothing to add but the

denominator discipline of 6.3.

build-up of 5.4 exists; it cannot say which layer caused it. Report as a proxy, in the register

lane_analysis.confidence already uses.

honest tier for anything this document unblocks is STRUCTURE + MEASURED PERFORMANCE DATA. A listen

remains a listen.

SOURCES

Citation verification log — 2026-08-08

An independent citation-reality pass sampled 20 of the sources below, fetching each and checking that

it exists and says what this document claims. Result: the numeric spine of the document is sound and

the practitioner layer had six defects, all now repaired in place.

Confirmed verbatim, with every number checked: ASWG-R001 v1.10 (all eleven recommendations, the

considerata, and the −23 to −24 LKFS revision note); Wang 2023 (the nine-title table row for row, the

−21.1 / −22.4 / −29.4 / −34.2 averages, and the Table 3 hypothesis); Bechtold and Senn 2018 (23–83 ms

PAT, 27 ms mean SD, r = 0.143); Kilchenmann and Senn 2015 (−67/+85 ms swing, −46/+58 ms funk, 20%

steps, the 60%-reduction peak, small-to-medium, experts only); Wing et al. / PMC4196478 (Rasch's

24–73 ms range, the 49 ms trio at 79 bpm, the 32 ms wind ensemble at 88 bpm, and 24 and 28 ms at

157 bpm); the Spitfire Chamber Strings manual (every quotation, including the velocity-to-transition

map, the 6 RR, SAMPLE START, the divisi and octave-doubling passages, and "By Speed Of Playing");

Gordon 1987; Wright 2008; the Feazelle numbers; the sonible nine rules; Sound on Sound Parts 3 and 9;

and the Berklee syllabus.

Repaired: (1) a Sound on Sound attribution for round-robin counts — "half a dozen" and EastWest at 16

— that appears in neither cited part; (2) two invented machine-gun quotations attributed to

MusicRadar; (3) two invented linked-CC quotations in section 2.2; (4) a Meyerson claim about high/

mid/low string stems and delay "instead of panning", which the interview does not support; (5) an

overstatement that Production Expert lists "simulate breathing" as a discrete technique; (6) a

non-existent Cinematic Composing course title. Also tightened: the Berklee lesson numbering, and a

perceptual-threshold figure in section 3.1 that the cited paper does not carry.

Every repair narrowed a claim or withdrew a quotation. None of them changed an ADOPTED rule, because

each affected rule rests on a measured number from section 1 or on a source that survived

verification — and one verified source added a rule we had missed (7b, the odd alternation period).

Standards and primary specifications

CONTENT ON SONY COMPUTER ENTERTAINMENT PLATFORMS, Recommendation ASWG-R001 v1.10, August 2013.

http://gameaudiopodcast.com/ASWG-R001.pdf (7 pages; recommendations 1–11 read in full).

levels. Cited by ASWG-R001 as its measurement basis; BS.1770-4 is the version implemented in

harness/music_gen/mix_policy.py.

http://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.1770-3-201208-I!!PDF-E.pdf

http://tech.ebu.ch/docs/tech/tech3341.pdf · http://tech.ebu.ch/docs/tech/tech3342.pdf

https://sfzformat.com/opcodes/seq_position/ and https://sfzformat.com/opcodes/xfin_loccN/

https://github.com/sfztools/sfizz/issues/23

Manufacturer manuals

ORCHESTRATION PRINCIPLES" (divisi, octave doubling, agility, range), "LEGATO" and "PERFORMANCE

LEGATO" (velocity-to-transition mapping, 6 RR), and "THE EXPERT VIEW" (SKIP THIS RR, ADJUST

RELEASE, SAMPLE START, UACC on CC#32, articulation triggering by CC range / keyswitch / velocity /

MIDI channel / speed of playing, microphone mixer, close-mic pan collapser, stereo width).

http://spitfire-www-assets.s3.amazonaws.com/manuals/SpitfireChamberStrings_UserManual.pdf

Peer-reviewed research

Society of America, 82(1), 88–105. https://pubmed.ncbi.nlm.nih.gov/3624645/

29(4), 323–335.

Probability Density Functions. PhD dissertation, Stanford University (CCRMA).

https://ccrma.stanford.edu/~matt/diss/Matthew-Wright-Dissertation.pdf

of saxophone sounds. Frontiers in Psychology, 9, 1692. https://doi.org/10.3389/fpsyg.2018.01692

behavior of music expert listeners. Frontiers in Psychology, 6, 1232.

https://doi.org/10.3389/fpsyg.2015.01232

synchronisation, as summarised with the numeric SDs in: Wing, A. M., Endo, S., Yates, T., and

Bradbury, A. Perception of string quartet synchronization. PMC4196478.

https://pmc.ncbi.nlm.nih.gov/articles/PMC4196478/ — VERIFIED verbatim 2026-08-08 for the whole

numeric set used in section 3.1: asynchrony SD "typically in the 10s of milliseconds range" for

professional ensembles at 40–130 bpm; "In a string trio (violin, viola, and cello) the average

between-player asynchrony SD was 49 ms (at an average 79 bpm) while the corresponding value for a

wind ensemble (oboe, clarinet, bassoon) was 32 ms (at 88 bpm). The range was 24–73 ms"; and "Wing

et al. (2014) reported figures for asynchrony SD of 24 and 28 ms (at 157 bpm) for two string

quartets". This article does NOT carry the onset-discrimination or temporal-order thresholds, which

section 3.1 now labels CRAFT CONSENSUS accordingly. See also Optimal feedback correction in string

quartet synchronization, PMC3928944, https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3928944/

(Oxford). https://academic.oup.com/book/8555/chapter/154427776

set). https://en.wikipedia.org/wiki/Perceptual_attack_time

Theses and industry surveys

Loudness Standards for Each Section of Game Audio. Master Degree Project in Informatics, University

of Skövde. Supervisor Mikael Johannesson, examiner Per Backlund.

https://his.diva-portal.org/smash/get/diva2:1790653/FULLTEXT01.pdf — Tables 1–3 (per-section

loudness of nine shipped AAA titles) are the source of section 6.2.

Routledge, 2023 (ISBN 9781032406930) — on game-audio dynamic range and the final-mix stage.

https://www.routledge.com/Working-with-Sound-The-Future-of-Audio-Work-in-Interactive-Entertainment/Bridgett/p/book/9781032406930

https://www.gamedeveloper.com/audio/the-game-audio-mixing-revolution

Courses and structured curricula

for its lesson ordering. VERIFIED 2026-08-08, with the lesson numbers corrected from an earlier

draft: reverb as a send effect is Lesson 2 (Basic Template and Reverb Setup); "Legato Sample

Pre-Delay" and "Sample Latency and Negative Track Delay/Offset" are Lesson 7 (Strings, Part 2);

multi-mic blending is Lesson 8 (Reverb and Room Placement); routing, bussing and stem concepts are

Lesson 10 (Stereo Panning and Audio Routing/Stem Concepts); mixbus processing, stem mastering, gain

staging, limiting and dither are Lesson 11 (Final Mixing and Mastering). Lesson 12 is touchscreen

controllers and networked host setups and is not cited here.

https://online.berklee.edu/courses/orchestral-mockups-in-film-scoring

Orchestral Mockups". CORRECTION 2026-08-08: an earlier draft cited a course titled "Symphonic

Virtual Orchestration: Orchestral Mockup Production" attributed to Marc Jovani. No course of that

name appears in the catalogue and the instructor attribution could not be confirmed; the title is

withdrawn. This entry grounds no claim in the body. https://cinematiccomposing.com/course786833

Score-mixing practice

the only one of the three that yielded fetchable text. VERIFIED verbatim 2026-08-08 for: "I use

multiple reverbs per stem and have the stem reverbs independent. So, my strings would have a set of

reverbs, brass another set, percussion another etc. This gives me a lot of space to play with and

build the movement"; building "an extension to that room" rather than matching the original; and

the Haas trick, "I delay one channel of that track by usually between 150 and 250 samples".

https://film-mixing.com/2016/07/28/film-score-mixing-with-alan-meyerson/

returns HTTP 403 to automated fetching and NO claim in this document rests on it.

https://mixwiththemasters.com/videos/alan-meyerson-reverb-programs

feature whose page carries no fetchable technical text, and no claim here rests on it.

https://www.soundonsound.com/people/alan-meyerson-mixing-movies

https://vi-control.net/community/threads/alan-meyerson-tips-for-mixing-sampled-orchestra.11849/

https://www.waves.com/get-more-from-reverb

Practitioner tutorials and community standards

Taming The Robin" is the cited text (round robins, the machine-gun effect, and the round-robin

reset mechanism). VERIFIED 2026-08-08; note that this article gives NO round-robin counts and does

not mention EastWest, contrary to an earlier draft of section 2.5.

https://www.soundonsound.com/techniques/sampled-orchestra-part9

September 2017 — the sample-latency source: samples "speak" late, negative track delay, the 10/20/

30/40 ms advance ladder, and slow-attack expressive strings needing large advancement. VERIFIED

verbatim 2026-08-08. https://www.soundonsound.com/techniques/sampled-orchestra-part3

actual scope is narrower than an earlier draft implied: it is a MIDI-CC article covering CC1 as

dynamic-layer crossfade, CC11 as expression and agogic shaping, CC64 for articulation triggering,

vibrato on its own controller (CC14 in some libraries), drawing CC curves by hand, and avoiding

unnatural curve combinations. It does NOT list "simulate breathing" as a discrete technique —

breathing appears once, as the reason to shape CC11 ("an oboist or a singer who needs to breathe

between phrases") — and it does not discuss round robins or timing humanisation at all.

https://www.production-expert.com/production-expert-1/how-to-improve-realism-in-orchestral-mock-ups

practitioner source found: EQ bounds, record levels, reverb ordering and split, 9% glue bus, 10%

stereo-field limit, vertical bar-by-bar programming). VERIFIED 2026-08-08 — every number used in

sections 4.2, 5.2, 5.4 and 5.5 was confirmed against the article, including the 3–4 dB maximum and

1–2 dB typical EQ bound (attributed there to Jake Jackson), the −12 to −6 dB part-recording level

(Marc Jovani), the convolution-then-algorithmic ordering with shorter reverbs on strings/brass/

winds and longer on percussion (Di Stefano), the 9% glue-bus mix, the 10% stereo-field adjustment

limit, and the Alex Ball articulation-first library criterion.

https://andrewfeazelle.com/how-to-make-an-orchestral-sample-library-sound-real/

to real recordings; polish your orchestration; use more articulations and less legato patches;

bring life to it with dynamics; let the virtual musicians breathe. Sources the marcato/staccato

film-brass observation and the crescendo-into / decrescendo-out-of phrase rule (tip 4, not tip 5).

It does NOT discuss tempo variation and does not describe layered dynamic-plus-vibrato controller

motion — both were attributed to it in an earlier draft and are withdrawn.

https://www.evenant.com/articles/5-tips-to-improve-your-orchestral-mockups

quotations that section 2.2 previously attributed to practitioner sources; those are withdrawn.

https://evenant.com/utilizing-dynamics-for-realism/

machine-gun definition used in section 2.5 ("the repetitive, 'inhuman' sound of the same sample

being used over and over again") and of the ODD-COUNT rule — it recommends "five or seven samples

in a 4/4 piece" so the round-robin cycle does not lock in phase with the metre. VERIFIED

2026-08-08.

https://www.musicradar.com/tuition/tech/how-to-avoid-the-machine-gun-effect-using-round-robin-sampling-632302

"Rant about cc1 cc11 and velocity"

https://vi-control.net/community/threads/rant-about-cc1-cc11-and-velocity.168479/ ;

"Is CC#11 (expression) just volume?"

https://vi-control.net/community/threads/is-cc-11-expression-just-volume.72676/ ;

"The difference between 'Dynamics' (CC#1) and 'Expression' (CC#11)?"

https://vi-control.net/community/threads/the-difference-between-dynamics-cc-1-and-expression-cc-11.58127/ ;

"Poll - How do you use Dynamics and Expression?"

https://www.vi-control.net/community/threads/poll-how-do-you-use-dynamics-and-expression.101377/ ;

"A guide to sample Delay/Latency, Offset/Negative Track Delay & Look Ahead"

https://vi-control.net/community/threads/a-guide-to-sample-delay-latency-offset-negative-track-delay-look-ahead-smart-delay.161372/ ;

"Orchestral Instruments Delay Offset"

https://vi-control.net/community/threads/orchestral-instruments-delay-offset.117434/

(Note: vi-control.net returns HTTP 403 to automated fetching; these threads were read through

search-engine extracts, and the claims drawn from them are labelled CRAFT CONSENSUS rather than

cited as primary text.)

Measured in-repo during this pass (the evidence behind section 1 and GAP NOTES; not external

sources, listed so the numbers are reproducible).

determinism; harness/music_gen/pass5_realise.py in full; harness/music_gen/mix_policy.py in

full; harness/music_gen/orchestrate.py _sfizz, _pan, _wrap_release;

harness/music_gen/complete_track.py _write_part_midi and write_score_midi;

harness/music_gen/sfz_palette.py PALETTE, SETS, PLAYER.

build/audio/pass5/LOUDNESS_REPORT.json.

sfizz_render 1.2.3 at D:/audio/tools/sfizz-1.2.3-win64, invoked with the pipeline's own flags.

ACTIONABLE RULES

Each rule names the file that owns it and the operation. Tier is CODE-ABLE unless marked otherwise.

On harness/music_gen/pass2_realise.py (the renderer both pass 4 and pass 5 call)

1. EMIT CONTROLLER DATA. _write_midi gains an expression stage that writes CC11 events for each

part. Without this, none of rules 2–5 can reach the sampler. Precedent already exists in

complete_track.write_score_midi (CC11) and complete_track._bend_events (pitch bend), which

proves the mechanism; the defect is that neither is on a render path.

2. SHAPE THE PHRASE, NOT THE CUE. The CC11 stream is derived per layer from phrase boundaries — rise

into the phrase, decline out of it, a declared dip at every phrase seam for wind and brass

families, a bow-cycle ripple for bowed strings. A single cue-wide envelope copied to every part is

the linked-CC failure of 2.2 in another costume and must be refused.

3. PLAUSIBILITY VALIDATOR. Refuse any emitted stream where a loud dynamic level coincides with a low

expression value beyond a declared tolerance, and any sustained note longer than a declared length

whose expression stream has zero variance.

4. SPEAK-OFFSET CORRECTION. Subtract a per-instrument speak_offset_ms from every onset at

MIDI-write time. The table is MEASURED from the palette's own samples (time to a declared fraction

of peak, per velocity layer) and emitted with its denominator, in the style of mix_policy.derive.

Measured spread today: 148.6 ms between fastest and slowest palette speaker, uncorrected.

5. ENSEMBLE SPREAD. Add a deterministic per-layer timing profile: a small signed per-stratum offset

plus a seeded, bounded per-note perturbation. Target a realised inter-layer spread on the order of

10–20 ms — roughly 40% of the 24–49 ms measured in real ensembles, per the Kilchenmann and Senn

downscaling result — never the literature's raw SD, and never unseeded noise.

6. VELOCITY VARIANCE, ACCENT-PRESERVING. A post-compile bounded perturbation that breaks literal

repeats without reordering the accent hierarchy, with a must-fire control asserting the accent

ordering is unchanged. Current literal-repeat rate: 89–91%.

7. REPEATED-NOTE ALTERNATION. Where an instrument declares two or more velocity bands and no

seq_position, force consecutive same-pitch notes onto different bands. This is the only

machine-gun mitigation available on 39% of our melodic layers without acquiring samples.

7b. PREFER AN ODD ALTERNATION PERIOD. Where we author overlay SFZ round robins, or where the

velocity-alternation of rule 7 sets its own period, make that period ODD relative to the metre —

MusicRadar's "five or seven samples in a 4/4 piece". An even period on a duple cycle lands the

same take on the same beat of every bar, which reads as a deliberate accent pattern rather than

as variation. Our palette declares seq_length=2 on 202 regions, so the phase-locked case is our

default case, and rule 7's naive two-band alternation would reproduce it exactly.

8. ARTICULATION PER NOTE. Resolve .sus versus .stac (and .pizz, .trem where present) per note

from notated duration and inter-onset interval, in the manner of Spitfire's speed-of-playing

trigger. Requires a schema change in pass2_plan.py from instrument-per-layer to family-per-layer.

9. FIX THE STALE CLAIM AND ARM THE CONTROL. The docstrings in pass2_realise.determinism and

orchestrate.py asserting the palette does not use round-robin opcodes are false (20 of 85 use

seq_position, 10 use lorand). Correct the text and convert the determinism check into an

explicit assertion that sfizz's sequence counter resets per render, since our reproducibility now

depends on it knowingly.

10. SEED EVERYTHING. A humanise_seed on the plan; every perturbation draws from a PRNG built from

that seed plus the layer id. Determinism is preserved by construction, as mix_policy.synth_ir

already does for the impulse response.

On harness/music_gen/mix_policy.py

11. DEPTH AS ONE NUMBER WITH FOUR CONSEQUENCES. A per-layer distance scalar drives gain trim, a

high-shelf attenuation, send level into the room, and pre-delay. A constant pre-delay applied to

everything contributes no depth, because depth is a difference.

12. SENDS, NOT AN INSERT ON THE SUM. Restructure apply_space into per-family sends into per-family

rooms plus one shared glue send at a small wet fraction, following the Meyerson multi-reverb model

and Feazelle's convolution-then-algorithmic ordering. The synthetic-IR licence position is

untouched: more sends, same generator, still no third-party asset.

13. HIGH-FREQUENCY DISTANCE CUE. Attenuate highs on both the source and, more strongly, its send, per

the inverse of the depth rules. This is the depth cue we are missing that costs the least.

14. CORRECTIVE EQ WITH A HARD BOUND. A per-family table, bounded at 3–4 dB and typically 1–2 dB,

cutting low-mid build-up on the mid-register instruments so the low instruments stay legible, plus

a high-pass on every reverb send. Declared as arguable numbers in the style of SPACE.

15. PLACEMENT BY LEVEL AND DELAY. Replace the pure constant-power _pan (in orchestrate.py) with a

bounded level-plus-inter-channel-delay placement derived from a declared seating position per

family.

16. SEPARATE THE DENOMINATORS. MIX_POLICY.json must carry three distinct, labelled quantities: the

corpus album median (diagnostic), the ASWG whole-programme figure of −24 (±2) LKFS home and −18

(±2) LKFS portable with the −1 dBTP ceiling (compliance, and a property of the game, not of a

cue), and a declared HOUSE ASSET REFERENCE that cue files are actually authored to.

clears_target must read against the third, not the first.

17. HOLD THE CEILING, KEEP THE HEADROOM. −1 dBTP per ASWG rec. 7, retained. The existing

_why_ceiling reasoning — that a game mix sums with SFX and dialogue at runtime — is exactly

right and is reinforced by ASWG's considerata (e) and (f) on runtime DSP and downmix headroom.

18. REPORT LRA, DO NOT CRUSH IT. LRA is an ASWG-required descriptor (rec. 3, EBU Tech 3342). Our cues

measure 8.45 to 12.25 LU against corpus medians of 2.98 to 10.66. That width is a property of

composed drops and the limiter must keep deferring to the arc battery, exactly as _why_this_shape

already specifies.

On harness/music_gen/pass5_realise.py

19. HONEST TIER UPDATE. TIER_NOTE currently says "no player has touched a note of it", which is

accurate and should stay. When rules 1–10 land, the tier line gains "MEASURED PERFORMANCE DATA"

and must NOT gain any claim about sounding real — no feature in the rig licenses that verdict.

20. NEW SELF-TEST CHECKS. Extend self_test past W1–W5 to assert: controller data present on every

sustained-carrier part; speak-offset table derived on this box (the same shape as the existing W3

"policy is DERIVED, not the fallback" check); and realised inter-layer onset spread non-zero.

On the grading rig (a new instrument beside harness/music_gen/floor_instruments.py)

21. Six symbolic axes, all exact and all computable before a sample loads: controller presence and

variance, inter-layer onset spread distribution, speak-offset compliance, repeated-note index,

velocity-repetition rate, depth spread. Calibrate every threshold on the exemplar corpus before

setting it, because a target derived from our own generator's output is not a bar.

WHAT WE ADOPT

Adopted, in priority order, with the reason each earns its place.

difference between our renders and every practice surveyed, the mechanism is already proven

elsewhere in our own repo, and CC11 is measurably live on our palette today. Everything else in

this document is smaller than this.

correct deterministically, and verify — the cheapest large win available, and it costs no schema

change to the plan.

ensemble magnitudes rather than at literature scale, and as a per-stratum RULE plus small

perturbation rather than as jitter. groove.py's existing refusal of random jitter is upheld, not

overturned — the addition is a bounded seeded layer beneath composed displacement, not a

replacement for it.

in our own docstrings and should land immediately regardless of the rest. Rule 7b — the odd

alternation period — was added by the 2026-08-08 citation-verification pass and matters more than

its size suggests: without it, rule 7's two-band alternation would reproduce the same phase-locked

accent artefact it was written to remove, on every duple cue we generate.

change a decision: the loudness "failure" on all three published cues is substantially a

denominator error, and the honest fix is to publish all three numbers rather than to push a

limiter harder.

Depth applied to a performance with no dynamics only makes the flatness more audible; the ordering

matters.

immediate build. It is the highest-ceiling item here and the most invasive; it should follow the

controller lane so its benefit is measurable against a moving baseline rather than a flat one.

exist to unblock the named artifact — a cue whose realisation is believable — and each must name it.

No axis lands without the operation it grades.

Explicitly NOT adopted.

palette (0.00e+00 effect, 0 of 85 files). Revisit only if a CC1-crossfaded set enters the stack or

we author overlay SFZ files.

DISCIPLINE is adopted for the sets we do layer; the practice is not.

document licenses that. The honest tier ceiling this lane can reach is STRUCTURE + MEASURED

PERFORMANCE DATA + MEASURED MIX.

GAP NOTES

Deviations already visible between the named stack files and the practice found above. The audit

phase consumes this list. Every number was measured during this pass.

GAP-VO-01 — pass2_realise.py::_write_midi writes ZERO continuous controller events, and so does

complete_track.py::_write_part_midi. Every note in every published cue is a note-on/note-off with a

fixed velocity. The industry's primary and secondary realism tools are both simply absent from the

signal path. complete_track.py::write_score_midi DOES write a CC11 envelope but its output is the

notation seam and is never rendered — the mechanism exists in the repo and has never been connected

to a sampler. SEVERITY: highest. Everything else in this list is smaller.

GAP-VO-02 — CC1 is inert on our palette. Zero of 85 SFZ files declare locc1, xfin_locc1 or any

_oncc1 modulation, and a rendered probe of a CC1 ramp from 10 to 127 produced a max sample-wise

difference of exactly 0.00e+00 against a no-CC render on horn.sus, clarinet.sus and trombone.sus. The

practice's central instruction — keep the modwheel moving on every long note — cannot be executed on

this stack without authoring overlay SFZ files. CC7 and CC11 do work (3.5e-02 to 5.5e-02 max

difference on the same probe), so the available continuous lane is level-only, which is precisely the

"volume does not simulate dynamics because the timbre is unchanging" failure the community names.

GAP-VO-03 — compile_layer places every onset at exact grid arithmetic, so nominally simultaneous

notes from different layers carry identical floating-point timestamps. Measured inter-layer spread:

0.000 ms across 74.4%, 93.3% and 91.5% of all notes in FALLS, ROAD and ROUNDS respectively, with

clusters up to 17 layers wide. The measured norm for professional ensembles is 24–73 ms SD (Rasch),

24–28 ms at 157 bpm (Wing et al.), and the ear's onset-discrimination threshold is around 20 ms.

GAP-VO-04 — No per-instrument speak-offset correction exists anywhere in the chain. Measured on our

own sample files, time to half peak ranges from 3.3 ms (conga) to 151.9 ms (clarinet.sus), median

47.6 ms across 22 probed instruments, spread 148.6 ms. A written downbeat therefore arrives as a

staggered event with percussion first and the tune-carrying winds last by up to a seventh of a

second. Every serious library ships a correction for this (Spitfire's SAMPLE START; DAW negative

track delay) and Berklee's mockup curriculum teaches it as routine. We have none.

GAP-VO-05 — Velocity is a per-section step function. `vel = base_vel * vscale * (0.55 + 0.65 *

inten)` contains no per-note variation, and 89.4% to 91.3% of consecutive notes within a layer carry

an IDENTICAL velocity. Three layers in each cue carry three or fewer distinct velocities across the

entire piece. On an instrument with velocity layers, an identical velocity on a repeated pitch also

guarantees the identical sample, which is the machine-gun effect by construction.

GAP-VO-06 — The docstrings in pass2_realise.determinism and orchestrate.py assert that "the

palette's SFZ files do not use" round-robin and random opcodes. FALSE: 20 of 85 palette entries

declare seq_position and 10 declare lorand; the palette declares seq_length=2 on 202 regions,

=6 on 6 and =3 on 3; and a rendered eight-repeat probe on conga, bass_drum and woodblock shows

real two-way alternation with 0 of 7 identical repeats. The determinism check passes only because

sfizz resets its sequence counter per render — an undeclared dependency our reproducibility now rests

on. This is a stale-claim defect of exactly the class CLAUDE.md's verification discipline warns about

("trust content, not labels").

GAP-VO-07 — Round-robin coverage is inverted relative to need. By family: drum 7/9, rattle 2/2,

struck_wood 1/2 — versus woodwind 1/13, brass 1/7, strings 4/21, tuned_perc 1/7, plucked 0/3, voice

0/4. Across the three pass-5 cues, 11 of 28 melodic and figural layers (39%) run on an instrument

with no round robin at all. The variation we have is on the layers a listener does not follow.

GAP-VO-08 — Dynamic-layer depth is thin and unmeasured. Velocity-band census across the palette: 20

instruments have no velocity bands at all, 12 have one, 27 have two, 8 have three, 13 have four, 5

have six. So 59 of 85 have two bands or fewer, and on those the only "dynamic" reachable is amplitude.

Nothing in the pipeline records this, so a plan can assign a soaring dynamic arc to an instrument

physically incapable of expressing one.

GAP-VO-09 — Articulation is fixed per layer for a whole cue. layer["instrument"] names one SFZ file

and compile_layer never changes it, so a line cannot move between sustain and staccato as its note

lengths change. The practice runs the other way — "use more articulations, less legato" — and the

libraries ship machine rules for it (Spitfire's trigger by velocity range, by CC range, and by speed

of playing with a configurable millisecond window).

GAP-VO-10 — No note-overlap or legato handling. _write_midi writes end = start + max(dur, 0.03)

with no overlap, and the compiler comment records that "sfizz stops a sample at note-off". Legato

transition sampling is the single most-cited realism feature in every manual read here, and even

without transition samples a small deliberate overlap on slurred material versus a deliberate gap on

detached material is a distinction our renders do not make.

GAP-VO-11 — mix_policy.apply_space is one room, applied once, as an INSERT on the finished stereo

sum. Score-mixing practice is per-section sends into per-section rooms plus a shared glue bus, and

the mockup curricula introduce "reverb as a send" in their opening lessons. One room on the sum

cannot produce depth, because depth is a difference between elements and there is none.

GAP-VO-12 — The synthetic IR has no early reflections, which the code declares honestly ("a DIFFUSE

FIELD with no early-reflection geometry… That limit is declared rather than papered over"). Early

reflections are the cue that carries DISTANCE information; late reflections describe the room. So the

one spatial dimension we generate is the one that does not place instruments.

GAP-VO-13 — Pre-delay and HF damping are per CUE CLASS, not per layer: every instrument in a cue gets

the same predelay_ms (10.0 to 22.0) and the same hf_damp (0.28 to 0.55). A constant applied to

everything supplies zero depth spread. There is no per-layer distance parameter in the plan schema at

all.

GAP-VO-14 — There is no EQ anywhere in the render or master chain. A grep for filter design across

pass2_realise.py, orchestrate.py and mix_policy.py finds biquads only inside the loudness

meter's K-weighting. Cues sum up to 34 parts with no low-mid management and no high-pass on the

reverb send, against practitioner guidance to cut low build-up on mid-register instruments and to

high-pass reverb returns. Bound to observe: 1–2 dB typical, 3–4 dB maximum.

GAP-VO-15 — Positioning is amplitude pan only. orchestrate._pan is a constant-power amplitude pan

on an already-stereo stem, with a static per-layer pan number. Meyerson's documented practice adds

inter-channel delay as a placement and width tool — one channel delayed by 150 to 250 samples, about

3.1 to 5.2 ms at 48 kHz — and Spitfire records players in situ and exposes width and collapse

controls rather than a pan. Our palette carries no in-situ imaging at all, so the position must be

synthesised, and the weakest available tool is the only one in use. Scope note: the source supports

delay as a width and placement technique; it does NOT state that delay replaces panning for section

positioning, and this entry no longer claims that it does.

GAP-VO-16 — Per-layer gain is static for the whole cue. part["gain_db"] is applied once as a scalar

in render. There is no balance automation, so the practice of riding a section down when it is

accompanying and up when it takes the tune — which is most of what a score mixer does — has no

representation in the pipeline.

GAP-VO-17 — The loudness target has one denominator and reads as three. MIX_POLICY.json derives

targets from 30 commercial ALBUM masters (BATTLE −9.84 LUFS, n=5; EXPLORATION −12.18, n=8;

MELANCHOLIC −13.95, n=4, borrowed by SANCTUARY), and clears_target is false on all three published

cues (−18.81, −17.71, −17.41 LUFS). ASWG-R001 specifies −24 (±2) LKFS home and −18 (±2) LKFS portable

for the WHOLE programme, explicitly "not… dialogue, sound effects or music specifically" (rec. 9);

and measured shipped titles put the in-game music bed at −23 to −40 LUFS (average −29.4 combat, −34.2

exploring). Three quantities, three meanings, one declared. The limiter's residual-gap anxiety in

LIMITER._why_it_exists is measured against the album number and may be chasing a bar that does not

apply to a game music asset.

GAP-VO-18 — SANCTUARY has no corpus class and borrows MELANCHOLIC's target. The file names this

honestly in CLASS_MAP, and it remains a real gap: one of our three published cues is graded against

a borrowed reference with n=4.

GAP-VO-19 — No runtime headroom budget exists. ASWG's considerata (e) and (f) require headroom for

runtime resampling, filtering and surround-to-stereo downmix, and our own _why_ceiling note reaches

the same conclusion by reasoning. But nothing in the repo states how much headroom the music bus is

allocated, what the dialogue anchor is, or how a cue's authored level relates to its in-game level.

That document does not exist and this lane cannot supply it — it belongs to a runtime mix doctrine

that should be boarded.

GAP-VO-20 — LRA is measured and reported but not policed against a game-appropriate band. Published

cues measure 8.45, 11.91 and 12.25 LU against corpus class medians of 2.98 to 10.66 LU, so all three

are wider than their reference. Wider is probably correct for cues with composed drops, but the

policy's lra_min/lra_max band is derived from album masters, so clears_lra_band inherits

GAP-VO-17's denominator error.

GAP-VO-21 — pass5_realise.self_test checks the plumbing (W1–W5: correct trees, derived policy,

resolvable targets, mix_policy's own controls) and nothing about performance data. There is no check

that any part carries controller data, that any onset was speak-corrected, or that the inter-layer

spread is non-zero — so every deviation in this list can be introduced, or left in place, with the

self-test green.

GAP-VO-22 — No instrument in the grading rig measures any performance-data property. The floor

battery grades structure, melody, harmony, groove, arc and now loudness; nothing grades controller

presence, onset spread, speak-offset compliance, repeat index, velocity repetition or depth spread.

All six are exact symbolic measurements computable before a sample loads, which makes their absence

cheap to fix and expensive to keep.

Generated by harness/site/structure_site.py — the URL path is the repo path. review root