|
|
|
03-09-2017, 09:11 AM
|
#1
|
Human being with feelings
Join Date: Aug 2012
Posts: 271
|
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
|
|
|
03-09-2017, 09:12 AM
|
#2
|
Human being with feelings
Join Date: Jan 2007
Location: Smokie Bay.
Posts: 796
|
Beautiful !
|
|
|
03-09-2017, 10:17 AM
|
#3
|
Human being with feelings
Join Date: Dec 2012
Posts: 13,333
|
Whaaat? It's awesome, man!
|
|
|
03-09-2017, 10:42 AM
|
#4
|
Human being with feelings
Join Date: Mar 2007
Location: I'm in a barn
Posts: 4,467
|
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.
|
|
|
03-09-2017, 12:43 PM
|
#5
|
Human being with feelings
Join Date: Aug 2012
Posts: 271
|
Quote:
Originally Posted by James HE
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
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
*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
|
|
|
03-09-2017, 01:20 PM
|
#6
|
Human being with feelings
Join Date: Mar 2007
Location: I'm in a barn
Posts: 4,467
|
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
|
|
|
03-09-2017, 01:30 PM
|
#7
|
Human being with feelings
Join Date: Apr 2011
Posts: 3,451
|
Looks great! :O
Going to test it!
|
|
|
03-09-2017, 01:51 PM
|
#8
|
Human being with feelings
Join Date: Nov 2015
Posts: 642
|
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.
|
|
|
03-09-2017, 03:20 PM
|
#9
|
Human being with feelings
Join Date: Mar 2015
Location: Moscow, Russia
Posts: 206
|
Разрыв башки просто
|
|
|
03-09-2017, 05:41 PM
|
#10
|
Human being with feelings
Join Date: Feb 2017
Posts: 76
|
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.
|
|
|
03-09-2017, 06:59 PM
|
#11
|
Human being with feelings
Join Date: Jun 2006
Posts: 22,567
|
you fucking legend
|
|
|
03-10-2017, 12:22 AM
|
#12
|
Human being with feelings
Join Date: Jul 2016
Posts: 48
|
man – you're awesome! thank you
|
|
|
03-10-2017, 12:32 AM
|
#13
|
Human being with feelings
Join Date: May 2010
Location: Earth
Posts: 1,883
|
Eugen thank you. This is awesome.
J
__________________
Win11, R 64bit
|
|
|
03-10-2017, 04:04 PM
|
#14
|
Human being with feelings
Join Date: Aug 2012
Posts: 271
|
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
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.
|
|
|
04-03-2017, 02:41 PM
|
#15
|
Human being with feelings
Join Date: Feb 2017
Posts: 76
|
Quote:
Originally Posted by eugen2777
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!
|
|
|
04-03-2017, 04:14 PM
|
#16
|
Human being with feelings
Join Date: Jun 2009
Location: South, UK
Posts: 14,214
|
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.
|
|
|
04-03-2017, 04:24 PM
|
#17
|
Human being with feelings
Join Date: Apr 2017
Location: St. Petersburg, FL
Posts: 880
|
Amazing!
Great idea and implementation.
|
|
|
04-05-2017, 07:36 AM
|
#18
|
Human being with feelings
Join Date: Jul 2014
Posts: 634
|
Does it work on Mac ?
It´s tells me unexpected symbol when try to save...
Thanks
|
|
|
04-08-2017, 09:29 AM
|
#19
|
Human being with feelings
Join Date: Aug 2012
Posts: 271
|
Yes, it should work. Do not forget that this is EEL-script, set ".eel"-extension.
|
|
|
04-08-2017, 01:15 PM
|
#20
|
Human being with feelings
Join Date: Jul 2012
Location: Netherlands
Posts: 5,247
|
This is absolutely awesome, many thanks !!
|
|
|
09-11-2017, 12:23 AM
|
#21
|
Human being with feelings
Join Date: May 2010
Location: Norway
Posts: 7,318
|
How does this script difference from the eel-compressor?
__________________
Reaper x64, win 11
Composer, text-writer, producer
Bandcamp
|
|
|
04-18-2018, 04:02 PM
|
#22
|
Human being with feelings
Join Date: Jul 2009
Posts: 429
|
Awesome
|
|
|
04-19-2018, 05:37 AM
|
#23
|
Human being with feelings
Join Date: Dec 2017
Location: Quebec, Canada
Posts: 550
|
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
|
|
|
07-21-2018, 09:55 AM
|
#24
|
Human being with feelings
Join Date: Aug 2015
Posts: 249
|
How do you get the waveform to show colours like that, I assume according to frequency?
|
|
|
07-21-2018, 11:16 AM
|
#26
|
Human being with feelings
Join Date: Aug 2015
Posts: 249
|
Quote:
Originally Posted by vitalker
|
That's really useful, thanks!
|
|
|
08-04-2018, 08:25 AM
|
#27
|
Human being with feelings
Join Date: Aug 2015
Posts: 249
|
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?
|
|
|
10-06-2018, 09:20 PM
|
#28
|
Human being with feelings
Join Date: Jun 2017
Posts: 110
|
Quote:
Originally Posted by shosty
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.
|
|
|
02-10-2019, 02:56 AM
|
#29
|
Human being with feelings
Join Date: Mar 2016
Posts: 21
|
Чувааак!))))) ТВОЙ КОМПРЕССОР это просто мечта, ничего качественнее, гибче, нагляднее и честнее не существует. я счастлив с ним)) а тут еще и Deess - СПАСИБО ОГРОМНОЕЕЕЕЕЕЕ, ТЫ ОЧЕНЬ КРУТ! ДА ДА YES YES!)))))
|
|
|
08-26-2019, 11:33 AM
|
#30
|
Human being with feelings
Join Date: Feb 2013
Location: Northeast Michigan
Posts: 3,460
|
Very cool script! Thank you!
|
|
|
01-20-2024, 02:04 AM
|
#32
|
Human being with feelings
Join Date: Sep 2022
Posts: 222
|
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
|
|
|
01-20-2024, 09:14 AM
|
#33
|
Human being with feelings
Join Date: Jun 2020
Posts: 656
|
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 "*"
|
|
|
01-20-2024, 10:02 AM
|
#34
|
Human being with feelings
Join Date: Jun 2006
Location: UK
Posts: 3,210
|
Quote:
Originally Posted by abnegative
* [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
|
|
|
01-20-2024, 10:08 AM
|
#35
|
Human being with feelings
Join Date: Jun 2006
Location: UK
Posts: 3,210
|
Quote:
Originally Posted by eugen2777
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
|
|
|
01-20-2024, 11:16 AM
|
#36
|
Human being with feelings
Join Date: Sep 2022
Posts: 222
|
Quote:
Originally Posted by tonalstates
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
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.
|
|
|
01-20-2024, 11:23 AM
|
#37
|
Human being with feelings
Join Date: Aug 2020
Posts: 276
|
perhaps you're trying to paste this code in a .lua script? It's EEL
|
|
|
01-20-2024, 12:47 PM
|
#38
|
Human being with feelings
Join Date: Sep 2022
Posts: 222
|
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();
|
|
|
01-20-2024, 12:48 PM
|
#39
|
Human being with feelings
Join Date: Sep 2022
Posts: 222
|
Quote:
Originally Posted by Subz
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
|
|
|
01-20-2024, 03:36 PM
|
#40
|
Human being with feelings
Join Date: Jun 2006
Location: UK
Posts: 3,210
|
Quote:
Originally Posted by abnegative
|
Thank you!
My old blind eyes need the extra size!
Subz
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 01:40 PM.
|