Tester feedback asked for a threshold and a ratio. Each band now cuts like a small compressor: Threshold (dB above the local floor) replaces Selectivity, Ratio scales the cut per dB above it (inf:1 is the old behaviour), and a Soft/Hard knee switch sets the curve. A small graph shows bump height in, cut out. Mix and Output move to the slider panel so the detection panel fits. common-ui gains rotary_text for knobs with custom value text.
561 lines
31 KiB
Markdown
561 lines
31 KiB
Markdown
# Plugin ideas
|
||
|
||
A running list of plugin ideas for riddim, dubstep and bass-music sound design.
|
||
Each entry names the problem first. Entries are grouped as released or idea. Names follow the metalwork theme of the Bass Foundry suite.
|
||
|
||
## Problems seen in bass-music production
|
||
|
||
1. Every bass patch brings its own sub level and phase, so the weight of a drop
|
||
jumps between switch-ups, and layered patches cancel in the sub.
|
||
2. Patches at the same peak level still differ in perceived loudness and
|
||
brightness. The usual fix is hand-set gain or clipping per patch.
|
||
3. Resampling is repetitive: bounce, chop, trim, declick, normalise, find the
|
||
root key, name, save, load into a sampler.
|
||
4. Writing wobbles: LFO shapes are drawn, synced, copied and edited for every
|
||
variation. Triplet and dotted patterns plus per-note changes take long.
|
||
5. Unison, OTT and stereo distortion widen the mids. Parts disappear in mono or
|
||
on club systems.
|
||
6. Kick and bass clash. Sidechain helps, but the sub phase at each note start
|
||
changes how the kick hits.
|
||
7. Distortion chains build up harsh resonances. (Patina covers this.)
|
||
8. Comparing a drop with a reference: the difference is usually sub/mid balance
|
||
over time, which generic meters do not show clearly.
|
||
9. Fixed-frequency tools act differently on every note. An EQ boost at 300 Hz
|
||
lifts the 4th harmonic of one note and the 7th of another; a distortion with
|
||
a fixed tone filter sounds brighter on low notes than on high notes.
|
||
10. Layered bass patches partly cancel in the mids, not only in the sub.
|
||
11. Texture makes a riddim patch: grit, rattle, metal, vowel, noise. It takes long
|
||
chains (distortion, comb, formant, OTT, resample, repeat), and the result
|
||
changes from note to note.
|
||
12. Grit and tone cannot be shaped separately. More distortion for more grit
|
||
also changes the body, the level and the low end.
|
||
13. Resampled textures sound printed: a loop of one moment, with no movement
|
||
inside the note.
|
||
14. Texture changes inside a note (the switch-up within one held note) need
|
||
automation lanes or chopping.
|
||
15. There is no meter for texture. Two switch-ups can sound "the same" without
|
||
a clear reason, and generic analysers show only level and spectrum.
|
||
16. OTT and multiband compression use fixed band edges, so the same setting
|
||
squashes different harmonics on every note.
|
||
17. Riddim masters rely on clipping. A clipper that also clips the sub turns
|
||
the low end into distortion.
|
||
18. Resampled basslines have no MIDI, so tools that need the notes have nothing
|
||
to follow.
|
||
19. A clean sub carries the note on a club system but vanishes on phones and
|
||
laptops. Distortion makes the note readable there, but also changes the
|
||
patch.
|
||
20. Detuned layers (reese) beat at a rate that changes with every note and every
|
||
harmonic, so the movement is never in time with the track.
|
||
21. Kick and sub on the same MIDI tick are not heard at the same moment: the
|
||
heard hit depends on the attack shapes and on the offset between them.
|
||
|
||
## Signal flow and suite audit (2026-11)
|
||
|
||
How the released plugins fit into one production:
|
||
|
||
```text
|
||
WRITE Rivet (motif → storyboard) ──MIDI──► synth
|
||
DESIGN synth → Lathe → Temper → Knurl → Patina
|
||
RESAMPLE Crucible (capture → slice → export) ──► sampler / wavetable synth ──► DESIGN
|
||
LAYER layer A + layer B → Weld (mids) → bass bus → Anvil (sub)
|
||
MIX gap: loudness, clipping, OTT, mono check, kick against sub, reference
|
||
```
|
||
|
||
Writing and sound design are covered. Mixing and mastering have only Anvil and
|
||
Patina. Findings from the audit:
|
||
|
||
- **Latency adds up.** A full chain (Knurl 71 + Temper 67 + Lathe 67 + Patina
|
||
about 45 + Anvil 80 ms) is about 330 ms. FL Studio compensates it for
|
||
playback, but a chain this long cannot be played live.
|
||
- **MIDI mode keeps the lookahead.** `Tracker::latency()` depends on the pitch
|
||
range only. With MIDI as the source, the note is known at its attack, so the
|
||
lookahead could be close to zero. This needs a latency change at runtime,
|
||
which must be checked in FL Studio first.
|
||
- **Knurl confuses every tracker after it.** Measured: Knurl output fed into
|
||
`TrackerConfig::BASS`. From C2 (65 Hz) upwards, Double, Fry (the default),
|
||
Gallop and Triple make the next tracker read the note one octave (Triple:
|
||
an octave and a fifth) too low for about 85 % of the note. Below C2 the false
|
||
sub-octave is under 30 Hz, out of range, so low notes are safe. Level and time
|
||
jitter also cause 5–25 false note starts per second. Anvil on the bus after
|
||
Knurl then plays the sub an octave low and restarts its phase. Until there is
|
||
a shared tracker: put Knurl after the other tracked plugins, and use MIDI as
|
||
the source for any tracked plugin after Knurl. See [Signal chain](chain.md).
|
||
- **Each tracked plugin needs its own MIDI route.** Four plugins in MIDI mode
|
||
are four FL routing setups.
|
||
- **Weld and delay compensation are untested together.** If the main layer's
|
||
chain has more latency than the sidechain layer and FL does not compensate
|
||
the sidechain route, the main layer arrives late, which an allpass cannot
|
||
fix. Put Weld after every plugin with latency on that track.
|
||
- **Crucible lost takes on reload.** Takes are not saved with the project.
|
||
Fixed: Keep takes writes every capture's loop to disk at once.
|
||
- **Settings handling differs.** Patina has presets and A/B; the others do not.
|
||
Lathe's drawn gains and Knurl's drawn pattern cannot be automated.
|
||
|
||
## Research findings (2026-11)
|
||
|
||
From the papers in `research/` (local, not committed). Each finding names where
|
||
it goes in the suite. They are starting points to test by ear, not rules.
|
||
|
||
- **A published bass fatness model.** Schmedeke's dissertation (Hamburg 2021,
|
||
"BASS DROP!", section 5.4.3) models momentary fatness of dance-music excerpts
|
||
over 50 ms windows from two inputs only, with adjusted R² 0.773:
|
||
`l = 10 / (1 + 4.5487·exp(0.13·(62.9366 − SPL<200)))`,
|
||
`h = 10 / (1 + 1.4317·exp(2.5575·(0.3299 − HR<200)))`,
|
||
`Fat = 0.14689·l·h` (0 to 14.7). SPL<200 is the C-weighted level below
|
||
200 Hz in dB(C) with the material normalised to −23 LUFS; HR<200 is the
|
||
MPEG-7 harmonic ratio (how periodic) of the same band. Chapter 4's earlier
|
||
linear model on synthetic tones (R² 0.597) points the same way: a tonal low
|
||
band is fatter, a noisy one is not. Anvil's clean sine maximises HR; Quench
|
||
keeps it when the top is clipped. The thesis does not state the dB(C) of its
|
||
reference, so the dBFS-to-dB(C) offset is an assumption. Measured with
|
||
`scripts/fatness.py` on the seven Devath references (offset 100 dB): drops
|
||
sit at 4–6, breakdowns near 0, kick gaps show as 50 ms dips; SPL<200 medians
|
||
are 67–69 dB(C), a few dB under the thesis's "mostly 70–80", so the offset
|
||
may be 2–5 dB low. Goes into Assay as one lane, never as an overall score.
|
||
- **Virtual bass from known harmonics.** Moliner, Rämö and Välimäki (DAFx 2020)
|
||
boost the harmonics that exist with weights that follow the sound's spectral
|
||
envelope (limits 10 dB/oct below, 3 dB/oct above) and generate the missing
|
||
ones, so a small speaker suggests the fundamental. Their nonlinear stage fails
|
||
intermodulation tests, so they use it on transients only. The suite knows f0,
|
||
so it can add harmonics at exactly k·f0 with no intermodulation (problem 19).
|
||
Anvil's sub is a pure sine, so Lathe has no harmonics there to boost.
|
||
- **Group-delay audibility.** Liski, Mäkivirta and Välimäki (2021): between
|
||
500 Hz and 4 kHz, listeners hear a group-delay peak from about 0.64 ms
|
||
(positive) or 0.56 ms (negative) on clicks over headphones; a fast-decaying
|
||
hi-hat hides it. Weld's allpass sections add positive group delay there.
|
||
Done: Weld shows the delay spread (released in 0.3.0). Measured: common fits from
|
||
Weld's own tests spread 0.82–1.03 ms, above the click threshold, so the
|
||
display gives a note, not a warning.
|
||
- **Timbral tension.** Farbood and Price (2017): more roughness, inharmonicity
|
||
and spectral flatness raise judged tension; brightness (centroid) gives no
|
||
clear result. These are the measures planned for Loupe, and the controls a
|
||
tension macro would move.
|
||
- **Coupled one-knob controls.** A 2026 distance renderer derives five distance
|
||
cues from one control, so they always agree; in its listening test it roughly
|
||
halved placement error and every participant preferred it. A pattern for
|
||
macros in Forge.
|
||
- **Shared motion binds layers.** Temporal coherence (Elhilali et al. 2009) is
|
||
a grouping cue: sub, body and top sound like one sound when their main
|
||
movements line up. One modulation source inside Forge gives that by
|
||
construction; across separate `.clap` files it needs the shared memory
|
||
rejected below.
|
||
- **Heard timing of layered hits.** Danielsen et al. (2026): attack shape and
|
||
the offset between two layers together set when the compound hit is heard
|
||
and whether it fuses. Hove et al. (2014): timing deviations are heard more
|
||
clearly in lower voices, so the bass sets the grid (problem 21).
|
||
- **Loopback FM.** Smyth (DAFx 2026): an oscillator that frequency-modulates
|
||
itself shifts its own sounding pitch as feedback rises. Her closed-form
|
||
solution gives the sounding frequency, so a growl can stay on the tracked
|
||
note at any feedback.
|
||
- **Beating depends on note and harmonic.** For two layers detuned by ratio r,
|
||
harmonic k beats at k·f0·(r − 1) Hz (Plomp and Levelt 1965 for the roughness
|
||
context). Fixed cents beat faster up the keyboard; fixed Hz beats the same on
|
||
every harmonic (problem 20).
|
||
- **Do not encode as rules:** a best sub frequency, crossover or kick/bass
|
||
offset; one number for loudness, roughness, groove and preference; random
|
||
jitter sold as humanisation; more harmonics sold as more physical bass;
|
||
largest correlation sold as the best alignment.
|
||
|
||
## Released
|
||
|
||
### Anvil — sub anchor (problems 1, 6)
|
||
|
||
Replaces the band below a split frequency with a clean mono sine that follows
|
||
the bass pitch, at one level and one start phase for every note. Pitch comes
|
||
from detection with 80 ms lookahead or from MIDI. See [Anvil](anvil/README.md).
|
||
|
||
### Crucible — resampler (problem 3)
|
||
|
||
Records the input continuously. One click captures the last bars on the host
|
||
bar grid, slices on a grid or on hits, trims, declicks, normalises, detects the
|
||
root key and exports labelled WAVs, a full loop and an optional Serum/Vital
|
||
wavetable. See [Crucible](crucible/README.md).
|
||
|
||
### Lathe — harmonic EQ (problem 9)
|
||
|
||
EQ bands placed on harmonics 1–32 of the detected note instead of fixed
|
||
frequencies. "+4 dB on harmonic 3, −6 dB on harmonic 7" sounds the same on F1
|
||
and on C2. Odd/even balance, tilt over harmonic number, and a Focus control
|
||
that lifts or cuts everything between the harmonics. Uses Anvil's pitch
|
||
tracker, or MIDI. See [Lathe](lathe/README.md).
|
||
|
||
### Temper — note-tracked distortion (problem 9)
|
||
|
||
A waveshaper whose tone filters before and after the shaper follow the note, so
|
||
every note distorts with the same character and the same harmonic content.
|
||
Input level is normalised before the shaper, so drive does not depend on how
|
||
loud the patch is, and the output is gain-matched. Oversampled to keep aliasing
|
||
(which is never harmonic) out. See [Temper](temper/README.md).
|
||
|
||
### Weld — layer phase alignment (problem 10)
|
||
|
||
Takes a second bass layer through the sidechain. It fits polarity and a chain
|
||
of up to four allpass sections to the measured cross-spectrum (no added
|
||
delay), so the layers sum instead of cancel. A display shows how much level the
|
||
cancellation cost and how much Weld recovered. Anvil solves the sub band; Weld
|
||
solves the mids. See [Weld](weld/README.md).
|
||
|
||
### Knurl — cycle texture (problems 11, 13)
|
||
|
||
Follows the played note and treats every cycle on its own: a repeating level
|
||
pattern (in-tune subharmonics), random level and timing per cycle, and a noise
|
||
burst per cycle tuned to the note. Amounts are counted in cycles, so the texture
|
||
is the same on every note. Slow per-harmonic drift is postponed. See
|
||
[Knurl](knurl/README.md).
|
||
|
||
### Planish — harmonic OTT (problem 16)
|
||
|
||
Upward and downward compression in four bands whose edges are harmonic numbers
|
||
of the tracked note (default 1, 2–4, 5–16, 17 and up), so the same setting
|
||
squashes the same harmonics on every note. Each band's level is measured over
|
||
one period of the note, so heavy settings do not ripple at f0. See [Planish](planish/README.md).
|
||
|
||
## Next for released plugins
|
||
|
||
- **Anvil**: *Kick lock* and the *offset audition* are done (Anvil 0.3.0, see
|
||
[Anvil](anvil/README.md)): the kick through the sidechain ducks the sub and
|
||
restarts its phase at an offset (problem 6); the audition steps −30 to +30 ms,
|
||
4 kicks each, Keep takes the offset heard, and the low-band sum per offset is
|
||
shown apart from that choice (problem 21). Measured on a 55 Hz kick burst
|
||
against a 55 Hz sub: +2.4 dB at 0 ms, −4.6 dB at −10 ms, −5.9 dB at +10 ms,
|
||
and +1.8 to +2.2 dB again one period away (±20 ms), so the sum alone cannot
|
||
pick the hit. Open: a finer second sweep around the kept offset; a gate or
|
||
sensitivity for kicks with long tails or a kick bus with other drums.
|
||
A sub shape from sine to rounded
|
||
triangle. A note attack counted in cycles. *Ghost harmonics* and the
|
||
*Phone* listen are done (Anvil 0.3.0, see [Anvil](anvil/README.md)): harmonics
|
||
2–10 above a "from" frequency, filled only where the patch lacks them, with
|
||
the sub level unchanged (problem 19). Open for Ghost: weights that follow the
|
||
patch's own harmonic slope instead of a fixed 1/k; measuring a new note's
|
||
harmonics from the lookahead, so its first 60 ms do not count them as
|
||
missing; a listening check on an 808 over a real phone.
|
||
- **Lathe**: A/B gain snapshots with one automatable Morph parameter. A
|
||
keyswitch note that selects the drawn shape (EQ switch-ups without
|
||
automation). A dynamic mode per harmonic.
|
||
- **Temper**: a harmonic split: harmonics 1–2 clean, 3 and up driven. More than
|
||
one Push band. A bias that changes per cycle from Knurl's cycle clock.
|
||
- **Knurl**: velocity or note selects the pattern. Stereo grit above a split
|
||
only. Drift (planned for 0.3).
|
||
- **Patina**: Tone guard (done, Patina 0.4.0). MIDI as its pitch source. M/S
|
||
processing. Threshold, Ratio and Soft/Hard knee from tester feedback (done,
|
||
unreleased 0.5.0). Next, from the same feedback round:
|
||
- An absolute level gate (dBFS) so quiet passages are never cut, if the
|
||
tester meant a loudness threshold rather than a prominence threshold.
|
||
- Narrow rings on dense or noisy material are under-read: a +12 dB ring
|
||
(Q 25) on noise reads only 3–6 dB above the floor, so it is cut by 1–3 dB.
|
||
Two causes, measured: the joined-tops envelope lifts the floor to the noise
|
||
peaks (about 5 dB above the noise mean), and envelope smoothing loses about
|
||
3 dB on a narrow ring. A floor that follows Sharpness (1/3–2 octaves) was
|
||
tried and rejected: it lost a resonant lowpass, absorbed broad bumps and cut
|
||
plain harmonic tones. Better candidates: join tops only across deep gaps
|
||
(harmonic spacing), or a mean-based floor for noise-like regions.
|
||
- A finer analysis grid (1024 cells) for narrow rings at high frequencies.
|
||
- **Weld**: delay spread display (done, Weld 0.3.0). A *gentle* fit option
|
||
that keeps the delay spread under a limit, for plucky layers. Alignment slots
|
||
per note or per switch-up. The External
|
||
sender/receiver fallback if FL's sidechain does not arrive.
|
||
- **Crucible**: a heard-onset marker per slice next to the technical cut, set
|
||
by ear and written to the WAV (problem 21). A switch-up slicer that cuts where the spectrum changes, for
|
||
legato basses. Optional retune of slices to one root. Reopening saved takes
|
||
from the `takes` folder in the take list.
|
||
- **Rivet**: more than two sound roles, one per switch-up patch. Its MIDI
|
||
output as the one note source for the tracked plugins.
|
||
- **Suite**: presets and A/B in `common-ui` for every plugin.
|
||
|
||
## Ideas
|
||
|
||
### Order
|
||
|
||
1. Small fixes from the audit. Done: chain-order guide
|
||
([Signal chain](chain.md)), Crucible Keep takes. Open: Weld test with delay
|
||
compensation (in FL), MIDI mode without lookahead (needs an FL check that a
|
||
latency change at runtime is accepted).
|
||
2. Patina pitch-aware mode. Done as **Tone guard** (Patina 0.4.0): bumps that
|
||
follow the note are protected, bumps fixed in Hz are cut. Measured first:
|
||
Patina already cut fixed formants on every note, but it also cut a boosted
|
||
harmonic as hard (5.7 dB), at a position that moved with the note.
|
||
Open: MIDI as the pitch source.
|
||
3. Planish (done, released 0.1.0), then Quench and Ballast (both done,
|
||
released 0.1.0): they fill the mix and master gap.
|
||
- In parallel, from the research findings, in this order: Weld delay
|
||
spread (done, Weld 0.3.0); the fatness lane, as the first Assay piece
|
||
(prototype `scripts/fatness.py`); Anvil Ghost harmonics and Phone listen
|
||
(done, Anvil 0.3.0); Braze (done, 0.1.0); Anvil Kick lock with offset
|
||
audition (done, Anvil 0.3.0).
|
||
4. Forge (done, unreleased 0.1.0): Lathe, Temper and Knurl behind one tracker.
|
||
5. Assay, one plugin for the display-only ideas.
|
||
6. Texture plugins (Anneal, Swarf, Etch, Bellows) and the note-keyed sequencer.
|
||
|
||
Merges: Gauge, Loupe and Drop compare share one analysis core and one display,
|
||
so they become one plugin, **Assay**. The wobble sequencer, Damascus and Chase
|
||
are all "step grid, note selects the pattern", so they become one sequencer.
|
||
|
||
### Forge — one tracked channel strip (problems 9, 11, latency)
|
||
|
||
One tracker, one latency, and Lathe, Temper, Knurl and later Anneal as modules
|
||
in an order you choose. Two further reasons from the research findings: one
|
||
modulation source for all modules moves sub, body and top together, which
|
||
binds them into one sound; and coupled macros become possible, for example a
|
||
*Tension* knob that raises roughness (Knurl), inharmonicity and noise (Anneal)
|
||
together at matched loudness, measured by the same descriptors as Loupe. It removes the stacked lookahead, the trackers that
|
||
disagree (Knurl's sub-octave cannot confuse a tracker that reads the input
|
||
before Knurl) and the repeated MIDI routing. The standalone plugins stay.
|
||
Sharing one tracker between separate `.clap` files would need named shared
|
||
memory across DLLs, which is fragile; one strip is simpler.
|
||
|
||
Built (unreleased 0.1.0, see [Forge](forge/README.md)). Lathe, Temper and Knurl
|
||
became modules (a `Tracked` trait in common-dsp: `ahead`, `event`, `process`);
|
||
each standalone plugin is now its tracker plus its module, Lathe and Temper
|
||
bit-exact against the old engines, Knurl one sample later (its interpolation
|
||
needs one newer sample) and equal within float rounding. In the strip one
|
||
tracker reads the input; a per-sample record of the tracker's events, note state
|
||
and input is replayed to each module, delayed by the latency of the modules in
|
||
front of it. Findings:
|
||
|
||
- One module alone in Forge matches its standalone plugin sample for sample, in
|
||
all six orders (tested).
|
||
- Knurl's Double-style pattern (0, −12 dB) in front of Lathe: standalone Lathe
|
||
after Knurl read the note an octave low in 149 of 149 frames on an A2 saw;
|
||
Lathe inside Forge read A2 in 149 of 149.
|
||
- Latency 72 ms against 206 ms for the three in a row (48 kHz).
|
||
- Temper's Normalize looks one lookahead ahead; in the strip it reads the strip
|
||
input, not the modules in front of it. Fine while those change every note's
|
||
level alike.
|
||
|
||
Next for Forge: the *Tension* macro over Knurl (and later Anneal) at matched
|
||
loudness; Planish and Braze as modules (both are tracked, and Braze after
|
||
Knurl is the next tracker that hears the sub-octave); a short crossfade when
|
||
the order changes; one shared modulation source (per-note envelope or LFO in
|
||
cycles) that every module can read.
|
||
|
||
### Braze — tempo-locked beating (problem 20)
|
||
|
||
Brazing joins two metals with a filler. Braze adds a detuned copy of the bass
|
||
whose beating is in time with the track on every note. With the tracked f0, it
|
||
sets the detune ratio for each note so that a chosen harmonic beats at a
|
||
tempo-synced rate: r = 1 + B/(k·f0), for example an eighth at 140 BPM is
|
||
B = 4.67 Hz. A second mode adds a frequency-shifted copy, so every harmonic
|
||
beats at the same rate. Controls: rate (synced), target harmonic, depth,
|
||
spread across harmonics, mode. It reuses the tracker, and Weld should not
|
||
"fix" this beating: put Weld before Braze.
|
||
|
||
Built (released 0.1.0, see [Braze](braze/README.md)). The detune is a delay
|
||
line whose delay falls one period per beat cycle and jumps back one period,
|
||
which is seamless on a periodic note, and the delay follows the host's beat
|
||
position, so the peaks land on the grid. Harmonic n then beats at n/k · B: every
|
||
harmonic is on the grid, so the planned spread control was not needed. A Low
|
||
cut (LR4 on the copy, the bass split by the same crossover) keeps the sub out.
|
||
Open: the frequency-shift mode. Mixed with the dry bass, a plain single-sideband
|
||
shift gives every harmonic the same envelope at the same moment, which is
|
||
tremolo; it needs a dispersive allpass on the copy to stagger the harmonics
|
||
before it sounds like movement. Also open: a listening check on a real reese,
|
||
and how Weld reads a layer after Braze.
|
||
|
||
### Arc — self-FM growl (research spike)
|
||
|
||
An arc welds with a sustained spark. Arc runs loopback FM (Smyth, DAFx 2026)
|
||
on the tracked note: a time-varying delay line modulated by its own output.
|
||
The closed-form sounding frequency lets Arc retune the carrier, so the growl
|
||
stays in key while feedback sweeps from clean to torn. Needs listening and an
|
||
aliasing check before it becomes a plugin.
|
||
|
||
### Quench — sub-safe clipper (problem 17)
|
||
|
||
Quenching hardens hot metal in one fast step. Quench clips only above a split
|
||
frequency and adds the clean sub back with its own headroom, so the master can
|
||
be clipped hard without distorting the low end. Pairs with Anvil's split.
|
||
|
||
Built (released 0.1.0, see [Quench](quench/README.md)). Design checks, made
|
||
in a prototype before the plugin:
|
||
|
||
- Splitting and giving the top the instantaneous room, clamp(top, −C − sub,
|
||
C − sub), is exactly a plain clip of the sum: the error is the same signal.
|
||
The sub-safe part has to come from somewhere else.
|
||
- Feeding the clip error back through 1 − lowpass diverges: the complement of
|
||
an LR4 lowpass peaks at 1.5× near the split.
|
||
- What works: clip the top symmetrically at the ceiling minus the sub's held
|
||
peak (no pumping at the sub's rate, the sum stays under the ceiling), then
|
||
high-pass the clip error at the split so its products below the split go.
|
||
Two clip-and-high-pass passes and an oversampled hard clip hold the ceiling.
|
||
Measured: sub level +0.04 dB against −2.2 dB for a plain clip; low-band
|
||
products −35 dB against −16 dB. Cost: 0.5–1.2 dB less RMS at the same
|
||
ceiling.
|
||
- Where it does not help: a top whose fundamental lies within an octave of the
|
||
split is partly in the sub band (saw at 98 Hz over a 49 Hz sub: about the same
|
||
as a plain clip).
|
||
- Next ideas: link the channels' sub peak and offer mono below the split
|
||
(with Gauge); give the top the room on the sub's far side too (asymmetric)
|
||
with the error still high-passed, and measure whether that wins back the
|
||
loudness without pumping; a true-peak ceiling.
|
||
|
||
### Scribe — audio to MIDI (problem 18)
|
||
|
||
A scribe marks lines on metal. Scribe runs the note tracker on a bass and
|
||
outputs MIDI notes and a `.mid` file. A resample from Crucible then gets its
|
||
notes back, so the other plugins can use MIDI as their source.
|
||
|
||
### Bevel — mono-safe harmonic widener (problem 5)
|
||
|
||
Pans harmonics of the note alternately (for example odd left, even right) with
|
||
complementary filters, so the mono sum stays flat. Pairs with Assay.
|
||
|
||
### Peen — note-start transient shaper
|
||
|
||
Peening hardens a surface with hammer blows. Attack and sustain shaping on
|
||
every note start, with times counted in cycles, so each switch-up gets the same
|
||
punch on every note. Could become part of Ballast.
|
||
|
||
### Ballast — switch-up loudness leveller (problem 2)
|
||
|
||
Measures short-term perceived loudness per note or per switch-up against a
|
||
target or a reference patch and adjusts gain only, so each switch-up lands at
|
||
the same loudness without compression changing its character. Earlier working
|
||
name: Hit Leveler. Pairs with Anvil: Anvil levels the sub, Ballast the whole
|
||
patch.
|
||
|
||
Built (released 0.1.0, see [Ballast](ballast/README.md)): one gain per part,
|
||
parts from note starts or the host grid (a patch change on the same note is not
|
||
a new note to the tracker), K-weighted loudness of the first 100 ms, Learn for
|
||
the reference. Found while building it:
|
||
|
||
- A note start from a pitch change comes about 20 ms early, in the gap before
|
||
the note; a plain mean over the window then reads the part ~0.9 dB quiet.
|
||
Fixed with 10 ms blocks and a relative gate (−20 dB under the loudest block).
|
||
- The K-weighting filters ring the last part into the next one: a near-silent
|
||
part after a loud one read −18 LUFS instead of under −60. Fixed by weighting
|
||
every part from rest.
|
||
- Next ideas: a brightness match next to loudness (problem 2 names both; with
|
||
Lathe or Patina doing the EQ), a "follow" option for long notes that swell,
|
||
and switch-up detection from timbre change instead of the grid.
|
||
|
||
### Bellows — pitch-tracked resonator
|
||
|
||
A comb or Karplus-style resonator tuned to the detected note. It turns noise,
|
||
distortion or drums into pitched metallic tone that is in key on every note.
|
||
Damping, harmonic spread, single or multiple combs.
|
||
|
||
### Gauge — low-end mono check (problem 5)
|
||
|
||
Shows phase correlation and mono-sum loss per band and per note in the bass
|
||
range, and marks the notes where widening breaks the mono sum. Optional fixes:
|
||
mono below a chosen frequency and phase rotation on the mids. Display-first, so
|
||
it is a small build. Earlier working name: Bass Mono Check.
|
||
|
||
### Wobble sequencer (problem 4)
|
||
|
||
Step patterns for volume, filter, formant and pitch with triplet and dotted
|
||
grids built in. Each MIDI note selects a different pattern, so a switch-up is a
|
||
different note in the piano roll. ShaperBox overlaps, but it has no note-keyed
|
||
patterns. No name yet.
|
||
|
||
### Fatness lane (problems 2, 8)
|
||
|
||
Momentary fatness per 50 ms from Schmedeke's model (see Research findings),
|
||
drawn as one lane next to sub/mid energy, for a patch and a reference. It
|
||
explains why two drops at the same LUFS feel different in weight: a quieter or
|
||
noisier low band lowers the value. Prototype: `scripts/fatness.py` (offline,
|
||
on rendered files). The first piece of Assay. Open: the dB(C) offset, and how
|
||
the lane reads on a single bass patch rather than a full mix.
|
||
|
||
### Drop compare (problem 8)
|
||
|
||
Loudness-matched A/B of a drop against a reference, with sub, low-mid, mid and
|
||
high energy over time: for example "your sub is 3 dB under the reference in
|
||
bars 2–4". No name yet.
|
||
|
||
## Texture ideas
|
||
|
||
These ideas target problems 11–15; Knurl, the first of them, is released above.
|
||
Most of them reuse the note tracker in
|
||
`common-dsp`, so a texture setting means the same thing on every note, the same
|
||
way Lathe and Temper work.
|
||
|
||
### Anneal — tone and grit split (problem 12)
|
||
|
||
Annealing changes how a metal behaves without changing its shape. Anneal
|
||
splits the signal into three parts: the harmonic part (energy on the harmonics
|
||
of the tracked note), the residual noise and grit between the harmonics, and
|
||
the transients. Each part has a level fader, a drive and a tilt.
|
||
|
||
- Turn the grit up 6 dB and keep the body and the sub unchanged.
|
||
- Take all the grit out of a layer and leave a clean tone for further design.
|
||
- Listen to each part solo, or send the grit to a second output for its own
|
||
chain.
|
||
|
||
DSP: an STFT with the note tracker; harmonic masks at k·f0, with a width that
|
||
follows the pitch; a transient mask from spectral flux. Latency is one FFT
|
||
frame. The display shows the three parts in different colours on Lathe's
|
||
harmonic strip.
|
||
|
||
### Swarf — in-key granular shavings (problems 11, 13)
|
||
|
||
Swarf is the shavings that machining leaves. Swarf records the bass itself and
|
||
sprays short grains of it back as a layer. Grain lengths are whole pitch
|
||
periods, and every grain is retuned to the note playing now, so the shredded
|
||
layer stays in key across a riddim line. Controls are density, spray (position
|
||
spread back in time), grain size in cycles, reverse probability, and a
|
||
harmonic-only filter for the layer. It is useful for the "shredded metal" top
|
||
layer, and works on a resample from Crucible as well.
|
||
|
||
### Etch — texture imprint (problem 11)
|
||
|
||
Etching transfers a pattern onto metal with acid. Etch takes a texture source
|
||
through the sidechain or from a loaded sample (a metal scrape, a vocal, a field
|
||
recording) and imprints its fine structure on the bass. The bass keeps its
|
||
pitch and its harmonic levels; between and on the harmonics, the source's
|
||
noise, roughness and movement come through. A "harmonic lock" mode samples the
|
||
source's spectral envelope only at the bass harmonics, so the imprint is always
|
||
in key. It differs from a vocoder: a vocoder transfers the envelope, and Etch
|
||
transfers the surface.
|
||
|
||
### Chase — talking formants that hit harmonics (problems 11, 14)
|
||
|
||
Chasing shapes metal by hammering it from the front. Chase is a formant filter
|
||
with a 2D vowel pad (a, e, i, o, u, plus "yoi" and "wub" shapes). You draw a
|
||
path over the pad and sync it to the tempo, or let each MIDI note select a path.
|
||
The formants stay in Hz, so a vowel stays a vowel on every note. A **snap**
|
||
control moves each resonant peak onto the nearest harmonic of the tracked
|
||
note, so a narrow formant never falls into the gap between two harmonics and
|
||
vanishes on some notes. Gain-matched, so a vowel change does not change the
|
||
level.
|
||
|
||
### Damascus — texture step sequencer (problem 14)
|
||
|
||
Damascus steel is folded from layers into a visible pattern. Damascus holds up
|
||
to four texture slots (for example a formant, a comb, a sample-rate reducer and
|
||
a Knurl-type rattle) and a tempo-synced step grid that chooses a slot, or a mix
|
||
of two, per step. Steps have their own crossfade time, so changes can be hard
|
||
cuts or smears. Each slot is gain-matched, so the steps change texture and not
|
||
level. Each MIDI note can select its own pattern, which is a texture switch-up
|
||
inside one held note. This overlaps with the wobble sequencer above; both could
|
||
become one plugin.
|
||
|
||
### Loupe — texture meter (problem 15)
|
||
|
||
A loupe is the lens used to inspect engraving. Loupe measures texture per note
|
||
over time:
|
||
|
||
- roughness and fluctuation strength (psychoacoustic models);
|
||
- harmonic-to-noise ratio, which shows how gritty a sound is;
|
||
- inharmonicity, which shows how metallic a sound is;
|
||
- brightness relative to the note (harmonic centroid, not centroid in Hz).
|
||
|
||
Roughness, inharmonicity and flatness are also the three timbre measures that
|
||
raise judged tension (Farbood and Price 2017), so the same lanes show a build-up
|
||
getting tenser without a note change.
|
||
|
||
It places every switch-up of a drop as a point on a texture map. Two patches
|
||
that sit on the same point are why a drop sounds repetitive. A reference track
|
||
can be loaded for comparison. Display only, so it is a small build, and it fits
|
||
with Gauge and Drop compare.
|
||
|
||
### Further leads
|
||
|
||
- **Creative extrema stretch** for Crucible: Nielsen (DAFx 2026) drives an
|
||
overlap-add stretch by the spacing of local extrema, a free measure of
|
||
detail. Cheap and gritty, not transparent; a bass has few extrema per cycle,
|
||
so the stretch stays close to cycle-synchronous.
|
||
- **Reference to preset:** an offline search over a bounded set of Lathe and
|
||
Temper parameters that matches a reference switch-up (ST-ITO, TAPE). Large;
|
||
needs learned audio features.
|