Go Back   Cockos Confederated Forums > REAPER Forums > JSFX and ReaScript Discussion

Reply
 
Thread Tools Display Modes
Old 03-24-2011, 05:58 PM   #41
Mich
Human being with feelings
 
Join Date: May 2009
Posts: 1,265
Default

Quote:
Originally Posted by caseyjames View Post
Not that I'd be able to write a handler for them, but is it not possible to write something within JS to read a midi file? Is it not able to load arbitrary files, even if it can't cope with them?
Unless Cockos changed something and they forgot to update the JS documentation, yes.

Here are all available file functions in JS:
http://www.reaper.fm/sdk/js/js.php#cat_file

MIDI is not among then and neither is arbitrary file access. Only wav, ogg and specially formated txt files.
Mich is offline   Reply With Quote
Old 03-24-2011, 06:53 PM   #42
groundhum
Human being with feelings
 
groundhum's Avatar
 
Join Date: Jan 2011
Location: Finger Lakes, NY
Posts: 54
Default

Doesn't file_mem() read from any open file? I'm just asking; the spec implies it.
__________________
Michael Rees, composer &c.
extraneous data
groundhum is offline   Reply With Quote
Old 03-24-2011, 08:23 PM   #43
Mich
Human being with feelings
 
Join Date: May 2009
Posts: 1,265
Default

Quote:
Originally Posted by groundhum View Post
Doesn't file_mem() read from any open file? I'm just asking; the spec implies it.
Maybe, but I don't think JS allowa you to open any other files than wav, ogg and txt. I could be wrong though, best thing would be you go and try to open a MIDI file and see whether file_mem() returns something usable, however I doubt it will work because similar requests were already made multiple times, e.g.: http://forum.cockos.com/showthread.php?t=75323 but the answer todate has (sadly) always been no you can't read arbitrary files with JS.
Mich is offline   Reply With Quote
Old 03-24-2011, 08:43 PM   #44
caseyjames
Human being with feelings
 
caseyjames's Avatar
 
Join Date: Jul 2009
Posts: 610
Default

Has there been any mention of a JS 2 anywhere on the horizon?
caseyjames is offline   Reply With Quote
Old 05-12-2011, 03:24 AM   #45
vocalid
Human being with feelings
 
vocalid's Avatar
 
Join Date: Sep 2009
Location: Middle of nowhere (where the cheese comes from)
Posts: 483
Default Displaying sliders without text

I don't know if anyone has ever had this problem:

You want to insert a slider but not have a desription left of it? ...space doesn't work, it won't display the slider.

Solution: insert ASCII code 129 -> hold alt down while pressing 0129 on the keyboard number pad

(took me ages of trying out stuff to find it)

Last edited by vocalid; 05-12-2011 at 03:36 AM.
vocalid is offline   Reply With Quote
Old 09-23-2011, 03:21 AM   #46
DarkStar
Human being with feelings
 
DarkStar's Avatar
 
Join Date: May 2006
Location: Surrey, UK
Posts: 15,386
Default Defininig arrays

I used to run into problems defining arrays in JS FX, losing track of how the memory was being used and inadvertently reusing or overwriting memory slots.

I've come up with a fairly fool-proof syntax for defining arrays:
-- define the start address, number of items and end address together
-- for the next array, its start address = the end address of the previous array
-- each array item can consist of multiple elements
-- include any initialisation or constants (indented, for clarity)

Here is an example:

Code:
// -----------------------------------------------------------
    in_buffs = 1024;					// start of array
    noofbuffs = 256;					// number of items in array
    end_in_buffs = in_buffs + noofbuffs;		// end of array

        in_buffs[0] =  21; in_buffs[1] =  25; etc 	// initialisation of array

// -----------------------------------------------------------
    label_X = end_in_buffs;				// start of next array, = end of previous array	
    nooflabs = 32;						// number of items in array
    label_Y = label_X + nooflabs;
    label_Z = label_Y + nooflabs;
    end_labels = label_Z + nooflabs;			// end of array

        label_X[0] = 20; label_X[1] = 50; etc	// initialisation of array
        label_Y[0] = 110; label_Y[1] = 57; etc
        label_Z[0] = 40; label_Z[1] = 60; etc
 
// -----------------------------------------------------------
    chan_state = end_labels;				// start of next array, = end of previous array
        OFF = 0;						// constants for buff_state
        ON = 1;
   noofchans = 16;
   end_chan_states = chan_state + noofchans;	// end of array
 
        memset(chan_state, OFF, noofchans);	// initialisation of array (dest, value, length)
        chan_state[2] = ON;

// -----------------------------------------------------------
__________________
DarkStar ... interesting, if true. Inspired by ...

My top 40 FRs, as voted by you (updated for June 2015)
DarkStar is online now   Reply With Quote
Old 01-14-2013, 06:16 AM   #47
IXix
Human being with feelings
 
Join Date: Jan 2007
Location: mcr:uk
Posts: 3,018
Default List import library

I made a suite of functions for managing lists of items in memory. Hopefully some people might find it useful .

Details and discussion at http://forum.cockos.com/showthread.p...23#post1104623
IXix is offline   Reply With Quote
Old 04-25-2013, 11:40 PM   #48
bang
Human being with feelings
 
