Old 01-05-2020, 11:00 AM   #1
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default Anyone who has PluginDoctor?

Hi

If anyone here has Plugin Doctor and would like to help out?

This JS-limiter/fatterner distorts a bit. However Id like to know how much of that is digital distortion versus harmonic distortion?

Theres two versions below. One original + one where Ive tried a way to "fix" aliasing. It seems to work a bit but Ive only checked with a regular spectogram. So a check of that would be awesome.

Many thanks /danerius

=====================================

desc:Loud Sinner Danerius

slider1:2.2<1.5,3,0.01>Keep between 1.8 <-> 2.2
slider2:1<0.5,1.5,0.01> Gain Staging
slider3:1<0,2,0.01>Master Volume

@init
bpos=0;

@slider
//factor = slider1;

@sample

tempL = spl0 * slider2;
tempR = spl1 * slider2;

tempL = sin ($pi * tempL / slider1);
tempR = sin ($pi * tempR / slider1);

spl0 = tempL * slider3;
spl1 = tempR * slider3;

===================================

desc:Anti-Alias Sinner Danerius

//slider1:0<0,100,1>Analog (%)
//slider2:0<0,100,1>Glue (%)
slider3:2.6<1.5,3,0.01>Character (%)
slider4:1<0.5,1.5,0.01>Drive (%)
slider5:-0.3<-120,0,0.1>Max Vol (dB)

@init
bpos=0;

@slider
threshold = 2 ^ (slider5/6);

@sample

//Limiter
//Straight processing
tempL1 = (spl0 * slider4);
tempR1 = (spl1 * slider4);

tempL1 = sin ($pi * tempL1 / slider3);
tempR1 = sin ($pi * tempR1 / slider3);

//Mirror processing
tempL2 = (spl0 * slider4) * -1;
tempR2 = (spl1 * slider4) * -1;

tempL2 = sin ($pi * tempL2 / slider3);
tempR2 = sin ($pi * tempR2 / slider3);

//Summing of Straight + Mirror
spl0 = (tempL + (tempL2 * -1)) * threshold;
spl1 = (tempR + (tempR2 * -1)) * threshold;
//
danerius is offline   Reply With Quote
Old 01-05-2020, 05:50 PM   #2
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 876
Default

TempL and TempR aren’t defined in the second script, so it’s basically just creating an inverted version of the first script, no harmonic difference. There is nothing in the second script that would reduce aliasing. If you look at Loser/saturation you’ll see a method of implementing sin() distortion that adjusts the amount of curvature, use that as a reference.

Note that once x hits +/- slider4/(2*slider3) it will cause foldover distortion, probably what you mean by “digital”. Loser/saturation prevents this by limiting the input with min/max.

Probably the simplest method to antialias would be oversampling, you should be able to find code examples in my post history, there are a few jsfx oversampling libraries and methods that have been posted here.

Desmos Calculator is a good online calculator, I strongly suggest graphing your functions out to help see what the functions are doing, eg in Loser/saturation.
SaulT is offline   Reply With Quote
Old 01-06-2020, 12:18 PM   #3
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Quote:
Originally Posted by SaulT View Post
TempL and TempR aren’t defined in the second script, so it’s basically just creating an inverted version of the first script, no harmonic difference. There is nothing in the second script that would reduce aliasing. If you look at Loser/saturation you’ll see a method of implementing sin() distortion that adjusts the amount of curvature, use that as a reference.

Note that once x hits +/- slider4/(2*slider3) it will cause foldover distortion, probably what you mean by “digital”. Loser/saturation prevents this by limiting the input with min/max.

Probably the simplest method to antialias would be oversampling, you should be able to find code examples in my post history, there are a few jsfx oversampling libraries and methods that have been posted here.

Desmos Calculator is a good online calculator, I strongly suggest graphing your functions out to help see what the functions are doing, eg in Loser/saturation.
Hi Saul

Its supposed to foldover, thats the point of the math formula But its supposed to produce harmonic distortion. Thats what I wanted to check with Plugin Doctor.
https://www.desmos.com/calculator/p9vhmx065j

The idea with doing a regular plus a mirror image math operation is the same as with XLR-Cables and humbuckers. Two things out of phase gets the same distortion added and then cancelled out with a 180 phase reversal. Wether that works in this domain or not Ive yet to find out. The idea is super simple... Someone must have tried it before me...

Ive made one simple distortion with Tales oversample.jsfx. I'll have a go with this one as well

Many thanks /danerius
danerius is offline   Reply With Quote
Old 01-06-2020, 04:16 PM   #4
ErBird
Human being with feelings
 
Join Date: Jan 2017
Location: Los Angeles
Posts: 1,161
Default

Quote:
Originally Posted by danerius View Post
The idea with doing a regular plus a mirror image math operation is the same as with XLR-Cables and humbuckers. Two things out of phase gets the same distortion added and then cancelled out with a 180 phase reversal.
I understand the logic, but this won't work. XLR cables and humbuckers work because noise is being added to the signal. Aliasing is a entirely different from noise. Plus sin(x) is an odd function, so sin(x) = -sin(-x). The "mirroring" code accomplishes nothing but doubling the signal level.

