CV-to-scale quantizer on the 1 V/octave standard. More...
#include <scale_quantizer.hpp>
Public Member Functions | |
| void | prepare (double sample_rate) |
| void | set_mode (QuantizeMode mode) |
| QuantizeMode | mode () const |
| void | set_edo (int n) |
| int | edo () const |
| void | set_scale_mask (std::uint16_t mask) |
| std::uint16_t | scale_mask () const |
| void | set_root_pc (int pc) |
| int | root_pc () const |
| void | set_hysteresis_cents (double cents) |
| double | hysteresis_cents () const |
| void | apply_reset_edge () |
| Verb 2: clears the hysteresis latch, so the next input quantizes on its own merits rather than being held by whatever the pattern left behind. | |
| void | reset () |
| int | latched_step () const |
| The latched pre-mask step, in units of 1/N octave (edo mode) or semitones (scale_mask mode). | |
| SampleType | process (SampleType cv_volts) |
| Quantizes one sample of pitch CV, in volts. | |
Static Public Member Functions | |
| static constexpr int | latency_samples () |
Static Public Attributes | |
| static constexpr int | kDefaultEdo = 12 |
| Steps per octave in edo mode. | |
| static constexpr int | kMaxEdo = 48 |
| static constexpr std::uint16_t | kMajorMask = 0b0000'1010'1011'0101u |
| Pitch classes of the major scale — bits 0, 2, 4, 5, 7, 9, 11. | |
| static constexpr double | kHystCents = 20.0 |
| Extra travel, in cents, an input must make past a step boundary before the output follows it. | |
| static constexpr double | kMaxHystCents = 1200.0 |
| Ceiling on the hysteresis setting, one octave. | |
| static constexpr double | kMaxHystSteps = 0.45 |
| Ceiling on the hysteresis window expressed as a fraction of one step. | |
| static constexpr double | kMaxAbsSteps = 4096.0 |
| Widest step index the quantizer will produce, in either direction. | |
CV-to-scale quantizer on the 1 V/octave standard.
(informative) In 12-tone equal temperament the octave is twelve equal semitones of 100 cents, so on the 1 V/oct standard a pitch plays in tune when it is a multiple of 1/12 V — "steps of exactly 1/12 V = one semitone" [illustrated by public quantizer documentation, e.g. Doepfer A-156; 12-TET itself is common practice, cited for illustration only]. The pitch-class bitmask convention is shared verbatim with the MIDI series' scale lock, so a scale authored on either side means the same thing here.
Hysteresis is the load-bearing part. A quantizer without it chatters whenever its input hovers on a step boundary — an LFO peak, a slow envelope, a noisy CV — and the chatter is audible as a trill, not as jitter. A step change therefore requires the input to cross the boundary by hyst_cents, and the latch is the block's only state.
The latch holds the chromatic (pre-mask) step rather than the snapped output. That is what makes the hysteresis window a fixed number of cents of input travel: if it latched the output, the window would silently widen and narrow with the gaps in the scale, so a semitone-wide leading tone and a minor-third gap would debounce differently.
Glide is not baked in. The output is a stepped voltage; a caller wanting smooth transitions puts a SlewLimiterT (kit) downstream, which keeps this block pure and lets the same quantizer feed a glide and a hard-stepped path.
USE. Taming the rungler or the Cartesian walk — any wild CV becomes an in-key melody. Sample-and-hold pitch — a SampleHoldT (kit) on an LFO into the quantizer into an oscillator is the classic random arpeggio. Microtonal — EDO-N mode reaches 24-tone quarter tones and 19- or 31-tone tunings without a lookup table.
RT contract: as the header. One llround-free floor and a bounded search.
|
inline |
Verb 2: clears the hysteresis latch, so the next input quantizes on its own merits rather than being held by whatever the pattern left behind.
|
inline |
|
inline |
|
inline |
The latched pre-mask step, in units of 1/N octave (edo mode) or semitones (scale_mask mode).
|
inlinestaticconstexpr |
|
inline |
|
inline |
|
inline |
Quantizes one sample of pitch CV, in volts.
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
|
staticconstexpr |
Steps per octave in edo mode.
12 is 12-TET (cited); the cap is ours. [design parameter] default 12, range 1 .. 48.
|
staticconstexpr |
Extra travel, in cents, an input must make past a step boundary before the output follows it.
[design parameter] default 20 cents, range 0 .. 50 cents.
|
staticconstexpr |
Pitch classes of the major scale — bits 0, 2, 4, 5, 7, 9, 11.
|
staticconstexpr |
Widest step index the quantizer will produce, in either direction.
This is the block that exists to tame wild CV — a rungler, a Cartesian walk, a runaway envelope — so it is the one place in the header that has to survive an input no musician would send. Casting an unbounded or non-finite double to int is undefined behaviour, not a wrong note. The bound sits far past any real pitch: the widest EDO at ten volts (EDO-48 at ±10 V) reaches ±480 steps. [design parameter] default ±4096 steps, range ±512 .. ±2^20.
|
staticconstexpr |
|
staticconstexpr |
Ceiling on the hysteresis setting, one octave.
Beyond a full octave the value is meaningless anyway, since kMaxHystSteps caps the window that actually applies; this bound exists so the arithmetic stays finite. [design parameter] default 1200 cents ceiling, range 100 .. 12000 cents.
|
staticconstexpr |
Ceiling on the hysteresis window expressed as a fraction of one step.
A window in cents and a step count are independent knobs, and above EDO-30 the shipped 20-cent default is wider than the half-step boundary it debounces: one EDO-31 step is 38.71 cents, the boundary sits 19.35 cents away, and 19.35 + 20 = 39.35 cents of required travel exceeds the 38.71 cents an adjacent step is away. The quantizer would then be unable to reach the next step at all and would lag a monotone input by one step forever — not anti-chatter, a stuck output. The window is therefore capped so an adjacent step always stays reachable with margin: required travel is 0.5 + kMaxHystSteps = 0.95 of a step, leaving 5 % of a step of headroom against float noise at the comparison. [design parameter] default 0.45 step, range 0.1 .. 0.499 step.