feat(knurl): add Knurl cycle texture
Check and Windows preview / check (anvil) (push) Successful in 2m1s
Check and Windows preview / check (crucible) (push) Successful in 1m31s
Check and Windows preview / check (knurl) (push) Successful in 2m4s
Check and Windows preview / check (lathe) (push) Successful in 1m27s
Check and Windows preview / check (patina) (push) Successful in 1m54s
Check and Windows preview / check (rivet) (push) Successful in 1m30s
Check and Windows preview / check (temper) (push) Successful in 1m31s
Check and Windows preview / check (weld) (push) Successful in 2m31s
Check and Windows preview / previews (push) Successful in 1m26s
Independent plugin release / plan (push) Successful in 7s
Check and Windows preview / windows (push) Successful in 2m26s
Independent plugin release / build (push) Successful in 3m0s
Independent plugin release / publish (push) Successful in 8s
Check and Windows preview / check (anvil) (push) Successful in 2m1s
Check and Windows preview / check (crucible) (push) Successful in 1m31s
Check and Windows preview / check (knurl) (push) Successful in 2m4s
Check and Windows preview / check (lathe) (push) Successful in 1m27s
Check and Windows preview / check (patina) (push) Successful in 1m54s
Check and Windows preview / check (rivet) (push) Successful in 1m30s
Check and Windows preview / check (temper) (push) Successful in 1m31s
Check and Windows preview / check (weld) (push) Successful in 2m31s
Check and Windows preview / previews (push) Successful in 1m26s
Independent plugin release / plan (push) Successful in 7s
Check and Windows preview / windows (push) Successful in 2m26s
Independent plugin release / build (push) Successful in 3m0s
Independent plugin release / publish (push) Successful in 8s
Knurl follows the played note and treats every cycle of the wave on its own: a repeating level pattern over 1-16 cycles makes subharmonics in tune with every note, random level and timing per cycle add rattle, and a noise burst per cycle, highpassed at a multiple of f0, adds grit. Amounts are counted in cycles, so the texture is the same on F1 and on C2. - Cycle clock from the shared note tracker, restarted at each note; the audio is delayed by the lookahead plus 4.2 ms of timing-jitter headroom. - Per-cycle randomness from a hash of the cycle number: Same every note or Free. - Patterns Off, Double, Triple, Fry (default), Gallop, Stutter or drawn; grit switchable per step. Pattern persisted as knurl-pattern. - Editor: last eight cycles overlaid, pattern bars with the playing step. - Tests match the prototype: Double gives f0/2 at -8.19 dB, Triple f0/3 at -10.68 dB, equal on F1 and C2, no added clicks, bit-exact when off, no allocation on the audio thread.
This commit is contained in:
1 parent
f4c0a833e6
commit
5cc3770737
27 files changed
+4699
-33
No files matched your search
+4
-2
@@ -25,7 +25,7 @@ Patina has `render` for offline WAV evaluation. The shared crates are:
|
||||
|
||||
- `common-ui`: palette, embedded fonts, header, panels, knobs, meters.
|
||||
- `common-dsp`: filters, YIN pitch tracking, the note tracker used by Anvil,
|
||||
Lathe and Temper, 4× oversampling, meters and WAV files.
|
||||
Lathe, Temper and Knurl, 4× oversampling, meters and WAV files.
|
||||
|
||||
The wrappers stay separate workspaces, each with its own lockfile, so the
|
||||
NIH-plug Git dependency stays out of the root workspace. Host identities and
|
||||
@@ -44,7 +44,8 @@ python3 scripts/check-plugin.py --plugin <product>
|
||||
python3 -m unittest discover -s scripts/tests -v
|
||||
```
|
||||
|
||||
Products: `rivet`, `patina`, `anvil`, `crucible`, `lathe`, `temper`, `weld`.
|
||||
Products: `rivet`, `patina`, `anvil`, `crucible`, `lathe`, `temper`, `weld`,
|
||||
`knurl`.
|
||||
|
||||
`check-plugin.py` runs formatting, tests and clippy for one product's packages
|
||||
and its wrapper, without compiling the other products. Run it for every product
|
||||
@@ -142,6 +143,7 @@ identify plugins by CLAP ID, so the vendor name does not affect saved projects.
|
||||
| Lathe | (new) | `io.storyboard.harmonic-eq` |
|
||||
| Temper | (new) | `io.storyboard.tracked-distortion` |
|
||||
| Weld | (new) | `io.storyboard.layer-align` |
|
||||
| Knurl | (new) | `io.storyboard.cycle-texture` |
|
||||
|
||||
The `io.storyboard.` prefix is historical and stays, because changing a CLAP ID
|
||||
breaks existing projects. Rivet keeps `story-session-v1` and its session
|
||||
|
||||
+10
-18
@@ -75,6 +75,14 @@ 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).
|
||||
|
||||
## Ideas
|
||||
|
||||
### Ballast — switch-up loudness leveller (problem 2)
|
||||
@@ -113,27 +121,11 @@ bars 2–4". No name yet.
|
||||
|
||||
## Texture ideas
|
||||
|
||||
These ideas target problems 11–15. Most of them reuse the note tracker in
|
||||
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.
|
||||
|
||||
### Knurl — pitch-synchronous grit (problems 11, 13)
|
||||
|
||||
Knurling presses a ridged pattern into metal. Knurl cuts the signal into single
|
||||
pitch periods with the note tracker and changes each period on its own:
|
||||
|
||||
- level and timing jitter per cycle;
|
||||
- short noise bursts locked to the cycle;
|
||||
- period doubling and tripling (a cycle pattern such as "loud, quiet, quiet"),
|
||||
which gives the subharmonic rattle and growl of riddim basses;
|
||||
- slow random drift of each harmonic's level and phase, which brings movement
|
||||
into a printed resample without widening it.
|
||||
|
||||
Rates are in cycles, not in Hz or tempo, so the grit has the same grain on F1
|
||||
and on C2. A pattern editor sets 1–16 cycles. Everything is mono-safe. Latency
|
||||
is the tracker lookahead, about 67 ms. Recommended first texture build: it is
|
||||
new, small, and reuses Lathe's tracking.
|
||||
|
||||
### Anneal — tone and grit split (problem 12)
|
||||
|
||||
Annealing changes how a metal behaves without changing its shape. Anneal
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# Knurl changelog
|
||||
|
||||
## 0.1.0
|
||||
|
||||
- Introduce Knurl, texture per cycle of the played note.
|
||||
- Step patterns over 1–16 cycles make subharmonics in tune with every note:
|
||||
Off, Double, Triple, Fry, Gallop, Stutter, or a drawn pattern.
|
||||
- Random level and timing per cycle, and a noise burst per cycle tuned to the
|
||||
note (Tone, Position, Length), switchable per step.
|
||||
- Same every note or Free random sequences.
|
||||
- Detect pitch and note starts from the audio with about 71 ms of latency, or
|
||||
follow MIDI notes sent to the effect.
|
||||
- Editor shows the last eight cycles overlaid and the pattern with the playing
|
||||
step.
|
||||
@@ -0,0 +1,86 @@
|
||||
# Knurl
|
||||
|
||||
Knurl gives every cycle of the note its own level, timing and grit. Current
|
||||
version **0.1.0**.
|
||||
|
||||
Knurling presses a ridged pattern into metal. Riddim and dubstep basses get their
|
||||
character the same way, from surface texture: rattle, growl, fry, grit. Usually
|
||||
that texture comes from long chains of distortion, comb filters, formants and
|
||||
resampling, and it changes from note to note. Knurl works on single cycles of the
|
||||
wave instead. It follows the played note and treats each cycle on its own, and
|
||||
every amount is counted in cycles, not in Hz or tempo. So the texture has the
|
||||
same grain on F1 and on C2.
|
||||
|
||||

|
||||
|
||||
## Install on Windows
|
||||
|
||||
Copy `Knurl.clap` into `C:\Program Files\Common Files\CLAP\`. In FL Studio 2024.1
|
||||
or newer, open Options → Manage plugins, enable Verify plugins, and Find installed
|
||||
plugins. Load Knurl in a mixer slot of the bass. Keep the font license with
|
||||
redistributed packages.
|
||||
|
||||
## Work with it
|
||||
|
||||
1. Play the bass. The note readout shows what Knurl tracks; the scope overlays
|
||||
the last eight cycles of the output, so the texture is visible cycle by cycle.
|
||||
2. Choose a **Pattern**. The pattern sets the level of each cycle and repeats:
|
||||
- **Double** (0, −9 dB): every second cycle quieter. This makes a sub-octave
|
||||
growl, exactly in tune, about 8 dB under the fundamental.
|
||||
- **Triple** (0, −12, −12 dB): a growl an octave and a fifth down.
|
||||
- **Fry** (0, −14, −5, −14 dB, the default): an uneven vocal-fry rattle.
|
||||
- **Gallop** and **Stutter**: rhythmic patterns over six and eight cycles.
|
||||
- **Off**: every cycle at full level.
|
||||
3. Draw your own pattern on the bars: drag a bar to set the level of that cycle,
|
||||
double-click to reset it. **Steps** sets the length (1–16 cycles).
|
||||
4. Add surface:
|
||||
- **Level** gives every cycle a random level (standard deviation in dB).
|
||||
- **Time** moves every cycle a little in time (percent of a period): rattle
|
||||
and scrape.
|
||||
- **Grit** adds a short noise burst inside every cycle. **Tone** sets its
|
||||
lowest frequency in harmonics of the note, **Position** where in the cycle
|
||||
it sits, and **Length** how long it is. The squares under the pattern bars
|
||||
switch the burst per step.
|
||||
5. **Edge** sets how soft each step change is. Low values are sharper and
|
||||
buzzier; high values smoother.
|
||||
|
||||
**Random**: **Same every note** (default) restarts every random sequence at each
|
||||
note, so identical notes sound identical, which keeps a riddim line tight.
|
||||
**Free** lets the sequences run on, so every note differs.
|
||||
|
||||
**Mix** blends with the delayed dry signal; **Output** trims the level.
|
||||
|
||||
### Pitch from MIDI
|
||||
|
||||
For basses whose fundamental is unclear (heavy FM, formant or noise patches),
|
||||
select **MIDI** and route the bass's MIDI notes to Knurl. In FL Studio, set the
|
||||
bass channel's MIDI output port and Knurl's input port to the same number.
|
||||
**Gate** sets the input level that counts as a note in AUDIO mode; **Snap to
|
||||
semitone** rounds the detected pitch (turn it off for slides).
|
||||
|
||||
## Timing and limits
|
||||
|
||||
Knurl delays the audio by about 71 ms: 67 ms of pitch-detection lookahead plus
|
||||
4 ms of room for the timing jitter. The delay is reported to the host for delay
|
||||
compensation, so the cycle clock knows every note before its attack leaves the
|
||||
plugin. The cycle clock restarts at every note start, so the pattern always
|
||||
begins with step 1 on the attack. Pitch range is 30–500 Hz, one note at a time.
|
||||
Between notes the effects fade out over 20 ms, so tails stay clean.
|
||||
|
||||
Knurl works per cycle of the tracked pitch; it does not look for cycle borders in
|
||||
the waveform. With a stable pitch that is the same thing. With heavy pitch
|
||||
modulation inside a note the pattern follows the tracked pitch, which can lag a
|
||||
fast bend. Both channels get the same treatment, so the effect is mono-safe.
|
||||
|
||||
## How it works
|
||||
|
||||
A note tracker (shared with Anvil, Lathe and Temper) detects pitch and note
|
||||
starts ahead of the delayed audio. A cycle clock starts at 0 on every note and
|
||||
advances by f0 / sample rate. Each cycle gets its step gain and its random level
|
||||
and time offset from a hash of the cycle number, so the result is deterministic.
|
||||
Step changes are raised-cosine crossfades over the last **Edge** of a cycle;
|
||||
level jitter crossfades over half a cycle and time jitter over the whole cycle,
|
||||
read from the delay line with cubic interpolation. The grit is white noise
|
||||
through a state-variable highpass at **Tone** × f0, shaped by a sin² window and
|
||||
scaled to the input level. There is no nonlinearity, so no oversampling is
|
||||
needed.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 291 KiB |
@@ -14,6 +14,7 @@ workflows are in `.gitea/workflows/`. A plugin's version is the `version` in
|
||||
| Lathe | `lathe-v0.1.0` | `lathe-windows-x86_64-0.1.0.zip` |
|
||||
| Temper | `temper-v0.1.0` | `temper-windows-x86_64-0.1.0.zip` |
|
||||
| Weld | `weld-v0.1.0` | `weld-windows-x86_64-0.1.0.zip` |
|
||||
| Knurl | `knurl-v0.1.0` | `knurl-windows-x86_64-0.1.0.zip` |
|
||||
|
||||
## Make a release
|
||||
|
||||
|
||||
Reference in new issue
Block a user