Old 12-20-2019, 05:11 PM   #1
nofish
Human being with feelings
 
nofish's Avatar
 
Join Date: Oct 2007
Location: home is where the heart is
Posts: 9,275
Default [Request] calibrated embeddable VU meter (DONE)

edit:
Done (see below), thanks ashcat_lt.

Reaper comes with the Liteon VU meter JSFX which is embedable in TCP/MCP but it doesn't seem to be calibrated/calibrateable to -18 = 0 VU (my preferred use case).



Also, maybe I used the wrong settings, but I couldn't quite get the meter ballistics matching other VU plugins.

Anyone could modify it (or make one)?

Last edited by nofish; 01-05-2020 at 07:00 PM.
nofish is offline   Reply With Quote
Old 01-05-2020, 09:26 AM   #2
ashcat_lt
Human being with feelings
 
Join Date: Dec 2012
Posts: 4,524
Default

Posted in the other thread a hack that makes it really rms, nice and smooth, and with both calibration and audio throughput gain adjustment.

https://forum.cockos.com/showpost.ph...0&postcount=18
ashcat_lt is offline   Reply With Quote
Old 01-05-2020, 10:09 AM   #3
nofish
Human being with feelings
 
nofish's Avatar
 
Join Date: Oct 2007
Location: home is where the heart is
Posts: 9,275
Default

Ballistic are very smooth now indeed and matching my other VUs, nice work, thank you ashcat.

I did however notice the reference level differs by 3 dB, but from what I know, both are correct, no? (depending on whether taking a sine or square wave as reference or something.)

nofish is offline   Reply With Quote
Old 01-05-2020, 10:25 AM   #4
ashcat_lt
Human being with feelings
 
Join Date: Dec 2012
Posts: 4,524
Default

I never really got that. RMS is RMS. It just turns out that square wave RMS is equal to the (rectified) peak level. Basically that meter is telling you what the peak level of a sine wave with that rms level would be. Or something. Seems silly, but there’s plenty of room for adjustment on the calibration slider.

I’m gonna play with it and add a couple options a little later.
ashcat_lt is offline   Reply With Quote
Old 01-05-2020, 01:08 PM   #5
nofish
Human being with feelings
 
nofish's Avatar
 
Join Date: Oct 2007
Location: home is where the heart is
Posts: 9,275
Default

Another thing I noticed, your version doesn't seem to embed in MCP anymore (which would actually be my intended use case).

nofish is offline   Reply With Quote
Old 01-05-2020, 04:27 PM   #6
ashcat_lt
Human being with feelings
 
Join Date: Dec 2012
Posts: 4,524
Default

Well shit yeah that really was the whole point. I haven't upgraded yet so can't test that. I wonder if there's something changed in the code to make it work? Any chance you could send me the code from your version?
ashcat_lt is offline   Reply With Quote
Old 01-05-2020, 04:44 PM   #7
ashcat_lt
Human being with feelings
 
Join Date: Dec 2012
Posts: 4,524
Default

But anyway, I made a "deluxe" version in case you want to check it out.


It has two new detector modes which change the ballistics pretty drastically. One is an average of rectified sample values rather than RMS and the other is slew rate limited rather than integrated. IDK which is most correct for actualy VU, but you can play around and see which feels best for you.


It also has an AutoGain feature. Set it to "1 = grab" and it will figure out how much gain it needs to hit the 0dbVU as set by the calibrate slider and then when you put it to "0 = run", it sets the gain slider to that. It works much better for more steady-state material. Can be weird with real percussive inputs.


Hopefully we can figure out the issue with the embedding.


Code:
desc: LT VU Meter Deluxe (Summed)
//tags: analysis visualization metering
//author: Liteon hacked by ashcat_lt 

slider1:300<0,1000,1>Meter Time(ms)
slider2:0<0,2,1{Left,Sum,Maximum}>Channel 
slider3:-18<-24,-9,0.1>Calibrate (0VU = xdbFS)
slider4:0<-24,24,0.1>Gain (db)
slider5:0<0,2,1{RMS,Average,Slew}>Detector
slider6:0<0,1,1>AutoGain (0=run, 1=grab)

in_pin:left input
in_pin:right input
out_pin:left output
out_pin:right output


@init
//rp - right channel y pading, r - radius
rp = 261;
r = 200;
yl = yr = ylt = yrt = 74;
xl = xr = 66;
ms  = slider1;
cs = 0;


function ratiotodb (x)
( x = 20 * log10 (x););

function dbtoratio (x)
( x = 10 ^(x/20););


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


function set_logistic_limit (x)
  instance (limit, scale)
  (this.limit = x;
   this.scale = 1/x;);

function slew_set(rms_ms, calib)
  instance(slew)
(
  this.slew = (1000 * calib) / (srate * rms_ms);
  this.set_logistic_limit (this.slew);
);

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

function average(input)
  instance(ave_s, coeff, icoeff)
(
  ave_s = (ave_s * coeff) + (icoeff * abs(input));
);


function logistic (x)
  instance(limit)
  (log_input = x * this.scale;
   log_curve = 1 / (1 + exp (-2 * log_input));
   log_shifted = 2 * log_curve - 1;
   log_outuput = this.limit * log_shifted;);

function slew(input)
  instance(slew_s, slew)
(
  input = abs(input);
  diff = input - slew_s;
  slew_s += this.logistic (diff);
);



@slider
rms_ms = slider1;
rms0.RMS_set(rms_ms);
calibrate = dbtoratio (slider3);
rms0.slew_set (rms_ms, calibrate);
gain = dbtoratio (slider4);