bang's Avatar
 
Join Date: Jul 2006
Posts: 554
Default newJs pseudo-object parameters

hello all!

seems that the main limitation of newJs pseudo-objects is that inside a function "this.foo" is all there is. there's no inbuilt way to refer to "that.foo". here's my current workaround technique:
Code:
function rgbapush()
  instance( r, g, b, a )
(
  stack_push( a );
  stack_push( b );
  stack_push( g );
  stack_push( r );
);

function rgbapop()
  instance( r, g, b, a )
(
  stack_pop( r );
  stack_pop( g );
  stack_pop( b );
  stack_pop( a );
);

// a.rgbapush(); b.rgbapush();
function rgbamix( mix ) // thread safe
  instance( r, g, b, a ) local( mix1 )
(
  mix1= 1-mix;
  this.rgbapop(); // this= b.rgbapush();
  // keep in sync w/ rgbapop()
  r= stack_pop() * mix1 + r * mix; //stack_pop( a.r );
  g= stack_pop() * mix1 + g * mix; //stack_pop( a.g );
  b= stack_pop() * mix1 + b * mix; //stack_pop( a.b );
  a= stack_pop() * mix1 + a * mix; //stack_pop( a.a );
);

/*** alas, doesn't work:
// a.rgbapush(); b.rgbapush();
function rgbamix2( mix )
  instance( r, g, b, a )
  local(a1, b1)
(
  mix1= 1-mix;
  b1.rgbapop(); a1.rgbapop();
  r= a1.r * mix1 + b1.r * mix;
  g= a1.g * mix1 + b1.g * mix;
  b= a1.b * mix1 + b1.b * mix;
  a= a1.a * mix1 + b1.a * mix;
); ***/
anyone have anything better than this?

enjoy! /dan
bang is offline   Reply With Quote
Old 05-26-2013, 05:56 AM   #49
TonE
Human being with feelings
 
Join Date: Feb 2009
Location: Midi automateable sends. Only via OSC.
Posts: 1,327
Default

Is there a copy of this thread, but ONLY for midi, no audio at all. Note speed detection, note duration manipulation, velocity manipulation, midi channel filtered processing, never hanging notes no matter what you do = note hanging prevention, note transposition, midi looping with velocity fade out per note using various fade out functions, midi looping with cc7 fade out using various fade out functions, note speed channelizer, polyphony channelizer, keyboard splitter into 3 zones per midi channel, chord info, key snap, arp!0

Tips and tricks, snippets, ideas for midi processing with zero audio processing.
__________________
Volume mixing via jogwheeling with mouseovering. Yeah!
Logarithmic bpm via oscii-bot and program change. Thanks Banned!
boreg made it, never hanging notes in Reaper again! Thanks boreg! boreg & bang.
TonE is offline   Reply With Quote
Old 05-26-2013, 12:32 PM   #50
Justin
Administrator
 
Justin's Avatar
 
Join Date: Jan 2005
Location: NYC
Posts: 9,441
Default

Quote:
Originally Posted by bang View Post
Code:
/*** alas, doesn't work:
// a.rgbapush(); b.rgbapush();
function rgbamix2( mix )
  instance( r, g, b, a )
  local(a1, b1)
(
  mix1= 1-mix;
  b1.rgbapop(); a1.rgbapop();
  r= a1.r * mix1 + b1.r * mix;
  g= a1.g * mix1 + b1.g * mix;
  b= a1.b * mix1 + b1.b * mix;
  a= a1.a * mix1 + b1.a * mix;
); ***/
anyone have anything better than this?
If you changed local(a1,b1) to instance(a1,b1), I believe this might work! local namespace support would be nice, too, but it isn't currently supported.
Justin is offline   Reply With Quote
Old 05-26-2013, 01:30 PM   #51
bang
Human being with feelings
 
bang's Avatar
 
Join Date: Jul 2006
Posts: 554
Default

Quote:
Originally Posted by Justin View Post
If you changed local(a1,b1) to instance(a1,b1), I believe this might work! local namespace support would be nice, too, but it isn't currently supported.
yes. but won't we end up with <psuedo-object>.a1.r/g/b/a and <psuedo-object>.b1.r/g/b/a for every psuedo-object which uses rgbamix2()? i guess i haven't wanted to load up the Js namespace any more than i need to. it already gets to be a pretty massive variables list in the debug window. :^)

and fwiw... what i'd really love to see someday is a way to alias psuedo-object namespaces inside functions. something like:
Code:
// rgbamix2( mix, a, b )
function rgbamix2( mix, @a1, @b1 )
  instance( r, g, b, a )
(
  mix1= 1-mix;
  r= a1.r * mix1 + b1.r * mix; // r= a.r * mix1 + b.r * mix
  g= a1.g * mix1 + b1.g * mix;
  b= a1.b * mix1 + b1.b * mix;
  a= a1.a * mix1 + b1.a * mix;
);
just sayin'... :^)

enjoy! /dan

ps- also fwiw, stack_push()/pop() are awesomely useful generally. thanks so much for those.

