EPTR Pulse and 'LTR' Antialiasing Oscillators

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

tonfilm wrote:the NI seems to be an interpolated wavetable while the virus one looks quite odd...
To me the NI one looks like a higher order and/or oversampled (poly)BLEP, and the virus one seems to have additional filtering.

BTW, is that saw really EPTR? Because I seem to remember that you used something else for saw in the code you posted earlier.

Post

I just wanted to say think you very much for restoring this thread, and it'as wonderful VVV was able to get the algorithm working in C++. there is another EPTR on my site, which is based on the one by DaveyC, in my site's own forums, as well as the first free synthesizer, which is built entirely in Cycling74 gen~ to provide 64-bit quality throughout, and the only one of its kind. As I understand it from the last message I received, the current policy is to allow me to post if I do not mention my company's name, so I cant provide a link either to the new antialiased oscillator, or to the free synths I am providing, which if anyone mentions in their own posts will be deleted, so you cant write about them here.

Post

What i can say, is that the free synth I am providing also contains the arpeggiator that I designed, which others wanted but refused to pay for its maintenance. I had been thinking to port it to C++ as a VST, but currently I have no means to support it, and no method to let other people know it exists except by advertizing.

Post

My other information is that the people who were condemning my work were automatically blocked by my new server software for attempting to guess passwords. That's all I can say with certainty, and thank you very much for your interest.

Post

Tale wrote:
tonfilm wrote:the NI seems to be an interpolated wavetable while the virus one looks quite odd...
To me the NI one looks like a higher order and/or oversampled (poly)BLEP, and the virus one seems to have additional filtering.

BTW, is that saw really EPTR? Because I seem to remember that you used something else for saw in the code you posted earlier.
Do you have any links to code samples of the algorithm you suspect the NI Massive has? because it looks like its technically the best one.

yes, the virus one looks definitely filtered...

The EPTR in the screenshot uses this algorithm, which i found somewhere here in the forums:

Code: Select all

FPhase = sync ? -1 : FPhase + t2 + FMBuffer[i]*FMLevel.Value;
if (FPhase > 1.0f - T) //transition
{
    sample = FPhase - (FPhase / T) + (1.0f / T) - 1.0f;
    FPhase -= 2.0f;
}
else
{
    sample = FPhase;
}

Post

tonfilm wrote:Do you have any links to code samples of the algorithm you suspect the NI Massive has? because it looks like its technically the best one.
Well, there is this thread, that contains come info on polyBLEPs, as well as links to different polynomials:
http://www.kvraudio.com/forum/viewtopic ... 3&t=375517

And recently itoa has started this thread in search of better polynomials (it contains a higher order one reportedly used by Monark):
http://www.kvraudio.com/forum/viewtopic ... 3&t=423884

And finally, don't forget to check out mystran's tutorial if you want to get serious with BLEPs:
http://www.kvraudio.com/forum/viewtopic ... 3&t=398553

Post

wow, great resources, thanks a lot. but i have to be careful, i can get quite side-tracked on topics like these, especially if they are mathematical. should rather work on other parts of the engine right now... but i will definitely come back here :)

Post

FWIW: I have now properly compared the EPTR you posted with polyBLEP, DPW, and PTR. It would seem that EPTR, PTR 1, and DPW 2 are the same. Likewise polyBLEP, PTR 2 and DPW 3 also null. As for sonic differences, higher orders are generally better at suppressing aliases, but also have slightly less high frequency content. Note that if you oversample the sonic differences become much smaller.

BTW, I noticed that use two polyBLEP functions, one for saw and another for square/pulse, but they are the same so you really only need one.

Post

Tale wrote:FWIW: I have now properly compared the EPTR you posted with polyBLEP, DPW, and PTR. It would seem that EPTR, PTR 1, and DPW 2 are the same. Likewise polyBLEP, PTR 2 and DPW 3 also null. As for sonic differences, higher orders are generally better at suppressing aliases, but also have slightly less high frequency content. Note that if you oversample the sonic differences become much smaller.
ok i see, so oversampling should rather be integrated than looking for other better algorithms...
BTW, I noticed that use two polyBLEP functions, one for saw and another for square/pulse, but they are the same so you really only need one.
thanks for clearing that up, just saw that the code was a bit different so i used them as they were, no time to compare them in detail.

Post

Tale wrote:You can also use the polyBLEP function to correct a saw, and I have just figured out a polyBLAMP function you can use to correct a (modified) triangle. If you want I guess I can post these as well.
I was just asked for the polyBLAMP function to create a triangle, so here it is:

Code: Select all

double poly_blamp(double t, double dt)
{
	if (t < dt)
	{
		t = t/dt - 1;
		return (double)-1/3 * t*t*t;
	}
	else if (t > 1 - dt)
	{
		t = (t - 1)/dt + 1;
		return (double)1/3 * t*t*t;
	}
	else
	{
		return 0;
	}
}

// Setup oscillator.
double freq = 220; // Hz
double phase = 0;
double phase_inc = freq / sample_rate;

// Generate samples.
for (int i = 0; i < num_samples; ++i)
{
	// Start with naive triangle.
	double sample = 4 * phase;
	if (sample >= 3)
	{
		sample = sample - 4;
	}
	else if (sample > 1)
	{
		sample = 2 - sample;
	}

	// Correct falling discontinuity.
	double scale = 4 * phase_inc;
	double phase2 = phase + 0.25;
	phase2 = phase2 - floor(phase2);
	sample = sample + scale * poly_blamp(phase2, phase_inc);

	// Correct rising discontinuity.
	phase2 = phase2 + 0.5;
	phase2 = phase2 - floor(phase2);
	sample = sample - scale * poly_blamp(phase2, phase_inc);

	// Increment phase for next sample.
	phase = phase + phase_inc;
	phase = phase - floor(phase);

	// Output current sample.
	output_buffer[i] = sample;
}
I hope that helps. :)

Post

thanks for sharing the full sources, not many do.

Post

Awesome. Cheers for that! :D

Post

You're welcome. :)

Post Reply

Return to “DSP and Plugin Development”