|
Tabula Sonora 0.1.0
A native C++20 implementation of the Roland Sound Canvas VA synth voice
|
One LFO's running state: phase, delay and fade-in accumulators, stepped a control tick at a time. More...
#include <tabulasonora/lfo_engine.hpp>
Public Member Functions | |
| LfoRunner (const LfoEngine &engine, const LfoConfig &config) | |
| const LfoConfig & | config () const noexcept |
| The configuration this runner steps. | |
| bool | is_applied () const noexcept |
| Whether the last tick ran an update at all, so the LFO has an output to give. | |
| void | tick (int rate_offset=0) noexcept |
| Advances one control tick. | |
| double | value (LfoDestination destination, int matrix_depth=0) const noexcept |
| The modulation for one destination, after the last tick. | |
| double | pitch_value (double wheel_depth) const noexcept |
| The pitch modulation with a mod-wheel depth folded in, in milli-semitones. | |
One LFO's running state: phase, delay and fade-in accumulators, stepped a control tick at a time.
All three destinations share one runner. The accumulators do not depend on which depth is being applied, so stepping once and reading three values is the same trajectory as running the LFO three times — and it is what the engine does, since a partial has one LFO object, not one per destination.
tick advances; the value is read afterwards, so the first tick already carries a phase increment.
|
inlinenodiscardnoexcept |
The configuration this runner steps.
|
inlinenodiscardnoexcept |
Whether the last tick ran an update at all, so the LFO has an output to give.
This is not "the delay has elapsed" — the delay holds the fade-in at zero but does not stop the LFO being applied, since a matrix depth is summed past the fade. What turns it off is an increment of nothing, which is the one case the module skips outright.
|
noexcept |
Advances one control tick.
rate_offset is the control matrix's LFO rate destination, in the same per-tick increment units as the configured rate — the engine adds it to the rate straight out of the table (or, for LFO2, to the raw rate) and clamps the total to 0x28f6.
A total of zero or less does not merely stop the phase: the engine skips the whole update, so the depths are not applied either and the LFO's last output is held rather than decaying. Deep enough negative rate modulation is therefore an off switch, which is why this shares its early return with a configured rate of zero.
|
nodiscardnoexcept |
The modulation for one destination, after the last tick.
matrix_depth is the control matrix's depth destination for this LFO, in the destination's own units. It is summed after the fade-in — the fade scales the patch's depth, not the controller's — and the total is then clamped to the destination's limit. Those limits are exactly the matrix's own full-scale figures, so a matrix depth alone can reach the rail but never exceed it.
|
nodiscardnoexcept |
The pitch modulation with a mod-wheel depth folded in, in milli-semitones.
The offline path's spelling of the same thing: the wheel reaches LFO1 pitch depth through the matrix, so this is value(LfoDestination::pitch, ...) with the wheel's contribution standing in for the whole matrix sum.