WAVEFORM METER
desc:Minimeters Waveform Replica (Pure Color - No Burn)
//tags: analysis waveform visualizer
//author: Gemini
slider1:0<0,3,1{Left,Right,Mid,Side}>Channel 1
slider2:1<0,4,1{Off,Left,Right,Mid,Side}>Channel 2
slider3:1<0,1,1{Static (White),Multi-band (Dynamic Map)}>Color Mode
slider4:1<0,2,1{Off,Fast,Slow}>History (Ghost Trail)
slider5:6<1,10,1>Zoom / Speed
in_pin:left input
in_pin:right input
options:no_meter
@init
gfx_ext_retina == 0 ? gfx_ext_retina = 1;
// Configuración de Memoria
max_len = 16384;
b1_m = 0; b1_l = 20000; b1_md = 40000; b1_h = 60000; b1_pk = 80000;
b2_m = 100000; b2_l = 120000; b2_md = 140000; b2_h = 160000; b2_pk = 180000;
w_idx = 0;
lp_f = 200; hp_f = 2500;
env1 = 0; env2 = 0;
@slider
ch1_s = slider1;
ch2_s = slider2 - 1;
ch2_on = (slider2 > 0);
col_mode = slider3;
hist_mode = slider4;
speed_zoom = slider5;
decay = (hist_mode == 1) ? 0.92 : 0.98;
samps_per_px = (11 - speed_zoom) * 40;
@block
alp = exp(-2 * $pi * lp_f / srate);
ahp = exp(-2 * $pi * hp_f / srate);
@sample
function get_s(sel, l, r) ( sel==0?l:sel==1?r:sel==2?(l+r)*0.5:(l-r)*0.5 );
s1 = get_s(ch1_s, spl0, spl1);
s2 = ch2_on ? get_s(ch2_s, spl0, spl1) : 0;
// --- PROCESO C1 ---
l1 = (s1*(1-alp)) + (ll1*alp); ll1=l1;
h1 = s1-ls1+(lh1*ahp); lh1=h1; ls1=s1;
m1 = s1 - l1 - h1;
env1 = max(env1 * decay, abs(s1));
acc1_m = max(acc1_m, abs(s1));
acc1_l = max(acc1_l, abs(l1));
acc1_md= max(acc1_md, abs(m1));
acc1_h = max(acc1_h, abs(h1));
// --- PROCESO C2 ---
ch2_on ? (
l2 = (s2*(1-alp)) + (ll2*alp); ll2=l2;
h2 = s2-ls2+(lh2*ahp); lh2=h2; ls2=s2;
m2 = s2 - l2 - h2;
env2 = max(env2 * decay, abs(s2));
acc2_m = max(acc2_m, abs(s2));
acc2_l = max(acc2_l, abs(l2));
acc2_md= max(acc2_md, abs(m2));
acc2_h = max(acc2_h, abs(h2));
);
cnt += 1;
cnt >= samps_per_px ? (
b1_m[w_idx] = acc1_m; b1_l[w_idx] = acc1_l; b1_md[w_idx] = acc1_md; b1_h[w_idx] = acc1_h; b1_pk[w_idx] = env1;
ch2_on ? (
b2_m[w_idx] = acc2_m; b2_l[w_idx] = acc2_l; b2_md[w_idx] = acc2_md; b2_h[w_idx] = acc2_h; b2_pk[w_idx] = env2;
);
w_idx = (w_idx + 1) % max_len;
acc1_m=0; acc1_l=0; acc1_md=0; acc1_h=0;
acc2_m=0; acc2_l=0; acc2_md=0; acc2_h=0;
cnt = 0;
);
@gfx 600 300
// Fondo Negro Absoluto
gfx_r=0; gfx_g=0; gfx_b=0; gfx_a=1;
gfx_rect(0,0,gfx_w,gfx_h);
lane_h = ch2_on ? gfx_h / 2 : gfx_h;
cy1 = ch2_on ? lane_h / 2 : gfx_h / 2;
cy2 = ch2_on ? lane_h + (lane_h / 2) : 0;
function draw_pure_slice(x, v_m, v_l, v_md, v_h, v_pk, cy, h) (
max_h = (h/2) * 0.95;
// 1. DIBUJAR GHOST TRAIL (Detrás)
hist_mode > 0 ? (
ph = v_pk * max_h;
gfx_r=0.15; gfx_g=0.15; gfx_b=0.15; gfx_a=1;
gfx_rect(x, cy - ph, 1, ph*2);
);
// 2. DIBUJAR ONDA DINÁMICA
len = v_m * max_h;
col_mode == 1 ? (
// Algoritmo de Color por Dominancia (Evita el blanco quemado)
total = v_l + v_md + v_h + 0.0001;
// Calculamos la influencia de cada banda
r = (v_l / total);
g = (v_md / total);
b = (v_h / total);
// Asignamos el color final a la onda única
gfx_r = r * 1.2; // Un poco de boost al rojo para los bajos
gfx_g = g * 0.9;
gfx_b = b * 1.5; // Boost al azul para los brillos
) : (
gfx_r=1; gfx_g=1; gfx_b=1;
);
gfx_a=1;
gfx_rect(x, cy - len, 1, len*2);
);
// RENDER LOOP
read_p = w_idx - 1;
i = 0;
gfx_mode = 0; // Modo normal para evitar sumas de brillo indeseadas
loop(gfx_w,
read_p < 0 ? read_p += max_len;
x = gfx_w - 1 - i;
draw_pure_slice(x, b1_m[read_p], b1_l[read_p], b1_md[read_p], b1_h[read_p], b1_pk[read_p], cy1, lane_h);
ch2_on ? draw_pure_slice(x, b2_m[read_p], b2_l[read_p], b2_md[read_p], b2_h[read_p], b2_pk[read_p], cy2, lane_h);
read_p -= 1;
i += 1;
);
// Labels
gfx_r=1; gfx_g=1; gfx_b=1; gfx_a=0.3;
gfx_x=5; gfx_y=cy1 - (lane_h/2) + 5;
ch1_s==0?gfx_drawstr("L"):ch1_s==1?gfx_drawstr("R"):ch1_s==2?gfx_drawstr("M"):gfx_drawstr("S");
ch2_on ? (
gfx_x=5; gfx_y=cy2 - (lane_h/2) + 5;
sel=slider2-1;
sel==0?gfx_drawstr("L"):sel==1?gfx_drawstr("R"):sel==2?gfx_drawstr("M"):gfx_drawstr("S");
gfx_a=0.1; gfx_line(0, gfx_h/2, gfx_w, gfx_h/2);
);