Bandlimited oscillator with morphing waveshape

  | what is it? | usage | downloads |

what is it?
A bandlimited morphing sine-saw-square-pulse oscillator with hardsync.

suggested use
Replace all sine/square/saw oscillators in approximately every softsynth ever created :-)

A bandlimited signal is created not by filtering or iFFT, more like a graphic pencil that draws the requested waveform sample by sample.
The signal consists of sine-like sweeps and straight lines.

sound example
From Csound manual.
Not very musical, full amplitude. Best appreciated if you download and open in a soundfile editor with sample-level zoom and spectral view.
left channel hardsyncs right, then left FM modulates right

by rasmus.ekman@abc.se


Waveshape is controlled by 2 parameters: clip (squareness) and skew (symmetry).
Hardsync raises freq very quickly until waveform is reset to beginning. Usually causes a pulse (bandlimited but sharp).

code usage
Initialize: Set min_sweep_length sample count; recommend range 4-20.
  • All inputs should be fed each sample: freq, clip, skew, sync (0 or 1).
  • Call generate() for each sample. Batch calling for 8+ samples is usually an optimization
  • Now audio + sync signal is available on the output.

Make sure that you use smoothing on inputs so there are no hard edges. Otherwise there will be crackling noise in the signal.

GUI suggestion
The shape can be usefully controlled by an X/Y input, with drawing of the waveshape.
I have some code that might help (Java graphics2d and C++ for VstGui).

  • Frequency (0 - sample_rate/2)
  • Clip - Squareness of waveform (range 0-1)
  • Skew - right/left symmetry offset (range +/-1)
  • Sync - 0 or 1. Resets waveform in 0-20 samples when input is >= 1

  • Audio (range +/-1)
  • Sync - 1 sample per cycle, else 0

  • Min sweep (range 4-100)

The smallest number of samples for waveform sweeps.
Suggest to randomize in range 4-15.

If you run several squinewaves in unison, it's useful to init them with different values of min-sweep.
The square/pulse waveforms have dips in the spectrum due to the rounded waveform.
With different min-sweep values these dips will cancel out rather than be exaggerated.

All code is 64-bit doubles.
Max 1 sine library call per sample, and there is some branching in the code.
C/C++ measurements suggest cost about 2-3 x over a typical pure-sine oscillator.
However, you can often get it back by skipping 1 filter in the signal chain, since decreasing clip value creates similar effect.


2016-10-10: Released Max object, subsequently pulled and rewritten.
2017-11-20: New version, has not been released. Please suggest where to host it so Max users can find.
C++ source: squinewave~max-2017-11-20.zip

2017-11-05: Csound version.
See https://csound.com/docs/manual/squinewave.html
Git: Csound / Opcodes
C source: squinewave_csound_2017-11-05.zip

2019-12-18: Java version for Voltage Modular.
See Squinewave module
Java source: squinewave-java_2019-11-25.zip

2016-10-09 19:00