Roland Supersaw - any idea how the original was done?

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

They made an emulation to run the OS, nothing to do with the sound.

Post

Whelp, logically, when you run the original firmware, you are getting the original sound. The only difference is whatever coloration migh be added by the D/A converter and analogue circuit behind it. Which I would suggest isn't much of a difference. Especially not after hearing some of the old trance tune recreations from JE-8086. Some of them sound better than the remasters of the original tracks. 😍
Evovled into noctucat...
http://www.noctucat.com/

Post

mystran wrote: Tue Jan 13, 2026 7:24 pm
NAD wrote: Tue Jan 13, 2026 2:07 pm
mystran wrote: Tue Jan 13, 2026 1:10 pm
NAD wrote: Tue Jan 13, 2026 12:24 pm But it looks like the "sum" variable is just adding up pitches, which is weird. And then that sum is passed to some mysterious high_pass function?
The "sum" variable is adding together all the individual waveforms at a particular time instant and then the result (mix of several saws) is put through a single high-pass together. The state of the high_pass() function is probably kept in global variables.
Is the idea that when it reaches the limit of a 24 bit signed integer it wraps around and that's what makes a saw?
No. The saw[i] variables must be less than 24 bits (so they wrap around earlier) or this code doesn't make any sense.
It's interesting that there is a waveform at all with a lookup table, if it was a pure mathematically correct saw, then the phase accumulators without any lookup that will make saw waves and make it faster. How does that wave look at all, is it really just a normal saw wave?

But you is always sharp, don't you think it has something to do with this line...
int24_t voice_detune = (detune_table * (pitch * detune)) >> 7;

Just put the code here for convenience...

Code: Select all

int24_t saw[7] = {0};

const int24_t detune_table[7] = { 0, 128, - 128, 816, -824, 1408, 1440 };

int24_t next(int24_t pitch, int24_t spread, int24_t detune) {
	int24_t sum = 0 ;

	for (int i = 0; i < 7; i++= {
		int24_t voice_detune = (detune_table[i] * (pitch * detune)) >> 7;
		saw[i] += pitch + voice_detune;
		
		if ( i == 0)
			sum += saw[i];
		else
			sum += saw[i] * spread;
	}
	
	return high_pass(sum);
}
I have not looked at the architecture at all, but it looks like it only can calculate in 24bit and 28bit if it does not have bigger registers in the core than it's memory. But if it's stated to be in 24bit in this pseudo c code (I do not know if he actually confirmed that this C code produce the right result at all), it's probably done in the 24bit core, and the other core is 28bit (but don't know and just make big assumptions as a start for the discussion).

But if it's only has 24bit registers that calculation can wrap like hell. It does not say anything about the pitch table that will give a baseline for the calculation. I have not looked at the prior discussion has been on that chip that may give a lot of details that can not be contrived from that code.

Lets say that Roland have tried to use the most of the headroom in all calculations, then to multiply with 1440 for example, must wrap crazy. And this may the reason that it has not made any sense and no one has figured out fully what is happening.

As it's downshifted 7 bits. Maybe the pitch table is in something like 17 or 16 bits. And that that calculation for the supersaw came about from a programming mistake. The 1440 is a 11 bit number, but if it's only a 24 bit core it will wrap. Can't imagine that they only used like 11-12 bit number for pitch as it will not give enough octaves, so my assumption is that it will wrap a lot.

Post

We have code that someone interpreted to C code in that discord channel, from assembly. He can not have missed any calculations that was done as he is obviously not insane and no one did complain as the guy giving the presentation is not insane or he would have remarked.

Does someone know how big the landing register is in the core in this custom DSP (is it 24bit?), and does someone have the pitch table so we know how many bits it's using?

Post


Post

OMG I thought I had wrapped my head around this but now I'm so much more confused! :cry:
Thank God for floating-point processors, am I right?? :lol:
Image

Post

NAD wrote: Tue Jan 20, 2026 11:09 am Thank God for floating-point processors, am I right?? :lol:
Yes! With floats, overflow is something we usually don't even have to even think about anymore (it really only happens with floats when some recursive algorithm is unstable, i.e. "explodes", which we need to avoid anyway) and the behavior of rounding errors is also improved a lot, because we are now dealing with relative errors rather than absolute errors which is usually better behaved. We don't really need to think about how things like headroom, gain-staging, etc. affect our roundoff noise because they don't...well, of course, I'm simplifying a bit but by and large, this is how it is. I really don't want to imagine how much more difficult every DSP process would be to implement well, if we would still have to deal with fixed point representations.

With regard to the supersaw: I would be perfectly fine with an emulation that is not bit-accurate and doesn't feature all the artifacts (aliasing, rounding noise, etc.) of the original. That means I wouldn't really care about emulating the (fixed-point) calculations of the original Roland implementation down to the bit level. Instead, I would focus on only getting the frequency ratios and the waveshape (i.e. mostly highpass tuning, I guess) right. I think, I would even prefer using a more modern and more perfectly anti-aliased bunch of oscillators. I think, aliasing is generally a bad thing and I wouldn't want to emulate it - and that goes also for supersaws. Quantization (roundoff) noise may be less problematic, but it's also a thing that I wouldn't want to emulate. The only place where they may have their place might be in Lo-Fi effects like bitcrushers with decimators - but elsewhere I consider them as undesirable artifacts that I try to avoid as much as possible.
Last edited by Music Engineer on Thu Jan 22, 2026 7:15 am, edited 1 time in total.
My website: rs-met.com, My presences on: YouTube, GitHub, Facebook

