Commit a87f3473 by PLN (Algolia)

mix: Take110 stem analysis (kick, d8) with evidence sheet

parent 014826ab
...@@ -116,3 +116,8 @@ Standard naming: ...@@ -116,3 +116,8 @@ Standard naming:
- Keep intermediate files until final verification - Keep intermediate files until final verification
- Use `--dry-run` on tools to preview commands - Use `--dry-run` on tools to preview commands
- For long files, tools show progress/ETA - For long files, tools show progress/ETA
## Analyses
Per-take stem analyses with their numbers, charts and the scripts that made them live in
`mix/analysis/`: `Take110.md` (d1 kick and d8 drums on the noir_soleil demo).
# Take110 — stem analysis: d1 kick and d8 drums (2026-11-01)
Take110 = the `noir_soleil` demo (`live/midi/nova/fusion/noir_soleil.tidal`), recorded 14:54:48,
333.7 s, 12 Ardour stems (float32 mono WAV pairs, left channel analysed). v0 master clock is the
take clock minus about 1 s. Trigger: PLN's first headphone listen of `Take110_master_v0` —
"d8 sometimes too piercing", "d3 banger whenever present", "d1 super tame", bass low.
Ear-feedback is logged in `armada/tide-table/performance_notes.md`; this file holds the numbers.
![Take110 evidence sheet](Take110/Take110_mix_evidence.png)
**Scope.** One take. Descriptive statistics, no significance claims. Orbit mapping from the code:
d1 kick (`jazz`), d2 clap, d3 open hats, d4 bass (`noir_bass`), d5 Rhodes (`FMRhodes1`), d7 trance
loop, d8 jungle breaks, d10/d11 `noir_angels`. d6, d9, d12 are silent in this take.
## 1. Per stem (frames of 8192 samples, "active" = frame RMS above −60 dBFS)
Bands: sub <60 Hz, bass 60–150, lomid 150–500, mid 0.5–2 kHz, pres 2–5 kHz, air >5 kHz.
Shares are of the stem's own energy over its active frames.
| stem | active % | RMS dBFS | peak dBFS | crest dB | sub | bass | lomid | mid | pres | air |
|---|---|---|---|---|---|---|---|---|---|---|
| d1 kick | 27.1 | −10.2 | +4.4 | 14.6 | 8.4 | 56.4 | 35.0 | 0.2 | 0.0 | 0.0 |
| d2 clap | 12.3 | −28.2 | −6.3 | 21.9 | 0.5 | 4.9 | 2.7 | 42.6 | 45.3 | 4.1 |
| d3 hats | 62.5 | −36.3 | −13.5 | 22.8 | 0.0 | 0.0 | 2.1 | 13.6 | 28.7 | 55.6 |
| d4 bass | 75.2 | −16.3 | +2.6 | 18.9 | 0.2 | 2.1 | 55.9 | 41.4 | 0.5 | 0.0 |
| d5 Rhodes | 29.3 | −18.2 | −5.5 | 12.8 | 1.0 | 8.7 | 22.1 | 67.7 | 0.5 | 0.0 |
| d7 trance | 43.9 | −35.4 | −6.8 | 28.6 | 0.1 | 0.5 | 42.4 | 33.4 | 11.5 | 12.0 |
| d8 breaks | 46.6 | −18.4 | +3.3 | 21.7 | 8.5 | 42.3 | 19.9 | 11.0 | 15.8 | 2.5 |
| d10 angels | 70.5 | −18.0 | −4.1 | 13.9 | 6.3 | 54.8 | 16.4 | 19.8 | 2.5 | 0.1 |
| d11 angels | 61.3 | −30.9 | −10.8 | 20.0 | 0.0 | 2.1 | 6.7 | 90.8 | 0.3 | 0.0 |
Stem peaks above 0 dBFS (d1 +4.4, d4 +2.6, d8 +3.3) are legal in float stems. They clip only
if the live Ardour faders sit at unity into a fixed-point sink; `take-master` trims uniformly from
the hottest stem, and on the left channel that stem is d1 (+4.4 against +3.3 and +2.6).
### Who owns each band of the mix (share of the mix's band energy, mix-active frames, %)
| band | d1 | d2 | d3 | d4 | d5 | d7 | d8 | d10 | d11 |
|---|---|---|---|---|---|---|---|---|---|
| sub <60 | 62.3 | 0.0 | 0.0 | 0.9 | 1.2 | 0.0 | 15.7 | 19.8 | 0.0 |
| bass 60–150 | 60.5 | 0.0 | 0.0 | 1.4 | 1.6 | 0.0 | 11.4 | 25.0 | 0.0 |
| lomid 150–500 | 40.9 | 0.0 | 0.0 | 40.4 | 4.3 | 0.2 | 5.8 | 8.2 | 0.2 |
| mid 0.5–2k | 0.3 | 0.5 | 0.1 | 50.7 | 22.3 | 0.3 | 5.5 | 16.7 | 3.6 |
| pres 2–5k | 0.1 | 4.7 | 2.5 | 5.1 | 1.5 | 0.8 | 67.2 | 18.0 | 0.1 |
| air >5k | 0.0 | 2.4 | 27.5 | 0.6 | 0.0 | 4.8 | 60.6 | 4.1 | 0.0 |
(Columns do not sum to 100: shares overlap in time, and a stem can own a band while quiet.)
Reading: d4 is a 150 Hz–2 kHz voice with almost nothing under 150 Hz, so the sub belongs to
d1, d10 and d8 (the earlier "bass is low" finding). d3 sits at −36 dBFS RMS yet owns 27.5% of the
air band, which is why it reads loud ("banger whenever present").
## 2. d1 kick (`jazz`, sample `000_BD.wav`)
222 hits detected (4 ms smoothed onset, threshold 35% of the 99th percentile, 120 ms refractory),
from 73.5 s to 209.8 s, median interval 0.480 s (125 bpm).
| measure | value |
|---|---|
| mean-spectrum peak bin (first 150 ms, Hann, zero-padded FFT 16384) | 64 Hz |
| level re peak, 20–40 Hz | −26.1 dB |
| level re peak, 40–60 / 60–100 / 100–200 Hz | −0.7 / 0.0 / −6.6 dB |
| level re peak, 1–2 kHz / 2–6 kHz | −62.4 / −71.8 dB |
| decay of the mean envelope to −20 / −40 dB | 119 / 184 ms |
| peak of the mean envelope | 14.6 ms after onset |
| hit peak level | +4.4 dBFS; 131 of 222 (59%) identical, 163 above 0 dBFS, 57 below 0.8 linear, 7 distinct levels (0.05 bins) |
| kick RMS vs mix RMS in the same 150 ms | −4.6 vs −5.1 dBFS |
The sample analyser (`tools/analyze_samples.py --bank jazz`) agrees on the shape: dominant 151 Hz,
sub 19.3%, low 80.3%, mid 0.4%, hi 0.0%, 0.29 s. Its energy centre (about 150 Hz) and the
mean-spectrum peak bin (64 Hz) are different statistics of a body that spans roughly 60–250 Hz.
Verdict: a boxy mid-bass thump with no attack transient (nothing above 1 kHz) and no deep sub
(nothing under 35 Hz). Level is not the issue.
### Masking, per kick (n = 222, median per hit)
| band, window | d1 | d10 | d4 | d8 | d5 |
|---|---|---|---|---|---|
| 30–120 Hz, 150 ms after the hit | 94% | 1% | 0% | 0% | 0% |
| 120–300 Hz, 150 ms after the hit | 59% | 5% | 3% | 1% | 0% |
Steady low end just before a hit, 30–120 Hz relative to the hit: d4 −33 dB, d8 −27 dB, d10 −26 dB.
In the 120 ms after a hit, 120–300 Hz: d4 sits a median 17.9 dB under d1, and within 10 dB of it
on 73 of 222 hits (a third). Conclusion: sidechaining would help d4 on a third of the hits and
barely anything else; it is not what makes the kick tame.
## 3. d8 jungle breaks (`jungle_breaks:93`, `slice 4`, `loopAt 2`)
RMS per 10 s window labelled by start time (take clock), dBFS; only windows above −45 dBFS.
| window | total | 2–5 kHz | peak | gap (total − 2–5k) |
|---|---|---|---|---|
| 140–150 | −16.5 | −29.9 | +1.9 | 13.4 |
| 150–160 | −15.4 | −26.6 | +3.3 | 11.2 |
| 160–170 | −14.7 | −27.8 | +3.3 | 13.2 |
| 170–180 | −14.5 | −28.1 | +2.4 | 13.6 |
| 180–190 | −15.7 | −30.4 | +2.4 | 14.7 |
| 190–200 | −20.3 | −35.4 | +0.1 | 15.1 |
| 210–220 | −18.5 | −26.0 | −0.2 | 7.5 |
| 220–230 | −18.1 | −21.1 | −0.7 | 3.1 |
| 230–240 | −17.9 | −20.9 | −0.8 | 3.1 |
| 240–250 | −21.6 | −24.0 | −0.8 | 2.4 |
Mean gap 13.5 dB at 140–200 s, 4.0 dB at 210–250 s: about 10 dB brighter relative to itself
(absolute 2–5 kHz +6.7 dB, total −2.8 dB). d8's share of the whole mix's 2–5 kHz power at
210–250 s: 77, 92, 92, 86% (10 s windows). 1/3-octave levels of d8 over 234–244 s peak at
3.15 kHz (relative to max: 2 kHz −5, 2.5 kHz −2, 3.15 kHz 0, 4 kHz −2, 5 kHz −4, 8 kHz −15 dB);
the mix over the same stretch has a matching bump (2 kHz −7, 3.15 kHz −3, 5 kHz −7 dB re its 500 Hz level),
so d8 shapes the mix's presence region.
Not established: *why* it brightens. Hypothesis, unchecked: a slice or `n` variant change
(`midiOn "^56" (# n 90)`, `midiOn "^92" (ply 2)`). To check, correlate the gig-log `cc` stream
(`~/.local/share/parvagues/gig-log/gig-20261101-132654.jsonl`) with the 210 s mark.
## 4. Prototype fixes (A/B excerpts, loudness-matched)
Excerpts (`output/Take110/Take110_AB_*.flac`, gitignored): A = current stem sum, 1 s gap, B =
processed. B is gain-matched to A by integrated LUFS, both scaled to −14 LUFS, then `alimiter`
0.89.
| excerpt | processing of B | B − A, dB per band |
|---|---|---|
| kick, take 160–190 s | synthetic sub (sine 85→52 Hz glide, 30 ms time constant, decay 110 ms) plus a 4 ms filtered-noise click on every detected d1 onset, velocity-following; sidechain duck from the same onsets: d4 −45%, d10 −35%, d8 −25% amplitude, 80 ms release, 3 ms lookahead | 20–60: +3.8, 60–120: +0.6, 120–300: −0.2, 0.3–2k: −0.6, 2–6k: −0.9 |
| d8, take 225–245 s | −5 dB peaking bell at 3.15 kHz, Q 0.9, on d8 only | 0.5–2k: +0.5, 2–5k: −3.1, 5–12k: −0.9 |
Parameters are hand-picked, not optimised, and not perceptually tested; PLN's ear decides.
The live fix for the kick is sound design (a `superkick` layer or a second sample), not mastering.
## 5. Method notes and corrections
- **Window length matters below 100 Hz.** A first pass split the hit into 0–20, 20–80, 80–300 ms
windows; at 60 ms the frequency resolution is about 17 Hz, so it reported "peak ~80 Hz, thin
below 60 Hz" and that was wrong. Use at least 150 ms with a zero-padded FFT for any claim about
content under 100 Hz.
- **Two numbers were wrong in the first chat answer and corrected the same day:** "163 of 222
identical" (131; 163 is the count above 0 dBFS) and d8 "85–100%" (that was the loudest frames;
the 10 s windows give 77–92%).
- Channels: left only; the right channel was not analysed.
- Spectrum of the mean over 222 hits averages away per-hit variation; the 57 quieter hits
(below 0.8 linear) are not shown separately.
## 6. Reproduce
Scripts as run on 2026-11-01 are in `mix/analysis/Take110/scripts/` (hard-coded paths to the
Take110 stems under `~/Work/Ardour/Tidal Live/interchange/Tidal Live/audiofiles/`).
| script | produces | python |
|---|---|---|
| `eda.py` | section 1 tables, first kick pass | `/usr/bin/python3` |
| `kick.py`, `recheck.py` | section 2 (recheck supersedes the 20–80 ms split) | `/usr/bin/python3` |
| `d8.py` | section 3 timeline and 1/3-octave levels | `/usr/bin/python3` |
| `ab.py` | section 4 excerpts (needs scipy) | `/usr/bin/python3` |
| `sheet.py` | the PNG (needs matplotlib) | pyenv `python3` (the system python's matplotlib breaks against numpy 2.5) |
Next step: a reusable per-voice card, starting with kicks: `TODO.d/2026-11-01-voice-cards.md`.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment