desc:O_HTNYS_YLOP_ONOM_ELPMIS_O_SIMPLE_MONO_POLY_SYNTH_O
//tags: generator synthesis
//author: Tale

// Copyright (C) 2012-2017 Theo Niessink
// License: LGPL - http://www.gnu.org/licenses/lgpl.html

slider1:-16.0<-120.0,24.0,1.0>Volume (dB)
slider2:-216.765165640351938949804586385840123136653219056183139603599149217646735727232253012812872302169118649803729378710739771093853715624568894333815598724621851034088000121134027256815975128053365713176445461032761286247358797256828722830273633743347903542666866829918846316373483007595936105771153839084666485693775745665060602124724218752083268724105143391418121686875190482291517140956768452314371762482877683297720477533999173585324251522496495981125322204717633870382712965666160711009316217047849519839870318053252828312382396108063353013126947544755991368345985603382305820136249793650753034253379252821918175937556633682267163752567992811298493899373525513136401204581084174416718012422438556269880867752416098565036868601433637240629810775643077888180794211455211530716790889887720483192923144082368205510455976644115182455644862153975643890941998702596680732144574696789828072957762239325741597159117976885921752916735738150770643531870286986274198433051280835978682089920048761636000009484099677739694802286281304098330775624855302756667663465914199835280521403584126702978866562685520543935421154050447867911059177606165262400020873499386906970146551709258988442219015851884780077312457798675129268880451090924376187951993650215478978540577809871650478335433496067696569172709154680067599190339674068728475127823219158593584293520181641121033571889926922988322204738828424961081179988160697636253125312587199961273670711823578025839414439902836133748950733557056118417544158459762584752332587945570291163241775201162554839277393583881184675269945128443847935839357642485523715074688051617424405438693358917906391483467609845703996189891303952682345149589858721888277757803678974892434557190464885545251809122492272306245588523987427849967587428830422842231739423876770335264304256678242698255841371780445755594028103216204355811117217525673077660846179708380418782642887734191316634387638449590106579471405320624521040703823058560089357391403190184811377531067236005226938823197327942854048172556166001068136742020482416705808809352723593072427688561149119175718044620421748032144198262093698469732732274368409058341283515181633228297291719114949004369681092837260557508753267949900030675309743513663220010068761498907184206093116104251896432080886754935886031134216646777467845545998139534915640708436928920187774609890923244187066751247681112763004571969479922504900632242448776933569687357560520495244868101595759629011974165332206941761836356661294814543292768708265102026801696145130396403537480797788900968909446747131024412954342545790930610116322957164284924044342217691051263695099207408728419442014319227218115189339569850217442994443889423121986384188708197620980234859752336656606343830875544790341500227418016575898463255006543977215573560684365148160050387483020919904561309524615716447977092152209272319580239449796635420160781417184515852383884215131748031790139296806204439127310301606862498673520622474116482371804268548365873105740328839693566081304135833508838209682069951430738375158682514429526302870537105572489537892659604563320301014700152395703701210170192139837119095273290793520446316817434511768407278303509858208930313606608825725665745510779900016387656488863100078146893405809236839595214750893004977627223866456794077324180301978443267864217482960065860085694868080412163449227369707031884792666159898561530898874263868057255486349690549104524934313738273418506122165864873879364100404404178796397097798905988378969961979721778908059247419844078895372274735480062945831219071854451481214745796366786043504328034461413545325537782138584488690778501945250587885053567133322729634661540986414157218459634918271030195973530786218731103273752481240844919954370465403782809485269884417039817646940455649857908066467293966724755971579381525905788964354163752286684014083946788964843348315648069971452406468838270154562986460054316402752319801674906670633228142723018795589031042247701460987400999854486435652358077000486005008274624274233717437232805250065950950992430293324050206963254686853183912470786034293094972650430039183469746249697249928329162659508594253604707344307121242103040242965423416108028740760198029596172472295226414297978392699162548799389277732242491348639403936263921012527382767333460130896855849878492960536946790285615999827624286307932783869821678171315639132623327894456900153823724323912294461500616857050476167017390713870806342618518444920884933672926718081062034123008415260680625912019945511501039199824452955963015753661023681224292485118659775555592249327594618243835114067750600237416189151711188784515229276172980113938609222622534762392396371267224244672125183739603836242480161101614674851767489921698602028864040665193408089884602165907729949589088090706483223475737038995334519233809538445061608617759097105754690914406615883898665551600514222259072160125163642101178332583321741961557372833342493853054873055857138782048767687334176099389357754505889466145659645841354875876536510093000768657335380410022508145621335150011674231464945530041373749551048173797267138907231659088901319276328782204454572203442303194789943780179612663015694678527094454663956076631419509133550486623190199469896823083868976815012088398686782827789286079978068850526459862797636629440819716134272756832976555596226392320189749345178629920862437599259338387733548515909104940642724967722328193067140059411090409120674934150447659747987979270039957921390923895749674204495178980051182148930256475773751948042134659711307619161743906376525197030214846945862831170482297684831020804966598928444806157153466211683094670596518824202635936211573837005970508936935051282455249783943138153594131724311199028858505567832033597368004277518243803051618218731710563640835119850461648376551635722867729431326788315170164646999340765590179367027109063268159746893130390473584568011304758605883729339877640659005462857704489290320853492401655837690830837896202286240830502194871424067628300109236119291115561084036828337129134594809480233802066812359752447477303970326637155992287454007482265823210548629592923136391419774766918210280480453346428272947599606054971375178401084665803762756837500815991211195392977952553482740165362573297199120777679335809828691735871713491759923612724085659452125209083570040015767485252896156746223064439925128781020273442442639702498334258962194139028838967856807844644069506494717216828264176717374517366966030660594055368380226543283868640249034895798326678576729832123484330789754577148850991565028640320056050237304987040759416745861343127626834962846849345961670700442539893075009529920325026726166925097662916609884314762050531750680847197429476093402741465100451690013846949470980812326106090289205166382058156235371555363367741431169652858798040138132617336613718887815000312056378880909255477903074154498732597316127299954249810959366555135035953130340638547689861628403179948802881125430804932486389508260778663740502817656122152303056741390659427881724737601138906520694005641313663377070431507512447449139174047667957491448643288644725318933479957579306363523029732499616216983346995606590422646655655762686198259602047839251278641839908462461039403367445113279266435223289430599977011034621623075230805925863790705070419855783547412014538628600328576045765383085086363103006165916100858934481312212869902491572516771181043704323936285953056258998868057872414481072565311429185172105490468412559677755224413307327916838407359346260086677043723866562970190704884134668287557945026488463837360703055034304445207241637454524596030459083188975235823001825687873874543029119403079398734889142741313294520659420150698007890820300696414888151856290022138068465514167238005434245709237552706914413520346825522100966822779385225958452435898495695346893814236542391954985155438771588762162881339712223420600618802376553500628737331944547240253548334776947100268568223029112261357498602086392196476569026092577911316873422330810948348689721178064579808200874283993488187096459176377078658444363098047672082363606100877657726475182930421140940332710456844027738795135390913882266562776596968283906389254185912094280015403685676605236684609277201854093589664803530681069249333566540362643133498922178327239797118296801802469954259751650607077382732399457507692446015660334017389978055345920107067384492429192183916581559487109855610861519955137721657335371480920234923282888224772426832473719910793395245850594900058365551688541527862151596481510848837538128537465313528833265682676964351350961652793609249448416106951684119706770490213389557350702681471536929443220611901782784138683378223834097413283106485976494301676697544584646287864863477064766684514273755155817458568222394637464665783227408871728409550126206488560170184224707083397528769743742076648276078892615225208335512414321046005413269336836380648475010369492078297505284027250523154188339241504327433071174079291869764823515602105766190628202019818098831310850557166153006883283777504052180423027105062520684280805833158667521880279793196018790876092236846062505089080511100531057845848945467100334050406399863577337431814936329287619319022969747163264875054935941547498099144383680170036376275892845491294111027074404894094342434216709636989415081763478706973524872549676441126309386123231887272463176700747804171470473440130871591919218074350115147009678919014459383205670897216872731045313133796581013012885910307115866109579925523859269911722075431267213199787484824476592410227504198987195817094207316600058506818058759241444659324155368875159423024389820745914991914040888088327117513423041397596491162651356606457142652630920895686922518219419009206290520858730133666264204157773923319185737507976167876312359848156063039032271501021874752565780078626592917988649565048336420594438241106038815935765592531547194359739041917615624071061349229309462757845621722598732996604285727750196761901920972961786054223704598029846427048072823111733889161406122717296093614440990730040767869103624470185864277056164181192330175782494599945343507953644537733177291540174<-1200.0,1200.0,1.0>Tuning (cent)
slider3:0<0,1>-Unused
slider4:10.303497314453125<0,5000,1>Attack (ms)
slider5:84406.25<1,15000,1>Decay (ms)
slider6:0.0<-120.0,24.0,1.0>Sustain (dB)
slider7:10.303497314453125<0,5000,1>Release (ms)
slider8:0<0,1>-Unused
slider9:0<0,14,1{Sine,HW Rect Sine,FW Rect Sine,Triangle,Trapezoid,Square,Pulse PW,Saw,Mod Triangle PW,Tri Pulse,Hammond,Staircase,Mod Square PW,Trapezoid PW,Tri Pulse PW}>Wave
slider10:0.30<0.0,1.0,0.01>Pulse Width
slider11:0<0,1>-Unused
slider12:200.0<0.0,1200.0,1.0>Pitch Wheel (cent)
slider13:0<0,1>-Unused
slider14:-36.0<-36.0,0.0,1.0>White Noise (dB)
slider15:0<0,1>-Unused
slider16:1.0<0.0,1.0,0.01>Low-Pass Filter
slider17:0<0,15000,1>Filter Decay (ms)
slider18:1.0<0.01,4.0,0.01>Filter Q
slider19:0<0,1>-Unused
slider20:0<-100,100,1>Pan (%)
slider21:0<0,1>-Unused
slider22:0<0,16,1{Any,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}>MIDI Ch
slider23:1<0,2,1{Legacy,Poly,Mono}>Mode
slider24:100<0,100,1>Velocity (%)
slider25:0<0,1>-Unused
slider26:0.0118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118




