desc:GFX G Deep 16 //tags: instrument drum machine synth kick snare clap deep house sequencer //author: JGWizrad / Garden FX (GFX) // // Requires gfx-ui and gfx-panel (.jsfx-inc) in the same folder. // // Fully synthesized deep house drum machine (no samples): a KICK and a SNARE / CLAP voice, then a drum-bus // chain: VCA COMPRESSOR > 3-BAND EQ > SATURATION > REVERB > MASTER. // // MIDI: note 36 (C1) kick, 38 (D1) snare, 40 (E1) clap (the snare voice with clap-style noise bursts and // less tone), 42 / 44 closed hat, 46 open hat (a closed hat chokes it), 37 rim shot. Velocity scales the level (and the kick's decay). Triggering is sample-accurate. // KICK: a sine with an exponential pitch drop (BASE + DROP falling with PITCH DECAY), exponential amp decay // (longer for harder hits), a transient CLICK burst and SUB DRIVE (tanh, strongest at the start). // SNARE / CLAP: a tonal body (sine with a fast pitch drop) + band-passed noise, each with its own envelope; // WIDTH delays the noise on the right channel by a few ms (the house "wide clap"). // HATS: six square-wave oscillators at inharmonic ratios (the classic analogue metal) blended with noise, // through a band-pass + high-pass at TONE; closed and open share the source, each with its own decay. // RIM: two short pitched pings and a click. // COMPRESSOR: feed-forward, stereo-linked peak detector, gain computed in dB, exponential attack / release // on the gain reduction, makeup gain. // EQ: low shelf, bell and high shelf (RBJ biquads, Direct Form II Transposed). // SATURATION: TAPE (tanh), TUBE (asymmetric, even harmonics, DC blocked), SOFT-CLIP (cubic); dry / wet blend. // REVERB: Schroeder / Freeverb style - 4 parallel damped combs into 2 series all-passes per channel, a // low-cut on the input so the kick does not muddy the tail, wet level in dB. // SEQUENCER (always on the panel: the steps in the voice matrix, SEQUENCER below): 16 steps x kick / snare / clap, click a step for off / // hit / accent; plays in time with Reaper's transport; SWING; factory grooves. // EXPORT MIDI: puts the pattern (repeated for BARS) into shared memory; the companion ReaScript // "GFX G-Deep - export MIDI.lua" (in the Scripts folder) turns it into a MIDI item at the edit cursor // on the track that holds G-Deep. Run the script once and it keeps listening for EXPORT presses, or // press EXPORT and then run the script. options:gmem=GFX_GDeep import gfx-ui.jsfx-inc import gfx-panel.jsfx-inc import gfx-drum.jsfx-inc // ---------- KICK VOICE ---------- slider1:48<30,120,0.1>-Kick base pitch (Hz) slider2:180<0,600,1>-Kick pitch drop depth (Hz) slider3:35<2,200,0.1>-Kick pitch decay (ms) slider4:420<50,2000,1>-Kick amp decay (ms) slider5:0.35<0,1,0.01>-Kick click level slider6:25<0,100,1>-Kick sub tone drive (%) slider7:0<-24,6,0.1>-Kick level (dB) // ---------- SNARE / CLAP VOICE ---------- slider8:185<100,400,0.1>-Snare tone pitch (Hz) slider9:80<10,500,1>-Snare tone decay (ms) slider10:2200<500,10000,1>-Snare noise cutoff (Hz) slider11:1.2<0.5,8,0.01>-Snare noise resonance (Q) slider12:210<20,800,1>-Snare noise decay (ms) slider13:12<0,30,0.1>-Snare stereo micro-delay / width (ms) slider14:-3<-24,6,0.1>-Snare level (dB) slider15:40<0,100,1>-Snare tone / noise mix (% tone) // ---------- MODULE 1 - COMPRESSOR ---------- slider16:1<0,1,1{Off,On}>-Comp on slider17:-14<-40,0,0.1>-Comp threshold (dB) slider18:4<1,20,0.1>-Comp ratio (x:1) slider19:8<0.1,100,0.1>-Comp attack (ms) slider20:120<10,1000,1>-Comp release (ms) slider21:0.3<-12,24,0.1>-Comp makeup gain (dB) // ---------- MODULE 2 - 3-BAND EQ ---------- slider22:1<0,1,1{Off,On}>-EQ on slider23:80<30,300,1>-EQ low shelf freq (Hz) slider24:2<-15,15,0.1>-EQ low shelf gain (dB) slider25:500<150,5000,1>-EQ mid bell freq (Hz) slider26:1<0.3,6,0.01>-EQ mid bell Q slider27:-2<-15,15,0.1>-EQ mid bell gain (dB) slider28:10000<2000,16000,10>-EQ high shelf freq (Hz) slider29:2<-15,15,0.1>-EQ high shelf gain (dB) // ---------- MODULE 3 - SATURATION ---------- slider30:1<0,1,1{Off,On}>-Saturation on slider31:6<0,24,0.1>-Saturation drive (dB) slider32:0<0,2,1{Tape,Tube,Soft-Clip}>-Saturation type slider33:50<0,100,1>-Saturation dry / wet (%) // ---------- MODULE 4 - REVERB ---------- slider34:1<0,1,1{Off,On}>-Reverb on slider35:0.35<0,1,0.01>-Reverb room size slider36:5000<1000,12000,10>-Reverb damping cutoff (Hz) slider37:0.45<0,1,0.01>-Reverb decay slider38:250<50,1000,1>-Reverb low-cut (Hz) slider39:-18<-60,0,0.1>-Reverb wet level (dB) // ---------- MASTER ---------- slider40:0<-24,12,0.1>-Master output volume (dB) slider41:0<0,16,1>-MIDI channel (0 = omni) // ---------- SEQUENCER ---------- slider42:0<0,1,1{Off,On}>-Sequencer play (with transport) slider43:0<0,75,1>-Sequencer swing (%) slider44:0<0,3,1{1 bar,2 bars,4 bars,8 bars}>-Export length // ---------- HATS / RIM (added later: kept after the original sliders so saved projects load) ---------- slider45:0<-12,12,0.1>-Hat tune (st) slider46:9000<3000,16000,10>-Hat tone (Hz) slider47:45<10,300,1>-Closed hat decay (ms) slider48:380<50,2000,1>-Open hat decay (ms) slider49:35<0,100,1>-Hat noise (% noise vs metal) slider50:-9<-30,6,0.1>-Hat level (dB) slider51:1700<600,3500,1>-Rim pitch (Hz) slider52:25<5,120,1>-Rim decay (ms) slider53:-8<-30,6,0.1>-Rim level (dB) in_pin:none out_pin:left output out_pin:right output @init #ui_man = "gfx-g-deep"; // the ? pop-up links to this manual // ---------- memory map ---------- SEQ = 1000; MQO = 2000; MQN = 2300; MQV = 2600; // MIDI note-ons of this block (256 each) // sequencer: row * 16 + step (0 off, 1 hit, 2 accent); saved with the project SDL = 10000; SDS = 8192; // snare noise micro-delay (right channel) CMB = 20000; CMS = 8192; // reverb combs: 8 x 8192 (4 per channel) APB = 90000; APS = 4096; // reverb all-passes: 4 x 4096 (2 per channel) memset(SDL, 0, SDS); memset(CMB, 0, 8 * CMS); memset(APB, 0, 4 * APS); DEN = 0.00000000000000000001; // denormal guard added inside feedback loops // ---------- helpers ---------- function dbg(db) ( 10 ^ (db / 20); ); function coef(ms) ( exp(-1 / (max(ms, 0.01) * 0.001 * srate)); ); // one-pole decay per sample: e^(-1/(t*fs)) function dcoef(ms) ( coef(ms / 4.6); ); // a DECAY time: the level is down 40 dB after ms function tanh_(x) ( x = min(max(x, -12), 12); x = exp(2 * x); (x - 1) / (x + 1); ); // RBJ biquad, Direct Form II Transposed: y = b0 x + z1; z1 = b1 x - a1 y + z2; z2 = b2 x - a2 y // kind 0 low shelf, 1 peaking bell, 2 high shelf (S = 1 shelves) function bq_set(kind, f, q, gdb) instance(b0, b1, b2, a1, a2) local(A, w, cw, sw, al, a0, sA) ( A = 10 ^ (gdb / 40); w = 2 * $pi * min(f, srate * 0.45) / srate; cw = cos(w); sw = sin(w); kind == 1 ? ( al = sw / (2 * q); a0 = 1 + al / A; b0 = (1 + al * A) / a0; b1 = -2 * cw / a0; b2 = (1 - al * A) / a0; a1 = -2 * cw / a0; a2 = (1 - al / A) / a0; ) : ( al = sw / 2 * sqrt(2); sA = 2 * sqrt(A) * al; kind == 0 ? ( a0 = (A + 1) + (A - 1) * cw + sA; b0 = A * ((A + 1) - (A - 1) * cw + sA) / a0; b1 = 2 * A * ((A - 1) - (A + 1) * cw) / a0; b2 = A * ((A + 1) - (A - 1) * cw - sA) / a0; a1 = -2 * ((A - 1) + (A + 1) * cw) / a0; a2 = ((A + 1) + (A - 1) * cw - sA) / a0; ) : ( a0 = (A + 1) - (A - 1) * cw + sA; b0 = A * ((A + 1) + (A - 1) * cw + sA) / a0; b1 = -2 * A * ((A - 1) + (A + 1) * cw) / a0; b2 = A * ((A + 1) + (A - 1) * cw - sA) / a0; a1 = 2 * ((A - 1) - (A + 1) * cw) / a0; a2 = ((A + 1) - (A - 1) * cw - sA) / a0; ); ); ); function bq_copy(src*) instance(b0, b1, b2, a1, a2) ( b0 = src.b0; b1 = src.b1; b2 = src.b2; a1 = src.a1; a2 = src.a2; ); function bq_run(x) instance(b0, b1, b2, a1, a2, z1, z2) local(y) ( y = b0 * x + z1; z1 = b1 * x - a1 * y + z2 + DEN; z2 = b2 * x - a2 * y - DEN; y; ); // TPT state-variable filter (stable at any cutoff / Q): returns the band-pass function svf_set(f, q) instance(g, k, a1, a2, a3) ( g = tan($pi * min(f, srate * 0.45) / srate); k = 1 / q; a1 = 1 / (1 + g * (g + k)); a2 = g * a1; a3 = g * a2; ); // band-pass + high-pass blend (the hats' "air"): bp + 0.7 hp function svf_bphp(x) instance(a1, a2, a3, ic1, ic2, k) local(v1, v2, v3) ( v3 = x - ic2; v1 = a1 * ic1 + a2 * v3; v2 = ic2 + a2 * ic1 + a3 * v3; ic1 = 2 * v1 - ic1 + DEN; ic2 = 2 * v2 - ic2 - DEN; v1 + 0.7 * (x - k * v1 - v2); ); function svf_bp(x) instance(a1, a2, a3, ic1, ic2) local(v1, v2, v3) ( v3 = x - ic2; v1 = a1 * ic1 + a2 * v3; v2 = ic2 + a2 * ic1 + a3 * v3; ic1 = 2 * v1 - ic1 + DEN; ic2 = 2 * v2 - ic2 - DEN; v1; ); // ---------- voices ---------- // KICK: phase accumulator sine; f(t) = base + drop * e^(-t/tp); amp(t) = vel * e^(-t/ta) function kick_trig(vel) ( k_ph = 0; k_pe = 1; k_ae = vel; k_ce = vel; k_adk = dcoef(slider4 * (0.6 + 0.4 * vel)); // harder hits ring longer k_on = 1; ); // SNARE (clap = 0) / CLAP (clap = 1) // HATS: closed (open = 0) or open (open = 1); a closed hat chokes a ringing open hat within ~3 ms function hat_trig(vel, open) ( open ? ( h_oe = vel; h_odk = h_odk_set; ) : ( h_ce = vel; h_odk = h_choke; ); h_on = 1; ); // RIM: two pings (body and crack) plus a click function rim_trig(vel) ( r_e1 = vel; r_e2 = vel; r_ce = vel; r_ph1 = r_ph2 = 0; rim_on = 1; ); function snare_trig(vel, clap) ( s_ph = 0; s_pe = 1; s_te = vel * (clap ? 0.25 : 1); // the clap keeps a little body s_ne = vel; s_nv = vel; s_clap = clap; s_t = 0; s_on = 1; ); // ---------- parameters (recomputed in @slider, and in @block when the panel moved something) ---------- function update() ( inv_sr = 1 / srate; // (no division per sample) c_b1 = floor(0.010 * srate); c_b2 = floor(0.020 * srate); c_b3 = floor(0.030 * srate); c_bdk = coef(3.5); // kick k_base = slider1; k_drop = slider2; k_pdk = coef(slider3); k_click = slider5; k_drv = slider6 / 100; k_lvl = dbg(slider7); k_cdk = coef(2.5); // snare / clap s_f = slider8; s_tdk = dcoef(slider9); s_ndk = dcoef(slider12); s_pdk = coef(7); s_lvl = dbg(slider14); s_tmix = slider15 / 100; s_dly = min(floor(slider13 * 0.001 * srate), SDS - 1); snF.svf_set(slider10, slider11); // compressor (ballistics as one-pole coefficients) c_on = slider16; c_thr = slider17; c_slope = 1 - 1 / slider18; c_att = coef(slider19); c_rel = coef(slider20); c_mk = dbg(slider21); // EQ coefficients (both channels share them) q_on = slider22; eqLS_L.bq_set(0, slider23, 0.707, slider24); eqLS_R.bq_copy(eqLS_L); eqPK_L.bq_set(1, slider25, slider26, slider27); eqPK_R.bq_copy(eqPK_L); eqHS_L.bq_set(2, slider28, 0.707, slider29); eqHS_R.bq_copy(eqHS_L); // saturation: drive gain, a loudness compensation so ON / OFF and the drive stay level-ish t_on = slider30; t_g = dbg(slider31); t_type = slider32; t_mix = slider33 / 100; t_comp = 1 / sqrt(t_g); // reverb: comb lengths (Freeverb tunings at 44.1 kHz) scaled by size and sample rate; right side +23 r_on = slider34; r_sc = (0.35 + 0.65 * slider35) * srate / 44100; rc0 = floor(1116 * r_sc); rc1 = floor(1188 * r_sc); rc2 = floor(1277 * r_sc); rc3 = floor(1356 * r_sc); rc4 = floor((1116 + 23) * r_sc); rc5 = floor((1188 + 23) * r_sc); rc6 = floor((1277 + 23) * r_sc); rc7 = floor((1356 + 23) * r_sc); ra0 = floor(556 * srate / 44100); ra1 = floor(441 * srate / 44100); ra2 = floor((556 + 23) * srate / 44100); ra3 = floor((441 + 23) * srate / 44100); r_fb = 0.7 + 0.28 * slider37; // comb feedback 0.70 .. 0.98 r_damp = exp(-2 * $pi * slider36 / srate); // one-pole LP in each comb loop r_hpc = exp(-2 * $pi * slider38 / srate); // input low-cut (one-pole HP) r_wet = dbg(slider39); m_vol = dbg(slider40); chan = slider41; sq_play = slider42; sq_swing = slider43 / 100 * 0.5; // hats: the six oscillator increments (ratios of the classic analogue metal), filter, decays h_t = 2 ^ (slider45 / 12) * inv_sr; h_i1 = 205.3 * h_t; h_i2 = 304.4 * h_t; h_i3 = 369.6 * h_t; h_i4 = 522.7 * h_t; h_i5 = 540 * h_t; h_i6 = 800 * h_t; hF.svf_set(slider46, 1.1); h_cdk = dcoef(slider47); h_odk_set = dcoef(slider48); h_choke = coef(1); h_nz = slider49 / 100; h_lvl = dbg(slider50); // rim r_i1 = slider51 * inv_sr; r_i2 = slider51 * 0.27 * inv_sr; r_dk1 = dcoef(slider52); r_dk2 = dcoef(slider52 * 0.8); r_cdk = coef(0.4); r_lvl = dbg(slider53); ); // reverb building blocks: idx = write position of each line // comb: y = buf[i]; f = y (1 - d) + f d; buf[i] = x + f fb (the LP f damps the highs on every pass) function comb(base, len, x) instance(i, f) local(y) ( y = base[i]; f = y * (1 - r_damp) + f * r_damp + DEN; base[i] = x + f * r_fb; i += 1; i >= len ? i = 0; y; ); // all-pass (Schroeder, g = 0.5): y = buf[i] - x; buf[i] = x + 0.5 buf[i] function allp(base, len, x) instance(i) local(b, y) ( b = base[i]; y = b - x; base[i] = x + b * 0.5 + DEN; i += 1; i >= len ? i = 0; y; ); // ---------- sequencer factory grooves (rows: kick, snare, clap, closed hat, open hat, rim; X accent, x hit) ---------- function srow(r, str) local(i, c) ( i = 0; loop(16, c = str_getchar(str, i); SEQ[r * 16 + i] = c == 'X' ? 2 : c == 'x' ? 1 : 0; i += 1; ); ); function groove(g) ( // hats and rim for each groove (closed, open, rim) g == 0 ? ( srow(3, "x.x.x.x.x.x.x.x."); srow(4, "..X...X...X...X."); srow(5, "................"); ) : g == 1 ? ( srow(3, "xxx.xxx.xxx.xxx."); srow(4, "...X.......X...."); srow(5, "......x.......x."); ) : g == 2 ? ( srow(3, "x.xxx.xxx.xxx.xx"); srow(4, "..X.......X....."); srow(5, "...x......x....."); ) : g == 3 ? ( srow(3, "x.x.x.x.x.x.x.xx"); srow(4, "..X.......X....."); srow(5, "...x..x....x..x."); ) : g == 4 ? ( srow(3, "x.x.x.x.x.x.x.x."); srow(4, "..X...X...X...X."); srow(5, "................"); ) : g == 5 ? ( srow(3, "....x.......x..."); srow(4, "..X.......X....."); srow(5, ".x....x..x....x."); ) : g == 6 ? ( srow(3, "x...x...x...x..."); srow(4, "..X...X...X...X."); srow(5, "................"); ) : ( srow(3, "................"); srow(4, "................"); srow(5, "................"); ); g == 0 ? ( srow(0, "X...X...X...X..."); srow(1, "................"); srow(2, "....X.......X..."); ) : // Deep Four g == 1 ? ( srow(0, "X...X...X...X..x"); srow(1, "..........x....."); srow(2, "....X.......X..."); ) : // Soulful g == 2 ? ( srow(0, "X...X...X..xX..."); srow(1, "....x..x....x..."); srow(2, "....X.......X..x"); ) : // Garage Shuffle g == 3 ? ( srow(0, "X..x..x...X....."); srow(1, "....X.......X..."); srow(2, "................"); ) : // Broken Deep g == 4 ? ( srow(0, "X...X...X...X..."); srow(1, "....X.......X.x."); srow(2, "....X.......X..."); ) : // Classic Chicago g == 5 ? ( srow(0, "X.....x...X....."); srow(1, "........X......."); srow(2, "....x.......x..."); ) : // Dub Minimal g == 6 ? ( srow(0, "X...X...X...X..."); srow(1, "..x...x...x...x."); srow(2, "....X..x....X..."); ) : // Off-beat Snare ( srow(0, "................"); srow(1, "................"); srow(2, "................"); ); // Clear ); function groove_name(g) ( g == 0 ? "DEEP FOUR" : g == 1 ? "SOULFUL" : g == 2 ? "GARAGE SHUFFLE" : g == 3 ? "BROKEN DEEP" : g == 4 ? "CLASSIC CHICAGO" : g == 5 ? "DUB MINIMAL" : g == 6 ? "OFF-BEAT SNARE" : "CLEAR"; ); // ---------- kits: the voice and FX settings (the sequencer pattern, MIDI channel and volume are kept) ---------- function kk(a, b, c, d, e, f, g) ( slider1 = a; slider2 = b; slider3 = c; slider4 = d; slider5 = e; slider6 = f; slider7 = g; ); function ks(a, b, c, d, e, f, g, h) ( slider8 = a; slider9 = b; slider10 = c; slider11 = d; slider12 = e; slider13 = f; slider14 = g; slider15 = h; ); function kc(on, t, r, a, rl, mk) ( slider16 = on; slider17 = t; slider18 = r; slider19 = a; slider20 = rl; slider21 = mk; ); function ke(on, lf, lg, mf, mq, mg, hf, hg) ( slider22 = on; slider23 = lf; slider24 = lg; slider25 = mf; slider26 = mq; slider27 = mg; slider28 = hf; slider29 = hg; ); function kt(on, d, ty, mx) ( slider30 = on; slider31 = d; slider32 = ty; slider33 = mx; ); function kr(on, sz, dm, dc, lc, wt) ( slider34 = on; slider35 = sz; slider36 = dm; slider37 = dc; slider38 = lc; slider39 = wt; ); function kh(tn, tone, cd, od, nz, hl, rp, rd, rl) ( slider45 = tn; slider46 = tone; slider47 = cd; slider48 = od; slider49 = nz; slider50 = hl; slider51 = rp; slider52 = rd; slider53 = rl; ); function load_kit(p) local(i) ( p == 0 ? kh(0, 9000, 45, 380, 35, -9, 1700, 25, -8) : // Deep Classic p == 1 ? kh(-2, 7000, 60, 520, 55, -10, 1400, 35, -9) : // Dusty Warehouse p == 2 ? kh(1, 11000, 30, 260, 25, -9, 2000, 18, -8) : // Tight Tech p == 3 ? kh(-3, 5500, 70, 650, 65, -11, 1200, 40, -9) : // Lo-Fi Dub p == 4 ? kh(0, 9500, 40, 420, 30, -9, 1800, 22, -8) : // Big Room Clap p == 5 ? kh(-1, 8000, 55, 480, 45, -10, 1600, 30, -8) : // Soulful Warm p == 6 ? kh(2, 12500, 25, 220, 20, -10, 2300, 15, -8) : // Minimal Click kh(0, 9000, 45, 380, 35, -9, 1700, 25, -8); // Init p == 0 ? ( kk(48, 180, 35, 420, 0.35, 25, 0); ks(185, 80, 2200, 1.2, 210, 12, -3, 40); kc(1, -14, 4, 8, 120, 0.3); ke(1, 80, 2, 500, 1, -2, 10000, 2); kt(1, 6, 0, 50); kr(1, 0.35, 5000, 0.45, 250, -18); ) : // Deep Classic p == 1 ? ( kk(45, 140, 45, 520, 0.2, 40, 0); ks(170, 110, 1600, 0.9, 260, 15, -4, 30); kc(1, -16, 3, 15, 180, 3.6); ke(1, 70, 3, 350, 0.8, -3, 8000, -2); kt(1, 10, 1, 60); kr(1, 0.5, 3500, 0.55, 300, -16); ) : // Dusty Warehouse p == 2 ? ( kk(52, 240, 22, 300, 0.5, 15, 0); ks(200, 60, 3200, 1.6, 150, 8, -3, 45); kc(1, -12, 6, 3, 80, -1.2); ke(1, 90, 1, 800, 1.2, -3, 11000, 3); kt(1, 4, 2, 40); kr(1, 0.2, 7000, 0.3, 350, -22); ) : // Tight Tech p == 3 ? ( kk(42, 120, 60, 800, 0.15, 55, 0); ks(160, 140, 1200, 0.8, 320, 18, -5, 25); kc(1, -18, 2.5, 20, 250, 5.6); ke(1, 60, 4, 300, 0.7, -2, 7000, -4); kt(1, 14, 0, 70); kr(1, 0.6, 2600, 0.6, 200, -14); ) : // Lo-Fi Dub p == 4 ? ( kk(50, 200, 30, 380, 0.3, 20, 0); ks(190, 50, 2600, 1.1, 280, 22, -2, 15); kc(1, -14, 4, 6, 140, -1.2); ke(1, 85, 2, 1200, 1, 2, 12000, 3); kt(1, 5, 0, 40); kr(1, 0.55, 6000, 0.55, 300, -14); ) : // Big Room Clap p == 5 ? ( kk(46, 160, 40, 600, 0.25, 30, 0); ks(180, 90, 1900, 1, 230, 10, -4, 35); kc(1, -15, 3, 10, 150, 1.3); ke(1, 75, 2.5, 450, 0.9, -1.5, 9000, 1); kt(1, 7, 1, 45); kr(1, 0.4, 4200, 0.5, 260, -18); ) : // Soulful Warm p == 6 ? ( kk(55, 300, 18, 260, 0.6, 10, 0); ks(220, 45, 4200, 2, 120, 5, -3, 50); kc(1, -10, 8, 1, 60, -2.2); ke(1, 100, 0, 1500, 1.4, -2, 12000, 4); kt(1, 3, 2, 30); kr(1, 0.15, 8000, 0.25, 400, -26); ) : // Minimal Click ( kk(48, 180, 35, 420, 0.35, 25, -2); ks(185, 80, 2200, 1.2, 210, 12, -5, 40); kc(0, -14, 4, 8, 120, 3); ke(0, 80, 0, 500, 1, 0, 10000, 0); kt(0, 6, 0, 50); kr(0, 0.35, 5000, 0.45, 250, -18); ); // Init (dry) i = 1; loop(39, slider_automate(2 ^ (i - 1)); i += 1; ); i = 45; loop(9, slider_automate(2 ^ (i - 1)); i += 1; ); cur_kit = p; update(); ); function kit_name(p) ( p == 0 ? "DEEP CLASSIC" : p == 1 ? "DUSTY WAREHOUSE" : p == 2 ? "TIGHT TECH" : p == 3 ? "LO-FI DUB" : p == 4 ? "BIG ROOM CLAP" : p == 5 ? "SOULFUL WARM" : p == 6 ? "MINIMAL CLICK" : "INIT (DRY)"; ); // ---------- export: the pattern into shared memory for the companion script ---------- // gmem[0] request counter, [1] bars, [2] steps (16), [3] swing (fraction of a 16th), [4] pending (1 = export me), // [5] rows (6), [10 + row * 16 + step] step values for rows kick / snare / clap / closed hat / open hat / rim // (notes 36 / 38 / 40 / 42 / 46 / 37) function export_midi() local(i) ( i = 0; loop(96, gmem[10 + i] = SEQ[i]; i += 1; ); gmem[5] = 6; gmem[1] = slider44 == 0 ? 1 : slider44 == 1 ? 2 : slider44 == 2 ? 4 : 8; gmem[2] = 16; gmem[3] = sq_swing; gmem[0] += 1; gmem[4] = 1; exp_t = time_precise(); ); // ---------- state ---------- !init_done ? ( groove(0); cur_kit = 0; sh_k = 1; sh_s = 1; sh_h = 1; aud_vel = 0.9; sel_p = 1; init_done = 1; ); k_on = 0; s_on = 0; k_ae = 0; s_te = 0; s_ne = 0; c_env = 0; c_gr = 0; sdw = 0; r_hl = r_hr = 0; t_dcL = t_dcR = 0; t_dxL = t_dxR = 0; lastkey = -1; cur_step = -1; !ui_dflt ? ui_thm = 5; !ui_dflt ? ui_hw = 1; !ui_dflt ? ui_kstyle = 0; PNL = 0x2A2C30; PNLD = 0x1F2124; INKL = 0xDADDE2; BLU = 0x6FB2F2; ORG = 0xFF9A3C; RED = 0xFF4A3A; SH1 = 0x303237; SH2 = 0x2B2D32; SH3 = 0x26282C; function mgroup(x, y, w, h, sec, title, shade) ( pk_inset(x * sc, y * sc, w * sc, h * sc, shade); pk_box(x * sc, y * sc, w * sc, h * sc, ui_mix(BLU, INKL, 0.4), title); ui_section(sec == 0 ? 2 : sec); C_INK = INKL; ); update(); 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(); // the panel's knobs do not run @slider: refresh every block evn = 0; while (midirecv(mofs, m1, m2, m3)) ( (m1 & 0xF0) == 0x90 && m3 > 0 && (chan == 0 || (m1 & 0x0F) + 1 == chan) && evn < 256 ? ( MQO[evn] = mofs; MQN[evn] = m2; MQV[evn] = m3 / 127; evn += 1; ); midisend(mofs, m1, m2, m3); ); evi = 0; spos = 0; playing = (play_state & 1) && sq_play; bp0 = beat_position; bps = tempo / 60 / srate; !playing ? ( lastkey = -1; cur_step = -1; ); aud > 0 ? ( aud == 1 ? ( kick_trig(aud_vel); lt_k = 1; ) : aud == 2 ? ( snare_trig(aud_vel, 0); lt_s = 1; ) : aud == 3 ? ( snare_trig(aud_vel, 1); lt_c = 1; ) : aud == 4 ? ( hat_trig(aud_vel, 0); lt_h = 1; ) : aud == 5 ? ( hat_trig(aud_vel, 1); lt_o = 1; ) : ( rim_trig(aud_vel); lt_r = 1; ); aud = 0; ); // a pad clicked on the panel @serialize file_var(0, ui_sz); // (show_seq: the old fold-out flag, kept so saved projects still load) file_var(0, show_seq); file_var(0, cur_kit); file_mem(0, SEQ, 48); // added later (pop-out sections, the hat and rim rows): only read when the saved state has them file_avail(0) != 0 ? ( file_var(0, sh_k); file_var(0, sh_s); file_var(0, sh_c); file_var(0, sh_e); file_var(0, sh_d); file_var(0, sh_r); file_var(0, sh_h); file_mem(0, SEQ + 48, 48); ); @sample // ---------- MIDI: sample-accurate triggers ---------- while (evi < evn && MQO[evi] <= spos) ( MQN[evi] == 36 ? ( kick_trig(MQV[evi]); lt_k = 1; ) : MQN[evi] == 38 ? ( snare_trig(MQV[evi], 0); lt_s = 1; ) : MQN[evi] == 40 ? ( snare_trig(MQV[evi], 1); lt_c = 1; ) : MQN[evi] == 42 || MQN[evi] == 44 ? ( hat_trig(MQV[evi], 0); lt_h = 1; ) : MQN[evi] == 46 ? ( hat_trig(MQV[evi], 1); lt_o = 1; ) : MQN[evi] == 37 ? ( rim_trig(MQV[evi]); lt_r = 1; ); evi += 1; ); // ---------- sequencer: steps locked to the project's beat position ---------- playing ? ( sbeat = bp0 + spos * bps; sbeat >= 0 ? ( sbar = floor(sbeat / 4); sfs = (sbeat - sbar * 4) * 4; // 16ths into the bar sst = floor(sfs); sfr = sfs - sst; s_eff = (sst & 1) && sfr < sq_swing ? sst - 1 : sst; // swing: off-beat 16ths arrive late skey = sbar * 32 + s_eff; skey != lastkey ? ( lastkey = skey; cur_step = s_eff; SEQ[s_eff] ? ( kick_trig(SEQ[s_eff] == 2 ? 1 : 0.72); lt_k = 1; ); SEQ[16 + s_eff] ? ( snare_trig(SEQ[16 + s_eff] == 2 ? 1 : 0.72, 0); lt_s = 1; ); SEQ[32 + s_eff] ? ( snare_trig(SEQ[32 + s_eff] == 2 ? 1 : 0.72, 1); lt_c = 1; ); SEQ[48 + s_eff] ? ( hat_trig(SEQ[48 + s_eff] == 2 ? 1 : 0.6, 0); lt_h = 1; ); SEQ[64 + s_eff] ? ( hat_trig(SEQ[64 + s_eff] == 2 ? 1 : 0.7, 1); lt_o = 1; ); SEQ[80 + s_eff] ? ( rim_trig(SEQ[80 + s_eff] == 2 ? 1 : 0.7); lt_r = 1; ); ); ); ); spos += 1; // ---------- KICK ---------- kick = 0; k_on ? ( k_ph += (k_base + k_drop * k_pe) * inv_sr; k_ph >= 1 ? k_ph -= 1; k_pe *= k_pdk; // exponential pitch envelope ks_ = sin(2 * $pi * k_ph); // sub drive: tanh(g x) / tanh(g), g strongest while the hit is young kg = 1 + k_drv * 6 * (0.35 + 0.65 * k_pe); ks_ = tanh_(ks_ * kg) / tanh_(kg); // click: a 2.5 ms burst of bright noise plus the first cycle's edge kcl = k_ce > 0.0001 ? ( knz = rand(2) - 1; khp = knz - kz1; kz1 = knz; k_ce *= k_cdk; khp * k_ce * k_click * 0.8; ) : 0; kick = (ks_ * k_ae + kcl) * k_lvl; k_ae *= k_adk; k_ae < 0.00003 && k_ce < 0.0001 ? k_on = 0; ); // ---------- SNARE / CLAP ---------- snL = 0; snR = 0; snN = 0; s_on ? ( s_ph += s_f * (1 + 1.4 * s_pe) * inv_sr; s_ph >= 1 ? s_ph -= 1; // body: a sine with a quick pitch drop s_pe *= s_pdk; stone = sin(2 * $pi * s_ph) * s_te; s_te *= s_tdk; // noise: band-passed white noise. The clap re-strikes three times (0 / 11 / 22 ms) before its tail. s_clap ? ( s_t += 1; s_t == c_b1 || s_t == c_b2 || s_t == c_b3 ? s_ne = s_nv * (s_t == c_b3 ? 1 : 0.85); s_ne *= s_t < c_b3 ? c_bdk : s_ndk; ) : s_ne *= s_ndk; snN = snF.svf_bp(rand(2) - 1) * s_ne * 2.2; stone *= s_tmix * 1.4; snN *= (1 - s_tmix * 0.6); snL = (stone + snN) * s_lvl; s_te < 0.00003 && s_ne < 0.00003 && (!s_clap || s_t > c_b3) ? s_on = 0; ); // width: the noise on the right is the same noise a few ms later (always running so the tail finishes) SDL[sdw] = snN * s_lvl; sdr = sdw - s_dly; sdr < 0 ? sdr += SDS; snR = snL - snN * s_lvl + SDL[sdr]; sdw += 1; sdw >= SDS ? sdw = 0; // ---------- HATS ---------- hat = 0; h_on ? ( // six square oscillators (+/-1 each), averaged, blended with white noise h_p1 += h_i1; h_p1 -= floor(h_p1); h_p2 += h_i2; h_p2 -= floor(h_p2); h_p3 += h_i3; h_p3 -= floor(h_p3); h_p4 += h_i4; h_p4 -= floor(h_p4); h_p5 += h_i5; h_p5 -= floor(h_p5); h_p6 += h_i6; h_p6 -= floor(h_p6); hm = ((h_p1 < 0.5) + (h_p2 < 0.5) + (h_p3 < 0.5) + (h_p4 < 0.5) + (h_p5 < 0.5) + (h_p6 < 0.5)) * 0.333333 - 1; hx = hm * (1 - h_nz) + (rand(2) - 1) * h_nz; hat = hF.svf_bphp(hx) * (h_ce + h_oe) * h_lvl * 1.6; h_ce *= h_cdk; h_oe *= h_odk; h_ce < 0.00003 && h_oe < 0.00003 ? h_on = 0; ); // ---------- RIM ---------- rim = 0; rim_on ? ( r_ph1 += r_i1; r_ph1 -= floor(r_ph1); r_ph2 += r_i2; r_ph2 -= floor(r_ph2); rnz = rand(2) - 1; rhp = rnz - r_z1; r_z1 = rnz; rim = (sin(2 * $pi * r_ph1) * r_e1 * 0.7 + sin(2 * $pi * r_ph2) * r_e2 * 0.5 + rhp * r_ce * 0.5) * r_lvl; r_e1 *= r_dk1; r_e2 *= r_dk2; r_ce *= r_cdk; r_e1 < 0.00003 && r_e2 < 0.00003 ? rim_on = 0; ); // hats a little right, the rim a little left L = (kick + snL + hat * 0.89 + rim * 1.05) * 0.5; R = (kick + snR + hat * 1.05 + rim * 0.89) * 0.5; // voice bus headroom into the chain // ---------- MODULE 1: VCA COMPRESSOR (feed-forward, stereo-linked peak) ---------- c_on ? ( c_in = 20 * log10(max(abs(L), abs(R)) + DEN); // detector level in dB c_tgt = min(0, (c_thr - c_in) * c_slope); // GR = min(0, (T - dB_in) (1 - 1/R)) // ballistics on the GR: attack when more reduction is needed, release when less c_gr = c_tgt < c_gr ? c_tgt + (c_gr - c_tgt) * c_att : c_tgt + (c_gr - c_tgt) * c_rel; c_g = 10 ^ (c_gr * 0.05) * c_mk; L *= c_g; R *= c_g; ) : c_gr = 0; // ---------- MODULE 2: 3-BAND EQ (DF2T biquads) ---------- q_on ? ( L = eqHS_L.bq_run(eqPK_L.bq_run(eqLS_L.bq_run(L))); R = eqHS_R.bq_run(eqPK_R.bq_run(eqLS_R.bq_run(R))); ); // ---------- MODULE 3: SATURATION ---------- t_on ? ( tl = L * t_g; tr = R * t_g; t_type == 0 ? ( tl = tanh_(tl); tr = tanh_(tr); // tape: symmetric tanh (odd harmonics) ) : t_type == 1 ? ( // tube: x + 0.15 x^2 (even harmonics) into a soft clip, then a DC blocker (the asymmetry adds DC) tl = tanh_(tl + 0.15 * tl * tl); tr = tanh_(tr + 0.15 * tr * tr); t_dyL = tl - t_dxL + 0.9995 * t_dyL + DEN; t_dxL = tl; tl = t_dyL; t_dyR = tr - t_dxR + 0.9995 * t_dyR + DEN; t_dxR = tr; tr = t_dyR; ) : ( // soft clip: x - x^3 / 3 inside +/-1, flat (2/3) beyond; x 1.5 so a full-scale input stays full scale tl = min(max(tl, -1), 1); tr = min(max(tr, -1), 1); tl = (tl - tl * tl * tl * 0.333333333) * 1.5; tr = (tr - tr * tr * tr * 0.333333333) * 1.5; ); L += (tl * t_comp - L) * t_mix; R += (tr * t_comp - R) * t_mix; // dry / wet crossfade ); // ---------- MODULE 4: REVERB (4 damped combs in parallel -> 2 all-passes in series, per channel) ---------- r_on ? ( // low-cut on the input (one-pole HP: x - LP(x)) so the kick's lows stay out of the tail rin = (L + R) * 0.015; // Freeverb's fixed input gain r_hl = rin + (r_hl - rin) * r_hpc; rx = rin - r_hl; rl = c0.comb(CMB, rc0, rx) + c1.comb(CMB + CMS, rc1, rx) + c2.comb(CMB + 2 * CMS, rc2, rx) + c3.comb(CMB + 3 * CMS, rc3, rx); rr = c4.comb(CMB + 4 * CMS, rc4, rx) + c5.comb(CMB + 5 * CMS, rc5, rx) + c6.comb(CMB + 6 * CMS, rc6, rx) + c7.comb(CMB + 7 * CMS, rc7, rx); rl = ap1.allp(APB + APS, ra1, ap0.allp(APB, ra0, rl)); rr = ap3.allp(APB + 3 * APS, ra3, ap2.allp(APB + 2 * APS, ra2, rr)); L += rl * r_wet * 3; R += rr * r_wet * 3; ); // ---------- MASTER ---------- spl0 = L * m_vol; spl1 = R * m_vol; pkL = max(pkL, abs(spl0)); pkR = max(pkR, abs(spl1)); @gfx 1180 606 // --------------------------------------------------------------------------------------------------------- // GFX drum machine panel (the G-Pulse family): header with the LCD, the voice matrix (voice tab, 16 steps, // every one of the voice's controls on a band in its colour), then SEQUENCER / COMPRESSOR / DRIVE / MASTER and // EQ / REVERB. Click a voice's name to hear it. // --------------------------------------------------------------------------------------------------------- fh = 600; ui_thm = 5; ui_hw = 1; ui_begin(1180, fh + 6); // light grey drum-box skin: grey case, dark grey keys and knobs, charcoal silkscreen, blue and orange accents PNL = 0xC4C6C9; INKL = 0x26282C; SH1 = 0xB3B6BA; SH2 = 0xB9BCC0; ORG = 0xE07A1E; RED = 0xD8402E; ACC = 0x2F6FB8; C_ACC = ACC; C_S0 = 0x3A7FCC; C_S2 = 0x3A7FCC; C_KC = 0xF0F2F4; dr_tabc = 0xD6D8DB; dr_tabs = 0xECEEF0; dr_ink = INKL; dr_c0 = 0xA9ACB1; dr_c1 = 0x9EA1A6; dr_hl = 0x000000; ui_col(0x7E8084); gfx_rect(0, 0, gfx_w, gfx_h); pk_chassis(8 * sc, 8 * sc, 1164 * sc, fh * sc, PNL); C_INK = INKL; dr_header("G-DEEP 16", "DEEP HOUSE DRUM SYNTHESIZER", INKL, PNL, ACC, 1180); gi = 0; loop(4, ui_col(gi == 0 ? 0x3E7FD0 : gi == 1 ? 0x4FB4E6 : gi == 2 ? 0xFF9A3C : 0xE5453A); gfx_rect((380 + gi * 14) * sc, 26 * sc, 10 * sc, 24 * sc); gi += 1; ); // LCD (yellow-green): kit and sequencer pk_lcd(452 * sc, 14 * sc, 300 * sc, 48 * sc, 1); pk_lcdfont(7, 13 * sc); ui_col(pk_lcdc); sprintf(#l1, "KIT %s", kit_name(cur_kit)); gfx_x = 464 * sc; gfx_y = 20 * sc; gfx_drawstr(#l1); pk_lcdfont(8, 10 * sc); cur_step >= 0 ? sprintf(#l2, "PLAY STEP %02d/16 %.1f BPM", cur_step + 1, tempo) : sprintf(#l2, "SEQ %s %.1f BPM", slider42 ? ((play_state & 1) ? "PLAY" : "WAITING FOR PLAY") : "OFF", tempo); gfx_x = 464 * sc; gfx_y = 42 * sc; gfx_drawstr(#l2); function kit_menu(x, y) local(i, k) ( #km = ""; i = 0; loop(8, cur_kit == i ? strcat(#km, "!"); strcat(#km, kit_name(i)); i < 7 ? strcat(#km, "|"); i += 1; ); gfx_x = x; gfx_y = y; k = gfx_showmenu(#km); k > 0 ? load_kit(k - 1); ); ui_noled = 1; ui_button(768 * sc, 22 * sc, 92 * sc, 30 * sc, "KITS", 0, 1) ? kit_menu(768 * sc, 52 * sc); ui_noled = 0; ui_size_picker(1060 * sc, 28 * sc); // ---------- the voice matrix ---------- pk_inset(24 * sc, 84 * sc, 1132 * sc, 262 * sc, SH1); function dsx(s) ( 194 + s * 28 + floor(s / 4) * 6; ); function dry(r) ( 106 + r * 38; ); gfx_setfont(4); ui_cola(INKL, 0.7); gfx_x = 44 * sc; gfx_y = 90 * sc; gfx_drawstr("VOICE NOTE"); gi = 0; loop(16, ui_cola(INKL, gi % 4 == 0 ? 0.85 : 0.35); sprintf(#sn, "%d", gi + 1); ui_text((dsx(gi) + 12.5) * sc, 90 * sc, #sn); gi += 1; ); ui_cola(INKL, 0.7); ui_text(910 * sc, 90 * sc, "VOICE CONTROLS"); // a knob in slot k of the current row (slider-bound), its name underneath function rk(k, idx, lo, hi, def, lg, label, fmt) ( ui_kmini = 1; ui_knob((704 + k * 64) * sc, (r_y + 13) * sc, idx, lo, hi, def, lg, "", fmt); ui_kmini = 0; drag_id == idx || (mouse_x >= (690 + k * 64) * sc && mouse_x < (718 + k * 64) * sc && mouse_y >= r_y * sc && mouse_y < (r_y + 26) * sc) ? 0 : dr_klabel(704 + k * 64, r_y + 27, label); ); gr = 0; loop(6, r_y = dry(gr); gc = gr == 0 ? 0xE0603A : gr == 1 ? 0xE8B23A : gr == 2 ? 0xD8D25A : gr == 3 ? 0x6FCB7A : gr == 4 ? 0x4FB8B0 : 0x8E7AE0; glt = gr == 0 ? lt_k : gr == 1 ? lt_s : gr == 2 ? lt_c : gr == 3 ? lt_h : gr == 4 ? lt_o : lt_r; dr_tab(32, r_y, 150, 34, gc, gr == 0 ? "KICK" : gr == 1 ? "SNARE" : gr == 2 ? "CLAP" : gr == 3 ? "CLOSED HAT" : gr == 4 ? "OPEN HAT" : "RIM SHOT", gr == 0 ? "36" : gr == 1 ? "38" : gr == 2 ? "40" : gr == 3 ? "42" : gr == 4 ? "46" : "37", glt, 0) ? ( aud = gr + 1; aud_vel = 0.9; ); gs = 0; loop(16, gx = dsx(gs); gv = SEQ[gr * 16 + gs]; dr_cell(gx, r_y, 25, 34, gv, gc, cur_step == gs, floor(gs / 4) % 2 == 0); pressed && drag_id == 0 && mouse_x >= gx * sc && mouse_x < (gx + 25) * sc && mouse_y >= r_y * sc && mouse_y < (r_y + 34) * sc ? ( drag_id = -1; SEQ[gr * 16 + gs] = (gv + 1) % 3; ); gs += 1; ); dr_band(672, r_y, 476, 34, gc, mouse_x >= 672 * sc && mouse_x < 1148 * sc && mouse_y >= r_y * sc && mouse_y < (r_y + 34) * sc); ui_section(gr % 2 ? 1 : 3); C_INK = INKL; gr == 0 ? ( rk(0, 1, 30, 120, 48, 1, "PITCH", "%.1f Hz"); rk(1, 2, 0, 600, 180, 0, "DROP", "%.0f Hz"); rk(2, 3, 2, 200, 35, 1, "P.DECAY", "%.1f ms"); rk(3, 4, 50, 2000, 420, 1, "DECAY", "%.0f ms"); rk(4, 5, 0, 1, 0.35, 0, "CLICK", "%.2f"); rk(5, 6, 0, 100, 25, 0, "DRIVE", "%.0f%%"); rk(6, 7, -24, 6, 0, 0, "LEVEL", "%.1f dB"); ) : gr == 1 ? ( rk(0, 8, 100, 400, 185, 1, "TONE", "%.0f Hz"); rk(1, 9, 10, 500, 80, 1, "T.DECAY", "%.0f ms"); rk(2, 15, 0, 100, 40, 0, "TONE MIX", "%.0f%%"); rk(6, 14, -24, 6, -3, 0, "LEVEL", "%.1f dB"); dr_klabel(962, r_y + 10, "body + level (snare and clap)"); ) : gr == 2 ? ( rk(0, 10, 500, 10000, 2200, 1, "CUTOFF", "%.0f Hz"); rk(1, 11, 0.5, 8, 1.2, 1, "RESO", "Q %.2f"); rk(2, 12, 20, 800, 210, 1, "N.DECAY", "%.0f ms"); rk(3, 13, 0, 30, 12, 0, "WIDTH", "%.1f ms"); dr_klabel(1034, r_y + 10, "noise (snare and clap)"); ) : gr == 3 ? ( rk(0, 45, -12, 12, 0, 0, "TUNE", "%+.1f st"); rk(1, 46, 3000, 16000, 9000, 1, "TONE", "%.0f Hz"); rk(2, 47, 10, 300, 45, 1, "CLOSED", "%.0f ms"); rk(3, 49, 0, 100, 35, 0, "NOISE", "%.0f%%"); rk(6, 50, -30, 6, -9, 0, "LEVEL", "%.1f dB"); ) : gr == 4 ? ( rk(2, 48, 50, 2000, 380, 1, "OPEN", "%.0f ms"); dr_klabel(1010, r_y + 10, "tune, tone, noise, level: as the closed hat"); ) : ( rk(0, 51, 600, 3500, 1700, 1, "PITCH", "%.0f Hz"); rk(1, 52, 5, 120, 25, 1, "DECAY", "%.0f ms"); rk(6, 53, -30, 6, -8, 0, "LEVEL", "%.1f dB"); ); gr += 1; ); lt_k *= 0.82; lt_s *= 0.82; lt_c *= 0.82; lt_h *= 0.82; lt_o *= 0.82; lt_r *= 0.82; gfx_setfont(4); ui_cola(INKL, 0.45); ui_text(590 * sc, 336 * sc, "click a voice's name to hear it - click a step: off > hit > accent - double-click a knob to reset it"); // ---------- bottom: SEQUENCER | COMPRESSOR | DRIVE | MASTER, then EQ | REVERB ---------- function sgroup(x, y, w, h, title) ( pk_inset(x * sc, y * sc, w * sc, h * sc, SH2); pk_box(x * sc, y * sc, w * sc, h * sc, ui_mix(ACC, INKL, 0.35), title); C_INK = INKL; ); function onbtn(x, y, idx) ( pk_ledbtn(x * sc, y * sc, 36 * sc, 30 * sc, slider(idx), ACC) ? ( slider(idx) = 1 - slider(idx); slider_automate(2 ^ (idx - 1)); ); gfx_setfont(4); ui_col(INKL); ui_text((x + 18) * sc, (y + 36) * sc, "ON"); ); sgroup(24, 360, 320, 112, "SEQUENCER"); pk_ledbtn(38 * sc, 376 * sc, 40 * sc, 30 * sc, slider42, 0x3ADF6A) ? ( slider42 = 1 - slider42; slider_automate(2 ^ 41); ); gfx_setfont(4); ui_col(INKL); ui_text(58 * sc, 412 * sc, "PLAY"); ui_section(1); C_INK = INKL; ui_knob(118 * sc, 406 * sc, 43, 0, 75, 0, 0, "SWING", "%.0f%%"); ui_section(2); C_INK = INKL; ui_noled = 1; ui_button(160 * sc, 374 * sc, 80 * sc, 24 * sc, "GROOVES", 0, 1) ? ( gfx_x = 160 * sc; gfx_y = 398 * sc; gsel = gfx_showmenu("Deep Four|Soulful|Garage Shuffle|Broken Deep|Classic Chicago|Dub Minimal|Off-beat Snare|Clear"); gsel > 0 ? groove(gsel - 1); ); ui_button(246 * sc, 374 * sc, 88 * sc, 24 * sc, "EXPORT MIDI", time_precise() - exp_t < 0.6, 1) ? export_midi(); gi = 0; loop(4, ui_keycap((160 + gi * 30) * sc, 418 * sc, 27 * sc, 22 * sc, gi == 0 ? "1" : gi == 1 ? "2" : gi == 2 ? "4" : "8", slider44 == gi, 1) ? ( slider44 = gi; slider_automate(2 ^ 43); ); gi += 1; ); ui_noled = 0; gfx_setfont(4); ui_cola(INKL, 0.6); gfx_x = 284 * sc; gfx_y = 424 * sc; gfx_drawstr("BARS"); ui_text(246 * sc, 452 * sc, gmem[4] && time_precise() - exp_t > 1.5 && exp_t > 0 ? "export waiting: run the GFX G-Deep export script" : "export: the GFX G-Deep export script"); sgroup(352, 360, 372, 112, "1 COMPRESSOR"); onbtn(364, 378, 16); ui_knob(438 * sc, 416 * sc, 17, -40, 0, -14, 0, "THRESH", "%.1f dB"); ui_knob(494 * sc, 416 * sc, 18, 1, 20, 4, 1, "RATIO", "%.1f:1"); ui_knob(550 * sc, 416 * sc, 19, 0.1, 100, 8, 1, "ATTACK", "%.1f ms"); ui_knob(606 * sc, 416 * sc, 20, 10, 1000, 120, 1, "RELEASE", "%.0f ms"); ui_knob(662 * sc, 416 * sc, 21, -12, 24, 0.3, 0, "MAKEUP", "%+.1f dB"); gi = 0; loop(8, pk_led(706 * sc, (380 + gi * 10) * sc, 2.6 * sc, -c_gr > gi * 1.5 + 0.5, gi < 5 ? ORG : RED); gi += 1; ); gfx_setfont(4); ui_cola(INKL, 0.6); ui_text(706 * sc, 462 * sc, "GR"); sgroup(732, 360, 236, 112, "3 DRIVE"); onbtn(744, 378, 30); gi = 0; loop(3, ui_noled = 1; ui_keycap(790 * sc, (372 + gi * 30) * sc, 52 * sc, 24 * sc, gi == 0 ? "TAPE" : gi == 1 ? "TUBE" : "SOFT", slider32 == gi, 1) ? ( slider32 = gi; slider_automate(2 ^ 31); ); ui_noled = 0; gi += 1; ); ui_knob(878 * sc, 416 * sc, 31, 0, 24, 6, 0, "DRIVE", "%.1f dB"); ui_knob(932 * sc, 416 * sc, 33, 0, 100, 50, 0, "WET", "%.0f%%"); sgroup(976, 360, 180, 112, "MASTER"); ui_knob(1014 * sc, 416 * sc, 40, -24, 12, 0, 0, "VOLUME", "%.1f dB"); ui_section(3); C_INK = INKL; knob_step = 1; ui_knob(1072 * sc, 416 * sc, 41, 0, 16, 0, 0, "CH", slider41 == 0 ? "OMNI" : "%.0f"); ui_section(2); C_INK = INKL; mL.ui_ledm(1116 * sc, 374 * sc, 11 * sc, 88 * sc, pkL); mR.ui_ledm(1132 * sc, 374 * sc, 11 * sc, 88 * sc, pkR); pkL *= 0.85; pkR *= 0.85; sgroup(24, 484, 560, 108, "2 3-BAND EQ"); onbtn(36, 500, 22); ui_knob(124 * sc, 538 * sc, 23, 30, 300, 80, 1, "LOW F", "%.0f Hz"); ui_knob(184 * sc, 538 * sc, 24, -15, 15, 0, 0, "LOW", "%+.1f dB"); ui_knob(264 * sc, 538 * sc, 25, 150, 5000, 500, 1, "MID F", "%.0f Hz"); ui_knob(324 * sc, 538 * sc, 26, 0.3, 6, 1, 1, "MID Q", "%.2f"); ui_knob(384 * sc, 538 * sc, 27, -15, 15, 0, 0, "MID", "%+.1f dB"); ui_knob(464 * sc, 538 * sc, 28, 2000, 16000, 10000, 1, "HIGH F", "%.0f Hz"); ui_knob(524 * sc, 538 * sc, 29, -15, 15, 0, 0, "HIGH", "%+.1f dB"); sgroup(592, 484, 564, 108, "4 REVERB"); onbtn(604, 500, 34); ui_knob(700 * sc, 538 * sc, 35, 0, 1, 0.35, 0, "SIZE", "%.2f"); ui_knob(780 * sc, 538 * sc, 37, 0, 1, 0.45, 0, "DECAY", "%.2f"); ui_knob(860 * sc, 538 * sc, 36, 1000, 12000, 5000, 1, "DAMPING", "%.0f Hz"); ui_knob(940 * sc, 538 * sc, 38, 50, 1000, 250, 1, "LOW-CUT", "%.0f Hz"); ui_knob(1030 * sc, 538 * sc, 39, -60, 0, -18, 0, "WET", "%.1f dB"); pk_end(); ui_end();