@block

  rmsl_gfx = ratiotodb(rms_in);
  slider6 == 1 ? 
    (gaindiff = min((slider3 - (rmsl_gfx - slider4)), 24)):
    (last6 == 1 ? slider4 = gaindiff);
  last6 = slider6;
  
  ool = min (6, max (-60, (rmsl_gfx  - slider3)));
  
  //get x from exp scale
  xlt = floor(exp(log(1.055)*2.1*ool)*285);
  
  //get y from x and radius - r     
  l=sqrt(sqr(r)+sqr(212-xlt));
  h=((l-r)*r/l);
  m=sqrt(sqr(l-r)-sqr(h));
  ylt=35+h;
  xlt < 212 ? xlt=xlt+m : xlt=xlt-m;
  
  //update x,y,out
  old_xl < xlt ? (xl = min(max(xlt,66),375); yl = ylt; );
  bscnt = pvl = pvr = 0;
;
//limit x
xl = min(max(xl,66),375);

olt = ratiotodb(peaksample);

@sample
spl0 *= gain;
spl1 *= gain;

slider2 == 0 ?
  (rms_in_0 = spl0;);
slider2 == 1 ?
  (rms_in_0 = (spl0 + spl1)/2) ;
slider2 == 2 ?
  (rms_in_0 = max(spl0, spl1)) ;

slider5 == 0 ? 
  (rms_in = rms0.RMS(rms_in_0));
slider5 == 1 ? 
  (rms_in = rms0.average(rms_in_0));
slider5 == 2 ? 
  (rms_in = rms0.slew(rms_in_0));  


peaksample = max (peaksample, rms_in_0);

@gfx 425 191
//**************************************************************** left
//red scale
gfx_r =  gfx_a = 1;
gfx_g = gfx_b =0;
gfx_x = 283;
gfx_y = 28;
gfx_drawnumber(0,0);
gfx_x = 370;
gfx_y = 55;
gfx_drawnumber(3,0);
gfx_x = 405;
gfx_y = 57;
gfx_drawchar($'+');
gfx_x = 283;
gfx_y = 38;
gfx_lineto(269,76,0.5);
gfx_x = 311;
gfx_y = 43;
gfx_lineto(293,80,1);
gfx_x = 342;
gfx_y = 51;
gfx_lineto(318,85,1);
gfx_x = 370;
gfx_y = 65;
gfx_lineto(344,93,0.5);

//white scale
gfx_r = gfx_g = gfx_b = 1;
gfx_a = 1;
gfx_x = 12;
gfx_y = 60;
gfx_drawchar($'-');
gfx_x = 41;
gfx_y = 53;
gfx_drawnumber(20,0);
gfx_x = 80;
gfx_y = 37;
gfx_drawnumber(10,0);
gfx_x = 125;
gfx_y = 29;
gfx_drawnumber(7,0);
gfx_x = 157;
gfx_y = 25;
gfx_drawnumber(5,0);
gfx_x = 198;
gfx_y = 24;
gfx_drawnumber(3,0);
gfx_x = 56;
gfx_y = 63;
gfx_lineto(82,92,0.5);
gfx_x = 95;
gfx_y = 47;
gfx_lineto(119,82,0.5);
gfx_x = 130;
gfx_y = 39;
gfx_lineto(146,77,0.5);
gfx_x = 145;
gfx_y = 37;
gfx_lineto(158,75,1);
gfx_x = 162;
gfx_y = 35;
gfx_lineto(171,74,0.5);
gfx_x = 180;
gfx_y = 34;
gfx_lineto(187,74,1);
gfx_x = 202;
gfx_y = 34;
gfx_lineto(204,72,0.5);
gfx_x = 227;
gfx_y = 34;
gfx_lineto(223,73,1);
gfx_x = 253;
gfx_y = 35;
gfx_lineto(245,73,1);

//vu box border
gfx_r = gfx_g = gfx_b = 0.75;
gfx_a = 1;
gfx_x = 198;
gfx_y = 108;
gfx_rectto(241,139);
//vu box
gfx_a = 1;
gfx_r = 0.5;
gfx_g = gfx_b = 0.1;
gfx_x = 200;
gfx_y = 110;
gfx_rectto(239,137);
//vu text
gfx_r = gfx_g = gfx_b = 0.85;
gfx_a = 1;
gfx_x = 212;
gfx_y = 120;
gfx_drawchar($'V');
gfx_drawchar($'U');

//meter
olt > 0 ? (
  gfx_r = 1; 
  gfx_g = gfx_b = 0;
) : (
  gfx_r = gfx_g = gfx_b = 1;
);
gfx_a = 1;
gfx_x = 212;
gfx_y = 236;
gfx_lineto(xl,yl,1);
gfx_x = 211;
gfx_y = 236;
gfx_lineto(xl-1,yl,1);
gfx_x = 210;
gfx_y = 236;
gfx_lineto(xl-2,yl,1);

//big border
gfx_r = gfx_g = gfx_b = 0.55;
gfx_a = 1;
gfx_x = 0;
gfx_y = 179;
gfx_rectto(425,180);
//big box 1
gfx_r = 0.1;
gfx_g = 0.2; 
gfx_b = 0.39;
gfx_a = 1;
gfx_x = 0;
gfx_y = 180;
gfx_rectto(425,261);
//big box 2 
gfx_r = gfx_g = gfx_b = 1;
gfx_a = 0.1;
gfx_x = 0;
gfx_y = 180;
gfx_rectto(425,190);
//big box 3
gfx_r = gfx_g = gfx_b = 0;
gfx_a = 0.3;
gfx_x = 0;
gfx_y = 245;
gfx_rectto(425,261);
//ch textbox1
gfx_r = gfx_g = gfx_b = 0;
gfx_a = 1;
gfx_x = 350;
gfx_y = 210;
gfx_rectto(415,227);
//ch textbox2
gfx_r = gfx_g = gfx_b = 0;
gfx_a = 1;
gfx_x = 250;
gfx_y = 210;
gfx_rectto(315,227);
//ch text
gfx_r = gfx_g = gfx_b = 1;
gfx_a = 1;
gfx_x = 20;
gfx_y = 215;
gfx_drawchar($'L');
gfx_drawchar($'+');
gfx_drawchar($'R');
gfx_x = 215;
slider5 == 0 ?
(gfx_drawchar($'R');
 gfx_drawchar($'M');
 gfx_drawchar($'S'););