Quote:
Originally Posted by danerius View Post
This JS-limiter/fatterner distorts a bit.
It distorts much more than a bit. I would hardly refer to this as a limiter/fattener. It's a sine distortion, about as nasty as distortions come.

Sine Distortion Foldover:
https://www.desmos.com/calculator/mvzdurbnoy

Quote:
Originally Posted by danerius View Post
However Id like to know how much of that is digital distortion versus harmonic distortion?
You're trying to discern how much of the distortion is harmonic vs. aliasing? I don't think PluginDoctor is going to do anything for you that a sine generator and Voxengo Span cannot. Reaper comes with "tone generator" and Span is free. MOscilloscope is also useful, but none of these are going to help you pick the aliasing out of the signal.

Quote:
Originally Posted by danerius View Post
slider3:2.6<1.5,3,0.01>Character (%)
slider4:1<0.5,1.5,0.01>Drive (%)
...
tempL1 = (spl0 * slider4);
tempR1 = (spl1 * slider4);
...
tempL1 = sin ($pi * tempL1 / slider3);
tempR1 = sin ($pi * tempR1 / slider3);
Why do you have two parameters that affect input gain? Turning up "character" lowers input gain, this seems counter-intuitive and not good.
ErBird is offline   Reply With Quote
Old 01-07-2020, 09:28 AM   #5
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Quote:
Originally Posted by ErBird View Post
I understand the logic, but this won't work. XLR cables and humbuckers work because noise is being added to the signal. Aliasing is a entirely different from noise. Plus sin(x) is an odd function, so sin(x) = -sin(-x). The "mirroring" code accomplishes nothing but doubling the signal level.

You're trying to discern how much of the distortion is harmonic vs. aliasing? I don't think PluginDoctor is going to do anything for you that a sine generator and Voxengo Span cannot. Reaper comes with "tone generator" and Span is free. MOscilloscope is also useful, but none of these are going to help you pick the aliasing out of the signal.

Why do you have two parameters that affect input gain? Turning up "character" lowers input gain, this seems counter-intuitive and not good.
Hi

Seems the humbucker-idea was too good to be true. No worries. Ideas are cheap

Ive done the tone generator + spectogram bit. It was inconclusive. Hence me asking about Plugin Doctor.

The "character" changes the slope of the waveshaper. Turning it up reduces the overall loudness but its not really a gain slider as such. Yes its counter intuitive. And yes its a prototype.

Best regards /danerius

PS. The waveshaper in Desmos. "b" changes the shape ie. the "character" slider. DS
https://www.desmos.com/calculator/8xixpgfklc
danerius is offline   Reply With Quote
Old 01-07-2020, 12:31 PM   #6
ErBird
Human being with feelings
 
Join Date: Jan 2017
Location: Los Angeles
Posts: 1,161
Default

Quote:
Originally Posted by danerius View Post
The "character" changes the slope of the waveshaper. Turning it up reduces the overall loudness but its not really a gain slider as such.
...
PS. The waveshaper in Desmos. "b" changes the shape ie. the "character" slider.
https://www.desmos.com/calculator/8xixpgfklc
It may appear that way, but it's misleading. The reality is multiplying the argument of sin(x) by a constant is equivalent to changing the input gain, it's not really changing the waveshaper shape or the overall loudness. If you split the equation into parts this becomes apparent.

Input x
https://www.desmos.com/calculator/ymfxlpr83o

Input sin(x)
https://www.desmos.com/calculator/fzpmwdcnrw

ErBird is offline   Reply With Quote
Old 01-07-2020, 06:12 PM   #7
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 876
Default

I really recommend the way Loser/Saturation does it. Mathematically it looks like this (albeit I’m using a cubic polynomial instead of the sin function)...

M(x) = a*x - a*a*a*x*x*x/b
N(x) = a - a*a*a/b

Out = m(x)/n(x)

Where a is 0.01 to 1, amount of saturation
And b is 3 to perhaps 6, lower numbers mean more max nonlinearity (this is “character”)

Note that n(x) can be precomputed. Loser/saturation does this (I think it is “bar” in that code).

Check my post history for stuff about cubic polynomials like this, you can think of it as a truncated Taylor polynomial, with a adjusting between the approximation for sine and the approximation for hyperbolic tangent.
SaulT is offline   Reply With Quote
Old 01-09-2020, 07:13 AM   #8
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Thanks ErBird and SaulT

I understand what youre saying but not the point of it. What am I missing? Does it make for better code to use polynomials? Is the math more accurate? Please elaborate... Im here to learn

The formula is doing what I am expecting it to do. Its a waveshaper that fold over on itself. Its meant to do that. Its meant to be producing harmonic distortion. Im looking to minimize the aliasing.

Heres three screen shots of an oscilloscope. One with overshooting. One thats squaring the sine. And one thats lowering the peak. Just as expected

Much appreciated /danerius
Attached Images
File Type: png FoldOver.png (43.2 KB, 187 views)
File Type: png Square.png (40.8 KB, 169 views)
File Type: png Sine.png (40.9 KB, 175 views)
danerius is offline   Reply With Quote
Old 01-11-2020, 10:04 PM   #9
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 876
Default

Okay, so I'll phrase this a different way.