474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228063680118474639022584228




06368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258422806368011847463902258<0.01,12.0,0.001>LFO Rate (Hz)
slider27:0<0,100,1>LFO Depth (%)

out_pin:Left
out_pin:Right

import midi_queue.jsfx-inc
import adsr.jsfx-inc
import rc_filter.jsfx-inc
import zdf_filter.jsfx-inc
import sine.jsfx-inc
import poly_blep.jsfx-inc
import noise.jsfx-inc

@init

osc_buf = 0; max_poly = 16; osc_size = 13;
note_buf = osc_buf + max_poly * osc_size;
hold_buf = note_buf + 128;
midiq.midiq_init(hold_buf + 128);

pitch = 1;

noise_gain = sqrt(srate / 48000);

lpf.m = 50;
lpf.ln = log(lpf.m);

function int(x) ( x|0 );
function gain(db, inf) ( db <= inf ? 0 : 10^(0.05 * db) );
function mix(a, b, mix) ( (1.0 - mix) * a + mix * b );
function cache(x) ( x != this ? ( this = x; 1; ); );

smooth.rc_set(0.0033);
function smooth() ( smooth.lp = this.smooth; this.smooth = smooth.rc_lp(this); );

min_inf = -384.0;
gain0.smooth = gain1.smooth = gain(slider1, min_inf);

