diff --git a/Meters/Channel Similarity Meter (S).txt b/Meters/Channel Similarity Meter (S).txt new file mode 100644 index 0000000..96f9155 --- /dev/null +++ b/Meters/Channel Similarity Meter (S).txt @@ -0,0 +1,340 @@ +// from https://forum.cockos.com/showthread.php?t=190168#30 by Tale, geraintluff, junh1024 + +desc: Channel Similarity Analyzer (uses FFT) + +slider1:1<1,16,1>Input (channel) +slider2:2<1,16,1>Compare to (channel) +slider3:0<0,100,1>-Rear threshold +slider4:0<0,100,1>-Crossover width +slider5:0<0,100,1>-Ch corrrelation% +slider6:0<0,100,1>Ch similarity % +slider7:0<0,100,1>-Rear transients +slider8:13<10,14,1>FFT size (pow2) + +import surroundlib2.txt +import surroundlib3.txt +import surroundlibf.txt + +in_pin:in +in_pin:in +in_pin:in +in_pin:in +in_pin:in +in_pin:in + +out_pin:L +out_pin:R +out_pin:C +out_pin:blank +out_pin:BL +out_pin:BR + +@init + +//see surroundlibf.txt + + + +// pdc_bot_ch = 0; +// pdc_top_ch = 6; + + +chan_A_prev=chan_A =chan_B_prev=chan_B =corr_numerator=corr_denominator=this=that=0; + + +@slider +sliderfft = (2^(slider8))|0; +fftsize != sliderfft ? fft_initialize(); + +// Rear_threshold= slider3*pi/180; +// Crossover_width=max(slider4*pi/180,0.1);//min of 0.1 since don't want an infinite slope/div 0 +// width_coeff=slider1/100; + +// depth_coeff=(slider2*$pi)/200; //depth scaled from 0-100 to 0>half pi +// calculate_depth_coeffs(depth_coeff); +// R_width_coeff=slider5/100; +// depth2=abs(slider2); + +// slider6=max(slider6,10); +// cutoff=slider6/100; +// cutoff_bins=floor(cutoff*(fftsize)); +// transient_amount=slider7/100; + +Time_Response=min(fftsize/8192,1); //clamp to 1, 0.5 @ 4k fft + +@block +slider6=abs(corr_stat-0.5)*2*100; + +@sample + +sum_all_spl+=abs(spl0)+abs(spl1); //silence detector + +// Buffer input +pos >= fftsize ? +( + tmp = buf1_a; + buf1_a = buf1_b; + buf1_b = tmp; + + tmp = buf2_a; + buf2_a = buf2_b; + buf2_b = tmp; + + // check_silence_set_fftsize(0); //reduce CPU + + // FFT + fft(buf1_a, fftsize); + fft_permute(buf1_a, fftsize); + + i = 0; + + //analyze up to 12k for 48k input + loop(fftsize / 4 + 1, + + + a = i; + b = a+1; + a2 = 2*fftsize-i; + b2 = a2+1; + + + x = buf1_a[a]; + y = buf1_a[b]; + x2= buf1_a[a2]; + y2= buf1_a[b2]; + + + //we have 2 sets cuz L&R are modified for LRC, but we want to measure the phase of the original LR + left_r = (x + x2)*0.5; + left_i = (y - y2)*0.5; + right_r = (y + y2)*0.5; + right_i = (x2 - x)*0.5; + //completely rewritten in Complex instead of Polar for more performance & no fiddly phase compensation + + left_i>1?get_signal=1; + + //convert to M/S, center content + + + // inspector1=fftsize-ceil((fftsize-cutoff_bins)/2); + + // width_coeff<1? + // width_coeff<1&&ichan_A_prev && chan_B>chan_B_prev) || (chan_Achan_A_prev && chan_Bchan_B_prev ) )?(corr_temp = -1; that =1;); + + //correlation stat is integrated for all time like LUFS-I + corr_numerator += corr_temp; + corr_denominator+=1; + + corr_stat=corr_numerator/corr_denominator; + + chan_A_prev=chan_A ; + chan_B_prev=chan_B ; + + + // ms_complex_set_sideness_center(); + + // Sideness1[i]=1; + + + // abs(1); + + // M/S decode LR + // left_r = (mid_r*Sideness1[i]) + (side_r); + // left_i = (mid_i*Sideness1[i]) + (side_i); + // right_r = (mid_r*Sideness1[i]) - (side_r); + // right_i = (mid_i*Sideness1[i]) - (side_i); + + + ); + // :(center_r=center_i=0;); + + + + //rear lowpass depends on slider6, rear hipass at a max of 1% SR when slider6=50% + // (i> floor (0.01*fftsize* ( 1- max (cutoff-0.5,0)*2) ) && ipi?Angle_Difference[i]=2*pi-Angle_Difference[i];//fix angle difference cuz should be under 180* + + // Angle_Difference[i]=(Angle_Difference[i]*(Time_Response))+(Angle_Difference_old[i]*(1-Time_Response)); + // Angle_Difference_old[i]=Angle_Difference[i]; + + // T_scaling=1; + + + // Magnitudes1[i]=(left_r^2+left_i^2);// only analysing L for transient & no sqrt cuz it's faster + //remove transients from top half of rear, copied from FFT Multi Tool + // ((i>cutoff_bins/2) && (Magnitudes1[i]>Magnitudes1_old[i]))? + // ( + // T_scaling=(((Magnitudes1[i]*(transient_amount^2))+(Magnitudes1_old[i]*(1-(transient_amount^2))))/Magnitudes1[i]); + // ); + + + //remove from front if wide, but scale it according to how transient it is, so transients get rmv from rear when subtraction happens later. + + // P_scaling=1-((Angle_Difference[i]/pi)*T_scaling); + // P_scaling=1-((Angle_Difference[i]/pi)); + // P_scaling=min(max(1-((((Angle_Difference[i])+Rear_threshold)/pi)*T_scaling),0),1); + // P_scaling=min(max(1-( ( ((+-h_pi)/(Crossover_width/pi))+h_pi ) *T_scaling ) ,0) ,1) ; + + + + // P_scaling= min(max( ( 1-(Angle_Difference[i]-Rear_threshold+(Crossover_width/2))*T_scaling*(1/Crossover_width) ) ,0) ,1) ; + + // P_scaling=1; + // P_scaling*=T_scaling; + // P_scaling=1; + // Angle_Difference[i]>Rear_threshold?(P_scaling=0); + + // lr_complex_apply_1_scaling(P_scaling); + + + // Magnitudes1_old[i]=Magnitudes1[i]; + + // ); + + //BUG: upscales to rear when 100% hard panned + + + //rear stuff + + // (Angle_Difference[i]>Rear_threshold-Crossover_width&&Angle_Difference[i]Rear_threshold)? + + //more voodoo + // buf1_a[a] = left_r - right_i; + // buf1_a[b] = left_i + right_r; + // buf1_a[a2] = left_r + right_i; + // buf1_a[b2] = right_r - left_i; + + //prepare c + + // buf2_a[a] = center_r; + // buf2_a[b] = center_i; + // buf2_a[a2]= center_r; + // buf2_a[b2]=-center_i; + + i += 2 + ); + + // fft_ipermute(buf1_a, fftsize); + // ifft(buf1_a, fftsize); + + // width_coeff<1?( + // fft_ipermute(buf2_a, fftsize); + // ifft(buf2_a, fftsize); +// ); + + // check_silence_restore_fftsize(); + + pos=0; + + + +); + + +//windowing? +w1 = window[pos/2]; +w2 = window[(fftsize-pos)/2-1]; +sw = (w1+w2)*fftsize; + +// out0 = (buf1_a[pos]+buf1_b[fftsize+pos])/sw; +// out1 = (buf1_a[pos+1]+buf1_b[fftsize+pos+1])/sw; +// out2 = (buf2_a[pos]+buf2_b[fftsize+pos])/sw; +// out3 = (buf2_a[pos+1]+buf1_b[fftsize+pos+1])/sw; + +// select channels +in0=spl(slider1-1); +in1=spl(slider2-1); + +buf1_a[pos] = w1*in0; +buf1_a[pos+1] = w1*in1; +buf1_b[fftsize+pos] = w2*in0; +buf1_b[fftsize+pos+1] = w2*in1; + +//more stuff for 2nd input +// buf2_a[pos] = w1*spl2; +// buf2_a[pos+1] = w1*spl3; +// buf2_b[fftsize+pos] = w2*spl2; +// buf2_b[fftsize+pos+1] = w2*spl3; + +//buffer the original spl0 +// out4 = buf1_org[pos2] ; +// out5 = buf1_org[pos2+1]; + +// buf1_org[pos2] = spl0; +// buf1_org[pos2+1] = spl1; + + +//output and FFT stuffs is disabled but doesn't save much CPU + +// spl4=out4; +// spl5=out5; + +// spl0 = out0; +// spl1 = out1; +// spl2= out2; + +//subtract front from original spl0 to get back +// spl4=out4-out0-(h_sqrt_2*out2); +// spl5=out5-out1-(h_sqrt_2*out2); + + +pos += 2; +pos2=(pos2+2)%(fftsize*2); + + +// do_width(width_coeff); +// do_depth(depth_coeff); +// do_cross_width(R_width_coeff); + + +@gfx 500 50 +/* +gfx_r = gfx_g = gfx_b = 1; +gfx_a = 0.5; +// box_width=8; +box_width=floor(0.7*sqrt((gfx_w+gfx_h)/2)); + +// draw guides +drawbox(Rear_threshold*gfx_w/pi,gfx_h/2); +drawbox((Rear_threshold+Crossover_width/2)*gfx_w/pi,gfx_h*1/4); +drawbox((Rear_threshold-Crossover_width/2)*gfx_w/pi,gfx_h*3/4); + +// gfx_mode=1.0; + +g=2;//counter for gfx + +while +( + set_color(g/(fftsize/2.5)); //update color according to frequency + gfx_a = min(sqrt(Magnitudes1[g])*fftsize/4,1); //set alpha to magnitude , a >1 looks weird + drawbox(Angle_Difference[g]*gfx_w/pi,gfx_h-g*gfx_h/(fftsize/2) ); //draw position for each bin + // g=ceil(g^1.2); + g+=8; + gDisplay + +slider1:1<1,16,1>Input (channel) +slider2:2<1,16,1>Compare to (channel) +slider3:0<0,100,1>-Unused +slider4:0<0,100,1>-Unused +slider5:0<0,100,1>-Ch corrrelation% +slider6:0<0,100,1>-Ch Pan % +slider7:0<0,100,1>-Unused +slider8:1<0,1,1{Dots,Lines}>Display in_pin:left input in_pin:right input @@ -37,6 +45,10 @@ scaling_hist_factor=1; // add volume normalization - junh1024 +// select channels +spl0=spl(slider1-1); +spl1=spl(slider2-1); + spl_avg_dc=(spl0+spl1)/2; spl_avg_dc*=sign(spl_avg_dc); @@ -114,14 +126,14 @@ x = y = sizeH; i = min(b,MAXDRAWSPLS); while ( - slider1 == DOTS ? ( + slider8 == DOTS ? ( // gfx_a=1; gfx_a=0.8; gfx_x=sizeH+0[i]*sizeDSqr05; gfx_y=sizeH-off[i]*sizeDSqr05; gfx_setpixel(0.5,1,0); ):( - slider1 == LINES ? ( + slider8 == LINES ? ( gfx_x=x; gfx_y=y; x=sizeH+0[i]*sizeDSqr05; y=sizeH-off[i]*sizeDSqr05; diff --git a/README.md b/README.md index 9da7420..519de97 100644 --- a/README.md +++ b/README.md @@ -149,15 +149,17 @@ Downmixers Effects (Audio) --- +- compressor_6.txt: multichannel compressor, intended as a long-term compressor (ie, leveler). Works for 16ch, but you can type in more. As the key & affector are all selected channels, it's suitable for holistic compression of ambisonics. [Note 1](#note-1) - dc_remove_6: DC remover for 6ch - limiter_6: limiter (or clipper) for 6ch -- compressor_6.txt: multichannel compressor, intended as a long-term compressor (ie, leveler). Works for 16ch, but you can type in more. As the key & affector are all selected channels, it's suitable for holistic compression of ambisonics. [Note 1](#note-1) - loop_slicer_multi.txt: beat-synced realtime loop slicer, which sequentially splits slices up to 4x stereo, according to split length +- Pitch Tracker 2 (X).txt: Compared to the original, adds PDC, off mode, automation out, removes MIDI out & gfx +- StereoField V2.txt: Compared to the original, the rotation is expanded to +- 180 deg, and width is processed before rotation, so DPL and SFR is now much easier Effects (MIDI) --- - KeyTracker 2 (M).txt: shows current MIDI note via slider. Use with PMOD for adding movement/width to a song. -- Octaver (S).txt +- midi_chorderizer V2.txt: Compared to the original, a 0 offset mutes the note, and fixes the velocity bug. Replaces my earlier buggy "Octaver (S).txt" Effects (Third-Party, external) --- @@ -165,6 +167,11 @@ Effects (Third-Party, external) - Reverb 64ch: please use fdnReverb from https://plugins.iem.at/ - Sonic Anomaly's other JSFX are available https://github.com/Sonic-Anomaly/Sonic-Anomaly-JSFX/tree/master/Plugins or in ReaPack +Meters & Analysis +--- +- Channel Similarity Meter (S).txt: Analysis of channel similarity based on FFT. Selection of 2/16ch input available. +- gfxGoniometer V2.txt: Compared to the original, automatic scaling of input, add pan analysis and selection of 2/16ch input, removes rays. + Specialist & Utility --- - DifferenceMaker.txt: subtracts Sidechain (3+4) from Main (1+2). Useful for getting the difference after an effect. @@ -194,7 +201,8 @@ Scripts for General Use - Reaper Stats.py: collects various project statistics and outputs them via a dialog. See script for more details. - Set item start to position.py - SetPanAccordingToName.py: Useful for implementing directional dialogue for films. -- Bitperfect Take Gain.py: You can set the gain of items directly, in a bitperfect way with this (not an adjustment/offset). Note that 1 bit = 6.02 dB (approx). +- Bitperfect Take Gain.py: You can set the gain of items directly, in a bitperfect way with this (not an adjustment/offset). Note that 1 bit = 6.02 dB (approx). +- Set Envelope Points.py: this script sets the value for all selected envelope points, not just the 1st one Scripts for Remixing ---