Old 07-30-2016, 02:51 AM   #1
Smashed Transistors
Human being with feelings
 
Smashed Transistors's Avatar
 
Join Date: Jul 2014
Location: Là bas les huîtres (FR)
Posts: 424
Default JSFX How slow is array indexing

Let's start a new thread on this topic.

The goal is to measure - and somewhat understand - array indexing so that we can use it efficiently in our jsfx code
__________________
JSFX plugins and synths. See you here and there: SoundCloud, Youtube, Google Play...

Last edited by Smashed Transistors; 07-30-2016 at 03:39 AM.
Smashed Transistors is offline   Reply With Quote
Old 07-30-2016, 03:19 AM   #2
Smashed Transistors
Human being with feelings
 
Smashed Transistors's Avatar
 
Join Date: Jul 2014
Location: Là bas les huîtres (FR)
Posts: 424
Default

Let's benchmark

On my PC (Win7 Intel i5-4440 3.10GHz 8Gb audio:EIEPro at 44.1kHz)
__________________________________________________ __________________
Empty loop
Code:
desc:Test1
@sample
i = 0; loop(10000,i+=1;
);
~36%
__________________________________________________ __________________

Empty indexing
Code:
@sample
i = 0; loop(10000,i+=1;
i[]=1.345;
);
~46%
__________________________________________________ __________________

Explicit 0 offset
Code:
@sample
i = 0; loop(10000,i+=1;
i[0]=1.345;
);
~46%
__________________________________________________ __________________

Explicit 5 offset
Code:
@sample
i = 0; loop(10000,i+=1;
i[5]=1.345;
);
~49%
__________________________________________________ __________________

i offset based on 0
Code:
@sample
i = 0; loop(10000,i+=1;
0[i]=1.345;
);
~46%
__________________________________________________ __________________

i offset based on 0
Code:
@sample
i = 0; loop(10000,i+=1;
5[i]=1.345;
);
~49%
__________________________________________________ __________________

base address in a var
Code:
@init
ad=13;
@sample
i = 0; loop(10000,i+=1;
ad[i]=1.345;
);
~49%
__________________________________________________ __________________

Base address in a variable var
Code:
@sample
i = 0; loop(10000,i+=1;
i[i]=1.345;
);
~49%
__________________________________________________ __________________

Direct
Code:
@sample
i = 0; loop(10000,i+=1;
a=1.345;
);
~36%
__________________________________________________ __________________

unwrapped loop
Code:
@sample
i = 0; loop(1000,
a0=1.345;
a1=1.345;
a2=1.345;
a3=1.345;
a4=1.345;
a5=1.345;
a6=1.345;
a7=1.345;
a8=1.345;
a9=1.345;
i+=1;
i+=1;
i+=1;
i+=1;
i+=1;
i+=1;
i+=1;
i+=1;
i+=1;
i+=1;
);
~36%

__________________________________________________ __________________

Unwrapped and variable values to avoid optimizations
Code:
@sample
i = 0; loop(1000,
i+=1;a0=i;
i+=1;a1=i;
i+=1;a2=i;
i+=1;a3=i;
i+=1;a4=i;
i+=1;a5=i;
i+=1;a6=i;
i+=1;a7=i;
i+=1;a8=i;
i+=1;a9=i;
);
~36%
__________________
JSFX plugins and synths. See you here and there: SoundCloud, Youtube, Google Play...

Last edited by Smashed Transistors; 07-30-2016 at 04:14 AM.
Smashed Transistors is offline   Reply With Quote
Old 07-30-2016, 04:48 AM   #3
octarone
Human being with feelings
 
octarone's Avatar
 
Join Date: Apr 2016
Posts: 30
Default

Yep, that's the way it is, unwrapping and other architecture-specific optimizations don't really matter, because it's interpreted byte code as far as I know.

Here's a summary:
  • Direct variables are the fastest. (e.g: a += 5)
  • Values in memory (pointers, with no indexing) are way slower, but faster than indexing. (e.g: a[0] += 5)
  • Indexing an array with any arbitrary index (other than numerical zero) is the slowest. (e.g: a[1] += 5 or a[var] += 5)

Whether the difference matters is up to you or the script's purpose, I'd honestly optimize it after being mostly "done" with the code though, because if you use a lot of such JSFX it will add up in a way.

Of course, reading from an array is the same thing. However, keep in mind that += or *= or such operations which both operate and assign at the same time are only one operation.

