Old 06-18-2020, 01:13 PM   #1
16bit
Human being with feelings
 
Join Date: Apr 2016
Location: England-land
Posts: 20
Default [JSFX] non-live RadioVoiceOver ducking suggestions...

Hi all,
Firsly I apologise if I missed any notices instructing users not to create posts like I am doing.

My friend is still using Adobe Audition 3.0 due to various workflow reasons.
He is trying to automate music bed (background music) ducking driven by a voice over track.
Due to the old software, it's a dual mono affair to get a side chain working, so Left is the Aux input, and right is the signal to process/duck.

All VST plugins that he could find had insufficient look ahead and a rather abrupt attack, including ReaComp. So I took it upon myself to try and modify existing JSFX and see what was possible.

I shamelessly took LOSER's "Digital Drum Compressor" and sought about re-purposing for the task. Added some bits from Cockos' "Time Adjustment Delay" and came up with this:

Code:
desc:RadioVoiceOverDuckingComp_DualMono
//tags: mono ducking compressor
//author: 16bit

slider1:-45<-60,0,.1>Threshold (dB)
slider2:100<0,250,.1>Ratio
slider3:2000<50,2500,1>Attack (ms)
slider4:1250<0,2500,.1>Hold (ms)
slider5:2500<0,2500,1>Release (ms)
slider6:50<0,1000,1>RMS Size (ms) 
slider7:0<0,1,1{Main-L,Main-R}>Feed
slider8:-1000<-2000,2000,1>Look Ahead (ms)
//slider9:0<-120,60,1>Output (dB)
slider11:-12<-30,-6,1>Maximum Gain Reduction (dB)


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

@init
gain = seekgain = 1;
c_ampdB = 8.65617025;

@slider
treshdB = min(slider1,-.1);
tresh = exp(treshdB/c_ampdB);
ratio_1 = ratio;
ratio = max(slider2,0.0001);

treshdB == -.1 || ratio_1 < .1  ? (gain = seekgain = 1; );

MaxGainRed = exp(slider11/c_ampdB);

delaylen = ( slider8/1000*srate)|0;
delaylen<0?(
  pdc_delay=-delaylen;  
  pdc_top_ch=2;
  pdc_bot_ch=0;
  delaylen=0;
):(
delaylen+=pdc_delay;
//pdc_delay=0;
);
bufsize=srate*4.0; // extra in case the user wants to go over

attack = exp( -treshdB/max( slider3*srate/1000 , 0) / c_ampdB  ) ;
hold = slider4/1000*srate;
under_tresh = 0;
release = exp( -treshdB/max( slider5*srate/1000 , 0) / c_ampdB ) ;

rms_size_1 = rms_size;
rms_size = min( max(slider6/1000*srate,1) , 1000000);
rms_size_1 != rms_size ? (
    rms_sqr_sum = rms_bpos = 0;
    memset(0,0,rms_size);
);

feed = slider7;

rms_size == 1 ? (
    volume = exp(slider9/c_ampdB) / (mode_make_up ? tresh+(1-tresh)/ratio : 1);
):(
    volume = exp(slider9/c_ampdB) / (mode_make_up ? tresh+(1-tresh)/ratio * 2.828427125 : 1);
);

seekgain = 1;

@sample
feed == 0 ? (maxsamples = spl0);
feed == 1 ? (maxsamples = spl1);
//feed == 0 ? (maxsamples = max(abs(spl0),abs(spl1)); );
feed == 2 ? (maxsamples = max(abs(spl0_out),abs(spl1_out));
 );



rms_sqr_sum = max(rms_sqr_sum - rms_bpos[0],0) + (rms_bpos[0] = sqr(maxsamples));
(rms_bpos+=1) >= rms_size ? rms_bpos=0;
rms = sqrt(rms_sqr_sum/rms_size);

rms > tresh ? (
    hold ?
    (
        ratio > 1 ? (
            seekgain = min( (tresh+(rms-tresh)/ratio)/rms ,seekgain );
        ):(
            seekgain = max( (tresh+(rms-tresh)/ratio)/rms ,seekgain );
        );
    ):(
        seekgain = (tresh+(rms-tresh)/ratio)/rms;
    );
    under_tresh = 0;
):(
    (under_tresh+=1)>hold ? (seekgain = 1; );
);


gain > seekgain ? gain=max(gain/attack,seekgain):gain=min(gain*release,seekgain);

gain=max(gain,MaxGainRed) ;

spl0_out = (spl1 *= gain * volume) ;

