Old 03-09-2017, 09:11 AM   #1
eugen2777
Human being with feelings
 
eugen2777's Avatar
 
Join Date: Aug 2012
Posts: 271
Default EEL:Envelope-based Deesser

The script creates volume envelope based on the sibilance and compress it.

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


==============
How use:
Select the audio-item(or several items).
Set time selection, if you want to process only a specific area.
Click "Activate Envelope" and "Show Envelope" button if need.
"Show Envelope" - toggle show/hide take vol envelope.
"Activate Envelope" - toggle activate/deactivate take vol envelope.

Use the sliders to adjust take volume envelope.

===============
Link(will be updated):
gen_Envelope-based Deesser.eel

Note: Needed SWS - latest version.

===============
How install - it is actual for all eel-scripts(unless otherwise stated):
Open Reaper. Actions>Show Action List. ReaScript: press "New".
Select the folder for scripts(By default - ...\Reaper\Scripts).
Specify the name and extension - .eel(it's mandatory). For Example, MyScript.eel. Click save. You will see a black window.
Copy the text of the script(link in the first post) in this window. Press Ctrl+S. Close the window. Now the script is available in the Action List.
===
In addition, you can use Reapack, but the link to my repository must be added manually
__________________
ReaScripts
eugen2777 is offline   Reply With Quote
Old 03-09-2017, 09:12 AM   #2
Arnar
Human being with feelings
 
Arnar's Avatar
 
Join Date: Jan 2007
Location: Smokie Bay.
Posts: 796
Default

Beautiful !
__________________
In Music We Trust.
http://soundcloud.com/hazar
http://soundcloud.com/ifthenrun
Arnar is offline   Reply With Quote
Old 03-09-2017, 10:17 AM   #3
vitalker
Human being with feelings
 
vitalker's Avatar
 
Join Date: Dec 2012
Posts: 13,333
Default

Whaaat? It's awesome, man!
vitalker is online now   Reply With Quote
Old 03-09-2017, 10:42 AM   #4
James HE
Human being with feelings
 
James HE's Avatar
 
Join Date: Mar 2007
Location: I'm in a barn
Posts: 4,467
Default

Cool! so glad you've done this in EEL.

One suggestion - add a refresh button - so when you are switching items, you can apply the settings to the item. For now adjusting any control makes the envelope, but a button to refresh would be much nicer!


*oh and some sort of preset system (this could be written to either the project and reaper ext state)
I might work on that myself actually, I have some functions already written that could help out.

Last edited by James HE; 03-09-2017 at 10:53 AM.
James HE is offline   Reply With Quote
Old 03-09-2017, 12:43 PM   #5
eugen2777
Human being with feelings
 
eugen2777's Avatar
 
Join Date: Aug 2012
Posts: 271
Default

Quote:
Originally Posted by James HE View Post
Cool! so glad you've done this in EEL.
EEL works incredibly faster in this situation.. I had no choice.
Look at "processing time".

Quote:
Originally Posted by James HE View Post
One suggestion - add a refresh button - so when you are switching items, you can apply the settings to the item. For now adjusting any control makes the envelope, but a button to refresh would be much nicer!
Well, I'll add the refresh-button.

Quote:
Originally Posted by James HE View Post
*oh and some sort of preset system (this could be written to either the project and reaper ext state)
I might work on that myself actually, I have some functions already written that could help out.
The preset system will be added soon. I also plan to make the Envelope-based gate soon
__________________
ReaScripts
eugen2777 is offline   Reply With Quote
Old 03-09-2017, 01:20 PM   #6
James HE
Human being with feelings
 
James HE's Avatar
 
Join Date: Mar 2007
Location: I'm in a barn
Posts: 4,467
Default

This script isn't working on different tabbed projects here, it only works on one project no matter which project tab is active.

Trying to find out why and modify it, you might be able to spot it before I do
James HE is offline   Reply With Quote
Old 03-09-2017, 01:30 PM   #7
amagalma
Human being with feelings
 
amagalma's Avatar
 
Join Date: Apr 2011
Posts: 3,451
Default

Looks great! :O

Going to test it!
__________________
Most of my scripts can be found in ReaPack.
If you find them useful, a donation would be greatly appreciated! Thank you! :)
amagalma is offline   Reply With Quote
Old 03-09-2017, 01:51 PM   #8
Luster
Human being with feelings
 
Luster's Avatar
 
Join Date: Nov 2015
Posts: 642
Default

Many many thanks for those envelope based dynamics scripts!
These are very big arguments to show my colleagues why I am using this quirky software called Reaper.

Your font choice for the Deesser looks also way better then the Arial in the compressor script. Looked into the script and saw you already left a comment switch in it.
I would suggest Calibri as default for both and maybe a subtle differentiation in backgroundcoloring for the scripts so the user always is aware which one (compressor/deesser/upcoming gate) he fired ATM.

Again a big thank you! Great work!

Last edited by Luster; 03-09-2017 at 03:18 PM.
Luster is offline   Reply With Quote
Old 03-09-2017, 03:20 PM   #9
stereolost
Human being with feelings
 
stereolost's Avatar
 
Join Date: Mar 2015
Location: Moscow, Russia
Posts: 206
Default

Разрыв башки просто
stereolost is offline   Reply With Quote
Old 03-09-2017, 05:41 PM   #10
Macc
Human being with feelings
 
Join Date: Feb 2017
Posts: 76
Default

I think I love you.

Only request: Make it bandpass-able, and full spectrum. Looks like it only goes to 2k...?

I could find SO MANY uses for this in mastering/post work. For example, uncompressing stuff that has been stupidly compressed, that pumps due to the bass content. Could work very well indeed.

Amazing stuff.
Macc is offline   Reply With Quote
Old 03-09-2017, 06:59 PM   #11
Jae.Thomas
Human being with feelings
 
Join Date: Jun 2006
Posts: 22,567
Default

you fucking legend
Jae.Thomas is offline   Reply With Quote
Old 03-10-2017, 12:22 AM   #12
radekdolezi
Human being with feelings
 
Join Date: Jul 2016
Posts: 48
Default

man – you're awesome! thank you
radekdolezi is offline   Reply With Quote
Old 03-10-2017, 12:32 AM   #13
Janne83
Human being with feelings
 
Join Date: May 2010
Location: Earth
Posts: 1,883
Default

Eugen thank you. This is awesome.

J
__________________
Win11, R 64bit
Janne83 is offline   Reply With Quote
Old 03-10-2017, 04:04 PM   #14
eugen2777
Human being with feelings
 
eugen2777's Avatar
 
Join Date: Aug 2012
Posts: 271
Default

Thank you all for your attention. We are waiting for something more interesting in the future, I think ...
James HE,
Quote:
Originally Posted by James HE View Post
This script isn't working on different tabbed projects here, it only works on one project no matter which project tab is active.

Trying to find out why and modify it, you might be able to spot it before I do
I could not get it. I used a lot of different tabs and always the script worked on the current project. This is probably due to global settings.

Luster, ok, I will update the compressor and change the font.

Macc,
Well, I'll add different filters to the env-based compressor(LP,HP,BP).
We can get some latency at low frequencies, but with envelopes it's easy to compensate.
===
One more thought about the compressor (not the DeSesser). We can get a quick and clear attack in the envelope.
This will not significantly affect performance, but it will be useful.
Sorry for my English, there are a few things that I can not explain.
Later I'll try to draw this to make it clearer.
__________________
ReaScripts
eugen2777 is offline   Reply With Quote
Old 04-03-2017, 02:41 PM   #15
Macc
Human being with feelings
 
Join Date: Feb 2017
Posts: 76
Default

Quote:
Originally Posted by eugen2777 View Post
Macc,
Well, I'll add different filters to the env-based compressor(LP,HP,BP).
We can get some latency at low frequencies, but with envelopes it's easy to compensate.
I only just saw this - thank you very much. Subscribing to the thread this time!
Macc is offline   Reply With Quote
Old 04-03-2017, 04:14 PM   #16
musicbynumbers
Human being with feelings
 
musicbynumbers's Avatar
 
Join Date: Jun 2009
Location: South, UK
Posts: 14,214
Default

Very cool!
__________________
subproject FRs click here
note: don't search for my pseudonym on the web. The "musicbynumbers" you find is not me or the name I use for my own music.
musicbynumbers is offline   Reply With Quote
Old 04-03-2017, 04:24 PM   #17
Robert Randolph
Human being with feelings
 
Robert Randolph's Avatar
 
Join Date: Apr 2017
Location: St. Petersburg, FL
Posts: 880
Default

Amazing!

Great idea and implementation.
Robert Randolph is offline   Reply With Quote
Old 04-05-2017, 07:36 AM   #18
Javier Robledo
Human being with feelings
 
Javier Robledo's Avatar
 
Join Date: Jul 2014
Posts: 634
Default

Does it work on Mac ?

It´s tells me unexpected symbol when try to save...

Thanks
Javier Robledo is offline   Reply With Quote
Old 04-08-2017, 09:29 AM   #19
eugen2777
Human being with feelings
 
eugen2777's Avatar
 
Join Date: Aug 2012
Posts: 271
Default

Yes, it should work. Do not forget that this is EEL-script, set ".eel"-extension.
__________________
ReaScripts
eugen2777 is offline   Reply With Quote
Old 04-08-2017, 01:15 PM   #20
vanhaze
Human being with feelings
 
vanhaze's Avatar
 
Join Date: Jul 2012
Location: Netherlands
Posts: 5,247
Default

This is absolutely awesome, many thanks !!
__________________
Macbook Pro INTEL | Reaper, always latest version | OSX Ventura | Presonus Studio 24c
My Reaper Tips&Tricks YouTube Channel: https://www.youtube.com/user/vanhaze2000/playlists
vanhaze is offline   Reply With Quote
Old 09-11-2017, 12:23 AM   #21
G-Sun
Human being with feelings
 
G-Sun's Avatar
 
Join Date: May 2010
Location: Norway
Posts: 7,318
Default

How does this script difference from the eel-compressor?
__________________
Reaper x64, win 11
Composer, text-writer, producer
Bandcamp
G-Sun is offline   Reply With Quote
Old 04-18-2018, 04:02 PM   #22
barbaroja
Human being with feelings
 
barbaroja's Avatar
 
Join Date: Jul 2009
Posts: 429
Default

Awesome
barbaroja is offline   Reply With Quote
Old 04-19-2018, 05:37 AM   #23
D Rocks
Human being with feelings
 
Join Date: Dec 2017
Location: Quebec, Canada
Posts: 550
Default

wow, I have been looking for this kind of DE-Essing method for a while now and cant wait to test it tonight. Thanks so much for the work and sharing for free
__________________
Alex | www.drocksrecords.com | Thanks for REAPER
D Rocks is offline   Reply With Quote
Old 07-21-2018, 09:55 AM   #24
shosty
Human being with feelings
 
Join Date: Aug 2015
Posts: 249
Default

How do you get the waveform to show colours like that, I assume according to frequency?
shosty is offline   Reply With Quote
Old 07-21-2018, 10:11 AM   #25
vitalker
Human being with feelings
 
vitalker's Avatar
 
Join Date: Dec 2012
Posts: 13,333
Default

Quote:
Originally Posted by shosty View Post
How do you get the waveform to show colours like that, I assume according to frequency?
https://www.youtube.com/results?sear...spectral+peaks
vitalker is online now   Reply With Quote
Old 07-21-2018, 11:16 AM   #26
shosty
Human being with feelings
 
Join Date: Aug 2015
Posts: 249
Default

Quote:
Originally Posted by vitalker View Post
That's really useful, thanks!
shosty is offline   Reply With Quote
Old 08-04-2018, 08:25 AM   #27
shosty
Human being with feelings
 
Join Date: Aug 2015
Posts: 249
Default

I've noticed a bit of a drawback to this and that is that it deletes existing shapes/automation. I often automate breathes with the volume take envelope and when I use this the edits are gone.

Would it be possible to somehow preserve any points that are not created by this tool?
shosty is offline   Reply With Quote
Old 10-06-2018, 09:20 PM   #28
shady
Human being with feelings
 
Join Date: Jun 2017
Posts: 110
Default

Quote:
Originally Posted by shosty View Post
I've noticed a bit of a drawback to this and that is that it deletes existing shapes/automation. I often automate breathes with the volume take envelope and when I use this the edits are gone.

Would it be possible to somehow preserve any points that are not created by this tool?
A workaround would be to do your first automation pass on the track volume envelope. the only downside is that you dont have the live updated waveform as youre editing, but this could be overcome with some thinking.
shady is offline   Reply With Quote
Old 02-10-2019, 02:56 AM   #29
Hitcher
Human being with feelings
 
Join Date: Mar 2016
Posts: 21
Default

Чувааак!))))) ТВОЙ КОМПРЕССОР это просто мечта, ничего качественнее, гибче, нагляднее и честнее не существует. я счастлив с ним)) а тут еще и Deess - СПАСИБО ОГРОМНОЕЕЕЕЕЕЕ, ТЫ ОЧЕНЬ КРУТ! ДА ДА YES YES!)))))
Hitcher is offline   Reply With Quote
Old 08-26-2019, 11:33 AM   #30
Jeffsounds
Human being with feelings
 
Jeffsounds's Avatar
 
Join Date: Feb 2013
Location: Northeast Michigan
Posts: 3,460
Default

Very cool script! Thank you!
__________________
"TV has become nothing more than a Petri dish where this country grows its idiots." -Dr. John Becker
My First CD On Spotify - Side O' The Highway
Jeffsounds is offline   Reply With Quote
Old 01-18-2024, 09:33 PM   #31
abnegative
Human being with feelings
 