slider5 == 1 ?
(gfx_drawchar($'A');
 gfx_drawchar($'V');
 gfx_drawchar($'G'););
slider5 == 2 ?
(gfx_drawchar($'S');
 gfx_drawchar($'L');
 gfx_drawchar($'W'););

gfx_x = 333;
gfx_drawchar($'P');
gfx_x = 255;
rmsl_gfx > -300 ? (
  rmsl_gfx > 0.0 ? (
    gfx_r = 1;
    gfx_g = gfx_b = 0;
    gfx_drawchar($'+');
  );
  gfx_drawnumber(rmsl_gfx,2);
) : (
  gfx_drawchar($'-');
  gfx_drawchar($'I');
  gfx_drawchar($'N');
  gfx_drawchar($'F');
);
gfx_r = 1;
gfx_g = gfx_b = 1;
gfx_x = 355;
olt > -300 ? (
  olt >= 0.0 ? (
    gfx_drawchar($'+');
    gfx_r = 1;
    gfx_g = gfx_b = 0;  
  );
  gfx_drawnumber(olt,2);
) : (
  gfx_drawchar($'-');
  gfx_drawchar($'I');
  gfx_drawchar($'N');
  gfx_drawchar($'F');
);
ashcat_lt is offline   Reply With Quote
Old 01-05-2020, 06:16 PM   #8
nofish
Human being with feelings
 
nofish's Avatar
 
Join Date: Oct 2007
Location: home is where the heart is
Posts: 9,275
Default

Quote:
Originally Posted by ashcat_lt View Post
Any chance you could send me the code from your version?
That's the code for the Liteon VU meter that comes with Reaper (which was modified by the Reaper devs to be embedable afaik).

Code:
// (C) 2008-2009, Lubomir I. Ivanov

// NO WARRANTY IS GRANTED. THIS PLUG-IN IS PROVIDED ON AN "AS IS" BASIS, WITHOUT
// WARRANTY OF ANY KIND. NO LIABILITY IS GRANTED, INCLUDING, BUT NOT LIMITED TO,
// ANY DIRECT OR INDIRECT,  SPECIAL,  INCIDENTAL OR CONSEQUENTIAL DAMAGE ARISING
// OUT OF  THE  USE  OR INABILITY  TO  USE  THIS PLUG-IN,  COMPUTER FAILTURE  OF
// MALFUNCTION INCLUDED.  THE USE OF THE SOURCE CODE,  EITHER  PARTIALLY  OR  IN
// TOTAL, IS ONLY GRANTED,  IF USED IN THE SENSE OF THE AUTHOR'S INTENTION,  AND
// USED WITH ACKNOWLEDGEMENT OF THE AUTHOR. FURTHERMORE IS THIS PLUG-IN A  THIRD
// PARTY CONTRIBUTION,  EVEN IF INCLUDED IN REAPER(TM),  COCKOS INCORPORATED  OR
// ITS AFFILIATES HAVE NOTHING TO DO WITH IT.  LAST BUT NOT LEAST, BY USING THIS
// PLUG-IN YOU RELINQUISH YOUR CLAIM TO SUE IT'S AUTHOR, AS WELL AS THE CLAIM TO
// ENTRUST SOMEBODY ELSE WITH DOING SO.
// 
// Released under GPL:
// <http://www.gnu.org/licenses/>.

//******************************************************************************
//References: cockos, wiki, math books
//******************************************************************************

desc: VU Meter (Summed)
//tags: analysis visualization metering
//author: Liteon

slider1:50<1,300,1>Response (ms)
slider2:5<1,10,0.1>Release (Slow/Fast)

in_pin:left input
in_pin:right input
out_pin:none

@init
//st - sample time, sc - db scale, rp - right channel y pading, r - radius
sc = 6/log(2);
rp = 261;
r = 200;
yl = yr = ylt = yrt = 74;
xl = xr = 66;
ms  = slider1;
cs = 0;
suml = sumr = 0;
rms_i = 0;
i_max = 36;

@slider
rel = slider2;
ms = slider1;
st = ms*srate/1000;
hold = (0.001*ms*srate);
cs = 0;
suml = sumr = 0;

@block
rmsl = floor(sc*log(sqrt(suml/cs))*100)/100;

ab1 = log(sqrt(suml/cs));
ab2 = sqrt(suml/cs);

rms_i == i_max ? (
  rmsl_gfx = rmsl;
  rms_i = 0;
);
rms_i += 1;

bscnt > st ? (

  ool = log(pvl)*sc;
  
  //get x from exp scale
  xlt = floor(exp(log(1.055)*2.1*ool)*285);
  
  //get y from x and radius - r     
  l=sqrt(sqr(r)+sqr(212-xlt));
  h=((l-r)*r/l);
  m=sqrt(sqr(l-r)-sqr(h));
  ylt=35+h;
  xlt < 212 ? xlt=xlt+m : xlt=xlt-m;
  
  //update x,y,out
  old_xl < xlt ? (xl = min(max(xlt,66),375); yl = ylt; olt = ool;);
  bscnt = pvl = pvr = 0;
);

old_xl = xl;

bscnt += samplesblock;

//indicator fall-back
fallback = rel/2*samplesblock/1024;
fbi_l = exp(xl/512)*fallback;
xl > 66 ? xl -= fbi_l;

//limit x
xl = min(max(xl,66),375);

//get y after fall-back
yl=35;
l=sqrt(sqr(r)+sqr(212-xl));
h=((l-r)*r/l);
yl=floor(yl+h);

@sample
spl0 *= 7.943282347242816;
spl1 *= 7.943282347242816;
pvl = max(pvl,abs((spl0+spl1)/2));
cs == hold ? (
cs = 0;
suml = 0;
) : (
cs += 1;
suml += sqr(abs((spl0+spl1)/2));
);

