Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
303 changes: 303 additions & 0 deletions Utility/karkas_BLU spectrum analizer.jsfx
Original file line number Diff line number Diff line change
@@ -0,0 +1,303 @@
desc: BLU spectrum analizer
author: Karkas
version: 1.2
about: BLU is a spectrum analyzer which develops the ideas of Cockos and Saike. Features: mid-side mode, +6 dB/oct slope (Brown noise), graphics with a focus on design and minimalism. The main feature is that the volume scale follows the slope of the spectrum, which is logical and more informative than the standard grid, especially in the low-frequency range.

desc:BLU
tags: analysis FFT meter spectrum
version: 1.2
author: Cockos, Joep Vanlier, Karkas

Copyright (C) 2007 Cockos Incorporated
Copyright (C) 2018 Joep Vanlier
Copyright (C) 2025 Karkas
License: LGPL - http://www.gnu.org/licenses/lgpl-3.0.html

slider1:10<0,9,1{16,32,64,128,256,512,1024,2048,4096,8192,16384,32768}>-FFT size
slider2:-80<-450,-12,6>-floor
slider3:0<0,1,1{disabled,enabled}>-show phase
slider4:3<0,3,1{rectangular,hamming,blackman-harris,blackman}>-window
slider5:0<0,2500,1>-integration time (ms)
slider6:1<1,6,.2>-scaling

in_pin:left input
in_pin:right input
options:no_meter

@init
gfx_ext_retina=2.0;
//ext_nodenorm=1.0;
ext_noinit=1.0;
ext_tail_size=1;
recpos=0;
max_fft_size=32768;
shift=327680;
recpos2=shift;
fftsize=max_fft_size;
gfx_clear=1;
windowtype=-1;
fftidx=-1;
scaling=1;
grid=2;

histsize=max_fft_size + (max_fft_size*0.5 - 1);
window=histsize;
fftworkspace=window+(max_fft_size*0.5 + 1);
integrate_buf = fftworkspace + max_fft_size*2;

histsize2=max_fft_size + (max_fft_size*0.5 - 1) + shift;
fftworkspace2=window+(max_fft_size*0.5 + 1) + shift;
integrate_buf2 = fftworkspace + max_fft_size*2 + shift;

@slider
slider2 != lfloor ? old_w=0;

@block
slider2 != lfloor ? (
lfloor = slider2;
minvol=2*exp(log(10)/20*slider2);
);

@sample

out0 = spl0 - last0;
out1 = spl1 - last1;

last0 = spl0;
last1 = spl1;

last0 = last0*0.9998;
last1 = last1*0.9998;

sp0 = out0*7.7;
sp1 = out1*7.7;

a1 = sp0+sp1;
b1 = sp1-sp0;

abs(recpos[]=(a1)*1.1) > minvol ? update=1;
recpos = ((recpos+1) >= histsize ? 0 : (recpos+1));

abs(recpos2[]=(b1)*1.1) > minvol ? update=1;
recpos2 = ((recpos2+1) >= histsize2 ? shift : (recpos2+1));

@gfx 640 270

gfx_ext_retina>1 ? gfx_setfont(1,"Arial",9*gfx_ext_retina,'b') : gfx_setfont(0);

function drawFFT(rpos, fftwspace, intbuf, bufStart, histEnd, rr, gg, bb)
(
buf1=rpos-fftsize;
buf1<bufStart ? buf1+=histsize;
buf2=window;
buf3=fftwspace;
loop(fftsize*.5 + 1,
buf3[] = buf1[]*buf2[];
buf3+=1;

buf2+=1;
(buf1+=1) >= histEnd ? buf1 -= histsize;
);
buf2-=1;
loop(fftsize*.5 - 1,
buf3[] = buf1[]*(buf2-=1)[];
buf3+=1;
(buf1+=1) >= histEnd ? buf1 -= histsize;
);

fft_real(fftwspace,fftsize);
fft_permute(fftwspace,fftsize/2);
fftwspace[1]=0;

ascale=gfx_h/$pi*0.25;
xscale=800/(fftsize-4);

buf3=fftwspace;
buf2=intbuf+max_fft_size*0.5;
i=0;
lx=0;
// Draw phase
slider3 ? loop(fftsize*0.5,
ang=-atan2(buf3[1],buf3[]);
buf3+=2;

integrate_en ? (
ang = buf2[] += integrate_sc * (ang - buf2[]);
buf2+=1;
);


ty2=ang*ascale + gfx_h*0.5;
tx = log(1.0+i*xscale)*wsc;

i ?
(
gfX_r=0.6; gfx_g=0; gfx_b=0.8; gfx_a=1;
gfx_x=lx; gfx_y=ly2; gfx_lineto(tx,ty2,1) ;
);

lx=tx; ly2=ty2;
i+=1;
);

// Draw FFT
buf3=fftwspace;
buf2=intbuf;
lx=0;
i=0;
fill_slmin=gfx_h;
fill_slast=0;
loop(fftsize*0.5,
ty = log(max(sqr(buf3[0])+sqr(buf3[1]),(10^(-500/20*2))));
buf3+=2;

integrate_en ? (
ty = buf2[] += integrate_sc * (ty - buf2[]);
buf2+=1;
);

ty = ty*-0.5*sc;
tx = log(1.0+i*xscale)*wsc;

i ?
(
gfX_r=rr;
gfx_g=gg;
gfx_b=bb;

1/*fill?*/ ? (
gfx_a=1;
tx0=tx|0;
lx0=lx|0;
tx0>lx0? (
ly < gfx_h || ty < gfx_h ? gfx_triangle(lx0,max(gfx_h,ly),lx,ly,tx0-1,ty,tx0-1,max(gfx_h,ty));
) : (
tx0 > fill_slast ? (
fill_slast < gfx_h ? gfx_line(fill_slast,gfx_h,fill_slast,fill_slmin);
fill_slmin=gfx_h;
) : (
fill_slmin=min(fill_slmin,ty);
);
);
fill_slast=tx0;
);
gfx_a=1;
gfx_x=lx; gfx_y=ly; gfx_lineto(tx,ty,1) ;
);

ty<gfx_h ? update=1;

lx=tx; ly=ty; ly2=ty2;
i+=1;
);
);