function set_tg(note)
  // global(tg*)
(
  tg.poly_setf(440 * 2^((note - 69) / 12));
);

function tg_wave(wave)
  // global(tg*)
(
  wave == 7  ? tg.poly_saw() :
  wave == 6  ? tg.poly_rect() :
  wave == 5  ? tg.poly_sqr() :
  wave == 4  ||
  wave == 13 ? tg.poly_trap2() :
  wave == 3  ? tg.poly_tri() :
  wave == 2  ? tg.poly_full() :
  wave == 1  ? tg.poly_half() :
  wave == 0  ? tg.poly_sin() :
  wave == 8  ? tg.poly_tri2() :
  wave == 9  ||
  wave == 14 ? tg.poly_trip() :
  wave == 10 ? tg.poly_ham() :
  wave == 11 ? tg.poly_stairs() :
/*wave == 12*/ tg.poly_sqr2();
);

function adsr_sets(g)
  instance(state)
(
  state == 4 ? state = 2;
  this.adsr_sets(g);
);

function load_adsr(p)
  // global(adsr*)
(
  adsr.state = p[3];
  adsr.env = p[4];
  adsr.scale = p[5];
  adsr.s = p[6];
);

function store_adsr(p)
  // global(adsr*)
(
  p[3] = adsr.state;
  p[4] = adsr.env;
  p[5] = adsr.scale;
  p[6] = adsr.s;
);

