Bandlimited synthesis

Hey everyone,

Today I have a question for some of the developers.

Has there been any DSP work done on the bandlimited oscillators since 3.6.6?

saw_freq_scope

The waveform appears to take a small dive in clarity just under 6k hZ, and slightly more distorted, and then very distorted around 12k.

Is this the ideal synthetic saw wave?

The reason I ask about 3.6.6 is because a long time ago, I asked a very similar question on these forums, and the response I received was (@nathan may remember this) was that SC hadn’t be able to manage the same level of perfection in band-limited waveform synthesis as certain other commercially available VST plugins, such as Serum.

Since we’re now 6-7 years in the future, I’m interested to know if any significant changes have occurred.

As an experiment, I thought I would compare SC’s Saw against sawtooth oscillators from VCV Rack. Since Rack specializes in analog modeling, we might suppose that its bandlimited synthesis is more advanced.

In JACK, I’m patching SC’s Saw into VCV to display it in VCV’s scope and frequency analyzer, and also patching VCV’s output into SC so that we can see how freqScope displays VCV’s waveforms.

1 - SC’s Saw in the freqScope. SC is purple in the oscilloscope, and green in the VCV analyzer. (Note that the VCV analyzer is using a Kaiser window and the display is much smoother.)

2 - Saw vs Bogaudio VCO. I switched the SC freqScope to bus 2 (reading the VCV signal). The SC display is… not much different. Bogaudio’s VCO rolls off the high end rather sharply.

3 - OK, let’s try VCV’s Fundamental VCO. This one includes a polynomial for mild distortion (no way to disable it). In VCV’s analyzer, we can see that the upper end of the spectrum is a bit more saturated than Bogaudio’s but still shows some high-frequency rolloff. SC’s analyzer still shows the 6kHz dip (but the increased saturation is visible in the SC freqscope too, so we know it’s picking up the signal from the changed oscillator).

4 - Finally, a Vult oscillator. Vult modules are often direct mathematical models of analog circuitry. It’s very, very close to the SC waveform (including SC’s lack of high-end rolloff). SC’s analyzer still shows the 6kHz dip.

From this, I might conclude that the “small dive in clarity just under 6k hZ, and slightly more distorted, and then very distorted around 12k” are probably artefacts of SC’s frequency analyzer, and not to be trusted.

It also looks like SC’s Saw compares reasonably well with Eurorack-emulation oscillators.

Two other thoughts:

  • Serum’s oscillators use oversampling to reduce aliasing. IMO, oversampling Osc / VOsc units would dramatically improve the sound quality, and usability, of wavetable oscillators. I’m not certain how much improvement we would get from an oversampled Saw, though, since it seems already to be doing pretty well.

  • In my experience with Rack, that juicy analog sound comes more than anything else from the filters. Rack module developers (particularly Vult!) take care to model the nonlinearities of analog circuitry in the filters. Even at a modest sample rate, these filters sound beautiful in a way that I’ve never been able to get out of SC (not even with Mads’s import of some virtual analog filters into SC, and not even by copying the polynomial distortion from the Rack Fundamental VCO).

hjh

3 Likes

I made a proposal to create new Saw, Pulse, etc. UGens with updated antialiasing (either PolyBLEP or Serum-style mipmapped wavetables), but I resigned as an SC developer before I got a chance to execute it.

When evaluating antialiasing, I would recommend using a better FFT analyzer, such as recording the output to a file and analyzing it with Python/NumPy/Matplotlib.

3 Likes

Agreed! What we’re seeing with SC’s RT Freq Analyzer looks like windowing artifacts to me. (@ ~1/2 the Nyquist.)

I’d say write the output to a file and use a critical NRT tool for the job.

EDIT:

As an aside, analysis via the Signal class using windows from ExtraWindows and soundfile reading via SignalBox could be used w/in SC.

I started this script that would essentially install & demonstrate the process for anyone interested… it may need some help.

(

if(
	not ( Git.checkForGit )
){
	openOS ( "https://www.google.com/search?q=download+git" )
}{
	Quarks.checkForUpdates
	{
		[
			"https://github.com/khoin/ExtraWindows.git"
			,
			"https://gitlab.com/dxarts/projects/SignalBox.quark"
		]

		do:	install

		(
			Quarks , _
		)
	}
}

)

// thisProcess.recompile

(

s waitForBoot:

{
	// ...
}

)