/**************************************
Blendpressor [Build 131001] by Stige T.
**************************************/

filename:0,blendpressor_gfx/slider.png
filename:1,blendpressor_gfx/bg.png
filename:2,blendpressor_gfx/switch.png

@serialize

file_var(0,input_gain);
file_var(0,output_gain);
file_var(0,crush);
file_var(0,tight);
file_var(0,relax);
file_var(0,compensation);
file_var(0,autogain);

file_var(0,p1.val_pos);
file_var(0,p2.val_pos);
file_var(0,p3.val_pos);
file_var(0,p4.val_pos);
file_var(0,p5.val_pos);
file_var(0,p6.val_pos);

!p1.val_pos ? p1.val_pos = 10;
!p2.val_pos ? p2.val_pos = 0;
!p3.val_pos ? p3.val_pos = 0;
!p4.val_pos ? p4.val_pos = 0;
!p5.val_pos ? p5.val_pos = 0;
!p6.val_pos ? p6.val_pos = 0;

@init

gfxmem = 1000;

t10 = exp(-1/(srate*0.01));
t20 = exp(-1/(srate*0.02));
t50 = exp(-1/(srate*0.05));
t75 = exp(-1/(srate*0.075));
t100 = exp(-1/(srate*0.1));
t300 = exp(-1/(srate*0.3));
t2000 = exp(-1/(srate*1));
h1 = ceil(srate/44.1);
agw = 1-exp(-2*$pi*((1/3000)*1000)/srate);
agf = 1-exp(-2*$pi*100/srate);
trw = 1-exp(-2*$pi*((1/3333)*1000)/srate);
trf = 1-exp(-2*$pi*1000/srate);

//-------------------------------
function follower(input,att,rel)
instance (env,tmp) (
  tmp = input;
  (tmp > env) ? (
      env = att * (env - tmp) + tmp;
  ) : (
      env = rel * (env - tmp) + tmp;
  );
);
//-------------------------------
function follower2(input,att,rel,hold)
instance (env,tmp,hld) (
  tmp = input;
  (tmp > env) ? (
      env = att * (env - tmp) + tmp;
      hld = 0;
  ) : (
      hld < hold ? (
        hld +=1;
      ) : (
        env = rel * (env - tmp) + tmp;
      );
  );
  env;
);
//-------------------------------
function filterLP(input,freq)
instance(temp,freq,out,n0,weight)
(
  temp != freq ? (
    n0 = 0;
    weight = 1-exp(-2*$pi*freq/srate);
    temp = freq;
  );
  
  out = (n0+=((input-n0)*weight));
);
//-------------------------------
function filterHP(input,freq)
instance(temp,freq,out,n0,weight)
(
  temp != freq ? (
    n0 = 0;
    weight = 1-exp(-2*$pi*freq/srate);
    temp = freq;
  );
  
  out = input - (n0+=((input-n0)*weight));
);
//-------------------------------
function transient(input,amount)
instance(e0,e1,e2,e3,s1,s2,peak,peak2,attack,rms)
(
  amount ? (
    rms = sqrt(s1 +=  trw * ( input^2 - s1 )) * 2;
    peak = e0.follower2(max(abs(input),rms),0,t50,h1);
    peak = e1.follower(peak,0,t50);
    peak = e2.follower(peak,0,t50);
    peak2 = e3.follower(peak,t50,0);
    attack = (-1/( sqrt(peak - peak2) +1) +1)/2 * amount;
    attack = s2 += trf * ( attack - s2 );
  ) : (attack = 0);
);
//-------------------------------
function agc(left,right)
instance(ag,f0,s1,s2)
(
  ag = max(left,right);
  ag = ag - ( s1 += agf * ( ag - s1 ) );
  ag = sqrt(s2 +=  agw * ( ag^2 - s2 ));
  ag = 1/(ag*10+0.3);
);

@gfx 600 150

function init_mouse() (
  !X ? (X = mouse_x;);
  !Y ? (Y = mouse_y;);
);
function uninit_mouse() (
  X = 0;
  Y = 0;
);
mouse_cap ? init_mouse() : uninit_mouse();

gfx_a = 1;
gfx_x = 0; gfx_y = 0;
gfx_blit(1,1,0);

// GR START