Code:
slider3:2.6<1.5,3,0.01>Character (%)
slider4:1<0.5,1.5,0.01>Drive (%)
...
tempL1 = (spl0 * slider4);
...
tempL1 = sin ($pi * tempL1 / slider3);
is the same as

Code:
tempL1 = sin($pi * tempL1 * spl0 * slider4 / slider3 );
That means that all you're doing is multiplying your input by a constant. Look at ErBird's first Desmos link, this is the equivalent to what you are doing, except using a single number instead of a ratio between two numbers. You could replace slider3 and slider4 with one variable, as below, and it would be precisely equivalent...

Code:
slider5:1<0.17,6,0.01>Scaling constant
...
tempL1 = sin ($pi * spl0 * slider5);
This is what ErBird's first Desmos graph shows. You need to graph this out for yourself and understand it. Slider3 and slider4 don't represent anything meaningful on their own, their ratio forms a constant. Not useful at best and misleading and confusing at worst.

I thought it would be helpful if I shared a useful variation of the Loser/Saturation algorithm instead of repeating it almost verbatim. I'm very fond of my variation, because it is more adaptable than sin()... it also doesn't do multiple levels of foldover distortion the way sin() does, but to me that's a feature and not a bug...

...Okay, this is a graph of the Loser/Saturation function. The reason it is a good algorithm is that the slider does something meaningful - it doesn't just multiply the input of sin() by a constant, it changes how the function operates, making it more nonlinear as you push the slider along. Slider3/slider4 simply do not do this. You cannot get a linear response out of slider3/slider4, you can only get a sine curve.

https://www.desmos.com/calculator/ahr7b4ir8s

...

I guess I'm assuming that you want a function that can go from "clean" to "dirty" in some way, I'm trying to show you that this is accomplished by using a waveshaping function that goes from linear (y=x) to very curved (y=sin(x)).

I don't know if I have any clever techniques for antialiasing deliberate foldover distortion beyond just oversampling... I have never liked the sound of it so never saw the point.
SaulT is offline   Reply With Quote
Old 01-14-2020, 09:30 AM   #10
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Hi SaulT and ErBird

First of all. Big thanks for taking the time and explaining all this. Im not a coder and my math skills are limited. Im gonna sink my teeth into all your suggestions and see if I can make it work in jsfx.

I didnt intend for it go from smooth to distorted. This was going to be one-trick clipper/limiter with an edgy sharp character. But your suggestions opens up a much broader use. Thanks

Ive talked to Chris from AirWindows regarding aliasing. He recommends raising the internal bit rate for distortion plugs. Oversampling doesnt help that much in his opinion. Havent tried it so cant confirm.

Thanks + best regards /danerius
danerius is offline   Reply With Quote
Old 01-16-2020, 04:47 PM   #11
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 876
Default

Ok, so I’ve got a crazy idea for you. Try this...

h(x)=x + x^3/6
f(x)=sin(h(a*x)/a)

When a is low then the output is pretty linear, although it will still fold over eventually. As a goes up it becomes more nonlinear and folds over more quickly. Might work for you.

Also, Reaper has internal 64 bit depth, so that part is fine.
SaulT is offline   Reply With Quote
Old 01-16-2020, 07:39 PM   #12
ashcat_lt
Human being with feelings
 
Join Date: Dec 2012
Posts: 7,295
Default

The way that the sin function folds over is not particularly harmonic in nature. It can sort of look like octave doubling with certain pure waveforms which “overshoot” by a specific amount, but the period of the resulting wave is more dependent on the amplitude of the input signal than on the frequency. I’ve messed with it quite a bit and any time it’s allowed to fold over it really just gets ugly and unmusical really fast.

If you want to change the character of the distortion, you could try changing the symmetry of the clipping function either by applying a DC offset going in (and stripping it back out on the other side) or by processing both sides differently.

One of the things that I noticed with Loser saturation et al is that it tends to inflate the average/overall level. When it’s actually all the way to the sin function, for signals near zero, there is gain of about half pi. If you wanted “unity” in the more or less linear range, you’d have to divide the output by half of pi, and then your maximum peaks end up around 2/pi. I suppose that makes some sense if you’re using it as a maximizing final output kind of thing, but I’m not sure it’s always understood or expected with sin implementations.
ashcat_lt is offline   Reply With Quote
Old 01-25-2020, 09:49 AM   #13
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Quote:
Originally Posted by SaulT View Post
Ok, so I’ve got a crazy idea for you. Try this...

h(x)=x + x^3/6
f(x)=sin(h(a*x)/a)

When a is low then the output is pretty linear, although it will still fold over eventually. As a goes up it becomes more nonlinear and folds over more quickly. Might work for you.

Also, Reaper has internal 64 bit depth, so that part is fine.
Hi SaulT + thanks. Been quite busy lately but finally got a chance to look into your idea

I plugged it into Desmos and got a curve that looks like it would emphasize the peaks a bit? Yes... No?
https://www.desmos.com/calculator/qgbyze02ky

