SynthMaker

Code tips x a beginner

Archive · 2008 96 old posts

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

Acrobat ·

I've started learning some code basics for optimization purposes, unfortunately there's very a few informations on the subject:

1. what's the meaning of "<=", "=>", "==" and "&" - how do they work?

I'm trying to build a simple signal phase inverter and I guess I have to use those symbols to get the streamboolin input receive 0 for straight phase, 1 for inverted phase and change the input into -1,1 to multiply the signal input with that value.

Well, I know, that's pretty simple but I just started learning....basically I just need to transform a 0 into -1, if anyone can help... or point to some good infos on the web..

🙂

stefan ·

Acrobat wrote: I've started learning some code basics for optimization purposes, unfortunately there's very a few informations on the subject:

Cool! If possible / appropriate, I hope you will share your enhanced components with the rest of the community!

Acrobat wrote: 1. what's the meaning of "<=", "=>", "==" and "&" - how do they work?

<= is "less than or equal to" afaik, there's no =>, but >= would be "more than or equal to" == is "equal to" & is bitwise AND

Acrobat wrote: I'm trying to build a simple signal phase inverter and I guess I have to use those symbols to get the streamboolin input receive 0 for straight phase, 1 for inverted phase and change the input into -1,1 to multiply the signal input with that.

Well, I know, that's pretty simple but I just started learning....if anyone can help... or point to some good infos on the web..

🙂

Starting simple is the way to go! I would probably solve such an issue like so:

streamin in; streamboolin invert; streamout out; out = in * ( 1 - (invert & 2.0) );

or, if getting rid of the multiplication is wanted

out = in - ( invert & (in + in) );

THAT being said, it would in most cases probably be easier to skip the boolean stuff and just do like...

streamin in; streamin mul; streamout out; out = in * mul;

and set mul to -1 when you want to invert the signal, otoh, you might just as well just use a stream multiply primitive then, which isn't really what you're after if you want to learn to use the code component 😉

You'll probably have more questions, just fire'm away!

edit: and, oh! had a look at the Conditional statements and assignmentstutorial?

Acrobat ·

stefan wrote: Cool! If possible / appropriate, I hope you will share your enhanced components with the rest of the community! You'll probably have more questions, just fire'm away!

Thanks a lot, this thread gonna be a beginner course, I can build a library on the wiki (the wiki doesn't even show infos on the code component, I think it's time to improve that section!).. I'll make my best to learn and optimize for the others! 🙂 🙂 🙂

Acrobat ·

so == means "value equal to" and = means "variable equal to"

ok, and conditional statements on the wiki explains the AND bitwise, I'm reading that....

other questions...mmh ... for example I learned there are different stages, I suppose all what we wrote 'till now is working in the stage 0, right?

I mean if I don't specify the stage, SM supposes it's the 0 one?

🙂

stefan ·

Acrobat wrote: so == means "value equal to" and = means "variable equal to"

Hm, the first is correct but I don't get what you mean by the second statement. = is the assignment operator, like x = a * b, and not a comparison operator.

Acrobat wrote: other questions...mmh ... for example I learned there are different stages, I suppose all what we wrote 'till now is working in the stage 0, right?

I mean if I don't specify the stage, SM supposes it's the 0 one?

🙂

No, stage(1) 🙂 stage(0) runs when the "process" is created (like when a voice is allocated for instance), so for instance this little piece of code:

float a = 3.0;

sets a to 3.0 in stage(0) (which just happens once for this specific instance of the variable a)

stage(1) is however the standard "do this for each sample" code.

Acrobat ·

big thanks..

so there are assignments and comparisons, 2 differnt things,ok..

..and why did you wrote just one decimal after the numerical value? 1.0, 2.0, 3.0

I guess that's intended to be 1.000000000000000 and if the value is 0.9999999999999 the result is false...

can I write 1 or it's needed to be 1.0 for some special reason?

I ask because I've seen in the stock SVF Filter some values having an incredible amount of decimals, like 0.3333333333333333333333333, I suppose that gives more precision, what are the limits?

I think I've made enough trouble for today, thanks a lot again, A.

stefan ·

Acrobat wrote: big thanks..

so there are assignments and comparisons, 2 differnt things,ok..

..and why did you wrote just one decimal after the numerical value? 1.0, 2.0, 3.0

I guess that's intended to be 1.000000000000000 and if the value is 0.9999999999999 the result is false...

can I write 1 or it's needed to be 1.0 for some special reason?

I ask because I've seen in the stock SVF Filter some values having an incredible amount of decimals, like 0.3333333333333333333333333, I suppose that gives more precision, what are the limits?

I think I've made enough trouble for today, thanks a lot again, A.

I wrote 1.0 just to clarify that it was a floating point value, it's exactly the same value as 1 or 1.0000000000000000. The reason for all those 3's in the SVF code is different from appending lots of zeros. Appending zeros does nothing to the value while appending 3's increases the precision if it's the value 1/3 we're after 🙂