Last edited by bang; 05-26-2013 at 01:35 PM. Reason: ps
bang is offline   Reply With Quote
Old 10-10-2013, 11:49 PM   #52
Hubi
Human being with feelings
 
Join Date: Oct 2010
Posts: 62
Default

A simple button maker function:

Code:
function button(state x1 y1 x2 y2 r g b)
  (
  gfx_x = x1;
  gfx_y = y1;
  gfx_r =r;gfx_b=b;gfx_g=g;
  (mouse_x > x1 && mouse_x < x1+x2 && mouse_y > y1 && mouse_y < y1+y2) ? (
    gfx_r =r+0.05;gfx_b=b+0.05;gfx_g=g+0.05; 
    mouse_cap == 1 ? (
      state = 1;
      gfx_r =r+0.2;gfx_b=b+0.2;gfx_g=g+0.2;
      );  
    ) : (
    state = 0; 
  ); 
  gfx_rectto(gfx_x+x2,gfx_y+y2); 
  state;
  );
Code:
button_clicked = button(state,20,20,40,20,0.6,0.6,0.6);
state returns "1" if the button is clicked, otherwise it is "0"
x1 and y1 are the position of the left top corner
x2 and y2 are the size of the button
r,g,b color


it shows if the mouse hovers over the button and if it is clicked

regards
Hubi
Hubi is offline   Reply With Quote
Old 10-17-2013, 01:15 PM   #53
reapercurious
Human being with feelings
 
reapercurious's Avatar
 
Join Date: Jul 2007
Posts: 1,428
Default

Quote:
Originally Posted by liteon View Post
a fast linear congruential generator (or specifically the park-miller variation) is described below.

basic algorithm:
Code:
@init
rnd=1;
@sample
rnd=rnd*a%m;
but the main problem is the range in our case, since with some of the common lcg parameters we go out of range:
Code:
@init
rnd=1;
@sample
rnd=rnd*16807%2147483647;
// call 0
// 1*16807%2147483647=16807
// call 1
// 16807*16807%2147483647=2824275249
// call 2
// 2824275249*16807%2147483647=1 -> out of range prevention
therefore a larger modulus cannot be used, such as the 2^31-1 -> 'marsenne prime'

so here are some parameters i've calculated based on the "zx-spectrum" multiplier,(77) but with much larger modulus.

Code:
//all with initial seed 1
rnd0*=77;                     //$x4D
rnd0%=16777219;               //$x1000003=2^24+3
rnd1*=76;                     //$x4C
rnd1%=16777221;               //$x1000005=2^24+5
rnd2*=77;                     //$x4D
rnd2%=8388609;                //$x800001=2^23+1
so basically all that is needed is a scaling factor in the end:
Code:
//full code
@init
rnd=1;
@sample
rnd*=77;
rnd%=16777219;
spl0=rnd*0.0000000593; //scale down to 0-1 range
comparison with the marsenne twister implementation in rand().
100 executions of rand() = 61% cpu
100 executions of one recursion lane lcg = 26% cpu

@gfx plots (ermm...30sec freerun)

two rand() x,y:

[img]http://img195.**************/img195/7922/mtwister.png[/img]

two recursions lanes lcg for x,y:

[img]http://img195.**************/img195/5992/gauss.png[/img]

the more expensive gaussian noise version as a bonus:
Code:
//gaussian version
@init
rnd0=rnd1=rnd2=1;
@sample
rnd0*=77;
rnd0%=16777219;
rnd1*=76;
rnd1%=16777221;
rnd2*=77;
rnd2%=8388609;
spl0=(rnd0+rnd1+rnd2)*0.00000002403333333333333; //.... *k
//k=(1/3*0.0000000721)

----
lubomir
real world user-understandable application would be appreciated on these snippets, otherwise they are only useful to people who understand terms and concepts that are four orders elevated in mean sophistication.
reapercurious is offline   Reply With Quote
Old 10-20-2013, 04:46 AM   #54
chilledpanda
Human being with feelings
 
chilledpanda's Avatar
 
Join Date: Jan 2013
Location: United Kingdom
Posts: 28
Default

Here's a technique I found useful for debugging, by watching local memory akin to memory watch widows in professional debuggers.