Pus Ive been checking other bits of code and the concept of having the math formula as a function in @init seems like a really neat idea (remember Im not a coder And then upsampling in the @sample section.

At some point Id like to ahve the different formulas posted here selectable in some fashion. Havent gotten around to learn how to do that yet. Maybe it cant even be done in the @init section

Best regards /danerius
danerius is offline   Reply With Quote
Old 01-25-2020, 09:56 AM   #14
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Quote:
Originally Posted by ashcat_lt View Post
The way that the sin function folds over is not particularly harmonic in nature. It can sort of look like octave doubling with certain pure waveforms which “overshoot” by a specific amount, but the period of the resulting wave is more dependent on the amplitude of the input signal than on the frequency. I’ve messed with it quite a bit and any time it’s allowed to fold over it really just gets ugly and unmusical really fast.

If you want to change the character of the distortion, you could try changing the symmetry of the clipping function either by applying a DC offset going in (and stripping it back out on the other side) or by processing both sides differently.

One of the things that I noticed with Loser saturation et al is that it tends to inflate the average/overall level. When it’s actually all the way to the sin function, for signals near zero, there is gain of about half pi. If you wanted “unity” in the more or less linear range, you’d have to divide the output by half of pi, and then your maximum peaks end up around 2/pi. I suppose that makes some sense if you’re using it as a maximizing final output kind of thing, but I’m not sure it’s always understood or expected with sin implementations.
Hi + thanks for replying

Long story short. Its supposed to fold over itself. Its a clipper with a somewhat limited use. A one-trick-pony. If you need a drum bus (for example) that emphasizes transients but still keeps them below 0 dB. This is your clipper

Given that I can implement the suggestion provided by ErBird + SaulT? It might turn out a bit more flexible in its use.

Best regards /danerius

Last edited by danerius; 01-25-2020 at 10:01 AM.
danerius is offline   Reply With Quote
Old 01-26-2020, 04:24 PM   #15
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 876
Default

In Desmos you have to literally write out

h(x)=x-x*x*x/6

H should not be a slider, it needs to be that function to get the effect I was suggesting.

Multiple formulas can be used to switch between distortion algos, it’s just a conditional.

switch == 1 ? ( out = dist1(in); ) : ( out = dist2(in); );

Is one way to do it.
SaulT is offline   Reply With Quote
Old 01-31-2020, 09:57 AM   #16
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Ive gotten stuck on getting a function working. The code compiles but theres no function. And all the C tutuorials Ive checked isnt helping much. What am I missing?

Thanks /danerius

-------------------------------------
desc:new effect

slider1:1<0,2,0.01>Multiplication


@init

function multi(x)
(
x = slider1;
);


@slider
//something=slider1*srate;

@block
//blah+=samplesblock;

@sample
spl0 = spl0 * multi;
spl1 = spl1 * slider1;
danerius is offline   Reply With Quote
Old 01-31-2020, 10:10 AM   #17
ashcat_lt
Human being with feelings
 
Join Date: Dec 2012
Posts: 7,295
Default

You have to pass an argument to the function.
ashcat_lt is offline   Reply With Quote
Old 01-31-2020, 10:59 AM   #18
ErBird
Human being with feelings
 
Join Date: Jan 2017
Location: Los Angeles
Posts: 1,161
Default

This is what SaulT meant by using a function. A mathematical function for both h and f.
https://www.desmos.com/calculator/kit2qsm00g

Quote:
Originally Posted by danerius View Post
Ive gotten stuck on getting a function working. The code compiles but theres no function. And all the C tutuorials Ive checked isnt helping much. What am I missing?

Thanks /danerius
Are you just trying to learn how to use functions in programming? You want a function that multiplies the input by a slider?

In this case look at the function as output = function(input1,input2) where the function just multiplies input1 and input2 and returns the product as the output. You can enter a sample as input1 and the slider as input2.

Super easy:
Code:
desc:new effect

slider1:1<0,2,0.01>Multiplication

@init

  function multi(x,slider)
  (
    x*slider;
  );

@sample

  spl0 = multi(spl0,slider1);
  spl1 = multi(spl1,slider1);
ErBird is offline   Reply With Quote
Old 01-31-2020, 11:37 AM   #19
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Quote:
Originally Posted by ErBird View Post
T
Are you just trying to learn how to use functions in programming? You want a function that multiplies the input by a slider?

In this case look at the function as output = function(input1,input2) where the function just multiplies input1 and input2 and returns the product as the output. You can enter a sample as input1 and the slider as input2.

Super easy:
Awesome ErBird. Thanks a million. I was just checking some youtube vids on Functions and Arguments like AshCat mentioned. This is a great foundation to work from.

I am learning to code in general, not just functions so any help when Im stuck is appreciated

thanks /danerius
danerius is offline   Reply With Quote
Old 01-31-2020, 11:16 PM   #20
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 876
Default

I did a post recently on a delay plugin, where I broke down what my thought process was at each portion of the code, that might be useful to you. JS is unusual in a few ways... it only has one array, only one value can be returned from a function and it's always the value of the last expression calculated by that function, etc.

Here is one way to code it. Perhaps we set a in the @slider block.

Code:
function h(x) ( x + x*x*x/6; );
function f(x) ( sin($pi * h(x * a)/a ); ); // a is a global variable
Or maybe a is changing dynamically, so we include it in the function call.

Code:
function f(x,a) ( sin($pi * h(x * a)/a ); );
Or maybe we have different saturation functions and we want them each to have a different a, so we've used the function to create objects, like such

Code:
function f(x)
 instance(a)
(
  sin($pi * h(x * a)/a );
);

// ...maybe a is dynamically set by the RMS level of the incoming signal?
// the code snippet might look a little like this

@sample
dist0.a = 1 + det0.RMS(spl0);
spl0 = dist0.f(spl0);

dist1.a = 1 + det1.RMS(spl1);
spl1 = dist1.f(spl1);
With a wider RMS window, in perhaps the 100-400 ms range, that might actually make for the beginnings of an interesting plugin. Or maybe a higher number than 1 (or lower, actually, a range from 0.1 to 5 is pretty good). Or put a multiplier on that RMS value to make it even more dynamic.

Actually, I would probably want to integrate that into the plugin itself. Could do it like this

Code:
function f(x)
 instance(det,off,mult,a)
(
  a = off + mult * this.det.RMS(x);
  sin($pi * h(x * a)/a );
);

function set_f(offset,multiplier,ms)
 instance(off,mult,det)
(
  this.off = offset;
  this.mult = multiplier;
  this.det.RMS_set(ms);
);


@slider

dist0.set_f(slider5,slider6,slider7);
See that det there? this.det.RMS(x) is pretty cool, you can have layers like this. Make sure to check the debug window so you see what those variables look like.

...

So this actually got me interested enough that I threw a plugin together. I have to admit, the sound is not bad. I am pleasantly surprised. It definitely has a thickening feel to it. If you are really interested in it I'll share, but I think you'd probably get more out of it if you built it yourself first. The key for me was that it needs to be blended in to the dry signal, and I definitely got some utility out of modifying offset and multiplier... it's a little harsh, and I think it would benefit from some oversampling or other filtering...
SaulT is offline   Reply With Quote
Old 02-04-2020, 03:12 PM   #21
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Quote:
Originally Posted by SaulT View Post
So this actually got me interested enough that I threw a plugin together. I have to admit, the sound is not bad. I am pleasantly surprised. It definitely has a thickening feel to it. If you are really interested in it I'll share, but I think you'd probably get more out of it if you built it yourself first. The key for me was that it needs to be blended in to the dry signal, and I definitely got some utility out of modifying offset and multiplier... it's a little harsh, and I think it would benefit from some oversampling or other filtering...
This is super cool of you SaulT

Ive been staring a t the code for a couple of days now to get my head around it. Youre right in me building it myself. I'll learn way more that way. Ive also been browsing the delay tutorial.

I'll post some code when I have some

Thanks /danerius
danerius is offline   Reply With Quote
Old 02-07-2020, 01:14 AM   #22
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Hi

So Ive managed to get my Sinner formula to work in a function and below is the code.

Now my question is? Is this a good way to do this? Is there en simpler way with less code? I havent got to adding functions yet but Ive commented out what I started writing.

Have a look and let mw know what you think. Thanks + best regards /danerius

//Edit: How do you grey-out a code section on this forum?
----------------------------------------------------------------------------------

desc:Function Test Sinner

slider1:2.2<1.5,3,0.01>Curve
//slider2:-0.3<-120,0,0.1>Max Level dB


@init

function sinner (sin,pi,spl,slider)
(
sin ($pi * spl / slider);
);

// function threshold ()

// (
// ;
// )

@slider
threshold = 2 ^ (slider2/6);

@sample

spl0 = sinner(sin, $pi, spl0, slider1);
spl1 = sinner(sin, $pi, spl1, slider1);
danerius is offline   Reply With Quote
Old 02-10-2020, 04:03 AM   #23
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 876
Default

https://en.scratch-wiki.info/wiki/BBCode#Code

As far as the code...

Okay, so some background information. JS handles variables almost exactly the same way that Javascript does, if that helps at all, in that by default variables are global unless they are specifically a part of an object. For example:

Code:
a = 6;        // this is available everywhere

foo.a = 8;    // this is available everywhere as foo.a

function seta(x)
 instance(a)
(
  a = 2*x;
);

bar.seta(5);  // this is bar.a and the value is 10

function setav2(x) ( this.a = 3*x; );

bar.setav2(5); // now bar.a is 15

function setav3(x) ( a = 4*x; );

bar.setav3(5); // bar.a is unaffected, and global value as is now 20!
Do you see how setav3() doesn't declare a as an instance variable and doesn't create it by using a this, and so JS assumes that a refers to the global variable a?

okay, let's look at the function

Code:
function sinner (sin,pi,spl,slider)
(
sin ($pi * spl / slider);
);
first off, you don't need the variable sin, sin() is a native method. Pi is also not needed, it's a native constant $pi, as you have in the function. Spl is valid, and slider is technically fine except that as I've tried to point out above it's not my preferred way to approach this, it's a scaling constant but whatever.

So if I was to rewrite this I would do so like this, you were very close:

Code:
function sinner(spl,slider) ( sin($pi * spl / slider; );
Hopefully that makes sense. I hope you have a chance to try out my suggested alternative function, I think you would find it interesting.
SaulT is offline   Reply With Quote
Old 02-12-2020, 04:39 PM   #24
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Thanks SaulT. This is again... awesome

So I got this one to work. Im guessing that if the text turns yellow, that means theres already a native method for it?

Code:
desc:Function Test Sinner

slider1:2.2<1.5,3,0.01>Curve
//slider2:-0.3<-120,0,0.1>Max Level dB

@init

function sinner(spl,slider) 
  ( 
    sin ( $pi * spl / slider); 
  );
  
@slider
//threshold = 2 ^ (slider2/6);

@sample

  spl0 = sinner(spl0, slider1);
  spl1 = sinner(spl1, slider1);
Now... regarding the other bits... Lets take one section at a time. I get that "a" is a variable and is equal to 6. But is "foo.a" a completely new variable or foo plus the first variable? I just googled instance and its an object right?
Code:
a = 6;        // this is available everywhere

foo.a = 8;    // this is available everywhere as foo.a

function seta(x)
instance(a)
(
 a = 2*x;
);
Best regards /danerius
danerius is offline   Reply With Quote
Old 02-12-2020, 10:05 PM   #25
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 876
Default

Quote:
Now... regarding the other bits... Lets take one section at a time. I get that "a" is a variable and is equal to 6. But is "foo.a" a completely new variable or foo plus the first variable? I just googled instance and its an object right?
Yes! JS is similar to Javascript in that you can create objects. In JS it's super easy, literally all you need to do is type "foo.bar" and JS creates the object foo that has a variable bar. This is where the idea of scope comes in, in that "a" and "foo.a" are two different variables. They're both "a", but one of them belongs to foo and must be referenced either by "foo.a" or in certain ways inside the function.

Code:
a = 6;

foo.a = 8;

// if a function 

function changemyA(x)
 instance(a)
(
  a = x;
);

function changemyA2(x)
(
  this.a = x;
);

foo.changemyA(2);
foo.changemyA2(2); // these two functions do exactly the same thing

// see something missing in the following function?

function changemyA3(x)
(
  a = x;
);

foo.changemyA3(2);

// since we didn't use a "this" or an instance() or local() call in the function
// here the function modifies the global "a" and not "foo.a"!
I'm talking a lot about objects because objects mean efficiency. For example, imagine that I'm coding a filter like the following but I'm doing it for four channels. I will show both approaches:

Code:
function twolp(x)
 instance(lp0,lp1,coeff)
(
  lp0 += coeff * (x - lp0);
  lp1 += coeff * (lp0 - lp1);
);

spl0 = ch0.twolp(spl0);
spl1 = ch1.twolp(spl1);
spl2 = ch2.twolp(spl2);
spl3 = ch3.twolp(spl3);
vs

Code:
lp00 += coeff * (spl0 - lp00);
lp01 += coeff * (lp00 - lp01);
lp10 += coeff * (spl1 - lp10);
lp11 += coeff * (lp10 - lp11);
lp20 += coeff * (spl2 - lp20);
lp21 += coeff * (lp20 - lp21);
lp30 += coeff * (spl3 - lp30);
lp31 += coeff * (lp30 - lp31);
The first example took a little effort to set up, but implementation is super simple! We could easily add a dozen more effects with a minimum of thought. Compare the second example - if we want more then we have to come up with new variable names, and all of those variables are global, which means that if we forget we're using lp30 here and use it somewhere else we are in trouble. By creating objects we keep those variables out of global space and reduce the chance that we'll accidentally overwrite them. It also means that we could use a different coefficient on ch2 than ch3, again with a minimum of effort. If we wanted to change the filter, then we modify the code once instead of four separate times!

Flexibility, scalability, protection... these are concepts of object oriented code that are implemented to a small degree in JS (and very similarly in Javascript).

So yeah, we use functions and objects together to do cool stuff. If I have not already done so, let me recommend taking a look at Tale's code, I found it very clear and easy to read. I think if you search for his mono_synth you should be able to find his pack of plugins and libraries etc.
SaulT is offline   Reply With Quote
Old 02-17-2020, 04:01 PM   #26
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Quote:
Originally Posted by SaulT View Post

So yeah, we use functions and objects together to do cool stuff. If I have not already done so, let me recommend taking a look at Tale's code, I found it very clear and easy to read. I think if you search for his mono_synth you should be able to find his pack of plugins and libraries etc.
Hi SaulT and big thanks again

I have been checking a lot code just to try and learn. Yours, Tale, Saikes, Losers plus a bunch of random ones in Reaper. And this last week studying a bunch of javascript tutorials and coding along with them.

I was thinking of upgrading my clipper with your 4x upsampling library and looked at your limiter. So the function is "process" right? I need to use my "sinner" function instead? And include the library of course

Code:
@sample

s0 = spl0 * boost;
s1 = spl1 * boost;

os0.os_up4(s0);
os1.os_up4(s1);

os0.y3 = process(os0.y3);
os0.y2 = process(os0.y2);
os0.y1 = process(os0.y1);
os0.y0 = process(os0.y0);
s0 = os0.os_down4();
Best regards /danerius

Last edited by danerius; 02-17-2020 at 11:26 PM.
danerius is offline   Reply With Quote
Old 02-17-2020, 04:08 PM   #27
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Code:
a = 6;

foo.a = 8;

// if a function 

function changemyA(x)
 instance(a)
(
  a = x;
);
This bit changes "a" to "x".... Right?

Code:
 function changemyA2(x)
(
  this.a = x;
);
As does this but its a local "a"...
Code:
foo.changemyA(2);
foo.changemyA2(2); // these two functions do exactly the same thing

// see something missing in the following function?

function changemyA3(x)
(
  a = x;
);

foo.changemyA3(2);

// since we didn't use a "this" or an instance() or local() call in the function
// here the function modifies the global "a" and not "foo.a"!
I think I get it. But Im still confused regarding the "foo". It was declared as 8 and now its what...?

Best regards /danerius

Last edited by danerius; 02-18-2020 at 01:59 AM. Reason: Double checked some youtube tutorials
danerius is offline   Reply With Quote
Old 02-18-2020, 11:54 AM   #28
ErBird
Human being with feelings
 
Join Date: Jan 2017
Location: Los Angeles
Posts: 1,161
Default

Code:
function f1(x)
instance(a)
(
  a = x;
);

function f2(x)
(
  this.a = x;
);
Here, f1 and f2 are equivalent.
Both act on variable "a" in the namespace (foo in these examples) the function is used within.
Using instance() is the same as using "this." within the body of the function.


Code:
function f3(x)
(
  a = x;
);

function f4(x)
global(a)
(
  a = x;
);
f3 and f4 are also equivalent.
If you use a variable within a function and don't declare either instance(), local(), global() or "this." the variable is global by default.

Of course nothing happens until you use the functions.
ErBird is offline   Reply With Quote
Old 02-18-2020, 12:02 PM   #29
ErBird
Human being with feelings
 
Join Date: Jan 2017
Location: Los Angeles
Posts: 1,161
Default

Code:
@init

a = 0;
foo.a = 0;

function changemyA(x)
instance(a)
(
  a = x;
);

function changemyA2(x)
(
  this.a = x;
);

function changemyA3(x)
(
  a = x;
);

@sample

foo.changemyA(1);  //foo.a is now 1
foo.changemyA2(2); //foo.a is now 2
foo.changemyA3(3); //Global a is now 3. foo.a is not altered.
ErBird is offline   Reply With Quote
Old 02-18-2020, 03:12 PM   #30
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 876
Default

Quote:
Originally Posted by danerius View Post
Hi SaulT and big thanks again

Code:
@sample

s0 = spl0 * boost;
s1 = spl1 * boost;

os0.os_up4(s0);
os1.os_up4(s1);

os0.y3 = process(os0.y3);
os0.y2 = process(os0.y2);
os0.y1 = process(os0.y1);
os0.y0 = process(os0.y0);
s0 = os0.os_down4();
repeat that last part for os1 as well, and you can of course replace process() with whatever function you want. I tend to use process() as a habit so when I go back to my code years later I at least have an idea of what I was trying to do. I have taken a lot of inspiration from how Tale wrote his oversampling code and have basically been using his formatting/style.

Check out ReaPack, if you haven't already, so much good code and a really good resource. I need to reinstall that myself, come to think of it. I have been poking away at releasing a pack myself but due to a laptop failure and a general failure to code a decent GUI I'm having to start again almost from scratch.

Oversampling and interpolation are two of my favorite topics, always have been...
SaulT is offline   Reply With Quote
Old 02-23-2020, 12:55 PM   #31
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Quote:
Originally Posted by ErBird View Post
f3 and f4 are also equivalent.
If you use a variable within a function and don't declare either instance(), local(), global() or "this." the variable is global by default.

Of course nothing happens until you use the functions.
Cool. Thanks ErBird

Best regards /danerius
danerius is offline   Reply With Quote
Old 02-23-2020, 12:57 PM   #32
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Quote:
Originally Posted by SaulT View Post
Check out ReaPack, if you haven't already, so much good code and a really good resource. I need to reinstall that myself, come to think of it. I have been poking away at releasing a pack myself but due to a laptop failure and a general failure to code a decent GUI I'm having to start again almost from scratch.

Oversampling and interpolation are two of my favorite topics, always have been...
Hi Sault. Sorry about your laptop. Im a designer by day so if you need help with the no-code portion of the GUI. Just let me know. Id really like to learn to code that bit as well.

Best regards /danerius
danerius is offline   Reply With Quote
Old 02-23-2020, 01:09 PM   #33
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Hi all

I cant get past this error message where the upsampling portion starts. Im guessing theres something with the library not working as it should. I have the library in the same folder as the plugin so it should load? Does it need to be someplace else? Ive found working bits of code all over the Effects folder and it seems to work fine. And in different text formats too.

Thanks + best regards /danerius

Code:
desc:Function Test

slider1:2.2<1.5,3,0.01>Curve

import st-oversampler.jsfx-inc

@init

pdc_bot_ch = 0; pdc_top_ch = 2;
pdc_delay = 31;


  function process (spl,slider)
    (
      sin ($pi * spl / slider);
    );
     
@slider

@sample
 
  s0 = spl0;
  s1 = spl1;
The following line is where I get the error message...

Code:
os0.os_up4(s0);
os1.os_up4(s1);
Im guessing this is the correct way to use the slider code bit?

Code:
os0.y3 = process(os0.y3,slider1);
And the rest of the code...
Code:
  os0.y2 = process(os0.y2);
  os0.y1 = process(os0.y1);
  os0.y0 = process(os0.y0);
  s0 = os0.os_down4();
  
  os1.y3 = process(os1.y3);
  os1.y2 = process(os1.y2);
  os1.y1 = process(os1.y1);
  os1.y0 = process(os1.y0);
  s1 = os1.os_down4();
  
  spl0 = s0;
  spl1 = s1;
danerius is offline   Reply With Quote
Old 02-24-2020, 12:47 PM   #34
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 876
Default

This is correct.

Code:
os0.y3 = process(os0.y3,slider1);
This is not. Process() needs two arguments.

Code:
  os0.y2 = process(os0.y2);
  os0.y1 = process(os0.y1);
  os0.y0 = process(os0.y0);
Once you change that, the code compiles correctly. I copy/pasted the code from your code boxes above, made the change I mentioned, and it ran. jsfx-inc files I think just need to be somewhere in the effects folder, although I often put them in the same folder as the effect itself just to make sure that if I zip it, the jsfx-inc file won't get lost.

You'll notice that your code can radically change the volume level, which I strongly suggest is something you don't want to do. This is because it's just scaling a sin() function. I talk about that in earlier posts and suggest one or two alternatives.
SaulT is offline   Reply With Quote
Old 02-24-2020, 02:09 PM   #35
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Hi SaulT

Tried it but still the same error. Im suspecting its not loading the library.

Thanks + best regards

Link to screen shot of error message: https://www.dropbox.com/s/orifgithtu...0JSFX.png?dl=0

PS Just checked. Theres some other JS-Effects that doesnt load their libraries. Googling like mad right now to find out why... DS

Code:
desc:Function Test

slider1:2.2<1.5,3,0.01>Curve

import st-oversampler.jsfx-inc

@init

pdc_bot_ch = 0; pdc_top_ch = 2;
pdc_delay = 31;


  function process (spl,slider)
    (
      sin ($pi * spl / slider);
    );
     
@slider

@sample
 
  s0 = spl0;
  s1 = spl1;
  
  os0.os_up4(s0);
  os1.os_up4(s1);
  
  os0.y3 = process(os0.y3,slider1);
  os0.y2 = process(os0.y2,slider1);
  os0.y1 = process(os0.y1,slider1);
  os0.y0 = process(os0.y0,slider1);
  s0 = os0.os_down4();
  
  os1.y3 = process(os1.y3,slider1);
  os1.y2 = process(os1.y2,slider1);
  os1.y1 = process(os1.y1,slider1);
  os1.y0 = process(os1.y0,slider1);
  s1 = os1.os_down4();
  
  spl0 = s0;
  spl1 = s1;

Last edited by danerius; 02-24-2020 at 02:27 PM.
danerius is offline   Reply With Quote
Old 02-24-2020, 03:05 PM   #36
Thonex
Human being with feelings
 
Join Date: May 2018
Location: Los Angeles
Posts: 1,721
Default

I have nothing to contribute to this thread other than I LOVE these kinds of discussions. This is a great forum... and thread!
__________________
Cheers... Andrew K
Reaper v6.80+dev0621 - June 21 2023 • Catalina • Mac Mini 2020 6 core i7 • 64GB RAM • OS: Catalina • 4K monitor • RME RayDAT card with Sync Card and extended Light Pipe.
Thonex is offline   Reply With Quote
Old 02-24-2020, 03:17 PM   #37
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Quote:
Originally Posted by Thonex View Post
I have nothing to contribute to this thread other than I LOVE these kinds of discussions. This is a great forum... and thread!
Hi Thonex. Im glad that me fumbling with code can be of help

Best regards /danerius
danerius is offline   Reply With Quote
Old 02-24-2020, 03:27 PM   #38
Thonex
Human being with feelings
 
Join Date: May 2018
Location: Los Angeles
Posts: 1,721
Default

Quote:
Originally Posted by danerius View Post
Hi Thonex. Im glad that me fumbling with code can be of help

Best regards /danerius
Well... I learned a few things...

1) Plugin Doctor may be a "must have" for me.
2) Desmos isn't just for teaching my kids.
3) Most of the thread is over my head...

And something I knew all along... Reaper has the best forum members! Especially the scripting community!
__________________
Cheers... Andrew K
Reaper v6.80+dev0621 - June 21 2023 • Catalina • Mac Mini 2020 6 core i7 • 64GB RAM • OS: Catalina • 4K monitor • RME RayDAT card with Sync Card and extended Light Pipe.
Thonex is offline   Reply With Quote
Old 02-24-2020, 03:30 PM   #39
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Okay... so my current theory is that Ive messed a bit too much the text editor and there might be some extraneous text formatting in the file.

Time to clean up and use a proper IDE. Any recommendations? Im on a Mac.

/danerius
danerius is offline   Reply With Quote
Old 02-25-2020, 03:30 PM   #40
danerius
Human being with feelings
 
Join Date: Oct 2018
Posts: 173
Default

Quote:
Originally Posted by Thonex View Post
Well... I learned a few things...

1) Plugin Doctor may be a "must have" for me.
2) Desmos isn't just for teaching my kids.
3) Most of the thread is over my head...

And something I knew all along... Reaper has the best forum members! Especially the scripting community!
Hi Thorex

Completely agree on the quality of the Reaper community. Everyone is really friendly and helpful.

Best regards /danerius
danerius is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 05:32 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.