desc:GFX G Pocket 70 //tags: instrument rompler sound module piano epiano strings pad bass drums //author: JGWizrad / Garden FX (GFX) // // Requires gfx-drift, gfx-output, gfx-ui, gfx-panel, gfx-instrument, gfx-voice, gfx-dyn and gfx-faceplate (.jsfx-inc) // in the same folder. // // A late-90s sound module: pick a patch, play it. 90 patches in ten groups, all synthesised (no samples): // the G Lab80 sounds (synthetic pianos, FM and chorus e-pianos, clav, drawbar organ, bells and glass, // the LA guitars, pads, choirs, brass, leads and basses) together with the pick of the Pocket 70 GM voices, // and a drum kit on the GM drum map. // EDIT TONE (tone, filter, resonance), FILTER ENVELOPE (amount, A D S R) and AMP ENVELOPE (A D S R) move the // patch from where it stands (centre = the patch as made); choosing a patch puts them back. The filter // envelope works on the analogue and GM-style patches (piano, bells, plucks, organ and drums have none). // PLAY VELOCITY, TUNE, BEND range and the MIDI channel. Mod wheel adds vibrato; sustain pedal works. // MOD RACK the GFX Mod Rack inside: TREMOLO, CHORUS, VIBE and DELAY, each with L / C / R outputs and tempo SYNC. // REVERB the GFX Space engine (ROOM / HALL / PLATE). // Every patch carries its own Mod Rack and reverb settings. // DRIFT (GFX instrument standard, fixed and subtle): the tuning wanders a little and every note lands slightly differently. // MIDI program change 0 - 89 picks the patch; pitch bend, CC1, CC64, CC120 / 123. import gfx-drift.jsfx-inc import gfx-output.jsfx-inc import gfx-ui.jsfx-inc import gfx-panel.jsfx-inc import gfx-instrument.jsfx-inc import gfx-voice.jsfx-inc import gfx-dyn.jsfx-inc import gfx-faceplate.jsfx-inc slider1:0<0,89,1>-Patch slider2:0<-24,6,0.1>-Volume (dB) slider4:0<0,16,1>-MIDI channel (0 = omni) slider5:50<0,100,1>-Tone (%) slider6:0<-6,3,0.01>-Filter (octaves) slider7:0<0,100,1>-Resonance (%) slider8:100<10,400,1>-Attack (%) slider9:100<10,400,1>-Release (%) slider11:70<0,100,1>-Velocity (%) slider12:0<-50,50,1>-Tune (cents) slider13:2<0,12,1>-Bend range (st) slider14:1<0,2,1{Room,Hall,Plate}>-Reverb type slider15:15<0,150,1>-Reverb pre-delay (ms) slider16:2.2<0.2,10,0.01>-Reverb decay (s) slider17:50<0,100,1>-Reverb damping (%) slider18:25<0,100,1>-Reverb mix (%) slider19:0.8<0.05,8,0.01>-FX chorus rate (Hz) slider20:50<0,100,1>-FX chorus depth (%) slider21:0<0,100,1>-FX chorus mix (%) slider23:1<0,1,1{Off,On}>-FX chorus L slider24:0<0,1,1{Off,On}>-FX chorus C slider25:1<0,1,1{Off,On}>-FX chorus R slider26:0<0,3,1{Off,Straight,Dotted,Triplet}>-FX chorus sync slider27:2<0,7,1{4 Bars,2 Bars,1 Bar,1/2,1/4,1/8,1/16,1/32}>-FX chorus sync rate slider28:4<0.1,15,0.01>-FX tremolo rate (Hz) slider29:0<0,100,1>-FX tremolo depth (%) slider31:1<0,1,1{Off,On}>-FX tremolo L slider32:0<0,1,1{Off,On}>-FX tremolo C slider33:1<0,1,1{Off,On}>-FX tremolo R slider34:0<0,3,1{Off,Straight,Dotted,Triplet}>-FX tremolo sync slider35:5<0,7,1{4 Bars,2 Bars,1 Bar,1/2,1/4,1/8,1/16,1/32}>-FX tremolo sync rate slider36:1.5<0.1,12,0.01>-FX vibe rate (Hz) slider37:0<0,100,1>-FX vibe depth (%) slider39:1<0,1,1{Off,On}>-FX vibe L slider40:0<0,1,1{Off,On}>-FX vibe C slider41:1<0,1,1{Off,On}>-FX vibe R slider42:0<0,3,1{Off,Straight,Dotted,Triplet}>-FX vibe sync slider43:4<0,7,1{4 Bars,2 Bars,1 Bar,1/2,1/4,1/8,1/16,1/32}>-FX vibe sync rate slider44:350<20,1500,1>-FX delay time (ms) slider45:30<0,95,1>-FX delay feedback (%) slider46:0<0,100,1>-FX delay mix (%) slider48:1<0,1,1{Off,On}>-FX delay L slider49:0<0,1,1{Off,On}>-FX delay C slider50:1<0,1,1{Off,On}>-FX delay R slider51:0<0,3,1{Off,Straight,Dotted,Triplet}>-FX delay sync slider52:4<0,7,1{4 Bars,2 Bars,1 Bar,1/2,1/4,1/8,1/16,1/32}>-FX delay sync rate slider53:100<10,400,1>-Amp decay (%) slider54:0<-100,100,1>-Amp sustain (+/-) slider55:100<0,200,1>-Filter envelope amount (%) slider56:100<10,400,1>-Filter attack (%) slider57:100<10,400,1>-Filter decay (%) slider58:0<-100,100,1>-Filter sustain (+/-) slider59:100<10,400,1>-Filter release (%) slider70:0<0,100,1>-Band sat (%) slider71:30<0,100,1>-Bias (%) slider72:120<40,400,1>-Sat low band (Hz) slider73:6000<2000,16000,10>-Sat high band (Hz) slider74:-0.3<-24,0,0.1>-Ceiling / limit threshold (dB) slider75:1<0,2,1{Off,Clip,Limit}>-Output stage slider76:20<20,500,1>-Mono below (Hz, 20 = off) slider77:0<0,100,1>-Stereo width (%) in_pin:none out_pin:left output out_pin:right output @init #ui_man = "gfx-g-pocket-70"; NV = 16; VS = 172; VB = 1000; // voice blocks: VB + v * VS (the GM voices use VB + v * VS + 100 ..) // field offsets F_N = 0; F_G = 1; F_S = 2; F_ACT = 3; F_AGE = 4; F_VEL = 5; F_F0 = 6; F_AE = 7; F_AST = 8; F_FE = 9; F_FST = 10; F_P1 = 11; F_P2 = 12; F_P3 = 13; F_S1 = 14; F_S2 = 15; F_S3 = 16; F_S4 = 17; F_O1 = 18; F_O2 = 19; F_O3 = 20; F_O4 = 21; F_E1 = 22; F_E2 = 23; F_E3 = 24; F_E4 = 25; F_VT = 26; F_MS = 27; F_MC = 31; F_MA = 35; F_MD = 39; F_MWS = 43; F_MWC = 47; F_CLK = 51; F_DCO = 64; F_DCF = 65; F_PY = 66; F_ATK = 67; F_PY2 = 68; // de-click: offset, flag, last two outputs, fade-in F_PE = 69; F_HN = 70; F_HL = 71; // pitch envelope, hammer / click noise state P_MS = 72; P_MC = 88; P_MA = 104; P_MD = 120; P_WS = 136; P_WC = 152; // 16 partials (piano, organ) F_KW = 55; F_KL = 56; F_KLP = 57; F_KAP = 58; F_KG = 59; F_KPO = 60; F_KHP = 61; F_KX = 62; F_DT = 63; KSB = 117000 + ceil(1.45 * srate); KSL = 4096; // string / pluck delay lines, one per voice (above the reverb at any rate) evq = 4000; // MIDI event queue cbuf = 8192; cmask = 8191; // chorus delay line PG = 70000; // GM voice programs: 46 x 16 PT = 72000; // patches: 90 x 64 (kind, index, chorus, trim, reverb x 3, Mod Rack x 34, group) MR = KSB + 16 * KSL + 64; // Mod Rack lines NP = 90; memset(VB, 0, NV * VS); memset(KSB, 0, NV * KSL); memset(cbuf, 0, 8192); age = 0; pedal = 0; modw = 0; cwp = 0; cps = 0; cpf = 0; mono_n = -1; mono_f = 0; bend_t = 0; bend_m = 1; function svf_set(f, q) instance(a1, a2, a3, k) local(g) ( g = tan($pi * min(f, srate * 0.45) / srate); k = 1 / q; a1 = 1 / (1 + g * (g + k)); a2 = g * a1; a3 = g * a2; ); function svf_bp(x) instance(a1, a2, a3, k, ic1, ic2) local(v1, v2, v3) ( v3 = x - ic2; v1 = a1 * ic1 + a2 * v3; v2 = ic2 + a2 * ic1 + a3 * v3; ic1 = 2 * v1 - ic1; ic2 = 2 * v2 - ic2; v1; ); function tanh_(x) local(e) ( x = min(max(x, -20), 20); e = exp(2 * x); (e - 1) / (e + 1) ); function blep(t, dt) ( t < dt ? ( t /= dt; t + t - t * t - 1; ) : t > 1 - dt ? ( t = (t - 1) / dt; t * t + t + t + 1; ) : 0; ); function saw(p, dt) ( 2 * p - 1 - blep(p, dt) ); function sqw(p, dt) local(q) ( q = p + 0.5; q >= 1 ? q -= 1; (p < 0.5 ? 1 : -1) + blep(p, dt) - blep(q, dt) ); function tc(t) ( exp(-1 / (max(t, 0.0005) * srate)) ); // ---------- the sounds: settings used when a key is struck ---------- function patch_set(s) ( snd = s; eng = s == 0 || s == 25 ? 1 : s == 1 ? 2 : s == 2 ? 3 : s == 24 || s == 38 ? 4 : s == 34 ? 5 : 0; // 0 analogue, 1 FM, 2 plucked string, 3 metal bar, 4 synthetic piano, 5 drawbar organ // analogue defaults o2w = 0; det = 0.006; subl = 0; o2l = 1; fbase = 1200; famt = 1.5; fres = 0.2; ktrk = 0.5; aA = 0.01; aD = 0.5; aS = 0.8; aR = 0.4; fA = 0.01; fD = 0.6; fS = 0.3; vib = 0; vibd = 0.4; mono = 0; glide = 0; chor = 0.3; three = 0; flfo = 0; lvl = 0.5; // layers (off by default): bell partials, plucked string, breath + chiff, osc 1 sine, formant "aah" bl_lvl = 0; bR0 = 1; bR1 = 2; bR2 = 3; bR3 = 4; bA0 = 1; bA1 = 0.5; bA2 = 0.3; bA3 = 0.15; bD0 = 1; bD1 = 0.5; bD2 = 0.25; bD3 = 0.12; ks_lvl = 0; ks_T = 1; ks_br = 0.4; ks_pick = 0; br_lvl = 0; chf = 0; o1w = 0; vamix = 1; form = 0; // extras: pitch envelope (semitones, s), velocity to filter, echo (mix, beats, feedback), tremolo, chorus rate, // rhythmic loop layer, piano brightness / decay / unison, organ percussion pe_amt = 0; pe_t = 0.1; vf = 0; brp = 0; dl_mix = 0; dl_bt = 0.75; dl_fb = 0.35; trem = 0; crate = 0.6; nd = 0; pn_hard = 0.6; pn_T = 1; pn_uni = 1; pn_knock = 1; pn_ch = 0.3; org_perc = 0; s == 3 ? ( det = 0.009; fbase = 700; famt = 1.6; fres = 0.25; aA = 0.6; aD = 1; aS = 0.85; aR = 1.6; fA = 1.2; fD = 2; fS = 0.5; chor = 0.6; lvl = 0.3; ) : s == 4 ? ( det = 0.004; subl = 0.6; o2l = 0.5; fbase = 420; famt = 0.8; fres = 0.12; aA = 0.9; aD = 1; aS = 0.9; aR = 2.2; fA = 1.5; fD = 2; fS = 0.6; chor = 0.9; flfo = 0.35; lvl = 0.32; ) : s == 5 ? ( det = 0.003; o2w = 1; o2l = 0.5; subl = 0.8; fbase = 140; famt = 3.2; fres = 0.45; ktrk = 0.3; aA = 0.002; aD = 0.5; aS = 0.75; aR = 0.12; fA = 0.001; fD = 0.28; fS = 0.15; mono = 1; glide = 0.04; chor = 0; lvl = 0.55; ) : s == 6 ? ( det = 0.005; fbase = 2200; famt = 0.6; fres = 0.1; ktrk = 0.8; aA = 0.35; aD = 1; aS = 0.9; aR = 0.8; fA = 0.4; fD = 1; fS = 0.7; vib = 5.3; vibd = 0.5; chor = 0.4; lvl = 0.3; ) : s == 7 ? ( det = 0.002; fbase = 4500; famt = 0.3; fres = 0.05; ktrk = 0.6; aA = 0.06; aD = 1; aS = 1; aR = 0.9; fA = 0.05; fD = 1; fS = 0.8; chor = 0.55; three = 1; lvl = 0.28; ) : s == 8 ? ( // BELL PAD det = 0.008; fbase = 800; famt = 1; fres = 0.15; aA = 0.8; aD = 1; aS = 0.85; aR = 2.2; fA = 1; fD = 2; fS = 0.5; chor = 0.9; lvl = 0.3; bl_lvl = 0.5; bR0 = 1; bR1 = 3.52; bR2 = 6.01; bR3 = 8.93; bA0 = 1; bA1 = 0.5; bA2 = 0.3; bA3 = 0.15; bD0 = 2.4; bD1 = 1; bD2 = 0.5; bD3 = 0.25; ) : s == 9 ? ( // STACCATO CHOIR det = 0.006; fbase = 1600; famt = 0.5; fres = 0.1; aA = 0.015; aD = 0.35; aS = 0.45; aR = 0.45; fA = 0.02; fD = 0.4; fS = 0.5; form = 1; chor = 0.8; lvl = 0.12; bl_lvl = 0.35; bR0 = 2; bR1 = 4.1; bR2 = 6.8; bR3 = 9.6; bA0 = 1; bA1 = 0.5; bA2 = 0.3; bA3 = 0.15; bD0 = 0.5; bD1 = 0.3; bD2 = 0.2; bD3 = 0.12; ) : s == 10 ? ( // PIZZ BELLS vamix = 0; aA = 0.001; aD = 0.2; aS = 0; aR = 0.1; chor = 0.5; lvl = 0.6; ks_lvl = 1; ks_T = 0.35; ks_br = 0.5; ks_pick = 0; bl_lvl = 0.4; bR0 = 1; bR1 = 4; bR2 = 7.2; bR3 = 10.1; bA0 = 1; bA1 = 0.4; bA2 = 0.2; bA3 = 0.1; bD0 = 0.9; bD1 = 0.4; bD2 = 0.2; bD3 = 0.1; ) : s == 11 ? ( // GLASS CHOIR det = 0.007; fbase = 1300; famt = 0.4; fres = 0.08; aA = 0.7; aD = 1; aS = 0.9; aR = 1.8; fA = 0.8; fD = 1; fS = 0.8; form = 1; br_lvl = 0.12; vib = 4.8; vibd = 0.45; chor = 1; lvl = 0.1; ) : s == 12 ? ( // NYLON HAZE vamix = 0.55; det = 0.007; fbase = 600; famt = 0.6; fres = 0.1; aA = 1.4; aD = 1; aS = 0.9; aR = 2; fA = 1.5; fD = 2; fS = 0.7; chor = 0.8; lvl = 0.34; ks_lvl = 1.6; ks_T = 2.2; ks_br = 0.35; ks_pick = 0; ) : s == 13 ? ( // SYNTH BRASS det = 0.004; fbase = 280; famt = 2.8; fres = 0.15; aA = 0.03; aD = 0.3; aS = 0.85; aR = 0.25; fA = 0.09; fD = 0.55; fS = 0.45; chor = 0.35; lvl = 0.38; ) : s == 14 ? ( // CRYSTAL HARP vamix = 0.35; det = 0.006; fbase = 4000; famt = 0.2; fres = 0.05; aA = 0.5; aD = 1; aS = 0.8; aR = 1.8; fA = 0.5; fD = 1; fS = 0.8; chor = 1; lvl = 0.32; bl_lvl = 0.55; bR0 = 1; bR1 = 2.005; bR2 = 4.02; bR3 = 7.13; bA0 = 1; bA1 = 0.45; bA2 = 0.3; bA3 = 0.12; bD0 = 3; bD1 = 1.6; bD2 = 0.8; bD3 = 0.3; ) : s == 15 ? ( // SUB BASS: pure sine o1w = 1; o2l = 0; det = 0; fbase = 400; famt = 0.3; fres = 0; ktrk = 0.5; aA = 0.003; aD = 0.5; aS = 0.9; aR = 0.12; fA = 0.001; fD = 0.3; fS = 0.5; mono = 1; glide = 0.03; chor = 0; lvl = 0.9; ) : s == 16 ? ( // ACID BASS: resonant saw, snappy envelope, slides o2l = 0; det = 0; fbase = 180; famt = 3.6; fres = 0.82; ktrk = 0.4; fA = 0.001; fD = 0.18; fS = 0.05; aA = 0.002; aD = 0.4; aS = 0.8; aR = 0.08; mono = 1; glide = 0.06; chor = 0; lvl = 0.6; ) : s == 17 ? ( // ROUND BASS: saw + square + sub det = 0.004; o2w = 1; o2l = 0.7; subl = 0.6; fbase = 220; famt = 1.8; fres = 0.3; fA = 0.001; fD = 0.35; fS = 0.25; aA = 0.002; aD = 0.6; aS = 0.85; aR = 0.1; mono = 1; glide = 0.02; chor = 0; lvl = 0.5; ) : s == 18 ? ( // PLUCK BASS: short and punchy, polyphonic det = 0.003; o2l = 0.6; subl = 0.5; fbase = 160; famt = 3; fres = 0.25; fA = 0.001; fD = 0.12; fS = 0; aA = 0.001; aD = 0.35; aS = 0; aR = 0.1; chor = 0; lvl = 0.6; ) : s == 19 ? ( // HOLLOW BASS: sine + square o1w = 1; o2w = 1; o2l = 1; det = 0; fbase = 600; famt = 0.8; fres = 0.1; fA = 0.001; fD = 0.4; fS = 0.4; aA = 0.002; aD = 0.5; aS = 0.8; aR = 0.1; mono = 1; glide = 0.03; chor = 0; lvl = 0.55; ) : s == 20 ? ( // REESE BASS: wide detuned saws det = 0.018; o2l = 1; subl = 0.4; fbase = 350; famt = 0.5; fres = 0.2; fA = 0.01; fD = 1; fS = 0.8; aA = 0.005; aD = 1; aS = 0.95; aR = 0.15; mono = 1; glide = 0.03; chor = 0.2; lvl = 0.5; ) : s == 21 ? ( // NATIVE DANCE: a tempo-synced log-drum loop riding a dark resonant sweep det = 0.006; fbase = 300; famt = 1.2; fres = 0.55; ktrk = 0.4; aA = 0.4; aD = 1; aS = 0.9; aR = 1.5; fA = 2.5; fD = 3; fS = 0.6; flfo = 0.5; chor = 0.6; lvl = 0.26; vamix = 0.7; nd = 1; bl_lvl = 0.9; chf = 0.0; dl_mix = 0.25; dl_bt = 0.75; dl_fb = 0.4; ) : s == 22 ? ( // CALLIOPE LEAD: a pipe (sine + a little square an octave up), pitched breath, a short chiff, vibrato o1w = 1; o2w = 1; o2l = 0.22; det = 0; fbase = 2200; famt = 0.3; fres = 0.05; ktrk = 0.7; aA = 0.04; aD = 1; aS = 0.95; aR = 0.25; fA = 0.05; fD = 1; fS = 0.9; br_lvl = 0.1; brp = 1; chf = 0.12; vib = 5.6; vibd = 0.7; chor = 0.5; lvl = 0.42; dl_mix = 0.18; dl_bt = 0.5; dl_fb = 0.3; ) : s == 23 ? ( // SOUNDTRACK PAD: a chime over a slow, warm sweep, with echo det = 0.007; subl = 0.3; fbase = 500; famt = 1.4; fres = 0.18; aA = 1.2; aD = 1; aS = 0.9; aR = 2.6; fA = 3; fD = 3; fS = 0.5; flfo = 0.3; chor = 1; lvl = 0.28; bl_lvl = 0.45; bR0 = 2; bR1 = 5.03; bR2 = 8.1; bR3 = 11.7; bA0 = 1; bA1 = 0.4; bA2 = 0.25; bA3 = 0.12; bD0 = 2; bD1 = 1; bD2 = 0.5; bD3 = 0.3; dl_mix = 0.25; dl_bt = 1; dl_fb = 0.4; ) : s == 24 ? ( // SESSION PIANO: warm and even pn_hard = 0.55; pn_T = 1; pn_uni = 1; pn_knock = 1; chor = 0.25; lvl = 0.5; ) : s == 25 ? ( // CHORUS EP: the FM tine piano with tremolo and a deep chorus chor = 0.9; trem = 0.25; lvl = 1; ) : s == 26 ? ( // DARK VOX: a low, slow "ooh" choir det = 0.006; fbase = 900; famt = 0.4; fres = 0.08; aA = 0.9; aD = 1; aS = 0.95; aR = 1.6; fA = 1; fD = 1; fS = 0.8; form = 2; br_lvl = 0.06; vib = 4.6; vibd = 0.35; chor = 0.9; lvl = 0.13; ) : s == 27 ? ( // FANTASY VOX: a bright "aah" with a glassy chime on the front det = 0.007; fbase = 1800; famt = 0.5; fres = 0.08; aA = 0.5; aD = 1; aS = 0.9; aR = 1.8; fA = 0.6; fD = 1; fS = 0.8; form = 1; br_lvl = 0.08; vib = 5; vibd = 0.4; chor = 1; lvl = 0.11; bl_lvl = 0.35; bR0 = 2; bR1 = 4.01; bR2 = 6.02; bR3 = 8.97; bA0 = 1; bA1 = 0.45; bA2 = 0.3; bA3 = 0.15; bD0 = 1.6; bD1 = 0.9; bD2 = 0.5; bD3 = 0.25; ) : s == 28 ? ( // SPACED VOX: airy "eh" voices, slow filter drift, long echo det = 0.008; fbase = 1500; famt = 0.3; fres = 0.1; aA = 1.2; aD = 1; aS = 0.95; aR = 2.4; fA = 1.4; fD = 1; fS = 0.9; form = 3; br_lvl = 0.14; flfo = 0.4; vib = 4.4; vibd = 0.3; chor = 1.2; lvl = 0.11; dl_mix = 0.3; dl_bt = 1.5; dl_fb = 0.45; ) : s == 29 ? ( // VELO STAB: playing harder opens it right up det = 0.008; o2l = 1; subl = 0.3; fbase = 260; famt = 4; fres = 0.35; ktrk = 0.5; aA = 0.002; aD = 0.35; aS = 0; aR = 0.2; fA = 0.001; fD = 0.22; fS = 0; vf = 1; chor = 0.4; lvl = 0.5; ) : s == 30 ? ( // HOOVER: wide saws and pulses that scoop up into the note det = 0.022; o2w = 1; o2l = 0.8; subl = 0.5; fbase = 1400; famt = 1; fres = 0.15; aA = 0.005; aD = 1; aS = 0.95; aR = 0.3; fA = 0.01; fD = 0.6; fS = 0.6; pe_amt = -7; pe_t = 0.12; mono = 1; glide = 0.08; chor = 1.2; lvl = 0.36; ) : s == 31 ? ( // FAT STRINGS: thick saws into the ensemble det = 0.009; subl = 0.25; fbase = 2600; famt = 0.5; fres = 0.08; ktrk = 0.6; aA = 0.25; aD = 1; aS = 1; aR = 1; fA = 0.3; fD = 1; fS = 0.8; chor = 0.8; three = 1; lvl = 0.26; ) : s == 32 ? ( // ORCHESTRA HIT: a big octave stab that drops in pitch det = 0.01; o2w = 1; o2l = 0.8; subl = 0.9; fbase = 1800; famt = 2; fres = 0.1; aA = 0.002; aD = 0.32; aS = 0; aR = 0.25; fA = 0.001; fD = 0.25; fS = 0; pe_amt = 3; pe_t = 0.05; chf = 0.9; chor = 0.5; lvl = 0.5; bl_lvl = 0.4; bR0 = 1; bR1 = 2; bR2 = 3; bR3 = 4.02; bA0 = 1; bA1 = 0.7; bA2 = 0.5; bA3 = 0.3; bD0 = 0.35; bD1 = 0.25; bD2 = 0.18; bD3 = 0.12; ) : s == 33 ? ( // BRASS SECTION: swelling filter, a little rise into the note, delayed vibrato det = 0.006; o2l = 0.9; fbase = 330; famt = 2.6; fres = 0.12; aA = 0.06; aD = 0.6; aS = 0.85; aR = 0.3; fA = 0.12; fD = 0.8; fS = 0.55; pe_amt = -0.6; pe_t = 0.06; vib = 5.2; vibd = 0.3; vf = 0.5; chor = 0.4; lvl = 0.36; ) : s == 34 ? ( // DRAWBAR ORGAN: 888 with third-harmonic percussion, fast rotary org_perc = 0.5; chor = 0.7; crate = 6.2; lvl = 0.3; ) : s == 35 ? ( // PAN FLUTE: sine with its breath tuned to the note, a soft chiff, vibrato o1w = 1; o2l = 0; det = 0; fbase = 3000; famt = 0.3; fres = 0; aA = 0.08; aD = 1; aS = 0.9; aR = 0.35; fA = 0.1; fD = 1; fS = 0.9; br_lvl = 0.16; brp = 1; chf = 0.15; vib = 5.2; vibd = 0.5; chor = 0.4; lvl = 0.5; ) : s == 36 ? ( // HARP: a long, round pluck vamix = 0; aA = 0.001; aD = 0.2; aS = 0; aR = 0.6; chor = 0.35; lvl = 0.7; ks_lvl = 1; ks_T = 3.2; ks_br = 0.3; ks_pick = 0; ) : s == 37 ? ( // SQUARE LEAD: two squares an octave apart, glide o1w = 2; o2w = 1; o2l = 0.5; det = 0.003; fbase = 2400; famt = 0.8; fres = 0.15; ktrk = 0.6; aA = 0.005; aD = 0.5; aS = 0.9; aR = 0.2; fA = 0.005; fD = 0.5; fS = 0.7; vib = 5.5; vibd = 0.5; mono = 1; glide = 0.05; chor = 0.3; lvl = 0.3; dl_mix = 0.15; dl_bt = 0.75; dl_fb = 0.3; ) : s == 38 ? ( // BRIGHT PIANO: harder hammers, more shimmer pn_hard = 0.85; pn_T = 0.85; pn_uni = 1.6; pn_knock = 1.3; chor = 0.45; lvl = 0.42; ) : s == 39 ? ( // LA NYLON: a round pluck with a soft pick, over a quiet sine body that swells in o1w = 1; o2l = 0; det = 0; fbase = 900; famt = 0.3; fres = 0; aA = 0.35; aD = 2; aS = 0.5; aR = 0.6; fA = 0.3; fD = 1; fS = 0.8; vamix = 0.18; chf = 0.08; chor = 0.45; lvl = 0.6; ks_lvl = 1.1; ks_T = 2.6; ks_br = 0.32; ks_pick = 0; ) : s == 40 ? ( // LA STEEL: a bright steel-string pick with a shimmering synth body det = 0.004; o2l = 0.5; fbase = 1500; famt = 0.6; fres = 0.05; aA = 0.25; aD = 2; aS = 0.4; aR = 0.7; fA = 0.2; fD = 1.5; fS = 0.5; vamix = 0.12; chf = 0.14; chor = 0.7; lvl = 0.5; ks_lvl = 1; ks_T = 3.2; ks_br = 0.78; ks_pick = 0; ) : s == 41 ? ( // LA CLEAN: a chorused electric (pickup near the bridge), with echo o1w = 1; o2l = 0; det = 0; fbase = 1200; famt = 0.2; fres = 0; aA = 0.2; aD = 2; aS = 0.4; aR = 0.5; fA = 0.2; fD = 1; fS = 0.7; vamix = 0.1; chf = 0.06; chor = 1; lvl = 0.55; dl_mix = 0.2; dl_bt = 0.75; dl_fb = 0.3; ks_lvl = 1; ks_T = 2.4; ks_br = 0.55; ks_pick = 1; ) : s == 42 ? ( // LA HARMONICS: glassy string harmonics over a soft pluck, with echo vamix = 0; aA = 0.001; aD = 0.2; aS = 0; aR = 0.8; chor = 0.7; lvl = 0.55; dl_mix = 0.25; dl_bt = 0.75; dl_fb = 0.4; ks_lvl = 0.5; ks_T = 1.8; ks_br = 0.45; ks_pick = 0; bl_lvl = 0.55; bR0 = 2; bR1 = 3; bR2 = 4; bR3 = 6; bA0 = 1; bA1 = 0.45; bA2 = 0.3; bA3 = 0.12; bD0 = 2.2; bD1 = 1.4; bD2 = 0.9; bD3 = 0.4; ); // LA retunes: closer to the classic layered presets s == 9 ? ( dl_mix = 0.3; dl_bt = 0.75; dl_fb = 0.4; ); // STACCATO GLASS: its echo s == 10 ? ( ks_br = 0.65; bl_lvl = 0.3; dl_mix = 0.12; dl_bt = 0.5; dl_fb = 0.25; ); // PIZZ FLOW: brighter pluck s == 12 ? ( dl_mix = 0.15; dl_bt = 1; dl_fb = 0.3; ); // NYLON ATMOS // the choir's vowels form == 1 ? ( fA1.svf_set(730, 5); fA2.svf_set(1090, 7); fA3.svf_set(2440, 9); ) : form == 2 ? ( fA1.svf_set(320, 5); fA2.svf_set(800, 6); fA3.svf_set(2300, 8); ) : form == 3 ? ( fA1.svf_set(530, 5); fA2.svf_set(1840, 7); fA3.svf_set(2480, 9); ); ); // ---------- plucked string: set up and run (clav and the pluck layers) ---------- function ks_setup(v, b, f0, vg, h, Ts, bright, pick) local(L, x, j, rr, x2_) ( L = srate / f0; b[F_KL] = L; b[F_KW] = floor(L); b[F_KLP] = 0; b[F_KAP] = 0; b[F_KHP] = 0; b[F_KX] = 0; b[F_O3] = 1; b[F_KG] = 10 ^ (-3 / (Ts * f0)); b[F_KPO] = pick ? max(floor(L * 0.13), 1) : 0; x = 0; x2_ = 0; j = 0; loop(min(ceil(L) + 2, KSL), rr = rand(2) - 1; x += (rr - x) * (bright * (0.3 + 0.7 * h)); // softer pluck when played gently x2_ += (x - x2_) * 0.6; KSB[v * KSL + j] = x2_ * vg * 0.45 * sin($pi * min(j / L, 1)) * (j < L * 0.5 ? 1 : 0.7); j += 1; ); ); function ks_tick(av, b, pick, bite) local(lc_, L, Li, fr, w_, ofs, rp, sv, ac, ap, lpv, gk, pq, y) ( lc_ = 0.72 + 0.26 * tone; // loop brightness L = b[F_KL] / pdrift - (1 - lc_) / lc_; // minus the loop filter delay Li = floor(L); fr = L - Li; fr < 0.1 ? ( Li -= 1; fr += 1; ); w_ = b[F_KW]; ofs = av * KSL; rp = w_ - Li; rp < 0 ? rp += KSL; sv = KSB[ofs + rp]; ac = (1 - fr) / (1 + fr); // fractional delay (first-order allpass) ap = ac * sv + b[F_KX] - ac * b[F_KAP]; b[F_KX] = sv; b[F_KAP] = ap; lpv = b[F_KLP] + (ap - b[F_KLP]) * lc_; b[F_KLP] = lpv; gk = held ? b[F_KG] : b[F_KG] * ks_rd; // the damper: a fast stop when the key lifts (RELEASE) KSB[ofs + w_] = lpv * gk; b[F_KW] = (w_ + 1) % KSL; pick ? ( pq = w_ - b[F_KPO]; pq < 0 ? pq += KSL; y = sv - KSB[ofs + pq]; ) : y = sv; b[F_KHP] += (y - b[F_KHP]) * 0.02; y -= b[F_KHP]; y = bite ? tanh_(y * 1.5) * 3.5 : y * 2.2; b[F_O3] = b[F_O3] * 0.9995 + abs(y) * 0.0005; // level tracker y; ); // bell partials (glockenspiel and the bell layers) function bell_set(b, f0, vg, h, ratio, amp, dk, k) local(w) ( w = 2 * $pi * min(f0 * ratio, srate * 0.45) / srate; b[F_MS + k] = 0; b[F_MC + k] = 1; b[F_MWS + k] = sin(w); b[F_MWC + k] = cos(w); b[F_MA + k] = f0 * ratio < srate * 0.45 ? amp : 0; b[F_MD + k] = tc(dk); ); function bell_tick(b, rel) local(k, s_, y) ( k = 0; y = 0; bell_amp = 0; loop(4, s_ = b[F_MS + k] * b[F_MWC + k] + b[F_MC + k] * b[F_MWS + k]; b[F_MC + k] = b[F_MC + k] * b[F_MWC + k] - b[F_MS + k] * b[F_MWS + k]; b[F_MS + k] = s_; b[F_MA + k] *= b[F_MD + k] * rel; y += s_ * b[F_MA + k]; bell_amp += b[F_MA + k]; k += 1; ); y; ); // 16-partial bank (synthetic piano, drawbar organ) function pn_set(b, k, f, amp, T) local(w) ( w = 2 * $pi * min(f, srate * 0.45) / srate; b[P_MS + k] = 0; b[P_MC + k] = 1; b[P_WS + k] = sin(w); b[P_WC + k] = cos(w); b[P_MA + k] = f < srate * 0.45 ? amp : 0; b[P_MD + k] = T > 0 ? tc(T) : 1; ); function pn_tick(b, rel) local(k, s_, y) ( k = 0; y = 0; pn_amp = 0; loop(16, b[P_MA + k] > 0.00001 ? ( s_ = b[P_MS + k] * b[P_WC + k] + b[P_MC + k] * b[P_WS + k]; b[P_MC + k] = b[P_MC + k] * b[P_WC + k] - b[P_MS + k] * b[P_WS + k]; b[P_MS + k] = s_; b[P_MA + k] *= b[P_MD + k] * rel; y += s_ * b[P_MA + k]; pn_amp += b[P_MA + k]; ); k += 1; ); y; ); // the oscillator pairs drift in amplitude after many cycles: renormalise once a block function pn_norm(b) local(k, m) ( k = 0; loop(16, m = sqrt(sqr(b[P_MS + k]) + sqr(b[P_MC + k])); m > 0 ? ( b[P_MS + k] /= m; b[P_MC + k] /= m; ); k += 1; ); ); // ---------- voices ---------- function vfree() local(v, best, ba) ( best = -1; v = 0; loop(NV, best < 0 && !VB[v * VS + F_ACT] ? best = v; v += 1; ); best < 0 ? ( ba = 1000000000; v = 0; loop(NV, (VB[v * VS + F_AGE] + (VB[v * VS + F_G] ? 100000000 : 0)) < ba ? ( ba = VB[v * VS + F_AGE] + (VB[v * VS + F_G] ? 100000000 : 0); best = v; ); v += 1; ); ); best; ); function pg(i, a, b, c, d, e, f, g, h, k, l, m, n, o, p, q, r) local(z) ( z = PG + i*16; z[0] = a; z[1] = b; z[2] = c; z[3] = d; z[4] = e; z[5] = f; z[6] = g; z[7] = h; z[8] = k; z[9] = l; z[10] = m; z[11] = n; z[12] = o; z[13] = p; z[14] = q; z[15] = r; ); // ---------- the GM voices (type, octave, cutoff, resonance, filter env, key track, A, D, S, R, // detune 2nd osc, p1, p2, p3, vibrato, level) and their names ---------- pg(0, 4, 0, 5000, 0.1, 0.5, 0.5, 1, 3000, 0.1, 600, 0, 1, 1.6, 400, 0, 0.5); strcpy(200 + 0, "E.Piano1"); pg(1, 4, 0, 8000, 0.1, 1.5, 0.5, 1, 2500, 0.05, 500, 0, 14, 1.2, 300, 0, 0.5); strcpy(200 + 1, "E.Piano2"); pg(2, 5, 0, 6000, 0.2, 1.5, 0.5, 1, 1500, 0, 300, 0, 0.5, 0, 0.996, 0, 4.5); strcpy(200 + 2, "Harpsi."); pg(3, 3, 0, 1800, 0.4, 2, 0.5, 1, 500, 0, 100, 0, 0.15, 0, 300, 0, 0); strcpy(200 + 3, "Clavi."); pg(4, 4, 12, 9000, 0.1, 1.5, 0.5, 1, 1500, 0, 500, 0, 3.5, 1.5, 200, 0, 1); strcpy(200 + 4, "Celesta"); pg(5, 4, 12, 9000, 0.1, 1.5, 0.5, 1, 1200, 0, 600, 0, 5, 1.2, 150, 0, 1.5); strcpy(200 + 5, "MusicBox"); pg(6, 4, 0, 8000, 0.1, 1.5, 0.5, 1, 3000, 0, 900, 0, 4, 0.8, 300, 0, -0.5); strcpy(200 + 6, "Vibes"); pg(7, 4, 0, 6000, 0.1, 1.5, 0.5, 1, 500, 0, 200, 0, 4, 1.5, 60, 0, 4.5); strcpy(200 + 7, "Marimba"); pg(8, 4, 12, 9000, 0.1, 1.5, 0.5, 1, 350, 0, 150, 0, 3, 2, 40, 0, 4.5); strcpy(200 + 8, "Xylophon"); pg(9, 4, 0, 9000, 0.1, 1.5, 0.5, 1, 5000, 0, 1500, 0, 3.5, 2.5, 900, 0, -3.5); strcpy(200 + 9, "TubulBel"); pg(10, 5, 0, 7000, 0.1, 1.5, 0.5, 1, 2000, 0, 500, 0, 0.5, 0, 0.998, 0, 4.5); strcpy(200 + 10, "Dulcimer"); pg(11, 5, 0, 3000, 0.1, 0.5, 0.5, 1, 3000, 0, 250, 0, 0.5, 0, 0.995, 0, 7.5); strcpy(200 + 11, "NylonGtr"); pg(12, 5, 0, 5000, 0.1, 0.5, 0.5, 1, 3000, 0, 250, 0, 0.5, 0, 0.997, 0, 6); strcpy(200 + 12, "SteelGtr"); pg(13, 5, 0, 5000, 0.1, 0.5, 0.5, 1, 300, 0, 250, 0, 0.5, 0, 0.985, 0, 7); strcpy(200 + 13, "Mute.Gtr"); pg(14, 8, 0, 2500, 0.3, 1, 0.5, 2, 2000, 0.6, 200, 6, 0.5, 0, 300, 0, 2); strcpy(200 + 14, "Ovrdrive"); pg(15, 1, -12, 1200, 0.2, 0.5, 0.5, 1, 1500, 0.2, 150, 0, 0.5, 0, 300, 0, 1.5); strcpy(200 + 15, "Aco.Bass"); pg(16, 4, -12, 1500, 0.2, 1.5, 0.5, 1, 800, 0.5, 150, 0, 1, 1.2, 300, 0, 0.5); strcpy(200 + 16, "FngrBass"); pg(17, 2, -12, 500, 0.6, 3, 0.5, 1, 300, 0.3, 150, 0, 0.5, 0, 300, 0, 5.5); strcpy(200 + 17, "SynBass1"); pg(18, 3, -12, 700, 0.5, 2.5, 0.5, 1, 350, 0.4, 150, 0, 0.3, 0, 300, 0, -0.5); strcpy(200 + 18, "SynBass2"); pg(19, 2, -24, 500, 0.15, 2.2, 0.6, 40, 600, 0.75, 180, 0, 0.5, 0, 300, 5, 0); strcpy(200 + 19, "SynBass3"); pg(20, 8, 0, 3500, 0.05, 0.3, 0.5, 80, 500, 1, 500, 4, 0.5, 0, 300, 14, 0.5); strcpy(200 + 20, "Violin"); pg(21, 8, 0, 2800, 0.05, 0.3, 0.5, 90, 500, 1, 500, 4, 0.5, 0, 300, 12, 1); strcpy(200 + 21, "Viola"); pg(22, 8, -12, 2200, 0.05, 0.3, 0.5, 90, 500, 1, 500, 4, 0.5, 0, 300, 10, -2); strcpy(200 + 22, "Cello"); pg(23, 8, 0, 3500, 0.05, 0.3, 0.5, 180, 500, 1, 500, 7, 0.5, 0, 300, 6, 2.5); strcpy(200 + 23, "Strings1"); pg(24, 8, 0, 4500, 0.05, 0.3, 0.5, 150, 500, 1, 500, 12, 0.5, 0, 300, 0, 1.5); strcpy(200 + 24, "Syn Str1"); pg(25, 3, 0, 1300, 0.2, 1, 0.5, 30, 400, 0.8, 120, 0, 0.5, 0, 300, 8, -3.5); strcpy(200 + 25, "SynReed"); pg(26, 0, 12, 6000, 0, 0, 0.5, 60, 300, 0.9, 150, 0, 0.5, 0, 300, 10, -3.5); strcpy(200 + 26, "Whistle"); pg(27, 1, 0, 6000, 0, 0, 0.5, 60, 300, 0.9, 150, 0, 0.5, 0.05, 300, 4, 0); strcpy(200 + 27, "Ocarina"); pg(28, 3, 0, 4000, 0.25, 1, 0.5, 3, 500, 0.8, 150, 0, 0.5, 0, 300, 8, -4.5); strcpy(200 + 28, "SquareLd"); pg(29, 2, 0, 4000, 0.25, 1, 0.5, 3, 500, 0.8, 150, 6, 0.5, 0, 300, 8, 1.5); strcpy(200 + 29, "Saw.Lead"); pg(30, 1, 0, 4000, 0.25, 1, 0.5, 3, 500, 0.8, 150, 0, 0.5, 0.1, 300, 8, 0.5); strcpy(200 + 30, "CaliopLd"); pg(31, 3, 0, 4000, 0.25, 2, 0.5, 3, 200, 0.6, 150, 0, 0.3, 0, 300, 8, -1.5); strcpy(200 + 31, "Chiff Ld"); pg(32, 8, 0, 3000, 0.5, 1, 0.5, 3, 500, 0.8, 150, 10, 0.5, 0, 300, 8, 1.5); strcpy(200 + 32, "CharanLd"); pg(33, 1, 0, 1800, 0.35, 0.2, 0.5, 40, 500, 1, 600, 8, 0.5, 0, 300, 10, 1.5); strcpy(200 + 33, "Voice Ld"); pg(34, 2, 0, 4000, 0.25, 1, 0.5, 3, 500, 0.8, 150, 702, 0.5, 0, 300, 8, -1); strcpy(200 + 34, "Fifth Ld"); pg(35, 2, -12, 1500, 0.4, 1, 0.5, 3, 500, 0.8, 150, 1200, 0.5, 0, 300, 8, -1); strcpy(200 + 35, "Bass &Ld"); pg(36, 8, 0, 2400, 0.15, 1.5, 0.5, 40, 1500, 1, 1500, 9, 0.5, 0, 300, 0, 0.5); strcpy(200 + 36, "PolySyPd"); pg(37, 1, 0, 1300, 0.35, 0.2, 0.5, 600, 500, 1, 1500, 8, 0.5, 0, 300, 10, 5.5); strcpy(200 + 37, "ChoirPad"); pg(38, 3, 0, 1500, 0.15, 0.5, 0.5, 800, 1500, 1, 1500, 9, 0.4, 0, 300, 0, 4); strcpy(200 + 38, "BowedPad"); pg(39, 4, 0, 6000, 0.15, 0.5, 0.5, 600, 1500, 1, 1500, 9, 3.5, 1.5, 3000, 0, 0); strcpy(200 + 39, "MetalPad"); pg(40, 8, 0, 900, 0.6, 3, 0.5, 1500, 4000, 0.4, 1500, 9, 0.5, 0, 300, 0, 12); strcpy(200 + 40, "SweepPad"); pg(41, 5, 0, 5000, 0.1, 1.5, 0.5, 1, 2500, 0, 400, 0, 0.5, 0, 0.996, 0, 4.5); strcpy(200 + 41, "Koto"); pg(42, 4, 0, 6000, 0.1, 1.5, 0.5, 1, 900, 0, 300, 0, 4.5, 1.2, 80, 0, 4); strcpy(200 + 42, "Kalimba"); pg(43, 4, 12, 9000, 0.1, 1.5, 0.5, 1, 1500, 0, 500, 0, 5.4, 1.5, 400, 0, 1.5); strcpy(200 + 43, "TnklBell"); pg(44, 4, 12, 6000, 0.1, 1.5, 0.5, 1, 400, 0, 200, 0, 2.3, 2, 80, 0, 5.5); strcpy(200 + 44, "Agogo"); pg(45, 4, 12, 5000, 0.1, 1.5, 0.5, 1, 120, 0, 80, 0, 3.1, 3, 20, 0, 7); strcpy(200 + 45, "WoodBlok"); function ms2c(ms) ( exp(-1/(max(ms, 0.1)*0.001*srate)); ); function dset(b, f, pe, pt, td, ta, na, nd_, nf, hp, lv) local(g, k) ( b[42] = f; b[43] = pe; b[44] = ms2c(pt); b[45] = ms2c(td); b[8] = ta; b[46] = na; b[47] = ms2c(nd_); b[48] = hp; g = tan($pi*min(nf, srate*0.45)/srate); k = hp ? 1.4 : 0.9; b[20] = k; b[50] = 1/(1 + g*(g + k)); b[51] = g*b[50]; b[52] = g*b[51]; b[38] = 1; b[39] = 1; b[40] = 1; b[62] *= lv; ); function drum_setup(b, n) ( n == 35 || n == 36 ? dset(b, 50, 2.2, 35, 320, 1, 0.08, 15, 3000, 0, 1.1) : n == 37 ? dset(b, 420, 0.3, 5, 40, 0.6, 0.4, 30, 2500, 0, 0.7) : n == 38 ? dset(b, 190, 0.5, 15, 110, 0.5, 0.75, 170, 3500, 1, 0.9) : n == 40 ? dset(b, 210, 0.5, 12, 90, 0.4, 0.85, 150, 5000, 1, 0.9) : n == 39 ? dset(b, 0, 0, 1, 1, 0, 1, 160, 1200, 0, 1) : n == 42 ? dset(b, 0, 0, 1, 1, 0, 0.6, 45, 8000, 1, 0.6) : n == 44 ? dset(b, 0, 0, 1, 1, 0, 0.55, 65, 7500, 1, 0.5) : n == 46 ? dset(b, 0, 0, 1, 1, 0, 0.55, 380, 7500, 1, 0.55) : n == 41 || n == 43 || n == 45 || n == 47 || n == 48 || n == 50 ? dset(b, n == 41 ? 80 : n == 43 ? 95 : n == 45 ? 110 : n == 47 ? 135 : n == 48 ? 155 : 180, 0.5, 60, 350, 1, 0.08, 40, 2000, 0, 0.9) : n == 49 || n == 57 || n == 52 ? dset(b, 0, 0, 1, 1, 0, 0.5, 1300, 5500, 1, 0.55) : n == 55 ? dset(b, 0, 0, 1, 1, 0, 0.5, 600, 6500, 1, 0.5) : n == 51 || n == 59 ? dset(b, 3100, 0, 1, 900, 0.12, 0.3, 1100, 7000, 1, 0.55) : n == 53 ? dset(b, 2300, 0, 1, 700, 0.5, 0.15, 600, 6000, 1, 0.55) : n == 54 ? dset(b, 0, 0, 1, 1, 0, 0.5, 160, 9000, 1, 0.5) : n == 56 ? dset(b, 560, 0, 1, 250, 0.6, 0.1, 80, 800, 0, 0.6) : n >= 60 && n <= 64 ? dset(b, n == 60 ? 300 : n == 61 ? 220 : n == 62 ? 200 : n == 63 ? 170 : 140, 0.3, 20, 180, 1, 0.1, 30, 2000, 0, 0.8) : n == 69 || n == 70 ? dset(b, 0, 0, 1, 1, 0, 0.45, 70, 7000, 1, 0.45) : n == 75 ? dset(b, 2500, 0, 1, 60, 0.8, 0, 1, 1000, 0, 0.6) : n == 76 || n == 77 ? dset(b, n == 76 ? 1700 : 1300, 0, 1, 70, 0.8, 0.05, 20, 2000, 0, 0.6) : dset(b, 600, 0.2, 10, 80, 0.4, 0.4, 60, 3000, 0, 0.5); ); // one GM voice or drum on its own block (pb = the voice block + 100): set up at the key // the GM voices' amp and filter envelopes, from the patch and the EDIT knobs (at note-on and while a note plays) function p_env(pb, q) ( pb[28] = 1/max(1, max(q[6]*atk_k + max(0, atk_k - 1)*150, 1)*0.001*srate); pb[29] = 1 - exp(-4.6/(max(q[7]*dec_k, 1)*0.001*srate)); pb[30] = min(max(q[8] + sus_o, 0), 1); pb[31] = 1 - exp(-4.6/(max(q[9]*rel_k, 1)*0.001*srate)); pb[5] = 1/max(1, max(q[6]*fatk_k + max(0, fatk_k - 1)*150, 1)*0.001*srate); pb[6] = 1 - exp(-4.6/(max(q[7]*fdec_k, 1)*0.001*srate)); pb[7] = min(max(q[8] + fsus_o, 0), 1); pb[9] = 1 - exp(-4.6/(max(q[9]*frel_k, 1)*0.001*srate)); ); function p_on(v, b, n, vg) local(pb, q, at, de, re, f, len, j, lp, k) ( pb = b + 100; memset(pb, 0, 64); pb[3] = n; pb[37] = (rand(2) - 1)*drift*3; // drift: a tiny tuning scatter per note eng == 7 ? ( n == 42 || n == 44 ? ( k = 0; loop(NV, VB[k*VS + F_ACT] && VB[k*VS + 103] == 46 ? ( VB[k*VS + F_ACT] = 0; VB[k*VS + 100] = 0; ); k += 1; ); ); // hats choke the open hat pb[49] = -1; pb[62] = vg*vg*1.6; pb[0] = 2; pb[1] = 1; drum_setup(pb, n); ) : ( q = PG + gprog*16; pb[49] = q[0]; pb[10] = n; p_env(pb, q); // the filter envelope starts as the patch's amp shape pb[55] = q[10] > 0 ? 2^(q[10]/1200) : 0; pb[56] = q[11]; pb[57] = q[12]; pb[58] = q[13]; pb[59] = q[4]; pb[60] = q[5]; pb[61] = min(max(q[2]*2^(filt_oct + tone_oct), 30), srate*0.45); pb[20] = 2*(1 - min(max(q[3] + reso*(0.95 - q[3]), 0), 0.95)); pb[62] = vg*10^(q[15]/20)*0.5; pb[63] = q[14]; pb[54] = q[12]; pb[53] = q[0] == 4 ? exp(-1/(max(q[13], 5)*0.001*srate)) : 1; pb[16] = q[12]; pb[0] = 1; pb[1] = 0; pb[24] = 0; pb[22] = rand(1); pb[4] = 1; pb[2] = 0; q[0] == 5 ? ( // pluck: fill the line with a noise burst f = 440*2^((n + q[1] - 69)/12); len = min(max(floor(srate/f), 2), 4090); pb[26] = len; pb[25] = 0; lp = 0; j = 0; loop(len, lp += (rand(2) - 1 - lp)*min(1, q[2]/8000 + 0.2); KSB[v*KSL + j] = lp*2; j += 1; ); ); ); ); // control rate (every 32 samples): pitch, vibrato, mod wheel, filter function p_ctl(pb) local(q, vib, st, f, oct, g, k) ( q = PG + gprog*16; p_env(pb, q); pb[22] += 5.5*32/srate; pb[22] -= floor(pb[22]); vib = sin(2*$pi*pb[22]); st = pb[10] + q[1] + (vib*(pb[63] + modw*50) + pb[37])/100; f = 440*2^((st - 69)/12)*tune*pdrift; pb[11] = min(f/srate, 0.45); pb[12] = pb[55] > 0 ? min(pb[11]*pb[55], 0.45) : 0; oct = (pb[59]*fam_k + max(0, fam_k - 1)*1.5)*(pb[2] - 1) + pb[60]*(pb[10] - 60)/12 + ins_cut; f = min(max(pb[61]*2^oct, 30), srate*0.45); g = tan($pi*f/srate); k = pb[20]; pb[50] = 1/(1 + g*(g + k)); pb[51] = g*pb[50]; pb[52] = g*pb[51]; ); // one sample function p_run(v, pb, held) local(t, y, ph, s, p2, nz, v1, v2, v3, k, a1, a2, a3, i0, i1, o) ( y = 0; pb[49] < 0 ? ( // drum pb[38] *= pb[44]; pb[39] *= pb[45]; pb[40] *= pb[47]; pb[42] > 0 ? ( pb[13] += pb[42]*(1 + pb[43]*pb[38])/srate; pb[13] -= floor(pb[13]); y = sin(2*$pi*pb[13])*pb[39]*pb[8]; ); pb[46] > 0 ? ( nz = rand(2) - 1; k = pb[20]; a1 = pb[50]; a2 = pb[51]; a3 = pb[52]; v3 = nz - pb[18]; v1 = a1*pb[17] + a2*v3; v2 = pb[18] + a2*pb[17] + a3*v3; pb[17] = 2*v1 - pb[17]; pb[18] = 2*v2 - pb[18]; y += (pb[48] ? nz - k*v1 - v2 : k*v1)*pb[40]*pb[46]; ); pb[39] < 0.0001 && pb[40] < 0.0001 ? pb[0] = 0; y *= pb[62]*0.9; ) : ( !held && pb[0] > 0 && pb[0] < 3 ? ( pb[0] = 3; pb[4] = 3; ); pb[4] == 1 ? ( pb[2] += pb[5]; pb[2] >= 1 ? ( pb[2] = 1; pb[4] = 2; ); ) : pb[4] == 2 ? ( pb[2] += (pb[7] - pb[2])*pb[6]; ) : ( pb[2] += (0 - pb[2])*pb[9]; ); pb[0] == 1 ? ( pb[1] += pb[28]; pb[1] >= 1 ? ( pb[1] = 1; pb[0] = 2; ); ) : pb[0] == 2 ? ( pb[1] += (pb[30] - pb[1])*pb[29]; ) : ( pb[1] += (0 - pb[1])*pb[31]; pb[1] < 0.0001 ? pb[0] = 0; ); (pb[24] -= 1) <= 0 ? ( pb[24] = 32; p_ctl(pb); ); t = pb[49]; pb[13] += pb[11]; pb[13] -= floor(pb[13]); ph = pb[13]; t == 0 ? ( y = sin(2*$pi*ph); pb[57] > 0 ? ( pb[27] += (rand(2) - 1 - pb[27])*0.3; y += pb[57]*pb[27]*2; ); ) : t == 1 ? ( y = 1 - 4*abs(ph - 0.5); pb[12] > 0 ? ( pb[14] += pb[12]; pb[14] -= floor(pb[14]); y = (y + 1 - 4*abs(pb[14] - 0.5))*0.6; ); ) : t == 2 || t == 8 ? ( y = 2*ph - 1 - vo_blep(ph, pb[11]); pb[12] > 0 ? ( pb[14] += pb[12]; pb[14] -= floor(pb[14]); y = (y + 2*pb[14] - 1 - vo_blep(pb[14], pb[12]))*0.6; ); ) : t == 3 ? ( p2 = ph + 1 - pb[56]; p2 -= floor(p2); y = (2*ph - 1 - vo_blep(ph, pb[11])) - (2*p2 - 1 - vo_blep(p2, pb[11])); pb[12] > 0 ? ( pb[14] += pb[12]; pb[14] -= floor(pb[14]); p2 = pb[14] + 1 - pb[56]; p2 -= floor(p2); y = (y + (2*pb[14] - 1 - vo_blep(pb[14], pb[12])) - (2*p2 - 1 - vo_blep(p2, pb[12])))*0.6; ); ) : t == 4 ? ( pb[15] += pb[11]*pb[56]; pb[15] -= floor(pb[15]); pb[16] = pb[16]*pb[53] + pb[54]*0.15*(1 - pb[53]); // the index falls towards 15 % of its start y = sin(2*$pi*ph + pb[16]*sin(2*$pi*pb[15])); ) : t == 5 ? ( o = KSB + v*KSL; i0 = pb[25]; i1 = i0 + 1; i1 >= pb[26] ? i1 = 0; y = o[i0]; o[i0] = (o[i0] + o[i1])*0.5*pb[58]; pb[25] = i1; ) : t == 6 ? ( y = rand(2) - 1; ) : t == 7 ? ( y = (sin(2*$pi*ph) + pb[56]*sin(4*$pi*ph) + pb[57]*sin(6*$pi*ph) + 0.35*sin(8*$pi*ph))*0.5; ); // 12 dB state-variable low-pass a1 = pb[50]; a2 = pb[51]; a3 = pb[52]; v3 = y - pb[18]; v1 = a1*pb[17] + a2*v3; v2 = pb[18] + a2*pb[17] + a3*v3; pb[17] = 2*v1 - pb[17]; pb[18] = 2*v2 - pb[18]; y = v2*pb[1]*pb[62]; ); y; ); function note_on(n, vel) local(v, b, f0, vg, h, Tn, j, k, L, x, rr, ratio, amp, dk, w, was, hd, Bc) ( f0 = 440 * 2 ^ ((n - 69) / 12) * tune; vg = (1 - sens) + sens * (vel / 127) ^ 1.3; h = vel / 127; mono && eng == 0 ? ( v = 0; // mono: always voice 0, glide from the last note b = VB; b[F_DCF] = 1; !b[F_ACT] ? ( b[F_PY] = 0; b[F_PY2] = 0; b[F_DCO] = 0; ); b[F_ATK] = 1; mono_n >= 0 && b[F_ACT] && b[F_AE] > 0.01 ? ( b[F_F0] = f0; b[F_G] = 1; b[F_N] = n; b[F_VEL] = vg; mono_n = n; ) : ( was = b[F_ACT]; // still ringing: rise from where it is b[F_N] = n; b[F_G] = 1; b[F_S] = 0; b[F_ACT] = 1; b[F_VEL] = vg; b[F_F0] = f0; mono_f = f0; b[F_DT] = 1; b[F_VT] = 0; !was ? ( b[F_AE] = 0; b[F_FE] = 0; ); b[F_AST] = 0; b[F_FST] = 0; mono_n = n; ); ) : ( // re-strike the same key on the same voice, else a free / old one v = -1; k = 0; loop(NV, VB[k * VS + F_N] == n && VB[k * VS + F_ACT] ? v = k; k += 1; ); v < 0 ? v = vfree(); b = VB + v * VS; age += 1; b[F_AGE] = age; was = b[F_ACT]; // re-struck / reused while still sounding? b[F_DCF] = 1; !was ? ( b[F_PY] = 0; b[F_PY2] = 0; b[F_DCO] = 0; ); b[F_ATK] = eng == 0 && ks_lvl == 0 && bl_lvl == 0 ? 1 : 0; // struck / plucked sounds get a short fade-in b[F_N] = n; b[F_G] = 1; b[F_S] = 0; b[F_ACT] = 1; b[F_VEL] = vg; b[F_F0] = f0; b[F_DT] = ins_note_detune(); // each note slightly out (GFX drift) b[F_E1] = (rand(2) - 1) * drift * 0.35; // ... and slightly brighter / darker b[F_AST] = 0; b[F_FST] = 0; b[F_VT] = 0; !was ? b[F_FE] = 0; eng >= 6 ? ( // the GM voices and the drum kit (the Pocket 70 engine) p_on(v, b, n, vg); b[F_ATK] = eng == 7 ? 1 : 0; ) : eng == 0 ? ( // a sounding voice keeps its oscillators and rises from where it is; a fresh one starts clean !was ? ( b[F_P1] = rand(1); b[F_P2] = rand(1); b[F_P3] = rand(1); b[F_AE] = 0; b[F_O1] = 0; b[F_O2] = 0; b[F_O3] = 0; ); // attack / extra layers Tn = 2 ^ (-(n - 72) / 24) * dec_k; k = 0; loop(4, b[F_MA + k] = 0; k += 1; ); bl_lvl > 0 && !nd ? ( bell_set(b, f0, vg, h, bR0, vg * bl_lvl * bA0, bD0 * Tn, 0); bell_set(b, f0, vg, h, bR1, vg * bl_lvl * bA1 * (0.5 + h), bD1 * Tn, 1); bell_set(b, f0, vg, h, bR2, vg * bl_lvl * bA2 * (0.4 + h), bD2 * Tn, 2); bell_set(b, f0, vg, h, bR3, vg * bl_lvl * bA3 * (0.3 + h), bD3 * Tn, 3); ); ks_lvl > 0 ? ks_setup(v, b, f0, vg * ks_lvl, h, ks_T * 2 ^ (-(n - 60) / 24) * dec_k, ks_br, ks_pick); b[F_CLK] = chf * vg; b[F_PE] = pe_amt; ) : eng == 4 ? ( // synthetic piano: stretched partials, two strings each (a quick prompt string and a slower, detuned // after-ring one); velocity sets the hammer: brightness, loudness, knock and how fast the top fades Tn = 7 * pn_T * 2 ^ (-(n - 40) / 17) * dec_k; hd = min(max(pn_hard * (0.15 + 1.15 * h ^ 1.2) + (tone - 0.5) * 0.5, 0.05), 1.15); vg = (1 - min(sens * 1.3, 1)) + min(sens * 1.3, 1) * h * h; // a wider dynamic range than the synths Bc = 0.00025 * 2 ^ ((n - 60) / 20); k = 0; loop(8, j = k + 1; ratio = j * sqrt(1 + Bc * j * j); amp = vg * j ^ -0.85 * hd ^ ((j - 1) * 0.75) * (0.35 + 0.65 * abs(sin($pi * j * 0.13)) ); dk = Tn / (1 + 0.45 * (j - 1) * (0.6 + 0.8 * h)); pn_set(b, k * 2, f0 * ratio, amp * 0.72, dk * 0.42); pn_set(b, k * 2 + 1, f0 * ratio * 2 ^ ((0.9 + 0.5 * k) * pn_uni / 1200), amp * 0.38, dk * 1.5); k += 1; ); b[F_CLK] = pn_knock * (0.05 + 0.3 * h * h) * vg; // the hammer's knock b[F_HN] = 0; b[F_HL] = 0; b[F_AE] = 1; ) : eng == 5 ? ( // drawbar organ: 16' 8' 5 1/3' 4' + a little 2 2/3' and 2', third-harmonic percussion on fresh chords k = 0; loop(9, ratio = k == 0 ? 0.5 : k == 1 ? 1 : k == 2 ? 1.5 : k == 3 ? 2 : k == 4 ? 3 : k == 5 ? 4 : k == 6 ? 5 : k == 7 ? 6 : 8; amp = k == 0 ? 0.8 : k == 1 ? 0.8 : k == 2 ? 0.8 : k == 3 ? 0.45 : k == 4 ? 0.25 : k == 5 ? 0.2 : 0.06; pn_set(b, k, f0 * ratio, amp * vg * 0.5, 0); k += 1; ); pn_set(b, 9, f0 * 3, org_perc * (nact == 0 ? 1 : 0.3) * vg * 0.6, 0.35); b[F_CLK] = 0.15 * vg; // key click b[F_AE] = 1; b[F_HN] = 0; b[F_HL] = 0; ) : eng == 1 ? ( // FM e-piano: carriers C1 (body) and C3 (tine), modulators M2 (ratio 1) and M4 (ratio 14) !was ? ( b[F_O1] = 0; b[F_O2] = 0; b[F_O3] = 0; b[F_O4] = 0; ); Tn = 4.5 * 2 ^ (-(n - 48) / 20); b[F_E1] = vg; b[F_E2] = 0.9 + 1.6 * h; b[F_E3] = vg * 0.55; b[F_E4] = 0.6 + 2.2 * h * h; b[F_MD] = tc(Tn * dec_k); b[F_MD + 1] = tc(Tn * 0.35 * dec_k); b[F_MD + 2] = tc(Tn * 0.4 * dec_k); b[F_MD + 3] = tc(0.09 + 0.05 * (1 - h)); b[F_AE] = 1; ) : eng == 2 ? ( // clav: a bright pluck, pickup near the string's end ks_setup(v, b, f0, vg, h, 4 * 2 ^ (-(n - 48) / 24) * dec_k, 0.4, 1); b[F_AE] = 1; ) : ( // glockenspiel bar: 4 inharmonic partials Tn = 3.2 * 2 ^ (-(n - 72) / 24) * dec_k; k = 0; loop(4, ratio = k == 0 ? 1 : k == 1 ? 2.756 : k == 2 ? 5.404 : 8.933; amp = vg * (k == 0 ? 1 : k == 1 ? 0.22 + 0.25 * h : k == 2 ? 0.08 + 0.15 * h : 0.04 + 0.08 * h); dk = Tn * (k == 0 ? 1 : k == 1 ? 0.35 : k == 2 ? 0.14 : 0.07); bell_set(b, f0, vg, h, ratio, amp, dk, k); k += 1; ); b[F_CLK] = vg * (0.1 + 0.15 * h); // mallet click (soft) b[F_AE] = 1; ); ); ); function note_off(n) local(v, b) ( v = 0; loop(NV, b = VB + v * VS; b[F_N] == n && b[F_G] ? ( b[F_G] = 0; b[F_S] = pedal; ); v += 1; ); mono && n == mono_n ? mono_n = -1; ); function pedal_set(on) local(v) ( pedal = on; !on ? ( v = 0; loop(NV, VB[v * VS + F_S] = 0; v += 1; ); ); ); function all_off() local(v) ( v = 0; loop(NV, VB[v * VS + F_G] = 0; VB[v * VS + F_S] = 0; v += 1; ); pedal = 0; ); function kill_all() ( memset(VB, 0, NV * VS); memset(KSB, 0, NV * KSL); pedal = 0; mono_n = -1; ); // ---------- reverb (GFX Space engine) ---------- rv_a = 96000; // small arrays: 8 per field rlw = rv_a; rlz = rv_a + 10; rlph = rv_a + 20; rlrt = rv_a + 30; rllen = rv_a + 40; rlga = rv_a + 50; rlgb = rv_a + 60; rapw = rv_a + 70; rapl = rv_a + 80; rbl = rv_a + 90; rtmp = rv_a + 100; rmix = rv_a + 110; memset(rv_a, 0, 120); rbl[0] = 31.7; rbl[1] = 37.1; rbl[2] = 41.3; rbl[3] = 47.9; rbl[4] = 53.3; rbl[5] = 61.1; rbl[6] = 70.7; rbl[7] = 79.3; rapl[0] = 142; rapl[1] = 107; rapl[2] = 379; rapl[3] = 277; i = 0; loop(8, rlrt[i] = 0.31 + 0.11 * i; rlph[i] = rand(1); i += 1; ); RBLK = ceil(0.16 * srate) + 16; rpre_b = 100000; rpre_len = ceil(0.16 * srate) + 8; rap_b = rpre_b + rpre_len; // 4 diffusers, rings of 4096 rln_b = rap_b + 4 * 4096; // 8 lines memset(rpre_b, 0, rln_b + 8 * RBLK - rpre_b); rpre_w = 0; rv_on = 0; bt_pos = 0; nd_last = -1; function rv_update() local(i, sz, L, gl, gh, a, t60) ( rtyp = floor(slider14 + 0.5); sz = rtyp == 0 ? 0.42 : rtyp == 1 ? 1 : 0.55; rdiff = rtyp == 2 ? 0.95 : 0.75; rpre = slider15 * 0.001 * srate; t60 = slider16 * 1.11; rmod = rtyp == 2 ? 0.0004 : 0.0008; i = 0; loop(8, L = min(rbl[i] * sz * 0.001 * srate, RBLK - 64); rllen[i] = L; gl = 10 ^ (-3 * L / (t60 * srate)); gh = 10 ^ (-3 * L / (t60 * (1 - 0.9 * slider17 / 100) * srate * (rtyp == 2 ? 1.4 : 1))); a = (gl - gh) / (gl + gh); rlga[i] = a; rlgb[i] = gl * (1 - a); i += 1; ); rv_wet = slider18 / 100; rv_on = rv_wet > 0.001; ); // ---------- MOD RACK (the GFX Mod Rack inside): chorus, tremolo, vibe, delay in parallel on the voices ---------- // each module adds only its change ("delta") to the dry signal; L / C / R pick left, mono centre, right mrCHN = 16384; mrDLN = floor(srate*2.2) + 8; mrChA = MR; mrChB = MR + mrCHN; mrChC = MR + 2*mrCHN; mrDlA = MR + 3*mrCHN; mrDlB = mrDlA + mrDLN; mrDlC = mrDlB + mrDLN; mrVsC = mrDlC + mrDLN; mrVsT = mrVsC + 48; mrVsV = mrVsT + 48; mrPre = mrVsV + 48; mrDls = mrPre + 4; mrRg = mrDls + 8; mrVbF = mrRg + 24; memset(MR, 0, mrVbF + 4 - MR); mrVsT[0] = mrVsT[16] = mrVsT[32] = 1; mrVbF[0] = 60; mrVbF[1] = 180; mrVbF[2] = 480; mrVbF[3] = 1300; mrCw = 1 - exp(-1/(0.15*srate)); mrCs = 1 - exp(-1/(3*srate)); mrCd = 1 - exp(-1/(0.8*srate)); mrCdr = 1 - exp(-1/(3*srate)); function mr_opc(fc) ( 1 - exp(-2*$pi*min(fc, srate*0.45)/srate); ); function mr_tanh(v) ( v = max(-20, min(20, v)); 1 - 2/(exp(2*v) + 1); ); mrVbLp = mr_opc(160); mrVbAt = 1 - exp(-1/(0.008*srate)); mrDlLc = mr_opc(3500); mrDlHc = mr_opc(70); mrDlTs = 1 - exp(-1/(0.25*srate)); mrDlT = 350; function mr_div(i, md) ( (i == 0 ? 4*mrBar : i == 1 ? 2*mrBar : i == 2 ? mrBar : i == 3 ? 2 : i == 4 ? 1 : i == 5 ? 0.5 : i == 6 ? 0.25 : 0.125)*(md == 2 ? 1.5 : md == 3 ? 2/3 : 1); ); function mr_hread(buf, n, pos) local(i, f, xm1, x0, x1, x2, c1, c2, c3) ( pos < 0 ? pos += n; pos >= n ? pos -= n; i = floor(pos); f = pos - i; xm1 = buf[(i - 1 + n) % n]; x0 = buf[i]; x1 = buf[(i + 1) % n]; x2 = buf[(i + 2) % n]; c1 = 0.5*(x1 - xm1); c2 = xm1 - 2.5*x0 + 2*x1 - 0.5*x2; c3 = 0.5*(x2 - xm1) + 1.5*(x0 - x1); ((c3*f + c2)*f + c1)*f + x0; ); function mr_rgen(q, period, coef) ( q[0] -= 1; q[0] <= 0 ? ( q[0] = period*srate; q[1] = rand(2) - 1; ); q[2] += coef*(q[1] - q[2]); q[2]; ); function mr_ch(buf, phoff, vs) local(lf, dms, y) ( lf = sin(2*$pi*(mrChPh + phoff)); dms = mrChBase + mrChDep*lf + mrWarb; y = mr_hread(buf, mrCHN, mrChW - max(1, dms)*srate*0.001); mrClkOn ? ( vs[0] += mrClkInc; vs[0] >= 1 ? ( vs[0] -= 1; vs[1] = y; ); y = vs[1]; ); vs[2] += mrChPc*(y - vs[2]); vs[3] += mrChPc*(vs[2] - vs[3]); vs[3]; ); function mr_tr(phoff, vs) local(sv, sh, g) ( sv = sin(2*$pi*(mrTrPh + phoff)); sh = mrTrK > 1.01 ? mr_tanh(mrTrK*sv)/mrTrTk : sv; g = 1 - mrTrDep*(0.5 - 0.5*sh); vs[0] += mrTrLag*(g - vs[0]); vs[0]; ); function mr_vb(x, phoff, vs) local(q, pw, lf, c, rr, oc, k, y, f, t, a1, xi) ( q = mrVbPh + phoff; q -= floor(q); pw = q < mrVbSk ? 0.5*q/mrVbSk : 0.5 + 0.5*(q - mrVbSk)/(1 - mrVbSk); lf = 0.5 - 0.5*cos(2*$pi*pw); c = lf > vs[8] ? mrVbAt : mrVbRl; vs[8] += c*(lf - vs[8]); rr = vs[8]; oc = mrVbOct*rr; y = x; k = 0; loop(4, f = min(srate*0.45, mrVbF[k]*2^oc); t = tan($pi*f/srate); a1 = (t - 1)/(t + 1); xi = y; y = a1*xi + vs[k*2] - a1*vs[k*2 + 1]; vs[k*2] = xi; vs[k*2 + 1] = y; k += 1; ); vs[9] += mrVbLp*(x - vs[9]); mrVbWet*(0.5*(y - x) + mrVbTh*(2*rr - 1)*vs[9]); ); function mr_loop(y, q) local(v) ( q[0] += mrDlLc*(y - q[0]); q[1] += mrDlHc*(q[0] - q[1]); v = q[0] - q[1]; mr_tanh(v*mrFbE*1.15)/1.15; ); // the controls (each block) function mr_update() local(fclk) ( mrChLo = slider23 > 0.5; mrChCo = slider24 > 0.5; mrChRo = slider25 > 0.5; mrTrLo = slider31 > 0.5; mrTrCo = slider32 > 0.5; mrTrRo = slider33 > 0.5; mrVbLo = slider39 > 0.5; mrVbCo = slider40 > 0.5; mrVbRo = slider41 > 0.5; mrDlLo = slider48 > 0.5; mrDlCo = slider49 > 0.5; mrDlRo = slider50 > 0.5; mrChBase = 7; mrChDep = slider20/100*3; fclk = 40000; mrClkOn = fclk < srate*0.98; mrClkInc = fclk/srate; mrChPc = mr_opc(min(14000, fclk*0.42)); mrChMix = slider21/100; mrTrK = 1; mrTrTk = mr_tanh(mrTrK); mrTrDep = slider29/100; mrTrLag = 1 - exp(-1/(6*0.001*srate)); mrVbSk = 0.5; mrVbRl = 1 - exp(-1/(0.04*srate)); mrVbTh = 0; mrVbOct = 3*slider37/100; mrVbWet = min(1, 2*slider37/100); mrFbE = 0.95*slider45/95; mrDlMix = slider46/100; ); // tempo (each block) function mr_block() ( mrBar = ts_denom > 0 ? ts_num*4/ts_denom : 4; mrPlay = play_state & 1; mrBpos = beat_position; mrBpInc = tempo/(60*srate); mrChSy = slider26 > 0.5; mrChQn = mr_div(slider27, slider26); mrTrSy = slider34 > 0.5; mrTrQn = mr_div(slider35, slider34); mrVbSy = slider42 > 0.5; mrVbQn = mr_div(slider43, slider42); mrDlTgt = slider51 > 0.5 && tempo > 0 ? min(1500, mr_div(slider52, slider51)*60000/tempo) : slider44; mrOn = mrChMix > 0 || mrTrDep > 0 || mrVbWet > 0 || mrDlMix > 0; ); // one sample: in mrL / mrR, out mrL / mrR function mr_run() local(xl, xr, m, dl, dr, y, sp, kc, ws, wc, dsm, ya, yb, yc) ( xl = mrL; xr = mrR; m = 0.5*(xl + xr); dl = dr = 0; mrBpos += mrBpInc; mrChSy ? mrChPh = (mrPlay ? mrBpos/mrChQn : mrChPh + mrBpInc/mrChQn) : mrChPh += slider19*(1 + 0.2*drift*mr_rgen(mrRg, 2.5, mrCdr))/srate; mrTrSy ? mrTrPh = (mrPlay ? mrBpos/mrTrQn : mrTrPh + mrBpInc/mrTrQn) : mrTrPh += slider28*(1 + 0.2*drift*mr_rgen(mrRg + 3, 2.5, mrCdr))/srate; mrVbSy ? mrVbPh = (mrPlay ? mrBpos/mrVbQn : mrVbPh + mrBpInc/mrVbQn) : mrVbPh += slider36*(1 + 0.2*drift*mr_rgen(mrRg + 6, 2.5, mrCdr))/srate; mrChPh -= floor(mrChPh); mrTrPh -= floor(mrTrPh); mrVbPh -= floor(mrVbPh); // chorus mrPre[0] += mrChPc*(xl - mrPre[0]); mrPre[1] += mrChPc*(xr - mrPre[1]); mrPre[2] += mrChPc*(m - mrPre[2]); mrChA[mrChW] = mrPre[0]; mrChB[mrChW] = mrPre[1]; mrChC[mrChW] = mrPre[2]; mrChMix > 0 ? ( sp = mrChCo && (mrChLo || mrChRo); kc = (mrChLo || mrChRo) ? 0.707 : 1; mrChLo ? dl += mrChMix*mr_ch(mrChA, 0, mrVsC); mrChRo ? dr += mrChMix*mr_ch(mrChB, sp ? 2/3 : 0.25, mrVsC + 16); mrChCo ? ( y = mrChMix*kc*mr_ch(mrChC, sp ? 1/3 : 0, mrVsC + 32); dl += y; dr += y; ); ); // tremolo mrTrDep > 0 ? ( sp = mrTrCo && (mrTrLo || mrTrRo); ws = mrTrCo ? 0.5 : 1; wc = (mrTrLo || mrTrRo) ? 0.5 : 1; mrTrLo ? dl += ws*xl*(mr_tr(0, mrVsT) - 1); mrTrRo ? dr += ws*xr*(mr_tr(sp ? 2/3 : 0, mrVsT + 16) - 1); mrTrCo ? ( y = wc*m*(mr_tr(sp ? 1/3 : 0, mrVsT + 32) - 1); dl += y; dr += y; ); ); // vibe mrVbWet > 0 ? ( sp = mrVbCo && (mrVbLo || mrVbRo); kc = (mrVbLo || mrVbRo) ? 0.707 : 1; mrVbLo ? dl += mr_vb(xl, 0, mrVsV); mrVbRo ? dr += mr_vb(xr, sp ? 2/3 : 0, mrVsV + 16); mrVbCo ? ( y = kc*mr_vb(m, sp ? 1/3 : 0, mrVsV + 32); dl += y; dr += y; ); ); // delay mrDlT += mrDlTs*(mrDlTgt - mrDlT); dsm = max(2, min(mrDLN*0.55, mrDlT*srate*0.001)); sp = mrDlCo && (mrDlLo || mrDlRo); kc = (mrDlLo || mrDlRo) ? 0.707 : 1; mrDlLo && mrDlMix > 0 ? ( ya = mr_hread(mrDlA, mrDLN, mrDlW - dsm*(sp ? 0.75 : 1)); mrDlA[mrDlW] = xl + mr_loop(ya, mrDls); dl += mrDlMix*ya; ) : mrDlA[mrDlW] = 0; mrDlRo && mrDlMix > 0 ? ( yb = mr_hread(mrDlB, mrDLN, mrDlW - dsm*(sp ? 1.25 : 1)); mrDlB[mrDlW] = xr + mr_loop(yb, mrDls + 2); dr += mrDlMix*yb; ) : mrDlB[mrDlW] = 0; mrDlCo && mrDlMix > 0 ? ( yc = mr_hread(mrDlC, mrDLN, mrDlW - dsm); mrDlC[mrDlW] = m + mr_loop(yc, mrDls + 4); y = mrDlMix*kc*yc; dl += y; dr += y; ) : mrDlC[mrDlW] = 0; mrChW += 1; mrChW >= mrCHN ? mrChW = 0; mrDlW += 1; mrDlW >= mrDLN ? mrDlW = 0; mrL = xl + dl; mrR = xr + dr; ); // ---------- the patches ---------- function pt(i, j, a, b, c, d, e, f, g, h, k, l, m, n, o, q) local(z) ( z = PT + i*64 + j; z[0] = a; z[1] = b; z[2] = c; z[3] = d; z[4] = e; z[5] = f; z[6] = g; z[7] = h; z[8] = k; z[9] = l; z[10] = m; z[11] = n; z[12] = o; z[13] = q; ); pt(0, 0, 0, 24, 0, 1.129, 1, 1.8, 18, 0.8, 50, 0, 0, 1, 0, 1); pt(0, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(0, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 0); strcpy(400 + 0, "Session Piano"); pt(1, 0, 0, 38, 0, 1.103, 1, 1.8, 18, 0.8, 50, 0, 0, 1, 0, 1); pt(1, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(1, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 0); strcpy(400 + 1, "Bright Piano"); pt(2, 0, 0, 25, 0, 0.58, 1, 1.8, 18, 0.8, 50, 0, 0, 1, 0, 1); pt(2, 14, 0, 2, 4.6, 50, 0, 1, 1, 1, 0, 5, 1.5, 0, 0, 1); pt(2, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 0); strcpy(400 + 2, "Chorus EP"); pt(3, 0, 0, 0, 0, 0.957, 1, 1.8, 18, 0.8, 50, 0, 0, 1, 0, 1); pt(3, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(3, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 0); strcpy(400 + 3, "FM E-Piano"); pt(4, 0, 1, 0, 0.5, 1.235, 1, 1.8, 18, 0.8, 50, 0, 0, 1, 0, 1); pt(4, 14, 0, 2, 4.2, 30, 0, 1, 1, 1, 0, 5, 1.5, 0, 0, 1); pt(4, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 0); strcpy(400 + 4, "E.Piano 1"); pt(5, 0, 1, 1, 0.5, 1.405, 1, 1.8, 18, 0.8, 50, 0, 0, 1, 0, 1); pt(5, 14, 0, 2, 4.2, 30, 0, 1, 1, 1, 0, 5, 1.5, 0, 0, 1); pt(5, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 0); strcpy(400 + 5, "E.Piano 2"); pt(6, 0, 0, 1, 0, 0.957, 1, 1.8, 18, 0.8, 50, 0, 0, 1, 0, 1); pt(6, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(6, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 0); strcpy(400 + 6, "Clav"); pt(7, 0, 1, 3, 0.2, 0.789, 1, 1.8, 18, 0.8, 50, 0, 0, 1, 0, 1); pt(7, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(7, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 0); strcpy(400 + 7, "Clavi"); pt(8, 0, 1, 2, 0.25, 0.878, 1, 1.8, 18, 0.8, 50, 0, 0, 1, 0, 1); pt(8, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(8, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 0); strcpy(400 + 8, "Harpsichord"); pt(9, 0, 0, 34, 0, 0.46, 0, 1.4, 14, 0.8, 50, 0, 0, 1, 0, 1); pt(9, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(9, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 0); strcpy(400 + 9, "Drawbar Organ"); pt(10, 0, 0, 2, 0, 0.443, 1, 2.4, 25, 0.8, 50, 0, 0, 1, 0, 1); pt(10, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(10, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 1); strcpy(400 + 10, "Glockenspiel"); pt(11, 0, 0, 8, 0, 0.691, 1, 2.4, 25, 0.8, 50, 0, 0, 1, 0, 1); pt(11, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(11, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 1); strcpy(400 + 11, "Fantasy Bells"); pt(12, 0, 0, 14, 0, 0.861, 1, 2.4, 25, 0.8, 50, 0, 0, 1, 0, 1); pt(12, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(12, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 1); strcpy(400 + 12, "Crystal Harp"); pt(13, 0, 0, 9, 0, 0.579, 1, 2.4, 25, 0.8, 50, 0, 0, 1, 0, 1); pt(13, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(13, 28, 0, 1, 0, 4, 350, 40, 42, 0, 1, 1, 1, 2, 5, 1); strcpy(400 + 13, "Staccato Glass"); pt(14, 0, 1, 4, 0.3, 1.065, 1, 2.4, 25, 0.8, 50, 0, 0, 1, 0, 1); pt(14, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(14, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 1); strcpy(400 + 14, "Celesta"); pt(15, 0, 1, 5, 0.3, 1.223, 1, 2.4, 25, 0.8, 50, 0, 0, 1, 0, 1); pt(15, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(15, 28, 0, 1, 0, 4, 320, 25, 15, 0, 1, 1, 1, 1, 4, 1); strcpy(400 + 15, "Music Box"); pt(16, 0, 1, 6, 0.3, 1.183, 1, 2.4, 25, 0.8, 50, 0, 0, 1, 0, 1); pt(16, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(16, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 1); strcpy(400 + 16, "Vibes"); pt(17, 0, 1, 7, 0.3, 0.785, 1, 2.4, 25, 0.8, 50, 0, 0, 1, 0, 1); pt(17, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(17, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 1); strcpy(400 + 17, "Marimba"); pt(18, 0, 1, 8, 0.3, 0.884, 1, 2.4, 25, 0.8, 50, 0, 0, 1, 0, 1); pt(18, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(18, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 1); strcpy(400 + 18, "Xylophone"); pt(19, 0, 1, 9, 0.3, 1.423, 1, 2.4, 25, 0.8, 50, 0, 0, 1, 0, 1); pt(19, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(19, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 1); strcpy(400 + 19, "Tubular Bells"); pt(20, 0, 1, 10, 0.3, 0.776, 1, 2.4, 25, 0.8, 50, 0, 0, 1, 0, 1); pt(20, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(20, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 1); strcpy(400 + 20, "Dulcimer"); pt(21, 0, 1, 43, 0.3, 1.127, 1, 2.4, 25, 0.8, 50, 0, 0, 1, 0, 1); pt(21, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(21, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 1); strcpy(400 + 21, "Tinkle Bell"); pt(22, 0, 0, 39, 0, 1.391, 2, 1.8, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(22, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(22, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 2); strcpy(400 + 22, "LA Nylon"); pt(23, 0, 0, 40, 0, 1.906, 2, 1.8, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(23, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(23, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 2); strcpy(400 + 23, "LA Steel"); pt(24, 0, 0, 41, 0, 1.237, 2, 1.8, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(24, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(24, 28, 0, 1, 0, 4, 350, 30, 28, 0, 1, 1, 1, 2, 5, 2); strcpy(400 + 24, "LA Clean"); pt(25, 0, 0, 42, 0, 0.638, 2, 1.8, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(25, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(25, 28, 0, 1, 0, 4, 350, 40, 35, 0, 1, 1, 1, 2, 5, 2); strcpy(400 + 25, "LA Harmonics"); pt(26, 0, 0, 12, 0, 1.839, 2, 1.8, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(26, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(26, 28, 0, 1, 0, 4, 350, 30, 21, 0, 1, 1, 1, 1, 4, 2); strcpy(400 + 26, "Nylon Atmos"); pt(27, 0, 0, 10, 0, 1.479, 2, 1.8, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(27, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(27, 28, 0, 1, 0, 4, 350, 25, 17, 0, 1, 1, 1, 1, 5, 2); strcpy(400 + 27, "Pizz Flow"); pt(28, 0, 0, 36, 0, 1.495, 2, 1.8, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(28, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(28, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 2); strcpy(400 + 28, "Harp"); pt(29, 0, 1, 11, 0.25, 1.074, 2, 1.8, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(29, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(29, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 2); strcpy(400 + 29, "Nylon Gtr"); pt(30, 0, 1, 12, 0.25, 0.847, 2, 1.8, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(30, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(30, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 2); strcpy(400 + 30, "Steel Gtr"); pt(31, 0, 1, 13, 0.25, 0.866, 2, 1.8, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(31, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(31, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 2); strcpy(400 + 31, "Muted Gtr"); pt(32, 0, 1, 14, 0.25, 0.825, 2, 1.8, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(32, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(32, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 2); strcpy(400 + 32, "Overdrive Gtr"); pt(33, 0, 1, 41, 0.25, 1.174, 2, 1.8, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(33, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(33, 28, 0, 1, 0, 4, 320, 25, 15, 0, 1, 1, 1, 1, 4, 2); strcpy(400 + 33, "Koto"); pt(34, 0, 1, 42, 0.25, 0.889, 2, 1.8, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(34, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(34, 28, 0, 1, 0, 4, 320, 25, 15, 0, 1, 1, 1, 1, 4, 2); strcpy(400 + 34, "Kalimba"); pt(35, 0, 0, 6, 0, 0.591, 1, 2.6, 28, 0.8, 50, 0, 0, 1, 0, 1); pt(35, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(35, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 3); strcpy(400 + 35, "Strings"); pt(36, 0, 0, 7, 0, 0.496, 1, 2.6, 28, 0.8, 50, 0, 0, 1, 0, 1); pt(36, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(36, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 3); strcpy(400 + 36, "String Ensemble"); pt(37, 0, 0, 31, 0, 0.577, 1, 2.6, 28, 0.8, 50, 0, 0, 1, 0, 1); pt(37, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(37, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 3); strcpy(400 + 37, "Fat Strings"); pt(38, 0, 0, 32, 0, 0.357, 1, 2.6, 28, 0.8, 50, 0, 0, 1, 0, 1); pt(38, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(38, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 3); strcpy(400 + 38, "Orchestra Hit"); pt(39, 0, 1, 20, 0.7, 0.958, 1, 2.6, 28, 0.8, 50, 0, 0, 1, 0, 1); pt(39, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(39, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 3); strcpy(400 + 39, "Violin"); pt(40, 0, 1, 21, 0.7, 0.795, 1, 2.6, 28, 0.8, 50, 0, 0, 1, 0, 1); pt(40, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(40, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 3); strcpy(400 + 40, "Viola"); pt(41, 0, 1, 22, 0.7, 1.044, 1, 2.6, 28, 0.8, 50, 0, 0, 1, 0, 1); pt(41, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(41, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 3); strcpy(400 + 41, "Cello"); pt(42, 0, 1, 23, 0.7, 0.673, 1, 2.6, 28, 0.8, 50, 0, 0, 1, 0, 1); pt(42, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(42, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 3); strcpy(400 + 42, "Strings 1"); pt(43, 0, 1, 24, 0.7, 0.804, 1, 2.6, 28, 0.8, 50, 0, 0, 1, 0, 1); pt(43, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(43, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 3); strcpy(400 + 43, "Syn Strings"); pt(44, 0, 0, 3, 0, 0.817, 1, 3.4, 30, 0.8, 50, 0, 0, 1, 0, 1); pt(44, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(44, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 4); strcpy(400 + 44, "Synth Pad"); pt(45, 0, 0, 4, 0, 0.821, 1, 3.4, 30, 0.8, 50, 0, 0, 1, 0, 1); pt(45, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(45, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 4); strcpy(400 + 45, "Warm Pad"); pt(46, 0, 0, 23, 0, 0.887, 1, 3.4, 30, 0.8, 50, 0, 0, 1, 0, 1); pt(46, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(46, 28, 0, 1, 0, 4, 350, 40, 35, 0, 1, 1, 1, 1, 4, 4); strcpy(400 + 46, "Soundtrack Pad"); pt(47, 0, 0, 21, 0, 1.349, 1, 3.4, 30, 0.8, 50, 0, 0, 1, 0, 1); pt(47, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(47, 28, 0, 1, 0, 4, 350, 40, 35, 0, 1, 1, 1, 2, 5, 4); strcpy(400 + 47, "Native Dance"); pt(48, 0, 1, 36, 0.8, 0.856, 1, 3.4, 30, 0.8, 50, 0, 0, 1, 0, 1); pt(48, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(48, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 4); strcpy(400 + 48, "Poly Synth"); pt(49, 0, 1, 38, 0.8, 0.53, 1, 3.4, 30, 0.8, 50, 0, 0, 1, 0, 1); pt(49, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(49, 28, 0, 1, 0, 4, 450, 40, 18, 0, 1, 1, 1, 2, 4, 4); strcpy(400 + 49, "Bowed Pad"); pt(50, 0, 1, 39, 0.8, 0.799, 1, 3.4, 30, 0.8, 50, 0, 0, 1, 0, 1); pt(50, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(50, 28, 0, 1, 0, 4, 450, 40, 18, 0, 1, 1, 1, 2, 4, 4); strcpy(400 + 50, "Metal Pad"); pt(51, 0, 1, 40, 0.8, 0.566, 1, 3.4, 30, 0.8, 50, 0, 0, 1, 0, 1); pt(51, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(51, 28, 0, 1, 0, 4, 450, 40, 18, 0, 1, 1, 1, 2, 4, 4); strcpy(400 + 51, "Sweep Pad"); pt(52, 0, 0, 11, 0, 0.688, 1, 3, 30, 0.8, 50, 0, 0, 1, 0, 1); pt(52, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(52, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 5); strcpy(400 + 52, "Glass Voices"); pt(53, 0, 0, 26, 0, 0.471, 1, 3, 30, 0.8, 50, 0, 0, 1, 0, 1); pt(53, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(53, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 5); strcpy(400 + 53, "Dark Vox"); pt(54, 0, 0, 27, 0, 0.432, 1, 3, 30, 0.8, 50, 0, 0, 1, 0, 1); pt(54, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(54, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 5); strcpy(400 + 54, "Fantasy Vox"); pt(55, 0, 0, 28, 0, 0.58, 1, 3, 30, 0.8, 50, 0, 0, 1, 0, 1); pt(55, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(55, 28, 0, 1, 0, 4, 350, 45, 42, 0, 1, 1, 1, 2, 4, 5); strcpy(400 + 55, "Spaced Vox"); pt(56, 0, 1, 37, 0.9, 0.604, 1, 3, 30, 0.8, 50, 0, 0, 1, 0, 1); pt(56, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(56, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 5); strcpy(400 + 56, "Choir Pad"); pt(57, 0, 0, 33, 0, 0.918, 1, 2, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(57, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(57, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 6); strcpy(400 + 57, "Brass Section"); pt(58, 0, 0, 13, 0, 0.901, 1, 2, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(58, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(58, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 6); strcpy(400 + 58, "Synth Brass"); pt(59, 0, 0, 29, 0, 0.925, 1, 2, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(59, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(59, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 6); strcpy(400 + 59, "Velo Stab"); pt(60, 0, 0, 30, 0, 0.76, 1, 2, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(60, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(60, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 6); strcpy(400 + 60, "Hoover"); pt(61, 0, 0, 35, 0, 0.413, 1, 2, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(61, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(61, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 6); strcpy(400 + 61, "Pan Flute"); pt(62, 0, 1, 25, 0.3, 1.679, 1, 2, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(62, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(62, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 6); strcpy(400 + 62, "Syn Reed"); pt(63, 0, 1, 26, 0.3, 1.778, 1, 2, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(63, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(63, 28, 0, 1, 0, 4, 350, 30, 22, 0, 1, 0, 1, 2, 5, 6); strcpy(400 + 63, "Whistle"); pt(64, 0, 1, 27, 0.3, 1.663, 1, 2, 20, 0.8, 50, 0, 0, 1, 0, 1); pt(64, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(64, 28, 0, 1, 0, 4, 350, 30, 22, 0, 1, 0, 1, 2, 5, 6); strcpy(400 + 64, "Ocarina"); pt(65, 0, 0, 37, 0, 0.745, 2, 1.8, 18, 0.8, 50, 0, 0, 1, 0, 1); pt(65, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(65, 28, 0, 1, 0, 4, 350, 30, 21, 0, 1, 1, 1, 2, 5, 7); strcpy(400 + 65, "Square Lead"); pt(66, 0, 0, 22, 0, 0.535, 2, 1.8, 18, 0.8, 50, 0, 0, 1, 0, 1); pt(66, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(66, 28, 0, 1, 0, 4, 350, 30, 25, 0, 1, 1, 1, 1, 5, 7); strcpy(400 + 66, "Calliope Lead"); pt(67, 0, 1, 28, 0.3, 1.606, 2, 1.8, 18, 0.8, 50, 0, 0, 1, 0, 1); pt(67, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(67, 28, 0, 1, 0, 4, 350, 30, 22, 0, 1, 0, 1, 2, 5, 7); strcpy(400 + 67, "Square Wave"); pt(68, 0, 1, 29, 0.3, 1.48, 2, 1.8, 18, 0.8, 50, 0, 0, 1, 0, 1); pt(68, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(68, 28, 0, 1, 0, 4, 350, 30, 22, 0, 1, 0, 1, 2, 5, 7); strcpy(400 + 68, "Saw Lead"); pt(69, 0, 1, 30, 0.3, 1.565, 2, 1.8, 18, 0.8, 50, 0, 0, 1, 0, 1); pt(69, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(69, 28, 0, 1, 0, 4, 350, 30, 22, 0, 1, 0, 1, 2, 5, 7); strcpy(400 + 69, "Calliope"); pt(70, 0, 1, 31, 0.3, 1.665, 2, 1.8, 18, 0.8, 50, 0, 0, 1, 0, 1); pt(70, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(70, 28, 0, 1, 0, 4, 350, 30, 22, 0, 1, 0, 1, 2, 5, 7); strcpy(400 + 70, "Chiff Lead"); pt(71, 0, 1, 32, 0.3, 1.624, 2, 1.8, 18, 0.8, 50, 0, 0, 1, 0, 1); pt(71, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(71, 28, 0, 1, 0, 4, 350, 30, 22, 0, 1, 0, 1, 2, 5, 7); strcpy(400 + 71, "Charang"); pt(72, 0, 1, 33, 0.3, 1.403, 2, 1.8, 18, 0.8, 50, 0, 0, 1, 0, 1); pt(72, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(72, 28, 0, 1, 0, 4, 350, 30, 22, 0, 1, 0, 1, 2, 5, 7); strcpy(400 + 72, "Voice Lead"); pt(73, 0, 1, 34, 0.3, 2.171, 2, 1.8, 18, 0.8, 50, 0, 0, 1, 0, 1); pt(73, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(73, 28, 0, 1, 0, 4, 350, 30, 22, 0, 1, 0, 1, 2, 5, 7); strcpy(400 + 73, "Fifth Lead"); pt(74, 0, 1, 35, 0.3, 1.817, 2, 1.8, 18, 0.8, 50, 0, 0, 1, 0, 1); pt(74, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(74, 28, 0, 1, 0, 4, 350, 30, 22, 0, 1, 0, 1, 2, 5, 7); strcpy(400 + 74, "Bass & Lead"); pt(75, 0, 0, 5, 0, 0.588, 0, 1, 6, 0.8, 50, 0, 0, 1, 0, 1); pt(75, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(75, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 8); strcpy(400 + 75, "Bass Synth"); pt(76, 0, 0, 15, 0, 0.306, 0, 1, 6, 0.8, 50, 0, 0, 1, 0, 1); pt(76, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(76, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 8); strcpy(400 + 76, "Sub Bass"); pt(77, 0, 0, 16, 0, 0.911, 0, 1, 6, 0.8, 50, 0, 0, 1, 0, 1); pt(77, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(77, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 8); strcpy(400 + 77, "Acid Bass"); pt(78, 0, 0, 17, 0, 0.565, 0, 1, 6, 0.8, 50, 0, 0, 1, 0, 1); pt(78, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(78, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 8); strcpy(400 + 78, "Round Bass"); pt(79, 0, 0, 18, 0, 0.801, 0, 1, 6, 0.8, 50, 0, 0, 1, 0, 1); pt(79, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(79, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 8); strcpy(400 + 79, "Pluck Bass"); pt(80, 0, 0, 19, 0, 0.265, 0, 1, 6, 0.8, 50, 0, 0, 1, 0, 1); pt(80, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(80, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 8); strcpy(400 + 80, "Hollow Bass"); pt(81, 0, 0, 20, 0, 0.738, 0, 1, 6, 0.8, 50, 0, 0, 1, 0, 1); pt(81, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(81, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 8); strcpy(400 + 81, "Reese Bass"); pt(82, 0, 1, 15, 0, 1.546, 0, 1, 6, 0.8, 50, 0, 0, 1, 0, 1); pt(82, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(82, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 8); strcpy(400 + 82, "Acoustic Bass"); pt(83, 0, 1, 16, 0, 1.738, 0, 1, 6, 0.8, 50, 0, 0, 1, 0, 1); pt(83, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(83, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 8); strcpy(400 + 83, "Finger Bass"); pt(84, 0, 1, 17, 0, 1.422, 0, 1, 6, 0.8, 50, 0, 0, 1, 0, 1); pt(84, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(84, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 8); strcpy(400 + 84, "Synth Bass 1"); pt(85, 0, 1, 18, 0, 1.536, 0, 1, 6, 0.8, 50, 0, 0, 1, 0, 1); pt(85, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(85, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 8); strcpy(400 + 85, "Synth Bass 2"); pt(86, 0, 1, 19, 0, 1.868, 0, 1, 6, 0.8, 50, 0, 0, 1, 0, 1); pt(86, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(86, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 8); strcpy(400 + 86, "Synth Bass 3"); pt(87, 0, 2, 0, 0, 0.698, 0, 1.2, 12, 0.8, 50, 0, 0, 1, 0, 1); pt(87, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(87, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 9); strcpy(400 + 87, "Drum Kit"); pt(88, 0, 1, 44, 0.2, 1.19, 0, 1.2, 12, 0.8, 50, 0, 0, 1, 0, 1); pt(88, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(88, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 9); strcpy(400 + 88, "Agogo"); pt(89, 0, 1, 45, 0.2, 2.139, 0, 1.2, 12, 0.8, 50, 0, 0, 1, 0, 1); pt(89, 14, 0, 2, 4, 0, 0, 1, 0, 1, 0, 5, 1.5, 0, 0, 1); pt(89, 28, 0, 1, 0, 4, 350, 30, 0, 0, 1, 0, 1, 0, 4, 9); strcpy(400 + 89, "Woodblock"); function grp_name(k) ( k == 0 ? "Pianos & Keys" : k == 1 ? "Mallets & Bells" : k == 2 ? "Guitars & Plucks" : k == 3 ? "Strings & Orchestra" : k == 4 ? "Pads" : k == 5 ? "Choirs & Voices" : k == 6 ? "Brass & Winds" : k == 7 ? "Leads" : k == 8 ? "Basses" : "Drums & Perc"; ); function grp_start(k) ( k == 0 ? 0 : k == 1 ? 10 : k == 2 ? 22 : k == 3 ? 35 : k == 4 ? 44 : k == 5 ? 52 : k == 6 ? 57 : k == 7 ? 65 : k == 8 ? 75 : k == 9 ? 87 : 90; ); function pname(p) ( 400 + min(max(floor(p + 0.5), 0), NP - 1); ); function pgrp(p) ( PT[min(max(floor(p + 0.5), 0), NP - 1)*64 + 41]; ); function update() ( tone = slider5/100; filt_oct = slider6; reso = slider7/100; atk_k = slider8/100; rel_k = slider9/100; chor_k = 1; dec_k = slider53/100; sus_o = slider54/100; fam_k = slider55/100; fatk_k = slider56/100; fdec_k = slider57/100; fsus_o = slider58/100; frel_k = slider59/100; sens = slider11/100; tune = 2^(slider12/1200); drift = 0.1; chan = slider4; // drift: fixed and subtle out_t = 10^(slider2/20); ins_output_setup(70); ins_stereo_setup(76); rv_update(); mr_update(); ); // the sound engine for a patch (no sliders touched) function patch_engine(p) local(o) ( p = min(max(floor(p + 0.5), 0), NP - 1); o = PT + p*64; kill_all(); o[0] == 0 ? patch_set(o[1]) : ( patch_set(-1); // neutral analogue settings, then the GM voice / drums eng = o[0] == 1 ? 6 : 7; gprog = o[1]; chor = o[2]; lvl = 0.4; mono = 0; ); ptr_t = o[3]; cur_p = p; ); // choose a patch: its engine, its Mod Rack and reverb, and the EDIT knobs back to centre function load_patch(p) local(o, i) ( p = min(max(floor(p + 0.5), 0), NP - 1); o = PT + p*64; slider1 = p; slider5 = 50; slider6 = 0; slider7 = 0; slider8 = 100; slider9 = 100; slider53 = 100; slider54 = 0; slider55 = 100; slider56 = 100; slider57 = 100; slider58 = 0; slider59 = 100; slider14 = o[4]; slider16 = o[5]; slider18 = o[6]; i = 0; loop(34, slider(19 + i) = o[7 + i]; i += 1; ); ui_auto(1); i = 5; loop(5, ui_auto(i); i += 1; ); ui_auto(14); ui_auto(16); ui_auto(18); i = 53; loop(7, ui_auto(i); i += 1; ); i = 19; loop(34, ui_auto(i); i += 1; ); patch_engine(p); update(); ); // ---------- state ---------- ins_drift_init(); ost_init(90000); ostL.ost_ch_init(); ostR.ost_ch_init(); fA1.svf_set(730, 5); fA2.svf_set(1090, 7); fA3.svf_set(2440, 9); sm = 1 - exp(-1 / (0.03 * srate)); pkL = 0; pkR = 0; nact = 0; vph = 0; flph = 0; !ui_dflt ? ( ui_sz = 2; p70_page = 0; ); patch_engine(slider1); ptr_s = ptr_t; update(); out_s = out_t; last_p = -1; // the first block adopts the saved patch without reloading it ui_dflt = 1; @slider update(); @block last_p < 0 ? last_p = slider1 : slider1 != last_p ? ( load_patch(slider1); last_p = slider1; ); update(); // knobs turned on the GUI take effect here evn = 0; pc_req = -1; while (midirecv(mofs, m1, m2, m3)) ( stt = m1 & 0xF0; mch = (m1 & 0x0F) + 1; (chan == 0 || mch == chan) ? ( stt == 0xE0 ? bend_t = ((m3*128 + m2) - 8192)/8192*slider13 : stt == 0xC0 ? pc_req = m2 : evn < 512 ? ( evq[evn * 4] = mofs; evq[evn * 4 + 1] = stt; evq[evn * 4 + 2] = m2; evq[evn * 4 + 3] = m3; evn += 1; ); ); ); pc_req >= 0 && pc_req < NP ? ( load_patch(pc_req); last_p = slider1; ); evi = 0; spos = 0; panic_req ? ( all_off(); panic_req = 0; ); ins_drift_block(drift, samplesblock); // GFX instrument drift bend_c = 1 - exp(-1/(0.004*srate)); // envelope coefficients (with the ATTACK / RELEASE macros) a_inc = 1 / max(max(aA * atk_k + max(0, atk_k - 1) * 0.15, 0.003) * srate, 1); // never faster than 3 ms (no click) fi_step = 1 / ((eng == 1 ? 0.003 : 0.002) * srate); dc_k = exp(-1 / (0.002 * srate)); f_inc = 1 / max(max(fA * fatk_k + max(0, fatk_k - 1) * 0.15, 0.002) * srate, 1); a_dec = tc(aD * dec_k); a_rel = tc(aR * rel_k); f_dec = tc(fD * fdec_k); f_rel = tc(aR * frel_k); ks_rd = 0.8 ^ (1 / (rel_k * rel_k)); aS_e = min(max(aS + sus_o, 0), 1); fS_e = min(max(fS + fsus_o, 0), 1); // SUSTAIN moves the patch's level gl_c = glide > 0 ? 1 - exp(-1 / (glide * srate)) : 1; fm_rel = tc(0.28 * rel_k); ks_damp = 0.6; gl_rel = tc(1.5 * rel_k); chf_d = tc(0.03); tone_oct = (tone - 0.5) * 3; // TONE: +/- 1.5 octaves on filters / brightness // output filter for the FM / string / bar / piano / organ sounds (FILTER 0 and no RESONANCE = bypassed) gf_on = eng >= 1 && eng <= 5 && (filt_oct < -0.01 || reso > 0.005); gf_g = tan($pi * min(18000 * 2 ^ filt_oct, srate * 0.45) / srate); gf_k = 2 - 1.9 * reso; gf_a1 = 1 / (1 + gf_g * (gf_g + gf_k)); gf_a2 = gf_g * gf_a1; gf_a3 = gf_g * gf_a2; // analogue sounds: the knobs move each note's filter va_res = fres + reso * (1.02 - fres); pe_c = tc(pe_t); pn_damp = tc(0.18 * rel_k) ^ 0.5; pn_kd = tc(0.012); org_rel = tc(0.03 * rel_k); org_ck = tc(0.004); (eng == 4 || eng == 5) ? ( pv = 0; loop(NV, VB[pv * VS + F_ACT] ? pn_norm(VB + pv * VS); pv += 1; ); ); // tempo: the host's when playing, else free-running at its tempo bt_inc = tempo / 60 / srate; (play_state & 1) ? bt_pos = beat_position; mr_block(); @serialize file_var(0, ui_sz); file_var(0, p70_page); @sample while (evi < evn && evq[evi * 4] <= spos) ( e1 = evq[evi * 4 + 1]; e2 = evq[evi * 4 + 2]; e3 = evq[evi * 4 + 3]; e1 == 0x90 && e3 > 0 ? ( note_on(e2, e3); ins_midi_hit(); ) : e1 == 0x80 || e1 == 0x90 ? note_off(e2) : e1 == 0xB0 ? ( e2 == 64 ? pedal_set(e3 >= 64); e2 == 1 ? modw = e3 / 127; e2 == 120 || e2 == 123 ? all_off(); ); evi += 1; ); spos += 1; bend_m += (2^(bend_t/12) - bend_m)*bend_c; pdrift = ins_pitch*bend_m; nz = rand(2) - 1; vph += (vib > 0 ? vib : 5.5) / srate; vph >= 1 ? vph -= 1; flph += 0.13 / srate; flph >= 1 ? flph -= 1; // NATIVE DANCE: a 16-step log-drum pattern, retuned to each held note nd ? ( ndst = floor(bt_pos * 4) & 15; ndst != nd_last ? ( nd_last = ndst; ndh = ndst == 0 || ndst == 3 || ndst == 6 || ndst == 8 || ndst == 10 || ndst == 11 || ndst == 14; ndh ? ( ndr = ndst == 6 || ndst == 14 ? 1.5 : ndst == 10 ? 2 : ndst == 11 ? 0.75 : 1; nda = ndst == 0 || ndst == 8 ? 1 : 0.6; av = 0; loop(NV, b = VB + av * VS; b[F_ACT] && (b[F_G] || b[F_S]) ? ( bell_set(b, b[F_F0] * 0.5, 1, 1, ndr, b[F_VEL] * bl_lvl * nda, 0.22, 0); bell_set(b, b[F_F0] * 0.5, 1, 1, ndr * 2.76, b[F_VEL] * bl_lvl * nda * 0.35, 0.07, 1); bell_set(b, b[F_F0] * 0.5, 1, 1, ndr * 4.1, b[F_VEL] * bl_lvl * nda * 0.15, 0.04, 2); b[F_CLK] = b[F_VEL] * 0.12 * nda; ); av += 1; ); ) : ndst % 2 == 1 ? ( av = 0; loop(NV, b = VB + av * VS; b[F_ACT] && (b[F_G] || b[F_S]) ? b[F_CLK] = b[F_VEL] * 0.05; av += 1; ); // shaker ticks ); ); ); bt_pos += bt_inc; mix = 0; nact = 0; av = 0; loop(NV, b = VB + av * VS; b[F_ACT] ? ( nact += 1; held = b[F_G] || b[F_S]; y = 0; eng >= 6 ? ( // ---------- GM voice / drum kit ---------- y = p_run(av, b + 100, held); b[100] == 0 ? b[F_ACT] = 0; ) : eng == 0 ? ( // ---------- analogue voice ---------- mono ? ( mono_f += (b[F_F0] - mono_f) * gl_c; f = mono_f; ) : f = b[F_F0]; b[F_VT] = min(b[F_VT] + 1 / (0.6 * srate), 1); // delayed vibrato f *= b[F_DT] * pdrift * (1 + (vibd * 0.006 * b[F_VT] * (vib > 0) + modw * 0.008) * sin(2 * $pi * vph)); b[F_PE] != 0 ? ( f *= 2 ^ (b[F_PE] / 12); b[F_PE] *= pe_c; abs(b[F_PE]) < 0.001 ? b[F_PE] = 0; ); // pitch envelope dt = f / srate; b[F_P1] += dt * (1 + det); b[F_P1] >= 1 ? b[F_P1] -= 1; b[F_P2] += dt * (1 - det); b[F_P2] >= 1 ? b[F_P2] -= 1; b[F_P3] += dt * 0.5; b[F_P3] >= 1 ? b[F_P3] -= 1; x = (o1w == 2 ? sqw(b[F_P1], dt * (1 + det)) : o1w ? 1.2 * sin(2 * $pi * b[F_P1]) : saw(b[F_P1], dt * (1 + det))) + o2l * (o2w ? sqw(b[F_P2], dt) : saw(b[F_P2], dt * (1 - det))) + subl * sqw(b[F_P3], dt * 0.5); // envelopes held ? ( b[F_AST] == 0 ? ( b[F_AE] += a_inc; b[F_AE] >= 1 ? ( b[F_AE] = 1; b[F_AST] = 1; ); ) : b[F_AE] = aS_e + (b[F_AE] - aS_e) * a_dec; b[F_FST] == 0 ? ( b[F_FE] += f_inc; b[F_FE] >= 1 ? ( b[F_FE] = 1; b[F_FST] = 1; ); ) : b[F_FE] = fS_e + (b[F_FE] - fS_e) * f_dec; ) : ( b[F_AE] *= a_rel; b[F_FE] *= f_rel; ); // 4-pole filter fc = fbase * 2 ^ ((famt * fam_k + max(0, fam_k - 1) * 1.5) * b[F_FE] * (vf > 0 ? (1 - vf) * (0.6 + 0.4 * b[F_VEL]) + vf * b[F_VEL] * b[F_VEL] * 1.2 : 0.6 + 0.4 * b[F_VEL]) + tone_oct + filt_oct + b[F_E1] + ins_cut + ktrk * log(f / 261.6) / log(2) + flfo * sin(2 * $pi * flph)); g = tan($pi * min(fc, srate * 0.42) / srate); gG = g / (1 + g); u = tanh_(x * 0.5 - va_res * 3.9 * b[F_S4]); v_ = (u - b[F_S1]) * gG; y1 = v_ + b[F_S1]; b[F_S1] = y1 + v_; v_ = (y1 - b[F_S2]) * gG; y2 = v_ + b[F_S2]; b[F_S2] = y2 + v_; v_ = (y2 - b[F_S3]) * gG; y3 = v_ + b[F_S3]; b[F_S3] = y3 + v_; v_ = (y3 - b[F_S4]) * gG; y4 = v_ + b[F_S4]; b[F_S4] = y4 + v_; y = y4 * b[F_AE] * b[F_VEL] * 2 * (1 + 0.8 * va_res) * vamix; // attack / extra layers bl_lvl > 0 ? y += 0.6 * bell_tick(b, held ? 1 : gl_rel) : bell_amp = 0; ks_lvl > 0 ? y += ks_tick(av, b, ks_pick, 0) : b[F_O3] = 0; br_lvl > 0 || b[F_CLK] > 0.0005 ? ( b[F_O1] += (nz - b[F_O1]) * 0.35; b[F_O2] += (b[F_O1] - b[F_O2]) * 0.03; // breath band brp ? ( // the pipes: breath through a narrow band an octave above the note (it sounds with the pipe, not as hiss); // the broad band only for the brief chiff bfc = 2 * sin($pi * min(f * 2, 6000) / srate); b[F_KLP] += bfc * b[F_KAP]; bfh = nz * br_lvl * b[F_AE] * b[F_VEL] - b[F_KLP] - 0.3 * b[F_KAP]; b[F_KAP] += bfc * bfh; y += b[F_KAP] * 0.8 + (b[F_O1] - b[F_O2]) * b[F_CLK]; ) : y += (b[F_O1] - b[F_O2]) * (br_lvl * b[F_AE] * b[F_VEL] + b[F_CLK]); b[F_CLK] *= chf_d; ); !held && b[F_AE] < 0.0003 && bell_amp < 0.0003 && b[F_O3] < 0.0002 ? ( b[F_ACT] = 0; ks_lvl > 0 ? memset(KSB + av * KSL, 0, KSL); ); ) : eng == 1 ? ( // ---------- FM e-piano ---------- f = b[F_F0] * pdrift * (1 + modw * 0.008 * sin(2 * $pi * vph)); b[F_O1] += f / srate; b[F_O1] -= floor(b[F_O1]); b[F_O2] += f / srate; b[F_O2] -= floor(b[F_O2]); b[F_O3] += f * 1.0017 / srate; b[F_O3] -= floor(b[F_O3]); b[F_O4] += f * 14 / srate; b[F_O4] -= floor(b[F_O4]); br = 2 ^ (tone_oct * 0.5); m2 = sin(2 * $pi * b[F_O2]) * b[F_E2] * br; m4 = sin(2 * $pi * b[F_O4]) * b[F_E4] * br; y = (0.62 * sin(2 * $pi * b[F_O1] + m2) * b[F_E1] + 0.42 * sin(2 * $pi * b[F_O3] + m4) * b[F_E3]); rm = held ? 1 : fm_rel; b[F_E1] *= b[F_MD] * rm; b[F_E2] *= b[F_MD + 1]; b[F_E3] *= b[F_MD + 2] * rm; b[F_E4] *= b[F_MD + 3]; y *= 0.6; b[F_E1] + b[F_E3] < 0.0003 ? b[F_ACT] = 0; ) : eng == 4 ? ( // ---------- synthetic piano ---------- rm = held ? 1 : pn_damp; y = pn_tick(b, rm) * 0.5; b[F_CLK] > 0.0003 ? ( // knock: a low thud and a short click b[F_HN] += (nz - b[F_HN]) * 0.08; b[F_HL] += (b[F_HN] - b[F_HL]) * 0.02; y += (b[F_HN] - b[F_HL] * 0.6) * b[F_CLK]; b[F_CLK] *= pn_kd; ); pn_amp < 0.0003 && b[F_CLK] < 0.0003 ? b[F_ACT] = 0; ) : eng == 5 ? ( // ---------- drawbar organ ---------- held ? b[F_AE] = 1 : b[F_AE] *= org_rel; y = pn_tick(b, 1) * b[F_AE]; b[F_CLK] > 0.0003 ? ( b[F_HN] += (nz - b[F_HN]) * 0.5; y += (nz - b[F_HN]) * b[F_CLK]; b[F_CLK] *= org_ck; ); !held && b[F_AE] < 0.0003 ? b[F_ACT] = 0; ) : eng == 2 ? ( // ---------- clav string ---------- y = ks_tick(av, b, 1, 1); !held && b[F_O3] < 0.0002 ? ( b[F_ACT] = 0; memset(KSB + av * KSL, 0, KSL); ); ) : ( // ---------- glockenspiel bar ---------- y = bell_tick(b, held ? 1 : gl_rel); amp = bell_amp; b[F_CLK] > 0.0005 ? ( b[F_KHP] += (nz - b[F_KHP]) * 0.45; y += (nz - b[F_KHP]) * b[F_CLK]; b[F_CLK] *= 0.993; ); y *= 0.6; amp < 0.0003 && b[F_CLK] < 0.0005 ? b[F_ACT] = 0; ); // de-click: fade-in for struck sounds, and any jump at a (re)start is smoothed over ~2 ms b[F_ATK] < 1 ? ( b[F_ATK] = min(b[F_ATK] + fi_step, 1); y *= b[F_ATK]; ); b[F_DCF] ? ( b[F_DCO] = 2 * b[F_PY] - b[F_PY2] - y; b[F_DCF] = 0; ); // continue the waveform's own slope y += b[F_DCO]; b[F_DCO] *= dc_k; b[F_PY2] = b[F_PY]; b[F_PY] = y; mix += y; ); av += 1; ); mix *= lvl; form ? ( // "aah": three vocal formants fo1 = fA1.svf_bp(mix); fo2 = fA2.svf_bp(mix); fo3 = fA3.svf_bp(mix); mix = 0.25 * mix + 1.6 * fo1 + 1.1 * fo2 + 0.7 * fo3; ); gf_on ? ( gv3 = mix - gf2; gv1 = gf_a1 * gf1 + gf_a2 * gv3; gv2 = gf2 + gf_a2 * gf1 + gf_a3 * gv3; gf1 = 2 * gv1 - gf1; gf2 = 2 * gv2 - gf2; mix = gv2; ) : ( gf1 = 0; gf2 = 0; ); // chorus / three-phase ensemble cbuf[cwp] = mix; ca = chor * chor_k; ca > 0.001 ? ( cps += crate * (1 + 0.15 * ins_fx) / srate; cps >= 1 ? cps -= 1; cpf += 5.5 / srate; cpf >= 1 ? cpf -= 1; aj = 0; t0 = 0; t1 = 0; t2 = 0; loop(3, d_ = (0.007 + ((crate > 2 ? 0.0006 : 0.0017) * sin(2 * $pi * cps + aj * 2.0944) + (three ? 0.0004 * sin(2 * $pi * cpf + aj * 2.0944) : 0)) * min(ca, 1.5)) * srate; rp2 = cwp - d_; ri = floor(rp2); rf = rp2 - ri; tv = cbuf[ri & cmask] * (1 - rf) + cbuf[(ri + 1) & cmask] * rf; aj == 0 ? t0 = tv : aj == 1 ? t1 = tv : t2 = tv; aj += 1; ); wet = min(ca, 1); oL = mix * (1 - 0.5 * wet) + wet * (t0 + 0.5 * t1) * 0.7; oR = mix * (1 - 0.5 * wet) + wet * (t2 + 0.5 * t1) * 0.7; ) : ( oL = mix; oR = mix; ); cwp = (cwp + 1) & cmask; // ---------- the Mod Rack ---------- mrL = oL; mrR = oR; mrOn ? mr_run(); oL = mrL; oR = mrR; // ---------- reverb send ---------- rv_on || rv_tail > 0.00001 ? ( rin = 0.5 * (oL + oR) * (rv_on ? 1 : 0); rpre_b[rpre_w] = rin; rq = rpre_w - floor(rpre); rq < 0 ? rq += rpre_len; rd = rpre_b[rq]; rpre_w += 1; rpre_w >= rpre_len ? rpre_w = 0; ak = 0; loop(4, rn = floor(rapl[ak] * srate / 48000 * (0.6 + 0.4 * rdiff)); ro = rap_b + ak * 4096; rw = rapw[ak]; rr = rw - rn; rr < 0 ? rr += 4096; rbv = ro[rr]; ryv = -rdiff * 0.75 * rd + rbv; ro[rw] = rd + rdiff * 0.75 * ryv; rd = ryv; rapw[ak] = (rw + 1) % 4096; ak += 1; ); ak = 0; loop(8, rlph[ak] += rlrt[ak] / srate; rlph[ak] >= 1 ? rlph[ak] -= 1; rm = rmod * srate * sin(2 * $pi * rlph[ak]); rp3 = rlw[ak] - rllen[ak] - rm; rp3 < 0 ? rp3 += RBLK; ri3 = floor(rp3); rf3 = rp3 - ri3; ro = rln_b + ak * RBLK; rv3 = ro[ri3 % RBLK] * (1 - rf3) + ro[(ri3 + 1) % RBLK] * rf3; rlz[ak] = rlgb[ak] * rv3 + rlga[ak] * rlz[ak]; rtmp[ak] = rlz[ak]; ak += 1; ); ra0 = rtmp[0]; ra1 = rtmp[1]; ra2 = rtmp[2]; ra3 = rtmp[3]; ra4 = rtmp[4]; ra5 = rtmp[5]; ra6 = rtmp[6]; ra7 = rtmp[7]; rb0 = ra0 + ra1; rb1 = ra0 - ra1; rb2 = ra2 + ra3; rb3 = ra2 - ra3; rb4 = ra4 + ra5; rb5 = ra4 - ra5; rb6 = ra6 + ra7; rb7 = ra6 - ra7; rc0 = rb0 + rb2; rc1 = rb1 + rb3; rc2 = rb0 - rb2; rc3 = rb1 - rb3; rc4 = rb4 + rb6; rc5 = rb5 + rb7; rc6 = rb4 - rb6; rc7 = rb5 - rb7; rmix[0] = (rc0 + rc4) * 0.35355339; rmix[1] = (rc1 + rc5) * 0.35355339; rmix[2] = (rc2 + rc6) * 0.35355339; rmix[3] = (rc3 + rc7) * 0.35355339; rmix[4] = (rc0 - rc4) * 0.35355339; rmix[5] = (rc1 - rc5) * 0.35355339; rmix[6] = (rc2 - rc6) * 0.35355339; rmix[7] = (rc3 - rc7) * 0.35355339; ak = 0; loop(8, ro = rln_b + ak * RBLK; ro[rlw[ak]] = rmix[ak] + rd * (ak & 1 ? -0.5 : 0.5); rlw[ak] += 1; rlw[ak] >= RBLK ? rlw[ak] = 0; ak += 1; ); rvL = (ra0 - ra2 + ra4 - ra6 + 0.5 * (ra1 + ra5)) * 0.5; rvR = (ra1 - ra3 + ra5 - ra7 + 0.5 * (ra2 - ra6)) * 0.5; rv_tail = max(abs(rvL), abs(rvR)) * 0.001 + rv_tail * 0.999; oL += rvL * rv_wet * 2.4; oR += rvR * rv_wet * 2.4; // +12 dB: the wet level now sits where it can be heard ); out_s += (out_t - out_s) * sm; ptr_s = ptr_t; oL = ostL.ost_band(oL * ptr_s) * out_s; oR = ostR.ost_band(oR * ptr_s) * out_s; ins_stereo(oL, oR); ost_out(ins_sl, ins_sr); // mono-maker / widener, then the output stage spl0 = ost_l; spl1 = ost_r; @gfx 960 570 // ===================================================================== // GUI - a top bar with the backlit LCD, then page 1 (LIST: every patch by group, click a name to play it) or // page 2 (EDIT: TONE, FILTER and AMP ENVELOPES, PLAY, REVERB and the patch's MOD RACK). Design space 1280 x 760 at qs = 0.75 * sc. // ===================================================================== ui_begin(960, 570); qs = sc*0.75; gfx_setfont(8, "Trebuchet MS", 13*qs, 'b'); gfx_setfont(9, "Courier New", 28*qs, 'b'); gfx_setfont(10, "Courier New", 17*qs, 'b'); gfx_setfont(11, "Trebuchet MS", 15*qs, 'b'); gfx_setfont(12, "Trebuchet MS", 40*qs, 'b'); gfx_setfont(13, "Trebuchet MS", 17*qs, 'b'); gfx_setfont(14, "Trebuchet MS", 19*qs, 'b'); gfx_setfont(15, "Courier New", 20*qs, 'b'); // patch-list names: the largest size (21 to 25) at which every name fits its row - worked out once per window size sc != p70_lsc ? ( p70_lsc = sc; p70_lfs = 25; fit_ = 0; loop(5, !fit_ ? ( gfx_setfont(17, "Trebuchet MS", p70_lfs*qs, 'b'); mw_ = 0; i_ = 0; loop(NP, gfx_measurestr(pname(i_), w_, h_); mw_ = max(mw_, w_); i_ += 1; ); mw_ <= 158*qs ? fit_ = 1 : p70_lfs -= 1; ); ); ); gfx_setfont(17, "Trebuchet MS", p70_lfs*qs, 'b'); BG = 0xB9BDC1; BG2 = 0xC9CCCF; BG3 = 0xA7ABB0; INK = 0x22262A; INK2 = 0x51575D; ACC = 0x2F6FB8; LB = 0xBFD0C4; LK = 0x16201C; KC = 0x6A6F76; AMB = 0xFFB030; FP3 = 0xB0B4B8; function R(x, y, w, h) ( gfx_rect(x*qs, y*qs, max(1, w*qs), max(1, h*qs)); ); function RR(x, y, w, h, r) ( rd_rr(x*qs, y*qs, w*qs, h*qs, r*qs); ); function TX(x, y, t) ( gfx_x = x*qs; gfx_y = y*qs; gfx_drawstr(t); ); function TC(cx, y, t) local(w, h) ( gfx_measurestr(t, w, h); gfx_x = cx*qs - w*0.5; gfx_y = y*qs; gfx_drawstr(t); ); function inbox(x, y, w, h) ( mouse_x >= x*qs && mouse_x < (x + w)*qs && mouse_y >= y*qs && mouse_y < (y + h)*qs; ); function hitbox(x, y, w, h) local(h_) ( h_ = pressed && drag_id == 0 && inbox(x, y, w, h); h_ ? drag_id = -1; h_; ); function setmsg(n, v) ( strcpy(#lcdn, n); strcpy(#lcdv, v); lcd_t = time_precise(); ); function setv(idx, v) ( slider(idx) = v; ui_auto(idx); ); function tog(idx) ( slider(idx) = slider(idx) < 0.5; ui_auto(idx); ); function touch(idx, name, val) ( drag_id == 1600 + idx ? setmsg(name, val); ); function sect(x, y, w, h, t) ( ui_col(BG3); RR(x, y, w, h, 6); ui_col(BG2); RR(x + 2, y + 2, w - 4, h - 4, 5); gfx_setfont(13); ui_col(ACC); TX(x + 12, y + 8, t); ); // knob on a slider: value on hover / drag only (house style); its name and value go to the LCD while turning function knob(idx, cx, cy, r, lo, hi, def, lg, cap, label, val) ( dy_kst = 7; dy_ink = INK; dy_ntick = 11; dy_knob(cx*0.75, cy*0.75, r*0.75, idx, lo, hi, def, lg, cap, label, val); touch(idx, label, val); ); function sknob(idx, cx, cy, r, lo, hi, def, cap, label, val) ( knob(idx, cx, cy, r, lo, hi, def, 0, cap, label, val); slider(idx) != floor(slider(idx) + 0.5) ? slider(idx) = floor(slider(idx) + 0.5); ); // a small lit switch with its text inside function chip(x, y, w, h, t, on) local(hov) ( hov = inbox(x, y, w, h); ui_col(on ? ACC : 0xE6E8EA); RR(x, y, w, h, 4); ui_cola(INK, hov ? 0.6 : 0.3); gfx_rect(x*qs, y*qs, w*qs, h*qs, 0); gfx_setfont(11); ui_col(on ? 0xFFFFFF : INK); TC(x + w*0.5, y + h*0.5 - 8, t); hitbox(x, y, w, h); ); function fms(v) ( v >= 1000 ? sprintf(#vt, "%.2f s", v/1000) : sprintf(#vt, "%d ms", floor(v + 0.5)); #vt; ); function fpc(v) ( sprintf(#vt, "%d%%", floor(v + 0.5)); #vt; ); function fdiv(i, md) ( strcpy(#dv, i == 0 ? "4 BARS" : i == 1 ? "2 BARS" : i == 2 ? "1 BAR" : i == 3 ? "1/2" : i == 4 ? "1/4" : i == 5 ? "1/8" : i == 6 ? "1/16" : "1/32"); md == 2 ? strcat(#dv, " D") : md == 3 ? strcat(#dv, " T"); #dv; ); // one Mod Rack module; kind 0 tremolo, 1 chorus, 2 vibe, 3 delay (chorus and delay have a MIX knob) function mrmod(mx, kind) local(b, hm, md, k, on, x_, i_l, i_sy, i_dv, cap) ( b = kind == 0 ? 28 : kind == 1 ? 19 : kind == 2 ? 36 : 44; hm = kind == 1 || kind == 3; i_l = b + 3 + hm; i_sy = b + 6 + hm; i_dv = b + 7 + hm; cap = kind == 0 ? 0xC8A23A : kind == 1 ? 0x2FB3A8 : kind == 2 ? 0x9A6A3C : 0x5A8FD0; ui_col(FP3); RR(mx, 548, 304, 142, 6); ui_col(cap); RR(mx, 548, 304, 5, 2); gfx_setfont(13); ui_col(INK); TX(mx + 12, 562, kind == 0 ? "TREMOLO" : kind == 1 ? "CHORUS" : kind == 2 ? "VIBE" : "DELAY"); md = floor(slider(i_sy) + 0.5); chip(mx + 110, 558, 76, 26, md <= 1 ? "SYNC" : md == 2 ? "SYNC D" : "SYNC T", md > 0) ? ( setv(i_sy, (md + 1) % 4); setmsg(kind == 3 ? "DELAY TIME" : "RATE", md == 0 ? "SYNC STRAIGHT" : md == 1 ? "SYNC DOTTED" : md == 2 ? "SYNC TRIPLET" : kind == 3 ? "IN MS" : "IN HZ"); ); k = 0; loop(3, on = slider(i_l + k) > 0.5; chip(mx + 196 + k*35, 558, 31, 26, k == 0 ? "L" : k == 1 ? "C" : "R", on) ? tog(i_l + k); k += 1; ); x_ = mx + 152 - (hm ? 80 : 40); // the knobs sit centred in the module md > 0 ? ( sknob(i_dv, x_, 626, 22, 0, 7, 4, cap, kind == 3 ? "TIME" : "RATE", fdiv(slider(i_dv), md)); ) : kind == 3 ? ( knob(b, x_, 626, 22, 20, 1500, 350, 1, cap, "TIME", fms(slider(b))); ) : ( sprintf(#mr0, "%.2f Hz", slider(b)); knob(b, x_, 626, 22, kind == 1 ? 0.05 : 0.1, kind == 1 ? 8 : kind == 0 ? 15 : 12, 1, 1, cap, "RATE", #mr0); ); kind == 3 ? knob(b + 1, x_ + 80, 626, 22, 0, 95, 30, 0, cap, "FDBK", fpc(slider(b + 1))) : knob(b + 1, x_ + 80, 626, 22, 0, 100, 50, 0, cap, "DEPTH", fpc(slider(b + 1))); hm ? knob(b + 2, x_ + 160, 626, 22, 0, 100, 0, 0, cap, "MIX", fpc(slider(b + 2))); ); // --------------------------------------------------------------------- ui_col(BG); gfx_rect(0, 0, gfx_w, gfx_h); cp_ = floor(slider1 + 0.5); // ---- top bar ---- ui_col(0x2A2E33); R(0, 0, 1280, 150); gfx_gradrect(0, 0, 1280*qs, 60*qs, 1, 1, 1, 0.05, 0, 0, 0, 0, 0, 0, 0, -0.05/(60*qs)); ui_col(ACC); gfx_circle(48*qs, 56*qs, 22*qs, 1, 1); gfx_setfont(2); ui_col(0xFFFFFF); ui_text(48*qs, 49*qs, "GFX"); gfx_setfont(12); ui_col(0xEDEDEA); TX(82, 30, "G POCKET 70"); gfx_setfont(11); ui_col(0xA6ACB2); TX(84, 82, "SOUND MODULE - 90 PATCHES"); // the backlit LCD: group, patch number and name (a knob's name and value while it turns) ui_col(0x101214); R(360, 18, 470, 114); ui_col(LB); R(366, 24, 458, 102); gfx_gradrect(366*qs, 24*qs, 458*qs, 102*qs, 1, 1, 1, 0.08, 0, 0, 0, 0, 0, 0, 0, -0.08/(102*qs)); ui_col(LK); time_precise() - lcd_t < 1.5 ? ( gfx_setfont(10); TX(380, 34, #lcdn); gfx_setfont(9); TX(380, 66, #lcdv); ) : ( gfx_setfont(10); strcpy(#l1, grp_name(pgrp(cp_))); TX(380, 34, #l1); gfx_setfont(9); sprintf(#l2, "%02d ", cp_ + 1); strcat(#l2, pname(cp_)); TX(380, 66, #l2); ); ui_button(842*qs, 24*qs, 42*qs, 102*qs, "<", 0, 1) ? ( setv(1, (cp_ + NP - 1) % NP); ); ui_button(888*qs, 24*qs, 42*qs, 102*qs, ">", 0, 1) ? ( setv(1, (cp_ + 1) % NP); ); rd_sqbg = 0x55595E; hitbox(360, 18, 470, 114) ? p70_page = 0; // click the LCD for the patch list rd_sq(952*0.75, 24*0.75, 74*0.75, 32*0.75, p70_page != 0, AMB, "EDIT") ? p70_page = 1; rd_led(964*0.75, 104*0.75, 5*0.75, ins_midi_lit(), 0x46D86A); gfx_setfont(11); ui_col(0xA6ACB2); TX(978, 96, "MIDI IN"); dy_kst = 7; dy_ink = 0xD8D8D2; dy_ntick = 11; sprintf(#mv, "%+.1f dB", slider2); dy_knob(1172*0.75, 58*0.75, 24*0.75, 2, -24, 6, 0, 0, 0x9DA2A8, "VOLUME", #mv); ui_size_picker(1180*qs, 124*qs); p70_page == 0 ? ( // ---- page 1: every patch, by group, in six recessed column cards - click a name to play it ---- c_ = 0; loop(6, tx_ = 8 + c_*212; ui_col(BG3); RR(tx_ - 2, 156, 208, 594, 7); ui_col(BG2); RR(tx_, 158, 204, 590, 6); c_ += 1; ); e_ = 0; p_ = 0; g_ = 0; loop(NP + 10, col_ = floor(e_/18); row_ = e_ % 18; tx_ = 8 + col_*212; ty_ = 160 + row_*32.6; p_ == grp_start(g_) && g_ < 10 ? ( row_ == 17 ? ( e_ += 1; col_ = floor(e_/18); row_ = 0; tx_ = 8 + col_*212; ty_ = 160; ); // no heading at a column's foot // group heading: a dark label bar with a blue tab ui_col(0x3A3E43); RR(tx_ + 3, ty_ + 2, 198, 28, 4); ui_col(ACC); RR(tx_ + 3, ty_ + 2, 5, 28, 2); gfx_setfont(14); gfx_measurestr(grp_name(g_), w_, h_); w_ > 180*qs ? ( gfx_setfont(13); gfx_measurestr(grp_name(g_), w_, h_); ); ui_col(0xFFFFFF); gfx_x = (tx_ + 15)*qs; gfx_y = (ty_ + 16)*qs - h_*0.5; gfx_drawstr(grp_name(g_)); g_ += 1; ) : ( on_ = p_ == cp_; hv_ = inbox(tx_, ty_, 204, 31); // zebra rows, hover and the selected patch on_ ? ( ui_col(ACC); RR(tx_ + 3, ty_ + 1, 198, 30, 4); ) : hv_ ? ( ui_col(BG3); RR(tx_ + 3, ty_ + 1, 198, 30, 4); ) : row_ % 2 ? ( ui_cola(0xFFFFFF, 0.25); R(tx_ + 3, ty_ + 1, 198, 30); ); gfx_setfont(15); ui_col(on_ ? 0xFFFFFF : INK2); sprintf(#pe, "%02d", p_ + 1); gfx_measurestr(#pe, w_, h_); gfx_x = (tx_ + 8)*qs; gfx_y = (ty_ + 16)*qs - h_*0.5; gfx_drawstr(#pe); gfx_setfont(17); ui_col(on_ ? 0xFFFFFF : INK); gfx_measurestr(pname(p_), w_, h_); gfx_x = (tx_ + 38)*qs; gfx_y = (ty_ + 16)*qs - h_*0.5; gfx_drawstr(pname(p_)); hitbox(tx_, ty_, 204, 31) ? setv(1, p_); p_ += 1; ); e_ += 1; ); ) : ( // ---- page 2: EDIT ---- ui_col(0x3A3E43); RR(12, 160, 1256, 44, 6); gfx_setfont(14); ui_col(0xFFFFFF); sprintf(#et, "%02d ", cp_ + 1); strcat(#et, pname(cp_)); TX(28, 171, #et); gfx_setfont(11); ui_col(0xA6ACB2); strcpy(#eg, grp_name(pgrp(cp_))); TX(420, 174, #eg); gfx_setfont(11); ui_col(0xA6ACB2); TX(760, 174, "Centre = the patch as made - choosing a patch resets these"); // TONE, FILTER ENVELOPE, AMP ENVELOPE sect(12, 214, 310, 168, "TONE"); sprintf(#q5, "%+d", floor(slider5 - 50 + 0.5)); knob(5, 73, 290, 26, 0, 100, 50, 0, 0x3D70CC, "TONE", #q5); sprintf(#q6, "%+.2f oct", slider6); knob(6, 167, 290, 26, -6, 3, 0, 0, 0x3D70CC, "FILTER", #q6); knob(7, 261, 290, 26, 0, 100, 0, 0, 0x3D70CC, "RESONANCE", fpc(slider7)); sect(344, 214, 498, 168, "FILTER ENVELOPE"); knob(55, 405, 290, 26, 0, 200, 100, 0, 0x3D70CC, "AMOUNT", fpc(slider55)); knob(56, 499, 290, 26, 10, 400, 100, 1, 0x3D70CC, "ATTACK", fpc(slider56)); knob(57, 593, 290, 26, 10, 400, 100, 1, 0x3D70CC, "DECAY", fpc(slider57)); sprintf(#q58, "%+d", slider58); knob(58, 687, 290, 26, -100, 100, 0, 0, 0x3D70CC, "SUSTAIN", #q58); knob(59, 781, 290, 26, 10, 400, 100, 1, 0x3D70CC, "RELEASE", fpc(slider59)); (eng >= 1 && eng <= 5) || eng == 7 ? ( // this patch has no filter envelope: dim the row ui_cola(BG2, 0.7); RR(346, 236, 494, 144, 5); gfx_setfont(11); ui_col(INK2); TX(560, 222, "(not on this patch)"); ); sect(864, 214, 404, 168, "AMP ENVELOPE"); knob(8, 925, 290, 26, 10, 400, 100, 1, 0x33A052, "ATTACK", fpc(slider8)); knob(53, 1019, 290, 26, 10, 400, 100, 1, 0x33A052, "DECAY", fpc(slider53)); sprintf(#q54, "%+d", slider54); knob(54, 1113, 290, 26, -100, 100, 0, 0, 0x33A052, "SUSTAIN", #q54); knob(9, 1207, 290, 26, 10, 400, 100, 1, 0x33A052, "RELEASE", fpc(slider9)); ui_cola(BG2, 0.7); // dim what this patch type has no use for (eng >= 1 && eng <= 5) || eng == 7 ? ( RR(881, 252, 88, 120, 6); RR(1069, 252, 88, 120, 6); ); // ATTACK, SUSTAIN eng == 5 || eng == 7 ? RR(975, 252, 88, 120, 6); // DECAY eng == 7 ? RR(1163, 252, 88, 120, 6); // RELEASE sect(12, 390, 490, 144, "PLAY"); knob(11, 80, 460, 22, 0, 100, 70, 0, KC, "VELOCITY", fpc(slider11)); sprintf(#q12, "%+d c", slider12); knob(12, 180, 460, 22, -50, 50, 0, 0, KC, "TUNE", #q12); sprintf(#q13, "%d st", slider13); sknob(13, 280, 460, 22, 0, 12, 2, KC, "BEND", #q13); gfx_setfont(11); ui_col(INK); TX(352, 428, "MIDI CH"); chip(352, 448, 120, 32, slider4 < 0.5 ? "OMNI" : sprintf(#ch, "%d", slider4), 0) ? ( gfx_x = 352*qs; gfx_y = 480*qs; k_ = gfx_showmenu("Omni|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16"); k_ > 0 ? setv(4, k_ - 1); ); sect(512, 390, 756, 144, "REVERB"); k_ = 0; loop(3, chip(640 + k_*112, 396, 104, 26, k_ == 0 ? "ROOM" : k_ == 1 ? "HALL" : "PLATE", floor(slider14 + 0.5) == k_) ? setv(14, k_); k_ += 1; ); sprintf(#q15, "%d ms", slider15); knob(15, 700, 462, 24, 0, 150, 15, 0, 0xC8862A, "PRE", #q15); sprintf(#q16, "%.1f s", slider16); knob(16, 840, 462, 24, 0.2, 10, 2.2, 1, 0xC8862A, "DECAY", #q16); knob(17, 980, 462, 24, 0, 100, 50, 0, 0xC8862A, "DAMP", fpc(slider17)); knob(18, 1120, 462, 24, 0, 100, 25, 0, 0xC8862A, "MIX", fpc(slider18)); // the patch's MOD RACK sect(12, 542, 1256, 152, ""); mrmod(20, 0); mrmod(332, 1); mrmod(644, 2); mrmod(956, 3); // output ui_col(BG3); R(0, 700, 1280, 60); gfx_setfont(13); ui_col(ACC); TX(24, 720, "OUTPUT"); ins_io(110*0.75, 708*0.75, 70, INK); sprintf(#q76, "%d Hz", slider76); knob(76, 760, 730, 14, 20, 500, 20, 1, KC, "", #q76); gfx_setfont(11); ui_col(INK); TX(620, 722, "MONO BELOW"); knob(77, 960, 730, 14, 0, 100, 0, 0, KC, "", fpc(slider77)); gfx_setfont(11); ui_col(INK); TX(860, 722, "WIDTH"); ); pk_end(); ui_end();