SynthMaker

Oversampling, how-to?

Archive · 2005 23 old posts

From the original SynthMaker forum (2004–2014), with its members’ names and dates.

fritzman ·

Hi folks,

I'm experimenting with some distortion and oscillators and such things that can use some serious oversampling. I want to get rid of aliasing. so AFAIK this is the way to go, right? Would someone please explain in simple terms ho it's done?

A code example with our little wellknown friend would be wonderful:

polyin In; polyout out;

float temp1; float temp2; float temp3;

temp1=In>=0&In+In<0&-1*In; temp2=In>=0&1+In<0&-1; temp3=In*(1-temp1/4); out=temp1>=2&temp2+temp1<2&temp3;

//parabolic saturator

Any other example is very wellcome for showing what has to be done.

Thanx a lot in advance.

Best wishes, FRitz

stefan ·

Basicly, what you need to do is run the oversampled segment several times for each "out" sample.

polyin In; polyout out;

float temp1; float temp2; float temp3;

loop(8) { temp1=In>=0&In+In<0&-1*In; temp2=In>=0&1+In<0&-1; temp3=In*(1-temp1/4); out=low_pass_filter(temp1>=2&temp2+temp1<2&temp3); }

Ofcourse, there's no such function as "low_pass_filter()", so you yourself has to make sure the out value is a lowpassed version of the parabolic saturator (which now runs with 8x oversampling). To do it the _right_ way you also have to upsample the input, which basicly means lowpass the In signal at the original nyquist frequency (which is also where you'd like to oversample the out signal).

fritzman ·

Thanx a lot Stefan!

So when I understand that right I have to do it like this:

polyin In; polyout out;

float temp1; float temp2; float temp3;

loop(8) {

in=low_pass_filter(in);

temp1=In>=0&In+In<0&-1*In; temp2=In>=0&1+In<0&-1; temp3=In*(1-temp1/4); out=low_pass_filter(temp1>=2&temp2+temp1<2&temp3); }

I'm not sure if I get the stuff right here, you wrote:

"To do it the _right_ way you also have to upsample the input, which basicly means lowpass the In signal at the original nyquist frequency (which is also where you'd like to oversample the out signal)."

Did you mean "lowpass the out signal at the original nyquist frequency"? Or does oversampling mean to multiply the sampling frequency AND to filter the signal?

All the best, FRitz

rl ·

- updsample: insert zeros and lowpass - process data - lowpass again (same settings) - downsample: take every n'th sample

Good explanation here; check the whole thread: http://aulos.calarts.edu/pipermail/musi ... 27463.html

lalo ·

rl wrote: - updsample: insert zeros and lowpass - process data - lowpass again (same settings) - downsample: take every n'th sample

Good explanation here; check the whole thread: http://aulos.calarts.edu/pipermail/musi ... 27463.html

what you mean with "- updsample: insert zeros and lowpass" ?.... and how to do it code-wise? the same goes for "- downsample: take every n'th sample"...

sorry for the newbish questions 🙂

lalo

fritzman ·

lalo wrote: what you mean with "- updsample: insert zeros and lowpass" ?.... and how to do it code-wise? the same goes for "- downsample: take every n'th sample"...

sorry for the newbish questions 🙂

lalo

Hi lalo,

I was about to ask the same questions. Thanx for doing it for me. 😀

Best wishes, FRitz

rl ·

ok, I'm trying to do a code example. Please consider I'm far away from doing any final touches on my synth-project (including oversampling) and so what I'm telling here is pure theoretical wannabe expert elitism. Thus if I'm going to write some nonsense here, please correct me.

Let's build a ring modulator effect, which is rather simple:

polyin sig1; polyin sig2;

polyout out;

out = sig1 * sig2;

Now introduce 2x oversampling. Here ist the principle:

polyin sig1; polyin sig2;

polyout out;