Keep in mind when doing comparisons with floating point values that you can most of the time NOT expect exact values (like 100 + 0.7 might not result in EXACTLY 100.7 when it's floating point maths.)

Acrobat ·

stefan wrote: otoh, you might just as well just use a stream multiply primitive then, which isn't really what you're after if you want to learn to use the code component 😉

Not only for that reason, I might want to invert the phase at poly speed rate, the stream multiply method would rely on a green integer switch instead....well, I read somewhere there's no sample-accurate triggering but surely it is a lot faster.. 🙂

stefan ·

Acrobat wrote: stefan wrote: otoh, you might just as well just use a stream multiply primitive then, which isn't really what you're after if you want to learn to use the code component 😉

Not only for that reason, I might want to invert the phase at poly speed rate, the stream multiply method would rely on a green integer switch instead....well, I read somewhere there's no sample-accurate triggering but surely it is a lot faster.. 🙂

Nono, I meant by having the "in" stream connected to one stream multiplicator input and the "invert" stream to the other, setting the invert streams value to -1 to invert the stream and +1 to keep it normal.

Acrobat ·

stefan wrote: Keep in mind when doing comparisons with floating point values that you can most of the time NOT expect exact values (like 100 + 0.7 might not result in EXACTLY 100.7 when it's floating point maths.)

ok.. I know what you mean, that's for the FPU. So I guess this a case where rounding to the integer can be useful.. 🙂

Acrobat ·

stefan wrote: Nono, I meant by having the "in" stream connected to one stream multiplicator input and the "invert" stream to the other, setting the invert streams value to -1 to invert the stream and +1 to keep it normal.

aaah yes, that works at full speed, yeah, sorry..

aliasant ·

Great thread.

Ill try to make another example question.

I often use the Max and Min to limit signals and so far I have excluded them from my optimizations since I havnt been sure how to implements them with the rest of the math.

streamin A; streamin B; streamin C; streamout out;

out=(A-B)*C;

This is a simple one that I might want to add a Min 0.5 to. So that nothing less then 0.5 goes thru.

What would that look like?

And maybe I need a max 1.5 as well. What would that then be?

TomC ·

aliasant wrote: Great thread.

Ill try to make another example question.

I often use the Max and Min to limit signals and so far I have excluded them from my optimizations since I havnt been sure how to implements them with the rest of the math.

streamin A; streamin B; streamin C; streamout out;

out=(A-B)*C;

This is a simple one that I might want to add a Min 0.5 to. So that nothing less then 0.5 goes thru.

What would that look like?

And maybe I need a max 1.5 as well. What would that then be?

If I understand you correctly you mean 0.5<=out<=1.5?

That'd be

streamin A; streamin B; streamin C; streamout out;

out=(A-B)*C; out = (out>=0.5 & out) & (out<=1.5 & out) & out;

Tom

infuzion ·

TomC wrote: ... out = (out>=0.5 & out) & (out<=1.5 & out) & out;

Why not min() max()?

stefan ·

And won't out become zero, which clearly is less than 0.5, if it before the statement is out of range? Or was that wanted?

I'd just go:

out = min(1.5, max(0.5, out));

should work.

chironex ·

I really have no clue how the conditional statements work, and the manual doesn't help much.

Could anyone clear away my fog? Thanks. 🙂

infuzion ·

chironex wrote: I really have no clue how the conditional statements work, and the manual doesn't help much. Could anyone clear away my fog? Thanks. 🙂

search wiki

TomC ·

infuzion wrote: TomC wrote: ... out = (out>=0.5 & out) & (out<=1.5 & out) & out;

Why not min() max()?

Too simple for the state of mind I'm currently in (read: I completely forgot the min/max functions).

Cheers,

Tom

aliasant ·

stefan wrote: And won't out become zero, which clearly is less than 0.5, if it before the statement is out of range? Or was that wanted?

I'd just go:

out = min(1.5, max(0.5, out));

should work.

Thanx Stefan. streamin in1; streamin in2; streamout out;

out=in1*in2; out = min(1.5, max(0.5, out));

That works perfectly. I didnt realize I could have more then 1

out = xxxxxxx Im so nooob

Tom7777 ·

What would this be in code?

Also does anyone have the code for just the lowpass from the SVF? the more optimized the better 😀

aliasant ·

Tom7777 wrote: What would this be in code?

I have made that half finished. I havnt managed to put in the inverse yet. Without the inverse it looks like this

Except that A and B is in my code A and C B is the one were I placed the inverse outside the code and D is just the plain mxi /crossfade In.

streamin A; streamin B; streamin C; streamin D; streamout out;

out=((A*B)+C*D);

It works but there are probably a better way to do it. And of course we need to put that inverse in it somehow. Havnt given it much thought yet.

Tom7777 ·

Thats got 4 inputs, if im right in thinking you can have the 1 inside the code somehow like

float v1;

then have

v1 = 1;

somewhere, but i maybe wrong

also your fast, i just edited the post above asking for a LP because i have no idea how, i can delete a few lines and have it working but thats definately not the best way im guessing 🙂

aliasant ·

😀

stefan ·

streamin InputA; streamin InputB; streamin Crossfade; streamout Output;

Output = InputA * (1 - Crossfade) + InputB * Crossfade;

or, slightly optimized:

Output = InputA + Crossfade * (InputB - InputA);

exonerate ·

The crossfader would be......

streamin input_A; streamin input_B; streamin crossfade; streamout out;

out = (input_A*(1-crossfade))+(input_B*crossfade);

cheers 😉

Exo

edit...stefan beat me 🙂

aliasant ·

its funny here that your codes are almost identical. But Stefan left out the ( )

Does that mean Stefans code is slightly more optimized?

And hey . THanx guys =)

Beautiful as ever.

Edit: I cant get Stefans codes to work.... But Exos works nice. Oops?

Updated: Stefan fixed the code =) I have no explanation to why I didnt see the missing semicolon. I guess Im just me........

aliasant ·

Oh. Another thing.

Tom7777 wanted to have a lowpass/smoother in here so we have a softer transition. We could always have a dezipper outside but I think he wanted one inside it. How would THAT look =) ??

Tom7777 ·

Thanks guys, well for the lowpass i wanted it exactly how it is in the SVF module but without the other filters highpass etc and optimized if possible. 😉

Edit - the other stuff would be there outside of the code, but the code would replace the main bit im sure you know what i mean 🙂

stefan ·

aliasant wrote: its funny here that your codes are almost identical. But Stefan left out the ( )

Does that mean Stefans code is slightly more optimized?

And hey . THanx guys =)

Beautiful as ever.

Edit: I cant get Stefans codes to work.... But Exos works nice. Oops?

I missed out on the final semi-colon 🙂 Edited the post.

The paranthesis doesn't have an effect on performance, it's just more clear (when you read the code) in which order stuff should be calculated with them there.

TomC ·

aliasant wrote: its funny here that your codes are almost identical. But Stefan left out the ( )

Does that mean Stefans code is slightly more optimized?

And hey . THanx guys =)

Beautiful as ever.

Edit: I cant get Stefans codes to work.... But Exos works nice. Oops?

Did you add the missing semicolon at the end of the last line of Stefan's code?

Tom

[Edit:] just noticed that Stefan corrected this while I wrote my posting.

exonerate ·

aliasant wrote: its funny here that your codes are almost identical. But Stefan left out the ( )

Does that mean Stefans code is slightly more optimized?

And hey . THanx guys =)

Beautiful as ever.

Edit: I cant get Stefans codes to work.... But Exos works nice. Oops?

Updated: Stefan fixed the code =)

Yeah as stefan mentioned the parenthesis is for readability so you can see at a glance the order things get calculated.

I think it's good practice to use them even when there not really needed, sometimes they are needed as with the (1-crossfade) if you didn't include them there then you would be multiplying input_A by 1 and then subtracting crossfade from that so in effect it would be......

(input_A*1)-crossfade

which would give you a completely different result.

This is because multiplication has precedence over subtraction, meaning it will be calculated first.

Also you'll see that we both have used descriptive names for the inputs, instead of your A,B,C ect.... this is also good programming practice, code has to be readable, and you should be able to know exactly what the code is doing just by glancing at it.

Cheers 😉

Exo

aliasant ·

exo wrote: Also you'll see that we both have used descriptive names for the inputs, instead of your A,B,C ect.... this is also good programming practice, code has to be readable, and you should be able to know exactly what the code is doing just by glancing at it.

Yeah. You are so right. I had fought my way thru a filter changing all the stuff possible to code and then to assembly code. That made it impossible to understand afterwords. Lucky for me I had the original module saved so I could pick it up to see what t.h. I had done.

I will name everything from now. =)

Btw. I used the cpu cycles analyzer to see if there was a diference between my original Mix Module and Stefs and yours. Couldnt really see much difference. If any at all. And that CPU cycles analyzer seems not to be the best. Very hard to get good results from.

Wouldnt it be nice if this was built into SM? Just hover the mouse over a module for more then 1 sec to see the cycles/cpu usage in %, as a floating little window. When mouse moves windows dissapears.

Panoply ·

I'm a c++ coder of sorts, and can't tell you how important properly readable code is.

you almost certainly don't need it for a little bit of code... you might think. But honestly, if you come back to even simple code in a couple of months time, where everything is A,B and var1, var2 it will just be a jumble, and you won't have an idea what anything means (or at least I find this to be true).

Also, its a very good idea if you follow some sort of standard, as it means other people will have a far easier time of helping you and understanding your code.

This is what I use, because errr well thats what I was taught, but there are others (probably better/more up to date/more relevant to SM for all I know).

http://en.wikipedia.org/wiki/Hungarian_notation

Do take the extra 5 minutes to make your code legible in the long run its in your interests! 🙂

/rant.

infuzion ·

Panoply wrote: http://en.wikipedia.org/wiki/Hungarian_notation

FYI: 98% of stream/audio data in SM is 32bit floats. On rare occasion one might convert to Int for rounding reasons, or use a Bool.

exonerate ·

infuzion wrote: Panoply wrote: http://en.wikipedia.org/wiki/Hungarian_notation

