bin(x) — reaching the spectrum
bass/mid/treb are three numbers for the whole audible range. bin(x) reads
the same analysis at whatever resolution you point it at: the engine’s
log-spaced band array, sampled at a normalized position and interpolated between
the two adjacent bands. A preset never names the band count, so nothing here
breaks if the engine ever re-bands.
[params]# Morph an attractor's shape from the low-mids rather than from a whole band.a = "1.4 + bin(0.15) * 0.4"# A treble-region shimmer, independent of what the bass is doing.brightness = "0.6 + bin(0.85) * 0.8"It is total: bin(0) is the lowest band, bin(1) the highest, anything
outside 0..1 clamps, and a NaN argument reads the lowest band. It never
errors and never rejects a preset at load.
[!WARNING]
bin(x)is a narrow probe, not a region average. One call sees about two of the 64 bands, so a handful of calls spot-samples a region rather than integrating it. The axis underneath it is logarithmic end to end — see the table.The band edges are laid out on a log curve from 35 Hz to 18 kHz (
core/src/dsp/fft.rs,edges_hz[k] = 35 × (18000/35)^(k/64)), and a second, longer analysis window feeds every band below the 246 Hz crossover, so no band is starved and the curve is the truth end to end (ADR-0049). No part of the axis is linear: a single-window analysis would floor each band at one FFT bin (23.4 Hz at 48 kHz) and bind the bottom half of the axis that way.Derived from
fft.rs’s edge formula andexpr.rs’sbin(), which places the probe at band-space positionx × 63and interpolates — so what it listens to is the centre of that interpolation, not of one band:
xlands on band width there 0.00~37 Hz 4 Hz (1.8 semitones) 0.10~68 Hz 7 Hz (1.8 semitones) 0.20~126 Hz 13 Hz (1.8 semitones) 0.31~247 Hz 25 Hz (1.8 semitones) — the crossover sits here 0.41~457 Hz 47 Hz (1.8 semitones) 0.50~794 Hz 81 Hz (1.8 semitones) 0.75~3.7 kHz 378 Hz (1.8 semitones) 0.84~6.4 kHz 657 Hz (1.8 semitones) 1.00~17.1 kHz 1.8 kHz (1.8 semitones)
- Every band is 1.8 semitones wide, everywhere. That uniformity is the axis being genuinely logarithmic, and it is what the second window bought. The old array’s bottom was its coarsest region — band 0 spanned a full octave in one number — and that is simply no longer the case.
35 × 514.3^xis now accurate across the whole axis, to within a few per cent. The old warning that it is “up to 2.9× wrong below the crossover” was true of the old layout and is false of this one. The residual is thex × 63step and the half-band interpolation offset; if you need better than ~5 %, read the table rather than the formula.- The mapping no longer moves with the sample rate.
hi = min(18 kHz, sr × 0.45), so at 44.1, 48 and 96 kHz the edges are identical. (What does still vary with rate is the resolution behind the low bands, since both windows are sized in samples — design-backlog 0032.)bin(0.02)is still not “the kick”. It is a ~1.7-semitone sliver near 40 Hz. Sweep the value while listening rather than assuming.Averaging a few calls does not integrate a region — it spot-samples one. Measured against a 6.5 kHz tone:
bin(0.84)reads0.094whilebin(0.82)andbin(0.88)both read exactly zero. Samples a few hundredths apart inxstep over bands rather than across them, so a narrow peak between two probes is invisible to all of them. There is no range-integrating companion (bin_range(lo, hi)) yet — until there is, usebin()when you want selectivity andbass/mid/trebwhen you want a region. Combining both is usually right: a band scalar for the body, abin()term for the detail, so the parameter never goes still on material that misses the probe.
Values come off the same normalization as the bands: a full-scale sine reads near
1.0 in its band, and ordinary music reads small, so multiply up and clamp
exactly as you would with bass.
Built from a8ce055 at version 0.115.0. This site tracks main and is not versioned per release.