desc:MIDI Velocity Humanizer V1.1 by Ian Dingwall 4th May 2011
in_pin:none
out_pin:none

slider1:0<0,127,1{C0,C#0,D0,D#0,E0,F0,F#0,G0,G#0,A0,Bb0,B0,C1,C#1,D1,D#1,E1,F1,F#1,G1,G#1,A1,Bb1,B2,C2,C#2,D2,D#2,E2,F2,F#2,G2,G#2,A2,Bb2,B2,C3,C#3,D3,D#3,E3,F3,F#3,G3,G#3,A3,Bb3,B3,C4,C#4,D4,D#4,E4,F4,F#4,G4,G#4,A4,Bb4,B4,C5,C#5,D5,D#5,E5,F5,F#5,G5,G#5,A5,Bb5,B5,C6,C#6,D6,D#6,E6,F6,F#6,G6,G#6,A6,Bb6,B6,C7,C#7,D7,D#7,E7,F7,F#7,G7,G#7,A7,Bb7,B7,C8,C#8,D8,D#8,E8,F8,F#8,G8,G#8,A8,Bb8,B8,C9,C#9,D9,D#9,E9,F9,F#9,G9,G#9,A9,Bb9,B9,C10,C#10,D10,D#10,E10,F10,F#10,G10>Lowest note to change
slider2:127<0,127,1{C0,C#0,D0,D#0,E0,F0,F#0,G0,G#0,A0,Bb0,B0,C1,C#1,D1,D#1,E1,F1,F#1,G1,G#1,A1,Bb1,B2,C2,C#2,D2,D#2,E2,F2,F#2,G2,G#2,A2,Bb2,B2,C3,C#3,D3,D#3,E3,F3,F#3,G3,G#3,A3,Bb3,B3,C4,C#4,D4,D#4,E4,F4,F#4,G4,G#4,A4,Bb4,B4,C5,C#5,D5,D#5,E5,F5,F#5,G5,G#5,A5,Bb5,B5,C6,C#6,D6,D#6,E6,F6,F#6,G6,G#6,A6,Bb6,B6,C7,C#7,D7,D#7,E7,F7,F#7,G7,G#7,A7,Bb7,B7,C8,C#8,D8,D#8,E8,F8,F#8,G8,G#8,A8,Bb8,B8,C9,C#9,D9,D#9,E9,F9,F#9,G9,G#9,A9,Bb9,B9,C10,C#10,D10,D#10,E10,F10,F#10,G10>Highest note to change
slider3:1<1,127,1>Compress input velocity minimum
slider4:127<1,127,1>Compress input velocity maximum
slider5:96<1,999,1>Sequence resolution
slider6:0<1,1,1{Absolute,Relative}>Velocity sequence usage
slider7:1<-3,3,0.01>Velocity sequence strength
slider8:0<-100,100,1>Velocity sequence velocity offset
slider9:0<-0.4999,0.5,0.0001>Velocity Sequence bar offset
slider10:0<0,50,1>Add random velocity humanization
slider11:1<1,192,1>Edit sequence selector 1/N (1=off)
slider12:0<0,4,1{No changes, Multiply resolution by 2, Multiply resolution by 3, Divide resolution by 2, Divide resolution by 3> Edit Resolution changer
@init
ext_noinit;
safe=1;
s1=0;
s2=127;
s3=1;
s4=127;
s6=0;
s7=1;
s8=0;
s9=0;
s10=0;
s11=1;
lastslider12=0;
sq=0;
seq=0;
selected=-1;
focus=-1;
oldmouse=0;
div127=1/127;
div126=1/126;
div12=1/12;
div100=1/100;
div3=1/3;
b_max=100;
b_is=0;
b_pos=1000;
b_beat=2000;
b_pitch=3000;
b_oldvel=4000;
b_newvel=5000;
b_sel=6000;
octave=7000;
octave[0]=$'C';
octave[1]=0;
octave[2]=$'C';
octave[3]=$'#';
octave[4]=$'D';
octave[5]=0;
octave[6]=$'D';
octave[7]=$'#';
octave[8]=$'E';
octave[9]=0;
octave[10]=$'F';
octave[11]=0;
octave[12]=$'F';
octave[13]=$'#';
octave[14]=$'G';
octave[15]=0;
octave[16]=$'G';
octave[17]=$'#';
octave[18]=$'A';
octave[19]=0;
octave[20]=$'B';
octave[21]=$'b';
octave[22]=$'B';
octave[23]=0;

iiii=0;
loop(b_max+1,
	b_beat[iiii]=-1;
	iiii+=1;
	);

@slider
slider1!=s1?
	(
	slider1>s2?
		(
		slider2=slider1;
		s2=slider2;
		);
	s1=slider1;
	);
slider2!=s2?
	(
	slider2<s1?
		(
		slider1=slider2;
		s1=slider1
		);
	s2=slider2;
	);	

slider3!=s3?
	(
	slider3>s4?
		(
		slider4=slider3;
		s4=slider4;
		);
	s3=slider3;
	);
slider4!=s4?
	(
	slider4<s3?
		(
		slider3=slider4;
		s3=slider3
		);
	s4=slider4;
	);
	
slider5!=seqsize?
	(
	seqsize=slider5;
	divseqsize=1/seqSize;
    s11=0;
	);

slider6!=s6?
	(
	s6=slider6;
	);

slider7!=s7?
	(
	s7=slider7;
	);
	
slider8!=s8?
	(
	s8=slider8;
	);

slider9!=s9?
	(
	s9=slider9;
	);
	
slider10!=s10?
	(
	s10=slider10;
	sq=sqrt(s10);
	);	
	
slider11!=s11?
	(
	s11=slider11;
	s11>seqsize?
		(
		s11=seqsize;
		slider11=seqsize;
		);
	seqsize%s11!=0?
		(
		while(
			s11-=1;
			seqsize%s11!=0;
			);
		slider11=s11;
		);
	);
	
slider12!=0?
		(
		slider12==1 && seqsize*2<999 && lastslider12==0 ?
			(
			slider12=0;
			ui=999;
			loop(1000,
				seq[ui]=seq[ui/2];
				ui-=1;
				);
			slider5=slider5*2;
			seqsize=seqsize*2;
			divseqsize=1/seqsize;
			);
		slider12==2 && seqsize*3<999 && lastslider12==0 ?
			(
			slider12=0;
			seq[999]=0;
			ui=998;
			loop(999,
				seq[ui]=seq[ui/3];
				ui-=1;
				);
			slider5=slider5*3;
			seqsize=seqsize*3;
			divseqsize=1/seqsize;
			);
		slider12==3 && lastslider12==0 ?
			(
			slider12=0;
			ui=0;
			loop(500,
				seq[ui]=(seq[ui*2]+seq[ui*2+1])*0.5;
				ui+=1;
				);
			ui=499;
			loop(500,
				seq[ui]=0;
				ui+=1;
				);
			slider5=floor(slider5/2);
			seqsize=0;
			);	
		slider12==4 && lastslider12==0 ?
			(
			slider12=0;
			ui=0;
			loop(333,
				seq[ui]=(seq[ui*3]+seq[ui*3+1]+seq[ui*3+2])*div3;
				ui+=1;
				);
			loop(667,
				seq[ui]=0;
				ui+=1;
				);
			slider5=floor(slider5/3);
			seqsize=0;
			);			
		lastslider12=10;
		);
slider12=0;

@block

divtn=1/ts_num;
divtempo=1/tempo;
divsrate=1/srate;

while 
	(
	midirecv(ts,msg1,msg23) ? 
		(
		bp=beat_position;
		divtn=1/ts_num;
		m=msg1&240;
		vel=(msg23/256)|0;
		note=msg23&127;
		m == 9*16 && vel > 0 && note >= s1 && note <= s2 ? 
			(
			pos=(bp*divtn)-floor(bp*divtn)+ts*divsrate*divtempo*60*divtn;
			pos>=1? pos=pos-1;
			offpos=pos-s9;
			offpos>=1? offpos=offpos-1;
			offpos<0? offpos=offpos+1;
			newvel=s3+((vel*(s4-s3))*div126)-1;
			s6==0?
				(
				newvel=newvel+s7*seq[floor(seqsize*offpos)]+s8;
				):(
				newvel=newvel*(1+s8*div100+s7*div100*seq[floor(seqsize*offpos)]);
				);
			s10>0?
				(
				newvel=newvel+sqr(rand(sq))*sign(rand(2)-1);
				);
			newvel=floor(newvel+0.5);
			newvel<0? newvel=0;
			newvel>127? newvel=127;
			b_is+=1;
			b_is>b_max? b_is=0;
			safe=0;
			b_pitch[b_is]=note;
			b_oldvel[b_is]=vel;
			play_state==1 || playstate==5?
				(
				b_pos[b_is]=pos;
				):(
				b_pos[b_is]=-1;
				);
			b_beat[b_is]=bp+((ts*divsrate)*divtempo)*60;
			b_newvel[b_is]=newvel;
			safe=1;
			midisend(ts,msg1,note+newvel*256);
			) :
			(
			midisend(ts,msg1,msg23);
			);
		);
	);

@gfx 400 200
lastslider12>0? lastslider12-=1;
gfx_clear=0;
gfx_mode=0;
divtsnum=1/ts_num;

gfx_r=0;
gfx_g=0;
gfx_b=0.15;
gfx_a=1;
velmax1=s3+((127*(s4-s3))*div126)-1;
velmin1=s3+((s4-s3)*div126)-1;
ii=0;
loop(seqsize,
	s6==0?
		(
		velmax=velmax1+s7*seq[ii]+s8;
		velmin=velmin1+s7*seq[ii]+s8;
		):(
		velmax=velmax1*(1+s8*div100+s7*div100*seq[ii]);
		velmin=velmin1*(1+s8*div100+s7*div100*seq[ii]);
		);
	s10>0?
		(
		velmax=velmax+s10;
		velmin=velmin-s10;
		);
	velmax=floor(velmax+0.5);
	velmax<0? velmax=0;
	velmax>127? velmax=127;
	gfx_y=gfx_h -1-velmax* gfx_h *div127;
	velmin=floor(velmin+0.5);
	velmin<0? velmin=0;
	velmin>127? velmin=127;
	gfxy=gfx_h -1-velmin* gfx_h *div127;

	xa=ii*(gfx_w-1)*divseqsize+s9*(gfx_w-1);
	xb=(ii+1)*(gfx_w-1)*divseqsize+s9*(gfx_w-1);
	xb>=gfx_w?
		(
		gfx_x=xa;
		gfx_rectto(xb,gfxy);
		xa-=gfx_w;
		xb-=gfx_w;
		);
	xa<0?
		(
		gfx_x=xa;
		gfx_rectto(xb,gfxy);
		xa+=gfx_w;
		xb+=gfx_w;
		);
	gfx_x=xa;
	gfx_rectto(xb,gfxy);
	ii+=1;
	);

gfx_a=1;
gfx_r=0.5;
gfx_g=0.5;
gfx_b=0.5;
ii=0;
loop((ts_num-1),
	ii+=1;
	gfx_x=ii*((gfx_W-1)*divtsnum);
	gfx_y=1;
	gfx_lineto(gfx_x,(gfx_h-1),0.5);
	);
gfx_a=0.3;
gfx_r=0;
gfx_g=1;
gfx_b=0;
gfx_x=0;
gfx_y=gfx_h/2;
gfx_lineto((gfx_w-1),(gfx_h-1)*0.5,0.5);
gfx_x=s9*(gfx_w-1);
gfx_x<0? gfx_x+=gfx_w;
gfx_y=0;
gfx_lineto(gfx_x,gfx_h-1,0.5);
s6==1?
	(
	fu=0.005;
	ha=100;
	):(
	fu=0.003937008;
	ha=127;
	);
mx=mouse_x;
my=mouse_y;
mx>=0 && mx<gfx_w && my>0 && my<gfx_h?
	(
	tempx=mx/gfx_w-s9;
	tempx<0? tempx+=1;
	tempx>1? tempx-=1;
	tempseq=floor(seqsize*tempx);
	s11>1?
		(
		q=floor(seqsize/s11);
		uu=0;
		loop(seqsize,
			(uu>tempseq && ((uu-tempseq)/q==floor((uu-tempseq)/q))) ||(uu<tempseq && ((tempseq-uu)/q==floor((tempseq-uu)/q))) || uu==tempseq ?
				(
				b_sel[uu]=1;
				):(
				b_sel[uu]=0;
				);
			uu+=1;
			);
		):(
		uu=0;
		loop(seqsize,
			b_sel[uu]=0;
			uu+=1;
			);
		b_sel[tempseq]=1;
		);
		
			
	tempy=(ha-s7*seq[tempseq]-s8)*(gfx_h-1)*fu;
	abs(my-tempy)<gfx_h*0.05 || (mouse_cap&1==1 && selected!=-1) ?
		(
		gfx_a=1;
		gfx_r=1;
		gfx_g=1;
		gfx_b=1;
		gfx_x=mx+15;
		gfx_y=my+15;
		gfx_drawnumber(seq[tempseq],0);
		s6==1? gfx_drawchar($'%');
		pressed!=1 ? selected=tempseq;
		mouse_cap&1==1?
			(
			pressed=1;
			nvel=floor((ha-s8-my/fu/(gfx_h-1))/s7+0.5);
			dvel=nvel-seq[selected];
			s11>1?
				(
				q=floor(seqsize/s11);
				uu=0;
				loop(seqsize,
					(uu>selected && ((uu-selected)/q==floor((uu-selected)/q))) ||(uu<selected && ((selected-uu)/q==floor((selected-uu)/q))) || uu==selected ?
						(
						b_sel[uu]=1;
						seq[uu]=seq[uu]+dvel;
						seq[uu]<-100? seq[uu]=-100;
						seq[uu]>100? seq[uu]=100;
						):(
						b_sel[uu]=0;
						);
					uu+=1;
					);
				):(
				uu=0;
				loop(seqsize,
					b_sel[uu]=0;
					uu+=1;
					);
				b_sel[selected]=1;
				seq[selected]=seq[selected]+dvel;
				seq[selected]<-100? seq[selected]=-100;
				seq[selected]>100? seq[selected]=100;
				);			

			//pressed=1;
			//ii=0;
			//loop(seqsize,
			//	b_sel==1?
			//		(
			//		seq[ii]=seq[ii]+dvel;
			//		seq[ii]<-100? seq[ii]=-100;
			//		seq[ii]>100? seq[ii]=100;
			//		);
			//	ii+=1;
			//	);
			):(
			pressed=-1;
			selected=-1;
			);
		):(
		selected=-1;
		);
	);

ii=0;
ya=((ha-s7*(seq[seqsize-1])-s8)*(gfx_h-1))*fu;
gfx_r=0.7;
gfx_g=0.7;
gfx_b=0;
gfx_a=0.5;
loop((seqsize),
	yb=((ha-s7*(seq[ii])-s8)*(gfx_h-1))*fu;
	xa=ii*(gfx_w-1)*divseqsize+s9*(gfx_w-1);
	xb=(ii+1)*(gfx_W-1)*divseqsize+s9*(gfx_w-1);
	xa<0?
		(
		xb>=0?
			(
			gfx_x=xa;
			gfx_y=yb;
			b_sel[ii]==1? gfx_a=1;
			gfx_lineto(xb,yb,0.5);
			gfx_a=0.5;
			);			
		xa+=gfx_w;
		xb+=gfx_w;
		):(
		xb>gfx_w-1?
			(
			xa<=gfx_w-1?
				(
				gfx_x=xa;
				gfx_y=ya;
				gfx_lineto(xa,yb,0.5);
				b_sel[ii]==1? gfx_a=1;
				gfx_lineto(xb,yb,0.5);
				gfx_a=0.5;
				);
			xa-=gfx_w;
			xb-=gfx_w;
			);
		);
	gfx_x=xa;
	gfx_y=ya;
	gfx_lineto(xa,yb,0.5);
	b_sel[ii]==1? gfx_a=1;
	gfx_lineto(xb,gfx_y,0.5);
	gfx_a=0.5;
	ii+=1;
	ya=yb;
	);
	
gfx_a=1;
gfx_r=1;
gfx_g=1;
gfx_b=1;
gfx_x=((beat_position*divtsnum)-floor(beat_position*divtsnum))*(gfx_w-1);
gfx_y=1;
gfx_lineto(gfx_x,(gfx_h-1),0.5);
i=0;
loop(b_max+1,
	((play_state!=1) & (play_state!=5)) ? b_pos[i]=-1;
	b_pos[i]!=-1?
		(
		(b_beat[i]+ts_num)<=beat_position?
			(b_pos[i]=-1;
			):(
			i!=b_is || safe==1?
				(
				ovel=b_oldvel[i];
				nvel=b_newvel[i];
				dvel=ovel-nvel;
				advel=abs(dvel);
				h2=gfx_h/200;
				h1=h2*2;
				h127=(gfx_h-1)/127;
				gfx_x=b_pos[i]*(gfx_w-1);
				gfx_y=(127-ovel)*h127;
				gfx_setpixel(1,1,1);
				gfx_r=1;
				gfx_g=1;
				gfx_b=1;
				gfx_a=0.1;
				gfx_lineto(gfx_x,(127-nvel)*h127,0.5);
				gfx_y=(127-nvel)*h127;
				gfx_x=gfx_x-h2;
				gfx_y=gfx_y-h2;
				gfx_a=0.4+advel*div127;
				gfx_a>1? gfx_a=1;
				(advel)<1?
					(
					gfx_r=0.6;
					gfx_g=0.6;
					gfx_b=0.6;
					):(
					ovel<nvel?
						(
						gfx_r=0.3;
						gfx_g=1;
						gfx_b=0.3;
						):(
						gfx_r=1;
						gfx_g=0.3;
						gfx_b=0.3;
						);
					);
				gfx_rectto(gfx_x+h1,gfx_y+h1);
				gfx_r=0.9;
				gfx_g=0.9;
				gfx_b=0.9;
				oct=floor(b_pitch[i]*div12);
				ton=b_pitch[i]-12*oct;
				gfx_drawchar(octave[ton*2]);
				gfx_drawchar(octave[ton*2+1]);
				gfx_drawnumber(oct,0);
				);
			);
		);
		i+=1;
	);


@serialize
iii=0;
seq=0;
file_var(0,seqsize); 
loop(1000,
	file_var(0,seq[iii]);
	iii+=1;
	);