FYI: 98% of stream/audio data in SM is 32bit floats. On rare occasion one might convert to Int for rounding reasons, or use a Bool.

Yeah it would make no sense to use that in SM, I don't even see the sense in using it in C++ to be honest.

Panoply ·

FYI: 98% of stream/audio data in SM is 32bit floats. On rare occasion one might convert to Int for rounding reasons, or use a Bool.

Which is why I suggested that there might be a more suited one to SM outside of my sphere of knowledge...

...my point is that a standardised method of naming would be No Bad Thing, especially for problematic code.

I don't even see the sense in using it in C++ to be honest.

my hat is off - you're clearly a better coder then me. 😉 However, if for some reason I was trying to understand your code, I would find it considerably easier if it was named this way.

Acrobat ·

Tom7777 wrote: Thanks guys, well for the lowpass i wanted it exactly how it is in the SVF module but without the other filters highpass etc and optimized if possible. 😉

Hey Dan, just dive into the stock compressor, there's lowpass and highpass separate, coded filters! I guess that's what you'r searching for...

😉 A.

infuzion ·

Panoply wrote: Which is why I suggested that there might be a more suited one to SM outside of my sphere of knowledge...

That is excellent advice for dealing with green Float data & sometimes stream, since one doesn't know the expected range unless you're a guru or take alot of time studying the OSM. For example, most audio data is expected to be -1..+1, but modifying audio data (eg LFOs) is typically only 0..+1. Green float data for pitch is confusing to me, since it may be either 0..1 or in Hz.

So perhaps SM should have some standard notation to express these concepts in a single letter (or 2 symbols) some how?

Tom7777 ·

Hey Dan, just dive into the stock compressor, there's lowpass and highpass separate, coded filters! I guess that's what you'r searching for...

Thanks, almost but still useful, this doesn't seem to be exactly like the SVFs though as theres no resonance.

stefan ·

Tom7777 wrote: Hey Dan, just dive into the stock compressor, there's lowpass and highpass separate, coded filters! I guess that's what you'r searching for...

Thanks, almost but still useful, this doesn't seem to be exactly like the SVFs though as theres no resonance.

If you want it to be EXACTLY like the SVF there really isn't much one can optimize. One can skip the notch calculation, but all the other modes must still be calculated. So, just use the SVF and don't use the unnecessary outputs.

exonerate ·

Yeah the only way you could optimize the SV is to put the coeff calculation in a hop and remove the oversampling, which will lower sound quality.

Heres a version I destroyed earlier 😉 ...

streamin input; streamin cut; streamin resonance;

streamout lp1; //lowpass; //streamout highpass; //streamout bandpass; //streamout notch; //streamout peak; float cutoff, rez, f; float hp1, bp1;//,lp1; float multi, x, x2, x3, x5, x7; //multi = 0.33333333333333333333333333333333;

rez = 1.0 - resonance; // clamp at 1.0 and 20/44100 cutoff = max(cut, 0.00045351473922902494331065759637188); cutoff = min(cutoff, 1.0); // tunable version //f = 2 * sin1((3.141592 * (cutoff / 36.0))); // taylor series version of 2 * sin(x) // cutoff * 1/38.0 hop(512) { x = 3.141592 * (cutoff * 0.026315789473684210526315789473684) * 2 * 3.141592; x2 = x*x; x3 = x2*x; x5 = x3*x2; x7 = x5*x2; // x3 / 6, x5 /120, x7 / 5040; f = 2.0 * (x - (x3 * 0.16666666666666666666666666666667) + (x5 * 0.0083333333333333333333333333333333) - (x7 * 0.0001984126984126984126984126984127)); } input = input + 1e-009; lp1 = lp1 + f * bp1; hp1 = (input-1e-009) - lp1 - rez * bp1; bp1 = f * hp1 + bp1; /*lowpass = lp1; highpass = hp1; bandpass = bp1;

lp1 = lp1 + f * bp1; hp1 = input - lp1 - rez * bp1; bp1 = f * hp1 + bp1; lowpass = lowpass + lp1; highpass = highpass + hp1; bandpass = bandpass + bp1;

input = input - 0.000000001; lp1 = lp1 + f * bp1; hp1 = input - lp1 - rez * bp1; bp1 = f * hp1 + bp1; lowpass = (lowpass + lp1) * multi; highpass = (highpass + hp1) * multi; bandpass = (bandpass + bp1) * multi;

peak = input + bandpass; notch = lowpass + highpass;*/ //no oversampling

That will be less stable at high resonance and if your modulating the cutoff with a fast lfo you might need to lower the hop number.

You could keep the oversampling and just use the hop, should sound pretty much the same then.

cheers 😉

Exo

stefan ·

exonerate: If I were you I'd give removing the averaging of the different outputs a try, you'll most likely get a better frequency response.

exonerate ·

stefan wrote: exonerate: If I were you I'd give removing the averaging of the different outputs a try, you'll most likely get a better frequency response.

You mean?

streamin input; streamin cut; streamin resonance;

streamout lowpass; //streamout highpass; //streamout bandpass; //streamout notch; //streamout peak; float cutoff, rez, f; float hp1, bp1,lp1; float multi, x, x2, x3, x5, x7; //multi = 0.33333333333333333333333333333333;

rez = 1.0 - resonance; // clamp at 1.0 and 20/44100 cutoff = max(cut, 0.00045351473922902494331065759637188); cutoff = min(cutoff, 1.0); // tunable version //f = 2 * sin1((3.141592 * (cutoff / 36.0))); // taylor series version of 2 * sin(x) // cutoff * 1/38.0 hop(512) { x = 3.141592 * (cutoff * 0.026315789473684210526315789473684) * 2 * 3.141592; x2 = x*x; x3 = x2*x; x5 = x3*x2; x7 = x5*x2; // x3 / 6, x5 /120, x7 / 5040; f = 2.0 * (x - (x3 * 0.16666666666666666666666666666667) + (x5 * 0.0083333333333333333333333333333333) - (x7 * 0.0001984126984126984126984126984127)); } input = input + 1e-009; lp1 = lp1 + f * bp1; hp1 = (input-1e-009) - lp1 - rez * bp1; bp1 = f * hp1 + bp1; lowpass = lp1; /*highpass = hp1; bandpass = bp1;

lp1 = lp1 + f * bp1; hp1 = input - lp1 - rez * bp1; bp1 = f * hp1 + bp1; lowpass = lowpass + lp1; highpass = highpass + hp1; bandpass = bandpass + bp1;

input = input - 0.000000001; lp1 = lp1 + f * bp1; hp1 = input - lp1 - rez * bp1; bp1 = f * hp1 + bp1; lowpass = (lowpass + lp1) * multi; highpass = (highpass + hp1) * multi; bandpass = (bandpass + bp1) * multi;

peak = input + bandpass; notch = lowpass + highpass;*/ //no oversampling

stefan ·

exonerate wrote: You mean?

No I mean:

streamin input; streamin cut; streamin resonance;

streamout lowpass; //streamout highpass; //streamout bandpass; //streamout notch; //streamout peak; float cutoff, rez, f; float hp1, bp1,lp1; float multi, x, x2, x3, x5, x7; //multi = 0.33333333333333333333333333333333;