function load_lpf(p)
  // global(lpf*)
(
  lpf.env.lp = p[7];
  lpf.freq.smooth = p[8];
  lpf.zdf.g = p[9];
  lpf.zdf.h = p[10];
  lpf.zdf.s1 = p[11];
  lpf.zdf.s2 = p[12];
);

function store_lpf(p)
  // global(lpf*)
(
  p[7] = lpf.env.lp;
  p[8] = lpf.freq.smooth;
  p[9] = lpf.zdf.g;
  p[10] = lpf.zdf.h;
  p[11] = lpf.zdf.s1;
  p[12] = lpf.zdf.s2;
);

function lpf_freq(dt)
  // global(lpf*, srate)
(
  (lpf.env.a < 1 ? lpf.env.rc_lp(lpf.n) : lpf.n) * dt * srate;
);

function reset_lpf(dt)
  // global(lpf*)
(
  lpf.env.lp = 0;
  lpf.zdf.zdf_reset();
  lpf.freq.smooth = lpf_freq(dt);
  lpf.zdf.zdf_lp(lpf.freq.smooth, lpf.q);
);

function set_buf(buf, num, size)
  // global(p, end)
(
  p = buf;
  end = p + num * size;
);

function remove_buf(size)
  // global(p, end)
(
  end -= size;
  p < end ? memcpy(p, p + size, end - p);
);

function find_note(note, buf, num, size)
  // global(p, end)
(
  set_buf(buf, num, size);
  while(p < end && p[] != note ? p += size);
);

function note_on(note, vel)
  // global(p, end, note_buf, num_notes, hold_buf, num_hold, osc_buf, num_osc, osc_size, num_poly, tuning, tg*, adsr*, lpf*)
(
  find_note(note, note_buf, num_notes, 1);
  p >= end ? (
    p[] = note;
    num_notes += 1;
  );

  find_note(note, hold_buf, num_hold, 1);
  p < end ? (
    remove_buf(1);
    num_hold -= 1;
  );

  find_note(note, osc_buf, num_osc, osc_size);
  p >= end ? (
    set_tg(note);

    num_osc >= num_poly ? (
      p = osc_buf;
      num_poly > 1 ? (
        // Set oscillator/ADSR state to first played note (to mimic old
        // mono_synth global state behavior).
        tg.t = p[1];
        load_adsr(p);
        load_lpf(p);
      );

      remove_buf(osc_size);
      p = end;
      num_osc -= 1;
    ) : (
      // Don't reset oscillator on first note (old mono_synth behavior).
      num_osc > 0 ? tg.t = 0;
      adsr.adsr_reset();
      reset_lpf(tuning * tg.dt);
    );

    num_osc += 1;
    p[0] = note;
    p[1] = tg.t;
    p[2] = tg.dt;
  ) : num_poly > 1 ? (
    load_adsr(p);
    load_lpf(p);
  );

  adsr.adsr_a(vel);
  lpf.env.lp = lpf.m;

  store_adsr(p);
  store_lpf(p);
);

function note_off(note)
  // global(p, end, note_buf, num_notes, osc_buf, num_osc, osc_size, num_poly, note_prio, tg*, adsr*)
(
  find_note(note, note_buf, num_notes, 1);
  p < end ? (
    remove_buf(1);
    num_notes -= 1;
  );

  find_note(note, osc_buf, num_osc, osc_size);
  p < end ? (
    // Mono, last-note priority
    num_poly == 1 && num_notes > 0 && note_prio ? (
      note = note_buf[num_notes - 1];
      set_tg(note);
      p[0] = note;
      p[1] = tg.t;
      p[2] = tg.dt;
    ) : (
      // Release
      num_poly > 1 ? load_adsr(p);
      adsr.adsr_r();
      store_adsr(p);
    );
  );
);

function hold_note(note)
  // global(p, end, hold_buf, num_hold)