Join Date: Sep 2022
Posts: 222
Default

This script is ridiculously good, thanks!

I added some features and mods: https://forum.cockos.com/showpost.ph...1&postcount=39

Last edited by abnegative; 01-20-2024 at 12:54 PM.
abnegative is offline   Reply With Quote
Old 01-20-2024, 02:04 AM   #32
abnegative
Human being with feelings
 
Join Date: Sep 2022
Posts: 222
Default fixed bug, see updated post below

* [Function] Resizeable GUI
* [Function] Bind window size to GUI layout (user cannot resize window)
* [Function] Add button to toggle spectrogram
* [Function] New default values: Threshold = 0dB, High-Pass Frequency = 20000.00Hz, Compression = 100%
* [Optional] Automatically activate and show volume envelope upon launch
* [Optional] Automatically hide volume envelope upon exit
* [Optional] Automatically show spectrogram upon launch
* [Optional] Automatically hide spectrogram upon exit
* [Optional] Remove processing time for simplicity
* [Optional] Remove Pre-Open slider for simplicity (default to 0ms)
* [Optional] Remove Interval slider for simplicity (default to 1ms)
* [Aesthetics] Make colors brighter
* [Aesthetics] Move units to right of value
* [Aesthetics] Simplify window title to "De-esser"
* [Aesthetics] Relabel controls

Edit:
https://forum.cockos.com/showpost.ph...1&postcount=39

Code:
/* 
   * ReaScript Name:Envelope-based Deesser
   * EEL script for Cockos REAPER
   * Author: EUGEN27771
   * Author URI: http://forum.cockos.com/member.php?u=50462
   * Licence: GPL v3
   * Version: 1.01
*/

/*
      * Human being with feelings: abnegative: https://forums.cockos.com/member.php?u=176590
      * [Function]    Resizeable GUI
      * [Function]    Bind window size to GUI layout (user cannot resize window)
      * [Function]    Add button to toggle spectrogram
      * [Function]    New default values: Threshold = 0dB, High-Pass Frequency = 20000.00Hz, Compression = 100%
      * [Optional]    Automatically activate and show volume envelope upon launch
      * [Optional]    Automatically hide volume envelope upon exit
      * [Optional]    Automatically show spectrogram upon launch
      * [Optional]    Automatically hide spectrogram upon exit
      * [Optional]    Remove processing time for simplicity
      * [Optional]    Remove Pre-Open slider for simplicity (default to 0ms)
      * [Optional]    Remove Interval slider for simplicity (default to 1ms)
      * [Aesthetics]  Make colors brighter
      * [Aesthetics]  Move units to right of value
      * [Aesthetics]  Simplify window title to "De-esser"
      * [Aesthetics]  Relabel controls
*/

//-- Script creates Envelope, based on the sibilance and compress it


/*
zoom:                       amount by which to scale the GUI size
on_by_default:              automatically activate and show the volume envelope upon launch
show_envelope_on_open:      automatically show the volume envelope upon launch
hide_envelope_on_close:     automatically hide the take volume envelope when the GUI is closed
show_spetrogram_on_open:    automatically show the spectrogram upon launch
hide_spectrogram_on_close:  automatically hide the spectrogram when the GUI is closed
hide_preopen:               hide the pre-open parameter in GUI for simplicity (no pre-open is applied)
hide_interval:              hide the interval parameter in GUI for simplicity (minimal interval used for highest resolution envelope points)
hide_stats:                 hide the processing time
*/
/*----------------------------------------------------------
=== User may modify the values below (see definitions above)
----------------------------------------------------------*/
zoom = 3;
on_by_default = 1;
show_envelope_on_open = 1;
hide_envelope_on_close = 1;
show_spetrogram_on_open = 1;
hide_spectrogram_on_close = 1;
hide_preopen = 1;
hide_interval = 1;
hide_stats = 1;
/*----------------------------------------------------------
=== DO NOT EDIT BELOW THIS LINE ============================
----------------------------------------------------------*/


font = 16;
control_x_init = 5;
control_y_init = 5;
control_y_offset = 25;
slider_w = 260;
slider_h = 18;
button_w = 80;
button_h = 20;
button_x_offset = 90;
row = -1;

function current_row(new_row)
(
  new_row? row = row + 1;
  row;
);

/*----------------------------------------------------------
=== Filter, Comp, Gate etc functions =======================
----------------------------------------------------------*/
// -- DB2VAL - VAL2DB(from SDK) ------------------
function DB2VAL(x)
(
  exp((x)*0.11512925464970228420089957273422);
);
//----------------------------
function VAL2DB(x)
  local(v)
(
  x < 0.0000000298023223876953125 ? (
    -150; 
  ) : (
    v = log(x)*8.6858896380650365530225783783321;
    v < -150 ? -150 : v;
  );
);

// -- Filter -------------------------------------
function FilterB.SetValues(cutoffFreq, samplerate)
  local(sqr2, c, c2, csqr2, d)
  instance(ampIn0, ampIn1, ampIn2, ampOut1, ampOut2)    
(
  // samplerate can be different from the global srate if need
  sqr2 = 1.414213562;
  c = tan(($pi/samplerate) * cutoffFreq );
  c2 = c * c;
  csqr2 = sqr2 * c;
  d = (c2 + csqr2 + 1);
  
  ampIn0 = 1 / d;
  ampIn1 = -(ampIn0 + ampIn0);
  ampIn2 = ampIn0;
  
  ampOut1 = (2 * (c2 - 1)) / d;
  ampOut2 = (1 - csqr2 + c2) / d;
);
//----------------------------
function FilterB.Apply(in)
  instance(ampIn0, ampIn1, ampIn2, ampOut1, ampOut2, dlyIn1, dlyIn2, dlyOut1, dlyOut2, out)
(
  out = (ampIn0 * in) + (ampIn1 * dlyIn1) + (ampIn2 * dlyIn2) - (ampOut1 * dlyOut1) - (ampOut2 * dlyOut2);
  
  dlyOut2 = dlyOut1;
  dlyOut1 = out;
  dlyIn2 = dlyIn1;
  dlyIn1 = in;
  out;
);

// -- Gate ---------------------------------------
function GateD.SetValues(attThresh_dB, hysteresis_dB, hold_ms, samplerate)
  instance(attThresh, relThresh, hold)    
( 
  // samplerate can be different from the global srate if need
  attThresh  = 10^(attThresh_dB/20);
  relThresh  = 10^((attThresh_dB + hysteresis_dB)/20);
  hold = samplerate * hold_ms/1000;
);
//----------------------------
function GateD.Apply(in)
  instance(attThresh, relThresh, hold, hold_cnt, trig)
(
  in > attThresh ? (
    trig = 1;
    hold_cnt = 0;
  ) : ( 
     hold_cnt > hold && in < relThresh ? trig = 0;
     hold_cnt+=1;
  );
  trig;
);

// -- Env follower -------------------------------
function EnvFollower.SetValues(attack_ms, release_ms, samplerate)
(
  // samplerate can be different from the global srate if need
  // -- ga, gr coeff --
  this.ga = exp(-1/(samplerate*attack_ms/1000));
  this.gr = exp(-1/(samplerate*release_ms/1000)); 
);
//----------------------------
function EnvFollower.Apply(in)
  instance(ga, gr, out)
(
  out < in ? out = in + ga*(out-in) : out = in + gr*(out-in); 
);

// -- Compressor ---------------------------------
function CompD.SetValues(thresh_dB, ratio)
(
  this.thresh_dB = thresh_dB;
  this.thresh = 10^(thresh_dB/20);
  this.ratio = ratio;
);
//----------------------------
function CompD.Apply(in) // -- dB var
  instance(thresh_dB, thresh, ratio, out_dB, out)
(
  in > thresh ? (
    out_dB = ratio * (thresh_dB - VAL2DB(in));
    out = DB2VAL(out_dB);
  ) : (
    out_dB = 0;
    out = 1;
  ); 
);

/*----------------------------------------------------------
=== New button, slider functions ===========================
----------------------------------------------------------*/
//-- New button function -------
function button_New(x,y,w,h, r,g,b,a, lbl)
(
  this.x = x; this.y = y; this.w = w; this.h = h; // coord
  this.r = r; this.g = g; this.b = b; this.a = a; // color
  this.lbl = lbl;
);

//-- New slider function -------
function slider_New(x,y,w,h, r,g,b,a, lbl, val,min_val,max_val,units)
(
  this.x = x; this.y = y; this.w = w; this.h = h; // coord
  this.r = r; this.g = g; this.b = b; this.a = a; // color
  this.lbl = lbl;
  this.val = val;
  this.min_val = min_val; 
  this.max_val = max_val;
  this.norm_val = (val - min_val)/(max_val - min_val); // norm value
  this.units = units;
);


/*----------------------------------------------------------
=== Simple Get mouse functions =============================
----------------------------------------------------------*/
//------------------
function pointIN(p_x, p_y)
  instance(x,y,w,h)
( // if point in obj area
  p_x >= x && p_x <= x+w && p_y >= y && p_y <= y+h;
);

function mouseIN()
( // if mouse in obj area
  !(mouse_cap&1) && this.pointIN(mouse_x, mouse_y);
);

//------------------
function mouseDown()
( // if mouse has been pressed in obj area
  mouse_cap&1 && this.pointIN(mouse_ox,mouse_oy);
);

function mouseUp()
( // if mouse released(anywhere) and has been pressed in obj area
  last_mouse_cap&1 && !(mouse_cap&1) && this.pointIN(mouse_ox,mouse_oy);
);

function mouseClick()
( // if mouse released in obj area and has been pressed in obj area
  last_mouse_cap&1 && !(mouse_cap&1) && 
  this.pointIN(mouse_x, mouse_y) && this.pointIN(mouse_ox,mouse_oy);
);
//------------------
function mouseR_Down()
( // if mouse R has been pressed in obj area
  mouse_cap&2 && this.pointIN(mouse_ox,mouse_oy);
);

function mouseM_Down()
( // if mouse M has been pressed in obj area
  mouse_cap&64 && this.pointIN(mouse_ox,mouse_oy);
);


/*----------------------------------------------------------
=== SLIDER =================================================
----------------------------------------------------------*/
//-- Set slider value ------------------
function slider_set_value()
  instance(x,y,w,h, val,min_val,max_val, norm_val)
  local(nv, K )
(
  K = 10; // K = coeff(when Ctrl pressed)
  Ctrl ? (
    nv = norm_val + (mouse_x-last_x)/(w*K);
  ) : (
    nv = (mouse_x-x)/w;
  );
  
  nv != norm_val ? (
    norm_val = min( max(nv, 0), 1 ); // verify and set values
    val = min_val + (max_val-min_val)*norm_val;
    this.isChanged = 1;
  );
); 

//-- Draw slider -----------------------
function slider_draw()
  instance(x,y,w,h, r,g,b,a, lbl, val, norm_val, units)
  local(aa, val_str, str_w, str_h)
  