Post

It's probably perfectly antialiased because it uses integer wavelengths. Will just be a bit out of tune at higher pitches.

Post

hugoderwolf wrote: Tue Jan 20, 2026 7:13 pm It's probably perfectly antialiased because it uses integer wavelengths. Will just be a bit out of tune at higher pitches.
You mean that they round the pitches in such a way that one period (or cycle) of the waveform has an integer number of samples? That would be new to me. I think, if that would be the case, it would be more accurate to say that the aliasing frequencies align with the harmonics but are still there and by mixing with the harmonics, they would alter their amplitudes - which would arguably be less objectionable than producing additional frequency components in between (and even below) the harmonics. But I remember reading somewhere that the original Roland supersaw does alias quite a lot and that one purpose of the highpass is to filter out those aliasing frequencies which fall below the fundamental frequency of the desired tone because these tend to be especially obnoxious and getting rid of them already goes a long way in cleaning up the sound?
Last edited by Music Engineer on Thu Jan 22, 2026 7:20 am, edited 1 time in total.
My website: rs-met.com, My presences on: YouTube, GitHub, Facebook

Post

hugoderwolf wrote: Tue Jan 20, 2026 7:13 pm It's probably perfectly antialiased because it uses integer wavelengths. Will just be a bit out of tune at higher pitches.
It's not perfect, highpass only removes lower mirrors but not those past its passband.

Post

hugoderwolf wrote: Tue Jan 20, 2026 7:13 pm It's probably perfectly antialiased because it uses integer wavelengths.
Do you mind elaborating on that? Not sure I understand why that would be the case.
Image

Post

NAD wrote: Wed Jan 21, 2026 8:14 pm
hugoderwolf wrote: Tue Jan 20, 2026 7:13 pm It's probably perfectly antialiased because it uses integer wavelengths.
Do you mind elaborating on that? Not sure I understand why that would be the case.
There is no anti-aliasing whatsoever.

There's nothing special about this and everyone just seems to be confused because it's written in fixed-point and they are probably too used to looking at the floating point equivalent.

We have a table of phase-accumulators saw[7] where each one holds the phase of one individual saw wave. Then every sample we add the detuned pitches to each of these in order to advance them. Because we're working in fixed-point using integer variables, we don't need to explicitly check for wrap-around like you would do with floating-point, because it just happens automatically due to how integer overflow works.

Then we just take the phase values and treat them as saw-waves directly. Since we have a bunch of them in unison, when add them all together. For this to work properly, you need the accumulator to be wider (more bits) than the phase accumulators, but I think this is just an error in the reversed code and the original probably accumulates into a double-wide (48-bit) register or something (not familiar with the architecture, but these are common in DSPs).

Finally you high-pass the whole thing to get rid of some of the aliasing below the fundamental. That's about the only "fancy" thing here.

Post

mystran wrote: Wed Jan 21, 2026 10:07 pm Finally you high-pass the whole thing to get rid of some of the aliasing below the fundamental. That's about the only "fancy" thing here.
To me, that's about the most genious thing i've ever seen when it comes to DSP. Maybe it's obvious to some but i would have never thought of that in a million years. You just don't use hipass filters for AA. Everyone knows that. Maybe that's why i never figured it out.....

Post

Had to do a quick test to see whether I'm stupid or not. Turns out I'm just about half stupid.

Here are two spectra of a second of naive 440 Hz saws. One with exact tuning, and one where the wavelength in samples is rounded to an integer.
NaiveSaw_FloatVsInt.png
Indeed with integer wavelength you get no inharmonic aliasing, but the harmonic amplitudes are messed up. I'm not sure why because in my mind a BLEP would have its zero crossings at integer sample offsets. But that's probably simply not the case (didn't confirm).

However, my assumption that due to the integer and wrapping arithmetic the supersaw thingy in question would result in integer rounded wavelength is wrong anyway. That would only happen if the phase's number range is an integer multiple of the increments. So yes, you'll get plenty of aliasing with this approach, and although the aliasing frequencies between the harmonics probably aren't annoying especially when you layer 7 saws, the stuff below the fundamental will be annoying so it needs to be highpassed away.

But it could be also an interesting approach to quantize to integer wavelengths instead, as the harmonic amplitude problem might be tolerable when layering 7 saws. Then you'd save the highpass as there are no harmonics below fundamental. However, tuning of higher notes will be off (haven't checked by how much).
You do not have the required permissions to view the files attached to this post.

Post

hugoderwolf wrote: Thu Jan 22, 2026 8:14 am Here are two spectra of a second of naive 440 Hz saws. One with exact tuning, and one where the wavelength in samples is rounded to an integer.

NaiveSaw_FloatVsInt.png
Would you mind please sharing the code for that?
Image

Post Reply

Return to “DSP and Plugin Development”