(
  find_note(note, hold_buf, num_hold, 1);
  p >= end ? (
    p[] = note;
    num_hold += 1;
  );
);

function release_notes()
  // global(hold_buf, num_hold)
  local(p)
(
  p = hold_buf;
  loop(num_hold,
    note_off(p[]);
    p += 1;
  );
  num_hold = 0;
);

function all_notes_off()
  // global(num_notes, num_hold, num_osc)
(
  num_notes = num_hold = num_osc = 0;
);

function pitch_bend(pitch_wheel)
  // global(pitch, pitch_range)
(
  pitch = pitch_range < 0.00001 ? 1 : 2^(pitch_wheel * pitch_range);
);

@slider

function adr(ms, lo, hi) ( max(lo, min(hi, ms)) * 0.001 );

function pan(gain, pos)
  // global(gain0, gain1)
(
  // REAPER default 0 dB pan law (thanks Justin!)
  // http://www.askjf.com/index.php?q=2342s

  pos *= 0.25*$pi;
  gain *= sqrt(2) * (1 - sqrt(0.5) * (1 / cos(pos) - 1));

  pos += 0.25*$pi;
  gain0 = cos(pos) * gain;
  gain1 = sin(pos) * gain;
);

pan(gain(slider1, min_inf), max(-100, min(100, slider20)) * 0.01);

adsr.adsr_seta(adr(slider4, 0, 5000));
adsr.adsr_setd(adr(slider5, 1, 15000));
adsr.adsr_sets(gain(slider6, min_inf));
adsr.adsr_setr(adr(slider7, 0, 5000));

tuning = 2^(slider2 / 1200);
wave = int(slider9);

// Limit pulse width for pulse, triangular pulse, modified square.
min_pw = wave == 6 || wave == 14 ? 0.10 : wave == 8 ? 0.01 : wave == 12 ? 0.20 : 0.0;
max_pw = wave == 6 ? 0.90 : wave == 8 ? 0.99 : 1.0;
pw = wave == 4 || wave == 9 ? 0.5 : max(min_pw, min(max_pw, slider10));

noise_mix = gain(slider14, -36.0);

lpf.n = slider16 >= 1.0 ? lpf.m : exp(max(0.0, slider16) * lpf.ln);
slider17 < 1 ? lpf.env.a = 1 : lpf.env.rc_sett(0.001 * min(15000, slider17));
lpf.q = max(0.01, min(4.0, slider18));

pitch_range = max(0.0, slider12) / 1200;
midi_ch.cache(max(0, min(16, int(slider22))) - 1) ? all_notes_off();
num_poly.cache(slider23 < 0.5 || slider23 >= 1.5 ? 1 : max_poly) ? all_notes_off();
note_prio.cache(slider23 >= 0.5) ? all_notes_off();
vel_range = max(0, min(100, slider24)) * 0.01;

lfo_range = max(0, min(100, slider27)) * 0.01;
lfo_range <= 0 ? (
  lfo_mod = 0;
) : wave == 6 || wave == 8 || wave >= 12 ? (
  lfo_mod = 1;
  lfo_range *= 0.5 * (max_pw - min_pw);
  pw = max(min_pw + lfo_range, min(max_pw - lfo_range, pw));
) : (
  lfo_mod = 2;
  lfo_range *= 0.5/12;
);
lfo_mod != 1 ? tg.poly_setpw(pw);
lfo_mod ? lfo.sin_setf(max(0.01, slider26));

@block

midiq.midiq_collect(midi_ch, 3|8|64);

@sample

while(midiq.midiq_remove() ? (
  midiq.msg1 &= 0xF0;

  // Note On
  midiq.msg1 == 0x90 && midiq.msg3 ? (
    note_on(midiq.msg2, (1.0 - vel_range) + vel_range * midiq.msg3 / 127);
  ) :

  // Note Off
  midiq.msg1 == 0x80 || midiq.msg1 == 0x90 ? (
    hold_pedal ? hold_note(midiq.msg2) : note_off(midiq.msg2);
  ) :

  // Pitch Wheel
  midiq.msg1 == 0xE0 ? (
    pitch_bend(((midiq.msg3 << 7 | midiq.msg2) - 8192) / (midiq.msg3 < 64 ? 8192 : 8191));
  ) :

  // Control Change
  midiq.msg1 == 0xB0 ? (

    // Damper Pedal (Sustain)
    midiq.msg2 == 64 ? (
      hold_pedal = midiq.msg3 >= 64;
      !hold_pedal ? release_notes();
    ) :

    // All Notes Off
    midiq.msg2 == 123 ? (
      all_notes_off();
    );
  );

  1; // while midiq.midiq_remove()
));

