|
|
|
03-24-2011, 05:58 PM
|
#41
|
Human being with feelings
Join Date: May 2009
Posts: 1,265
|
Quote:
Originally Posted by caseyjames
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.
|
|
|
03-24-2011, 06:53 PM
|
#42
|
Human being with feelings
Join Date: Jan 2011
Location: Finger Lakes, NY
Posts: 54
|
Doesn't file_mem() read from any open file? I'm just asking; the spec implies it.
|
|
|
03-24-2011, 08:23 PM
|
#43
|
Human being with feelings
Join Date: May 2009
Posts: 1,265
|
Quote:
Originally Posted by groundhum
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.
|
|
|
03-24-2011, 08:43 PM
|
#44
|
Human being with feelings
Join Date: Jul 2009
Posts: 633
|
Has there been any mention of a JS 2 anywhere on the horizon?
|
|
|
05-12-2011, 03:24 AM
|
#45
|
Human being with feelings
Join Date: Sep 2009
Location: Middle of nowhere (where the cheese comes from)
Posts: 483
|
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.
|
|
|
09-23-2011, 03:21 AM
|
#46
|
Human being with feelings
Join Date: May 2006
Location: Surrey, UK
Posts: 19,681
|
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 ...
|
|
|
01-14-2013, 06:16 AM
|
#47
|
Human being with feelings
Join Date: Jan 2007
Location: mcr:uk
Posts: 3,891
|
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
|
|
|
04-25-2013, 11:40 PM
|
#48
|
Human being with feelings
Join Date: Jul 2006
Posts: 626
|
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
|
|
|
05-26-2013, 12:32 PM
|
#49
|
Administrator
Join Date: Jan 2005
Location: NYC
Posts: 15,746
|
Quote:
Originally Posted by bang
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.
|
|
|
05-26-2013, 01:30 PM
|
#50
|
Human being with feelings
Join Date: Jul 2006
Posts: 626
|
Quote:
Originally Posted by Justin
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
|
|
|
10-10-2013, 11:49 PM
|
#51
|
Human being with feelings
Join Date: Oct 2010
Posts: 83
|
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
|
|
|
10-17-2013, 01:15 PM
|
#52
|
Human being with feelings
Join Date: Jul 2007
Posts: 1,891
|
Quote:
Originally Posted by liteon
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.
|
|
|
10-20-2013, 04:46 AM
|
#53
|
Human being with feelings
Join Date: Jan 2013
Location: United Kingdom
Posts: 28
|
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.
|
|
|
02-04-2014, 11:25 AM
|
#55
|
Human being with feelings
Join Date: Mar 2007
Location: I'm in a barn
Posts: 4,467
|
Quote:
Originally Posted by Argitoth
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
|
|
|
05-30-2014, 10:36 AM
|
#56
|
Human being with feelings
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
|
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 - Home of the chaosfly and pretty oscilloscope.
MyReaperPlugin - Easy-to-use cross-platform C++ REAPER extension template
|
|
|
06-05-2014, 08:52 PM
|
#57
|
Human being with feelings
Join Date: Oct 2013
Location: Seattle, WA
Posts: 876
|
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.
|
|
|
06-11-2014, 01:24 PM
|
#58
|
Human being with feelings
Join Date: Oct 2013
Location: Seattle, WA
Posts: 876
|
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
|
|
|
09-17-2014, 10:55 AM
|
#59
|
Human being with feelings
Join Date: Jul 2014
Location: Là bas les huîtres (FR)
Posts: 424
|
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);
);
);
|
|
|
10-09-2014, 10:20 PM
|
#60
|
Human being with feelings
Join Date: Oct 2013
Location: Seattle, WA
Posts: 876
|
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.
|
|
|
02-03-2015, 12:35 AM
|
#63
|
Human being with feelings
Join Date: Oct 2013
Location: Seattle, WA
Posts: 876
|
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
|
|
|
02-15-2015, 12:23 PM
|
#64
|
Human being with feelings
Join Date: Feb 2008
Location: Mesa, AZ
Posts: 2,057
|
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 - Home of the chaosfly and pretty oscilloscope.
MyReaperPlugin - Easy-to-use cross-platform C++ REAPER extension template
Last edited by Argitoth; 02-18-2015 at 03:05 PM.
|
|
|
10-11-2015, 04:31 AM
|
#65
|
Human being with feelings
Join Date: Jan 2007
Location: mcr:uk
Posts: 3,891
|
JS Plugin instance tracking
Library to help with managing plugin instances when sharing global memory...
http://forum.cockos.com/showthread.php?t=167427
|
|
|
10-17-2015, 02:03 AM
|
#66
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
|
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.
|
|
|
10-17-2015, 02:55 AM
|
#67
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
|
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
|
|
|
10-17-2015, 03:00 AM
|
#68
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
|
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
|
|
|
10-17-2015, 03:15 AM
|
#69
|
Human being with feelings
Join Date: Dec 2014
Posts: 417
|
Quote:
Originally Posted by mschnell
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. https://stash.reaper.fm/
|
|
|
10-17-2015, 03:20 AM
|
#70
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
|
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);
)
|
|
|
10-17-2015, 03:33 AM
|
#71
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
|
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.
|
|
|
10-18-2015, 12:04 AM
|
#72
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
|
Quote:
Originally Posted by NextLevel
|
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
|
|
|
10-18-2015, 01:46 AM
|
#73
|
Human being with feelings
Join Date: Dec 2014
Posts: 417
|
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.
|
|
|
10-18-2015, 01:50 PM
|
#74
|
Human being with feelings
Join Date: Jun 2013
Location: Krefeld, Germany
Posts: 14,785
|
Ah, now I see...
The first few entries I checked did not show a description, Though
-Michael
|
|
|
10-19-2015, 05:48 AM
|
#75
|
Human being with feelings
Join Date: Feb 2011
Location: Adelaide, South Australia
Posts: 217
|
EDIT: Ive written an improved heap manager which is available from here:
https://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.
Last edited by derek.john.evans; 11-05-2015 at 10:58 AM.
|
|
|
11-05-2015, 09:54 AM
|
#76
|
Human being with feelings
Join Date: Nov 2009
Location: UK
Posts: 669
|
Anyone know the maths to calculate a rolling value for the width of the stereo field?
|
|
|
11-05-2015, 10:51 AM
|
#77
|
Human being with feelings
Join Date: Feb 2011
Location: Adelaide, South Australia
Posts: 217
|
Quote:
Originally Posted by mrlimbic
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);
|
|
|
11-05-2015, 11:01 AM
|
#78
|
Human being with feelings
Join Date: Nov 2009
Location: UK
Posts: 669
|
Quote:
Originally Posted by derek.john.evans
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.
|
|
|
11-05-2015, 11:17 AM
|
#79
|
Human being with feelings
Join Date: Feb 2011
Location: Adelaide, South Australia
Posts: 217
|
Quote:
Originally Posted by mrlimbic
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.
|
|
|
11-05-2015, 12:02 PM
|
#80
|
Human being with feelings
Join Date: Nov 2009
Location: UK
Posts: 669
|
Quote:
Originally Posted by derek.john.evans
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.
|
Yes that's it. It is like ducking but for panning instead of volume (pucking?!!)
It seems I could do it as a multichannel effect (like ducking) or via envelope generation and stick the envelope to the pan parameter of another item.
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 04:07 AM.
|