desc:GFX Flanger //tags: flanger modulation jet through-zero bbd envelope //author: JGWizrad / Garden FX (GFX) // // Requires gfx-drift, gfx-lfo, gfx-input, gfx-output, gfx-ui, gfx-panel, gfx-dyn, gfx-faceplate and gfx-instrument (.jsfx-inc) in the same folder. // // Three flangers in one, from the jet-plane pedals to the studio racks and the real tape trick // (personal use; the sound is designed from scratch). // PEDAL - the bucket-brigade pedal: a darker, slightly gritty loop (the delay chips' top end and noise), // sweep from about 0.3 to 6 ms, strong REGEN for the jet sound. // RACK - the wide-sweep studio rack: clean, from very short to very long delays (0.15 - 14 ms), so it // can go from metallic flange to a slow, chorus-like sweep. // THRU-0 - through-zero flanging, as done with two tape machines: the dry path is delayed too, and the swept // copy passes right through it - the deep "zero" cancellation as it crosses. // SWEEP LFO - the usual sweep: shape, FREE / SYNC / FLOW rate. // MATRIX - the "filter matrix" trick: the sweep stops and MANUAL places the comb by hand. // ENVELOPE - your playing drives the sweep: louder = further (SENS sets how far). // MANUAL - where the sweep sits (the delay time). WIDTH - how far it sweeps. REGEN - feedback: positive for // the ringing, metallic jet; negative for the hollow, nasal tone. SPREAD - the right side's sweep // offset from the left (0 = classic mono flange, 90 - 180 = wide stereo motion). // DRIFT - slow random wander of the rate, width and manual (a hand on the tape, an old clock). // IN / OUT: TRIM (with the GUARD key), SAT and the OUT stage (OFF / CLIP / LIM) sit on the panel. // LOW CUT (MASTER) - a high-pass on the effected signal only (20 = off): the bass stays dry, clean and centred. import gfx-drift.jsfx-inc import gfx-lfo.jsfx-inc import gfx-input.jsfx-inc import gfx-output.jsfx-inc import gfx-ui.jsfx-inc import gfx-panel.jsfx-inc import gfx-dyn.jsfx-inc import gfx-faceplate.jsfx-inc import gfx-instrument.jsfx-inc slider1:0<0,2,1{Pedal,Rack,Thru-zero}>-Mode slider2:1<0,3,1{Sine,Triangle,Square,Random}>-Shape slider3:0<0,2,1{Free,Sync,Flow}>-Rate mode slider4:0.25<0.02,10,0.01>-Free rate (Hz) slider5:2<0,15,1{4 bars,2 bars,1 bar,1/2,1/2 D,1/2 T,1/4,1/4 D,1/4 T,1/8,1/8 D,1/8 T,1/16,1/16 D,1/16 T,1/32}>-Sync rate slider6:40<0,100,1>-Manual (%) slider7:70<0,100,1>-Width (%) slider8:50<-95,95,1>-Regen (%) slider9:0<0,180,1>-Spread (deg) slider10:50<0,100,1>-Mix (%) slider11:0<0,2,1{LFO,Matrix,Envelope}>-Sweep slider12:50<0,100,1>-Envelope sens (%) slider13:5<0,50,1>-Rate drift (%) slider14:10<0,50,1>-Width drift (%) slider15:5<0,50,1>-Manual drift (%) slider16:0.25<0.02,2,0.01>-Drift speed (Hz) slider17:0<-24,12,0.1>-Output (dB) slider18:0<0,100,1>-Band sat (%) slider19:30<0,100,1>-Bias (%) slider20:120<40,400,1>-Sat low band (Hz) slider21:6000<2000,16000,10>-Sat high band (Hz) slider22:-0.3<-24,0,0.1>-Ceiling / limit threshold (dB) slider23:1<0,2,1{Off,Clip,Limit}>-Output stage slider24:0<-24,12,0.1>-Input trim (dB) slider25:1<0,1,1{Off,On}>-Input guard slider26:20<20,500,1>-Wet low cut (Hz, 20 = off) slider27:50<0,100,1>-Drift (%) in_pin:left input in_pin:right input out_pin:left output out_pin:right output @init #ui_man = "gfx-flanger"; // the ? pop-up links to this manual // clean below -3 dBFS, rounds off peaks above (keeps high regen from running away) function sat(x) local(a) ( a = abs(x); a < 0.7 ? x : sign(x) * (0.7 + 0.3 * lfo_tanh((a - 0.7) / 0.3)); ); // fractional delay read, 4-point Hermite function dread(buf, d) local(rp, i, f, xm1, x0, x1, x2) ( rp = wp - d; rp < 0 ? rp += tsize; i = floor(rp); f = rp - i; xm1 = buf[(i + tsize - 1) & tmask]; x0 = buf[i & tmask]; x1 = buf[(i + 1) & tmask]; x2 = buf[(i + 2) & tmask]; ((((0.5 * (x2 - xm1) + 1.5 * (x0 - x1)) * f + (xm1 - 2.5 * x0 + 2 * x1 - 0.5 * x2)) * f + 0.5 * (x1 - xm1)) * f + x0); ); // delay (ms) for a sweep position u (-1 .. 1) around the manual setting, per mode function del_ms(man, wid, u) local(lo, hi, c, d) ( mode == 2 ? ( c = 0.25 + man * 4.75; // thru-zero: the dry path sits at c ms ... max(c * (1 + 1.25 * wid * u), 0.02); // ... and the swept copy passes through it ) : ( lo = mode ? 0.15 : 0.3; hi = mode ? 14 : 6; c = lo * (hi / lo) ^ man; // MANUAL: log between the mode's limits d = c * 2 ^ (wid * u * (mode ? 3.2 : 2.2)); // WIDTH: octaves of sweep either side min(max(d, lo * 0.5), hi * 1.3); ); ); // LOW CUT: a 12 dB/oct high-pass on the wet signal only function wlc(x) instance(x1, x2, y1, y2) local(y) ( y = wl_b0 * (x - 2 * x1 + x2) - wl_a1 * y1 - wl_a2 * y2; x2 = x1; x1 = x; y2 = y1; y1 = y; y; ); function wlc_set(f) local(w0, al, n) ( w0 = 2 * $pi * min(f, srate * 0.45) / srate; al = sin(w0) / (2 * 0.7071); n = 1 + al; wl_b0 = (1 + cos(w0)) * 0.5 / n; wl_a1 = -2 * cos(w0) / n; wl_a2 = (1 - al) / n; ); function update() ( wl_on = slider26 > 20.5; wl_on ? wlc_set(slider26); mode = slider1; shape = slider2; syncmode = slider3; frate = slider4; div = floor(slider5 + 0.5); man_t = slider6 / 100; wid_t = slider7 / 100; fb_t = slider8 / 100; spread = slider9 / 360; mix_t = slider10 / 100; sweep = slider11; sens = slider12 / 100; drift_macro(slider27); // DRIFT dial: 50% = the drift settings, 100% = twice, 0 = none rd = slider13 / 100 * dm_a; wd = min(slider14 / 100 * dm_a, 1); md = slider15 / 100 * dm_a; dspd = slider16 * dm_s; out_t = 10 ^ (slider17 / 20); in_setup(slider24, slider25); ost_setup(slider18 / 100, slider19 / 100, slider20, slider21, slider22, slider23); lfoL.lfo_setup(shape, 0.2); lfoR.lfo_setup(shape, 0.2); lpc = 1 - exp(-2 * $pi * min(mode == 0 ? 6500 : 15000, srate * 0.45) / srate); // PEDAL: the BBD's darker loop ); // ---------- presets (leave drift speed, output and the I/O rows alone) ---------- // mode, shape, rate mode, rate, sync div, manual, width, regen, spread, mix, sweep, sens function setp(m, sh, sy, fr, dv, mn, wi, rg, sp, mx, sw, se) ( slider1 = m; slider2 = sh; slider3 = sy; slider4 = fr; slider5 = dv; slider6 = mn; slider7 = wi; slider8 = rg; slider9 = sp; slider10 = mx; slider11 = sw; slider12 = se; ); function pname(p) ( p == 1 ? "Classic Pedal" : p == 2 ? "Jet Plane" : p == 3 ? "Negative Hollow" : p == 4 ? "Stereo Pedal" : p == 5 ? "Rack Wide Sweep" : p == 6 ? "Rack Chorus-Flange" : p == 7 ? "Thru-Zero Tape" : p == 8 ? "Thru-Zero Jet" : p == 9 ? "Filter Matrix" : p == 10 ? "Envelope Swoosh" : p == 11 ? "Synced 1/2 Bar" : "Reset all to defaults"; ); function load_preset(p) ( p == 1 ? setp(0, 1, 0, 0.25, 2, 40, 70, 50, 0, 50, 0, 50) : // Classic Pedal p == 2 ? setp(0, 1, 0, 0.1, 2, 35, 85, 85, 0, 50, 0, 50) : // Jet Plane p == 3 ? setp(0, 0, 0, 0.3, 2, 45, 60, -70, 0, 50, 0, 50) : // Negative Hollow p == 4 ? setp(0, 1, 0, 0.2, 2, 30, 70, 40, 90, 50, 0, 50) : // Stereo Pedal p == 5 ? setp(1, 0, 0, 0.12, 2, 45, 100, 40, 90, 50, 0, 50) : // Rack Wide Sweep p == 6 ? setp(1, 0, 0, 0.8, 2, 75, 25, 15, 120, 40, 0, 50) : // Rack Chorus-Flange p == 7 ? setp(2, 0, 0, 0.12, 2, 40, 80, 0, 0, 50, 0, 50) : // Thru-Zero Tape p == 8 ? setp(2, 1, 0, 0.08, 2, 30, 90, 60, 30, 50, 0, 50) : // Thru-Zero Jet p == 9 ? setp(0, 1, 0, 0.25, 2, 30, 70, 80, 0, 50, 1, 50) : // Filter Matrix p == 10 ? setp(0, 1, 0, 0.25, 2, 20, 80, 60, 0, 50, 2, 70) : // Envelope Swoosh p == 11 ? setp(1, 1, 1, 0.25, 3, 40, 70, 55, 60, 50, 0, 50); // Synced 1/2 Bar p >= 1 && p <= 11 ? slider_automate(4095); // sliders 1-12 p == 12 ? ( // Reset all to defaults setp(0, 1, 0, 0.25, 2, 40, 70, 50, 0, 50, 0, 50); slider13 = 5; slider14 = 10; slider15 = 5; slider16 = 0.25; slider17 = 0; slider18 = 0; slider19 = 30; slider20 = 120; slider21 = 6000; slider22 = -0.3; slider23 = 1; slider24 = 0; slider25 = 1; slider26 = 20; slider27 = 50; slider_automate(134217727); ); ); // ---------- memory ---------- tsize = 32768; tmask = tsize - 1; fbL_b = 1024; fbR_b = fbL_b + tsize; // flange lines (with regen) cbL = fbR_b + tsize; cbR = cbL + tsize; // clean lines (the delayed dry path for THRU-0) memset(0, 0, cbR + tsize); wp = 0; // ---------- state ---------- sm = 1 - exp(-1 / (0.03 * srate)); dsm = 1 - exp(-1 / (0.004 * srate)); // delay-time smoothing (no zipper on MANUAL moves) env_a = 1 - exp(-1 / (0.005 * srate)); env_r = 1 - exp(-1 / (0.18 * srate)); lfoL.lfo_init(); lfoR.lfo_init(); drR.drift_init(0.8 + rand(0.5)); drW.drift_init(0.8 + rand(0.5)); drM.drift_init(0.8 + rand(0.5)); ost_init(140000); ostL.ost_ch_init(); ostR.ost_ch_init(); // clear of the four delay lines (1024 - 132096) in_init(); vuc = 1 - exp(-1 / (0.01 * srate)); vu_ms = 0; !ui_dflt ? ui_thm = 14; !ui_dflt ? ui_hw = 1; // defaults for new instances: Slate, hardware (saved projects keep their own) pkL = 0; pkR = 0; cur_preset = 1; update(); man_s = man_t; wid_s = wid_t; fb_s = fb_t; mix_s = mix_t; out_s = out_t; dL_s = del_ms(man_t, 0, 0) * srate / 1000; dR_s = dL_s; 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(); lfoL.lfo_block(syncmode, div, frate); lfoR.lfo_block(syncmode, div, frate); @serialize file_var(0, ui_thm); file_var(0, ui_sz); file_var(0, ui_hw); file_avail(0) != 0 ? file_var(0, pr_cur); // the preset in use (older projects end before it) @sample // input stage: DC block, trim, guard in_process(spl0, spl1); inL = in_l; inR = in_r; vu_ms += (0.5 * (inL * inL + inR * inR) - vu_ms) * vuc; // drift dinc = dspd / srate; vR = drR.drift_tick(dinc); vW = drW.drift_tick(dinc); vM = drM.drift_tick(dinc); // smoothing man_s += (man_t - man_s) * sm; wid_s += (wid_t - wid_s) * sm; fb_s += (fb_t - fb_s) * sm; mix_s += (mix_t - mix_s) * sm; out_s += (out_t - out_s) * sm; // the sweep: LFO, frozen (MATRIX) or the input's envelope (ENVELOPE) lvL = lfoL.lfo_tick(0, rd, vR); lvR = lfoR.lfo_tick(spread, rd, vR); lv = max(abs(inL), abs(inR)); env += (lv - env) * (lv > env ? env_a : env_r); sweep == 1 ? ( uL = 0; uR = 0; ) : sweep == 2 ? ( uL = min(env * (1 + 12 * sens), 1) * 2 - 1; uR = uL; ) : ( uL = lvL; uR = lvR; ); mn = min(max(man_s + md * 0.25 * vM, 0), 1); wi = wid_s * (1 - wd * (0.5 + 0.5 * vW)); sweep == 1 ? wi = 0; dL_s += (del_ms(mn, wi, uL) * srate / 1000 - dL_s) * dsm; dR_s += (del_ms(mn, wi, uR) * srate / 1000 - dR_s) * dsm; dL = max(dL_s, 1); dR = max(dR_s, 1); // the flange lines: write input + regen, read the swept tap fbL_b[wp] = inL + fb_s * fL; fbR_b[wp] = inR + fb_s * fR; cbL[wp] = inL; cbR[wp] = inR; wL = dread(fbL_b, dL); wR = dread(fbR_b, dR); lpL += (wL - lpL) * lpc; lpR += (wR - lpR) * lpc; // loop tone (PEDAL darker) mode == 0 ? ( lpL += (rand(2) - 1) * 0.00002; lpR += (rand(2) - 1) * 0.00002; ); // the delay chips' faint hiss fL = sat(lpL); fR = sat(lpR); // dry path: straight, or delayed to the sweep's centre in THRU-0 so the copy can cross it mode == 2 ? ( dc = (0.25 + mn * 4.75) * srate / 1000; xL = dread(cbL, dc); xR = dread(cbR, dc); ) : ( xL = inL; xR = inR; ); fbc = fb_s > 0 ? 1 / (1 + 1.2 * fb_s * fb_s) : 1 / (1 + 0.2 * fb_s * fb_s); // level compensation for strong regen oL = wl_on ? xL + mix_s * (WLL.wlc(lpL * fbc) - WDL.wlc(xL)) : (1 - mix_s) * xL + mix_s * lpL * fbc; // LOW CUT: the lows stay dry at full level oR = wl_on ? xR + mix_s * (WLR.wlc(lpR * fbc) - WDR.wlc(xR)) : (1 - mix_s) * xR + mix_s * lpR * fbc; // LOW CUT: the lows stay dry at full level wp = (wp + 1) & tmask; // output stage: band saturation -> output gain -> clipper / limiter oL = ostL.ost_band(oL) * in_comp * out_s; oR = ostR.ost_band(oR) * in_comp * out_s; ost_out(oL, oR); spl0 = ost_l; spl1 = ost_r; pkL = max(pkL, abs(spl0)); pkR = max(pkR, abs(spl1)); dispMd = dL / srate * 1000; dispFb = fb_s; dispMix = mix_s; dispFbc = fbc; dispDry = mode == 2 ? (0.25 + mn * 4.75) : 0; @gfx 1060 320 ui_begin(1060, 320); // ---------- DRAFT A: 80s studio rack flanger - dove-grey painted face, blue print, red LED readout ---------- FACE = 0xC4C6C3; INK = 0x22262C; BLU = 0x2B5CA8; DIMI = 0x5A6068; SILV = 0xB9BDC2; dy_ink = INK; dy_bg = FACE; function setv(idx, v) ( slider(idx) = v; ui_auto(idx); ); // printed section title: a short blue bar and blue caps function fa_sect(x, y, s) ( ui_col(BLU); gfx_rect(x * sc, (y + 2) * sc, 3 * sc, 9 * sc); rd_sub(x + 7, y, s, BLU, 1); ); // sweep position 0..1: where the delay sits inside the mode's travel function fa_pos() local(lo, hi) ( slider1 == 2 ? ( dispDry > 0 ? 0.5 + 0.5 * (dispMd / dispDry - 1) / 1.25 : 0.5; ) : ( lo = slider1 ? 0.15 : 0.3; hi = slider1 ? 14 : 6; log(max(dispMd, lo * 0.5) / (lo * 0.5)) / log(hi * 1.3 / (lo * 0.5)); ); ); // ---------- chassis ---------- ui_col(0x0A0A0B); gfx_rect(0, 0, gfx_w, gfx_h); rd_plate(0, 0, 1060, 320, FACE, 0); ui_cola(0x000000, 0.35); gfx_rect(0, 0, 1060 * sc, 1.5 * sc); gfx_rect(0, 318 * sc, 1060 * sc, 2 * sc); // blue print stripes ui_col(BLU); gfx_rect(44 * sc, 58 * sc, 972 * sc, 3 * sc); gfx_rect(44 * sc, 306 * sc, 972 * sc, 1.5 * sc); // ---------- header ---------- rd_badge(60, 32, 15, BLU, FACE); rd_title(84, 14, "FLANGER", 28, INK); rd_sub(256, 30, "STEREO FLANGER ยท THRU-ZERO", BLU, 1); pk_pextra = "Reset all to defaults"; // the house preset display: PRESETS, prev / next, LCD (click it for the list) k_ = pk_preset(640 * sc, 16 * sc, 290 * sc, 34 * sc, pr_cur, "Classic Pedal|Jet Plane|Negative Hollow|Stereo Pedal|Rack Wide Sweep|Rack Chorus-Flange|Thru-Zero Tape|Thru-Zero Jet|Filter Matrix|Envelope Swoosh|Synced 1/2 Bar"); k_ > 0 ? ( load_preset(k_); pr_cur = k_ > 11 ? 0 : k_; ); ui_size_picker(940 * sc, 21 * sc); // ---------- delay readout + sweep bar graph ---------- fa_sect(44, 68, "DELAY"); ui_col(0x5C5F63); gfx_rect(44 * sc, 84 * sc, 246 * sc, 82 * sc); ui_col(0x0C0607); gfx_rect(46 * sc, 86 * sc, 242 * sc, 78 * sc); gfx_gradrect(46 * sc, 86 * sc, 242 * sc, 30 * sc, 1, 1, 1, 0.06, 0, 0, 0, 0, 0, 0, 0, -0.06 / (30 * sc)); dispMd < 10 ? sprintf(#fa_ms, "%.2f", dispMd) : sprintf(#fa_ms, "%.1f", dispMd); rd_seg(62, 96, 26, 42, 4, #fa_ms, 0xFF2A1A, 0x1C0604); rd_lbl(222, 124, "ms", 0xFF4A30, 0.9); rd_lbl(256, 96, slider1 == 0 ? "BBD" : slider1 == 1 ? "RACK" : "TAPE", 0xFF4A30, 0.55); rd_lbl(256, 112, slider11 == 1 ? "HOLD" : slider11 == 2 ? "ENV" : "LFO", 0xFF4A30, 0.55); fa_p = min(max(fa_pos(), 0), 1); fa_k = 0; loop(12, fa_c = fa_k < 7 ? 0x3AE060 : fa_k < 10 ? 0xFFC020 : 0xFF3020; fa_on = fa_k <= floor(fa_p * 11.99); ui_col(fa_on ? fa_c : ui_mix(fa_c, 0x0C0607, 0.8)); gfx_rect((62 + fa_k * 18) * sc, 150 * sc, 13 * sc, 6 * sc); fa_on && fa_k == floor(fa_p * 11.99) ? ( ui_cola(fa_c, 0.3); gfx_rect((60 + fa_k * 18) * sc, 148 * sc, 17 * sc, 10 * sc); ); fa_k += 1; ); rd_sub(62, 170, "SHORT", DIMI, 1); rd_sub(244, 170, "LONG", DIMI, 1); rd_lbl(167, 172, "SWEEP POSITION", DIMI, 1); // ---------- MODE / SWEEP keys ---------- rd_sq(44, 194, 76, 24, slider1 == 0, 0x4A8FE8, "PEDAL") ? setv(1, 0); rd_sq(129, 194, 76, 24, slider1 == 1, 0x4A8FE8, "RACK") ? setv(1, 1); rd_sq(214, 194, 76, 24, slider1 == 2, 0x4A8FE8, "THRU-0") ? setv(1, 2); rd_lbl(167, 222, "MODE", INK, 1); rd_sq(44, 248, 76, 24, slider11 == 0, 0xF0A830, "LFO") ? setv(11, 0); rd_sq(129, 248, 76, 24, slider11 == 1, 0xF0A830, "MATRIX") ? setv(11, 1); rd_sq(214, 248, 76, 24, slider11 == 2, 0xF0A830, "ENVELOPE") ? setv(11, 2); rd_lbl(167, 276, "SWEEP", INK, 1); ui_cola(INK, 0.2); gfx_rect(306 * sc, 72 * sc, 1 * sc, 226 * sc); gfx_rect(870 * sc, 72 * sc, 1 * sc, 226 * sc); // ---------- LFO ---------- fa_sect(322, 68, "LFO"); rd_sq(322, 90, 34, 20, slider2 == 0, 0xF2F0E6, "SIN") ? setv(2, 0); rd_sq(360, 90, 34, 20, slider2 == 1, 0xF2F0E6, "TRI") ? setv(2, 1); rd_sq(398, 90, 34, 20, slider2 == 2, 0xF2F0E6, "SQR") ? setv(2, 2); rd_sq(436, 90, 34, 20, slider2 == 3, 0xF2F0E6, "RND") ? setv(2, 3); rd_lbl(396, 114, "SHAPE", INK, 1); rd_sq(322, 140, 46, 20, slider3 == 0, 0xF2F0E6, "FREE") ? setv(3, 0); rd_sq(373, 140, 46, 20, slider3 == 1, 0xF2F0E6, "SYNC") ? setv(3, 1); rd_sq(424, 140, 46, 20, slider3 == 2, 0xF2F0E6, "FLOW") ? setv(3, 2); rd_lbl(396, 164, "RATE MODE", INK, 1); rd_led(518, 84, 3.5, slider11 == 0 && lvL > 0, 0xFF3020); // ---------- the flange knobs ---------- dy_kst = 7; slider3 == 1 ? ( dy_step = 16; dy_steps = ""; dy_knob(518, 128, 22, 5, 0, 15, 2, 0, SILV, "RATE", lfo_div_name(floor(slider5 + 0.5))); ) : ( sprintf(#v, "%.2f Hz", slider4); dy_knob(518, 128, 22, 4, 0.02, 10, 0.25, 1, SILV, "RATE", slider11 == 1 ? "stopped" : #v); ); fa_sect(566, 68, "FLANGE"); sprintf(#v, "%.0f%%", slider6); dy_knob(604, 128, 30, 6, 0, 100, 40, 0, 0x3A72C8, "MANUAL", #v); sprintf(#v, "%.0f%%", slider7); dy_knob(688, 128, 22, 7, 0, 100, 70, 0, SILV, "WIDTH", slider11 == 1 ? "n/a" : #v); sprintf(#v, "%+.0f%%", slider8); dy_knob(762, 128, 22, 8, -95, 95, 50, 0, SILV, "REGEN", #v); sprintf(#v, "%.0f deg", slider9); dy_knob(834, 128, 22, 9, 0, 180, 0, 0, SILV, "SPREAD", #v); // ---------- lower row: envelope sens, drift, in / out ---------- ui_cola(INK, 0.2); gfx_rect(322 * sc, 206 * sc, 532 * sc, 1 * sc); fa_sect(322, 214, "ENV"); dy_nov = 1; // ENV, DRIFT and IN / OUT show their value only while touched sprintf(#v, "%.0f%%", slider12); dy_knob(340, 254, 13, 12, 0, 100, 50, 0, 0xF0A830, "SENS", #v); fa_sect(388, 214, "DRIFT"); sprintf(#v, "%.0f%%", slider27); dy_knob(494, 252, 16, 27, 0, 100, 50, 0, SILV, "DRIFT", #v); fa_sect(630, 214, "IN / OUT"); rd_ioc1 = 0x2A2A2E; rd_ioc2 = SILV; rd_ioc3 = 0xC83A2A; rd_io(632, 232, 24, 25, 18, 23); dy_nov = 0; // ---------- master ---------- fa_sect(882, 68, "MASTER"); dy_kst = 7; sprintf(#v, "%.0f%%", slider10); dy_knob(910, 116, 18, 10, 0, 100, 50, 0, 0x3A72C8, "MIX", #v); slider26 <= 20.5 ? strcpy(#v, "off") : sprintf(#v, "%.0f Hz", slider26); dy_kf = 1; dy_knob(982, 116, 14, 26, 20, 500, 20, 1, 0, "LOW CUT", #v); sprintf(#v, "%+.1f dB", slider17); dy_knob(910, 236, 18, 17, -24, 12, 0, 0, SILV, "OUTPUT", #v); ui_col(0x1A1B1E); gfx_rect(962 * sc, 194 * sc, 34 * sc, 72 * sc); mL.ui_ledm(966 * sc, 198 * sc, 12 * sc, 64 * sc, pkL); mR.ui_ledm(980 * sc, 198 * sc, 12 * sc, 64 * sc, pkR); pkL *= 0.85; pkR *= 0.85; rd_lbl(979, 272, "OUT", INK, 1); pk_end(); ui_end();