SynthMaker

Is this possible to code? :

Archive · 2005 32 old posts

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

global goon ·

a module that contains 4 or 6 or 8 sine wave oscillators as well as phase mod routing possibilities.

would it be more CPU friendly than making it with the inbuilt components?

heres a picture of how a 4 osc version of the module would look:

global goon ·

I mean using the built in code component btw

stefan ·

Yes, it's possible. And it would probably be more efficient indeed. You could try using both the look-up table (sin1() function) or taylor series (google for sine taylor series or something).

Granted, I myself would probably split it up into several modules so that I wouldn't have to bother with the phase routing type within the code component. Because of clarity etc.

global goon ·

thanks stefancrs, i'm just trying to suss out how to create a basic sine wave oscillator at the moment!

stefan ·

Ok, here goes the fastest one I know of (finished it earlier today):

polyin freq; polyin phase; polyout out; float cos; float sin; float tCos,tSin; float mul; // since the code component does not support initialising of variables we have to do a hack float isInitialised; isInitialised= ((cos > 0) & 1.0) + ((cos < 0) & 1.0); cos = (1.0 - isInitialised) * 0.99 + (isInitialised > 0) & cos; mul = freq * 1.0 * 3.141592; // roughly pi

cos = cos - sin * mul; sin = sin + cos * mul;

/* this is the "obvious" implementation of phase modulation tCos = cos - sin * phase; tSin = sin + tCos * phase; out = tSin; but we can simplify it into one expression instead for better perfomance, like this */ out = sin + (cos - sin * phase) * phase;

Very cpu-friendly 🙂

global goon ·

fantastic!

global goon ·

i expanded on your code to make a module that has 6 oscillators. it has freq and level in for each and 1 output. It's a fixed algorithm :- (f+e+d+c+b)-->a

It's very CPU friendly, a 10 note chord uses about 6% processing on my 2.8ghz pentium

The FMness is quite subtle though

polyin aFreq; polyin bFreq; polyin cFreq; polyin dFreq; polyin eFreq; polyin fFreq;

polyin aLevel; polyin bLevel; polyin cLevel; polyin dLevel; polyin eLevel; polyin fLevel;

polyout aOut;

float aOutf; float bOutf; float cOutf; float dOutf; float eOutf; float fOutf;

float aCos; float bCos; float cCos; float dCos; float eCos; float fCos;

float aSin; float bSin; float cSin; float dSin; float eSin; float fSin;

float mul; float totalPhase; // since the code component does not support initialising of variables we have to do a hack float isInitialised; isInitialised= ((aCos > 0) & 1.0) + ((aCos < 0) & 1.0);

aCos = (1.0 - isInitialised) * 0.99 + (isInitialised > 0) & aCos; mul = aFreq * 1.0 * 3.141592; // roughly pi aCos = aCos - aSin * mul; aSin = aSin + aCos * mul;

bCos = (1.0 - isInitialised) * 0.99 + (isInitialised > 0) & bCos; mul = bFreq * 1.0 * 3.141592; // roughly pi bCos = bCos - bSin * mul; bSin = bSin + bCos * mul;

cCos = (1.0 - isInitialised) * 0.99 + (isInitialised > 0) & cCos; mul = cFreq * 1.0 * 3.141592; // roughly pi cCos = cCos - cSin * mul; cSin = cSin + cCos * mul;

dCos = (1.0 - isInitialised) * 0.99 + (isInitialised > 0) & dCos; mul = dFreq * 1.0 * 3.141592; // roughly pi dCos = dCos - dSin * mul; dSin = dSin + dCos * mul;

eCos = (1.0 - isInitialised) * 0.99 + (isInitialised > 0) & eCos; mul = eFreq * 1.0 * 3.141592; // roughly pi eCos = eCos - eSin * mul; eSin = eSin + eCos * mul;

fCos = (1.0 - isInitialised) * 0.99 + (isInitialised > 0) & fCos; mul = fFreq * 1.0 * 3.141592; // roughly pi fCos = fCos - fSin * mul; fSin = fSin + fCos * mul;

bOutf = bSin * bLevel; cOutf = cSin * cLevel; dOutf = dSin * dLevel; eOutf = eSin * eLevel; fOutf = fSin * fLevel;

totalPhase = bOutf + cOutf + dOutf + eOutf + fOutf;

aOut = (aSin + (aCos - aSin * totalPhase) * totalPhase) * aLevel;

global goon ·

here's a test synth based on example.osm

http://www.globalgoon.com/synthmaker/goon6FM001.osm