rez = 1.0 - resonance; // clamp at 1.0 and 20/44100 cutoff = max(cut, 0.00045351473922902494331065759637188); cutoff = min(cutoff, 1.0); // tunable version //f = 2 * sin1((3.141592 * (cutoff / 36.0))); // taylor series version of 2 * sin(x) // cutoff * 1/38.0 hop(512) { x = 3.141592 * (cutoff * 0.026315789473684210526315789473684) * 2 * 3.141592; x2 = x*x; x3 = x2*x; x5 = x3*x2; x7 = x5*x2; // x3 / 6, x5 /120, x7 / 5040; f = 2.0 * (x - (x3 * 0.16666666666666666666666666666667) + (x5 * 0.0083333333333333333333333333333333) - (x7 * 0.0001984126984126984126984126984127)); } input = input + 1e-009; lp1 = lp1 + f * bp1; hp1 = (input-1e-009) - lp1 - rez * bp1; bp1 = f * hp1 + bp1;

lp1 = lp1 + f * bp1; hp1 = input - lp1 - rez * bp1; bp1 = f * hp1 + bp1;

input = input - 0.000000001; lp1 = lp1 + f * bp1; hp1 = input - lp1 - rez * bp1; bp1 = f * hp1 + bp1; lowpass = lp1;

🙂

Btw, wouldn't you have to get rid of the assignments to the non-existing outputs?

Also I would probably change the denormal removal code into truncating to zero if too small values in the feedback path, or, if doable, avoid denormal removal code in some other manner (I guess the only other manner would be to feed noise into the entire stream section though, so maybe truncating or adding small values like now is best...)

fabb ·

Hi there! I'm also a newbie at the code component, started today with it. I've got a bit programming knowledge, but not in DSP yet - but it doesn't seem as hard as I thought. On the other hand the few available instructions seem a bit limiting.

Is there a way to calculate a square root?

And I've got a problem with arrays:

monoout xout; float x[2],tmp; x[0]=5; x[1]=x[0]; //this doesn't get executed xout=x[1]; //and so this outputs 0 instead of 5

Sure, I can save the value of x[0] in a temporary variable and then assign x[1] to that variable's value, but that seems a bit unnecessarily complicated.

EDIT: And a third question tortures me: how can I mask the sign of a float value?

thanks for helping!

Acrobat ·

stefan wrote: Tom7777 wrote: Hey Dan, just dive into the stock compressor, there's lowpass and highpass separate, coded filters! I guess that's what you'r searching for...

Thanks, almost but still useful, this doesn't seem to be exactly like the SVFs though as theres no resonance.

If you want it to be EXACTLY like the SVF there really isn't much one can optimize. One can skip the notch calculation, but all the other modes must still be calculated. So, just use the SVF and don't use the unnecessary outputs.

1. On the "unnecessary outputs": SVF (and other code giving multiple outputs) requires approx 500 cycles on my computer for every out apart from the bandpass giving out a few less, like 430), it's the same on every computer?

2. I played a bit more with the code module and converting stream nets to code gives some results, I'm very happy, even if I expected more from the change... when I measure a block that is less that 80-90 with the CPU meter I don't get almost any improvement after the cure,... it's normal?

Anyway I succeded in converting the voicing in Alieno for the lateral modules from 700 cycles to 590 each which gives me a lot less stress to the CPU... simply putting everything in code, things like multiplications, min max, nothing too complicated still... It's cool, very fun, but I still don't understand how floats can be used in a proper way, at the moment I just change assignments without involving too much floats..

What's not so clear to me is the flow, I find myself coding from the bottom to the top instead of writing lines in succession because I know what I need (the outputs)...so from the end of the loop to its start, strange ! 😕

Tom7777 ·

Thanks everyone, the lowpass wouldnt have to be exactly the same btw but just sound the same as the SVFs really with a cutoff and reso working on a 0-1 system and as low cpu as possible so i can use a few without getting huge cpu rises, also if anyones cool with making me one a allpass that is 0-1 as usually but low cpu so can be put in a chain. I usually try to make what i can myself but theres some things like certain filters i can't really do without having coded by someone. 🙂

infuzion ·

fabb wrote: Is there a way to calculate a square root?

And I've got a problem with arrays:

EDIT: And a third question tortures me: how can I mask the sign of a float value?

1a) SM ASM has sqrtps activated 1b) There is a module in the toolbox for x^y, so I think if y=0.5 = sqr(x) 2) SM arrays are kinda a hack in SM... might be out of scope for SM's implementation, or a bug. :/ 3) You mean absolute value? More ASM: streamin i;streamout o; int ABSMASK=2147483647; movaps xmm0,i; andps xmm0,ABSMASK; movaps o,xmm0; Code is o=i&absmask; I think.

infuzion ·

stefan wrote: Also I would probably change the denormal removal code into truncating to zero if too small values in the feedback path, or, if doable, avoid denormal removal code in some other manner (I guess the only other manner would be to feed noise into the entire stream section though, so maybe truncating or adding small values like now is best...)

Interesting... exactly where would the single truncation or the add noise go? Inside the hop() near the beginning? At the end of the entire code? TIA 😇

exonerate ·

fabb wrote: Hi there! I'm also a newbie at the code component, started today with it. I've got a bit programming knowledge, but not in DSP yet - but it doesn't seem as hard as I thought. On the other hand the few available instructions seem a bit limiting.

Is there a way to calculate a square root?

And I've got a problem with arrays:

monoout xout; float x[2],tmp; x[0]=5; x[1]=x[0]; //this doesn't get executed xout=x[1]; //and so this outputs 0 instead of 5

Sure, I can save the value of x[0] in a temporary variable and then assign x[1] to that variable's value, but that seems a bit unnecessarily complicated.

EDIT: And a third question tortures me: how can I mask the sign of a float value?

thanks for helping!

Yeah it seems you cannot do the x[1]=x[0]; doesn't seem to work, you could go the temporay variable route, but it's easier to set them to the same value using a loop.

for example...

monoout xout; float x[4],index,index2;

