desc:GFX Starfish //tags: filter envelope auto-wah sample-and-hold step funk //author: JGWizrad / Garden FX (GFX) // // Requires gfx-drift, gfx-input, gfx-output, gfx-ui, gfx-panel, gfx-instrument and gfx-dyn (.jsfx-inc) in the same folder. // // Starfish: an automatic filter in the spirit of the classic 70s envelope-filter pedals and the modern sample-and-hold filter // machines (personal use; the sound is designed from scratch). A resonant two-pole state-variable filter, swept by // your playing or stepped in time with the project. // MODE - ENV: the envelope follower sweeps the filter (the classic auto-wah / quack). S&H: random steps in time // with the project. ENV+S&H: the steps, scaled by how hard you play. // FILTER - LP / BP / HP / N (notch). // FREQ - where the sweep starts. DEPTH - how far it goes (0 - 6 octaves). PEAK - resonance. // UP / DOWN - the sweep direction (click the arrows). RANGE - LOW or HIGH (an octave up). // SENS, RESPONSE - how strongly and how fast the envelope follows your playing (RESPONSE: fast and snappy to slow // and vocal). // RATE x MULT - the step length (1/2 - 1/32 of a note, x1 / x2 / x4). GLIDE - smooths between steps. // PATTERN - FREE: a new random step every time. LOOP: a one-bar random pattern that repeats, so it grooves. // DRIVE - pushes the filter for a fatter, grittier sound. MIX, OUTPUT. // HOLD freezes the filter where it is; ON switches the effect in or out (both in the header). // PRESETS, and IN / OUT (bottom band): TRIM with the GUARD key, SAT and the OUT stage (OFF / CLIP / LIM). import gfx-drift.jsfx-inc import gfx-input.jsfx-inc import gfx-output.jsfx-inc import gfx-ui.jsfx-inc import gfx-panel.jsfx-inc import gfx-instrument.jsfx-inc import gfx-dyn.jsfx-inc import gfx-faceplate.jsfx-inc slider1:0<0,2,1{Env,S&H,Env+S&H}>-Mode slider2:1<0,3,1{LP,BP,HP,Notch}>-Filter slider3:250<60,3000,1>-Freq (Hz) slider4:3.5<0,6,0.01>-Depth (octaves) slider5:4<0.5,15,0.01>-Peak slider6:1<0,1,1{Down,Up}>-Direction slider7:0<0,1,1{Low,High}>-Range slider8:60<0,100,1>-Sens (%) slider9:40<0,100,1>-Response (%) slider10:2<0,4,1{1/2,1/4,1/8,1/16,1/32}>-Rate slider11:0<0,2,1{x1,x2,x4}>-Mult slider12:15<0,100,1>-Glide (%) slider13:1<0,1,1{Free,Loop}>-Pattern slider14:20<0,100,1>-Drive (%) slider15:100<0,100,1>-Mix (%) slider16:0<-12,12,0.1>-Output (dB) slider17:1<0,1,1{Bypass,On}>-Effect slider18:0<0,1,1{Off,On}>-Hold slider19:0<-24,12,0.1>-Input trim (dB) slider20:1<0,1,1{Off,On}>-Input guard slider21:0<0,100,1>-Band sat (%) slider22:30<0,100,1>-Bias (%) slider23:120<40,400,1>-Sat low band (Hz) slider24:6000<2000,16000,10>-Sat high band (Hz) slider25:-0.3<-24,0,0.1>-Ceiling / limit threshold (dB) slider26:1<0,2,1{Off,Clip,Limit}>-Output stage in_pin:left input in_pin:right input out_pin:left output out_pin:right output @init #ui_man = "gfx-starfish"; // the ? pop-up links to this manual HN = 240; HFC = 30000; HST = 30300; SPX = 30700; SPY = 30720; // display history: cutoff, step markers memset(30000, 0, 760); function th(x) ( x = min(max(x, -3), 3); x * (27 + x * x) / (27 + 9 * x * x); ); // two-pole state-variable filter (trapezoidal), coefficients shared by both sides function svf(x) instance(s1, s2) local(v1, v2, v3) ( v3 = x - s2; v1 = fa1 * s1 + fa2 * v3; v2 = s2 + fa2 * s1 + fa3 * v3; s1 = 2 * v1 - s1; s2 = 2 * v2 - s2; s1 = th(s1 * 0.5) * 2; // the integrator saturates gently when pushed ftype == 0 ? v2 : ftype == 1 ? v1 * fk : ftype == 2 ? x - fk * v1 - v2 : x - fk * v1; ); function rnd(i) ( i = sin(i * 12.9898 + 4.1) * 43758.5453; i - floor(i); ); function update() ( mode = slider1; ftype = slider2; fbase = slider3 * (slider7 ? 2 : 1); depth = slider4; fk = 1 / slider5; dir = slider6 ? 1 : -1; sensg = 10 ^ ((slider8 - 50) / 25) * 4; env_a = dy_ms(1 + slider9 / 100 * 19); env_r = dy_ms(30 + slider9 / 100 * 770); spb = (slider10 == 0 ? 0.5 : slider10 == 1 ? 1 : slider10 == 2 ? 2 : slider10 == 3 ? 4 : 8) * (slider11 == 0 ? 1 : slider11 == 1 ? 2 : 4); // steps per beat glide = slider12 / 100; loopp = slider13; dg = 1 + slider14 / 100 * 4; mix_t = slider15 / 100; og = 10 ^ (slider16 / 20); fx_on = slider17; hold = slider18; in_setup(slider19, slider20); ins_output_setup(21); ); // ---------- presets (leave INPUT and OUTPUT alone) ---------- function ps(md, ft, f, d, pk, dr, rg, sn, rs, rt, ml, gl, lp, dv) ( slider1 = md; slider2 = ft; slider3 = f; slider4 = d; slider5 = pk; slider6 = dr; slider7 = rg; slider8 = sn; slider9 = rs; slider10 = rt; slider11 = ml; slider12 = gl; slider13 = lp; slider14 = dv; slider15 = 100; slider16 = 0; slider17 = 1; slider18 = 0; ); function load_preset(p) ( p == 1 ? ps(0, 1, 250, 3.5, 4, 1, 0, 60, 40, 2, 0, 15, 1, 20) : // Init (the defaults) p == 2 ? ps(0, 1, 250, 3.5, 5, 1, 0, 60, 30, 2, 0, 15, 1, 20) : // Funk Up p == 3 ? ps(0, 0, 900, 3, 6, 0, 0, 65, 35, 2, 0, 15, 1, 30) : // Bass Quack (down) p == 4 ? ps(1, 1, 300, 4, 7, 1, 0, 60, 40, 3, 0, 5, 1, 25) : // Ship Steps (1/16 loop) p == 5 ? ps(1, 0, 200, 4.5, 8, 1, 0, 60, 40, 2, 1, 45, 0, 15) : // Random Gurgle p == 6 ? ps(2, 1, 250, 4, 6, 1, 0, 70, 30, 3, 0, 10, 1, 20) : // Envelope Steps p == 7 ? ps(0, 3, 300, 4, 3, 1, 0, 55, 60, 2, 0, 15, 1, 0) : // Notch Sweep p == 8 ? ps(0, 1, 180, 3.5, 9, 1, 0, 60, 90, 2, 0, 15, 1, 10) : // Slow Talker p == 9 ? ps(0, 1, 400, 3, 6, 1, 1, 70, 15, 2, 0, 15, 1, 35) : // Clav Wah p == 10 ? ps(1, 1, 500, 3.5, 10, 1, 1, 60, 40, 4, 0, 0, 1, 10) : // Synth Blips (1/32) p == 11 ? ps(0, 0, 120, 5, 2, 1, 0, 50, 70, 2, 0, 15, 1, 0); // Lowpass Bloom p >= 1 && p <= 11 ? slider_automate(262143); // sliders 1-18 p == 12 ? ( // Reset all to defaults ps(0, 1, 250, 3.5, 4, 1, 0, 60, 40, 2, 0, 15, 1, 20); slider19 = 0; slider20 = 1; slider21 = 0; slider22 = 30; slider23 = 120; slider24 = 6000; slider25 = -0.3; slider26 = 1; slider_automate(67108863); ); ); in_init(); ost_init(20000); ostL.ost_ch_init(); ostR.ost_ch_init(); sm = 1 - exp(-1 / (0.03 * srate)); !ui_dflt ? ui_thm = 5; !ui_dflt ? ui_hw = 1; BLU = 0x1D3BC4; BLUD = 0x142A8C; SKYB = 0x46B2EE; REDP = 0xD43A2C; WHT = 0xF2F4FA; CHR = 0xC9CDD2; update(); mix_s = mix_t; fc = fbase; stv = 0; stg = 0; lstep = -1; bpos = 0; !ui_dflt ? pr_cur = 1; // a new instance opens on Init ui_dflt = 1; // theme defaults above apply once: @init re-runs (playback start, device reset) must not undo the saved theme @slider update(); @block update(); playing = play_state & 1; playing ? bpos = beat_position; bpm = tempo > 1 ? tempo : 120; // (no host tempo: 120) binc = bpm / 60 / srate; @serialize file_avail(0) != 0 ? ( // the preset in use (older projects end before it) file_var(0, pr_cur); pr_ver = 2; file_avail(0) != 0 ? file_var(0, pr_ver) : pr_cur >= 1 ? pr_cur += 1; // saved before INIT became preset 1 ) : pr_cur = 0; @sample in_process(spl0, spl1); dl = in_l; dr = in_r; // envelope follower (on the mono input) det = abs(dl + dr) * 0.5 * sensg; env += (det - env) * (det > env ? env_a : env_r); e = min(env, 1) ^ 0.7; // sample and hold: a step at each division of the beat bpos += binc; sidx = floor(bpos * spb); sidx != lstep ? ( lstep = sidx; stv = loopp ? rnd(sidx % max(1, floor(spb * 4)) + 1) : rand(1); steph = 1; ); glide > 0.005 ? stg += (stv - stg) / (1 + glide * 0.35 * srate * 60 / (bpm * spb)) : stg = stv; // GLIDE: a share of the step length amt = mode == 0 ? e : mode == 1 ? stg : stg * e; // the cutoff, then the filter !hold ? fc = min(max(fbase * 2 ^ (dir * depth * amt), 25), min(18000, srate * 0.42)); fg = tan($pi * fc / srate); fa1 = 1 / (1 + fg * (fg + fk)); fa2 = fg * fa1; fa3 = fg * fa2; xl = th(dl * dg) / dg * (1 + (dg - 1) * 0.3); xr = th(dr * dg) / dg * (1 + (dg - 1) * 0.3); yl = FL.svf(xl); yr = FR.svf(xr); yl = th(yl * 0.7) / 0.7; yr = th(yr * 0.7) / 0.7; mix_s += ((fx_on ? mix_t : 0) - mix_s) * sm; oL = (dl + (yl - dl) * mix_s) * (fx_on ? og : 1); oR = (dr + (yr - dr) * mix_s) * (fx_on ? og : 1); oL = ostL.ost_band(oL * in_comp); oR = ostR.ost_band(oR * in_comp); ost_out(oL, oR); spl0 = ost_l; spl1 = ost_r; fcm = fc; envm = max(envm, e); @gfx 900 382 ui_begin(900, 382); dy_ink = WHT; dy_bg = BLU; dy_kst = 0; function txt(x, y, s, a) ( gfx_setfont(4); ui_cola(WHT, a); ui_text(x * sc, y * sc, s); ); // a five-point star: filled, or as a ring of rhinestones function starpts(cx, cy, R) local(i, a) ( i = 0; loop(10, a = -$pi * 0.5 + i * $pi / 5; SPX[i] = cx + cos(a) * (i % 2 ? R * 0.42 : R); SPY[i] = cy + sin(a) * (i % 2 ? R * 0.42 : R); i += 1; ); ); function star(cx, cy, R, col) local(i, j) ( starpts(cx, cy, R); ui_col(col); i = 0; loop(10, j = (i + 1) % 10; gfx_triangle(cx * sc, cy * sc, SPX[i] * sc, SPY[i] * sc, SPX[j] * sc, SPY[j] * sc); i += 1; ); ); function rhinestar(cx, cy, R, n) local(i, j, t, k, x, y) ( starpts(cx, cy, R); i = 0; loop(10, j = (i + 1) % 10; k = 0; loop(n, t = k / n; x = SPX[i] + (SPX[j] - SPX[i]) * t; y = SPY[i] + (SPY[j] - SPY[i]) * t; ui_col(0x8E949C); gfx_circle(x * sc, y * sc, 2.4 * sc, 1, 1); ui_col(0xE8ECF2); gfx_circle(x * sc, y * sc, 1.7 * sc, 1, 1); ui_cola(0xFFFFFF, 0.9); gfx_circle((x - 0.6) * sc, (y - 0.6) * sc, 0.7 * sc, 1, 1); k += 1; ); i += 1; ); ); // a slide switch (n positions) with a coloured cap; returns the new position when clicked function slide(x, y, w, n, pos, cap, labs, title) local(cx, hit, i, sw) ( sw = (w - 16) / max(n - 1, 1); ui_col(0x0A0A12); ui_rrect(x * sc, (y - 6) * sc, w * sc, 12 * sc, 3 * sc); cx = x + 8 + pos * sw; ui_cola(0x000000, 0.4); gfx_rect((cx - 11) * sc, (y - 7) * sc, 24 * sc, 16 * sc); ui_col(cap); gfx_rect((cx - 12) * sc, (y - 8) * sc, 24 * sc, 16 * sc); ui_cola(0xFFFFFF, 0.35); gfx_rect((cx - 12) * sc, (y - 8) * sc, 24 * sc, 3 * sc); ui_cola(0x000000, 0.25); i = -2; loop(5, gfx_rect((cx + i * 4) * sc, (y - 4) * sc, 1 * sc, 9 * sc); i += 1; ); gfx_setfont(6, "Arial", 12 * sc, 'b'); ui_col(WHT); ui_text((x + w * 0.5) * sc, (y + 10) * sc, title); hit = pressed && drag_id == 0 && mouse_x >= x * sc && mouse_x < (x + w) * sc && abs(mouse_y - y * sc) < 10 * sc; hit ? ( drag_id = -1; pos = n == 2 ? 1 - pos : min(n - 1, max(0, floor((mouse_x / sc - x) / w * n))); ); pos; ); // a starfish: five soft arms, coral, with a row of dots down each arm function starfish(cx, cy, R, rot) local(i, j, a, k, t) ( i = 0; loop(10, a = -$pi * 0.5 + rot + i * $pi / 5; SPX[i] = cx + cos(a) * (i % 2 ? R * 0.36 : R); SPY[i] = cy + sin(a) * (i % 2 ? R * 0.36 : R); i += 1; ); k = 0; loop(2, ui_col(k == 0 ? 0xB8502A : 0xF28A4C); i = 0; loop(10, j = (i + 1) % 10; gfx_triangle((cx + k * 0) * sc, cy * sc, (SPX[i] + (k ? 0 : (SPX[i] - cx) * 0.06)) * sc, (SPY[i] + (k ? 0 : (SPY[i] - cy) * 0.06)) * sc, (SPX[j] + (k ? 0 : (SPX[j] - cx) * 0.06)) * sc, (SPY[j] + (k ? 0 : (SPY[j] - cy) * 0.06)) * sc); i += 1; ); i = 0; loop(5, gfx_circle(SPX[i * 2] * sc, SPY[i * 2] * sc, R * (k ? 0.15 : 0.19) * sc, 1, 1); i += 1; ); k += 1; ); ui_cola(0xFFFFFF, 0.18); gfx_circle((cx - R * 0.08) * sc, (cy - R * 0.1) * sc, R * 0.3 * sc, 1, 1); i = 0; loop(5, k = 1; loop(3, t = k / 4; ui_col(0xFFE2C8); gfx_circle((cx + (SPX[i * 2] - cx) * t) * sc, (cy + (SPY[i * 2] - cy) * t) * sc, max(1, R * 0.06 * (1.2 - t * 0.5)) * sc, 1, 1); k += 1; ); i += 1; ); ui_col(0xFFE2C8); gfx_circle(cx * sc, cy * sc, R * 0.08 * sc, 1, 1); ); // a palm tree silhouette (base at x, y; h tall), in col function palm(x, y, h, col, a) local(i, t, px, py, nx, ny, f, an, l, fx, fy, w) ( ui_cola(col, a); i = 0; px = x; py = y; loop(12, t = (i + 1) / 12; nx = x + sin(t * 1.3) * h * 0.18; ny = y - t * h; w = (1 - t * 0.5) * h * 0.035; gfx_triangle((px - w) * sc, py * sc, (px + w) * sc, py * sc, (nx + w * 0.9) * sc, ny * sc, (nx - w * 0.9) * sc, ny * sc); px = nx; py = ny; i += 1; ); f = 0; loop(7, an = -$pi + f / 6 * $pi * 1.0 + (f > 3 ? 0.15 : -0.15); l = h * (f == 3 ? 0.42 : 0.55); i = 0; fx = px; fy = py; loop(10, t = (i + 1) / 10; nx = px + cos(an) * l * t; ny = py + sin(an) * l * t + l * 0.55 * t * t; w = sin(t * $pi) * h * 0.07; gfx_triangle(fx * sc, fy * sc, nx * sc, ny * sc, (fx + nx) * 0.5 * sc, ((fy + ny) * 0.5 + w) * sc); gfx_line(fx * sc, fy * sc, nx * sc, ny * sc, 1); fx = nx; fy = ny; i += 1; ); f += 1; ); gfx_circle((px - h * 0.02) * sc, (py + h * 0.03) * sc, h * 0.035 * sc, 1, 1); gfx_circle((px + h * 0.03) * sc, (py + h * 0.04) * sc, h * 0.03 * sc, 1, 1); ); // ---------- body ---------- fh = 374; ui_col(0x0B0B0C); gfx_rect(0, 0, gfx_w, gfx_h); pk_chassis(8 * sc, 4 * sc, 884 * sc, fh * sc, BLU); gfx_gradrect(10 * sc, 6 * sc, 880 * sc, 284 * sc, 0.12, 0.25, 0.8, 0, 0, 0, 0, 0, 0, 0, 0, 0.0008 / sc); // header ui_col(WHT); gfx_circle(36 * sc, 30 * sc, 13 * sc, 1, 1); gfx_setfont(4); ui_col(BLU); ui_text(36 * sc, 25 * sc, "GFX"); rhinestar(78, 31, 17, 4); gfx_setfont(6, "Arial", 26 * sc, 'bi'); ui_col(WHT); gfx_x = 104 * sc; gfx_y = 15 * sc; gfx_drawstr("STARFISH"); txt(310, 26, "ENVELOPE + STEP FILTER", 0.75); pk_ledbtn(400 * sc, 19 * sc, 26 * sc, 22 * sc, slider18, 0xFF3A2A) ? ( slider18 = 1 - slider18; ui_auto(18); ); gfx_setfont(4); ui_col(WHT); gfx_x = 432 * sc; gfx_y = 25 * sc; gfx_drawstr("HOLD"); pk_ledbtn(474 * sc, 19 * sc, 26 * sc, 22 * sc, slider17, dy_grn) ? ( slider17 = 1 - slider17; ui_auto(17); ); gfx_setfont(4); ui_col(WHT); gfx_x = 506 * sc; gfx_y = 25 * sc; gfx_drawstr("ON"); pk_pextra = "Reset all to defaults"; // the house preset display: PRESETS, prev / next, LCD (click it for the list) k_ = pk_preset(540 * sc, 12 * sc, 282 * sc, 34 * sc, pr_cur, "Init|Funk Up|Bass Quack (down)|Ship Steps|Random Gurgle|Envelope Steps|Notch Sweep|Slow Talker|Clav Wah|Synth Blips|Lowpass Bloom"); k_ > 0 ? ( load_preset(k_); pr_cur = k_ > 11 ? 0 : k_; ); ui_size_picker(834 * sc, 20 * sc); // ---------- display: the cutoff over time ---------- ui_col(0x050507); ui_rrect(18 * sc, 58 * sc, 344 * sc, 124 * sc, 5 * sc); ui_col(0x140808); gfx_rect(22 * sc, 62 * sc, 336 * sc, 116 * sc); gi = 0; loop(HN - 1, HFC[gi] = HFC[gi + 1]; HST[gi] = HST[gi + 1]; gi += 1; ); HFC[HN - 1] = fcm; HST[HN - 1] = lstep != lsd; lsd = lstep; palm(76, 178, 82, 0x000000, 0.8); gi = 0; loop(4, gf_ = gi == 0 ? 100 : gi == 1 ? 1000 : gi == 2 ? 10000 : 50; gyy = 174 - log(gf_ / 25) / log(720) * 108; ui_cola(0xFF4030, 0.14); gfx_rect(22 * sc, gyy * sc, 336 * sc, 1 * sc); gi += 1; ); txt(40, 164 - log(100 / 25) / log(720) * 108, "100", 0.35); txt(40, 164 - log(1000 / 25) / log(720) * 108, "1k", 0.35); txt(40, 164 - log(10000 / 25) / log(720) * 108, "10k", 0.35); gi = 1; loop(HN - 1, gx0 = 22 + (gi - 1) / (HN - 1) * 336; gx1 = 22 + gi / (HN - 1) * 336; gy0 = 174 - log(max(HFC[gi - 1], 25) / 25) / log(720) * 108; gy1 = 174 - log(max(HFC[gi], 25) / 25) / log(720) * 108; mode && HST[gi] ? ( ui_cola(0xFF6A4A, 0.25); gfx_rect(gx1 * sc, 62 * sc, 1 * sc, 116 * sc); ); ui_cola(0xFF5040, 0.35); gfx_line(gx0 * sc, (gy0 + 1.5) * sc, gx1 * sc, (gy1 + 1.5) * sc, 1); ui_col(0xFFB0A0); gfx_line(gx0 * sc, gy0 * sc, gx1 * sc, gy1 * sc, 1); gfx_line(gx0 * sc, (gy0 - 0.8) * sc, gx1 * sc, (gy1 - 0.8) * sc, 1); gi += 1; ); fcm >= 1000 ? sprintf(#v, "%.2f kHz", fcm / 1000) : sprintf(#v, "%.0f Hz", fcm); gfx_setfont(4); ui_col(0xFFB0A0); gfx_x = 300 * sc; gfx_y = 66 * sc; gfx_drawstr(#v); envd = max(envm, envd * 0.85); envm = 0; pk_led(34 * sc, 72 * sc, 4 * sc, envd > 0.08, 0xFF3A2A); gfx_setfont(4); ui_cola(0xFFB0A0, 0.8); gfx_x = 42 * sc; gfx_y = 67 * sc; gfx_drawstr("ENV"); // ---------- the split block: UP (blue) / DOWN (red), DEPTH and FREQ ---------- ui_col(slider6 ? SKYB : ui_mix(SKYB, BLUD, 0.55)); gfx_rect(376 * sc, 58 * sc, 118 * sc, 124 * sc); ui_col(!slider6 ? REDP : ui_mix(REDP, BLUD, 0.55)); gfx_rect(496 * sc, 58 * sc, 118 * sc, 124 * sc); ui_col(0x0A0A12); gfx_triangle(388 * sc, 78 * sc, 402 * sc, 78 * sc, 395 * sc, 66 * sc); gfx_triangle(588 * sc, 66 * sc, 602 * sc, 66 * sc, 595 * sc, 78 * sc); pressed && drag_id == 0 && mouse_y >= 58 * sc && mouse_y < 90 * sc ? ( mouse_x >= 376 * sc && mouse_x < 416 * sc ? ( slider6 = 1; ui_auto(6); drag_id = -1; ); mouse_x >= 574 * sc && mouse_x < 614 * sc ? ( slider6 = 0; ui_auto(6); drag_id = -1; ); ); sprintf(#v, "%.1f oct", slider4); dy_ink = 0x0A0A12; dy_knob(435, 118, 22, 4, 0, 6, 3.5, 0, WHT, "DEPTH", #v); slider3 >= 1000 ? sprintf(#v, "%.2f kHz", slider3 / 1000) : sprintf(#v, "%.0f Hz", slider3); dy_knob(555, 118, 22, 3, 60, 3000, 250, 1, WHT, "FREQ", #v); dy_ink = WHT; // ---------- right: filter type, three slide switches ---------- dy_step = 4; dy_steps = "LP|BP|HP|N"; dy_knob(668, 124, 18, 2, 0, 3, 1, 0, WHT, "FILTER", ""); gs_ = slide(732, 76, 140, 2, slider7, 0x3A70E8, "", "RANGE LO / HI"); gs_ != slider7 ? ( slider7 = gs_; ui_auto(7); ); gs_ = slide(732, 116, 140, 2, slider13, 0xF2F4FA, "", "PATTERN FREE / LOOP"); gs_ != slider13 ? ( slider13 = gs_; ui_auto(13); ); gs_ = slide(732, 156, 140, 3, slider1, 0xE0402E, "", "ENV / S&H / BOTH"); gs_ != slider1 ? ( slider1 = gs_; ui_auto(1); ); // ---------- knob row ---------- ui_cola(WHT, 0.18); gfx_rect(18 * sc, 192 * sc, 864 * sc, 1 * sc); sprintf(#v, "%.1f", slider5); dy_knob(52, 236, 16, 5, 0.5, 15, 4, 1, WHT, "PEAK", #v); sprintf(#v, "%.0f%%", slider8); dy_knob(132, 236, 16, 8, 0, 100, 60, 0, WHT, "SENS", #v); sprintf(#v, "%.0f%%", slider9); dy_knob(212, 236, 16, 9, 0, 100, 40, 0, WHT, "RESPONSE", #v); ui_cola(WHT, 0.18); gfx_rect(260 * sc, 200 * sc, 1 * sc, 82 * sc); dy_step = 5; dy_steps = "1/2|1/4|1/8|1/16|1/32"; dy_knob(312, 236, 16, 10, 0, 4, 2, 0, WHT, "RATE", ""); gi = 0; loop(3, gx_ = 384 + gi * 26; ui_col(slider11 == gi ? WHT : BLUD); gfx_circle(gx_ * sc, 230 * sc, 10 * sc, 1, 1); ui_col(WHT); gfx_circle(gx_ * sc, 230 * sc, 10 * sc, 0, 1); gfx_setfont(6, "Arial", 11 * sc, 'b'); ui_col(slider11 == gi ? BLU : WHT); ui_text(gx_ * sc, 224 * sc, gi == 0 ? "1" : gi == 1 ? "2" : "4"); pressed && drag_id == 0 && (mouse_x - gx_ * sc) ^ 2 + (mouse_y - 230 * sc) ^ 2 < (11 * sc) ^ 2 ? ( slider11 = gi; ui_auto(11); drag_id = -1; ); gi += 1; ); gfx_setfont(5); ui_col(WHT); ui_text(410 * sc, 248 * sc, "MULT"); sprintf(#v, "%.0f%%", slider12); dy_knob(482, 236, 16, 12, 0, 100, 15, 0, WHT, "GLIDE", #v); ui_cola(WHT, 0.18); gfx_rect(530 * sc, 200 * sc, 1 * sc, 82 * sc); sprintf(#v, "%.0f%%", slider14); dy_knob(582, 236, 16, 14, 0, 100, 20, 0, WHT, "DRIVE", #v); sprintf(#v, "%.0f%%", slider15); dy_knob(662, 236, 16, 15, 0, 100, 100, 0, WHT, "MIX", #v); sprintf(#v, "%+.1f dB", slider16); dy_knob(742, 236, 16, 16, -12, 12, 0, 0, WHT, "OUTPUT", #v); starfish(830, 236, 30, 0.25); star(866, 206, 6, WHT); star(800, 204, 5, SKYB); // ---------- IN / OUT band ---------- ui_cola(WHT, 0.3); gfx_rect(14 * sc, 294 * sc, 872 * sc, 1 * sc); gfx_setfont(4); ui_cola(WHT, 0.8); gfx_x = 30 * sc; gfx_y = 324 * sc; gfx_drawstr("IN / OUT"); dy_ink = WHT; dy_bg = BLU; dy_nov = 1; rd_iok = 20; rd_ioc1 = 0x1C2440; rd_ioc2 = 0xF2C21B; rd_ioc3 = 0xFF5A3A; rd_io(96, 302, 19, 20, 21, 26); dy_nov = 0; pk_end(); ui_end();