@gfx 425 240

// override drawing functions for graphical window scaling
gsc = min(gfx_w/425,gfx_h/240); igsc = 1.0/gsc;
gxo = max(0,  gfx_w/2 - gfx_h*425/240/2);
function gfx_lineto(x,y,aa) ( gfx_x*=gsc; gfx_y*=gsc; gfx_x+=gxo; gfx_lineto(x*gsc+gxo,y*gsc,aa); gfx_x-=gxo; gfx_x*=igsc; gfx_y*=igsc; );
function gfx_rectto(x,y)(gfx_x*=gsc; gfx_y*=gsc; gfx_x+=gxo; gsc>.5 ? gfx_rectto(x*gsc+gxo,y*gsc); gfx_x-=gxo;  gfx_x*=igsc; gfx_y*=igsc;);
function gfx_drawnumber(y,x) (
  gsc>.5 ? (
    gsc<.7 && x>1 ? x=1;
    gfx_x*=gsc; gfx_y*=gsc; gfx_x+=gxo; gfx_drawnumber(y,x); gfx_x-=gxo;  gfx_x*=igsc; gfx_y*=igsc; 
  );
);
function gfx_drawchar(x) ( gfx_x*=gsc; gfx_y*=gsc; gfx_x+=gxo; gsc>.5 ? gfx_drawchar(x); gfx_x-=gxo; gfx_x*=igsc; gfx_y*=igsc; );


//**************************************************************** left
//red scale
gfx_r =  gfx_a = 1;
gfx_g = gfx_b =0;
gfx_x = 283;
gfx_y = 28;
gfx_drawnumber(0,0);
gfx_x = 370;
gfx_y = 55;
gfx_drawnumber(3,0);
gfx_x = 405;
gfx_y = 57;
gfx_drawchar($'+');
gfx_x = 283;
gfx_y = 38;
gfx_lineto(269,76,0.5);
gfx_x = 311;
gfx_y = 43;
gfx_lineto(293,80,1);
gfx_x = 342;
gfx_y = 51;
gfx_lineto(318,85,1);
gfx_x = 370;
gfx_y = 65;
gfx_lineto(344,93,0.5);

//white scale
gfx_r = gfx_g = gfx_b = 1;
gfx_a = 1;
gfx_x = 12;
gfx_y = 60;
gfx_drawchar($'-');
gfx_x = 41;
gfx_y = 53;
gfx_drawnumber(20,0);
gfx_x = 80;
gfx_y = 37;
gfx_drawnumber(10,0);
gfx_x = 125;
gfx_y = 29;
gfx_drawnumber(7,0);
gfx_x = 157;
gfx_y = 25;
gfx_drawnumber(5,0);
gfx_x = 198;
gfx_y = 24;
gfx_drawnumber(3,0);
gfx_x = 56;
gfx_y = 63;
gfx_lineto(82,92,0.5);
gfx_x = 95;
gfx_y = 47;
gfx_lineto(119,82,0.5);
gfx_x = 130;
gfx_y = 39;
gfx_lineto(146,77,0.5);
gfx_x = 145;
gfx_y = 37;
gfx_lineto(158,75,1);
gfx_x = 162;
gfx_y = 35;
gfx_lineto(171,74,0.5);
gfx_x = 180;
gfx_y = 34;
gfx_lineto(187,74,1);
gfx_x = 202;
gfx_y = 34;
gfx_lineto(204,72,0.5);
gfx_x = 227;
gfx_y = 34;
gfx_lineto(223,73,1);
gfx_x = 253;
gfx_y = 35;
gfx_lineto(245,73,1);

//vu box border
gfx_r = gfx_g = gfx_b = 0.75;
gfx_a = 1;
gfx_x = 198;
gfx_y = 108;
gfx_rectto(241,139);
//vu box
gfx_a = 1;
gfx_r = 0.5;
gfx_g = gfx_b = 0.1;
gfx_x = 200;
gfx_y = 110;
gfx_rectto(239,137);
//vu text
gfx_r = gfx_g = gfx_b = 0.85;
gfx_a = 1;
gfx_x = 212;
gfx_y = 120;
gfx_drawchar($'V');
gfx_drawchar($'U');

//meter
olt > 0 ? (
  gfx_r = 1; 
  gfx_g = gfx_b = 0;
) : (
  gfx_r = gfx_g = gfx_b = 1;
);
gfx_a = 1;
gfx_x = 212;
gfx_y = 236;
gfx_lineto(xl,yl,1);
gfx_x = 211;
gfx_y = 236;
gfx_lineto(xl-1,yl,1);
gfx_x = 210;
gfx_y = 236;
gfx_lineto(xl-2,yl,1);

