The old LFO is great: it's sub-sample accurate, so if you want a 6.1Hz vibrato, which is 7,229.5081967213114754098360655738 samples, you will get exactly that. It also supports PhaseIn PhaseOut SyncIn and SyncOut. You can vary its Frequency or even Waveform in real time. It supports Duty for square and triangle waves. It also goes to the top of audio range... because it is actually the same code as the Geometric Oscillator. (The difference is only that its output isn't reduced for frequency, and its default pitch isn't set by the note played.) But, it is an absolute CPU hog.
My new LFO might be over 10x faster though. For a typical usage, it may require the frequency to be a multiple of 128 samples, so if you want 6.0Hz, you might get 6.044Hz. (For common vibrato speeds, around 6Hz, it will be within about 1/20Hz of what you request.) And, it will only check only every 32 samples for a change of Frequency, Waveform, SyncIn, etc., and PhaseIn will only be checked at the start of a patch. No Duty for square/triangle. Finally, the Sine wave won't be a pure sine function, but instead, at a typical 6Hz, 214 straight segments approximating a sine wave.
In all other respects, though, the output will be as high quality as the old one, and it can support undiminished PhaseOut and SyncOut.
There will be a further optimization though. LFO's are used to adjust frequency (of an oscillator, or a filter cutoff) or volume (for tremolo), and in all these cases, you actually need an exponential curve. For instance if you want a 40 cents vibrato around a frequency f, you calculate:
f * (2^(40/1200)) ^ LFO
You can pre-calculate 2^(40/1200) to be 1.0234 (and Moselle does) but then you have to raise this number to the power of the LFO's output... EVERY SAMPLE. And raising to the power of something is slow for the CPU. So, after I get the new LFO working, I'll make the optimizer internally recognize when the LFO is being used in this fashion, and change it instead to an internal mode that outputs an exponential curve going from f/1.0234 up to f*1.0234... and we can generate that exponential curve simply with a series of multiplies instead of a series of additions. So we do away with the power calculation as well. (This optimization could be done with the current LFO, but it's so slow that the power calculation only makes it a little slower; the new LFO will be so fast that getting rid of the power calculations will suddenly be a noticeable improvement itself.)
Specifically, LFOVibrato is a module that is created for you in every patch, and is wired into the Pitch module's pitch calculation:
Output = Input * Octave * Transpose * Detune * BendRange ^ PitchBend * PitchEnv * Max( VibManual, VibControl, VibEnv ) ^ VibSource * UnisonDetune
(That's the actual Moselle default value for Pitch:Output.) VibSource defaults to LFOVibrato:Output, so we have:
Output = Input * Octave * Transpose * Detune * BendRange ^ PitchBend * PitchEnv * Max( VibManual, VibControl, VibEnv ) ^ LFOVibrato:Output * UnisonDetune
The optimizer will then change LFOVibrato's type from LFO to ExpLFO, and move Max( VibManual, VibControl, VibEnv ) to be a new input ExpRange of the ExpLFO. That leaves:
Output = Input * Octave * Transpose * Detune * BendRange ^ PitchBend * PitchEnv * LFOVibrato:Output * UnisonDetune
And LFOVibrato turns into:
[LFOVibrato]
ModType = ExpLFO
ExpRange = Max( VibManual, VibControl, VibEnv )
So, I'll make the new LFO the default LFO, and have the old one still available as "PreciseLFO" or something.
FAR FASTER LFO!
[phpBB Debug] PHP Warning: in file [ROOT]/vendor/twig/twig/lib/Twig/Extension/Core.php on line 1266: count(): Parameter must be an array or an object that implements Countable
Who is online
Users browsing this forum: No registered users and 16 guests