( 
  aa = a;
  this.isChanged = this.isReleased = 0; // reset 
  this.mouseIN() ? aa = a + 0.1;
  this.mouseDown() ? (
    aa = a + 0.2;
    this.slider_set_value();
  );
  
  this.mouseUp() ? this.isReleased = 1;
  
  //-- draw body, frame ------
  gfx_set(r,g,b,aa);
  gfx_rect(x,y,w,h, 0);
  gfx_rect(x, y, w*norm_val, h, 1);
  //-- draw label ------------
  gfx_set(0.9,0.8,0.5,0.9);
  gfx_measurestr(lbl, str_w, str_h);
  gfx_x = x + 5; gfx_y = y + (h-str_h)/2;
  gfx_drawstr(lbl);
  //-- draw value ------------
  val_str = sprintf(#, "%.2f%s", val, units); 
  gfx_measurestr(val_str, str_w, str_h);
  gfx_x = x - 5 + w - str_w; gfx_y = y + (h-str_h)/2;
  gfx_drawstr(val_str);
);


/*----------------------------------------------------------
=== BUTTON =================================================
----------------------------------------------------------*/
//-- Draw button -----------------------
function button_draw()
  instance(x,y,w,h, r,g,b,a, lbl)
  local(aa, str_w, str_h)
(   
  aa = a;
  this.mouseIN() ? aa = a + 0.1;
  this.mouseDown() ? aa = a + 0.2; 
  this.mouseClick() ? this.isClicked = 1 : this.isClicked = 0;
  
  //-- draw body, frame ------
  gfx_set(r,g,b,aa);
  gfx_rect(x,y,w,h, 1);
  gfx_rect(x,y,w,h, 0); // frame
  //-- draw label ------------
  gfx_set(0.9,0.8,0.5,0.9);
  gfx_measurestr(lbl, str_w, str_h);
  gfx_x = x + (w-str_w)/2; gfx_y = y + (h-str_h)/2;
  gfx_drawstr(lbl);

);


/*----------------------------------------------------------------------------------------
=== Create controls ======================================================================
----------------------------------------------------------------------------------------*/

//-- Create Sliders --------------------
//-- args = (x,y,w,h, r,g,b,a, lbl, val,min_val,max_val,units)
Thresh.slider_New(control_x_init*zoom,control_y_init * zoom + control_y_offset * current_row(1) * zoom,slider_w * zoom,slider_h * zoom,    5,0.3,0.3,0.2, "Threshold",    0,  -48,     0, " dB" );
HPFreq.slider_New(control_x_init*zoom,control_y_init * zoom + control_y_offset * current_row(1) * zoom,slider_w * zoom,slider_h * zoom,    0.4,5,0.5,0.2, "High-Pass Frequency",     20000, 2000, 20000, " Hz" );
!hide_preopen? PreOpen.slider_New(control_x_init*zoom,control_y_init * zoom + control_y_offset * current_row(1) * zoom,slider_w * zoom,slider_h * zoom,   0.4,5,0.5,0.2, "Pre-Open",        0,   0,    20, " ms" );
!hide_interval? Interval.slider_New(control_x_init*zoom,control_y_init * zoom + control_y_offset * current_row(1) * zoom,slider_w * zoom,slider_h * zoom,  0.4,5,0.5,0.2, "Interval",       1,    1,    10, " ms" );
Compress.slider_New(control_x_init*zoom,control_y_init * zoom + control_y_offset * current_row(1) * zoom,slider_w * zoom,slider_h * zoom, 0.3,0.4,5,0.2, "Compression",    100,    0,   100, " %" );

//-- Create Buttons --------------------
//-- args = (x,y,w,h, r,g,b,a, lbl)
ActEnv.button_New(control_x_init*zoom + 0*button_x_offset*zoom,control_y_init * zoom + control_y_offset * current_row(1) * zoom,button_w * zoom,button_h * zoom,   0.5,0.3,0.3,0.2, "Activate");
Spectr.button_New(control_x_init*zoom + 1*button_x_offset*zoom,control_y_init * zoom + control_y_offset * current_row(0) * zoom,button_w * zoom,button_h * zoom,  0.5,0.3,0.3,0.2, "Spectrogram");
VisEnv.button_New(control_x_init*zoom + 2*button_x_offset*zoom,control_y_init * zoom + control_y_offset * current_row(0) * zoom,button_w * zoom,button_h * zoom,  0.5,0.3,0.3,0.2, "Visibility");


//======================================================================================//


//----------------------------------------------------------------------------------------
//--- Toggle active, visible vol envelope ------------------------------------------------
//----------------------------------------------------------------------------------------
function ToggleActVis_VolEnvelope(mode)
  local(item_cnt, item_idx, item, take, VolEnv, BR_Env,
        BR_Env, active,visible,armed, inLane,laneHeight, 
        defShape, minVal,maxVal,centerVal, type, faderScaling)   
(
  item_cnt = CountSelectedMediaItems(0);
  item_cnt ? Undo_OnStateChange("Envelope-based Deesser");
  item_idx=0;
  loop(item_cnt,
      item = GetSelectedMediaItem(0, item_idx);
      take = GetActiveTake(item);
      VolEnv = GetTakeEnvelopeByName(take,"Volume"); // Get take "Volume" envelope
      
      //-- Toggle act,vis depend of mode(if VolEnv exists) -----
      VolEnv ? (
        BR_Env = extension_api("BR_EnvAlloc", VolEnv, 0);
        extension_api("BR_EnvGetProperties", BR_Env, active,visible,armed, inLane,laneHeight, 
                      defShape, minVal,maxVal,centerVal, type, faderScaling);
        mode == "act" ? active  = !active;  // toggle active
        mode == "vis" ? visible = !visible; // toggle visible
        extension_api("BR_EnvSetProperties", BR_Env, active,visible,armed, inLane,laneHeight, 
                      defShape, faderScaling);
        extension_api("BR_EnvFree", BR_Env, 1);

      ) : (
        //-- Create(if VolEnv no exist) ----
        Main_OnCommand(NamedCommandLookup("_S&M_TAKEENV1"), 0);
        VolEnv = GetTakeEnvelopeByName(take,"Volume");
      );
      item_idx+=1;
  );

);

//----------------------------------------------------------------------------------------
//--- Rebuild volume envelope ------------------------------------------------------------
//----------------------------------------------------------------------------------------

function CreateEnvelope(VolEnv, range_start, range_len, srate, envbuf, pnt_cnt)
  local(PreOpen, env_mode, shape,tens,sel,nosort, val,val1, rs_val,re_val, i, pos)     
(
  PreOpen = PreOpen.val/1000;
  //--------------------------
  env_mode = GetEnvelopeScalingMode(VolEnv);     // get VolEnv scaling mode
  val1 = ScaleToEnvelopeMode(env_mode, 1);       // Scaled  val=1
  //shape = 2; tens = 0; sel = 0; nosort = 1;    // def for new deess points 1
  shape = 0; tens = 0; sel = 0; nosort = 1;      // def for new deess points 2
  
  //-- Del Old points, Ins points at edges(use cur values) ------
  Envelope_Evaluate(VolEnv, range_start, srate, 0, rs_val);           // get env val at start
  Envelope_Evaluate(VolEnv, range_start+range_len, srate, 0, re_val); // get env val at end
  DeleteEnvelopePointRange(VolEnv, range_start-0.0001, range_start+range_len+0.0001); // Del Old points 
  //--------------------------
  InsertEnvelopePoint(VolEnv, range_start, rs_val, 0, 0, 0, 1);           // Insert point=curval at start
  InsertEnvelopePoint(VolEnv, range_start, val1, 0, 0, 0, 1);             // Insert point=1 at start
  InsertEnvelopePoint(VolEnv, range_start+range_len, val1, 0, 0, 0, 1);   // Insert point=1 at end
  InsertEnvelopePoint(VolEnv, range_start+range_len, re_val, 0, 0, 0, 1); // Insert point=curval at end
  
  //--------------------------
  i = 0;
  while(envbuf[i] <= range_start + PreOpen && i < pnt_cnt)( 
    i+=2; pnt_cnt-=2; // Если точки выходят за range_start!
  );
  //--------------------------

  loop(pnt_cnt*0.5,
    pos = envbuf[i] - PreOpen;
    val = ScaleToEnvelopeMode(env_mode,  envbuf[i+1]);   // Scale point val
    // -----------------------
    InsertEnvelopePoint(VolEnv, pos, val, shape, tens, sel, nosort); // Insert point        
    i+=2;  
  );
);

//----------------------------------------------------------------------------------------
//--- Rebuild volume envelope ------------------------------------------------------------
//----------------------------------------------------------------------------------------
function RebuildVolEnvelope(item, take, srate, n_chans, VolEnv)
  local(item_start, item_len, sel_start, sel_end, playrate, range_start, range_len, range_len_smpls, 
        block_size, n_blocks, rest_smples, AA, starttime_sec, samplebuf, smpl, ch_smpl, chan_sum, cur_block, envbuf,
        take_vol, item_vol, vol_offs, 
        trig, last_trig, input, fltr_out, env_out, comp_out, pnt_cnt, interval, interval_cnt, oo_offs)
( 
  item_start = GetMediaItemInfo_Value(item, "D_POSITION"); // item position
  item_len  = GetMediaItemInfo_Value(item, "D_LENGTH");    // item orig length
  GetSet_LoopTimeRange(0, 0, sel_start, sel_end, 0);       // get time selection
  !(sel_end - sel_start) ? (       // if no selection, then
    sel_start = item_start;        // use item start
    sel_end = item_start+item_len; // use item end
  );
  sel_start = max(sel_start, item_start);         // if sel_start or sel_end out of item, then
  sel_end   = min(sel_end, item_start+item_len);  // use item_start, item_end respectively
  //sel_end - sel_start < 0 ? MB("Time selection out of item range!", "Note", 0); 
  
  
  //----------------------------------------------------------------------------
  sel_end - sel_start > 0 ? ( 
    //-- If playrate != 1 ----------------------------------
    playrate  = GetMediaItemTakeInfo_Value(take, "D_PLAYRATE"); // get take orig playrate
    playrate != 1 ? (
      SetMediaItemTakeInfo_Value(take, "D_PLAYRATE", 1); // AA work faster with playrate = 1
      SetMediaItemInfo_Value(item, "D_LENGTH", item_len*playrate); // len*playrate 
    );
    //-- Define range(with regard orig playrate) -----------
    range_start = (sel_start-item_start)*playrate;  // range start
    range_len = (sel_end-sel_start)*playrate;       // range length
    range_len_smpls = floor(range_len*srate);       // range length to samples
    //-----------------------
    block_size = floor(65536/n_chans);  // full block size(samples), note MAX = 65536!!!
    //-----------------------
    n_blocks = floor(range_len_smpls/block_size);         // number of full blocks
    rest_smples = range_len_smpls - block_size*n_blocks;  // rest of samples(incomplete last block)
    
    //-- Set Filter and Gate Values from sliders -----------
    take_vol = GetMediaItemTakeInfo_Value(take, "D_VOL"); // regard take volume
    item_vol = GetMediaItemInfo_Value(item, "D_VOL");     // regard item volume
    vol_offs = VAL2DB(take_vol*item_vol);  // offset is subtracted from the comp threshold
    FilterB.SetValues(HPFreq.val, srate);
    EnvFollower.SetValues(0.2, 40, srate); // att-rel - constants(ms), can be changed
    CompD.SetValues(Thresh.val-vol_offs, Compress.val/100);
      
      //----------------------------------------------------
      AA = CreateTakeAudioAccessor(take);
      starttime_sec = range_start; // first block start
      samplebuf = 0;  // buffer for accessor samples
      envbuf = 65536; // buffer for envelope points
      cur_block = 0;
      trig = last_trig = 0;
      pnt_cnt = 0; 
      //-----------
      interval = ceil(Interval.val/1000 * srate);
      // -- Audio processing, search sibilance -------------
      loop(n_blocks+1,
          cur_block == n_blocks ? block_size = rest_smples; // last block = rested samples  
          //memset(0,0,block_size); // clear samplebuffer - Можно не чистить, но все же...???
          //GetAudioAccessorSamples(AA, srate, 1, starttime_sec, block_size, samplebuf); // get as mono
          GetAudioAccessorSamples(AA, srate, n_chans, starttime_sec, block_size, samplebuf); // get all channels
          //-- Average value(if more then one channel) -----
          n_chans > 1 ? (
            smpl = 0;
            loop(block_size,
              ch_smpl = smpl * n_chans;
              chan_sum = 0;
              loop(n_chans, chan_sum += samplebuf[ch_smpl]; ch_smpl+=1; ); // sum all channels
              samplebuf[smpl] = chan_sum/n_chans; // average value
              smpl+=1; 
            );
          );
            //---------------------------------          
            smpl = 0;
            loop(block_size,
                input = samplebuf[smpl];
                fltr_out = FilterB.Apply(input);
                env_out = EnvFollower.Apply(abs(fltr_out));
                comp_out = CompD.Apply(env_out);
      
                //-- Add comp point ---------
                comp_out < 1 ? (
                  trig = 1;
                  interval_cnt > interval ? (
                    envbuf[pnt_cnt] = starttime_sec + smpl/srate; // position
                    envbuf[pnt_cnt+1] = comp_out; // value
                    pnt_cnt+=2;
                    interval_cnt = 0;
                  );
                  interval_cnt+=1;
                ) : (
                  trig = 0;
                );
                
                //-- Add On-Off point -------
                trig != last_trig ? (
                  trig ? (oo_offs = -8; interval_cnt = interval+1;) : oo_offs = 8;
                  envbuf[pnt_cnt] = starttime_sec + (smpl+oo_offs)/srate; // position
                  envbuf[pnt_cnt+1] = 1; // value
                  pnt_cnt+=2;
                  last_trig = trig;
                );
                
                //---------------------------               
                smpl+=1;   
            );
          starttime_sec+=block_size/srate; // next block starttime
          cur_block+=1; // block counter
      );
      
      DestroyAudioAccessor(AA);
      //----------------------------------------------------
      CreateEnvelope(VolEnv, range_start, range_len, srate, envbuf, pnt_cnt); // Create Envelope
      //----------------------------------------------------
      playrate != 1 ? (
        SetMediaItemTakeInfo_Value(take, "D_PLAYRATE", playrate); // restore orig playrate
        SetMediaItemInfo_Value(item, "D_LENGTH", item_len);  // restore orig lengthstart_time
      );          
      Envelope_SortPoints(VolEnv);
      UpdateTimeline();
      UpdateArrange();          
  );  

);


//======================================================================================//
function MAIN()
local(item_cnt, item_idx, item, take, PCM_source, srate, n_chans, VolEnv)  
( 
  !hide_stats? start_time = time_precise(); // start time test
  //--------------------------  
  item_cnt = CountSelectedMediaItems(0);
  item_idx = 0;
  loop(item_cnt,
      //-- item, take data -------------
      item = GetSelectedMediaItem(0, item_idx);
      take = GetActiveTake(item);
      PCM_source = GetMediaItemTake_Source(take);
      srate = GetMediaSourceSampleRate(PCM_source);
      n_chans = GetMediaSourceNumChannels(PCM_source);
      VolEnv = GetTakeEnvelopeByName(take,"Volume");
      //-- rebuild - create envelope ---
      VolEnv && srate ? (
        RebuildVolEnvelope(item, take, srate, n_chans, VolEnv);
      );
      item_idx+=1;
  );
  //--------------------------
  !hide_stats? process_time  = time_precise() - start_time; // end time test

);


//----------------------------------------------------------
function Draw_Controls()
(
  //-- sliders ---------------
  Thresh.slider_draw();
  HPFreq.slider_draw();
  !hide_preopen? PreOpen.slider_draw();
  Compress.slider_draw();
  !hide_interval? Interval.slider_draw();
  //--------------------------
  Thresh.isReleased || HPFreq.isReleased ||
  PreOpen.isReleased || Compress.isReleased ||
  Interval.isReleased ? (
    Undo_OnStateChange("Envelope-based Deesser");
    RunMain = 1;
  );
  
  //-- buttons ---------------
  ActEnv.button_draw();
  Spectr.button_draw();
  VisEnv.button_draw();
  ActEnv.isClicked ? ToggleActVis_VolEnvelope("act");
  Spectr.isClicked ? Main_OnCommand(42294, 0); // Peaks: Toggle spectrogram
  VisEnv.isClicked ? ToggleActVis_VolEnvelope("vis");
 
  
  //--------------------------
  !hide_stats? (
    gfx_x = control_x_init*zoom;
    gfx_y = control_y_init * zoom + control_y_offset * (current_row(0)+1) * zoom;
    gfx_drawstr("Processing time: ");
    gfx_drawnumber(process_time,3);
    gfx_drawstr(" s");
  );

);

//-- mainloop ----------------------------------------------
function mainloop()
(
  //-- mouse and modkeys -----
  (mouse_cap&1 && !(last_mouse_cap&1))  ||    //-- L mouse
  (mouse_cap&2 && !(last_mouse_cap&2))  ||    //-- R mouse
  (mouse_cap&64 && !(last_mouse_cap&64)) ? (  //-- M mouse
    mouse_ox = mouse_x; mouse_oy = mouse_y;
  ); 

  Ctrl  = mouse_cap&4;  //-- Ctrl  state
  Shift = mouse_cap&8;  //-- Shift state
  Alt   = mouse_cap&16; //-- Shift state
  
  //-- Main functions etc ----
  Draw_Controls();
  RunMain? ( 
    MAIN(); 
    RunMain = 0; 
  ); 
  
  //--------------------------
  last_mouse_cap = mouse_cap;
  last_x = mouse_x; last_y = mouse_y;
  char = gfx_getchar();
  char==32 ? Main_OnCommand(40044, 0); //-- play
  char >= 0 ?
  (
    defer("mainloop();"); //-- defer
  ) :
  (
    hide_envelope_on_close && Main_OnCommand(NamedCommandLookup("_S&M_TAKEENVSHOW4"), 0);
    hide_spectrogram_on_close && GetToggleCommandState(42294) && Main_OnCommand(42294, 0); // Peaks: Toggle spectrogram
  );
  gfx_init("",width*zoom,height*zoom);
  gfx_update();
);

//-- init --------------------------------------------------
function Init()
( //-- window ----------------
  width = 270; height = 106; dockstate = 0; xpos = 1600; ypos = 900;
  !hide_preopen? height = height + control_y_offset;
  !hide_interval? height = height + control_y_offset;
  !hide_stats? height = height + control_y_offset;
  gfx_init("De-esser",width*zoom,height*zoom,dockstate,xpos,ypos);
  R = G = B = 20;
  gfx_clear = R + G*256 + B*65536;
  //-- Init mouse ------------
  last_mouse_cap = 0;
  last_x = last_y = 0;
  mouse_ox = mouse_oy = -1;
  
  gfx_setfont(1, "Calibri", font * zoom);

  on_by_default? Main_OnCommand(NamedCommandLookup("_S&M_TAKEENV1"), 0) : show_envelope_on_open? Main_OnCommand(NamedCommandLookup("_S&M_TAKEENVSHOW1"), 0);
  show_spetrogram_on_open? !GetToggleCommandState(42294) && Main_OnCommand(42294, 0); // Peaks: Toggle spectrogram
);

/*---------------------------------------
--- Start Script ------------------------
---------------------------------------*/
Init();
mainloop();

Last edited by abnegative; 01-20-2024 at 12:56 PM. Reason: fix bug
abnegative is offline   Reply With Quote
Old 01-20-2024, 09:14 AM   #33
tonalstates
Human being with feelings
 
tonalstates's Avatar
 
Join Date: Jun 2020
Posts: 656
Default

Hi, abnegative

I'm trying to use your script to check it out but I get errors when trying to save the script. These come from the "*" you're using in the beginning description of the script... at least for me, I wonder how you got it working without that error.

The error gives: unexpected symbol near "/" so I guess it's the "*"
tonalstates is online now   Reply With Quote
Old 01-20-2024, 10:02 AM   #34
Subz
Human being with feelings
 
Subz's Avatar
 
Join Date: Jun 2006
Location: UK
Posts: 3,210
Default

Quote:
Originally Posted by abnegative View Post
* [Function] Resizeable GUI
* [Function] Bind window size to GUI layout (user cannot resize window)
* [Function] Add button to toggle spectrogram
* [Function] New default values: Threshold = 0dB, High-Pass Frequency = 20000.00Hz, Compression = 100%
* [Optional] Automatically activate and show volume envelope upon launch
* [Optional] Automatically hide volume envelope upon exit
* [Optional] Automatically show spectrogram upon launch
* [Optional] Automatically hide spectrogram upon exit
* [Optional] Remove processing time for simplicity
* [Optional] Remove Pre-Open slider for simplicity (default to 0ms)
* [Optional] Remove Interval slider for simplicity (default to 1ms)
* [Aesthetics] Make colors brighter
* [Aesthetics] Move units to right of value
* [Aesthetics] Simplify window title to "De-esser"
* [Aesthetics] Relabel controls

Code:
/* 
   * ReaScript Name:Envelope-based Deesser
   * EEL script for Cockos REAPER
   * Author: EUGEN27771
   * Author URI: http://forum.cockos.com/member.php?u=50462
   * Licence: GPL v3
   * Version: 1.01
*/

/*
      * Human being with feelings: abnegative: https://forums.cockos.com/member.php?u=176590
      * [Function]    Resizeable GUI
      * [Function]    Bind window size to GUI layout (user cannot resize window)
      * [Function]    Add button to toggle spectrogram
      * [Function]    New default values: Threshold = 0dB, High-Pass Frequency = 20000.00Hz, Compression = 100%
      * [Optional]    Automatically activate and show volume envelope upon launch
      * [Optional]    Automatically hide volume envelope upon exit
      * [Optional]    Automatically show spectrogram upon launch
      * [Optional]    Automatically hide spectrogram upon exit
      * [Optional]    Remove processing time for simplicity
      * [Optional]    Remove Pre-Open slider for simplicity (default to 0ms)
      * [Optional]    Remove Interval slider for simplicity (default to 1ms)
      * [Aesthetics]  Make colors brighter
      * [Aesthetics]  Move units to right of value
      * [Aesthetics]  Simplify window title to "De-esser"
      * [Aesthetics]  Relabel controls
*/

//-- Script creates Envelope, based on the sibilance and compress it


/*
zoom:                       amount by which to scale the GUI size
on_by_default:              automatically activate and show the volume envelope upon launch
show_envelope_on_open:      automatically show the volume envelope upon launch
hide_envelope_on_close:     automatically hide the take volume envelope when the GUI is closed
show_spetrogram_on_open:    automatically show the spectrogram upon launch
hide_spectrogram_on_close:  automatically hide the spectrogram when the GUI is closed
hide_preopen:               hide the pre-open parameter in GUI for simplicity (no pre-open is applied)
hide_interval:              hide the interval parameter in GUI for simplicity (minimal interval used for highest resolution envelope points)
hide_stats:                 hide the processing time
*/
/*----------------------------------------------------------
=== User may modify the values below (see definitions above)
----------------------------------------------------------*/
zoom = 3;
on_by_default = 1;
show_envelope_on_open = 1;
hide_envelope_on_close = 1;
show_spetrogram_on_open = 1;
hide_spectrogram_on_close = 1;
hide_preopen = 1;
hide_interval = 1;
hide_stats = 1;
/*----------------------------------------------------------
=== DO NOT EDIT BELOW THIS LINE ============================
----------------------------------------------------------*/


font = 16;
control_x_init = 5;
control_y_init = 5;
control_y_offset = 25;
slider_w = 260;
slider_h = 18;
button_w = 80;
button_h = 20;
button_x_offset = 90;
row = -1;

function current_row(new_row)
(
  new_row? row = row + 1;
  row;
);

/*----------------------------------------------------------
=== Filter, Comp, Gate etc functions =======================
----------------------------------------------------------*/
// -- DB2VAL - VAL2DB(from SDK) ------------------
function DB2VAL(x)
(
  exp((x)*0.11512925464970228420089957273422);
);
//----------------------------
function VAL2DB(x)
  local(v)
(
  x < 0.0000000298023223876953125 ? (
    -150; 
  ) : (
    v = log(x)*8.6858896380650365530225783783321;
    v < -150 ? -150 : v;
  );
);

// -- Filter -------------------------------------
function FilterB.SetValues(cutoffFreq, samplerate)
  local(sqr2, c, c2, csqr2, d)
  instance(ampIn0, ampIn1, ampIn2, ampOut1, ampOut2)    
(
  // samplerate can be different from the global srate if need
  sqr2 = 1.414213562;
  c = tan(($pi/samplerate) * cutoffFreq );
  c2 = c * c;
  csqr2 = sqr2 * c;
  d = (c2 + csqr2 + 1);
  
  ampIn0 = 1 / d;
  ampIn1 = -(ampIn0 + ampIn0);
  ampIn2 = ampIn0;
  
  ampOut1 = (2 * (c2 - 1)) / d;
  ampOut2 = (1 - csqr2 + c2) / d;
);
//----------------------------
function FilterB.Apply(in)
  instance(ampIn0, ampIn1, ampIn2, ampOut1, ampOut2, dlyIn1, dlyIn2, dlyOut1, dlyOut2, out)
(
  out = (ampIn0 * in) + (ampIn1 * dlyIn1) + (ampIn2 * dlyIn2) - (ampOut1 * dlyOut1) - (ampOut2 * dlyOut2);
  
  dlyOut2 = dlyOut1;
  dlyOut1 = out;
  dlyIn2 = dlyIn1;
  dlyIn1 = in;
  out;
);

// -- Gate ---------------------------------------
function GateD.SetValues(attThresh_dB, hysteresis_dB, hold_ms, samplerate)
  instance(attThresh, relThresh, hold)    
( 
  // samplerate can be different from the global srate if need
  attThresh  = 10^(attThresh_dB/20);
  relThresh  = 10^((attThresh_dB + hysteresis_dB)/20);
  hold = samplerate * hold_ms/1000;
);
//----------------------------
function GateD.Apply(in)
  instance(attThresh, relThresh, hold, hold_cnt, trig)
(
  in > attThresh ? (
    trig = 1;
    hold_cnt = 0;
  ) : ( 
     hold_cnt > hold && in < relThresh ? trig = 0;
     hold_cnt+=1;
  );
  trig;
);

// -- Env follower -------------------------------
function EnvFollower.SetValues(attack_ms, release_ms, samplerate)
(
  // samplerate can be different from the global srate if need
  // -- ga, gr coeff --
  this.ga = exp(-1/(samplerate*attack_ms/1000));
  this.gr = exp(-1/(samplerate*release_ms/1000)); 
);
//----------------------------
function EnvFollower.Apply(in)
  instance(ga, gr, out)
(
  out < in ? out = in + ga*(out-in) : out = in + gr*(out-in); 
);

// -- Compressor ---------------------------------
function CompD.SetValues(thresh_dB, ratio)
(
  this.thresh_dB = thresh_dB;
  this.thresh = 10^(thresh_dB/20);
  this.ratio = ratio;
);
//----------------------------
function CompD.Apply(in) // -- dB var
  instance(thresh_dB, thresh, ratio, out_dB, out)
(
  in > thresh ? (
    out_dB = ratio * (thresh_dB - VAL2DB(in));
    out = DB2VAL(out_dB);
  ) : (
    out_dB = 0;
    out = 1;
  ); 
);

/*----------------------------------------------------------
=== New button, slider functions ===========================
----------------------------------------------------------*/
//-- New button function -------
function button_New(x,y,w,h, r,g,b,a, lbl)
(
  this.x = x; this.y = y; this.w = w; this.h = h; // coord
  this.r = r; this.g = g; this.b = b; this.a = a; // color
  this.lbl = lbl;
);

//-- New slider function -------
function slider_New(x,y,w,h, r,g,b,a, lbl, val,min_val,max_val,units)
(
  this.x = x; this.y = y; this.w = w; this.h = h; // coord
  this.r = r; this.g = g; this.b = b; this.a = a; // color
  this.lbl = lbl;
  this.val = val;
  this.min_val = min_val; 
  this.max_val = max_val;
  this.norm_val = (val - min_val)/(max_val - min_val); // norm value
  this.units = units;
);


/*----------------------------------------------------------
=== Simple Get mouse functions =============================
----------------------------------------------------------*/
//------------------
function pointIN(p_x, p_y)
  instance(x,y,w,h)
( // if point in obj area
  p_x >= x && p_x <= x+w && p_y >= y && p_y <= y+h;
);

function mouseIN()
( // if mouse in obj area
  !(mouse_cap&1) && this.pointIN(mouse_x, mouse_y);
);

//------------------
function mouseDown()
( // if mouse has been pressed in obj area
  mouse_cap&1 && this.pointIN(mouse_ox,mouse_oy);
);

function mouseUp()
( // if mouse released(anywhere) and has been pressed in obj area
  last_mouse_cap&1 && !(mouse_cap&1) && this.pointIN(mouse_ox,mouse_oy);
);

function mouseClick()
( // if mouse released in obj area and has been pressed in obj area
  last_mouse_cap&1 && !(mouse_cap&1) && 
  this.pointIN(mouse_x, mouse_y) && this.pointIN(mouse_ox,mouse_oy);
);
//------------------
function mouseR_Down()
( // if mouse R has been pressed in obj area
  mouse_cap&2 && this.pointIN(mouse_ox,mouse_oy);
);

function mouseM_Down()
( // if mouse M has been pressed in obj area
  mouse_cap&64 && this.pointIN(mouse_ox,mouse_oy);
);


/*----------------------------------------------------------
=== SLIDER =================================================
----------------------------------------------------------*/
//-- Set slider value ------------------
function slider_set_value()
  instance(x,y,w,h, val,min_val,max_val, norm_val)
  local(nv, K )
(
  K = 10; // K = coeff(when Ctrl pressed)
  Ctrl ? (
    nv = norm_val + (mouse_x-last_x)/(w*K);
  ) : (
    nv = (mouse_x-x)/w;
  );
  
  nv != norm_val ? (
    norm_val = min( max(nv, 0), 1 ); // verify and set values
    val = min_val + (max_val-min_val)*norm_val;
    this.isChanged = 1;
  );
); 

//-- Draw slider -----------------------
function slider_draw()
  instance(x,y,w,h, r,g,b,a, lbl, val, norm_val, units)
  local(aa, val_str, str_w, str_h)
  
( 
  aa = a;
  this.isChanged = this.isReleased = 0; // reset 
  this.mouseIN() ? aa = a + 0.1;
  this.mouseDown() ? (
    aa = a + 0.2;
    this.slider_set_value();
  );
  
  this.mouseUp() ? this.isReleased = 1;
  
  //-- draw body, frame ------
  gfx_set(r,g,b,aa);
  gfx_rect(x,y,w,h, 0);
  gfx_rect(x, y, w*norm_val, h, 1);
  //-- draw label ------------
  gfx_set(0.9,0.8,0.5,0.9);
  gfx_measurestr(lbl, str_w, str_h);
  gfx_x = x + 5; gfx_y = y + (h-str_h)/2;
  gfx_drawstr(lbl);
  //-- draw value ------------
  val_str = sprintf(#, "%.2f%s", val, units); 
  gfx_measurestr(val_str, str_w, str_h);
  gfx_x = x - 5 + w - str_w; gfx_y = y + (h-str_h)/2;
  gfx_drawstr(val_str);
);


/*----------------------------------------------------------
=== BUTTON =================================================
----------------------------------------------------------*/
//-- Draw button -----------------------
function button_draw()
  instance(x,y,w,h, r,g,b,a, lbl)
  local(aa, str_w, str_h)
(   
  aa = a;
  this.mouseIN() ? aa = a + 0.1;
  this.mouseDown() ? aa = a + 0.2; 
  this.mouseClick() ? this.isClicked = 1 : this.isClicked = 0;
  
  //-- draw body, frame ------
  gfx_set(r,g,b,aa);
  gfx_rect(x,y,w,h, 1);
  gfx_rect(x,y,w,h, 0); // frame
  //-- draw label ------------
  gfx_set(0.9,0.8,0.5,0.9);
  gfx_measurestr(lbl, str_w, str_h);
  gfx_x = x + (w-str_w)/2; gfx_y = y + (h-str_h)/2;
  gfx_drawstr(lbl);

);


/*----------------------------------------------------------------------------------------
=== Create controls ======================================================================
----------------------------------------------------------------------------------------*/

//-- Create Sliders --------------------
//-- args = (x,y,w,h, r,g,b,a, lbl, val,min_val,max_val,units)
Thresh.slider_New(control_x_init*zoom,control_y_init * zoom + control_y_offset * current_row(1) * zoom,slider_w * zoom,slider_h * zoom,    5,0.3,0.3,0.2, "Threshold",    0,  -48,     0, " dB" );
HPFreq.slider_New(control_x_init*zoom,control_y_init * zoom + control_y_offset * current_row(1) * zoom,slider_w * zoom,slider_h * zoom,    0.4,5,0.5,0.2, "High-Pass Frequency",     20000, 2000, 20000, " Hz" );
!hide_preopen? PreOpen.slider_New(control_x_init*zoom,control_y_init * zoom + control_y_offset * current_row(1) * zoom,slider_w * zoom,slider_h * zoom,   0.4,5,0.5,0.2, "Pre-Open",        0,   0,    20, " ms" );
!hide_interval? Interval.slider_New(control_x_init*zoom,control_y_init * zoom + control_y_offset * current_row(1) * zoom,slider_w * zoom,slider_h * zoom,  0.4,5,0.5,0.2, "Interval",       1,    1,    10, " ms" );
Compress.slider_New(control_x_init*zoom,control_y_init * zoom + control_y_offset * current_row(1) * zoom,slider_w * zoom,slider_h * zoom, 0.3,0.4,5,0.2, "Compression",    100,    0,   100, " %" );

//-- Create Buttons --------------------
//-- args = (x,y,w,h, r,g,b,a, lbl)
ActEnv.button_New(control_x_init*zoom + 0*button_x_offset*zoom,control_y_init * zoom + control_y_offset * current_row(1) * zoom,button_w * zoom,button_h * zoom,   0.5,0.3,0.3,0.2, "Activate");
Spectr.button_New(control_x_init*zoom + 1*button_x_offset*zoom,control_y_init * zoom + control_y_offset * current_row(0) * zoom,button_w * zoom,button_h * zoom,  0.5,0.3,0.3,0.2, "Spectrogram");
VisEnv.button_New(control_x_init*zoom + 2*button_x_offset*zoom,control_y_init * zoom + control_y_offset * current_row(0) * zoom,button_w * zoom,button_h * zoom,  0.5,0.3,0.3,0.2, "Visibility");


//======================================================================================//


//----------------------------------------------------------------------------------------
//--- Toggle active, visible vol envelope ------------------------------------------------
//----------------------------------------------------------------------------------------
function ToggleActVis_VolEnvelope(mode)
  local(item_cnt, item_idx, item, take, VolEnv, BR_Env,
        BR_Env, active,visible,armed, inLane,laneHeight, 
        defShape, minVal,maxVal,centerVal, type, faderScaling)   
(
  item_cnt = CountSelectedMediaItems(0);
  item_cnt ? Undo_OnStateChange("Envelope-based Deesser");
  item_idx=0;
  loop(item_cnt,
      item = GetSelectedMediaItem(0, item_idx);
      take = GetActiveTake(item);
      VolEnv = GetTakeEnvelopeByName(take,"Volume"); // Get take "Volume" envelope
      
      //-- Toggle act,vis depend of mode(if VolEnv exists) -----
      VolEnv ? (
        BR_Env = extension_api("BR_EnvAlloc", VolEnv, 0);
        extension_api("BR_EnvGetProperties", BR_Env, active,visible,armed, inLane,laneHeight, 
                      defShape, minVal,maxVal,centerVal, type, faderScaling);
        mode == "act" ? active  = !active;  // toggle active
        mode == "vis" ? visible = !visible; // toggle visible
        extension_api("BR_EnvSetProperties", BR_Env, active,visible,armed, inLane,laneHeight, 
                      defShape, faderScaling);
        extension_api("BR_EnvFree", BR_Env, 1);

      ) : (
        //-- Create(if VolEnv no exist) ----
        Main_OnCommand(NamedCommandLookup("_S&M_TAKEENV1"), 0);
        VolEnv = GetTakeEnvelopeByName(take,"Volume");
      );
      item_idx+=1;
  );

);

//----------------------------------------------------------------------------------------
//--- Rebuild volume envelope ------------------------------------------------------------
//----------------------------------------------------------------------------------------

function CreateEnvelope(VolEnv, range_start, range_len, srate, envbuf, pnt_cnt)
  local(PreOpen, env_mode, shape,tens,sel,nosort, val,val1, rs_val,re_val, i, pos)     
(
  PreOpen = PreOpen.val/1000;
  //--------------------------
  env_mode = GetEnvelopeScalingMode(VolEnv);     // get VolEnv scaling mode
  val1 = ScaleToEnvelopeMode(env_mode, 1);       // Scaled  val=1
  //shape = 2; tens = 0; sel = 0; nosort = 1;    // def for new deess points 1
  shape = 0; tens = 0; sel = 0; nosort = 1;      // def for new deess points 2
  
  //-- Del Old points, Ins points at edges(use cur values) ------
  Envelope_Evaluate(VolEnv, range_start, srate, 0, rs_val);           // get env val at start
  Envelope_Evaluate(VolEnv, range_start+range_len, srate, 0, re_val); // get env val at end
  DeleteEnvelopePointRange(VolEnv, range_start-0.0001, range_start+range_len+0.0001); // Del Old points 
  //--------------------------
  InsertEnvelopePoint(VolEnv, range_start, rs_val, 0, 0, 0, 1);           // Insert point=curval at start
  InsertEnvelopePoint(VolEnv, range_start, val1, 0, 0, 0, 1);             // Insert point=1 at start
  InsertEnvelopePoint(VolEnv, range_start+range_len, val1, 0, 0, 0, 1);   // Insert point=1 at end
  InsertEnvelopePoint(VolEnv, range_start+range_len, re_val, 0, 0, 0, 1); // Insert point=curval at end
  
  //--------------------------
  i = 0;
  while(envbuf[i] <= range_start + PreOpen && i < pnt_cnt)( 
    i+=2; pnt_cnt-=2; // Если точки выходят за range_start!
  );
  //--------------------------

  loop(pnt_cnt*0.5,
    pos = envbuf[i] - PreOpen;
    val = ScaleToEnvelopeMode(env_mode,  envbuf[i+1]);   // Scale point val
    // -----------------------
    InsertEnvelopePoint(VolEnv, pos, val, shape, tens, sel, nosort); // Insert point        
    i+=2;  
  );
);

//----------------------------------------------------------------------------------------
//--- Rebuild volume envelope ------------------------------------------------------------
//----------------------------------------------------------------------------------------
function RebuildVolEnvelope(item, take, srate, n_chans, VolEnv)
  local(item_start, item_len, sel_start, sel_end, playrate, range_start, range_len, range_len_smpls, 
        block_size, n_blocks, rest_smples, AA, starttime_sec, samplebuf, smpl, ch_smpl, chan_sum, cur_block, envbuf,
        take_vol, item_vol, vol_offs, 
        trig, last_trig, input, fltr_out, env_out, comp_out, pnt_cnt, interval, interval_cnt, oo_offs)
( 
  item_start = GetMediaItemInfo_Value(item, "D_POSITION"); // item position
  item_len  = GetMediaItemInfo_Value(item, "D_LENGTH");    // item orig length
  GetSet_LoopTimeRange(0, 0, sel_start, sel_end, 0);       // get time selection
  !(sel_end - sel_start) ? (       // if no selection, then
    sel_start = item_start;        // use item start
    sel_end = item_start+item_len; // use item end
  );
  sel_start = max(sel_start, item_start);         // if sel_start or sel_end out of item, then
  sel_end   = min(sel_end, item_start+item_len);  // use item_start, item_end respectively
  //sel_end - sel_start < 0 ? MB("Time selection out of item range!", "Note", 0); 
  
  
  //----------------------------------------------------------------------------
  sel_end - sel_start > 0 ? ( 
    //-- If playrate != 1 ----------------------------------
    playrate  = GetMediaItemTakeInfo_Value(take, "D_PLAYRATE"); // get take orig playrate
    playrate != 1 ? (
      SetMediaItemTakeInfo_Value(take, "D_PLAYRATE", 1); // AA work faster with playrate = 1
      SetMediaItemInfo_Value(item, "D_LENGTH", item_len*playrate); // len*playrate 
    );
    //-- Define range(with regard orig playrate) -----------
    range_start = (sel_start-item_start)*playrate;  // range start
    range_len = (sel_end-sel_start)*playrate;       // range length
    range_len_smpls = floor(range_len*srate);       // range length to samples
    //-----------------------
    block_size = floor(65536/n_chans);  // full block size(samples), note MAX = 65536!!!
    //-----------------------
    n_blocks = floor(range_len_smpls/block_size);         // number of full blocks
    rest_smples = range_len_smpls - block_size*n_blocks;  // rest of samples(incomplete last block)
    
    //-- Set Filter and Gate Values from sliders -----------
    take_vol = GetMediaItemTakeInfo_Value(take, "D_VOL"); // regard take volume
    item_vol = GetMediaItemInfo_Value(item, "D_VOL");     // regard item volume
    vol_offs = VAL2DB(take_vol*item_vol);  // offset is subtracted from the comp threshold
    FilterB.SetValues(HPFreq.val, srate);
    EnvFollower.SetValues(0.2, 40, srate); // att-rel - constants(ms), can be changed
    CompD.SetValues(Thresh.val-vol_offs, Compress.val/100);
      
      //----------------------------------------------------
      AA = CreateTakeAudioAccessor(take);
      starttime_sec = range_start; // first block start
      samplebuf = 0;  // buffer for accessor samples
      envbuf = 65536; // buffer for envelope points
      cur_block = 0;
      trig = last_trig = 0;
      pnt_cnt = 0; 
      //-----------
      interval = ceil(Interval.val/1000 * srate);
      // -- Audio processing, search sibilance -------------
      loop(n_blocks+1,
          cur_block == n_blocks ? block_size = rest_smples; // last block = rested samples  
          //memset(0,0,block_size); // clear samplebuffer - Можно не чистить, но все же...???
          //GetAudioAccessorSamples(AA, srate, 1, starttime_sec, block_size, samplebuf); // get as mono
          GetAudioAccessorSamples(AA, srate, n_chans, starttime_sec, block_size, samplebuf); // get all channels
          //-- Average value(if more then one channel) -----
          n_chans > 1 ? (
            smpl = 0;
            loop(block_size,
              ch_smpl = smpl * n_chans;
              chan_sum = 0;
              loop(n_chans, chan_sum += samplebuf[ch_smpl]; ch_smpl+=1; ); // sum all channels
              samplebuf[smpl] = chan_sum/n_chans; // average value
              smpl+=1; 
            );
          );
            //---------------------------------          
            smpl = 0;
            loop(block_size,
                input = samplebuf[smpl];
                fltr_out = FilterB.Apply(input);
                env_out = EnvFollower.Apply(abs(fltr_out));
                comp_out = CompD.Apply(env_out);
      
                //-- Add comp point ---------
                comp_out < 1 ? (
                  trig = 1;
                  interval_cnt > interval ? (
                    envbuf[pnt_cnt] = starttime_sec + smpl/srate; // position
                    envbuf[pnt_cnt+1] = comp_out; // value
                    pnt_cnt+=2;
                    interval_cnt = 0;
                  );
                  interval_cnt+=1;
                ) : (
                  trig = 0;
                );
                
                //-- Add On-Off point -------
                trig != last_trig ? (
                  trig ? (oo_offs = -8; interval_cnt = interval+1;) : oo_offs = 8;
                  envbuf[pnt_cnt] = starttime_sec + (smpl+oo_offs)/srate; // position
                  envbuf[pnt_cnt+1] = 1; // value
                  pnt_cnt+=2;
                  last_trig = trig;
                );
                
                //---------------------------               
                smpl+=1;   
            );
          starttime_sec+=block_size/srate; // next block starttime
          cur_block+=1; // block counter
      );
      
      DestroyAudioAccessor(AA);
      //----------------------------------------------------
      CreateEnvelope(VolEnv, range_start, range_len, srate, envbuf, pnt_cnt); // Create Envelope
      //----------------------------------------------------
      playrate != 1 ? (
        SetMediaItemTakeInfo_Value(take, "D_PLAYRATE", playrate); // restore orig playrate
        SetMediaItemInfo_Value(item, "D_LENGTH", item_len);  // restore orig lengthstart_time
      );          
      Envelope_SortPoints(VolEnv);
      UpdateTimeline();
      UpdateArrange();          
  );  

);


//======================================================================================//
function MAIN()
local(item_cnt, item_idx, item, take, PCM_source, srate, n_chans, VolEnv)  
( 
  !hide_stats? start_time = time_precise(); // start time test
  //--------------------------  
  item_cnt = CountSelectedMediaItems(0);
  item_idx = 0;
  loop(item_cnt,
      //-- item, take data -------------
      item = GetSelectedMediaItem(0, item_idx);
      take = GetActiveTake(item);
      PCM_source = GetMediaItemTake_Source(take);
      srate = GetMediaSourceSampleRate(PCM_source);
      n_chans = GetMediaSourceNumChannels(PCM_source);
      VolEnv = GetTakeEnvelopeByName(take,"Volume");
      //-- rebuild - create envelope ---
      VolEnv && srate ? (
        RebuildVolEnvelope(item, take, srate, n_chans, VolEnv);
      );
      item_idx+=1;
  );
  //--------------------------
  !hide_stats? process_time  = time_precise() - start_time; // end time test

);


//----------------------------------------------------------
function Draw_Controls()
(
  //-- sliders ---------------
  Thresh.slider_draw();
  HPFreq.slider_draw();
  !hide_preopen? PreOpen.slider_draw();
  Compress.slider_draw();
  !hide_interval? Interval.slider_draw();
  //--------------------------
  Thresh.isReleased || HPFreq.isReleased ||
  PreOpen.isReleased || Compress.isReleased ||
  Interval.isReleased ? (
    Undo_OnStateChange("Envelope-based Deesser");
    RunMain = 1;
  );
  
  //-- buttons ---------------
  ActEnv.button_draw();
  Spectr.button_draw();
  VisEnv.button_draw();
  ActEnv.isClicked ? ToggleActVis_VolEnvelope("act");
  Spectr.isClicked ? Main_OnCommand(42294, 0); // Peaks: Toggle spectrogram
  VisEnv.isClicked ? ToggleActVis_VolEnvelope("vis");
 
  
  //--------------------------
  !hide_stats? (
    gfx_x = control_x_init*zoom;
    gfx_y = control_y_init * zoom + control_y_offset * (current_row(0)+1) * zoom;
    gfx_drawstr("Processing time: ");
    gfx_drawnumber(process_time,3);
    gfx_drawstr(" s");
  );

);

//-- mainloop ----------------------------------------------
function mainloop()
(
  //-- mouse and modkeys -----
  (mouse_cap&1 && !(last_mouse_cap&1))  ||    //-- L mouse
  (mouse_cap&2 && !(last_mouse_cap&2))  ||    //-- R mouse
  (mouse_cap&64 && !(last_mouse_cap&64)) ? (  //-- M mouse
    mouse_ox = mouse_x; mouse_oy = mouse_y;
  ); 

  Ctrl  = mouse_cap&4;  //-- Ctrl  state
  Shift = mouse_cap&8;  //-- Shift state
  Alt   = mouse_cap&16; //-- Shift state
  
  //-- Main functions etc ----
  Draw_Controls();
  RunMain? ( 
    MAIN(); 
    RunMain = 0; 
  ); 
  
  //--------------------------
  last_mouse_cap = mouse_cap;
  last_x = mouse_x; last_y = mouse_y;
  char = gfx_getchar();
  char==32 ? Main_OnCommand(40044, 0); //-- play
  char >= 0 ?
  (
    defer("mainloop();"); //-- defer
  ) :
  (
    hide_envelope_on_close && Main_OnCommand(NamedCommandLookup("_S&M_TAKEENVSHOW4"), 0);
    hide_spectrogram_on_close && GetToggleCommandState(42294) && Main_OnCommand(42294, 0); // Peaks: Toggle spectrogram
  );
  gfx_init("",width*zoom,height*zoom);
  gfx_update();
);

//-- init --------------------------------------------------
function Init()
( //-- window ----------------
  width = 270; height = 106; dockstate = 0; xpos = 1600; ypos = 900;
  !hide_preopen? height = height + control_y_offset;
  !hide_interval? height = height + control_y_offset;
  !hide_stats? height = height + control_y_offset;
  gfx_init("De-esser",width*zoom,height*zoom,dockstate,xpos,ypos);
  R = G = B = 20;
  gfx_clear = R + G*256 + B*65536;
  //-- Init mouse ------------
  last_mouse_cap = 0;
  last_x = last_y = 0;
  mouse_ox = mouse_oy = -1;
  
  gfx_setfont(1, "Calibri", font * zoom);

  on_by_default? Main_OnCommand(NamedCommandLookup("_S&M_TAKEENV1"), 0) : show_envelope_on_open? Main_OnCommand(NamedCommandLookup("_S&M_TAKEENVSHOW1"), 0);
  show_spetrogram_on_open? !GetToggleCommandState(42294) && Main_OnCommand(42294, 0); // Peaks: Toggle spectrogram
);

/*---------------------------------------
--- Start Script ------------------------
---------------------------------------*/
Init();
mainloop();

When I edit parameters, it only processes the first minute of a file?

If I go with the default settings that it loads it processes the full item, not just the first minute

Subz
Subz is offline   Reply With Quote
Old 01-20-2024, 10:08 AM   #35
Subz
Human being with feelings
 
Subz's Avatar
 
Join Date: Jun 2006
Location: UK
Posts: 3,210
Default

Quote:
Originally Posted by eugen2777 View Post
The script creates volume envelope based on the sibilance and compress it.

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


==============
How use:
Select the audio-item(or several items).
Set time selection, if you want to process only a specific area.
Click "Activate Envelope" and "Show Envelope" button if need.
"Show Envelope" - toggle show/hide take vol envelope.
"Activate Envelope" - toggle activate/deactivate take vol envelope.

Use the sliders to adjust take volume envelope.

===============
Link(will be updated):
gen_Envelope-based Deesser.eel

Note: Needed SWS - latest version.

===============
How install - it is actual for all eel-scripts(unless otherwise stated):
Open Reaper. Actions>Show Action List. ReaScript: press "New".
Select the folder for scripts(By default - ...\Reaper\Scripts).
Specify the name and extension - .eel(it's mandatory). For Example, MyScript.eel. Click save. You will see a black window.
Copy the text of the script(link in the first post) in this window. Press Ctrl+S. Close the window. Now the script is available in the Action List.
===
In addition, you can use Reapack, but the link to my repository must be added manually
This is excellent!!

Thank You

Subz
Subz is offline   Reply With Quote
Old 01-20-2024, 11:16 AM   #36
abnegative
Human being with feelings
 
Join Date: Sep 2022
Posts: 222
Default

Quote:
Originally Posted by tonalstates View Post
The error gives: unexpected symbol near "/" so I guess it's the "*"
Hi tonalstates,

It sounds like it may have been a copy-paste error? I'll upload the file next time once I fix the issue Subz brought to my attention.


Quote:
Originally Posted by Subz View Post
When I edit parameters, it only processes the first minute of a file?

If I go with the default settings that it loads it processes the full item, not just the first minute

Subz
Thanks for pointing this out (should've tested on a longer sample!). Looking into it now.
abnegative is offline   Reply With Quote
Old 01-20-2024, 11:23 AM   #37
hans
Human being with feelings
 
Join Date: Aug 2020
Posts: 276
Default

perhaps you're trying to paste this code in a .lua script? It's EEL
hans is offline   Reply With Quote
Old 01-20-2024, 12:47 PM   #38
abnegative
Human being with feelings
 
Join Date: Sep 2022
Posts: 222
Default Added new features & Modifications [delta_v1]

* [Function] Resizeable GUI (static, set within script)
* [Function] Bind window size to GUI layout (user cannot resize window)
* [Function] Add button to toggle spectrogram
* [Function] New default values: Threshold = 0dB, High-Pass Frequency = 20000.00Hz, Compression = 100%
* [Optional] Automatically activate and show volume envelope upon launch
* [Optional] Automatically hide volume envelope upon exit
* [Optional] Automatically show spectrogram upon launch
* [Optional] Automatically hide spectrogram upon exit
* [Optional] Remove processing time for simplicity
* [Optional] Remove Pre-Open slider for simplicity (default to 0ms)
* [Optional] Remove Interval slider for simplicity (default to 1ms)
* [Aesthetics] Make colors brighter
* [Aesthetics] Move units to right of value
* [Aesthetics] Simplify window title to "De-esser"
* [Aesthetics] Relabel controls

If you copy the code from here, please save it as a .eel file.
I'm considering making further changes to save external state in order to recall last used settings, so stay tuned for a (possible) new post with delta_v2 in the title.
I'm also considering making similar changes to EEL:Envelope-based Compressor


Code:
/* 
   * ReaScript Name:Envelope-based Deesser
   * EEL script for Cockos REAPER
   * Author: EUGEN27771
   * Author URI: http://forum.cockos.com/member.php?u=50462
   * Licence: GPL v3
   * Version: 1.01
*/

/*
      * Human being with feelings: abnegative: https://forums.cockos.com/member.php?u=176590
      * [Function]    Resizeable GUI
      * [Function]    Bind window size to GUI layout (user cannot resize window)
      * [Function]    Add button to toggle spectrogram
      * [Function]    New default values: Threshold = 0dB, High-Pass Frequency = 20000.00Hz, Compression = 100%
      * [Optional]    Automatically activate and show volume envelope upon launch
      * [Optional]    Automatically hide volume envelope upon exit
      * [Optional]    Automatically show spectrogram upon launch
      * [Optional]    Automatically hide spectrogram upon exit
      * [Optional]    Remove processing time for simplicity
      * [Optional]    Remove Pre-Open slider for simplicity (default to 0ms)
      * [Optional]    Remove Interval slider for simplicity (default to 1ms)
      * [Aesthetics]  Make colors brighter
      * [Aesthetics]  Move units to right of value
      * [Aesthetics]  Simplify window title to "De-esser"
      * [Aesthetics]  Relabel controls
*/

//-- Script creates Envelope, based on the sibilance and compress it


/*
zoom:                       amount by which to scale the GUI size
on_by_default:              automatically activate and show the volume envelope upon launch
show_envelope_on_open:      automatically show the volume envelope upon launch
hide_envelope_on_close:     automatically hide the take volume envelope when the GUI is closed
show_spetrogram_on_open:    automatically show the spectrogram upon launch
hide_spectrogram_on_close:  automatically hide the spectrogram when the GUI is closed
hide_preopen:               hide the pre-open parameter in GUI for simplicity (no pre-open is applied)
hide_interval:              hide the interval parameter in GUI for simplicity (minimal interval used for highest resolution envelope points)
hide_stats:                 hide the processing time
*/
/*----------------------------------------------------------
=== User may modify the values below (see definitions above)
----------------------------------------------------------*/
zoom = 3;
on_by_default = 1;
show_envelope_on_open = 1;
hide_envelope_on_close = 1;
show_spetrogram_on_open = 1;
hide_spectrogram_on_close = 1;
hide_preopen = 1;
hide_interval = 1;
hide_stats = 1;
/*----------------------------------------------------------
=== DO NOT EDIT BELOW THIS LINE ============================
----------------------------------------------------------*/


font = 16;
control_x_init = 5;
control_y_init = 5;
control_y_offset = 25;
slider_w = 260;
slider_h = 18;
button_w = 80;
button_h = 20;
button_x_offset = 90;
row = -1;

function current_row(new_row)
(
  new_row? row = row + 1;
  row;
);

/*----------------------------------------------------------
=== Filter, Comp, Gate etc functions =======================
----------------------------------------------------------*/
// -- DB2VAL - VAL2DB(from SDK) ------------------
function DB2VAL(x)
(
  exp((x)*0.11512925464970228420089957273422);
);
//----------------------------
function VAL2DB(x)
  local(v)
(
  x < 0.0000000298023223876953125 ? (
    -150; 
  ) : (
    v = log(x)*8.6858896380650365530225783783321;
    v < -150 ? -150 : v;
  );
);

// -- Filter -------------------------------------
function FilterB.SetValues(cutoffFreq, samplerate)
  local(sqr2, c, c2, csqr2, d)
  instance(ampIn0, ampIn1, ampIn2, ampOut1, ampOut2)    
(
  // samplerate can be different from the global srate if need
  sqr2 = 1.414213562;
  c = tan(($pi/samplerate) * cutoffFreq );
  c2 = c * c;
  csqr2 = sqr2 * c;
  d = (c2 + csqr2 + 1);
  
  ampIn0 = 1 / d;
  ampIn1 = -(ampIn0 + ampIn0);
  ampIn2 = ampIn0;
  
  ampOut1 = (2 * (c2 - 1)) / d;
  ampOut2 = (1 - csqr2 + c2) / d;
);
//----------------------------
function FilterB.Apply(in)
  instance(ampIn0, ampIn1, ampIn2, ampOut1, ampOut2, dlyIn1, dlyIn2, dlyOut1, dlyOut2, out)
(
  out = (ampIn0 * in) + (ampIn1 * dlyIn1) + (ampIn2 * dlyIn2) - (ampOut1 * dlyOut1) - (ampOut2 * dlyOut2);
  
  dlyOut2 = dlyOut1;
  dlyOut1 = out;
  dlyIn2 = dlyIn1;
  dlyIn1 = in;
  out;
);

// -- Gate ---------------------------------------
function GateD.SetValues(attThresh_dB, hysteresis_dB, hold_ms, samplerate)
  instance(attThresh, relThresh, hold)    
( 
  // samplerate can be different from the global srate if need
  attThresh  = 10^(attThresh_dB/20);
  relThresh  = 10^((attThresh_dB + hysteresis_dB)/20);
  hold = samplerate * hold_ms/1000;
);
//----------------------------
function GateD.Apply(in)
  instance(attThresh, relThresh, hold, hold_cnt, trig)
(
  in > attThresh ? (
    trig = 1;
    hold_cnt = 0;
  ) : ( 
     hold_cnt > hold && in < relThresh ? trig = 0;
     hold_cnt+=1;
  );
  trig;
);

// -- Env follower -------------------------------
function EnvFollower.SetValues(attack_ms, release_ms, samplerate)
(
  // samplerate can be different from the global srate if need
  // -- ga, gr coeff --
  this.ga = exp(-1/(samplerate*attack_ms/1000));
  this.gr = exp(-1/(samplerate*release_ms/1000)); 
);
//----------------------------
function EnvFollower.Apply(in)
  instance(ga, gr, out)
(
  out < in ? out = in + ga*(out-in) : out = in + gr*(out-in); 
);

// -- Compressor ---------------------------------
function CompD.SetValues(thresh_dB, ratio)
(
  this.thresh_dB = thresh_dB;
  this.thresh = 10^(thresh_dB/20);
  this.ratio = ratio;
);
//----------------------------
function CompD.Apply(in) // -- dB var
  instance(thresh_dB, thresh, ratio, out_dB, out)
(
  in > thresh ? (
    out_dB = ratio * (thresh_dB - VAL2DB(in));
    out = DB2VAL(out_dB);
  ) : (
    out_dB = 0;
    out = 1;
  ); 
);

/*----------------------------------------------------------
=== New button, slider functions ===========================
----------------------------------------------------------*/
//-- New button function -------
function button_New(x,y,w,h, r,g,b,a, lbl)
(
  this.x = x; this.y = y; this.w = w; this.h = h; // coord
  this.r = r; this.g = g; this.b = b; this.a = a; // color
  this.lbl = lbl;
);

//-- New slider function -------
function slider_New(x,y,w,h, r,g,b,a, lbl, val,min_val,max_val,units)
(
  this.x = x; this.y = y; this.w = w; this.h = h; // coord
  this.r = r; this.g = g; this.b = b; this.a = a; // color
  this.lbl = lbl;
  this.val = val;
  this.min_val = min_val; 
  this.max_val = max_val;
  this.norm_val = (val - min_val)/(max_val - min_val); // norm value
  this.units = units;
);


/*----------------------------------------------------------
=== Simple Get mouse functions =============================
----------------------------------------------------------*/
//------------------
function pointIN(p_x, p_y)
  instance(x,y,w,h)
( // if point in obj area
  p_x >= x && p_x <= x+w && p_y >= y && p_y <= y+h;
);

function mouseIN()
( // if mouse in obj area
  !(mouse_cap&1) && this.pointIN(mouse_x, mouse_y);
);

//------------------
function mouseDown()
( // if mouse has been pressed in obj area
  mouse_cap&1 && this.pointIN(mouse_ox,mouse_oy);
);

function mouseUp()
( // if mouse released(anywhere) and has been pressed in obj area
  last_mouse_cap&1 && !(mouse_cap&1) && this.pointIN(mouse_ox,mouse_oy);
);

function mouseClick()
( // if mouse released in obj area and has been pressed in obj area
  last_mouse_cap&1 && !(mouse_cap&1) && 
  this.pointIN(mouse_x, mouse_y) && this.pointIN(mouse_ox,mouse_oy);
);
//------------------
function mouseR_Down()
( // if mouse R has been pressed in obj area
  mouse_cap&2 && this.pointIN(mouse_ox,mouse_oy);
);

function mouseM_Down()
( // if mouse M has been pressed in obj area
  mouse_cap&64 && this.pointIN(mouse_ox,mouse_oy);
);


/*----------------------------------------------------------
=== SLIDER =================================================
----------------------------------------------------------*/
//-- Set slider value ------------------
function slider_set_value()
  instance(x,y,w,h, val,min_val,max_val, norm_val)
  local(nv, K )
(
  K = 10; // K = coeff(when Ctrl pressed)
  Ctrl ? (
    nv = norm_val + (mouse_x-last_x)/(w*K);
  ) : (
    nv = (mouse_x-x)/w;
  );
  
  nv != norm_val ? (
    norm_val = min( max(nv, 0), 1 ); // verify and set values
    val = min_val + (max_val-min_val)*norm_val;
    this.isChanged = 1;
  );
); 

//-- Draw slider -----------------------
function slider_draw()
  instance(x,y,w,h, r,g,b,a, lbl, val, norm_val, units)
  local(aa, val_str, str_w, str_h)
  
( 
  aa = a;
  this.isChanged = this.isReleased = 0; // reset 
  this.mouseIN() ? aa = a + 0.1;
  this.mouseDown() ? (
    aa = a + 0.2;
    this.slider_set_value();
  );
  
  this.mouseUp() ? this.isReleased = 1;
  
  //-- draw body, frame ------
  gfx_set(r,g,b,aa);
  gfx_rect(x,y,w,h, 0);
  gfx_rect(x, y, w*norm_val, h, 1);
  //-- draw label ------------
  gfx_set(0.9,0.8,0.5,0.9);
  gfx_measurestr(lbl, str_w, str_h);
  gfx_x = x + 5; gfx_y = y + (h-str_h)/2;
  gfx_drawstr(lbl);
  //-- draw value ------------
  val_str = sprintf(#, "%.2f%s", val, units); 
  gfx_measurestr(val_str, str_w, str_h);
  gfx_x = x - 5 + w - str_w; gfx_y = y + (h-str_h)/2;
  gfx_drawstr(val_str);
);


/*----------------------------------------------------------
=== BUTTON =================================================
----------------------------------------------------------*/
//-- Draw button -----------------------
function button_draw()
  instance(x,y,w,h, r,g,b,a, lbl)
  local(aa, str_w, str_h)
(   
  aa = a;
  this.mouseIN() ? aa = a + 0.1;
  this.mouseDown() ? aa = a + 0.2; 
  this.mouseClick() ? this.isClicked = 1 : this.isClicked = 0;
  
  //-- draw body, frame ------
  gfx_set(r,g,b,aa);
  gfx_rect(x,y,w,h, 1);
  gfx_rect(x,y,w,h, 0); // frame
  //-- draw label ------------
  gfx_set(0.9,0.8,0.5,0.9);
  gfx_measurestr(lbl, str_w, str_h);
  gfx_x = x + (w-str_w)/2; gfx_y = y + (h-str_h)/2;
  gfx_drawstr(lbl);

);


/*----------------------------------------------------------------------------------------
=== Create controls ======================================================================
----------------------------------------------------------------------------------------*/

//-- Create Sliders --------------------
//-- args = (x,y,w,h, r,g,b,a, lbl, val,min_val,max_val,units)
Thresh.slider_New(control_x_init*zoom,control_y_init * zoom + control_y_offset * current_row(1) * zoom,slider_w * zoom,slider_h * zoom,    5,0.3,0.3,0.2, "Threshold",    0,  -48,     0, " dB" );
HPFreq.slider_New(control_x_init*zoom,control_y_init * zoom + control_y_offset * current_row(1) * zoom,slider_w * zoom,slider_h * zoom,    0.4,5,0.5,0.2, "High-Pass Frequency",     20000, 2000, 20000, " Hz" );
PreOpen.slider_New(control_x_init*zoom,control_y_init * zoom + control_y_offset * current_row(hide_preopen? 0:1) * zoom,slider_w * zoom,slider_h * zoom,   0.4,5,0.5,0.2, "Pre-Open",        0,   0,    20, " ms" );
Interval.slider_New(control_x_init*zoom,control_y_init * zoom + control_y_offset * current_row(hide_interval? 0:1) * zoom,slider_w * zoom,slider_h * zoom,  0.4,5,0.5,0.2, "Interval",       1,    1,    10, " ms" );
Compress.slider_New(control_x_init*zoom,control_y_init * zoom + control_y_offset * current_row(1) * zoom,slider_w * zoom,slider_h * zoom, 0.3,0.4,5,0.2, "Compression",    100,    0,   100, " %" );

//-- Create Buttons --------------------
//-- args = (x,y,w,h, r,g,b,a, lbl)
ActEnv.button_New(control_x_init*zoom + 0*button_x_offset*zoom,control_y_init * zoom + control_y_offset * current_row(1) * zoom,button_w * zoom,button_h * zoom,   0.5,0.3,0.3,0.2, "Activate");
Spectr.button_New(control_x_init*zoom + 1*button_x_offset*zoom,control_y_init * zoom + control_y_offset * current_row(0) * zoom,button_w * zoom,button_h * zoom,  0.5,0.3,0.3,0.2, "Spectrogram");
VisEnv.button_New(control_x_init*zoom + 2*button_x_offset*zoom,control_y_init * zoom + control_y_offset * current_row(0) * zoom,button_w * zoom,button_h * zoom,  0.5,0.3,0.3,0.2, "Visibility");


//======================================================================================//


//----------------------------------------------------------------------------------------
//--- Toggle active, visible vol envelope ------------------------------------------------
//----------------------------------------------------------------------------------------
function ToggleActVis_VolEnvelope(mode)
  local(item_cnt, item_idx, item, take, VolEnv, BR_Env,
        BR_Env, active,visible,armed, inLane,laneHeight, 
        defShape, minVal,maxVal,centerVal, type, faderScaling)   
(
  item_cnt = CountSelectedMediaItems(0);
  item_cnt ? Undo_OnStateChange("Envelope-based Deesser");
  item_idx=0;
  loop(item_cnt,
      item = GetSelectedMediaItem(0, item_idx);
      take = GetActiveTake(item);
      VolEnv = GetTakeEnvelopeByName(take,"Volume"); // Get take "Volume" envelope
      
      //-- Toggle act,vis depend of mode(if VolEnv exists) -----
      VolEnv ? (
        BR_Env = extension_api("BR_EnvAlloc", VolEnv, 0);
        extension_api("BR_EnvGetProperties", BR_Env, active,visible,armed, inLane,laneHeight, 
                      defShape, minVal,maxVal,centerVal, type, faderScaling);
        mode == "act" ? active  = !active;  // toggle active
        mode == "vis" ? visible = !visible; // toggle visible
        extension_api("BR_EnvSetProperties", BR_Env, active,visible,armed, inLane,laneHeight, 
                      defShape, faderScaling);
        extension_api("BR_EnvFree", BR_Env, 1);

      ) : (
        //-- Create(if VolEnv no exist) ----
        Main_OnCommand(NamedCommandLookup("_S&M_TAKEENV1"), 0);
        VolEnv = GetTakeEnvelopeByName(take,"Volume");
      );
      item_idx+=1;
  );

);

//----------------------------------------------------------------------------------------
//--- Rebuild volume envelope ------------------------------------------------------------
//----------------------------------------------------------------------------------------

function CreateEnvelope(VolEnv, range_start, range_len, srate, envbuf, pnt_cnt)
  local(PreOpen, env_mode, shape,tens,sel,nosort, val,val1, rs_val,re_val, i, pos)     
(
  PreOpen = PreOpen.val/1000;
  //--------------------------
  env_mode = GetEnvelopeScalingMode(VolEnv);     // get VolEnv scaling mode
  val1 = ScaleToEnvelopeMode(env_mode, 1);       // Scaled  val=1
  //shape = 2; tens = 0; sel = 0; nosort = 1;    // def for new deess points 1
  shape = 0; tens = 0; sel = 0; nosort = 1;      // def for new deess points 2
  
  //-- Del Old points, Ins points at edges(use cur values) ------
  Envelope_Evaluate(VolEnv, range_start, srate, 0, rs_val);           // get env val at start
  Envelope_Evaluate(VolEnv, range_start+range_len, srate, 0, re_val); // get env val at end
  DeleteEnvelopePointRange(VolEnv, range_start-0.0001, range_start+range_len+0.0001); // Del Old points 
  //--------------------------
  InsertEnvelopePoint(VolEnv, range_start, rs_val, 0, 0, 0, 1);           // Insert point=curval at start
  InsertEnvelopePoint(VolEnv, range_start, val1, 0, 0, 0, 1);             // Insert point=1 at start
  InsertEnvelopePoint(VolEnv, range_start+range_len, val1, 0, 0, 0, 1);   // Insert point=1 at end
  InsertEnvelopePoint(VolEnv, range_start+range_len, re_val, 0, 0, 0, 1); // Insert point=curval at end
  
  //--------------------------
  i = 0;
  while(envbuf[i] <= range_start + PreOpen && i < pnt_cnt)( 
    i+=2; pnt_cnt-=2; // Если точки выходят за range_start!
  );
  //--------------------------

  loop(pnt_cnt*0.5,
    pos = envbuf[i] - PreOpen;
    val = ScaleToEnvelopeMode(env_mode,  envbuf[i+1]);   // Scale point val
    // -----------------------
    InsertEnvelopePoint(VolEnv, pos, val, shape, tens, sel, nosort); // Insert point        
    i+=2;  
  );
);

//----------------------------------------------------------------------------------------
//--- Rebuild volume envelope ------------------------------------------------------------
//----------------------------------------------------------------------------------------
function RebuildVolEnvelope(item, take, srate, n_chans, VolEnv)
  local(item_start, item_len, sel_start, sel_end, playrate, range_start, range_len, range_len_smpls, 
        block_size, n_blocks, rest_smples, AA, starttime_sec, samplebuf, smpl, ch_smpl, chan_sum, cur_block, envbuf,
        take_vol, item_vol, vol_offs, 
        trig, last_trig, input, fltr_out, env_out, comp_out, pnt_cnt, interval, interval_cnt, oo_offs)
( 
  item_start = GetMediaItemInfo_Value(item, "D_POSITION"); // item position
  item_len  = GetMediaItemInfo_Value(item, "D_LENGTH");    // item orig length
  GetSet_LoopTimeRange(0, 0, sel_start, sel_end, 0);       // get time selection
  !(sel_end - sel_start) ? (       // if no selection, then
    sel_start = item_start;        // use item start
    sel_end = item_start+item_len; // use item end
  );
  sel_start = max(sel_start, item_start);         // if sel_start or sel_end out of item, then
  sel_end   = min(sel_end, item_start+item_len);  // use item_start, item_end respectively
  //sel_end - sel_start < 0 ? MB("Time selection out of item range!", "Note", 0); 
  
  
  //----------------------------------------------------------------------------
  sel_end - sel_start > 0 ? ( 
    //-- If playrate != 1 ----------------------------------
    playrate  = GetMediaItemTakeInfo_Value(take, "D_PLAYRATE"); // get take orig playrate
    playrate != 1 ? (
      SetMediaItemTakeInfo_Value(take, "D_PLAYRATE", 1); // AA work faster with playrate = 1
      SetMediaItemInfo_Value(item, "D_LENGTH", item_len*playrate); // len*playrate 
    );
    //-- Define range(with regard orig playrate) -----------
    range_start = (sel_start-item_start)*playrate;  // range start
    range_len = (sel_end-sel_start)*playrate;       // range length
    range_len_smpls = floor(range_len*srate);       // range length to samples
    //-----------------------
    block_size = floor(65536/n_chans);  // full block size(samples), note MAX = 65536!!!
    //-----------------------
    n_blocks = floor(range_len_smpls/block_size);         // number of full blocks
    rest_smples = range_len_smpls - block_size*n_blocks;  // rest of samples(incomplete last block)
    
    //-- Set Filter and Gate Values from sliders -----------
    take_vol = GetMediaItemTakeInfo_Value(take, "D_VOL"); // regard take volume
    item_vol = GetMediaItemInfo_Value(item, "D_VOL");     // regard item volume
    vol_offs = VAL2DB(take_vol*item_vol);  // offset is subtracted from the comp threshold
    FilterB.SetValues(HPFreq.val, srate);
    EnvFollower.SetValues(0.2, 40, srate); // att-rel - constants(ms), can be changed
    CompD.SetValues(Thresh.val-vol_offs, Compress.val/100);
      
      //----------------------------------------------------
      AA = CreateTakeAudioAccessor(take);
      starttime_sec = range_start; // first block start
      samplebuf = 0;  // buffer for accessor samples
      envbuf = 65536; // buffer for envelope points
      cur_block = 0;
      trig = last_trig = 0;
      pnt_cnt = 0; 
      //-----------
      interval = ceil(Interval.val/1000 * srate);
      // -- Audio processing, search sibilance -------------
      loop(n_blocks+1,
          cur_block == n_blocks ? block_size = rest_smples; // last block = rested samples  
          //memset(0,0,block_size); // clear samplebuffer - Можно не чистить, но все же...???
          //GetAudioAccessorSamples(AA, srate, 1, starttime_sec, block_size, samplebuf); // get as mono
          GetAudioAccessorSamples(AA, srate, n_chans, starttime_sec, block_size, samplebuf); // get all channels
          //-- Average value(if more then one channel) -----
          n_chans > 1 ? (
            smpl = 0;
            loop(block_size,
              ch_smpl = smpl * n_chans;
              chan_sum = 0;
              loop(n_chans, chan_sum += samplebuf[ch_smpl]; ch_smpl+=1; ); // sum all channels
              samplebuf[smpl] = chan_sum/n_chans; // average value
              smpl+=1; 
            );
          );
            //---------------------------------          
            smpl = 0;
            loop(block_size,
                input = samplebuf[smpl];
                fltr_out = FilterB.Apply(input);
                env_out = EnvFollower.Apply(abs(fltr_out));
                comp_out = CompD.Apply(env_out);
      
                //-- Add comp point ---------
                comp_out < 1 ? (
                  trig = 1;
                  interval_cnt > interval ? (
                    envbuf[pnt_cnt] = starttime_sec + smpl/srate; // position
                    envbuf[pnt_cnt+1] = comp_out; // value
                    pnt_cnt+=2;
                    interval_cnt = 0;
                  );
                  interval_cnt+=1;
                ) : (
                  trig = 0;
                );
                
                //-- Add On-Off point -------
                trig != last_trig ? (
                  trig ? (oo_offs = -8; interval_cnt = interval+1;) : oo_offs = 8;
                  envbuf[pnt_cnt] = starttime_sec + (smpl+oo_offs)/srate; // position
                  envbuf[pnt_cnt+1] = 1; // value
                  pnt_cnt+=2;
                  last_trig = trig;
                );
                
                //---------------------------               
                smpl+=1;   
            );
          starttime_sec+=block_size/srate; // next block starttime
          cur_block+=1; // block counter
      );
      
      DestroyAudioAccessor(AA);
      //----------------------------------------------------
      CreateEnvelope(VolEnv, range_start, range_len, srate, envbuf, pnt_cnt); // Create Envelope
      //----------------------------------------------------
      playrate != 1 ? (
        SetMediaItemTakeInfo_Value(take, "D_PLAYRATE", playrate); // restore orig playrate
        SetMediaItemInfo_Value(item, "D_LENGTH", item_len);  // restore orig lengthstart_time
      );          
      Envelope_SortPoints(VolEnv);
      UpdateTimeline();
      UpdateArrange();          
  );  

);


//======================================================================================//
function MAIN()
local(item_cnt, item_idx, item, take, PCM_source, srate, n_chans, VolEnv)  
( 
  !hide_stats? start_time = time_precise(); // start time test
  //--------------------------  
  item_cnt = CountSelectedMediaItems(0);
  item_idx = 0;
  loop(item_cnt,
      //-- item, take data -------------
      item = GetSelectedMediaItem(0, item_idx);
      take = GetActiveTake(item);
      PCM_source = GetMediaItemTake_Source(take);
      srate = GetMediaSourceSampleRate(PCM_source);
      n_chans = GetMediaSourceNumChannels(PCM_source);
      VolEnv = GetTakeEnvelopeByName(take,"Volume");
      //-- rebuild - create envelope ---
      VolEnv && srate ? (
        RebuildVolEnvelope(item, take, srate, n_chans, VolEnv);
      );
      item_idx+=1;
  );
  //--------------------------
  !hide_stats? process_time  = time_precise() - start_time; // end time test

);


//----------------------------------------------------------
function Draw_Controls()
(
  //-- sliders ---------------
  Thresh.slider_draw();
  HPFreq.slider_draw();
  !hide_preopen? PreOpen.slider_draw();
  Compress.slider_draw();
  !hide_interval? Interval.slider_draw();
  //--------------------------
  Thresh.isReleased || HPFreq.isReleased ||
  PreOpen.isReleased || Compress.isReleased ||
  Interval.isReleased ? (
    Undo_OnStateChange("Envelope-based Deesser");
    RunMain = 1;
  );
  
  //-- buttons ---------------
  ActEnv.button_draw();
  Spectr.button_draw();
  VisEnv.button_draw();
  ActEnv.isClicked ? ToggleActVis_VolEnvelope("act");
  Spectr.isClicked ? Main_OnCommand(42294, 0); // Peaks: Toggle spectrogram
  VisEnv.isClicked ? ToggleActVis_VolEnvelope("vis");
 
  
  //--------------------------
  !hide_stats? (
    gfx_x = control_x_init*zoom;
    gfx_y = control_y_init * zoom + control_y_offset * (current_row(0)+1) * zoom;
    gfx_drawstr("Processing time: ");
    gfx_drawnumber(process_time,3);
    gfx_drawstr(" s");
  );

);

//-- mainloop ----------------------------------------------
function mainloop()
(
  //-- mouse and modkeys -----
  (mouse_cap&1 && !(last_mouse_cap&1))  ||    //-- L mouse
  (mouse_cap&2 && !(last_mouse_cap&2))  ||    //-- R mouse
  (mouse_cap&64 && !(last_mouse_cap&64)) ? (  //-- M mouse
    mouse_ox = mouse_x; mouse_oy = mouse_y;
  ); 

  Ctrl  = mouse_cap&4;  //-- Ctrl  state
  Shift = mouse_cap&8;  //-- Shift state
  Alt   = mouse_cap&16; //-- Shift state
  
  //-- Main functions etc ----
  Draw_Controls();
  RunMain? ( 
    MAIN(); 
    RunMain = 0; 
  ); 
  
  //--------------------------
  last_mouse_cap = mouse_cap;
  last_x = mouse_x; last_y = mouse_y;
  char = gfx_getchar();
  char==32 ? Main_OnCommand(40044, 0); //-- play
  char >= 0 ?
  (
    defer("mainloop();"); //-- defer
  ) :
  (
    hide_envelope_on_close && Main_OnCommand(NamedCommandLookup("_S&M_TAKEENVSHOW4"), 0);
    hide_spectrogram_on_close && GetToggleCommandState(42294) && Main_OnCommand(42294, 0); // Peaks: Toggle spectrogram
  );
  gfx_init("",width*zoom,height*zoom);
  gfx_update();
);

//-- init --------------------------------------------------
function Init()
( //-- window ----------------
  width = 270; height = 106; dockstate = 0; xpos = 1600; ypos = 900;
  !hide_preopen? height = height + control_y_offset;
  !hide_interval? height = height + control_y_offset;
  !hide_stats? height = height + control_y_offset;
  gfx_init("De-esser",width*zoom,height*zoom,dockstate,xpos,ypos);
  R = G = B = 20;
  gfx_clear = R + G*256 + B*65536;
  //-- Init mouse ------------
  last_mouse_cap = 0;
  last_x = last_y = 0;
  mouse_ox = mouse_oy = -1;
  
  gfx_setfont(1, "Calibri", font * zoom);

  on_by_default? Main_OnCommand(NamedCommandLookup("_S&M_TAKEENV1"), 0) : show_envelope_on_open? Main_OnCommand(NamedCommandLookup("_S&M_TAKEENVSHOW1"), 0);
  show_spetrogram_on_open? !GetToggleCommandState(42294) && Main_OnCommand(42294, 0); // Peaks: Toggle spectrogram
);

/*---------------------------------------
--- Start Script ------------------------
---------------------------------------*/
Init();
mainloop();
Attached Files
File Type: zip de-ess.zip (6.8 KB, 36 views)
abnegative is offline   Reply With Quote
Old 01-20-2024, 12:48 PM   #39
abnegative
Human being with feelings
 
Join Date: Sep 2022
Posts: 222
Default

Quote:
Originally Posted by Subz View Post
When I edit parameters, it only processes the first minute of a file?

If I go with the default settings that it loads it processes the full item, not just the first minute

Subz
Fixed, thanks! The update is here: https://forum.cockos.com/showpost.ph...1&postcount=39
abnegative is offline   Reply With Quote
Old 01-20-2024, 03:36 PM   #40
Subz
Human being with feelings
 
Subz's Avatar
 
Join Date: Jun 2006
Location: UK
Posts: 3,210
Default

Quote:
Originally Posted by abnegative View Post
Thank you!

My old blind eyes need the extra size!

Subz
Subz 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:33 AM.


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