//big border
gfx_r = gfx_g = gfx_b = 0.55;
gfx_a = 1;
gfx_x = 0;
gfx_y = 179;
gfx_rectto(425,180);
//big box 1
gfx_r = 0.1;
gfx_g = 0.2; 
gfx_b = 0.39;
gfx_a = 1;
gfx_x = 0;
gfx_y = 180;
gfx_rectto(425,261);
//big box 2 
gfx_r = gfx_g = gfx_b = 1;
gfx_a = 0.1;
gfx_x = 0;
gfx_y = 180;
gfx_rectto(425,190);
//big box 3
gfx_r = gfx_g = gfx_b = 0;
gfx_a = 0.3;
gfx_x = 0;
gfx_y = 245;
gfx_rectto(425,261);
//ch textbox1
gfx_r = gfx_g = gfx_b = 0;
gfx_a = 1;
gfx_x = 350;
gfx_y = 210;
gfx_rectto(415,227);
//ch textbox2
gfx_r = gfx_g = gfx_b = 0;
gfx_a = 1;
gfx_x = 250;
gfx_y = 210;
gfx_rectto(315,227);
//ch text
gfx_r = gfx_g = gfx_b = 1;
gfx_a = 1;
gfx_x = 20;
gfx_y = 215;
gfx_drawchar($'L');
gfx_drawchar($'+');
gfx_drawchar($'R');
gfx_x = 215;
gfx_drawchar($'R');
gfx_drawchar($'M');
gfx_drawchar($'S');
gfx_x = 333;
gfx_drawchar($'P');
gfx_x = 255;
rmsl_gfx > -300 ? (
  rmsl_gfx > 0.0 ? (
    gfx_r = 1;
    gfx_g = gfx_b = 0;
    gfx_drawchar($'+');
  );
  gfx_drawnumber(rmsl_gfx,2);
) : (
  gfx_drawchar($'-');
  gfx_drawchar($'I');
  gfx_drawchar($'N');
  gfx_drawchar($'F');
);
gfx_r = 1;
gfx_g = gfx_b = 1;
gfx_x = 355;
olt > -300 ? (
  olt >= 0.0 ? (
    gfx_drawchar($'+');
    gfx_r = 1;
    gfx_g = gfx_b = 0;  
  );
  gfx_drawnumber(olt,2);
) : (
  gfx_drawchar($'-');
  gfx_drawchar($'I');
  gfx_drawchar($'N');
  gfx_drawchar($'F');
);
edit:
Simply pasting the
// override drawing functions for graphical window scaling
section in your version did it.

Last edited by nofish; 01-05-2020 at 06:21 PM.
nofish is offline   Reply With Quote
Old 01-05-2020, 06:23 PM   #9
ashcat_lt
Human being with feelings
 
Join Date: Dec 2012
Posts: 4,524
Default

K.


Try this and LMK:


Code:
desc: LT VU Meter Deluxe (Summed)
//tags: analysis visualization metering
//author: Liteon hacked by ashcat_lt 

slider1:300<0,1000,1>Meter Time(ms)
slider2:0<0,2,1{Left,Sum,Maximum}>Channel 
slider3:-18<-24,-9,0.1>Calibrate (0VU = xdbFS)
slider4:0<-24,24,0.1>Gain (db)
slider5:0<0,2,1{RMS,Average,Slew}>Detector
slider6:0<0,1,1>AutoGain (0=run, 1=grab)

in_pin:left input
in_pin:right input
out_pin:left output
out_pin:right output


@init
//rp - right channel y pading, r - radius
rp = 261;
r = 200;
yl = yr = ylt = yrt = 74;
xl = xr = 66;
ms  = slider1;
cs = 0;


function ratiotodb (x)
( x = 20 * log10 (x););

function dbtoratio (x)
( x = 10 ^(x/20););


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


function set_logistic_limit (x)
  instance (limit, scale)
  (this.limit = x;
   this.scale = 1/x;);

function slew_set(rms_ms, calib)
  instance(slew)
(
  this.slew = (1000 * calib) / (srate * rms_ms);
  this.set_logistic_limit (this.slew);
);

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

function average(input)
  instance(ave_s, coeff, icoeff)
(
  ave_s = (ave_s * coeff) + (icoeff * abs(input));
);


function logistic (x)
  instance(limit)
  (log_input = x * this.scale;
   log_curve = 1 / (1 + exp (-2 * log_input));
   log_shifted = 2 * log_curve - 1;
   log_outuput = this.limit * log_shifted;);

function slew(input)
  instance(slew_s, slew)
(
  input = abs(input);
  diff = input - slew_s;
  slew_s += this.logistic (diff);
);



@slider
rms_ms = slider1;
rms0.RMS_set(rms_ms);
calibrate = dbtoratio (slider3);
rms0.slew_set (rms_ms, calibrate);
gain = dbtoratio (slider4);




@block

  rmsl_gfx = ratiotodb(rms_in);
  slider6 == 1 ? 
    (gaindiff = min((slider3 - (rmsl_gfx - slider4)), 24)):
    (last6 == 1 ? slider4 = gaindiff);
  last6 = slider6;
  
  ool = min (6, max (-60, (rmsl_gfx  - slider3)));
  
  //get x from exp scale
  xlt = floor(exp(log(1.055)*2.1*ool)*285);
  
  //get y from x and radius - r     
  l=sqrt(sqr(r)+sqr(212-xlt));
  h=((l-r)*r/l);
  m=sqrt(sqr(l-r)-sqr(h));
  ylt=35+h;
  xlt < 212 ? xlt=xlt+m : xlt=xlt-m;
  
  //update x,y,out
  old_xl < xlt ? (xl = min(max(xlt,66),375); yl = ylt; );
  bscnt = pvl = pvr = 0;
;
//limit x
xl = min(max(xl,66),375);

olt = ratiotodb(peaksample);

@sample
spl0 *= gain;
spl1 *= gain;

slider2 == 0 ?
  (rms_in_0 = spl0;);
slider2 == 1 ?
  (rms_in_0 = (spl0 + spl1)/2) ;
slider2 == 2 ?
  (rms_in_0 = max(spl0, spl1)) ;

slider5 == 0 ? 
  (rms_in = rms0.RMS(rms_in_0));
slider5 == 1 ? 
  (rms_in = rms0.average(rms_in_0));
slider5 == 2 ? 
  (rms_in = rms0.slew(rms_in_0));  


peaksample = max (peaksample, rms_in_0);

@gfx 425 240