First set up a slider (I use 64 as it's he last one),
This slider allows you to view local 0-to 2048,

slider64:0<0,2048,16>MEMWATCH LOC

Then change/add @slider to read the slider and set the memwatchvariable

@slider
//debugging code
memwatch = floor(slider64);


Add the follow to the @gfx uppdate block this constantly updates so allows us to constantly update the mem watch variables

@gfx

//debug code
memwatch_00 = memwatch[0];
memwatch_01 = memwatch[1];
memwatch_02 = memwatch[2];
memwatch_03 = memwatch[3];
memwatch_04 = memwatch[4];
memwatch_05 = memwatch[5];
memwatch_06 = memwatch[6];
memwatch_07 = memwatch[7];
memwatch_08 = memwatch[8];
memwatch_09 = memwatch[9];
memwatch_10 = memwatch[10];
memwatch_11 = memwatch[11];
memwatch_12 = memwatch[12];
memwatch_13 = memwatch[13];
memwatch_14 = memwatch[14];
memwatch_15 = memwatch[15];



Then in the JS development environment editor make sure the auto refresh is ticked under the left window and then locate the memwatch variables.

Move the slider and see the memory locations update in steps of 16 values.
__________________
-------------------------------------------------------------------------------
http://soundcloud.com/chilled-panda
chilledpanda is offline   Reply With Quote
Old 02-04-2014, 11:09 AM   #55
Argitoth
Human being with feelings
 
Argitoth's Avatar
 
Join Date: Feb 2008
Location: Phoenix, AZ
Posts: 1,965
Default

this page: https://ccrma.stanford.edu/~craig/ar...essenmidi.html seems to have some explanation on midi messages, but does not exactly correlate to JS explanation: http://www.reaper.fm/sdk/js/midi.php#js_midi

Is there a comprehensive list of midi messages/parameters? Like note on/off, channel pressure, midi cc, etc.
__________________
Soundemote - Actively pursuing the advancement of sample library technology
MyReaperPlugin - Easy-to-use cross-platform C++ REAPER extension template
Argitoth is offline   Reply With Quote
Old 02-04-2014, 11:25 AM   #56
James HE
Human being with feelings
 
James HE's Avatar
 
Join Date: Mar 2007
Location: some prairie in the near mid-west
Posts: 3,827
Default

Quote:
Originally Posted by Argitoth View Post

Is there a comprehensive list of midi messages/parameters? Like note on/off, channel pressure, midi cc, etc.
here.

http://www.midi.org/techspecs/midimessages.php
__________________
James HE - Solitude for the Paranoid, Joy for the Unexcited
on itunes and Spotify and facebook
James HE is offline   Reply With Quote
Old 05-30-2014, 10:36 AM   #57
Argitoth
Human being with feelings
 
Argitoth's Avatar
 
Join Date: Feb 2008
Location: Phoenix, AZ
Posts: 1,965
Default

check this out, 0 to 1 taper, log-like to exp-like and everything inbetween

http://www.mathopenref.com/graphfunc...40425531914894

interactive graph, we should start using this more often.
__________________
Soundemote - Actively pursuing the advancement of sample library technology
MyReaperPlugin - Easy-to-use cross-platform C++ REAPER extension template
Argitoth is offline   Reply With Quote
Old 06-05-2014, 08:52 PM   #58
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 633
Default

This is the function that Argitoth is suggesting:

Code:
x = [0, 1]
y = (a*x-x)/(2*a*x-a-1)

range: a = [-1, 1]
a -> 1  log taper
a == 0  linear
a -> -1  reverse log taper
I have an alternative. It is slightly faster to execute but a little harder to dial in precisely.

Code:
x = [0, 1]
y = ((1+a)*x)/(a+x)

range: a can neither be nor be between 0 and -1

a from large positive -> 0.0001...   log taper
a from large negative -> -1.0001...   reverse log taper
http://www.mathopenref.com/graphfunc...0&al=-10&a=-10

Illustration of Tapers

http://www.geofex.com/article_folder...s/pottaper.gif

Last edited by SaulT; 06-05-2014 at 09:08 PM.
SaulT is offline   Reply With Quote
Old 06-11-2014, 01:24 PM   #59
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 633
Default

For reference, a quick approximation of the analog hardware audio log taper, with a direct comparison between Argitoth's code and mine. The curves are basically interchangeable.

My code

Code:
function reverseLogTaper(val)
(
  (val*1.1)/(val+0.1);
);

function logTaper(val)
(
  (-0.1*val)/(val-1.1);
);
Argitoth's

Code:
function reverseLogTaper(val)
(
  (-0.85*x-x)/(-1.7*val-0.15);
);

function logTaper(val)
(
  (0.85*val-val)/(1.7*val-1.85);
);
Log (Audio) Taper comparison

http://www.mathopenref.com/graphfunc...=5&bl=-5&b=0.1

Reverse Log (Reverse Audio) Taper comparison

http://www.mathopenref.com/graphfunc...=5&bl=-5&b=0.1
SaulT is offline   Reply With Quote
Old 09-17-2014, 10:55 AM   #60
Smashed Transistors
Human being with feelings
 
Smashed Transistors's Avatar
 
Join Date: Jul 2014
Location: Là bas les huîtres (FR)
Posts: 373
Default Alternative to atan2

Diamond angle is a fast alternative to atan2.
It is useful for angle comparisons.

Code:
//______________________________________________________________________
//diamond angle 0..4
function diamAngle(x y) (
  y >= 0 ? (
    x >= 0 ?     y / (x + y) : 1 + x / (x - y);
  ) : (
    x < 0  ? 2 + y / (x + y) : 3 + x / (x - y); 
  );
);
__________________
JSFX plugins and synths. See you here and there: SoundCloud, Youtube, Google Play...
Smashed Transistors is offline   Reply With Quote
Old 10-09-2014, 10:20 PM   #61
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 633
Default

Parameter smoothing

Sometimes its nice to have your sliders change gracefully so as to not cause abrupt changes to the sound. One example usage is minimizing zipper noise when changing the frequency of an oscillator. This is a simple one-pole parameter smoother.

Code:
coff = exp(-1/(ms/1000*srate));

function singlepole(in,target,coeff)
(
  in*coeff + target*(1-coeff);
);
an example usage could be (assuming that slider1 controls the frequency, say)

Code:
smooth_coeff = exp(-1/(20/1000*srate));   // 20 ms

@sample
freq = singlepole(freq,slider1,smooth_coeff);
Obviously there are different ways to code it, but that's the basic idea. You could also put it in a @block if you wanted, you'd just have to tweak the code a bit.

Code:
smooth_coeff = exp(-1/(ms/1000*srate/samplesblock));

Last edited by SaulT; 10-09-2014 at 10:33 PM.
SaulT is offline   Reply With Quote
Old 11-22-2014, 12:50 AM   #62
IXix
Human being with feelings
 
Join Date: Jan 2007
Location: mcr:uk
Posts: 3,018
Default GUI Library

IX JS/EEL GUI Library v1. A system for easy(ish) implementation of bitmap based GUIs in JS/EEL scripts. Release/discussion thread here...
IXix is offline   Reply With Quote
Old 01-25-2015, 02:08 PM   #63
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 633
Default

Good general JS information, including mouse-clicks and character codes.


http://forum.cockos.com/showpost.php...37&postcount=9
SaulT is offline   Reply With Quote
Old 02-03-2015, 12:35 AM   #64
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 633
Default

I remembered the parameter smoothing, forgot to put RMS in. This is one way to go about it.

Code:
function RMS_set(ms)
  instance(coeff, icoeff)
(
  coeff = exp(-1/(ms / 1000 * srate));
  icoeff = 1-coeff;
);

function RMS(input)
  instance(rms_s, coeff, icoeff)
(
  rms_s = (rms_s * this.coeff) + (icoeff * input * input);
  sqrt(rms_s);
);
usage

Code:
@init

rms0.RMS_set(100); // set rms0 as a 100 ms RMS

@sample

s0 = rms0.RMS(spl0); // s0 now contains the 100 ms RMS of spl0
SaulT is offline   Reply With Quote
Old 02-15-2015, 12:23 PM   #65
Argitoth
Human being with feelings
 
Argitoth's Avatar
 
Join Date: Feb 2008
Location: Phoenix, AZ
Posts: 1,965
Default

trick for functions with optional parameters by overloading functions, where the overloaded functions use previously declared functions.

Code:
function setcolor(r, g, b) (
    gfx_r = r;
    gfx_g = g;
    gfx_b = b;
);
function setalpha(a) (
    gfx_a = a
);
function setcolor(g) (
    setcolor(g,g,g)
);
function setcolor(g,a) ( //g as in grey
    setcolor(g,g,g);
    setalpha(a);
);
function setcolor(r, g, b, a) (
    setcolor(r,g,b);
    setalpha(a);
);
for easy swapping of variables
Code:
function swap(a*,b*) local(t) (a = t; a = b; b = t);
usage:
a=1;
b=2;
swap(a,b);
now a=2 and b=1


bit twiddling hack to get the power of 2 of an integer, useful for checking trigger buttons

Code:
function bitPow2(a) local(b) (
    b=-1;
    while(a) (
      a = a >> 1;
      b+=1;
    );
    b;
);
2^5 is 32
trigger button #5 is 32
bitPow2(32) returns 5.

this is how to make any Log function, here's how to make Log2.
Code:
@init
log2 = log(2); //establish your log constant

function log2(f) ( log(f)/log2 ); //create your function
__________________
Soundemote - Actively pursuing the advancement of sample library technology
MyReaperPlugin - Easy-to-use cross-platform C++ REAPER extension template

Last edited by Argitoth; 02-18-2015 at 03:05 PM.
Argitoth is offline   Reply With Quote
Old 10-11-2015, 04:31 AM   #66
IXix
Human being with feelings
 
Join Date: Jan 2007
Location: mcr:uk
Posts: 3,018
Default JS Plugin instance tracking

Library to help with managing plugin instances when sharing global memory...

http://forum.cockos.com/showthread.php?t=167427
IXix is offline   Reply With Quote
Old 10-17-2015, 02:03 AM   #67
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Germany
Posts: 1,409
Default Storing Text in variables

encode_string() / decode_string() stores / retrieves four characters of text in a variable that can be assigned to a (invisible) slider and hence be managed by the DAW.

encode_5() and decode_5() handle 20 characters in a very trivial way.

Improvement appreciated.

-Michael


Code:
function encode_string(s) local(c_s, i) (
  i = 0;
  c_s = 0;
  while(
    c_s = c_s << 8;
    c_s = c_s + str_getchar(s, 4-i);  
    i = i+1;
    i < 5;
  );
  c_s;
);

function encode_5(r*, s) (
  r._1 = encode_string(strcpy_substr(#, s, 0, 4));
  r._2 = encode_string(strcpy_substr(#, s, 4, 4));
  r._3 = encode_string(strcpy_substr(#, s, 8, 4));
  r._4 = encode_string(strcpy_substr(#, s, 12, 4));
  r._5 = encode_string(strcpy_substr(#, s, 16, 4));
);

function decode_string(c_s) local (i, c_ss, _) (
  i = 0;
  strcpy (_, "");
  while(
    c_ss = c_s & 0xFF;
    c_s = c_s >> 8;
    c_ss >= 32 ? (
      str_setchar(_, -0.25, c_ss);
        i += 1;
    );  
    (i < 4) & (c_ss >= 32);
  );
  _;
);

function decode_5(r*) (  
  #__ =  decode_string(r._1);
  #__ += decode_string(r._2);
  #__ += decode_string(r._3);
  #__ += decode_string(r._4);
  #__ += decode_string(r._5);
);
Edit: Improved code now using parameters and return results instead of dedicated text variables and using the undocumented (but seemingly perfectly alowwable) "r*" notation for namespace parameters.

Still not happy with the non-local #__ intermediate String variable, though.

-Michael

Last edited by mschnell; 11-05-2015 at 02:37 PM.
mschnell is offline   Reply With Quote
Old 10-17-2015, 02:55 AM   #68
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Germany
Posts: 1,409
Default Paged User Interface

If you need more than some 30 Faders for configuration and/or want to hide the configuration User Interface and display just a Status Window, it makes sense to do a "Paged User Interface".

This can be done by providing multiple JSFXes that communicate via global memory.

As the concept is rather trivial and the necessary code will vary depending on the application, I don't provide code snippets here.

But rather soon I will publish a JSFX-"Application" that uses this concept with a status display plus a dynamic count of configuration pages.

-Michael
mschnell is offline   Reply With Quote
Old 10-17-2015, 03:00 AM   #69
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Germany
Posts: 1,409
Default Where to drop complete JSFXes ?

This sticky forum thread is nice for the purpose the caption suggests, but, as here, the code for multiple purposes is mixed with comment on same, it's only useful for developers that bother to search for snippets that might help. But:

Is there a place on the Cockos Site users can drop complete JSFXes with the appropriate documentation is a structured way so that other uses can find them ?

-Michael
mschnell is offline   Reply With Quote
Old 10-17-2015, 03:15 AM   #70
NextLevel
Human being with feelings
 
Join Date: Dec 2014
Posts: 136
Default

Quote:
Originally Posted by mschnell View Post

Is there a place on the Cockos Site users can drop complete JSFXes with the appropriate documentation is a structured way so that other uses can find them ?

-Michael
Here ya go. http://stash.reaper.fm/
NextLevel is offline   Reply With Quote
Old 10-17-2015, 03:20 AM   #71
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Germany
Posts: 1,409
Default User Interface: simple Text Line Editor

Code:
desc: edit 
//tags: User Interface
//author: mschnell

in_pin:none
in_pin:none
options:want_all_kb

         
    
@init                 

@gfx 60, 30

cc = gfx_getchar();
cc > 1 ? (
  cc >= 32 ? (
    strlen(#s) < 20 ? (
      c = cc;
      #sc = ".";
      str_setchar(#sc, 0, c);
      #s += #sc;
    );  
   ) : cc == 8 ? (                            // Backspace
    strcpy_substr(#s, #s, 0, strlen(#s)-1);
   ) :  cc == 13 ? (                          // Enter: acknowlage this text
    #ss = #s;
    #s = "";    
   ) : (
    #s = #ss;                        // other keys: Use latest acknowlaged Text as Edit Template
  );  
);



gfx_clear=0xC0C0C0; // set clearing to "gray".
gfx_a=1; // alpha 1.0
gfx_setfont(1,"Arial",20,'b');  
gfx_x = 10;
gfx_y = 10;
strlen(#s) == 0 ? (
  gfx_r = 1;
  gfx_g = 0;
  gfx_b = 0;
  gfx_drawstr(#ss);
 ) : (
  gfx_r = 0;
  gfx_g = 0;
  gfx_b = 0;
  gfx_drawstr(#s);
)
mschnell is offline   Reply With Quote
Old 10-17-2015, 03:33 AM   #72
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Germany
Posts: 1,409
Default User Interface: Drawing a "Button"

Drawing a Button with some special functions.

The caption text is automatically sized according to the button dimensions (a very non-perfect algorithm)

The button text color is given in a single variable: just eight colors.

The color of the button is set by gfx_r, gfx_g, gfx_b before calling the function.

-Michael


Code:
function button(x,y,w,h,tc,s) (
  radius1 = 10;
  gfx_roundrect(x,y,w,h,radius1);
  gfx_roundrect(x+1,y+1,w-2,h-2,radius1-2);
  gfx_roundrect(x+2,y+2,w-4,h-4,radius1-3);
  gfx_roundrect(x+3,y+3,w-6,h-6,radius1-4);
  gfx_rect(x+4, y+4, w-6, h-6);
  stack_push(gfx_r);
  stack_push(gfx_g);
  stack_push(gfx_b);
  gfx_r = tc & 1;
  gfx_g = (tc >> 1) & 1;
  gfx_b = (tc >> 2) & 1;
  w > h ? w = h;
  gfx_setfont(1,"Arial",w,'b');  
  gfx_x = x + (w - gfx_texth/2) / 2;
  gfx_y = y + (h - gfx_texth) / 2; 
  gfx_drawstr(s);
  stack_pop(gfx_b);
  stack_pop(gfx_g);
  stack_pop(gfx_r);
);
In a User interface I caught mouse clicks on a button simply by

Code:
mouse_cap == 1 ? (
  m_cap == 0 ? (
    m_cap = 1 ;
    m_x = mouse_x;
    m_y = mouse_y;
  
    (m_x>button_x) && (m_x<button_x+button_width) && 
    (m_y>button_y) && (m_y<button_y+button_height) ? (
     
       // place on-click code here
     
    );
   ); 
 ) : (
  m_cap = 0;
);
If you want to do multiple buttons it would be appropriate to manage an array of button area definitions by some button_create() function and loop though this array.

Maybe an object-like code using namespaces can be done, as well.

edit: improved code using the button text as a parameter.

-Michael

Last edited by mschnell; 10-25-2015 at 03:12 PM.
mschnell is offline   Reply With Quote
Old 10-18-2015, 12:04 AM   #73
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Germany
Posts: 1,409
Default

Quote:
Originally Posted by NextLevel View Post
Thanks !
Of course I will use it.

But I did not find a "short description" that should be visible with each entry so that it would be possible to find anything here.

-Michael
mschnell is offline   Reply With Quote
Old 10-18-2015, 01:46 AM   #74
NextLevel
Human being with feelings
 
Join Date: Dec 2014
Posts: 136
Default

The description is there. Once you click on a file it takes you to another page with a description and download link. Unfortunately not everyone enters a descript of what they've posted.
NextLevel is offline   Reply With Quote
Old 10-18-2015, 01:50 PM   #75
mschnell
Human being with feelings
 
mschnell's Avatar
 
Join Date: Jun 2013
Location: Germany
Posts: 1,409
Default

Ah, now I see...

The first few entries I checked did not show a description, Though

-Michael
mschnell is offline   Reply With Quote
Old 10-19-2015, 05:48 AM   #76
derek.john.evans
Human being with feelings
 
derek.john.evans's Avatar
 
Join Date: Feb 2011
Location: Adelaide, South Australia
Posts: 217
Default

EDIT: Ive written an improved heap manager which is available from here:
http://stash.reaper.fm/v/25527/Heman...%20Manager.zip

Here is my older memory manager code. Managed memory starts from block 4. Largest memory block allowed is 1 Gig. I'm now using the Heman code available above.

TIP: Ignore the heap functions, and just use the standard malloc(), calloc(), realloc() & free() functions.

Code:
@init

// Helper function to ensure a valid memory size value.
function size_t(x) global()
(
  max(floor(x), 0);
);

// Sets the starting offset for heap memory. Also resets heap link list.
function heap.min(min) global()
(
  // Heap min is hardcoded to block 4.
  this.min = this.max = max(size_t(min), 4 << 16);
  this.min[] = 0;
);

function heap.max(max) global()
(
  this.max = max(this.min, size_t(max));
);

heap.min(0);

// Returns the max heap used. Includes memory that was freed.
function heap.size() global()
(
  this.max - this.min;
);

// Checks the heap block is valid. Not 100% perfect, but the best we can achieve.
function heap.check(block) global()
(
  block >= this.min && (block[] <= -1 || block[] >= 1);
);

// Returns true if heap block is free.
function heap.isfree(block) global()
(
  this.heap.check(block) && block[] < 0;
);

// Merges free blocks into one free block.
function heap.merge(block) global() local(ptr, size)
(
  this.heap.isfree(block) ? (
    size = 0; ptr = block;
    while (this.heap.isfree(ptr)) ( size += ptr[]; ptr += abs(ptr[]); );
    block[] = size;
  );
);

/*
Checks if block is avaliable to store a given size. Also handles merging
of freed blocks after given block.
*/
function heap.avail(block, size) global()
(
  !this.heap.check(block) ? block[] = -0x80000000; // 1 gig should be more than enough.
  this.heap.merge(block);
  size <= -block[];
);

// Allocates a block of memory. Does not clear the new memory.
function malloc(size) global(heap*) local(block)
(
  size = size_t(size) + 1;
  size >= 1 && size < 0x80000000 ? (
    block = heap.min;
    while (!heap.avail(block, size)) ( block += abs(block[]); );
    size != -block[] ? block[size] = block[] + size;
    block[] = size;
    heap.max(max(heap.max, block + size));
    block + 1;
  ) : 0;
);

// Same as malloc, but clears the memory to zero. (This is a non-standard helper)
function calloc(size) global()
(
  size = size_t(size);
  memset(malloc(size), 0, size);
);

// Same as malloc, but clears the memory to zero. 
function calloc(count, size) global()
(
  calloc(size_t(count) * size_t(size));
);

// Returns TRUE if memory location is valid.
function mcheck(memory) global(heap*)
(
  heap.check(memory - 1);
);

// Returns the size of given memory location.
function _msize(memory) global()
(
  mcheck(memory) && memory[-1] > 0 ? memory[-1] - 1 : 0;
);

// Same as _msize(). Mac name alias.
function malloc_size(memory) global()
(
  _msize(memory);
);

// Frees a memory block.
function free(memory) global()
(
  mcheck(memory) ? memory[-1] = -abs(memory[-1]);
  0;
);

// Realloc a memory block, with option to clear new memory.
function realloc(memory, size, clear) global() local(newmem)
(
  size = size_t(size);
  size == _msize(memory) ? (
    memory;
  ) : (
    newmem = clear ? calloc(size) : malloc(size);
    memcpy(newmem, memory, min(size, _msize(memory)));
    free(memory);
    newmem;
  );
);

// Traditional realloc. New memory is not cleared.
function realloc(m, n) global()
(
  realloc(m, n, 0);
);
Just a little info about JS memory. JS memory is allocated in pages of (1 << 16) items. ie: 65536 doubles, which is 512kb of memory. The above memory manager starts on page 4, which gives 2 meg for normal memory usage.

Sing out if you find a bug. I have done a lot of testing, but, more testing is always good.
__________________
http://wascal.net/music/

Last edited by derek.john.evans; 11-05-2015 at 10:58 AM.
derek.john.evans is offline   Reply With Quote
Old 11-05-2015, 09:54 AM   #77
mrlimbic
Human being with feelings
 
mrlimbic's Avatar
 
Join Date: Nov 2009
Location: UK
Posts: 363
Default

Anyone know the maths to calculate a rolling value for the width of the stereo field?
__________________
Mac OS X 10.9.x, Motu Ultralite, Reaper, FCP X.
http://vordio.net
http://twitter.com/vordio
mrlimbic is offline   Reply With Quote
Old 11-05-2015, 10:51 AM   #78
derek.john.evans
Human being with feelings
 
derek.john.evans's Avatar
 
Join Date: Feb 2011
Location: Adelaide, South Australia
Posts: 217
Default

Quote:
Originally Posted by mrlimbic View Post
Anyone know the maths to calculate a rolling value for the width of the stereo field?
Mmm. This could be one of those deceptively simple questions.

Do you mean RMS or DB or peak levels over time? It should be the same as what is used in DB level displays or compressors, just with the side being used.

vumeter has code to calculate DB over time. dynamics_meter contains code for 3 types of levels over time. Depends on how complex or "accurate" you need it.

Here is some basic code using a decay style level. Or, you can implement a window style level, which is just calculating the level of the average over a time period (window).

Code:
desc: Mid-Side Levels

@init

sc = 6 / log(2);
response = 0.5;

@sample

// Calculate the DB of mid/side
mid_db = max(log(abs(spl0 + spl1)) * sc, -80);
sid_db = max(log(abs(spl0 - spl1)) * sc, -80);

// Or, calculate the abs level of mid/side
mid_le1 = abs(spl0 + spl1);
sid_le1 = abs(spl0 - spl1);

// Or, calculate the sqrt of abs level of mid/side. (I think this might be RMS)
mid_le2 = sqrt(abs(spl0 + spl1));
sid_le2 = sqrt(abs(spl0 - spl1));

// You can then use a response formular to soften the level changes.
// This is the same type of code used in a compressor.
mid_level += (mid_db - mid_level) * response;
sid_level += (sid_db - sid_level) * response;

@gfx

// Some code to display two DB bars. Needs to be adjusted for other level types.
gfx_r = gfx_g = gfx_b = gfx_a = 1;
gfx_x = 0; gfx_y = 10; gfx_rectto(80 + mid_level, gfx_y + 16);
gfx_x = 0; gfx_y = 40; gfx_rectto(80 + sid_level, gfx_y + 16);
__________________
http://wascal.net/music/
derek.john.evans is offline   Reply With Quote
Old 11-05-2015, 11:01 AM   #79
mrlimbic
Human being with feelings
 
mrlimbic's Avatar
 
Join Date: Nov 2009
Location: UK
Posts: 363
Default

Quote:
Originally Posted by derek.john.evans View Post
Mmm. This could be one of those deceptively simple questions.

Do you mean RMS or DB or peak levels over time? It should be the same as what is used in DB level displays or compressors, just with the side being used.

vumeter has code to calculate DB over time. dynamics_meter contains code for 3 types of levels over time. Depends on how complex or "accurate" you need it.

Here is some basic code using a decay style level. Or, you can implement a window style level, which is just calculating the level of the average over a time period (window).
Thanks. I suspect RMS will be more useful. The idea is to create an automation envelope from the stereo width of one audio item and apply that to pan on another item.
__________________
Mac OS X 10.9.x, Motu Ultralite, Reaper, FCP X.
http://vordio.net
http://twitter.com/vordio
mrlimbic is offline   Reply With Quote
Old 11-05-2015, 11:17 AM   #80
derek.john.evans
Human being with feelings
 
derek.john.evans's Avatar
 
Join Date: Feb 2011
Location: Adelaide, South Australia
Posts: 217
Default

Quote:
Originally Posted by mrlimbic View Post
Thanks. I suspect RMS will be more useful. The idea is to create an automation envelope from the stereo width of one audio item and apply that to pan on another item.
Sounds interesting. Have you set up the effect using current JS/VST effects?

Sounds like some kinda stereo field ducking/dodging effect. Maybe start a new thread and document your idea.
__________________
http://wascal.net/music/
derek.john.evans 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 04:55 AM.


Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.