Basic LFOs in SpinCAD Designer

Oct 22, 2022 at 11:04 AM

Spin AN0001 (Application Note 1) is the reference document for the built-in LFOs in the FV-1.

Sine/Cosine LFOs

Let's start by looking at the Sin/Cos LFO block under the "Controls" menu.

An LFO (Low1 Frequency Oscillator) is primarily used in modulation effects such as chorus, flanger, phase shifter, rotary, tremolo, etc. to wobble some audio parameter back and forth relatively slowly. They also find common use in reverbs and pitch shifters. The Spin FV-1 offers hardware support for two sine/cosine LFOs that go up to about 20 Hz, and two ramp LFOs that can go up to about 128 Hz at a sampling rate of 32 kHz.

As this is a control-only block, the inputs enter from the left and the outputs come out on the right.

The Speed control input is expected to connect to something that goes from 0 to 1 (such as a pot). That value is multiplied against the speed setting in the control panel, which goes from 0 Hz (not very useful) to 20.3 Hz at 32.768 kHz sampling rate.

The most likely application for the Sin/Cos LFO is for modulation (chorus, flange, auto-wah, tremolo, phaser). If you use it to modulate amplitude or filter frequency, you can start to get some ring-modulator type sounds above 10 Hz.

The Width control input is also expected to connect to something that goes from 0 to 1. That value is multiplied against the width setting in the control panel, which goes from 0 (not very useful) to 32767. The full output width corresponds to an amplitude of +/- 1 and scales linearly with the width setting and control input.

The Sin(e) and Cos(ine) outputs are 90 degrees out of phase with each other.

Using these individually (that is, only one and not the other) doesn't yield any tangible difference as you cannot tell the difference between a sine wave and cosine - their shapes are identical. However, you can use them both at the same time, for example using one to modulate a vibrato while using the other to modulate a tremolo or filter on the same signal. This may or may not correlate to a real-world scenario (I'm thinking about a rotary speaker) however in my world view the ability to emulate a real world device takes back seat to an interesting sonic result.

If you are interested in stereo effects, you can also use the 90 degree out of phase signals to modulate things differently in the left and right channels, which can lead to interesting results.

There is a radio button to select LFO1 or LFO2 (there are only two such LFOs in the FV-1).

Finally, you can choose whether the output range goes from -1.0 to 1.0 (which is the oscillator's natural behavior) or from 0 to 1 (which is more useful when thinking of the LFO as a control signal). I'll warn you straight away that using the 0 to 1 option adds a SOF instruction:

SOF 0.5, 0.5

Which performs the following transformation:

If your goal is to generate a sine wave centered at y1, with a width of w, the most efficient way of going about it is to start with the Sin/Cos set to -1.0 to 1.0 and then add a Scale/Offset where:

  • Scale = 0.5 * w

  • Offset = y1

For example, let's say I want to wiggle a resonant filter around with the center "value" (it's not really the frequency and should probably be determined by ear) at 0.45 and a width of 0.1 (which is +/- 0.05), then use:

  • Scale = 0.05

  • Offset = 0.45

Note that the vertical scale has changed.

When using the Scale/Offset block, remember that you don't enter the scale and offset directly. In this case you should map:

  • Input low (0) to Output low (0.45)

  • Input high: (1.0) to Output High (0.50)

You can confirm that the scale and offset values are as intended. "Input Low" should not be interpreted as "the lowest part of the waveform". It is simply to say "I will map 0, the center of the sine wave, to 0.45". Also, 0 is the lowest value that you can choose for "Input Low". I'll admit, it may not make sense to everyone. I'm further tempted to have a second form for the Scale/Offset block where you simply enter the values directly.

Sample patch with 4 LFO phases

Download and open 4-swept-filters.spcd. This uses a single Sin/Cos LFO block along with a pair of Invert blocks from the Controls menu to deliver all 4 phases. I've also added Scale/Offset blocks to allow you to tune the sweep of each filter (in conjunction with the filter block's frequency setting). There are 2 bandpass filters, a low pass, and a highpass. I've set those to give a cool sound but I'd wager that there are many more sounds lurking in this patch with slight adjustments to the Power, Scale/Offset, and SVP 2P blocks. You could even stand to make the LFO top speed a bit faster.

Ramp and Triangle LFOs

If you read Spin AN0001 you will notice that the equations given for calculating the ramp LFO coefficients revolve around what is needed when using these as part of a pitch shifting algorithm to get a specific number of semitones shift up or down. The Pitch Shift blocks in SpinCAD Designer have a control panel slider that calculates the proper Ramp LFO coefficient for a given pitch shift.

