Instruments: rebuild the Acid section after nodeseq (#421)
The Acid node now follows the acid voice of nodeseq.com/studio. The section describes the new knobs, the shared ADSR, the glide and the comparison with nodeseq. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent
5c215d655d
commit
63f5f5a0ae
1 file changed
+58
-53
+58
-53
@@ -1,7 +1,7 @@
|
||||
An **instrument** (**+ → Instrument**, #331) makes a note a sound. It is a node graph like a
|
||||
[sound FX](Sounds#sound-fx): **Notes** nodes bring the note in, a **Sample** plays a sound for it
|
||||
or a **Chip** makes one the way old game consoles did (#329), an **Acid** plays a bass line as the
|
||||
Roland TB-303 does (#421), the effects of a sound FX shape it
|
||||
or a **Chip** makes one the way old game consoles did (#329), an **Acid** plays an acid bass line as
|
||||
nodeseq.com does (#421), the effects of a sound FX shape it
|
||||
and the **Output** is what is heard. It is the first piece of the music tools planned in #330: a
|
||||
[pattern](Patterns) (#333) plays one, and a [song](Songs) (#334) lays patterns out. A behavior
|
||||
plays one with **Play note**, and the tab plays it from its keys.
|
||||
@@ -23,7 +23,7 @@ A at 440 Hz, 127 the highest. A note is named with its octave after it and no da
|
||||
| **Notes** | Where the notes come in. `any` triggers what it is connected to for every note from **From** to **To**. `note` is the number of the note played, `frequency` its pitch in Hz (`440 * 2^((note - 69) / 12)`), `velocity` how hard it is struck, 0 to 1. With **Single notes** there is one trigger output for every note in the range as well, and each can have a **name** of its own (*Name of C2* in the inspector): the output shows it, and so do the keys of the [piano roll](Patterns#the-pattern-tab). |
|
||||
| **Sample** | Plays a sound asset when its `trigger` is on. With **Follow note** (on by default) it plays higher or lower by the distance from **Root**, the note it sounds as it is (C4 by default), and **keeps its length** — it is played by the same worklet as a Pitch (#317). Off, every note plays it as it is, as for a drum. **Play** says how it is played while the note is held and once it is let go (table below). **Loop start** and **Loop end** are in seconds, 0 at the end being the end of the sound, counted in the stretch of the [clip](Sounds#clips) when it plays one. The volume of the sound asset counts. |
|
||||
| **Chip** | Makes a raw wave for every note that triggers it, the way sfxr makes its sounds: square, triangle, saw, sine or noise, with a slide, vibrato, an arpeggio and repeat. It needs no sound file. See [Chips](#chips). |
|
||||
| **Acid** | A bass line in the way of the Roland TB-303: a saw or a square through a resonant low-pass that saturates, swept open on every note, with accent and slide. It needs no sound file. See [Acid](#acid). |
|
||||
| **Acid** | An acid bass line as nodeseq.com plays it: a saw or a square through a low-pass with a sharp resonance, one ADSR on volume and filter, a glide from the note before. It needs no sound file. See [Acid](#acid). |
|
||||
| **Parameters** | The instrument's own parameters, each a number output with a default — like the parameters of a sound FX's Input. One per instrument. |
|
||||
| **Sound FX** | Sends the sound through a sound FX asset, as if it were the sound at the FX's Input. Every parameter of that FX is an input here; one left open is the FX's default. The node is titled after the FX, and a double click opens it. |
|
||||
| **Envelope** | Shapes a note as it is played: **Attack**, **Decay** and **Release** in seconds, **Sustain** from 0 to 1. On the way of the sound it is its volume; its output `value` moves a number with the same curve, from **From** to **To**. See [Envelopes](#envelopes). |
|
||||
@@ -264,66 +264,71 @@ from 0 to 1, the Chip counts in Hz, semitones and seconds.
|
||||
|
||||
## Acid
|
||||
|
||||
An **Acid** (#421) plays a bass line the way the Roland TB-303 does: one oscillator, a resonant
|
||||
low-pass that squeals and saturates, a sweep that opens it on every note, accent and slide. Notes
|
||||
`any` into its `trigger`, its `out` to the Output. It always plays the pitch of the note.
|
||||
An **Acid** (#421) plays an acid bass line the way [nodeseq.com](https://nodeseq.com/studio)
|
||||
plays its *Acid* bass: one oscillator, a low-pass with a sharp resonance, and one ADSR that shapes
|
||||
the volume and sweeps the filter alike. Its defaults are nodeseq's acid. Notes `any` into its
|
||||
`trigger`, its `out` to the Output. It always plays the pitch of the note.
|
||||
|
||||
| Input | Default | What it does |
|
||||
| --- | --- | --- |
|
||||
| **Wave** (setting) | Saw | *Saw* or *Square*, band-limited (PolyBLEP), so a high note does not alias. |
|
||||
| **Tuning (st)** | 0 | Semitones off the note, -12 to 12. |
|
||||
| **Cutoff (Hz)** | 400 | Where the filter rests, 30 Hz to 12 kHz. |
|
||||
| **Resonance** | 0.7 | How sharply it rings at the cutoff, 0 to 1. At 1 it is just short of whistling by itself. It takes some of the bass, as the 303's does. |
|
||||
| **Env mod** | 0.5 | How far every note opens the filter: up to four octaves above the cutoff at 1. |
|
||||
| **Decay (s)** | 0.5 | How long the filter takes to fall back, 0.2 to 2 s (to 1 % of the sweep). Grey while *Env mod* is 0. |
|
||||
| **Accent** | 0.6 | How much an accented note stands out, 0 to 1. |
|
||||
| **Slide time (s)** | 0.06 | How long a slide takes to all but reach its note (95 %). The 303's is about 60 ms. |
|
||||
| **Cutoff (Hz)** | 250 | Where the filter rests, 40 Hz to 18 kHz. nodeseq's Cutoff 0 to 100 is 40 Hz × 2^(8.8 × value/100), so its 30 is 250 Hz. |
|
||||
| **Resonance** | 0.78 | How sharply it rings at the cutoff, 0 to 1: a Q of 0.5 dB to 17.5 dB, as nodeseq's Reso 0 to 100. |
|
||||
| **Env mod** | 0.62 | How far the envelope opens the filter: up to five octaves above the cutoff at 1, never above 18 kHz. At 0.62 that is 3.1 octaves, from 250 Hz up to 2.14 kHz. |
|
||||
| **Attack (s)** | 0.003 | How long volume and filter take to climb to the top, in a straight line. |
|
||||
| **Decay (s)** | 0.16 | How long they take to fall back to where the sustain holds them. Grey at *Sustain* 1 while *Env mod* is 0. |
|
||||
| **Sustain** | 0.15 | Where the volume stays while the note is held, 0 to 1. The filter stays at 60 % of that up its sweep: at the defaults 420 Hz. |
|
||||
| **Release (s)** | 0.08 | How long volume and filter take to close after the note ends. |
|
||||
| **Glide (s)** | 0.05 | How long the pitch takes to glide from the note before. 0 does not glide. |
|
||||
|
||||
- **Accent comes from the velocity:** a note at **0.9 or more** is accented. The piano roll strikes
|
||||
at 0.8 unless told otherwise, so a plain note is not. An accented note is up to twice as loud
|
||||
(+6 dB), its sweep falls in 0.2 s whatever *Decay* says, and the filter opens further, up to two
|
||||
octaves more with *Accent* and *Resonance* at full. That extra goes through a "capacitor" that
|
||||
charges with a time constant of 20 ms and empties with one of 0.25 s, as the 303's accent
|
||||
circuit does: accents a sixteenth apart start each one from what the last left, so a run of
|
||||
them climbs.
|
||||
- **Slide:** a note that starts while the note before it on the same Acid still plays, or right
|
||||
where it ends (within 2 ms), **slides**: the pitch glides there in *Slide time* and nothing is
|
||||
struck anew, so the sweep and the volume run on. The note before is silent from the first sample
|
||||
of the new one. Notes that start at the same moment do not slide, they all play. In the piano
|
||||
roll a slide is two notes that touch or overlap. On the keys it is a key struck while the one
|
||||
before is still held.
|
||||
- **Its own volume:** the sound rises in 3 ms and dies away slowly (a time constant of 1.6 s) while
|
||||
the note is held, and ends with the note, faded out in 10 ms. An **Envelope** behind it starts over
|
||||
with every note, a slide too, so it is better left out.
|
||||
- **On the audio thread** (AudioParams): *Cutoff*, *Resonance*, *Env mod*, *Decay* and *Accent*. An
|
||||
Envelope can move *Cutoff*, `Set sound FX parameters` reaches any of them fed by a parameter. A
|
||||
**Pitch** behind it moves its frequency. *Wave*, *Tuning* and *Slide time* are fixed when the note
|
||||
starts.
|
||||
- **How it is made:** a worklet per note, in the same module as the Chip. The oscillator and the
|
||||
filter run at twice the rate and are averaged down. The filter is four one-pole low-passes in a
|
||||
row with feedback, solved without a delay in the loop (Zavalishin's topology-preserving
|
||||
transform), the signal into it saturated by `tanh`. The notes of one Acid that slide into each
|
||||
other share one synth on the audio thread: it runs once per block, and each note hears the part of
|
||||
the block that is its own, so it makes no difference which note the audio thread runs first.
|
||||
- **The node is a device** (#421), 520x280, in the brushed silver of the 303. The inputs are on the
|
||||
- **Why it squelches:** the filter falls back **in Hz, not in octaves**, as a Web Audio
|
||||
`setTargetAtTime` on the cutoff does. So it drops fast from the top and lingers low. With the
|
||||
sharp two-pole resonance on top, that makes the "yow". Attack, decay and release work as
|
||||
nodeseq automates them: the attack is a straight ramp, decay and release are `setTargetAtTime`
|
||||
with a time constant of a third and a quarter of their time.
|
||||
- **Every note strikes anew** and glides from the pitch of the note before on the same Acid, also
|
||||
after a gap of up to 2 s. A note that starts while the one before still sounds **cuts it short**,
|
||||
in a fall with a time constant of 6 ms, gone after 60 ms. Notes that start at the same moment do
|
||||
not glide and do not cut, they all play.
|
||||
- **Its own volume:** it plays out its *Release* when the note ends and stops after 1.6 releases
|
||||
and 50 ms, as nodeseq stops its oscillator. So it **needs no Envelope behind it.** An Envelope
|
||||
there would shape it a second time.
|
||||
- **Velocity** makes it louder or softer. A note at velocity 1 is as loud as nodeseq's bass at its
|
||||
volume 0.8.
|
||||
- **On the audio thread** (AudioParams): *Cutoff*, *Resonance* and *Env mod*. An Envelope can move
|
||||
*Cutoff*, `Set sound FX parameters` reaches any of them fed by a parameter. A **Pitch** behind
|
||||
it moves its frequency. *Wave*, the ADSR and *Glide* are fixed when the note starts. The note's
|
||||
end and the cut are set on the audio clock, to the sample.
|
||||
- **How it is made:** a worklet per note, in the same module as the Chip. The filter is a
|
||||
state-variable filter solved without a delay in the loop (Simper's). It has the same curve as the
|
||||
cookbook biquad that Chrome's `BiquadFilterNode` runs, and it stays steady however fast the cutoff
|
||||
moves. Like that node it takes its Q in dB.
|
||||
- **Grit** comes from behind it: nodeseq runs its whole mix through a `tanh` drive, a compressor and
|
||||
a limiter. Here that is a **Saturation**, a **Compressor** and a **Limiter** after the Acid or on
|
||||
the master.
|
||||
- **The node is a device** (#421), 580x280, in the brushed silver of the 303. The inputs are on the
|
||||
left, `out` on the right:
|
||||
- a **button for each wave** at the top, the one playing lit in orange;
|
||||
- a dark screen, **Filter over a note**: the filter where it rests in dull green, at the top of a
|
||||
plain note's sweep in acid green, the room between them lit faintly, 20 Hz to 20 kHz, +24 to
|
||||
-48 dB. It says where it rests and how far a note sweeps it; the bezel says how far a full
|
||||
accent takes it;
|
||||
- a **chrome knob** for every number, grouped *Filter* (cutoff, resonance, env mod, decay) and
|
||||
*Note* (tuning, accent, slide). A drag is one undo step, a double-click goes back to the
|
||||
default. The tuning has 0 straight up.
|
||||
- a dark screen, **Filter over a note**: the filter where it rests in dull green, at the top of
|
||||
its sweep in acid green, the room between them lit faintly, 20 Hz to 20 kHz, +24 to -48 dB. It
|
||||
says where it rests and how far a note sweeps it; the bezel says where the sustain holds it;
|
||||
- a **chrome knob** for every number, grouped *Filter* (cutoff, resonance, env), *Envelope*
|
||||
(attack, decay, sustain, release) and *Note* (glide). A drag is one undo step, a double-click
|
||||
goes back to the default.
|
||||
|
||||
The screen is drawn from the settings, not listened to. The
|
||||
[presets](#presets-randomize-and-mutate) give an Acid three columns of room; Randomize and
|
||||
Mutate leave it as it is.
|
||||
- **Measured** (2026-10-13, e2e 34, Chrome offline on the Windows runner): two notes on one line,
|
||||
the second sliding in at 0.1 s. The first was heard from sample 0 to 4799, the second from 4800
|
||||
to the end. Where it took over, the sound of both together moved by 0.0012 from one sample to
|
||||
the next, the largest step anywhere else was 0.10. Live, of three notes at 120 BPM the second,
|
||||
struck where the first ended, slid, the third after half a second's gap did not.
|
||||
- **Measured against nodeseq** (2026-10-13, Chrome offline): five sixteenths at 132 BPM, played by
|
||||
the worklet and by nodeseq's voice built from Web Audio nodes as its studio builds it. In every
|
||||
10 ms window the two were no more than 0.14 dB apart in loudness, and 95 to 97 % of the windows
|
||||
were within a tenth of an octave in brightness (the others are dark windows where only the place
|
||||
of the saw's jump differs). That held at the defaults, at full resonance and sweep, without
|
||||
resonance, and with a slow ADSR. e2e 34 checks it.
|
||||
- **A Chrome quirk found on the way:** an `OscillatorNode` started inside a block of 128 samples,
|
||||
with its frequency automated, runs its first samples at the frequency it had before it started
|
||||
(440 Hz unless told otherwise). So in nodeseq every note but those on a block's start begins at
|
||||
a phase at random. Nobody hears that, and the Acid starts every note at the same phase.
|
||||
|
||||
## The Instrument tab
|
||||
|
||||
@@ -398,7 +403,7 @@ The instruments, all on every note unless the table says otherwise:
|
||||
| *Pluck* | Square at duty 0.3 → Envelope → Low-pass that snaps shut from 6 kHz to 600 Hz | dies away |
|
||||
| *Triangle Bass* | The triangle of the NES → Envelope at full sustain | held |
|
||||
| *Pluck Bass* | Saw → Envelope → resonant Low-pass that snaps open to 2.4 kHz and falls back towards 180 Hz | held |
|
||||
| *Acid Bass* | [Acid](#acid), a saw at cutoff 300 Hz, resonance 0.8, env mod 0.6, decay 0.4 s, accent 0.7 → Delay, a dotted eighth, a little of it | dies away slowly, slides |
|
||||
| *Acid Bass* | [Acid](#acid) with nodeseq's acid: a saw at cutoff 250 Hz, resonance 0.78, env mod 0.62, attack 3 ms, decay 0.16 s, sustain 0.15, release 80 ms, glide 50 ms → Delay, a dotted eighth, a little of it | squelches, glides |
|
||||
| *Drum Kit* | *Single notes* 36 to 46: Kick on C2, Snare on D2, Closed hat on F#2, Open hat on A#2, as in General MIDI | each ends by itself |
|
||||
|
||||
The kick is a sine that drops from 160 Hz until it is below 30 Hz, the snare a falling triangle and
|
||||
|
||||
Reference in new issue
Block a user