stefan ·

Nice sound. I made some very moody scapes with it. Once again, good work 🙂

jorge ·

Yeah, I'm playing with it too, creating some presets, could be interesting to exchange some. Thanks global goon

stefan ·

So how about arrays and loops jorge? 🙂

jorge ·

stefancrs wrote: So how about arrays and loops jorge? 🙂

Well, I blame global goon for me not having done it this morning 🙂 but I know what you mean, it would be handy to have them for the efficient Sine code, and I guess also having the variables initialise would make the code much more efficient. What I had on my mind instead was to put the drawbar LFOs in global goon's synth 🙂. We'll see what happens, at least loop is very easy to implement as it is very similar to the hop function so I might have a go.

global goon ·

cool!

i tried it with feedback, but it doesn't overdrive in the way synthmakers inbuilt oscillators do.

. . . bOutf = bSin * bLevel; cOutf = cSin * cLevel; dOutf = dSin * dLevel; eOutf = eSin * eLevel; fOutf = fSin * fLevel;

aOutf = (aSin + (aCos - aSin * totalPhase) * totalPhase) * 0.6; // feedback 0.6 totalPhase = aOutf + bOutf + cOutf + dOutf + eOutf + fOutf;

aOut = aOutf;

[/code]

EDIT: yeah, this bit of code is nonsense!!

stefan ·

Strange, I succesfully tried overdrive and created a sawtooth that way. A bit busy atm, so I can't really look at your code right now 🙂

jorge ·

I put some drawbar modules in global goon's schematic:

[old link]

global goon ·

awesome!

Tom7777 ·

Nice, thanks everyone

global goon ·

i worked out last night that the code for the oscillator only works with phases of up to 90degrees(0.25). here is an osm that demonstrates this: http://www.globalgoon.com/synthmaker/stefan%20phase%20mod.osm

global goon ·

polyin freq; polyin phase; polyout out; float cos; float sin; float tCos,tSin; float mul;

// since the code component does not support initialising of variables we have to do a hack float isInitialised; isInitialised= ((cos > 0) & 1.0) + ((cos < 0) & 1.0); cos = (1.0 - isInitialised) * 0.99 + (isInitialised > 0) & cos; mul = freq * 6.283185; // roughly 2 * pi

cos = cos - sin * mul; sin = sin + cos * mul;

tCos = cos - sin * 4 * phase ; tSin = sin + tCos * 4 * phase; out = tSin;

to make this oscillator produce the same wave as the inbuilt, i shifted it up an octave and multiplied the phase by 4.

In the osm above, you'll see that both stefans osc and the inbuilt one work similarly upto a phase of 0.25. After that point, stefs amplitude increases (change the float box "max phase angle" from 0.25 to 1 to see this)

stefan ·

Well, if you skip multiplying the phase by four, it's ok to let it go from -1.0 to 1.0 if a slight change in amplitude is ok by you. It is by me 🙂

-1..1 allows for a 180 degree change of phase, also it allows phase feedback from another oscillator and so forth.

But if this oscillator is not suitable, use the sin1() function instead. It's not as efficient, but it's also less restricted and more precise. Taylor series is another option, but you'd have to deal with negative phase and "mirroring" the first half of the cycle when going to the other half etc. But it's doable. Not as efficiently as this though.

Are you interested in having a slightly more cpu heavy version of this sine, but allowing phase to go from 0 to 360 degrees instead of from -90 to +90?

global goon ·

cheers stefancrs,

i like the sound of your oscillator and it's low cpusage - it's nice and subtle

if it isn't any trouble i'd like to see your 360 degree one!

stefan ·

polyin freq; polyin phase; polyout out; float cos; float sin; float tCos,tSin; float mul; float mul2; // since the code component does not support initialising of variables we have to do a hack float isInitialised; isInitialised= ((cos > 0) & 1.0) + ((cos < 0) & 1.0); cos = (1.0 - isInitialised) * 0.99 + (isInitialised > 0) & cos; mul = freq * 6.283185307; // roughly 2 * pi

cos = cos - sin * mul; sin = sin + cos * mul; mul2 = 3.1415926535897932 * 0.25; tCos = cos; tSin = sin; loop(8) { tCos = tCos - tSin * phase * mul2; tSin = tSin + tCos * phase * mul2; }

out = tSin;

You can change the number of iterations and the multiplier if you like to get a higher precision or a higher efficiency (pick one 🙂)

This is really a 720 degree one though, you can go forwards or backwards in phase 360 degrees.

Tom7777 ·

Thanks everyone 🙂