// lowpass filter coefficients: assuming that they are calculated outside // TODO coefficient calculation with fc = samplerate / 2 // requirements for filter: steep brickwall with small passband ripple polyin a0; polyin a1; polyin a2; polyin b1; polyin b2;

// sig1 -> 2 samples float sig11; // 1st float sig12; // 2nd

// sig2 -> 2 samples float sig21; // 1st float sig22; // 2nd

// out -> 2 samples float out1; // 1st float out2; // 2nd

// filter outputs float fout11; float fout12;

float fout21; float fout22;

// insert zeros each 2nd sample sig11=sig1; sig12=0;

sig21=sig2; sig22=0;

// now instead of one sample we have to process the code module for two samples

// lowpass with given coefficients (a0, a1, a2, b1, b2)

fout11=....; fout21=....;

fout12=....; fout22=....;

// sound processing

out1=fout11 * fout21; out2=fout12 * fout22;

// again lowpass (same filter settings)

fout11=....; fout21=....;

// output any 2nd sample (throw away out2 values) out = fout11;

Filter code is still missing. If anyone wants to jump in, your welcome. Out of my head and untested, it's 2:00 am, bye, bye Rudolf.

lalo ·

great rl....i understand now... ..please someone jump in for filter 🙂...

what exactly is a polyphase filter? 😊

lalo

dasdeck ·

i would also like to see a basic filter for oversampling and how to set it to nyuist frequency. very nice explanations here! thank you! 😇

D3CK

fritzman ·

Yup, me too. Thanx a lot Rudolf for your explanations and even with code! Very cool. I'm also very interested in a well suited filter for osa. Until now I tried a simple 6dB LP with Stefans code and it's not really the beanies. The 6dBLP I mean.

Best wishes, FRitz

ake ·

Here are some information

http://ccrma-www.stanford.edu/~jos/resample/

Åk

fritzman ·

ake wrote: Here are some information

http://ccrma-www.stanford.edu/~jos/resample/

Åk

Thank you, Ak (sorry, dunno how to make that bubble upon the "A"!?),

will have some reading there.

Best wishes, FRitz

angstrom ·

Å http://en.wikipedia.org/wiki/Angstrom

😉

BTW - Angstrom is my nom de plume rather than an indication of nationality, I'm sorry to say my Swedish or Norwegian is non-existant.

fritzman ·

Hi Angstrom,

this is what Wikipedia gives me:

Unicode includes the "angstrom sign" at U+212B (in your browser it looks like Å). However, the "angstrom sign" is canonically decomposed into U+00C5, thereby seen as a (preexisting) encoding mistake, and it is better to use U+00C5 (Å) directly.

And I still don't know how to do it with my german pc keyboard. When I type U+00C5 it looks like that!? Copy and Paste must be the best to do?

Hehe, we germans have our üäöß stuff, dunno how I would do that on an english pc keyboard. 😉

Best wishes, FRitz

The Sound Scientist ·

üäöß 😉

fritzman ·

The Sound Scientist wrote: üäöß 😉

Hehe ... 😉

Kingston ·

Not to sound impatient but I'd like to see how the lowpass filter for the oversampler is designed. Anyone?

Or what parameters am I looking at? It would be a piece of piss in matlab as well. I just don't know how.

fritzman ·

Ah, the oversampling freaks! Where's bmanic? 😉

And yes, I would love to know it also. 😀

Best wishes, FRitz

rl ·

in this thread (FIR filters?) sambean has given an excellent explaination of designing a brickwall FIR lowpass filter.

(edit: there is also an example here: Using SSE for efficient oversampling?)

sambean ·

Thanks rl,

If you use FIR filters for the oversampling you can take advantage of the fact you are inserting zero's to the signal when you up-sample and you are skipping samples when you down-sample. In the second link rl provided, even though it looks like a standard FIR, a lot of the FIR calculations are being skipped..

eg, consider a stream of data that is to be interpolated..

...x(2), x(1), x(0), x(-1), x(-2),...

First we insert zeros (4 x oversampling)