slider10 = log(gain)*c_ampdB;
sliderchange(512);
Wrapping with ReaJS in AA3.0 it does indeed work. However, the Look Ahead doesn't seem to function nor does the Attack. I don't know what is up, but they seem to work (albeit not that accurately) in Reaper itself.
Playing with PDC latency is probably not going to work so well outside of Reaper, especially with such an old DAW.

I'm happy for anyone to modify this, after all it's my first dabble beyond just changing a value or two in a JSFX plugin.
16bit is offline   Reply With Quote
Old 07-01-2020, 04:29 PM   #2
16bit
Human being with feelings
 
Join Date: Apr 2016
Location: England-land
Posts: 20
Default

Update.
Here is the full stereo version. Works on 4 channel track. Affects ch1/2, side chain input 3/4.
Max Gain Reduction added where it should be, so attack/release times are true.

Due to PDC being used for look-ahead, that simply wont function outside of Reaper or another DAW that knows how to deal with it.

Code:
desc:VoiceOverDuck-Stereo
//tags: dynamics compressor
//Developed from LOSER digital drum compressor


slider1:-45<-60,0,1>Threshold (dB)
slider2:50<1,250,1>Ratio
slider3:2000<50,2500,10>Attack (ms)
slider4:1250<0,2500,10>Hold (ms)
slider5:2500<0,2500,10>Release (ms)
slider6:50<0,250,1>RMS Size (ms) 
slider7:2<0,2,1{Feedforward,Feedback,Sidechain}>Feed
slider8:-1000<-2500,0,1>Look Ahead (ms)
slider9:-12<-36,0,1>Max Gain Reduction (dB)
slider10:0,=Current Reduction (dB)=
//slider11:0,SeekGain (dB)

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

@init
gain = seekgain = 1;
c_ampdB = 8.65617025;

@slider
treshdB = min(slider1,-.1);
tresh = exp(treshdB/c_ampdB);
ratio_1 = ratio;
ratio = max(slider2,0.0001);

treshdB == -.1 || ratio_1 < .1  ? (gain = seekgain = 1; );

delaylen = ( slider8/1000*srate)|0;
delaylen<0?(
  pdc_delay=-delaylen;  
  pdc_top_ch=2;
  pdc_bot_ch=0;
  delaylen=0;
):(
delaylen+=pdc_delay;
//pdc_delay=0;
);
bufsize=srate*4.0; // extra in case the user wants to go over

attack = exp( -treshdB/max( slider3*srate/1000 , 0) / c_ampdB  ) ;
hold = slider4/1000*srate;
under_tresh = 0;
release = exp( -treshdB/max( slider5*srate/1000 , 0) / c_ampdB ) ;

MaxGainRed = exp(slider9/c_ampdB);

rms_size_1 = rms_size;
rms_size = min( max(slider6/1000*srate,1) , 1000000);
rms_size_1 != rms_size ? (
    rms_sqr_sum = rms_bpos = 0;
    memset(0,0,rms_size);
);

feed = slider7;

seekgain = 1;

@sample
feed == 0 ? (maxsamples = max(abs(spl0),abs(spl1)); );
feed == 1 ? (maxsamples = max(abs(spl0_out),abs(spl1_out)); );
feed == 2 ? (maxsamples = max(abs(spl2),abs(spl3)); );



rms_sqr_sum = max(rms_sqr_sum - rms_bpos[0],0) + (rms_bpos[0] = sqr(maxsamples));
(rms_bpos+=1) >= rms_size ? rms_bpos=0;
rms = sqrt(rms_sqr_sum/rms_size);

rms > tresh ? (
    hold ?
    (
        ratio > 1 ? (
            seekgain = min( (tresh+(rms-tresh)/ratio)/rms ,seekgain );
        ):(
            seekgain = max( (tresh+(rms-tresh)/ratio)/rms ,seekgain );
        );
    ):(
        seekgain = (tresh+(rms-tresh)/ratio)/rms;
    );
    under_tresh = 0;
):(
    (under_tresh+=1)>hold ? (seekgain = 1; );
);


//max gain red, but keep attack and release the same length
seekgain = max(seekgain,MaxGainRed) ;

gain > seekgain ? gain=max(gain/attack,seekgain):gain=min(gain*release,seekgain);


spl0_out = (spl0 *= gain) ;
spl1_out = (spl1 *= gain) ;

slider10 = log(gain)*c_ampdB;
//slider11 = log(seekgain)*c_ampdB;
sliderchange(512);
16bit 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 05:49 AM.


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