function sample_tg(t, dt)
  // global(adsr*, freq_mod, tg*, wave, white_noise, noise_mix)
  local(ph, out)
(
  adsr.state ? (
    noise_mix < 1.0 ? (
      // Correct full-wave rectified sine/triangular pulse phase.
      ph = wave == 2 ? 0.25 : wave == 14 ? 0.75 + 0.5 * tg.pw;
      ph > 0 ? tg.poly_sync(t - ph) : tg.t = t;

      tg.poly_setdt(freq_mod * dt);
      tg.poly_resetf();
      out = adsr.env * mix(tg_wave(wave), white_noise, noise_mix);

      ph > 0 ? tg.poly_sync(tg.t + ph);
      out;
    ) : (
      adsr.env * white_noise;
    );    
  );
  // 0.0 otherwise
);

function apply_lpf(in, dt)
  // global(lpf*, tuning)
  local(out)
(
  lpf.freq = lpf_freq(tuning * dt);
  lpf.freq.smooth();

  // Recalculate LPF coefficients only every 16 samples.
  lpf.skip <= 0 && lpf.freq.smooth != lpf.zdf.freq ? (
    lpf.zdf.freq = lpf.freq.smooth;
    lpf.zdf.zdf_lp(lpf.zdf.freq, lpf.q);
  );

  out = lpf.zdf.zdf_svf_lp(in);
  lpf.n < lpf.m ? out : in;
);

function adsr_lpf_off()
  // global(adsr*, lpf.zdf*)
(
  !adsr.state && lpf.zdf.s1 == 0 && lpf.zdf.s2 == 0;
);

freq_mod = pitch * tuning;
lfo_mod ? lfo_mod == 1 ? tg.poly_setpw(pw + lfo_range * lfo.sin_sin()) : freq_mod *= 2^(lfo.sin_sin() * lfo_range);

white_noise = noise_mix > 0.0 ? noise_gain * noise.lcg_white();
out = 0.0;

// Optimize for mono i.e. don't load/store oscillator/ADSR/filter state.
num_poly == 1 ? (
  num_osc ? (
    adsr.adsr_process();
    out = apply_lpf(sample_tg(tg.t, osc_buf[2]), osc_buf[2]);
    adsr_lpf_off() ? num_osc = 0;
  );
) :

/* num_poly > 1 ? */ (
  sus = adsr.s;

  set_buf(osc_buf, num_osc, osc_size);
  while(p < end ? (

    // Functions indexing memory seems to be slow, so manually inline them.
    /* load_adsr(p); */ adsr.state = p[3]; adsr.env = p[4]; adsr.scale = p[5]; adsr.s = p[6];
    adsr.s != sus ? adsr.adsr_sets(sus);
    adsr.adsr_process();
    /* store_adsr(p); */ p[3] = adsr.state; p[4] = adsr.env; p[5] = adsr.scale; p[6] = adsr.s;

    s = sample_tg(p[1], p[2]);
    p[1] = tg.t;

    /* load_lpf(p); */ lpf.env.lp = p[7]; lpf.freq.smooth = p[8]; lpf.zdf.g = p[9]; lpf.zdf.h = p[10]; lpf.zdf.s1 = p[11]; lpf.zdf.s2 = p[12];
    s = apply_lpf(s, p[2]);
    /* store_lpf(p); */ p[7] = lpf.env.lp; p[8] = lpf.freq.smooth; p[9] = lpf.zdf.g; p[10] = lpf.zdf.h; p[11] = lpf.zdf.s1; p[12] = lpf.zdf.s2;

    out += s;

    adsr_lpf_off() ? (
      remove_buf(osc_size);
      num_osc -= 1;
    ) : (
      p += osc_size;
    );
  ));
);

lpf.skip > 0 ? lpf.skip -= 1 : lpf.skip = 16 - 1;

spl0 += gain0.smooth() * out;
spl1 += gain1.smooth() * out;