Shifrin ·

Cheers Stefan 🙂

Shif.

global goon ·

nice one stef!

stefan ·

Just thought of a small optimisation.

polyin freq; polyin phase; polyout out; float cos; float sin; float tCos,tSin; float mul; float mul2; // since the code component does not support initialising of variables we have to do a hack float isInitialised; isInitialised= ((cos > 0) & 1.0) + ((cos < 0) & 1.0); cos = (1.0 - isInitialised) + (isInitialised > 0) & cos; mul = freq * 6.283185307179586476925286766559; // pi * 2

cos = cos - sin * mul; sin = sin + cos * mul; phase = phase - (phase > 0.5) & 1.0; phase = phase + (phase < -0.5) & 1.0; mul2 = phase * 1.5707963267948966192313216916398; // pi * 0.5 tCos = cos; tSin = sin;

loop(4) { tCos = tCos - tSin * mul2; tSin = tSin + tCos * mul2; }

out = tSin;

unkargherth ·

I managed to introduce another feature on this osc. Hard/Soft syncing To use it, connect output of another osc to "sync input. When this input croses form < 0 to > 0, phase gets set to zero

Thos ways of doing it: Hardsync: Simply set the phase to 0 Softsync: smoothly crossfades phase over 1/steps samples

Still haven't found how much aliasing it produces...

polyin freq; polyin phase; polyin sync; polyout out; float cos,sin; float tCos,tSin; float mul, mul2; float gateup, gatem1; // for sync trigger // float csync,ssync; // for hardsync float isync,syncing, step; // for softsync step=0.025;

// since the code component does not support initialising of variables we have to do a hack float isInitialised; isInitialised= ((cos > 0) & 1.0) + ((cos < 0) & 1.0); cos = (1.0 - isInitialised) + (isInitialised > 0) & cos; mul = freq * 6.283185307179586476925286766559; // pi * 2

// Read the sync trigger gateup=(sync>=0)&0.5+(gatem1<0)&0.5; gatem1=sync; //Uncomment this block for hardsync //csync=(gateup<1)&cos; //ssync=(gateup<1)&sin; //cos = csync; //sin = ssync;

//Uncomment this block for softsync syncing=max(syncing,gateup); isync=isync+(syncing>=1)&step;

cos=isync+(1-isync)*cos; sin=(1-isync)*sin; // End of softsync block

cos = cos - sin * mul; sin = sin + cos * mul; phase = phase - (phase > 0.5) & 1.0; phase = phase + (phase < -0.5) & 1.0; mul2 = phase * 1.5707963267948966192313216916398; // pi * 0.5 tCos = cos; tSin = sin;

loop(4) { tCos = tCos - tSin * mul2; tSin = tSin + tCos * mul2; }

out = tSin; // Uncomment this block for softsync syncing=(syncing>=1)&1-(isync>=1)&1; isync=(syncing>=1)&isync; // End of softsync block

jorge ·

Hi unkargherth

unkargherth wrote: I managed to introduce another feature on this osc. Hard/Soft syncing

I must say I'm very impressed, I guess this is the point where I can just stop working and let you guys do it all from now on. I knew the code component would open up a lot of possibilities but it's going a lot beyond my expectations. Thanks a lot unkargherth. I was already impressed with stefan's hack for initialising variables, everything seems possible even when it hasnt been implemented yet 🙂. I also like this collaborative work where each person improves on what was there before, it's great. I feel I should contribute too but its getting too hard now 🙂

lalo ·

jorge wrote: I must say I'm very impressed, I guess this is the point where I can just stop working and let you guys do it all from now on.

yet ready for your world-travelling jorge? 😉 don't let yer lappy at home 😀

yes guys i'm very impressed!!

congrats to you all and to jorge and malc...when i'll finish understand all this code i'll start contribute 😀

lowe

lalo

jorge ·

lalo wrote: yet ready for your world-travelling jorge? 😉 don't let yer lappy at home 😀

Yeah, I think I'll start with Italy, do you know anyone in Italy where I could stay for a week or so?

Here is some soft syncing in action using the stefan/unkargherth/global goon code ( did I forget anyone? ):

lalo ·

jorge wrote: lalo wrote: yet ready for your world-travelling jorge? 😉 don't let yer lappy at home 😀

Yeah, I think I'll start with Italy, do you know anyone in Italy where I could stay for a week or so?

😀..obviously by me 🙂

lalo

Shifrin ·

This is awesome stuff guys, wow. Thanks to all those who've contributed 🙂

Shif.

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.