x(0), 0, 0, 0, x(-1), 0, 0, 0, x(-2), 0, 0, 0,...

then we use an FIR filter to remove the aliases (anti-aliasing filter) we will need to run the filter for 4 itterations to get our 4 interpolated values..

First oversampled value:

x(0)*c0 + 0*c1 + 0*c2 + 0*c3 + x(-1)*c4 + 0*c5 + 0*c6 + 0*c7 + x(-2)*c8 + 0*c9 + 0*c10 + 0*c11,...

where c0, c1,... are the FIR coefficients, notice most of the terms can be ignored because of the zero's, leaving:

x(0)*c0 + x(-1)*c4 + x(-2)*c8 + x(-3)*c12...

This is the first oversampled value, notice the pattern..

Now if we advance the FIR one sample we have the input data series:

0, x(0), 0, 0, 0, x(-1), 0, 0, 0, x(-2), 0, 0, 0,...

If as before we plug this in the FIR and cancel the zeros we get:

x(0)*c1 + x(-1)*c5 + x(-2)*c9 + x(-3)*c13...

So for our 4 oversampled values we have

y(0) = x(0)*c0 + x(-1)*c4 + x(-2)*c8 + x(-3)*c12 +... y(1) = x(0)*c1 + x(-1)*c5 + x(-2)*c9 + x(-3)*c13 +... y(2) = x(0)*c2 + x(-1)*c6 + x(-2)*c10 + x(-3)*c14 +... y(3) = x(0)*c3 + x(-1)*c7 + x(-2)*c11 + x(-3)*c15 +...

The x4 pack oversampling example is using the mono4 connectors to simplify this calculation with SSE. Each of the y(n) oversampled values is one of the mono4 channels. If you look this is what you see happening in the interpolation module..

Any questions?

😀

Kingston ·

Thanks sambeam, that bit was actually clear to me thanks to your code in the oversampling thread.

I guess I should've specified my question a bit further.

You're using sinc as lowpass filter in your example. I know it's the best possible solution if sound quality is the goal, but what if we wanted to cut corners and use a lowpass filter simpler than sinc?

Wouldn't that make the implementation a lot more efficient?

That's what I meant wanting to see how the lowpass filter is designed... What tried and tested filter solutions are there for efficient oversampling? A good sounding workhorse solution even?

Thanks

Kingston ·

Ok, seems like I found just the right book about this filter design subject,

http://www.biochem.oulu.fi/~oniemita/dsp/deip.pdf

Anyone here able to point out quickly what solution there would be most elegant for efficient and good sounding workhorse oversampling based on that text?

(there's so many to choose from) 😊

It wouldn't have to be symmetrical, but preferably something that introduces no latency.. If that's even possible?

sambean ·

Good find, I've not tried any other types of interpolation really, In my travels I've come accross this before, never tried it out though..

Just glancing throught the pdf, I'd say try out the optimal methods, perhaps a 4-point 4th order, seems to have pretty good SNR and fairly straightford to implenment..

Wrote something here? To have a post removed or your name hidden, write to [email protected].

Before your first post

A few rules keep this a friendly place. You agree to them once.

Shown next to what you post, here and in the app. It doesn’t have to be your real name: 3–24 lower-case letters, digits or _ (capitals become lower case, spaces become _).

    Then your post goes up straight away.

    Delete this reply?

    Open it in SynthMaker?

    It goes on the track you’re editing there, in place of that track’s sound, and into My sounds. Your other tracks stay as they are.

    Want to keep that track’s sound? Start a new song in SynthMaker first (Song › New song), then open this.

    Report this reply?

    Only the developer reads reports. The person isn’t told who reported them.

    What’s wrong with it?

    Block this person?

    You won’t see their posts and replies here any more. They aren’t told, and you can unblock them at any time.

    People you’ve blocked

    Their posts and replies are hidden from you. Unblock someone to see them again.

    The community rules

    A few rules keep this a friendly place. Everyone agrees to them once, before their first post.