// override drawing functions for graphical window scaling
gsc = min(gfx_w/425,gfx_h/240); igsc = 1.0/gsc;
gxo = max(0,  gfx_w/2 - gfx_h*425/240/2);
function gfx_lineto(x,y,aa) ( gfx_x*=gsc; gfx_y*=gsc; gfx_x+=gxo; gfx_lineto(x*gsc+gxo,y*gsc,aa); gfx_x-=gxo; gfx_x*=igsc; gfx_y*=igsc; );
function gfx_rectto(x,y)(gfx_x*=gsc; gfx_y*=gsc; gfx_x+=gxo; gsc>.5 ? gfx_rectto(x*gsc+gxo,y*gsc); gfx_x-=gxo;  gfx_x*=igsc; gfx_y*=igsc;);
function gfx_drawnumber(y,x) (
  gsc>.5 ? (
    gsc<.7 && x>1 ? x=1;
    gfx_x*=gsc; gfx_y*=gsc; gfx_x+=gxo; gfx_drawnumber(y,x); gfx_x-=gxo;  gfx_x*=igsc; gfx_y*=igsc; 
  );
);
function gfx_drawchar(x) ( gfx_x*=gsc; gfx_y*=gsc; gfx_x+=gxo; gsc>.5 ? gfx_drawchar(x); gfx_x-=gxo; gfx_x*=igsc; gfx_y*=igsc; );


//**************************************************************** left
//red scale
gfx_r =  gfx_a = 1;
gfx_g = gfx_b =0;
gfx_x = 283;
gfx_y = 28;
gfx_drawnumber(0,0);
gfx_x = 370;
gfx_y = 55;
gfx_drawnumber(3,0);
gfx_x = 405;
gfx_y = 57;
gfx_drawchar($'+');
gfx_x = 283;
gfx_y = 38;
gfx_lineto(269,76,0.5);
gfx_x = 311;
gfx_y = 43;
gfx_lineto(293,80,1);
gfx_x = 342;
gfx_y = 51;
gfx_lineto(318,85,1);
gfx_x = 370;
gfx_y = 65;
gfx_lineto(344,93,0.5);

//white scale
gfx_r = gfx_g = gfx_b = 1;
gfx_a = 1;
gfx_x = 12;
gfx_y = 60;
gfx_drawchar($'-');
gfx_x = 41;
gfx_y = 53;
gfx_drawnumber(20,0);
gfx_x = 80;
gfx_y = 37;
gfx_drawnumber(10,0);
gfx_x = 125;
gfx_y = 29;
gfx_drawnumber(7,0);
gfx_x = 157;
gfx_y = 25;
gfx_drawnumber(5,0);
gfx_x = 198;
gfx_y = 24;
gfx_drawnumber(3,0);
gfx_x = 56;
gfx_y = 63;
gfx_lineto(82,92,0.5);
gfx_x = 95;
gfx_y = 47;
gfx_lineto(119,82,0.5);
gfx_x = 130;
gfx_y = 39;
gfx_lineto(146,77,0.5);
gfx_x = 145;
gfx_y = 37;
gfx_lineto(158,75,1);
gfx_x = 162;
gfx_y = 35;
gfx_lineto(171,74,0.5);
gfx_x = 180;
gfx_y = 34;
gfx_lineto(187,74,1);
gfx_x = 202;
gfx_y = 34;
gfx_lineto(204,72,0.5);
gfx_x = 227;
gfx_y = 34;
gfx_lineto(223,73,1);
gfx_x = 253;
gfx_y = 35;
gfx_lineto(245,73,1);

//vu box border
gfx_r = gfx_g = gfx_b = 0.75;
gfx_a = 1;
gfx_x = 198;
gfx_y = 108;
gfx_rectto(241,139);
//vu box
gfx_a = 1;
gfx_r = 0.5;
gfx_g = gfx_b = 0.1;
gfx_x = 200;
gfx_y = 110;
gfx_rectto(239,137);
//vu text
gfx_r = gfx_g = gfx_b = 0.85;
gfx_a = 1;
gfx_x = 212;
gfx_y = 120;
gfx_drawchar($'V');
gfx_drawchar($'U');

//meter
olt > 0 ? (
  gfx_r = 1; 
  gfx_g = gfx_b = 0;
) : (
  gfx_r = gfx_g = gfx_b = 1;
);
gfx_a = 1;
gfx_x = 212;
gfx_y = 236;
gfx_lineto(xl,yl,1);
gfx_x = 211;
gfx_y = 236;
gfx_lineto(xl-1,yl,1);
gfx_x = 210;
gfx_y = 236;
gfx_lineto(xl-2,yl,1);

//big border
gfx_r = gfx_g = gfx_b = 0.55;
gfx_a = 1;
gfx_x = 0;
gfx_y = 179;
gfx_rectto(425,180);
//big box 1
gfx_r = 0.1;
gfx_g = 0.2; 
gfx_b = 0.39;
gfx_a = 1;
gfx_x = 0;
gfx_y = 180;
gfx_rectto(425,261);
//big box 2 
gfx_r = gfx_g = gfx_b = 1;
gfx_a = 0.1;
gfx_x = 0;
gfx_y = 180;
gfx_rectto(425,190);
//big box 3
gfx_r = gfx_g = gfx_b = 0;
gfx_a = 0.3;
gfx_x = 0;
gfx_y = 245;
gfx_rectto(425,261);
//ch textbox1
gfx_r = gfx_g = gfx_b = 0;
gfx_a = 1;
gfx_x = 350;
gfx_y = 210;
gfx_rectto(415,227);
//ch textbox2
gfx_r = gfx_g = gfx_b = 0;
gfx_a = 1;
gfx_x = 250;
gfx_y = 210;
gfx_rectto(315,227);
//ch text
gfx_r = gfx_g = gfx_b = 1;
gfx_a = 1;
gfx_x = 20;
gfx_y = 215;
gfx_drawchar($'L');
gfx_drawchar($'+');
gfx_drawchar($'R');
gfx_x = 215;
slider5 == 0 ?
(gfx_drawchar($'R');
 gfx_drawchar($'M');
 gfx_drawchar($'S'););
slider5 == 1 ?
(gfx_drawchar($'A');
 gfx_drawchar($'V');
 gfx_drawchar($'G'););
slider5 == 2 ?
(gfx_drawchar($'S');
 gfx_drawchar($'L');
 gfx_drawchar($'W'););