loopsize = 200;
gr_pos_x = 280;
gr_pos_y = 55;

gfx_r = gfx_g = gfx_b = 0.75;

gfx_x = gr_pos_x; gfx_y = 145+gr_pos_y;
gfx_lineto(loopsize+gr_pos_x,145+gr_pos_y,0);
gfx_drawnumber(-30,0);

gfx_x = gr_pos_x; gfx_y = 134+gr_pos_y;
gfx_lineto(loopsize+gr_pos_x,134+gr_pos_y,0);
gfx_drawnumber(-20,0);

gfx_x = gr_pos_x; gfx_y = 102+gr_pos_y;
gfx_lineto(loopsize+gr_pos_x,102+gr_pos_y,0);
gfx_drawnumber(-10,0);

gfx_x = gr_pos_x; gfx_y = 74+gr_pos_y;
gfx_lineto(loopsize+gr_pos_x,74+gr_pos_y,0);
gfx_drawnumber(-6,0);

gfx_x = gr_pos_x; gfx_y = 43+gr_pos_y;
gfx_lineto(loopsize+gr_pos_x,43+gr_pos_y,0);
gfx_drawnumber(-3,0);

gfx_x = gr_pos_x; gfx_y = 16+gr_pos_y;
gfx_lineto(loopsize+gr_pos_x,16+gr_pos_y,0);
gfx_drawnumber(-1,0);

gfx_x = gr_pos_x; gfx_y = gr_pos_y;
gfx_lineto(loopsize+gr_pos_x,gr_pos_y,0);
gfx_drawnumber(0,0);

gfx_a = 0.33;
gfx_r = 1; gfx_g = 1; gfx_b = 1;

play_state ? (
  gfx_x = i+gr_pos_x; gfx_y = gr_pos_y;
  gfx_lineto(i+gr_pos_x,150+gr_pos_y,1);
  gfxmem[i] = min(envsum,1);
  gfxmem[loopsize+i] = min(envL,1);
  i += 1;
  i > loopsize ? i = 1;
);

gfx_a = 0.5;
gfx_r = 0; gfx_g = 1; gfx_b = 0;
gfx_x = gr_pos_x; gfx_y = y_mem;
dloop = 1;
loop (loopsize,
  y_mem = floor(150-gfxmem[dloop]*150 + gr_pos_y);
  x_mem = dloop + gr_pos_x;
  gfx_lineto(x_mem,y_mem,1);
  gfx_x = x_mem; gfx_y = y_mem;
  dloop += 1;
);

gfx_a = 1;
gfx_r = 1; gfx_g = 0.5; gfx_b = 0;
gfx_x = gr_pos_x; gfx_y = y_mem2;
dloop2 = 1;
loop (loopsize,
  rms = sqrt(rmss +=  0.02 * (gfxmem[dloop2]^2 - rmss ));
  y_mem2 = floor(150-rms*150 + gr_pos_y);
  x_mem2 = dloop2 + gr_pos_x;
  gfx_lineto(x_mem2,y_mem2,1);
  gfx_x = x_mem2; gfx_y = y_mem2;
  dloop2 += 1;
);

// GR END

