desc:GFX G Lab80 //tags: instrument synth workstation fm epiano clav glockenspiel pad bass strings //author: JGWizrad / Garden FX (GFX) // // Requires gfx-drift, gfx-output, gfx-ui, gfx-panel and gfx-instrument (.jsfx-inc) in the same folder. // DRIFT: GFX instrument standard (pitch, per-note tuning, filter, chorus speed). // // G-Lab80 (formerly Sound Lab / Palette): pick a sound, play it. File name kept so saved projects still find it. // FM E-PIANO - 4-operator FM (tine "ding" pair + body pair), velocity sets the bark // CLAV - plucked string (Karplus-Strong) + pickup comb + bite filter, quick damper // GLOCK - struck metal bar: inharmonic partials, mallet click, rings on // SYNTH PAD - detuned saws, 4-pole filter with slow envelope, chorus // WARM PAD - saw + sub, low filter with slow movement, wide chorus // BASS SYNTH - mono with glide: saw + sub, punchy filter envelope // STRINGS - detuned saws, slow attack, delayed vibrato // STR ENSEMBLE - bright saws into a three-phase ensemble // PRESETS (or a click on the display) lists the sounds by type; < > step through them in that order: // PIANOS & KEYS - SESSION PIANO and BRIGHT PIANO (openly synthetic: struck partials with stretched tuning and // paired strings; velocity sets the hammer's brightness, the loudness, the knock and how fast // the top fades), CHORUS EP, FM E-PIANO, CLAV, DRAWBAR ORGAN // MALLETS & BELLS - GLOCKENSPIEL, FANTASY BELLS, CRYSTAL HARP, STACCATO GLASS (with its echo) // GUITARS & PLUCKS - LA NYLON, LA STEEL, LA CLEAN and LA HARMONICS (late-80s plucked guitars: a plucked string // with a pick transient over a soft synth body), NYLON ATMOS, PIZZ FLOW, HARP // PADS - SYNTH PAD, WARM PAD, SOUNDTRACK PAD, NATIVE DANCE (a tempo-synced log-drum loop over a // resonant sweep) // CHOIRS & VOICES - GLASS VOICES, DARK VOX, FANTASY VOX, SPACED VOX // STRINGS & ORCH - STRINGS, STRING ENSEMBLE, FAT STRINGS, ORCHESTRA HIT // BRASS & LEADS - BRASS SECTION, SYNTH BRASS, VELO STAB, HOOVER, SQUARE LEAD, CALLIOPE LEAD, PAN FLUTE // (the pipes breathe through a pitched band, not open hiss) // BASSES - BASS SYNTH, SUB, ACID, ROUND, PLUCK, HOLLOW, REESE (most are mono with glide) // Some sounds carry their own tempo-synced echo, tremolo or rotary speed. // Changing sound puts FILTER, RESO, TONE, ATTACK, RELEASE and CHORUS back to neutral for the new sound. // REVERB: the GFX Space engine (ROOM / HALL / PLATE), added as a send on top of the sound. // FILTER / RESONANCE: analogue sounds move each note's own 4-pole filter (RESONANCE up to self-oscillation); // FM e-piano, clav and glock go through a resonant low-pass (FILTER 0 = wide open). // Macros: TONE, ATTACK, RELEASE, CHORUS, VELOCITY, TUNE. Sustain pedal (CC64) and mod wheel (vibrato). 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 slider1:0<0,42,1{FM E-Piano,Clav,Glockenspiel,Synth Pad,Warm Pad,Bass Synth,Strings,String Ensemble,Fantasy Bells,Staccato Glass,Pizz Flow,Glass Voices,Nylon Atmos,Synth Brass,Crystal Harp,Sub Bass,Acid Bass,Round Bass,Pluck Bass,Hollow Bass,Reese Bass,Native Dance,Calliope Lead,Soundtrack Pad,Session Piano,Chorus EP,Dark Vox,Fantasy Vox,Spaced Vox,Velo Stab,Hoover,Fat Strings,Orchestra Hit,Brass Section,Drawbar Organ,Pan Flute,Harp,Square Lead,Bright Piano,LA Nylon,LA Steel,LA Clean,LA Harmonics}>-Sound slider2:50<0,100,1>-Tone (%) slider3:100<10,400,1>-Attack (%) slider4:100<10,400,1>-Release (%) slider5:100<0,200,1>-Chorus (%) slider6:70<0,100,1>-Velocity (%) slider7:0<-50,50,1>-Tune (cents) slider8:25<0,100,1>-Drift (%) slider9:0<0,16,1>-MIDI channel (0 = omni) slider10:0<-24,12,0.1>-Output (dB) slider11:0<0,100,1>-Band sat (%) slider12:30<0,100,1>-Bias (%) slider13:120<40,400,1>-Sat low band (Hz) slider14:6000<2000,16000,10>-Sat high band (Hz) slider15:-0.3<-24,0,0.1>-Ceiling / limit threshold (dB) slider16:1<0,2,1{Off,Clip,Limit}>-Output stage slider17:0<-6,3,0.01>-Filter (octaves) slider18:0<0,100,1>-Resonance (%) slider19:1<0,2,1{Room,Hall,Plate}>-Reverb type slider20:15<0,150,1>-Reverb pre-delay (ms) slider21:2.2<0.2,10,0.01>-Reverb decay (s) slider22:50<0,100,1>-Reverb damping (%) slider23:25<0,100,1>-Reverb mix (%) slider24:20<20,500,1>-Mono below (Hz, 20 = off) slider25:0<0,100,1>-Stereo width (%) in_pin:none out_pin:left output out_pin:right output @init #ui_man = "gfx-g-lab80"; // the ? pop-up links to this manual NV = 12; VS = 172; VB = 1000; // voice blocks: VB + v * 64 // 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 = 30000; KSL = 4096; // clav string delay lines, one per voice evq = 4000; // MIDI event queue cbuf = 8192; cmask = 8191; // chorus delay line 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; 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] * 0.8; // the damper: a fast stop when the key lifts 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 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 == 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; DLB = 400000; memset(DLB, 0, 262144); dl_w = 0; dl_tail = 0; dlpL = 0; dlpR = 0; trph = 0; bt_pos = 0; nd_last = -1; dl_len = 24000; function rv_update() local(i, sz, L, gl, gh, a, t60) ( rtyp = slider19; sz = rtyp == 0 ? 0.42 : rtyp == 1 ? 1 : 0.55; rdiff = rtyp == 2 ? 0.95 : 0.75; rpre = slider20 * 0.001 * srate; t60 = slider21 * 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 * slider22 / 100) * srate * (rtyp == 2 ? 1.4 : 1))); a = (gl - gh) / (gl + gh); rlga[i] = a; rlgb[i] = gl * (1 - a); i += 1; ); rv_wet = slider23 / 100; rv_on = rv_wet > 0.001; ); function update() ( slider1 != snd ? ( snd >= 0 ? ( // a new sound starts from its own settings: the sound-shaping knobs go back to neutral slider17 = 0; slider18 = 0; slider2 = 50; slider3 = 100; slider4 = 100; slider5 = 100; sliderchange(slider2); sliderchange(slider3); sliderchange(slider4); sliderchange(slider5); sliderchange(slider17); sliderchange(slider18); ); kill_all(); patch_set(slider1); ); tone = slider2 / 100; atk_k = slider3 / 100; rel_k = slider4 / 100; dec_k = 1; chor_k = slider5 / 100; sens = slider6 / 100; tune = 2 ^ (slider7 / 1200); drift = slider8 / 100; chan = slider9; out_t = 10 ^ (slider10 / 20); ins_output_setup(11); ins_stereo_setup(24); filt_oct = slider17; reso = slider18 / 100; rv_update(); ); // ---------- sound names + menu order (grouped) ---------- function sname(i) ( i == 0 ? "FM E-PIANO" : i == 1 ? "CLAV" : i == 2 ? "GLOCKENSPIEL" : i == 3 ? "SYNTH PAD" : i == 4 ? "WARM PAD" : i == 5 ? "BASS SYNTH" : i == 6 ? "STRINGS" : i == 7 ? "STRING ENSEMBLE" : i == 8 ? "FANTASY BELLS" : i == 9 ? "STACCATO GLASS" : i == 10 ? "PIZZ FLOW" : i == 11 ? "GLASS VOICES" : i == 12 ? "NYLON ATMOS" : i == 13 ? "SYNTH BRASS" : i == 14 ? "CRYSTAL HARP" : i == 15 ? "SUB BASS" : i == 16 ? "ACID BASS" : i == 17 ? "ROUND BASS" : i == 18 ? "PLUCK BASS" : i == 19 ? "HOLLOW BASS" : i == 20 ? "REESE BASS" : i == 21 ? "NATIVE DANCE" : i == 22 ? "CALLIOPE LEAD" : i == 23 ? "SOUNDTRACK PAD" : i == 24 ? "SESSION PIANO" : i == 25 ? "CHORUS EP" : i == 26 ? "DARK VOX" : i == 27 ? "FANTASY VOX" : i == 28 ? "SPACED VOX" : i == 29 ? "VELO STAB" : i == 30 ? "HOOVER" : i == 31 ? "FAT STRINGS" : i == 32 ? "ORCHESTRA HIT" : i == 33 ? "BRASS SECTION" : i == 34 ? "DRAWBAR ORGAN" : i == 35 ? "PAN FLUTE" : i == 36 ? "HARP" : i == 37 ? "SQUARE LEAD" : i == 38 ? "BRIGHT PIANO" : i == 39 ? "LA NYLON" : i == 40 ? "LA STEEL" : i == 41 ? "LA CLEAN" : "LA HARMONICS"; ); mord = 900; // menu order, by type NSND = 43; mord[0] = 24; mord[1] = 38; mord[2] = 25; mord[3] = 0; mord[4] = 1; mord[5] = 34; mord[6] = 2; mord[7] = 8; mord[8] = 14; mord[9] = 9; mord[10] = 39; mord[11] = 40; mord[12] = 41; mord[13] = 42; mord[14] = 12; mord[15] = 10; mord[16] = 36; mord[17] = 3; mord[18] = 4; mord[19] = 23; mord[20] = 21; mord[21] = 11; mord[22] = 26; mord[23] = 27; mord[24] = 28; mord[25] = 6; mord[26] = 7; mord[27] = 31; mord[28] = 32; mord[29] = 33; mord[30] = 13; mord[31] = 29; mord[32] = 30; mord[33] = 37; mord[34] = 22; mord[35] = 35; mord[36] = 5; mord[37] = 15; mord[38] = 16; mord[39] = 17; mord[40] = 18; mord[41] = 19; mord[42] = 20; NGRP = 8; GST = 960; GSZ = 970; GST[0] = 0; GSZ[0] = 6; GST[1] = 6; GSZ[1] = 4; GST[2] = 10; GSZ[2] = 7; GST[3] = 17; GSZ[3] = 4; GST[4] = 21; GSZ[4] = 4; GST[5] = 25; GSZ[5] = 4; GST[6] = 29; GSZ[6] = 7; GST[7] = 36; GSZ[7] = 7; function grp_name(k) ( k == 0 ? "PIANOS & KEYS" : k == 1 ? "MALLETS & BELLS" : k == 2 ? "GUITARS & PLUCKS" : k == 3 ? "PADS" : k == 4 ? "CHOIRS & VOICES" : k == 5 ? "STRINGS & ORCHESTRA" : k == 6 ? "BRASS & LEADS" : "BASSES"; ); function grp_menu(k) ( k == 0 ? "Pianos & Keys" : k == 1 ? "Mallets & Bells" : k == 2 ? "Guitars & Plucks" : k == 3 ? "Pads" : k == 4 ? "Choirs & Voices" : k == 5 ? "Strings & Orchestra" : k == 6 ? "Brass & Leads" : "Basses"; ); function snd_pos(sn) local(i, q) ( q = 0; i = 0; loop(NSND, mord[i] == sn ? q = i; i += 1; ); q; ); function pos_grp(q) local(k, g) ( g = 0; k = 0; loop(NGRP, q >= GST[k] ? g = k; k += 1; ); g; ); // the sound list, grouped into sub-menus by type function snd_menu(x, y) local(i, k, sel) ( #sm = ""; i = 0; loop(NSND, k = pos_grp(i); i == GST[k] ? ( strcat(#sm, ">"); strcat(#sm, grp_menu(k)); strcat(#sm, "|"); ); i == GST[k] + GSZ[k] - 1 ? strcat(#sm, "<"); slider1 == mord[i] ? strcat(#sm, "!"); strcat(#sm, sname(mord[i])); i < NSND - 1 ? strcat(#sm, "|"); i += 1; ); gfx_x = x; gfx_y = y; sel = gfx_showmenu(#sm); sel > 0 ? ( slider1 = mord[sel - 1]; slider_automate(1); ); ); // ---------- 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)); // per-patch level trim: keeps the hottest patches out of the output clipper (measured with 8 notes at full // velocity, worst case held under -3 dBFS); the quieter patches are left as they are function patch_trim(p) ( p == 0 ? 0.582 : p == 1 ? 0.339 : p == 2 ? 0.359 : p == 3 ? 0.543 : p == 4 ? 0.376 : p == 5 ? 0.989 : p == 6 ? 0.468 : p == 7 ? 0.351 : p == 8 ? 0.473 : p == 9 ? 0.543 : p == 10 ? 0.708 : p == 11 ? 0.427 : p == 12 ? 0.822 : p == 13 ? 0.432 : p == 14 ? 0.631 : p == 15 ? 0.851 : p == 16 ? 1.000 : p == 17 ? 1.000 : p == 18 ? 0.335 : p == 19 ? 0.785 : p == 20 ? 1.000 : p == 21 ? 0.955 : p == 22 ? 0.316 : p == 23 ? 0.966 : p == 24 ? 1.122 : p == 25 ? 0.501 : p == 26 ? 0.363 : p == 27 ? 0.452 : p == 28 ? 0.822 : p == 29 ? 0.610 : p == 30 ? 0.407 : p == 31 ? 0.582 : p == 32 ? 0.359 : p == 33 ? 0.624 : p == 34 ? 0.716 : p == 35 ? 0.266 : p == 36 ? 2.018 : p == 37 ? 0.473 : p == 38 ? 1.230 : p == 39 ? 1.413 : p == 40 ? 2.188 : p == 41 ? 1.567 : p == 42 ? 0.575 : 1.000; ); ptr_s = patch_trim(slider1); pkL = 0; pkR = 0; midi_led = 0; nact = 0; vph = 0; flph = 0; !ui_dflt ? ui_thm = 10; !ui_dflt ? ui_hw = 1; // fixed late-80s workstation faceplate !ui_dflt ? ui_kstyle = 0; BRW = 0x3A2E28; INKL = 0xE8DED2; TEAL = 0x2FB5A0; REDL = 0xFF3A2A; SH1 = 0x463830; SH2 = 0x403229; SH3 = 0x372B24; // macros, reverb, utility function mgroup(x, y, w, h, sec, title, shade) ( pk_inset(x * sc, y * sc, w * sc, h * sc, shade); pk_box(x * sc, y * sc, w * sc, h * sc, TEAL, title); ui_section(sec == 0 ? 2 : sec); C_INK = INKL; ); snd = -1; update(); out_s = out_t; ui_dflt = 1; // theme defaults above apply once: @init re-runs (playback start, device reset) must not undo the saved theme @slider update(); @block evn = 0; while (midirecv(mofs, m1, m2, m3)) ( stt = m1 & 0xF0; mch = (m1 & 0x0F) + 1; (chan == 0 || mch == chan) && evn < 512 ? ( evq[evn * 4] = mofs; evq[evn * 4 + 1] = stt; evq[evn * 4 + 2] = m2; evq[evn * 4 + 3] = m3; evn += 1; ); midisend(mofs, m1, m2, m3); ); evi = 0; spos = 0; panic_req ? ( all_off(); panic_req = 0; ); update(); ins_drift_block(drift, samplesblock); // GFX instrument drift pdrift = ins_pitch; // envelope coefficients (with the ATTACK / RELEASE macros) a_inc = 1 / max(max(aA * atk_k, 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 * atk_k, 0.002) * srate, 1); a_dec = tc(aD); a_rel = tc(aR * rel_k); f_dec = tc(fD); 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 sounds (FILTER 0 and no RESONANCE = bypassed) gf_on = eng != 0 && (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; // echo time (beats) dl_len = min(floor(dl_bt * 60 / tempo * srate), 131000); @serialize file_var(0, ui_sz); @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); midi_led = 1; 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; 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 == 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 + (b[F_AE] - aS) * 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 + (b[F_FE] - fS) * f_dec; ) : ( b[F_AE] *= a_rel; b[F_FE] *= a_rel; ); // 4-pole filter fc = fbase * 2 ^ (famt * 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; // tremolo (stereo, as an autopan) trem > 0 ? ( trph += 4.6 / srate; trph -= floor(trph); tw = sin(2 * $pi * trph) * trem; oL *= 1 - tw; oR *= 1 + tw; ); // tempo-synced ping-pong echo dl_mix > 0 || dl_tail > 0.00001 ? ( drp = dl_w - dl_len; drp < 0 ? drp += 131072; dyL = DLB[drp]; dyR = DLB[131072 + drp]; dlpL += (dyL - dlpL) * 0.35; dlpR += (dyR - dlpR) * 0.35; // each repeat a little darker DLB[dl_w] = (oL + oR) * 0.5 * (dl_mix > 0) + dlpR * dl_fb; DLB[131072 + dl_w] = dlpL * dl_fb; dl_w = (dl_w + 1) % 131072; oL += dyL * dl_mix * 1.4; oR += dyR * dl_mix * 1.4; dl_tail = max(abs(dyL), abs(dyR)) * 0.001 + dl_tail * 0.999; ); // ---------- 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 * 0.6; oR += rvR * rv_wet * 0.6; ); out_s += (out_t - out_s) * sm; ptr_s = patch_trim(slider1); // follows the patch at once (a patch change is a discrete event) 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; pkL = max(pkL, abs(spl0)); pkR = max(pkR, abs(spl1)); @gfx 640 420 ui_thm = 10; ui_hw = 1; ui_begin(640, 420); // ---------- chassis: dark brown workstation with teal accents ---------- ui_col(0x0B0C0D); gfx_rect(0, 0, gfx_w, gfx_h); fh = 412; // the panel, with the IN / OUT strip along the bottom pk_chassis(8 * sc, 4 * sc, 624 * sc, fh * sc, BRW); ui_col(TEAL); gfx_rect(8 * sc, 42 * sc, 624 * sc, 2 * sc); ui_col(TEAL); gfx_circle(36 * sc, 24 * sc, 14 * sc, 1, 1); gfx_setfont(4); ui_col(BRW); ui_text(36 * sc, 19 * sc, "GFX"); gfx_setfont(6, "Trebuchet MS", 20 * sc, 'b'); ui_col(INKL); gfx_x = 58 * sc; gfx_y = 12 * sc; gfx_drawstr("G-LAB80"); gfx_setfont(4); ui_cola(INKL, 0.6); gfx_x = 152 * sc; gfx_y = 20 * sc; gfx_drawstr("DIGITAL SOUND WORKSTATION"); ui_size_picker(448 * sc, 13 * sc); pk_ledbtn(520 * sc, 8 * sc, 32 * sc, 28 * sc, 0, REDL) ? panic_req = 1; gfx_setfont(4); ui_col(INKL); gfx_x = 558 * sc; gfx_y = 17 * sc; gfx_drawstr("PANIC"); // ---------- SOUND: PRESETS | < > | green LCD (click it for the list) ---------- cur_pos = snd_pos(slider1); cur_grp = pos_grp(cur_pos); ui_noled = 1; ui_button(20 * sc, 56 * sc, 86 * sc, 38 * sc, "PRESETS", 0, 1) ? snd_menu(20 * sc, 98 * sc); ui_noled = 1; ui_button(110 * sc, 56 * sc, 32 * sc, 38 * sc, "◄", 0, 1) ? ( slider1 = mord[(cur_pos + NSND - 1) % NSND]; slider_automate(1); ); ui_noled = 1; ui_button(146 * sc, 56 * sc, 32 * sc, 38 * sc, "►", 0, 1) ? ( slider1 = mord[(cur_pos + 1) % NSND]; slider_automate(1); ); ui_noled = 0; pk_lcd(188 * sc, 52 * sc, 436 * sc, 46 * sc, 1); pk_lcdfont(7, 18 * sc); ui_col(pk_lcdc); gfx_x = 200 * sc; gfx_y = 56 * sc; gfx_drawstr(sname(slider1)); pk_lcdfont(8, 11 * sc); sprintf(#ks, "%s %d/%d %02d SOUNDING%s", grp_name(cur_grp), cur_pos - GST[cur_grp] + 1, GSZ[cur_grp], nact, pedal ? " SUS" : ""); gfx_x = 200 * sc; gfx_y = 80 * sc; gfx_drawstr(#ks); pressed && drag_id == 0 && mouse_x >= 188 * sc && mouse_x < 624 * sc && mouse_y >= 52 * sc && mouse_y < 98 * sc ? ( drag_id = -1; snd_menu(188 * sc, 98 * sc); ); // ---------- MACROS ---------- mgroup(16, 112, 608, 92, 0, "MACROS", SH1); ui_knob(70 * sc, 156 * sc, 17, -6, 3, 0, 0, "FILTER", slider17 > -0.005 && slider17 < 0.005 ? "OPEN" : "%+.2f oct"); ui_knob(144 * sc, 156 * sc, 18, 0, 100, 0, 0, "RESO", "%.0f%%"); ui_knob(218 * sc, 156 * sc, 2, 0, 100, 50, 0, "TONE", "%.0f%%"); ui_knob(292 * sc, 156 * sc, 3, 10, 400, 100, 1, "ATTACK", "%.0f%%"); ui_knob(366 * sc, 156 * sc, 4, 10, 400, 100, 1, "RELEASE", "%.0f%%"); ui_knob(440 * sc, 156 * sc, 5, 0, 200, 100, 0, "CHORUS", "%.0f%%"); ui_knob(514 * sc, 156 * sc, 6, 0, 100, 70, 0, "VELOCITY", "%.0f%%"); ui_knob(588 * sc, 156 * sc, 7, -50, 50, 0, 0, "TUNE", "%+.0f cents"); // ---------- REVERB ---------- mgroup(16, 214, 608, 92, 0, "REVERB", SH2); i = 0; loop(3, pk_ledbtn(34 * sc, (224 + i * 26) * sc, 26 * sc, 22 * sc, slider19 == i, TEAL) ? ( slider19 = i; slider_automate(262144); ); gfx_setfont(5); ui_col(INKL); gfx_x = 68 * sc; gfx_y = (229 + i * 26) * sc; gfx_drawstr(i == 0 ? "ROOM" : i == 1 ? "HALL" : "PLATE"); i += 1; ); ui_knob(190 * sc, 258 * sc, 20, 0, 150, 15, 0, "PRE-DELAY", "%.0f ms"); ui_knob(300 * sc, 258 * sc, 21, 0.2, 10, 2.2, 1, "DECAY", "%.2f s"); ui_knob(410 * sc, 258 * sc, 22, 0, 100, 50, 0, "DAMPING", "%.0f%%"); ui_knob(540 * sc, 258 * sc, 23, 0, 100, 25, 0, "MIX", "%.0f%%"); // ---------- DRIFT ---------- mgroup(16, 316, 112, 92, 1, "DRIFT", SH3); ui_knob(72 * sc, 360 * sc, 8, 0, 100, 25, 0, "DRIFT", "%.0f%%"); // ---------- MIDI ---------- mgroup(136, 316, 214, 92, 3, "MIDI", SH3); knob_step = 1; ui_knob(186 * sc, 360 * sc, 9, 0, 16, 0, 0, "CHANNEL", slider9 == 0 ? "OMNI" : "CH %.0f"); pk_led(246 * sc, 345 * sc, 4 * sc, ins_midi_lit() || nact > 0, REDL); gfx_setfont(5); ui_col(INKL); gfx_x = 258 * sc; gfx_y = 338 * sc; gfx_drawstr("MIDI IN"); ui_cola(INKL, 0.8); gfx_x = 240 * sc; gfx_y = 360 * sc; gfx_drawstr("CC64 SUSTAIN"); gfx_x = 240 * sc; gfx_y = 378 * sc; gfx_drawstr("CC1 VIBRATO"); // ---------- MASTER ---------- mgroup(358, 316, 266, 92, 2, "MASTER", SH3); ui_knob(460 * sc, 360 * sc, 10, -24, 12, 0, 0, "OUTPUT", "%.1f dB"); mL.ui_ledm(570 * sc, 326 * sc, 16 * sc, 70 * sc, pkL); mR.ui_ledm(592 * sc, 326 * sc, 16 * sc, 70 * sc, pkR); pkL *= 0.85; pkR *= 0.85; gfx_setfont(4); ui_col(INKL); ui_text(590 * sc, 398 * sc, "OUT"); // ---------- IN / OUT strip: SAT, OUT, STEREO ---------- // ins_strip(16, 414, 608, 11, 24, TEAL, SH3); pk_end(); ui_end();