In the case of the Ramp/Triangle LFO however, the control panel maps the desired LFO frequency to the coefficient that is inserted into the code.

The method for generating a triangle wave from the Ramp LFO is given at Spin's Knowledge base.

The control pins include:

  • Rate (input) - 0 - 1 range, multiplies with the control panel setting.

  • Ramp LFO (output) - goes from 0 to 0.5

  • Triangle LFO (output) - goes from 0 to 0.5

The control panel settings are:

The "Width" parameter corresponds to the width value that you would set up when initializing the ramp LFO and has the possible settings:

  • 512

  • 1024

  • 2048

  • 4096

Note that the Rate depends on the width. When width is set to 4096, the maximum rate is 16 Hz. When width is set to 512, the maximum rate increases to 128 Hz. Since the output level of this block is totally not obvious, I'm thinking it might be nice to add a control panel slider allowing you to bump up the level to 1.0. This would add a width-dependent gain after the LFO.

Today, if you want to normalize the Ramp of Triangle LFO output levels, you can add a Gain block with the following gain set depending on the LFO's Width.

  • 512 - 24 dB

  • 1024 - 18 dB

  • 2048 - 12 dB

  • 4096 - 6 dB

Here is a patch I used to check the behavior of this block. When the simulator mode is set to Simulator->File, this will record the LFO to a WAV file which you can inspect.

With the Frequency set to 16 Hz and Width set to 4096, the output looks like this (viewed in Audacity):

You can see that 16 cycles fit into 1 second of time. The top trace is the triangle and the bottom trace is the Ramp (or sawtooth).

With the frequency set to -8 Hz and width at 4096, the output now looks like this. 8 cycles fit into 1 second. The triangle wave's shape is unchanged but the ramp now ramps up instead of down.

Sample patch with Ramp and Triangle LFOs

I made a more-or-less equivalent version of the sample patch using a Ramp/Triangle LFO in place of the Sin/Cos. Download and open the file 4-swept-filters-ramp.spcd.

On this one, you can hear the jump of the bandpass filters being modulated by the Ramp LFO.

I was not able to add the gain boost for both LFO outputs as I was at the limit of registers for this patch. Hand optimization of the generated Spin ASM would probably allow it.

Notice that the Ramp LFO block does not have a width control input, necessitating the use of external multiplies. This is an opportunity for improvement.

The LFO Value Block

There is another block which may prove useful from time to time. The "LFO Value" block allows you to pick off the LFO value which is being used by another block.

The control panel lets you pick one of 6 possible waveforms.

Generally speaking, you will not need to use this if you have included the Sin/Cos LFO or Ramp/Triangle LFO blocks directly into your patch, as you can simply connect to the output pins. However, there are a few blocks, such as some reverbs, the 1- and 4-voice choruses, LFO flanger, pitch shifters and phaser, which include embedded LFOs which are not brought out to a pin. The LFO block allows you to pick off the LFO to use it somewhere else. I don't have any specific example to give you, since doing this is a little esoteric, so I'll leave it to you to tell me what you used it for!

The resources bar

The resources bar will show you which LFOs have been allocated in the current design. Note that this indicator does not update when you make control panel changes. You have to either start/stop the simulator, or to drag and drop any block in the design.

The colors have the following meanings:

  • Green - unallocated, available to use

  • Yellow - allocated, in use

  • Red - allocated by two or more blocks, will probably result in unintended behavior

Thoughts about improvements to the LFO blocks

While looking at these blocks, the following ideas came to mind about how to make them both more useful and use fewer resources in common applications.

  • Add a Width control input to the Ramp LFO block to remove the need to add an external multiply.

  • The "width" value for the ramp LFO (512 to 4096) is primarily of interest in pitch shifting applications. For LFO applications I think it's best to just select the desired frequency up to 128 Hz and then set the width automatically to put you in the proper range.

  • The Ramp block outputs could use "center/width" settings for both Ramp and Triangle LFO outputs, since quite often you will wind up putting a SOF on the signal to get it into the range you want, why not include that into the block?

  • For the Sin/Cos block, instead of having two output range settings, allow the user to select the output range and offset, which will lead to coefficients for a SOF instruction.

  • For both Sin/Cos and Ramp LFO blocks, offer "raw" in addition to scaled outputs, for the situation where you want to use the same LFO waveform for more than one thing. Sin/Cos "raw" would go -1.0 to 1.0. Ramp and triangle LFO "raw" width would depend on the frequency setting (which sets the width). The raw width could be displayed in the control panel.

Last updated