gfx_x = 333;
gfx_drawchar($'P');
gfx_x = 255;
rmsl_gfx > -300 ? (
  rmsl_gfx > 0.0 ? (
    gfx_r = 1;
    gfx_g = gfx_b = 0;
    gfx_drawchar($'+');
  );
  gfx_drawnumber(rmsl_gfx,2);
) : (
  gfx_drawchar($'-');
  gfx_drawchar($'I');
  gfx_drawchar($'N');
  gfx_drawchar($'F');
);
gfx_r = 1;
gfx_g = gfx_b = 1;
gfx_x = 355;
olt > -300 ? (
  olt >= 0.0 ? (
    gfx_drawchar($'+');
    gfx_r = 1;
    gfx_g = gfx_b = 0;  
  );
  gfx_drawnumber(olt,2);
) : (
  gfx_drawchar($'-');
  gfx_drawchar($'I');
  gfx_drawchar($'N');
  gfx_drawchar($'F');
);
ashcat_lt is offline   Reply With Quote
Old 01-05-2020, 07:04 PM   #10
nofish
Human being with feelings
 
nofish's Avatar
 
Join Date: Oct 2007
Location: home is where the heart is
Posts: 9,275
Default

Yep, works. Thanks.

nofish is offline   Reply With Quote
Old 01-05-2020, 07:14 PM   #11
ashcat_lt
Human being with feelings
 
Join Date: Dec 2012
Posts: 4,524
Default

Woot!
ashcat_lt is offline   Reply With Quote
Old 01-12-2020, 04:54 PM   #12
ashcat_lt
Human being with feelings
 
Join Date: Dec 2012
Posts: 4,524
Default

Minor update here.



Added an "audio" output on channel 3 that represents the calculated value (RMS or whatever). Be careful with this. Use pin connectors to assign it to a track channel that you're not using for other things. You can use it as a sidechain or "Control Voltage" input for other plugins or as a way to analyze the dynamics of your signal. OR Render it to an audio item, adjust its volume envelope, and then copy that to an envelope on your original signal.



But then I also added a slider labeled "level" which is literally the same thing but you can write it to automation. Not sure why you'd want that, but it's there.



Code:
desc: LT VU Meter Deluxe (Summed)
//tags: analysis visualization metering
//author: Liteon hacked by ashcat_lt 

slider1:300<0,1000,1>RMS size (ms)
slider2:0<0,2,1{Left,Sum,Maximum}>Channel 
slider3:-18<-24,-9,0.1>Calibrate (0VU = xdbFS)
slider4:0<-24,24,0.1>Gain (db)
slider5:0<0,2,1{RMS,Average,Slew}>Detector
slider6:0<0,1,1>AutoGain
slider7:<0,1,0.001>level

in_pin:left input
in_pin:right input
out_pin:left output
out_pin:right output
out_pin:level output (CV)


@init
//rp - right channel y pading, r - radius
rp = 261;
r = 200;
yl = yr = ylt = yrt = 74;
xl = xr = 66;
ms  = slider1;
cs = 0;


function ratiotodb (x)
( x = 20 * log10 (x););

function dbtoratio (x)
( x = 10 ^(x/20););


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


function set_logistic_limit (x)
  instance (limit, scale)
  (this.limit = x;
   this.scale = 1/x;);

function slew_set(rms_ms, calib)
  instance(slew)
(
  this.slew = (1000 * calib) / (srate * rms_ms);
  this.set_logistic_limit (this.slew);
);

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

function average(input)
  instance(ave_s, coeff, icoeff)
(
  ave_s = (ave_s * coeff) + (icoeff * abs(input));
);


function logistic (x)
  instance(limit)
  (log_input = x * this.scale;
   log_curve = 1 / (1 + exp (-2 * log_input));
   log_shifted = 2 * log_curve - 1;
   log_outuput = this.limit * log_shifted;);

function slew(input)
  instance(slew_s, slew)
(
  input = abs(input);
  diff = input - slew_s;
  slew_s += this.logistic (diff);
);



@slider
rms_ms = slider1;
rms0.RMS_set(rms_ms);
calibrate = dbtoratio (slider3);
rms0.slew_set (rms_ms, calibrate);
gain = dbtoratio (slider4);




@block
  
  slider7 = rms_in;
  slider_automate (slider7);
  rmsl_gfx = ratiotodb(rms_in);
  slider6 == 1 ? 
    (gaindiff = min((slider3 - (rmsl_gfx - slider4)), 24)):
    (last6 == 1 ? slider4 = gaindiff);
  last6 = slider6;
  
  ool = min (6, max (-60, (rmsl_gfx  - slider3)));
  
  //get x from exp scale
  xlt = floor(exp(log(1.055)*2.1*ool)*285);
  
  //get y from x and radius - r     
  l=sqrt(sqr(r)+sqr(212-xlt));
  h=((l-r)*r/l);
  m=sqrt(sqr(l-r)-sqr(h));
  ylt=35+h;
  xlt < 212 ? xlt=xlt+m : xlt=xlt-m;
  
  //update x,y,out
  old_xl < xlt ? (xl = min(max(xlt,66),375); yl = ylt; );
  bscnt = pvl = pvr = 0;
;
//limit x
xl = min(max(xl,66),375);

olt = ratiotodb(peaksample);

@sample
spl0 *= gain;
spl1 *= gain;

slider2 == 0 ?
  (rms_in_0 = spl0;);
slider2 == 1 ?
  (rms_in_0 = (spl0 + spl1)/2) ;
slider2 == 2 ?
  (rms_in_0 = max(spl0, spl1)) ;

slider5 == 0 ? 
  (rms_in = rms0.RMS(rms_in_0));
slider5 == 1 ? 
  (rms_in = rms0.average(rms_in_0));
slider5 == 2 ? 
  (rms_in = rms0.slew(rms_in_0));  

spl2 = rms_in;
peaksample = max (peaksample, rms_in_0);