// only update if new fft data is there or if the size changed
update || old_w != gfx_w || old_h!=gfx_h? (

old_w=gfx_w; old_h=gfx_h;

gfx_r=gfx_g=gfx_b=0.1; gfx_a=1;
gfx_x=gfx_y=0;
gfx_rectto(gfx_w,gfx_h);

sc=(gfx_h-20)*20/(-slider2 * log(10));

// draw horz grid

gfx_r=gfx_g=gfx_b=0.3;
gfx_a=0.6;
gv=1;
gv2=1;
cnt=100;
gfx_y=-100;
while(
y=20-log(gv)*sc;
y2=((gv2+2.0))*(sc);
y3=(gv2-4.1)*(sc);
y2> gfx_y ? (
//gfx_line(0,y,gfx_w,y,0);
gfx_line(0,y2,gfx_w,y3,0);
bottom_line = gfx_y;
gfx_x=2;
gfx_y=y2;
gfx_drawnumber(log10(gv)*20,0);
//gfx_drawchar($'d');
//gfx_drawchar($'B');
gfx_y+=gfx_texth;
);
gv*=(0.5/grid);
gv2+=(0.692*grid);

gfx_y<gfx_h && cnt-=10 > 0;
);

wsc=scaling*gfx_w/log(1+400);

// draw vert grid

f=10;
gfx_x+=4;
lx=gfx_x;
while(
tx = log(1.0+(f/srate*2.0)*400)*wsc;
dotext = tx > gfx_x && f!=0 && f!=40000 && f != 150000 &&
(f<900 || f >= 1000 || f == 500) && (f<60000 || f>=10000);
tx > lx ? ( lx=tx+4; gfx_line(tx,(dotext ? 0 : gfx_texth+2),tx,gfx_h,0); );
dotext ? (
gfx_x = tx + 4;
gfx_y = 2;
f>=1000 ? gfx_printf("%dK",f*.001) : gfx_printf("%d",f);
);
f += (f<100?10:f<1000?100:f<10000?1000:5000);
f < srate*0.5;
);

update ? (
update=0;
scaling = slider6;

integrate_sc = 1;
slider5 > 0 ? (
integrate_now = time_precise();
integrate_en ? (
fps = 1/(integrate_now - integrate_lastt);
integrate_sc -= exp(-5 * 1000.0 * (integrate_now - integrate_lastt) / slider5);
) : (
// force overwrite of buffer
integrate_en = 1;
);
integrate_lastt = integrate_now;
) : (
integrate_en = 0;
);

fftidx != (slider1|0) ? (
fftidx=slider1|0;
fftsize=2^(min(max(fftidx,0),11)+4);
integrate_sc=1;
);

windowsize != fftsize || windowtype != (slider4|0) ? (
windowtype=slider4|0;
windowsize=fftsize;
dwindowpos = $pi*2/fftsize;
i=pwr=0;
loop(fftsize*.5+1,
windowpos=i*dwindowpos;
pwr += (window[i] = (
windowtype==1 ? 0.53836 - cos(windowpos)*0.46164 :
windowtype==2 ? 0.35875 - 0.48829 * cos(windowpos) + 0.14128 * cos(2*windowpos) - 0.01168 * cos(3*windowpos) :
windowtype==3 ? 0.42 - 0.50 * cos(windowpos) + 0.08 * cos(2.0*windowpos) :
1.0));
i+=1;
);
pwr=.5/(pwr*2-window[i-1]);
loop(fftsize*.5+1,window[i-=1]*=pwr);
integrate_sc=1;
);

drawFFT(recpos, fftworkspace, integrate_buf, 0, histsize, 0.8, 0.8, 0.8);
drawFFT(recpos2, fftworkspace2, integrate_buf2, shift, histsize2, 0, 0.5, 0.7);
);
);