stage(0) { loop(2) { x[index]=5; //Set index 0/1 to 5 index = index+1; } index2 = 2; loop(2) { x[index2]=8; //Set index 2/3 to 8 index2 = index2+1; } } xout=x[1];

as you can see because your filling the array with static variables it makes sense to use stage 0 (which is the initialization stage) this example will use a lot less CPU doing it in stage zero.

Acrobat ·

My first creations, both from Alieno, the first one is a simple thing, strum voicing:

streamin freq; streamin tune; streamin tuneinv; streamin anim; streamin sr;

streamout freq1; streamout freq2;

float srrev;

srrev = 1/(sr * 0.5); freq1 = srrev * ((tune+anim) * freq); freq2 = srrev * ((tuneinv+anim) * freq);

and the second is a bit more complicated, it's the warp effect in the upper left corner:

streamin inL; // asse di vibrazione sinistro streamin inR; // asse di vibrazione destro streamin factor; // fattore di campo streamin lfo; // curvatura spazio-temporale

streamout inLfd; // residuale sinistra streamout inRfd; // residuale destra streamout inpanL; // deformazione sinistra streamout inpanR; // deformazione destra streamout panpos; // vibrazione di campo

float factorinv, amp, pan; // flottanze di propulsione

factorinv = ( 1 - factor ); // calcolo del residuo

amp = ( lfo + 0 ) * 2; // calcolo della deformazione amp = min(amp,1); amp = max(amp,0);

inLfd = inL * factorinv; // eiezione sinistra inRfd = inR * factorinv; // eiezione destra inpanL = ( inL * factor ); // massa inpanR = (inR * amp); // energia panpos = amp; // eventualita'

can anyone please can tell if it's alright/can be better? A. 🙂

oddson ·

srrev = 1/(sr * 0.5); Since the 1/Nyquist value is constant you should either calculate it in green outside or make it a stage(0) calculation (assuming that's what this is).

Acrobat ·

oddson wrote: srrev = 1/(sr * 0.5); Since the 1/Nyquist value is constant you should either calculate it in green outside or make it a stage(0) calculation (assuming that's what this is).

oh yes it is, I did that to avoid a divide, I'll do that outside, thx! 😀

...mmh... I've noticed that when you write a number in code, that number is taken as a float, I wrote for example A = 1 /(B+C) and linking a string to the code module and in ASM it says that "1" is assigned to a float, that's strange... I was thinking that numbers remain numbers and nothing more... 😕

stefan ·

infuzion wrote: stefan wrote: Also I would probably change the denormal removal code into truncating to zero if too small values in the feedback path, or, if doable, avoid denormal removal code in some other manner (I guess the only other manner would be to feed noise into the entire stream section though, so maybe truncating or adding small values like now is best...)

Interesting... exactly where would the single truncation or the add noise go? Inside the hop() near the beginning? At the end of the entire code? TIA 😇

I'd put truncation of all feedback paths inside the filter at the end. Adding noise I'd do wherever it ends being added to the entire stream section so that it'd remove all denormals in that section.

infuzion ·

Acrobat wrote: and the second is a bit more complicated, it's the warp effect in the upper left corner: streamin inL; // asse di vibrazione sinistro streamin inR; // asse di vibrazione destro streamin factor; // fattore di campo streamin lfo; // curvatura spazio-temporale

streamout inLfd; // residuale sinistra streamout inRfd; // residuale destra streamout inpanL; // deformazione sinistra streamout inpanR; // deformazione destra streamout panpos; // vibrazione di campo

float factorinv, amp, pan; // flottanze di propulsione

factorinv = ( 1 - factor ); // calcolo del residuo

amp = ( lfo + 0 ) * 2; // calcolo della deformazione amp = min(amp,1); amp = max(amp,0);

inLfd = inL * factorinv; // eiezione sinistra inRfd = inR * factorinv; // eiezione destra inpanL = ( inL * factor ); // massa inpanR = (inR * amp); // energia panpos = amp; // eventualita' can anyone please can tell if it's alright/can be better?

I don't understand what you mean by "field factor"/"fattore di campo"? And I don't understand why you amp the Right out without an amp for the Left? Why LFO+0? You also can combine a few functions: streamin inL; // asse di vibrazione sinistro streamin inR; // asse di vibrazione destro streamin factor; // fattore di campo streamin lfo; // curvatura spazio-temporale

streamout inLfd; // residuale sinistra streamout inRfd; // residuale destra streamout inpanL; // deformazione sinistra streamout inpanR; // deformazione destra streamout panpos; // vibrazione di campo

float factorinv, pan; // flottanze di propulsione

factorinv = ( 1 - factor ); // calcolo del residuo

panpos = max( min( (lfo * 2) ,1) ) ,0); // calcolo della deformazione

inLfd = inL * factorinv; // eiezione sinistra inRfd = inR * factorinv; // eiezione destra inpanL = inL * factor; // massa inpanR = inR * panpos; // energia

== Acrobat wrote: I've noticed that when you write a number in code, that number is taken as a float,... in ASM it says that "1" is assigned to a float

Almost all "stream" audio are 4 channels of 32bit floats. When SM translates Code into ASM, it assumes this. Exceptions: * PolyInt: 4 channels of 32bit integers * Mono (plain,1 dot): 1 channel of 32bit float * Stream Double ("D"): 2 channels of 64bit floats (or maybe 2x2, taking up twice the CPU of a regular stream)[/list]

Acrobat ·

The warp is a sort of a pan-tremolo, "Factor" is the first knob, similar to a mix, then there's the lfo waveform selection and a third rotary to control the speed of lfo in 16ths of the beat. The only green float that enters the code is "Factor", the other two controls affects the lfo. LFO+0 is an old fix used by many people here, I don't know exactly what they apply w/that, it can be deleted I guess. The distribution of values to the 2 different pan modules: I think is correct, this code has to be attached to other two codes that perform a simple pan and then to a third code joining together the stereo image, so this code is just the "distribution of forces"... 🙂

The problem is I am reproducing a net of blue streams, so I don't know how to reproduce the connection order properly..so a good question is this: Q; how to reproduce connection order of streams in code?

@ infuzion: Thanks for the combination in one line of min max, that's my next step to learn, combine things in one line where is possible!

fabb ·

exonerate wrote: Yeah it seems you cannot do the x[1]=x[0]; doesn't seem to work, you could go the temporay variable route, but it's easier to set them to the same value using a loop.

This doesn't work for my code, as x[0] is the actual value and x[1] is the value at the sample 1024 back (hop). Each round I calculate the difference and set x[1] to the newer x[0] and calculate a new x[0]:

... stage(1){ hop(1024) { gx=x[0]-x[1]; ... x[0]=x[0]+(1.0... ... xout=x[0]; xout=max(xout,0); //will this work? xout=min(xout,1); //xout is a monoout. Can I first set the output and then use it to change itself? Or would I get jumps within one sample here? } }

Then I'll go with the temporary variable.

fabb ·

infuzion wrote: fabb wrote: Is there a way to calculate a square root?

And I've got a problem with arrays:

EDIT: And a third question tortures me: how can I mask the sign of a float value?

1a) SM ASM has sqrtps activated 1b) There is a module in the toolbox for x^y, so I think if y=0.5 = sqr(x) 2) SM arrays are kinda a hack in SM... might be out of scope for SM's implementation, or a bug. :/ 3) You mean absolute value? More ASM: streamin i;streamout o; int ABSMASK=2147483647; movaps xmm0,i; andps xmm0,ABSMASK; movaps o,xmm0; Code is o=i&absmask; I think.

Yeah, I know the power module, but I had to go out of the code module in the middle of my calculations and then back into a new code module. *grmbl* In which stage are the external modules calculated?

And sqrtps is just for ASM? Assembler isn't my thing (yet)...

Thanks, 2147483647 works out great!

fabb

fabb ·

Tom7777 wrote: Thanks everyone, the lowpass wouldnt have to be exactly the same btw but just sound the same as the SVFs really with a cutoff and reso working on a 0-1 system and as low cpu as possible so i can use a few without getting huge cpu rises, also if anyones cool with making me one a allpass that is 0-1 as usually but low cpu so can be put in a chain. I usually try to make what i can myself but theres some things like certain filters i can't really do without having coded by someone. 🙂

Have a look at Robert Bristow-Johnson's EQ Cookbook: http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt I didn't yet use it myself, but it should be good. Gol used this for his Parametric EQ2 in FL Studio, so it can't be bad!

fabb ·

Square Root Aproximation: http://mathworld.wolfram.com/SquareRootAlgorithms.html Found this aproximation formulas, the 4th/5th order is close enough for me!

Phew! Just came around using the ASM module... 😉

rl ·

more square root: http://michael.dipperstein.com/sqrt/index.html

TomC ·

For most things I do the following approximation is close enough:

/* sqrt(x) approximation * * max(error) in [0,1] < 0.12 * * Tom Crowning */

streamin in; streamout out;

float x2, x3;

x2 = in*in; x3 = in*x2;

out = (1+21*in+35*x2+7*x3)/(7+35*in+21*x2+x3);

Cheers, Tom

bootsy ·

What a coincidence - I just used that Pade aprox as a substitute for the sqrtps but unfortunately its not that much faster and not precise enough for my needs - I'm gonna continue searching and maybe report here ...

fabb ·

TomC wrote: For most things I do the following approximation is close enough:

/* sqrt(x) approximation * * max(error) in [0,1] < 0.12 * * Tom Crowning */

streamin in; streamout out;

float x2, x3;

x2 = in*in; x3 = in*x2;

out = (1+21*in+35*x2+7*x3)/(7+35*in+21*x2+x3);

Cheers, Tom

For values between 0.1 and 1 this is perfect. But below 0.1 it get's hairy. The maximum error is 0.1429, at an input val 0. Not so good!!

Acrobat ·

Ok, I've got a simplier, much more readable version of Warp effect:

// warp effect, Acrobat february 2008 streamin asse; // signal input streamin curvatura; //modulation input streamin fattore; //0..1 dry/wet control

streamout warpL; //left output streamout warpR; //right output

// calcolo variabili float eiezione,deformazione,residuale; eiezione = max(min(curvatura,1),0); deformazione = asse*curvatura*2*fattore; residuale = asse*(1-fattore);

// composizione stereo warpL = ((1-eiezione*eiezione)*deformazione)+residuale; warpR = ((1-(1-eiezione)*(1-eiezione))*deformazione)+residuale;

applied all tricks you gave me and tried to stay in line as much as possible, now it uses 52 cycles, stream version was 57!

😀

Tom7777 ·

Anyone notice that cpu in effects seems to be constant even if the connected test synth isn't playing? I don't think it used to be that way but i may be wrong, anyways one of my effect uses 8 of these allpasses and is 56% cpu, does anyone know how to optimize this -

streamin in; streamin freq; streamin q; streamout out;

float in1,in2,out1,out2; float a0,a1,a2,b0,b1,b2; float sin,cos,alpha,abs;

stage(0) { abs = 3.4e38|0.999999|0.1; b2 = 1; } stage(1) { sin = sin1(0.5*freq); cos = cos1(0.5*freq); alpha = sin/(2*q); a0 = 1/(1 + alpha); a1 = a0*-2*cos; a2 = a0*(1 - alpha); b0 = a2; b1 = a1; out = in*b0 + in1*b1 + in2*b2 - out1*a1 - out2*a2; out = ((out&abs) > 1e-11)&out; out2 = out1; out1 = out; in2 = in1; in1 = in; }

Also if a code has been optimized is it still more efficiant to convert to ASM after or could that mess things up? And if anyones willing to i have a ASM SVF im using which i converted from code that could be optimized.

Acrobat ·

Dan, experts may correct me if I'm wrong but the ASM that comes from code is exactly efficient as the code, it must be reduced at hand to gain some speed..

MyCo ·

Well the ASM-Code in this case is unoptimized 50 Cycles faster. That's 25%!

I changed the code to that:

streamin in; streamin freq; streamin q; streamout out0;

float in1,in2,out1,out2; float a0,a1,a2; float sin,cos,alpha,abs;

stage(0) { abs = 3.4e38|0.999999|0.1; } stage(1) { sin = sin1(0.5*freq); cos = cos1(0.5*freq); alpha = sin/(2*q); a0 = 1/(1 + alpha); a1 = a0*-2*cos; a2 = a0*(1 - alpha); out0 = in*a2 + in1*a1 + in2 - out1*a1 - out2*a2; out0 = ((out0&abs) > 1e-11)&out0; out2 = out1; out1 = out0; in2 = in1; in1 = in; }

And then I did the freaky stuff 😈

streamin in; streamin freq; streamin q; streamout out0;

float smIntVarTemp=0.0; float in1=0; float in2=0; float out1=0; float out2=0; float abs=0; float F3P4eA038=3.4e+038; float F0P999999=0.999999; float F0P1=0.1; float F0P5=0.5; float F65536=65536; float F16384=16384; float F2=2; float F1=1; float FM2=-2; float F1eM011=1e-011;

stage0; movaps xmm0,F3P4eA038; orps xmm0,F0P999999; orps xmm0,F0P1; movaps abs,xmm0;

stage1; stage1; movaps xmm0,F0P5; mulps xmm0,freq; movaps xmm2,xmm0; // backup

// begin sine mulps xmm0,F65536; movaps smIntVarTemp,xmm1; fld smIntVarTemp[0];fistp smIntVarTemp[0];mov eax,smIntVarTemp[0];and eax,65535;shl eax,2;add eax,sine;fld [eax];fstp smIntVarTemp[0]; fld smIntVarTemp[1];fistp smIntVarTemp[1];mov eax,smIntVarTemp[1];and eax,65535;shl eax,2;add eax,sine;fld [eax];fstp smIntVarTemp[1]; fld smIntVarTemp[2];fistp smIntVarTemp[2];mov eax,smIntVarTemp[2];and eax,65535;shl eax,2;add eax,sine;fld [eax];fstp smIntVarTemp[2]; fld smIntVarTemp[3];fistp smIntVarTemp[3];mov eax,smIntVarTemp[3];and eax,65535;shl eax,2;add eax,sine;fld [eax];fstp smIntVarTemp[3]; movaps xmm0,smIntVarTemp; // end sine

movaps xmm1,q; mulps xmm1,F2; divps xmm0,xmm1;

// ->xmm0=alpha // ->xmm2=freq/2 // ->xmm1=q*2

// begin cosine mulps xmm2,F65536; addps xmm2,F16384; movaps smIntVarTemp,xmm2; fld smIntVarTemp[0];fistp smIntVarTemp[0];mov eax,smIntVarTemp[0];and eax,65535;shl eax,2;add eax,sine;fld [eax];fstp smIntVarTemp[0]; fld smIntVarTemp[1];fistp smIntVarTemp[1];mov eax,smIntVarTemp[1];and eax,65535;shl eax,2;add eax,sine;fld [eax];fstp smIntVarTemp[1]; fld smIntVarTemp[2];fistp smIntVarTemp[2];mov eax,smIntVarTemp[2];and eax,65535;shl eax,2;add eax,sine;fld [eax];fstp smIntVarTemp[2]; fld smIntVarTemp[3];fistp smIntVarTemp[3];mov eax,smIntVarTemp[3];and eax,65535;shl eax,2;add eax,sine;fld [eax];fstp smIntVarTemp[3]; movaps xmm2,smIntVarTemp; //end cosine

mulps xmm2,FM2;

// ->xmm0=alpha // ->xmm2=-2*cos // ->xmm1=q*2

addps xmm0,F1; movaps xmm1,F1; divps xmm1,xmm0; mulps xmm2,xmm1;

// ->xmm0=1+alpha // ->xmm2=a1 // ->xmm1=a0

//movaps a1,xmm2;

movaps xmm3,F2; subps xmm3,xmm0; mulps xmm1,xmm3;

// ->xmm1=a2 // ->xmm2=a1

movaps xmm0,in; mulps xmm0,xmm1; addps xmm0,in2; mulps xmm1,out2; subps xmm0,xmm1;

// ->xmm0=in*a2+in2-out2*a2 // ->xmm1=a2*out2 // ->xmm2=a1

movaps xmm1,xmm2; mulps xmm1,in1; addps xmm0,xmm1; mulps xmm2,out1; subps xmm0,xmm2;

// ->xmm0=in*a2+in2-out2*a2+in1*a1-out1*a1

movaps xmm1,xmm0;

andps xmm0,abs; cmpps xmm0,F1eM011,6; andps xmm0,xmm1; movaps out0,xmm0;

// ->xmm0 = ((out0&abs) > 1e-11)&out0;

movaps xmm0,out1; movaps out2,xmm0;

movaps xmm0,out0; movaps out1,xmm0;

movaps xmm0,in1; movaps in2,xmm0;

movaps xmm0,in; movaps in1,xmm0; stage1;

that executes 31%(62 Cycles removed from 202) faster than the original.

exonerate ·

How about an approximation for the sine and cosine:D

streamin in; streamin freq; streamin q; streamout out0;

float smIntVarTemp=0.0; float in1=0; float in2=0; float out1=0; float out2=0; float abs=0; float F3P4eA038=3.4e+038; float F0P999999=0.999999; float F0P1=0.1; float F0P5=0.5; float F65536=65536; float F16384=16384; float F2=2; float F1=1; float FM2=-2; float F1eM011=1e-011;

stage0; movaps xmm0,F3P4eA038; orps xmm0,F0P999999; orps xmm0,F0P1; movaps abs,xmm0;

stage1; stage1; movaps xmm1,F0P5; mulps xmm1,freq; movaps xmm4,xmm1; // backup

// begin sine addps xmm1, xmm1; // addps xmm1, hpi; // COS1

movaps xmm0,xmm1; // angle=angle-(angle>pi)&tpi; cmpps xmm0,pi,6; andps xmm0,tpi; subps xmm1,xmm0;

movaps xmm0,xmm1; // angle=angle+(angle<pi)&tpi; cmpps xmm0,npi,1; andps xmm0,tpi; addps xmm1,xmm0;

movaps xmm0, xmm1; // Parabolic sine approximation movaps xmm2, pi; addps xmm0, xmm0; andps xmm1, absmask; addps xmm0, xmm0; subps xmm2, xmm1; mulps xmm0, xmm2; // Result= 4*X*(1-abs(X))

movaps xmm1, xmm0; // Calibrate for extra precision andps xmm1, absmask; mulps xmm1, xmm0; subps xmm1, xmm0; mulps xmm1, P; addps xmm0, xmm1; // end sine

movaps xmm1,q; mulps xmm1,F2; divps xmm0,xmm1; movaps xmm3,xmm0;

// ->xmm0=alpha // ->xmm2=freq/2 // ->xmm1=q*2

// begin cosine movaps xmm1,xmm4; addps xmm1, xmm1; addps xmm1, hpi; // COS1

movaps xmm0,xmm1; // angle=angle-(angle>pi)&tpi; cmpps xmm0,pi,6; andps xmm0,tpi; subps xmm2,xmm0;

movaps xmm0,xmm2; // angle=angle+(angle<pi)&tpi; cmpps xmm0,npi,1; andps xmm0,tpi; addps xmm1,xmm0;

movaps xmm0, xmm1; // Parabolic sine approximation movaps xmm2, pi; addps xmm0, xmm0; andps xmm1, absmask; addps xmm0, xmm0; subps xmm2, xmm1; mulps xmm0, xmm2; // Result= 4*X*(1-abs(X))

movaps xmm1, xmm0; // Calibrate for extra precision andps xmm1, absmask; mulps xmm1, xmm0; subps xmm1, xmm0; mulps xmm1, P; addps xmm0, xmm1; //end cosine

mulps xmm0,FM2;

// ->xmm0=alpha // ->xmm2=-2*cos // ->xmm1=q*2

addps xmm3,F1; movaps xmm1,F1; divps xmm1,xmm3; mulps xmm0,xmm1; movaps xmm5,xmm0;

// ->xmm0=1+alpha // ->xmm2=a1 // ->xmm1=a0

//movaps a1,xmm2;

movaps xmm2,F2; subps xmm2,xmm3; mulps xmm1,xmm2;

// ->xmm1=a2 // ->xmm2=a1

movaps xmm0,in; mulps xmm0,xmm1; addps xmm0,in2; mulps xmm1,out2; subps xmm0,xmm1;

// ->xmm0=in*a2+in2-out2*a2 // ->xmm1=a2*out2 // ->xmm2=a1

movaps xmm1,xmm5; mulps xmm1,in1; addps xmm0,xmm1; mulps xmm2,out1; subps xmm0,xmm2;

// ->xmm0=in*a2+in2-out2*a2+in1*a1-out1*a1

movaps xmm1,xmm0;

andps xmm0,abs; cmpps xmm0,F1eM011,6; andps xmm0,xmm1; movaps out0,xmm0;

// ->xmm0 = ((out0&abs) > 1e-11)&out0;

movaps xmm0,out1; movaps out2,xmm0;

movaps xmm0,out0; movaps out1,xmm0;

movaps xmm0,in1; movaps in2,xmm0;

movaps xmm0,in; movaps in1,xmm0; stage1;

Warning I've not tested that code just copied and pasted the SSE sine from the other thread and slapped it in and did a bit a register juggling 😉

cheers 😉

Exo

Tom7777 ·

The optimizations make it sound different 🙁

fabb ·

MyCo wrote: ... abs = 3.4e38|0.999999|0.1; ...

What did you there MyCo? The | operator isn't in the manual. Is it a bitwise OR?

thx fabb

MyCo ·

yes: [old link]

MyCo ·

exonerates code doesn't work, because it overrides some registers, that are needed later.

to check that, I've put comments in it, which tell you which registers are used, an what is in there

Tom7777 ·

Well i tried both, they both sounded different 😕

MyCo ·

Can you give an example? My code is a 1:1 translation, so it shouldn't sound different.

fabb ·

infuzion wrote: fabb wrote: Is there a way to calculate a square root?

3) You mean absolute value? More ASM: streamin i;streamout o; int ABSMASK=2147483647; movaps xmm0,i; andps xmm0,ABSMASK; movaps o,xmm0; Code is o=i&absmask; I think.

Masking with 2147483647 is problematic, I found out: http://babbage.cs.qc.edu/IEEE-754/Decimal.html When you enter the number here, you'll see that the exponent is 10011101. So when you've got a number that has got a 1 on any of the 0 places of the exponent of 2147483647 in its floating point representation, masking it will output a wrong number. So be careful. As the exponent 11111111 is reserved, you can't mask with just one number to get the right absolute value. Now I know what MyCo did with "abs = 3.4e38|0.999999|0.1". When you enter these numbers on the website above, you'll see that ORed together they output just 1s except to the first (sign) place. If you want to be cool and build your own abs mask, you can try your luck here: http://babbage.cs.qc.edu/IEEE-754/32bit.html As stated above, you need at least two numbers. So eg. abs=1.7014118346046923e+38|2.3509885615147286e-38 The output of the absmask should always give 7FFFFFFF (everything except the sign bit). MyCo's version is of course better readable 😉 EDIT: And Synthmaker truncates the floats after some digits, so the above example is translated into a slightly wrong absmask!! Go with MyCo's.

TomC ·

Tom7777 wrote: Thanks, This is turning out to be a great thread, any chance someones done the Interpolated Delay 😉 Use that one quite a bit 😀

Just uploaded it to the Wiki: Optimized Interpolated Delay

I enhanced the original Interpolated Delay a bit (the delay time is sample rate independent now), so read the included documentation and double check if that's okay for your project.

Cheers,

Tom

infuzion ·

fabb wrote: infuzion wrote: streamin i;streamout o; int ABSMASK=2147483647; movaps xmm0,i; andps xmm0,ABSMASK; movaps o,xmm0;

Masking with 2147483647 is problematic, I found out: http://babbage.cs.qc.edu/IEEE-754/Decimal.html When you enter the number here, you'll see that the exponent is 10011101. So when you've got a number that has got a 1 on any of the 0 places of the exponent of 2147483647 in its floating point representation, masking it will output a wrong number. So be careful... EDIT: And Synthmaker truncates the floats after some digits... Go with MyCo's.

I wonder if the ABSMASK above takes advantage of SM's rounding; because it seems all output of the above code equals SM's Float ABS, at least to SM's Float Equals. But I will keep your warning in mind, & changed my abs() suggestion.

& yes, I think the bit-flag for rounding is enabled in SM.

stefan ·

Tom777: Regarding optimizing your allpass filter, do you need to calculate the coefficients on a per-sample basis? Because that's probably what eats up most of the CPU cycles.

fabb ·

infuzion wrote: & yes, I think the bit-flag for rounding is enabled in SM.

I don't think so. Otherwise 2147483647 wouldn't work at all. Type it in at http://babbage.cs.qc.edu/IEEE-754/Decimal.html and you'll see, rounded it gives just zeros for the significand. (Maybe they do round differently, could be. But I think the rounding is a part from the IEEE standardization). BTW, if you want to get either +1 or -1 depending on the sign, you can mask like this: (x&80000000)|3F800000.

Tom7777 ·

Not sure stefan, im emailing you the project so you can take a look 🙂

infuzion ·

fabb wrote: BTW, if you want to get either +1 or -1 depending on the sign, you can mask like this: (x&80000000)|3F800000.

Sambean taught me this: streamin i; streamout oABS;streamout oNEG; int ABSMASK=2147483647;int NEGMASK=-2147483648; movaps xmm0,i;movaps xmm1,xmm0; movaps xmm2,ABSMASK; //speeds up Core+ andps xmm0,xmm2;orps xmm1,NEGMASK; movaps oABS,xmm0;movaps oNEG,xmm1; Is that what you're saying?

What is the fastest way to flip a sign please? I just x*-1, but that uses a fixed port: a mask would be better.

fabb ·

Wait! you're talking about INTegers, I'm talking about FLOATs! With integers the absmask 2147483647 works fine, not with floats! And no, with (x&80000000)|3F800000 you're also working with floats. with x&80000000 you strip out the sign bit and with |3F800000 you set it to 1 (+/- depending on the sign bit you ored together). It's a sign function. You can also OR every other positive float with it to get this value +/-ed.

With your code, the ABS and NEG value are both off 1 if the original value is negative/positive. But when speed matters this probably won't be a problem. Do you need inverting with integers or floats?

infuzion ·

fabb wrote: Wait! you're talking about INTegers, I'm talking about FLOATs! With integers the absmask 2147483647 works fine, not with floats! And no, with (x&80000000)|3F800000 you're also working with floats. with x&80000000 you strip out the sign bit and with |3F800000 you set it to 1 (+/- depending on the sign bit you ored together). It's a sign function. You can also OR every other positive float with it to get this value +/-ed.

With your code, the ABS and NEG value are both off 1 if the original value is negative/positive. But when speed matters this probably won't be a problem. Do you need inverting with integers or floats?

First of all, in SSE, you can mix floats with ints freely; seems all that matters is bit-width, & I think that can be messed with as well. This works fine: streamin i;streamout o; int ABSMASK=2147483647; movaps xmm0,i; andps xmm0,ABSMASK; movaps o,xmm0; If you notice, all SSE commands are for 4x32bit floats, but ABSMASK is declared as an int. Still no problem. Same with MyCo's delay ASM. For the most part, ultimately I'm worried about 32bit SSE floats, but like in MyCo's dynamic arrays, ints may be used also.

This Code doesn't work... are these hex numbers please? streamin i;streamout o; o=(i&80000000)|3F800000;

MyCo ·

infuzion wrote: First of all, in SSE, you can mix floats with ints freely; seems all that matters is bit-width, & I think that can be messed with as well.

Are you sure? I've noticed, that you can not compare (cmpps) an int with a float. One other thing that I noticed with cmpps is, if you try to compare 2 ints with that, it works, but it takes a realy long time (170 Cycles in my case)

fabb ·

The code component doesn't provide ints, it works (till now) only with floats, so I didn't even consider using integers.

That's why I overlooked that "int ABSMASK=2147483647;" uses an int in asm as well, my fault. But as I'm not using asm yet this doesn't help me out. But I'm starting to have fun looking at the asm code... Ohoh, transformation begins.... 😉

Yes, these are hex numbers (should have written an 0x before it).

exonerate ·

I spent last night doing a bit of optimizing of the AHDSR, got it down form about 218 cycles to about 112 😀 ==edit=== is about 122 now had to roll back to a previous version because of problems with clicks==edit==

Moved all the stuff inside the first hop into green math increased the hop to 32 and did some register optimizing, i'm happy with the result but I'm sure it can be reduced even more.

Wiki entry

If anyone can see any more reductions in the ASM please post it here!

Cheers 😉

Exo

Ps: I had it using less so i think it can be optimized more this was the last version to work correctly![/code]

MyCo ·

I've put the variable env in register xmm2 and used this in the code before hop, that saves 3 Cycles on my system. Not much, but you use all registers, so it's hard to do more 😈

exonerate ·

MyCo wrote: I've put the variable env in register xmm2 and used this in the code before hop, that saves 3 Cycles on my system. Not much, but you use all registers, so it's hard to do more 😈

Thanks, yeah i know I'm making full use of the registers 🙂 , I did have this about 10 cycles lower, it's possible to unuse xmm3 which is currently in use further down the code and then use that for stage, I did that before but must have broke something, I'll probally try that again soon.

Cheers 😉

Exo

TomC ·

exonerate wrote: I spent last night doing a bit of optimizing of the AHDSR, got it down form about 218 cycles to about 112 😀

Hey, that's about twice as fast

exonerate wrote: ==edit=== is about 122 now had to roll back to a previous version because of problems with clicks==edit==

Ps: I had it using less so i think it can be optimized more this was the last version to work correctly!

Don't tell me. I've got a nice version of the Interpolated Delay, and it runs perfectly (means no matter what you do, the original Delay's signal minus the optimized Delay's signal is ALWAYS 0) within SynthMaker, but absolutely fucks up as exe or VST.

I hope I'll find some time before my vacation to debug this.

Cheers.

Tom

fabb ·

bah, coldness...

it was just half a joke, there really is (was?) a patent for xor...

aliasant ·

Hmm. Not so cold here. In Stockholm we have had the warmest winter since they started measuring, about 250 years ago.

fabb ·

really? it wasn't that cold, but some days in february kicked my ass... brrrrrr. and today it snowed (near vienna). just a little bit, but snow. if it was after me, it always would be summer. with some 20°C days in it of course...

fabb ·

btw. without xor it's a bit more complicated, something like "(NOT floatvalue AND 0x80000000) OR (floatvalue AND 0x7FFFFFFF)"

Acrobat ·

aliasant wrote: Hmm. Not so cold here. In Stockholm we have had the warmest winter since they started measuring, about 250 years ago.

Global warming.. 😮 😮 😮

RuleT ·

Sorry, I haven't read all pages, but what if we'll use something like asm snippet shown below for abs() realisation?

streamin in; streamout out;

mov eax, in[0]; and eax, 2147483647; mov out[0], eax; mov eax, in[1]; and eax, 2147483647; mov out[1], eax; mov eax, in[2]; and eax, 2147483647; mov out[2], eax; mov eax, in[3]; and eax, 2147483647; mov out[3], eax;

It should be precise enough & SSE1 safe, I think. 😊

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.