This is a very important distinction especially when using arrays.

a[1] = a[1] + 5 is way slower than a[1] += 5 because it does the indexing and read/write twice! Even a direct variable is slower, but not by much since direct variables are faster.

Always use += *= -= etc when you can, especially with arrays. If you must do some intermediate calculations and want optimization, use a temporary direct variable like this:

Code:
temp = a[0];
// operations on temp
a[0] = temp;
__________________
My JSFX & other things at my simple site, if you are interested: http://sites.google.com/site/octarone
octarone is offline   Reply With Quote
Old 07-30-2016, 08:41 AM   #4
Smashed Transistors
Human being with feelings
 
Smashed Transistors's Avatar
 
Join Date: Jul 2014
Location: Là bas les huîtres (FR)
Posts: 424
Default

Yes, temporary transfer to variables is a good solution in many cases (i use this in the String synth https://stash.reaper.fm/v/26664/TiaR_...ThingIV_04.zip which is 128 voice polyphonic.

The reason I'd like fast array access/interpolation is essentially when i need tables, wave tables, function tables. i.e. including linear or hermite interpolation. Fast built'in functions would be a delight
__________________
JSFX plugins and synths. See you here and there: SoundCloud, Youtube, Google Play...
Smashed Transistors is offline   Reply With Quote
Old 07-30-2016, 10:06 AM   #5
IXix
Human being with feelings
 
Join Date: Jan 2007
Location: mcr:uk
Posts: 3,891
Default

While you're in a measuring frame of mind, how does gmem[] compare?
IXix is offline   Reply With Quote
Old 07-31-2016, 02:15 AM   #6
Smashed Transistors
Human being with feelings
 
Smashed Transistors's Avatar
 
Join Date: Jul 2014
Location: Là bas les huîtres (FR)
Posts: 424
Default

Hello IXix,

Code:
@sample
i = 0; loop(10000,i+=1;
gmem[i]=1;
);
~52%
__________________
JSFX plugins and synths. See you here and there: SoundCloud, Youtube, Google Play...
Smashed Transistors is offline   Reply With Quote
Old 07-31-2016, 02:22 AM   #7
Smashed Transistors
Human being with feelings
 
Smashed Transistors's Avatar
 
Join Date: Jul 2014
Location: Là bas les huîtres (FR)
Posts: 424
Default

Quote:
Originally Posted by octarone View Post
...
a[1] = a[1] + 5 is way slower than a[1] += 5 because it does the indexing and read/write twice! Even a direct variable is slower, but not by much since direct variables are faster.
...
Sure it is much slower:

Code:
i = 0; loop(10000,i+=1;
a[i]+=2;
);
~55%
__________________________________________________

Code:
i = 0; loop(10000,i+=1;
a[i]=a[i]+2;
);
~85%
__________________
JSFX plugins and synths. See you here and there: SoundCloud, Youtube, Google Play...
Smashed Transistors is offline   Reply With Quote
Old 07-31-2016, 02:48 AM   #8
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,784
Default

A comparison between memcpy and a coded loop would be interesting (with what count of values memcppy is faster ?).

If anybody has installed the JSFX to ddl compiler and is in the mood to do so, a comparison to the fully compiled version of such code (not only with indexing) would be really nice.

-Michael
mschnell is offline   Reply With Quote
Old 07-31-2016, 03:04 AM   #9
snooks
Banned
 
Join Date: Sep 2015
Posts: 1,650
Default

Interesting. Here with an extra instruction to set the buffer variable to the index you want (bench3) is faster than indexing with the []s (bench2)...
Code:
@init
iterations = 100000;

a=0;
i=0;
start_time = time_precise();
loop(iterations,
      a=i;
      i+=1;
);
bench1 = time_precise() - start_time;


a=0;
i=0;
start_time = time_precise();
loop(iterations,
      a[i]=i;
      i+=1;
);
bench2 = time_precise() - start_time;


i=0;
start_time = time_precise();
loop(iterations,
      a=i;
      a[]=i;
      i+=1;
);
bench3 = time_precise() - start_time;


a=0;
i=0;
start_time = time_precise();
loop(iterations,
      gmem[i]=i;
      i+=1;
);
bench4 = time_precise() - start_time;
snooks is offline   Reply With Quote
Old 07-31-2016, 03:27 AM   #10
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,653
Default

Quote:
Originally Posted by mschnell View Post
A comparison between memcpy and a coded loop would be interesting (with what count of values memcppy is faster ?).
memcpy() is already faster with 4 to 8, but of course it depends on the exact loop. You could also do it without a loop BTW, assuming the count is constant (and preferrably low), e.g.:

Code:
// Will likely beat memcpy(dst, src, 4).
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
Tale is offline   Reply With Quote
Old 07-31-2016, 03:56 AM   #11
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,653
Default

Quote:
Originally Posted by Smashed Transistors View Post
Let's benchmark
Here are the same benchmarks on my MacBook Pro Core2 Duo (REAPER i386). Note that this machine couldn't handle 10000 loops, so I did 1000 instead.

Empty loop: ~10%
Empty indexing: ~23%
Explicit 0 offset: ~25%
Explicit 5 offset: ~28%
i offset based on 0: 25%
i offset based on 5: 27%
base address in a var: 26%
Base address in a variable var: 26%
Direct: 11%

(I haven't done the last two, because they don't use indexing, and we already have the empty loop as a base.)

Anyway, I think this is not bad, because it would seem that indexing is "only" about 2.3-2.8x slower. It also shows that using pointers (i.e. [0]) indeed is faster, but only marginally.
Tale is offline   Reply With Quote
Old 07-31-2016, 07:00 AM   #12
reapercurious
Human being with feelings
 
reapercurious's Avatar
 
Join Date: Jul 2007
Posts: 1,891
Default

are entire loops @sample executed within the duration of one sample?
reapercurious is offline   Reply With Quote
Old 07-31-2016, 08:07 AM   #13
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,653
Default

Quote:
Originally Posted by reapercurious View Post
are entire loops @sample executed within the duration of one sample?
Yeah, so that's 10000 * srate iterations per second, which is why my old MacBook couldn't handle it (at 48 kHz).
Tale is offline   Reply With Quote
Old 07-31-2016, 10:09 AM   #14
reapercurious
Human being with feelings
 
reapercurious's Avatar
 
Join Date: Jul 2007
Posts: 1,891
Default

Quote:
Originally Posted by Tale View Post
Yeah, so that's 10000 * srate iterations per second, which is why my old MacBook couldn't handle it (at 48 kHz).
wow!

can't wait to try that! probably great for dezipping and interpolation

(edit) well maybe not...
reapercurious is offline   Reply With Quote
Old 08-10-2016, 12:36 PM   #15
Smashed Transistors
Human being with feelings
 
Smashed Transistors's Avatar
 
Join Date: Jul 2014
Location: Là bas les huîtres (FR)
Posts: 424
Default

Sure reapercurious... don't do that at home !
__________________
JSFX plugins and synths. See you here and there: SoundCloud, Youtube, Google Play...
Smashed Transistors is offline   Reply With Quote
Old 08-10-2016, 01:01 PM   #16
Smashed Transistors
Human being with feelings
 
Smashed Transistors's Avatar
 
Join Date: Jul 2014
Location: Là bas les huîtres (FR)
Posts: 424
Default

Back to some practice/experiments...

A few months ago i coded a fully polyphonic "String Thing".
Here, fully polyphonic means there is a generator under each and every key

To do so, i use arrays for every "state variables" (phase, frequency and others) of the generators. Each array has 128 entries (one for each MIDI key).

For each key/generator
  • i temporarily copy the state variables from the arrays to variables,
  • then i use and process the variables,
  • and finally, i put their updated values into the arrays.

It's quite cpu efficient - thanks to the copies to the variables - but the code is somewhat ugly. And worse, it is easy to make bugs if i forget to copy or update values from the arrays to the work-faster-variables.


So, last week end, i get that insane idea: no more array, no more copies.
Let's instantiate 128 generators (v000 to v127).

...I cannot resist to have a try ... this evening was coding and ice cream.

Here is a minimalistic - but operational and usable - example :
FullPolyOrgan.zip
I'll be happy to have your feedback, on my PC the perf is quite good but i don't know how it behaves on other platforms.
__________________
JSFX plugins and synths. See you here and there: SoundCloud, Youtube, Google Play...

Last edited by Smashed Transistors; 08-10-2016 at 01:23 PM.
Smashed Transistors is offline   Reply With Quote
Old 08-10-2016, 01:13 PM   #17
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,784
Default

Slightly related question.

To do a very simple modification on audio passing through a plugin, is it better to use the @sample event or to use the @block event and do a loop in EEL to access each sample ?

-Michael
mschnell is offline   Reply With Quote
Old 08-10-2016, 01:17 PM   #18
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,784
Default

Quote:
Originally Posted by Smashed Transistors View Post
So, last week end, i get that insane idea: no more array, no more copies.
Let's instantiate 128 generators (v000 to v127).

...I cannot resist to try it this evening.
While you are in a can't resist mood; did you ever try to compile the JSFX (either version) to a VST plugin using Jes2Cpp ?

-Michael
mschnell is offline   Reply With Quote
Old 08-10-2016, 02:10 PM   #19
Smashed Transistors
Human being with feelings
 
Smashed Transistors's Avatar
 
Join Date: Jul 2014
Location: Là bas les huîtres (FR)
Posts: 424
Default

That's evil mschnell... now i'm downloading it... and mingw with gcc... i won't go to bed before 2 in the morning :-/
__________________
JSFX plugins and synths. See you here and there: SoundCloud, Youtube, Google Play...
Smashed Transistors is offline   Reply With Quote
Old 08-10-2016, 02:47 PM   #20
Smashed Transistors
Human being with feelings
 
Smashed Transistors's Avatar
 
Join Date: Jul 2014
Location: Là bas les huîtres (FR)
Posts: 424
Default

Thanks for the link mschnell, it works just fine.
The perfs of the jsfx are slightly better on my PC than the vst version.
__________________
JSFX plugins and synths. See you here and there: SoundCloud, Youtube, Google Play...
Smashed Transistors is offline   Reply With Quote
Old 08-10-2016, 09:26 PM   #21
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,784
Default

Doing the stuff in just half an hour ?!?!?!?!

That's amazing !

But of course a pity that it does not perform better than the interpreted code. I had expected it run at least at double speed.

-Michael
mschnell is offline   Reply With Quote
Old 08-10-2016, 10:30 PM   #22
Smashed Transistors
Human being with feelings
 
Smashed Transistors's Avatar
 
Join Date: Jul 2014
Location: Là bas les huîtres (FR)
Posts: 424
Default

I used Geet Jeez. These are great piece of software !
By the way jsfx as far as i knowis not interpreted, it is compiled on the fly. This internal compilation is very fast.
__________________
JSFX plugins and synths. See you here and there: SoundCloud, Youtube, Google Play...
Smashed Transistors is offline   Reply With Quote
Old 08-10-2016, 11:06 PM   #23
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,653
Default

Quote:
Originally Posted by mschnell View Post
To do a very simple modification on audio passing through a plugin, is it better to use the @sample event or to use the @block event and do a loop in EEL to access each sample ?
Well, you have to use @sample, or you won't have any samples... You could however buffer samples in @sample, and then process the buffer in the next @block call, but this will likely be slower, and add extra latency.
Tale is offline   Reply With Quote
Old 08-10-2016, 11:19 PM   #24
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,653
Default

Quote:
Originally Posted by Smashed Transistors View Post
To do so, i use arrays for every "state variables" (phase, frequency and others) of the generators. Each array has 128 entries (one for each MIDI key).

For each key/generator
  • i temporarily copy the state variables from the arrays to variables,
  • then i use and process the variables,
  • and finally, i put their updated values into the arrays.

It's quite cpu efficient - thanks to the copies to the variables - but the code is somewhat ugly. And worse, it is easy to make bugs if i forget to copy or update values from the arrays to the work-faster-variables.
I use a slightly different variation, I store all state variables for a key sequentially i.e.:

Code:
p[0] = phase1;
p[1] = freq1;
p[2] = whatever1;

p[3] = phase2;
p[4] = freq2;
p[5] = whatever2;

// etc.
This might be slightly more efficient (less variables/indexing, might be better for CPU cache), or maybe not (needs extra multiplication ptr=key*idx). It is just as "ugly" / error-prone though...
Tale is offline   Reply With Quote
Old 08-11-2016, 02:44 PM   #25
Smashed Transistors
Human being with feelings
 
Smashed Transistors's Avatar
 
Join Date: Jul 2014
Location: Là bas les huîtres (FR)
Posts: 424
Default

Maybe there is also some implicit float -> integer conversions in a case and not in the other.
I don't really know how JS handles these.

Here is an awful snippet from the FullPolyOrgan i put on the stash:
Code:
@block
... MIDI STUFF ...
// global block processing
para_blk();
// voice block processing
v000.blk(gGate[  0]);v001.blk(gGate[  1]);v002.blk(gGate[  2]);v003.blk(gGate[  3]);v004.blk(gGate[  4]);v005.blk(gGate[  5]);v006.blk(gGate[  6]);v007.blk(gGate[  7]);v008.blk(gGate[  8]);v009.blk(gGate[  9]);v010.blk(gGate[ 10]);v011.blk(gGate[ 11]);
v012.blk(gGate[ 12]);v013.blk(gGate[ 13]);v014.blk(gGate[ 14]);v015.blk(gGate[ 15]);v016.blk(gGate[ 16]);v017.blk(gGate[ 17]);v018.blk(gGate[ 18]);v019.blk(gGate[ 19]);v020.blk(gGate[ 20]);v021.blk(gGate[ 21]);v022.blk(gGate[ 22]);v023.blk(gGate[ 23]);
v024.blk(gGate[ 24]);v025.blk(gGate[ 25]);v026.blk(gGate[ 26]);v027.blk(gGate[ 27]);v028.blk(gGate[ 28]);v029.blk(gGate[ 29]);v030.blk(gGate[ 30]);v031.blk(gGate[ 31]);v032.blk(gGate[ 32]);v033.blk(gGate[ 33]);v034.blk(gGate[ 34]);v035.blk(gGate[ 35]);
v036.blk(gGate[ 36]);v037.blk(gGate[ 37]);v038.blk(gGate[ 38]);v039.blk(gGate[ 39]);v040.blk(gGate[ 40]);v041.blk(gGate[ 41]);v042.blk(gGate[ 42]);v043.blk(gGate[ 43]);v044.blk(gGate[ 44]);v045.blk(gGate[ 45]);v046.blk(gGate[ 46]);v047.blk(gGate[ 47]);
v048.blk(gGate[ 48]);v049.blk(gGate[ 49]);v050.blk(gGate[ 50]);v051.blk(gGate[ 51]);v052.blk(gGate[ 52]);v053.blk(gGate[ 53]);v054.blk(gGate[ 54]);v055.blk(gGate[ 55]);v056.blk(gGate[ 56]);v057.blk(gGate[ 57]);v058.blk(gGate[ 58]);v059.blk(gGate[ 59]);
v060.blk(gGate[ 60]);v061.blk(gGate[ 61]);v062.blk(gGate[ 62]);v063.blk(gGate[ 63]);v064.blk(gGate[ 64]);v065.blk(gGate[ 65]);v066.blk(gGate[ 66]);v067.blk(gGate[ 67]);v068.blk(gGate[ 68]);v069.blk(gGate[ 69]);v070.blk(gGate[ 70]);v071.blk(gGate[ 71]);
v072.blk(gGate[ 72]);v073.blk(gGate[ 73]);v074.blk(gGate[ 74]);v075.blk(gGate[ 75]);v076.blk(gGate[ 76]);v077.blk(gGate[ 77]);v078.blk(gGate[ 78]);v079.blk(gGate[ 79]);v080.blk(gGate[ 80]);v081.blk(gGate[ 81]);v082.blk(gGate[ 82]);v083.blk(gGate[ 83]);
v084.blk(gGate[ 84]);v085.blk(gGate[ 85]);v086.blk(gGate[ 86]);v087.blk(gGate[ 87]);v088.blk(gGate[ 88]);v089.blk(gGate[ 89]);v090.blk(gGate[ 90]);v091.blk(gGate[ 91]);v092.blk(gGate[ 92]);v093.blk(gGate[ 93]);v094.blk(gGate[ 94]);v095.blk(gGate[ 95]);
v096.blk(gGate[ 96]);v097.blk(gGate[ 97]);v098.blk(gGate[ 98]);v099.blk(gGate[ 99]);v100.blk(gGate[100]);v101.blk(gGate[101]);v102.blk(gGate[102]);v103.blk(gGate[103]);v104.blk(gGate[104]);v105.blk(gGate[105]);v106.blk(gGate[106]);v107.blk(gGate[107]);
v108.blk(gGate[108]);v109.blk(gGate[109]);v110.blk(gGate[110]);v111.blk(gGate[111]);v112.blk(gGate[112]);v113.blk(gGate[113]);v114.blk(gGate[114]);v115.blk(gGate[115]);v116.blk(gGate[116]);v117.blk(gGate[117]);v118.blk(gGate[118]);v119.blk(gGate[119]);
v120.blk(gGate[120]);v121.blk(gGate[121]);v122.blk(gGate[122]);v123.blk(gGate[123]);v124.blk(gGate[124]);v125.blk(gGate[125]);v126.blk(gGate[126]);v127.blk(gGate[127]);
For a synth it is not a problem to do the processing in the @block section and copy it in a buffer.
The contents of the buffer is added to the output in the @sample section.
The main benefit if that some conditional commands ("ifs") are done once per @block and not on every sample.

gGate are updated in the MIDI loop.
The blk function does the work and is called for every and each 128 voices.
It looks like:
Code:
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
//                                             voice block processing
// "sample" level stuff are calculated here too (trick to limit cpu)
//                                outputs go into SP0 and SP1 tables
function blk(gate)
local(k n)
instance(note fenv p dp modDp out)(
  gate != 0 || fenv > 0.005 ? (                   // if not active we don't work !!!
    k = gSavedK;  n = 0; loop(samplesblock,            // sample loop
// _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _
      k += 1; k >= KRATE ? ( k = 0;                   // control rate
        // we use gVibCoef from para_blk to modulate 
        // the delta phase (frequency) -> vibrato
        modDp = dp * gVibCoef[n];
      );
// _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _
//                                                         audio rate
      p += modDp;
      p -= 8192 * (p >= 8192);
      fenv += 0.01 * (gate - fenv);
      out = fenv * gSin8192[(p + 16*8192 
        + gIndex * gSin8192[(p*(slider4+1))%8192]) % 8192];
      SP0[n] += out; // SP0 and SP1 are output buffers
      SP1[n] += out; // they are added to spl0 and spl1 in @sample
      SUMENV2[n] += fenv * fenv; // used for output global "compression"
// _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _  _
      n += 1;
    );
  );
);
And i don't need to copy from or to state variable arrays
I only have to write ugly code once, afterwards i just have to implement the "blk" function.

The same principle goes for init and slider...

I did some more experiments with this method and, as far as i experimented, it looks to be very efficient. I'll certainly use it for a poly version of "ze little cheesy synth".
__________________
JSFX plugins and synths. See you here and there: SoundCloud, Youtube, Google Play...

Last edited by Smashed Transistors; 08-11-2016 at 03:02 PM.
Smashed Transistors is offline   Reply With Quote
Old 08-11-2016, 03:50 PM   #26
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 15,745
Default

You guys can dig into the internals of JSFX by looking at WDL's eel2/ directory... nseel-compiler.c is the main place to look, but also the file asm-nseel-x86-gcc.c.

Some additional info:

x[y] and y[x] both compile as megabuf(x+y), and if x or y are 0, then just megabuf(xory)

The big cost associated with using [] rather than direct variables is that it has to convert the address to integer, then bounds check it, look up the appropriate page in the script's memory (and if it is unused, allocate it), etc. Whereas using a variable, the address is already known.

There is a bunch of code in Super8 which uses a mix of arrays and namespaces, where it will often copy data from the array to the namespace at certain points, then use the namespace within @sample if possible (since the address for a particular variable is resolved at compile-time).

Anyway...
Justin is offline   Reply With Quote
Old 09-01-2016, 10:04 AM   #27
Smashed Transistors
Human being with feelings
 
Smashed Transistors's Avatar
 
Join Date: Jul 2014
Location: Là bas les huîtres (FR)
Posts: 424
Default

Quote:
Originally Posted by Justin View Post
... it has to convert the address to integer...
Hello Justin
and thank you for Reaper ,

is there a way to tell JS that some variable is an integer and that it does not have to translate it from double to integer and from integer to double.

My idea is to split my phase counter into an integer part and a float part so that no double to integer conversion is necessary.

Something like:
Code:
integers
dp_i : delta phase (frequency)
p_i :  "phase" [0,127[

floats
dp_f : delta phase float part
p_f  : phase float part [0, 1[

p_f += dp_f;         // increment the phase
carry = p_f >= 1;    // is there a carry ?
p_f -= carry;        // stay in [0,1[ please
p_i += dp_i + carry; // increment and take the carry
p_i %= 128;          // modulo to stay in the wavetable

out = table[p_i] + p_f * (table[(p_i+1)%128] - table[p_i]);
__________________
JSFX plugins and synths. See you here and there: SoundCloud, Youtube, Google Play...
Smashed Transistors 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 06:17 PM.


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