function draw_slider(pot_x,pot_y,min_val,max_val,step_size,frame_width,frame_height,frame_count,showval,gfxindex)
instance(
  total_steps,fpos,pos_temp,
  val_pos,pot_x,pot_y,min_val,
  max_val,step_size,frame_width,
  frame_height,frame_count,showval,
  gfxindex,coordinatelist,offset,prec
)
(
  !mouse_cap ? (pos_temp = mouse_y;);

  X > pot_x && X < pot_x+frame_width && Y > pot_y && Y < pot_y+frame_height ? (
    mouse_cap & 4 ? val_pos = 0;
    pos_temp != mouse_y ? (
      mouse_cap & 16 ? (
        mouse_y > pos_temp ? val_pos -= step_size;
        mouse_y < pos_temp ? val_pos += step_size;
      ) : (
        val_pos = floor(  (max_val - (((max_val - min_val)/(frame_height-(frame_height/7.5))) * (mouse_y-pot_y-(frame_height/15)))) * (1/step_size)  ) / (1/step_size);
      );
    );
    pos_temp = mouse_y;
  );
  
  val_pos = max(val_pos,min_val);
  val_pos = min(val_pos,max_val);
  fpos = floor(((val_pos - min_val) * (frame_count-1))/(max_val - min_val)) * frame_height;
  coordinatelist[0] = 0;
  coordinatelist[1] = fpos;
  coordinatelist[2] = coordinatelist[6] = frame_width;
  coordinatelist[3] = coordinatelist[7] = frame_height;
  coordinatelist[4] = pot_x;
  coordinatelist[5] = pot_y;
  gfx_a=1;
  gfx_r=gfx_g=gfx_b=1;
  gfx_blitext(gfxindex, coordinatelist, 0);
  showval ? (
    step_size >= 1 ? prec = 0;
    step_size < 1 ? prec = 1;
    step_size < 0.1 ? prec = 2;
    offset = 3;    
    val_pos < 0 ? offset = 11;
    val_pos <= -10 ? offset = 13;
    val_pos <= -100 ? offset = 16;    
    val_pos >= 10 ? offset = 7;
    val_pos >= 100 ? offset = 12;
    offset += prec^2 + (prec ? 7 : 0);
    
    gfx_x = pot_x+frame_width/2-offset; gfx_y = pot_y+frame_height+5;
    gfx_drawnumber(val_pos,prec);
  );
  val_pos;
);

input_gain_lin = p1.draw_slider(30,50,0,40,1,20,150,40,1,0);
input_gain = 10 ^ ((input_gain_lin) / 20);

crush_lin = p2.draw_slider(90,50,0,100,1,20,150,40,1,0);
crush = crush_lin/100;

tight_lin = p3.draw_slider(150,50,0,100,1,20,150,40,1,0);
tight = tight_lin/100;

relax_lin = p4.draw_slider(210,50,0,100,1,20,150,40,1,0);
relax = relax_lin/100;

compensation = 0.1/(crush + tight + relax) + 1 ;

output_gain_lin = p5.draw_slider(550,50,-20,20,1,20,150,40,1,0);
output_gain = 10 ^ ((output_gain_lin) / 20);

autogain = p6.draw_slider(530,50,0,1,1,10,20,2,0,2);

@sample

M = (spl0 + spl1)*0.5;
S = (spl0 - spl1)*0.5;

inputM = ( M + (flt1M.filterHP(M,8000) * 3) ) * input_gain;
inputM = abs(inputM);

relmodM = relmodM.follower(inputM,0,t300);
relmodM = t2000 / (0.00003 * relmodM+1);

crush ? (env1M = env1M.follower(inputM,0,t20););
tight ? (env2M = env2M.follower(inputM,t10,t75););
relax ? (env3M = env3ML.follower(inputM,t100,relmodM););

envM = ( (env1M*crush*0.8*0.708) + (env2M*tight*1.2*0.708) + (env3M*relax*2*0.708) ) * compensation;
envM = env4M.follower(envM,0,t20);
envM = env5M.follower(envM,0,t20);

envM = 1/(envM + 1);

inputS = ( S + (flt1S.filterHP(S,8000) * 3) ) * input_gain;
inputS = abs(inputS);

relmodS = relmodS.follower(inputS,0,t300);
relmodS = t2000 / (0.00003 * relmodS+1);

crush ? (env1S = env1S.follower(inputS,t10,t20););
tight ? (env2S = env2S.follower(inputS,t20,t75););
relax ? (env3S = env3S.follower(inputS,t75,relmodS););

envS = ( (env1S*crush*0.8) + (env2S*tight*1.2) + (env3S*relax*2) ) * compensation;
envS = env4S.follower(envS,0,t20);
envS = env5S.follower(envS,0,t20);

envS = 1/(envS + 0.708);

t_driver = sqrt((input_gain_lin/40)^0.5);
t_driver2 = sqrt((tight*30)^0.5);

attackM = aM.transient(M,(t_driver * t_driver2));
attackS = aS.transient(S,t_driver * t_driver2);

envsum = min(envM,envS);

M = M + M * attackM;
//S = S + S * attackS;
M = (M * envM);
S = (S * envS) * 0.794;

spl0 = M+S;
spl1 = M-S;

autogain ? (ag = ag.agc(spl0,spl1);) : (ag = 1;);

spl0 = spl0 * output_gain * ag;
spl1 = spl1 * output_gain * ag;