@gfx 425 191
//**************************************************************** left
//red scale
gfx_r =  gfx_a = 1;
gfx_g = gfx_b =0;
gfx_x = 283;
gfx_y = 28;
gfx_drawnumber(0,0);
gfx_x = 370;
gfx_y = 55;
gfx_drawnumber(3,0);
gfx_x = 405;
gfx_y = 57;
gfx_drawchar($'+');
gfx_x = 283;
gfx_y = 38;
gfx_lineto(269,76,0.5);
gfx_x = 311;
gfx_y = 43;
gfx_lineto(293,80,1);
gfx_x = 342;
gfx_y = 51;
gfx_lineto(318,85,1);
gfx_x = 370;
gfx_y = 65;
gfx_lineto(344,93,0.5);

//white scale
gfx_r = gfx_g = gfx_b = 1;
gfx_a = 1;
gfx_x = 12;
gfx_y = 60;
gfx_drawchar($'-');
gfx_x = 41;
gfx_y = 53;
gfx_drawnumber(20,0);
gfx_x = 80;
gfx_y = 37;
gfx_drawnumber(10,0);
gfx_x = 125;
gfx_y = 29;
gfx_drawnumber(7,0);
gfx_x = 157;
gfx_y = 25;
gfx_drawnumber(5,0);
gfx_x = 198;
gfx_y = 24;
gfx_drawnumber(3,0);
gfx_x = 56;
gfx_y = 63;
gfx_lineto(82,92,0.5);
gfx_x = 95;
gfx_y = 47;
gfx_lineto(119,82,0.5);
gfx_x = 130;
gfx_y = 39;
gfx_lineto(146,77,0.5);
gfx_x = 145;
gfx_y = 37;
gfx_lineto(158,75,1);
gfx_x = 162;
gfx_y = 35;
gfx_lineto(171,74,0.5);
gfx_x = 180;
gfx_y = 34;
gfx_lineto(187,74,1);
gfx_x = 202;
gfx_y = 34;
gfx_lineto(204,72,0.5);
gfx_x = 227;
gfx_y = 34;
gfx_lineto(223,73,1);
gfx_x = 253;
gfx_y = 35;
gfx_lineto(245,73,1);

//vu box border
gfx_r = gfx_g = gfx_b = 0.75;
gfx_a = 1;
gfx_x = 198;
gfx_y = 108;
gfx_rectto(241,139);
//vu box
gfx_a = 1;
gfx_r = 0.5;
gfx_g = gfx_b = 0.1;
gfx_x = 200;
gfx_y = 110;
gfx_rectto(239,137);
//vu text
gfx_r = gfx_g = gfx_b = 0.85;
gfx_a = 1;
gfx_x = 212;
gfx_y = 120;
gfx_drawchar($'V');
gfx_drawchar($'U');

//meter
olt > 0 ? (
  gfx_r = 1; 
  gfx_g = gfx_b = 0;
) : (
  gfx_r = gfx_g = gfx_b = 1;
);
gfx_a = 1;
gfx_x = 212;
gfx_y = 236;
gfx_lineto(xl,yl,1);
gfx_x = 211;
gfx_y = 236;
gfx_lineto(xl-1,yl,1);
gfx_x = 210;
gfx_y = 236;
gfx_lineto(xl-2,yl,1);

//big border
gfx_r = gfx_g = gfx_b = 0.55;
gfx_a = 1;
gfx_x = 0;
gfx_y = 179;
gfx_rectto(425,180);
//big box 1
gfx_r = 0.1;
gfx_g = 0.2; 
gfx_b = 0.39;
gfx_a = 1;
gfx_x = 0;
gfx_y = 180;
gfx_rectto(425,261);
//big box 2 
gfx_r = gfx_g = gfx_b = 1;
gfx_a = 0.1;
gfx_x = 0;
gfx_y = 180;
gfx_rectto(425,190);
//big box 3
gfx_r = gfx_g = gfx_b = 0;
gfx_a = 0.3;
gfx_x = 0;
gfx_y = 245;
gfx_rectto(425,261);
//ch textbox1
gfx_r = gfx_g = gfx_b = 0;
gfx_a = 1;
gfx_x = 350;
gfx_y = 210;
gfx_rectto(415,227);
//ch textbox2
gfx_r = gfx_g = gfx_b = 0;
gfx_a = 1;
gfx_x = 250;
gfx_y = 210;
gfx_rectto(315,227);
//ch text
gfx_r = gfx_g = gfx_b = 1;
gfx_a = 1;
gfx_x = 20;
gfx_y = 215;
gfx_drawchar($'L');
gfx_drawchar($'+');
gfx_drawchar($'R');
gfx_x = 215;
slider5 == 0 ?
(gfx_drawchar($'R');
 gfx_drawchar($'M');
 gfx_drawchar($'S'););
slider5 == 1 ?
(gfx_drawchar($'A');
 gfx_drawchar($'V');
 gfx_drawchar($'G'););
slider5 == 2 ?
(gfx_drawchar($'S');
 gfx_drawchar($'L');
 gfx_drawchar($'W'););

gfx_x = 333;
gfx_drawchar($'P');
gfx_x = 255;
rmsl_gfx > -300 ? (
  rmsl_gfx > 0.0 ? (
    gfx_r = 1;
    gfx_g = gfx_b = 0;
    gfx_drawchar($'+');
  );
  gfx_drawnumber(rmsl_gfx,2);
) : (
  gfx_drawchar($'-');
  gfx_drawchar($'I');
  gfx_drawchar($'N');
  gfx_drawchar($'F');
);
gfx_r = 1;
gfx_g = gfx_b = 1;
gfx_x = 355;
olt > -300 ? (
  olt >= 0.0 ? (
    gfx_drawchar($'+');
    gfx_r = 1;
    gfx_g = gfx_b = 0;  
  );
  gfx_drawnumber(olt,2);
) : (
  gfx_drawchar($'-');
  gfx_drawchar($'I');
  gfx_drawchar($'N');
  gfx_drawchar($'F');
);
ashcat_lt 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 02:55 AM.


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