>6 months in the making and the first of its kind, the Synthcore library contains a hundred functions written in Cycling74 gen~ codebox for audio. The download package includes: the library itself; a demo patch illustrating usage of the main functions; data files; and two complete synths built with the library that implement the audio path entirely in gen~.

Synthcore Library Demo Patch
Synthcore Library Demo Patch

Using the Library

All the signatures and return values are documented in the library code (which is ~1700 lines, listed below). The _LIBRARY.maxpat patch illustrates ~50 of the functions in operation.

Using the Synths

The _SYNTH.maxpat' and SYNTH_LITE.maxpat patches are included in the download at the end of this page. The 'lite' version is for Macintosh users who find the graphics too overwhelming for their machines.

See Synthcore 2, on this site, for more information.

The Source Code

The source code listing follows, so you can decide whether to get it :)

Hide LIne Numbers
  1. /*                    
  2.                         SYNTHCORE - ALL AUDIO IN GEN
  3.  
  4. - LIBRARY CONTENTS
  5.   * MATHS - qcos(), qsin(), db2a().
  6.   * PANS & SMOOTHERS - pan1(), pan2(), smoother(), smoother2(), smoother3(), 
  7.     rampgate(), ramptrig(), line().
  8.   * SATURATORS- parabol1(), parabol2(), paraboln(), hyperbol().
  9.   * 1-POLE FILTERS - static(), staticlo(), statichi(), shelflo(), shelfhi(). 
  10.   * BIQUADS - biquad(), biquad0(), biquadlow(), biquadlo2(), biguadlo3(),
  11.     biquadband(), biquadband2(), biquadband3(), biquadhi(), biquadhi2(),
  12.     biquadhi3(), biquadnotch(), biquadval(), biquadamp(), biquadplot(), 
  13.     biquadplot2().
  14.   * RAMP OSCS - ramp(), ramptrg(), rampgate(), rampphase(), rampsoft(),
  15.     rampsofter(), rampramp(), rampramper().
  16.   * OSCS  -    sine(), pulse1(), pulse2(), eptr(), eptrpulse(), eptrpulse3x(),
  17.     sawdown(), sawup(), tri(), tri2(), sawtri(), karplus(), karplusd(),
  18.     karplusenv(), karplusm(), waveset(), noiselpf(), noisebpf(), noisehpf(), 
  19.     noisenotch(), pinknoise(), noiseosc(), osc().
  20.   * IIR - comb().
  21.   * SVFs - upsample(), downsample() svf(), svfCoeffs3x(), gainComp(), 
  22.     svfMixer(), filt3x(), filt().
  23.   * LFOs - lfo(), lfopoly().
  24.   * EnvS - adsr(), adsrloop(), padsrloop(), adbdsrloop(), padbdsrloop().
  25.   * EFFECTS - glide(), ping1(), ping2(), chorus1(), chorus2(), diffdelay(), 
  26.     earlyreflections(), tank(), reverb().
  27. - DECLARATIONS - Buffers and constants.
  28.  
  29. **********************************************************************************
  30. FUNCTION LIBRARY
  31.     For Max 7.3.1.+ Parts may work with older versions but it's not been checked.
  32.     These are optimized functions. Input ranges are not clipped or normalized. 
  33.     Inputs are in range 0~1, and outputs are bipolar, unless otherwise noted.
  34.     Samplerate constants are passed in, as they are not compiled out of functions.
  35. **********************************************************************************/
  36.  
  37. // math functions *************************************************************/
  38. qcos(x){                                        // quick cosine calc
  39.     x *= x;
  40.     x = x*(x*(x*(x*(x *-.0000002605 +.000024709
  41.         )- .00138884)+.416667)- .499923)+ 1;
  42.     return x;
  43. }
  44. qsin(y){                                        // quick sine calc
  45.     x =y * y;
  46.     x = y*(x*(x*(x*(x*(x *.0000000239 +.0000027526
  47.         )- .000198409)+.008333333)- .16666667)+ 1); 
  48.     return x;
  49. }
  50. db2a(db){                                        // quick db2a convert
  51.     x = pow(db,1.12202);
  52.     return x;
  53. }
  54. //**********************************************************************
  55. // pans  and smoothers (actually integrators)
  56. /******************************************************************************/
  57. pan1(pan){                                // optimized pan with +3dB at center
  58. // returns 0~1 values for gain control
  59.     p = 1 - pan;
  60.     return 
  61.         p * (4 - p)     *.333333333333333,    // left
  62.         pan * (4 - pan) *.333333333333333;    // right
  63. }
  64. pan2(pan, left, right){                 // optimized pan with +3dB at center
  65. // returns panned signal
  66.     p = 1 - pan;
  67.     return 
  68.         left * p * (4 - p)      *.333333333333333,    // left
  69.         right * pan * (4 - pan) *.333333333333333;    // right
  70. }
  71. smoother1(val){             // smoothing over ~46 clock cycles
  72.     History z1, zdir;
  73.     x = change(val);
  74.     if (x !=0) zdir = x;
  75.      if (zdir >0) z1 = (z1 < val -.02)? val * .01 + z1 *.99 : val;
  76.     else z1 = (z1 > val +.02)? val * .01 + z1 *.99 : val;
  77.     return z1;
  78. }
  79. smoother2(val){             // slower smoothing for delay line times
  80.     History z1, zdir;
  81.     x = change(val);
  82.     if (x !=0) 
  83.         zdir = x;
  84.      if (zdir >0) z1 = (z1 < val -.002)? val * .001 + z1 *.999 : val;
  85.     else z1 = (z1 > val +.002)? val * .001 + z1 *.999 : val;
  86.     return z1;
  87. }
  88. smoother3(val){             // slowest smoothing for long delay line times
  89.     History z1, zdir;
  90.     x = change(val);
  91.     if (x !=0) zdir = x;
  92.      if (zdir >0) z1 = (z1 < val -.0002)? val * .0001 + z1 *.9999 : val;
  93.     else z1 = (z1 > val +.0002)? val * .0001 + z1 *.9999 : val;
  94.     return z1;
  95. }
  96. ramptrig(msecs, trg, rsrms){                    // ramp, time in msecs
  97. //        msecs:     duration or ramp
  98. //        trg:     when HIGH, restarts
  99. //        srms:     constant, 1000/samplerate
  100. // returns ramped signal in 0~1 range
  101.     History z1;
  102.     inc = rsrms/ msecs;
  103.     if (trg >0) z1 = 1;
  104.     if (z1 >0) { z1 = z1 - inc; return z1; } 
  105.     else       { z1 = 0;        return 0;  }
  106. }
  107. line(input, inc){                                // line~, 
  108. // incr     1 / (samplerate * linetime)
  109.     History z0, z1, z2, z3;
  110.     y = input - z0;
  111.     z0 = input;
  112.     if (y != 0) { z1 = 0; z2 = y; z3 = input;        }
  113.     if (z1 <1)  { z1 = z1 + inc; return z1 * z2 + z3;} 
  114.     else        { z1 = 0;        return y;           }
  115. }
  116. /******************************************************************************/
  117. // Saturators
  118. // all inputs are bipolar
  119. parabol1(input){                 // parabolic in unity range, clipped above it
  120. output = clip(input, -1, 1); 
  121.     return 
  122.         output * (1 -(abs(output) * .125));
  123. }
  124. parabol2(input){                 // parabolic with 2x headroom
  125.     output = clip(input, -2, 2); 
  126.     return output * (1 -(abs(output) * .25));
  127. }
  128. paraboln(input, slope){            // parabolic with adjustable slope
  129. // slope controls POW factor
  130.     output += pow(abs(input),1- slope *.01) * sign(input);
  131. }
  132. hyperbol(input, x){                // hyperbolic within unity output range
  133. // x controls hyperbolic factor
  134.     return (input > 0)?
  135.             x -(x *(x /(abs(input) +x))) :  
  136.         neg(x -(x *(x /(abs(input) +x))));  
  137. }
  138. //**************************************************************
  139. // 1-pole filters 
  140. //**************************************************************
  141. static(input, a1, b0, b1){                        //1-pole core
  142. // input        signal to filter
  143. // a1, b0, b1     coefficients from below functions
  144.     History zx1, zx2;
  145.     x = zx1   * a1  + input * b0  + zx2   * b1;
  146.     zx1 = x; zx2 = input; return x;    
  147. }
  148. staticlo(fc){                            //1-pole low pass
  149. // returns filtered signal 
  150. // fc        cutoff in Hz,  range sr/24576~sr/2.125
  151.     c1 = tan(fc * pi/samplerate);
  152.     c2 = 1 /(c1 + 1);
  153.     a1 = (1 - c1) * c2; 
  154.     b0 = c1       * c2;
  155.     return a1, b0, b0;
  156. }
  157. statichi(fc){                            //1-pole high pass
  158.     c1 = tan(fc * pi/samplerate);
  159.     b0 = 1 /(c1 + 1);
  160.     b1 = neg(b0);
  161.     a1 = (1 - c1) * b0; 
  162.     return a1, b0, b1;
  163. }
  164. shelflo(fc, b){                            //1-pole low shelf
  165. // returns filtered signal 
  166. // fc        cutoff in Hz, range sr/24576~sr/2.125
  167. // b        low-freqency boost(dB), 1~36
  168.     a  = pow(b, 1.059);
  169.     a *= a;
  170.     fc = fc /a;
  171.     c1 = tan(fc * pi/samplerate);
  172.     c2 = 1 /(c1 + 1);
  173.     a1 = (1 - c1) * c2; 
  174.     c1 = (a - 1) *  c1 * c2;
  175.     b0 = c1 + 1;
  176.     b1 = c1 - a1;
  177.     return a1, b0, b1;
  178. }
  179. shelfhi(fc, b){                            //1-pole high shelf
  180. // returns filtered signal 
  181. // fc        cutoff in Hz, range sr/24576~sr/2.125
  182. // b        high-freqency boost(dB), range 1~36 
  183.     a  = pow(b, 1.059);
  184.     fc = fc * a;
  185.     a *= a;
  186.     c1 = tan(fc * pi/samplerate);
  187.     c2 = 1 /(c1 + 1);
  188.     a1 = (1 - c1) * c2;
  189.     b1 = (a - 1)  * c2;
  190.     b0 = b1 +1;
  191.     b1 = neg(a1 + b1);
  192.     return a1, b0, b1;
  193. }
  194. /******************************************************************************/
  195. // Biquads 
  196. //********************************************************************
  197. biquad0(input, a0, a1, a2, b1, b2) {        // direct form 1
  198.     // for some reason this doesn't work,
  199.      // but the next one is better anyway
  200.     History z1, z2, z3, z4;
  201.     y  = input * a0
  202.         + z1 * a1
  203.         + z2 * a2
  204.         - z3 * b1
  205.         - z4 * b2;
  206.     z1 = input;
  207.     z2 = z1;
  208.     z3 = y;
  209.     z4 = z3;
  210.     return y;
  211. }
  212. biquad(input, a0, a1, a2, b1, b2) {         // optimized form 2
  213.     // theoretically more efficient
  214.     History z1, z2;
  215.     output = (input * a0) + z2;
  216.     z2     = ((input * a1) - (output * b1)) + z1;
  217.     z1     = (input *  a2) - (output * b2);
  218.     return output;
  219. }
  220. biquadlo(fc, Q, rsrxpi){                      // simple lowpass
  221. //  fc        cutoff freq, Hz 
  222. //  Q        resonance, typ 1~20, cannot be zero
  223. // rsrxpi     constant, pi/samplerate 
  224. // returns standard biquad coefficients
  225.     k = tan(rsrxpi * fc);
  226.     norm = 1 /(1 + k / Q + k * k);
  227.     a0 = k * k * norm;
  228.     a1 = a0 *2;
  229.     //a2 = a0;                // merged into return
  230.     b1 = (k * k - 1) * norm *2;
  231.     b2 = (1 - k / Q + k * k) * norm;
  232.     return a0, a1, a0, b1, b2;
  233. }
  234. biquadband(fc, Q, rsrxpi){                    //simple bandpass
  235. //  I/O ranges same as biquadlow
  236.     k = tan(rsrxpi * fc);
  237.     norm = 1 / (1 + k / Q + k * k);
  238.     a0 = k / Q * norm;
  239.     // a1 = 0;                // merged into return
  240.     // a2 = -a0;
  241.     b1 = 2 * (k * k - 1) * norm;
  242.     b2 = (1 - k / Q + k * k) * norm;
  243.     return a0, 0, neg(a0), b1, b2;
  244. }
  245. biquadhi(fc, Q, rsrxpi){                    //simple highpass
  246. //  I/O ranges same as biquadlow
  247.     k = tan(rsrxpi * fc);
  248.     norm = 1 / (1 + k / Q + k * k);
  249.     a0 = 1 * norm;
  250.     a1 = -2 * a0;
  251.     // a2 = a0;                // merged into return
  252.     b1 = 2 * (k * k - 1) * norm;
  253.     b2 = (1 - k / Q + k * k) * norm;
  254.     return a0, a1, a0, b1, b2;
  255. }
  256. biquadnotch(fc, Q, rsrxpi){                    //simple notch 
  257. //  I/O ranges same as biquadlow
  258.     k = tan(rsrxpi * fc);
  259.     norm = 1 / (1 + k / Q + k * k);
  260.     a0 = (1 + k * k) * norm;
  261.     a1 = 2 * (k * k - 1) * norm;
  262.     // a2 = a0;                // merged into return
  263.     // b1 = a1;
  264.     b2 = (1 - k / Q + k * k) * norm;
  265.     return a0, a1, a0, a1, b2;
  266. }
  267. biquadlo2(p, q, rsrxpi2){                    // standard-range i/p low
  268. // p    pitch in midi units
  269. // q    range 0 to < 1.
  270.     omega = mtof(p) * rsrxpi2;
  271.     alpha = (1 - q) * qsin(omega);
  272.     omega = qcos(omega);
  273.     b0    = 1 / (alpha + 1);
  274.     b1    = b0 * omega * -2;
  275.     b2    = b0 * (1 - alpha);
  276.     a1    = b0 * (1 - omega);
  277.     a0    = a1 * .5;
  278.     //a2  = a0;
  279.     return a0, a1, a0, b1, b2;
  280. }
  281. biquadlo3(p, q, rsrxpi2){                    // qain-limiting low
  282. // p    pitch in midi units
  283. // q    range 0 to < 1.
  284.     omega = mtof(p) * rsrxpi2;
  285.     alpha = (1 - q) * qsin(omega);
  286.     omega = qcos(omega);
  287.     b0    = 1 / (alpha + 1);
  288.     b1    = b0 * omega * -2;
  289.     b2    = b0 * (1 - alpha);
  290.     b2    = b0 * (1 - alpha);
  291.     a1    = b0 * (1 - omega);
  292.     a0    = a1 * alpha;
  293.     a2    = b0 * alpha;
  294.     return a0, a1, a2, b1, b2;
  295. }
  296. biquadband2(p, q, rsrxpi2){                    // standard-range i/p band
  297. // p    pitch in midi units
  298. // q    range 0 to < 1.
  299.     omega = mtof(p) * rsrxpi2;
  300.     alpha = (1 - q) * qsin(omega);
  301.     omega = qcos(omega);
  302.     b0    = 1 / (alpha + 1);
  303.     b1    = b0 * omega * -2;
  304.     b2    = b0 * (1 - alpha);
  305.     a0    = b0 * (1 -omega) * .5;
  306.     //a1    = 0;
  307.     a2    = neg(a0);
  308.     return a0, 0, a2, b1, b2;
  309. }
  310. biquadband3(p, q, rsrxpi2){                    // gain limiting band
  311. // p    pitch in midi units
  312. // q    range 0 to < 1.
  313.     omega = mtof(p) * rsrxpi2;
  314.     alpha = (1 - q) * qsin(omega);
  315.     omega = qcos(omega);
  316.     b0    = 1 / (alpha  + 1);
  317.     b1    = b0 * omega * -2;
  318.     b2    = b0 * (1 - alpha);
  319.     a0    = b0 * alpha;
  320.     //a1  = 0;
  321.     a2    = b0 * neg(alpha);
  322.     return a0, 0, a2, b1, b2;
  323. }
  324. biquadband4(p, q, rsrxpi2){                    // unity-gain band
  325. // p    pitch in midi units
  326. // q    range 0 to < 1.
  327.     omega = mtof(p) * rsrxpi2;
  328.     alpha = (1 - q) * qsin(omega);
  329.     omega = qcos(omega);
  330.     b0    = 1 / (alpha + 1);
  331.     b1    = b0 * omega * -2;
  332.     b2    = b0 * (1 - alpha);
  333.     a0    = b0 * alpha;
  334.     //a1  = 0;
  335.     a2    = b0 * neg(alpha);
  336.     return a0, 0, a2, b1, b2;
  337. }
  338. biquadhi2(p, q, rsrxpi2){                    // standard-range i/p hi
  339. // p    pitch in midi units
  340. // q    range 0 to < 1.
  341.     omega = mtof(p) * rsrxpi2;
  342.     alpha = (1 - q) * qsin(omega);
  343.     omega = qcos(omega);
  344.     b0    = 1/(alpha +1);
  345.     b1    = b0 * omega * -2;
  346.     b2    = b0 * (1 - alpha);
  347.     a1    = b0 * neg(omega +1);
  348.     a0    = a1 * -.5;
  349.     //a2  = a0;
  350.     return a0, a1, a0, b1, b2;
  351. }
  352. biquadhi3(p, q, rsrxpi2){                    // gain limiting hi
  353. // p    pitch in midi units
  354. // q    range 0 to < 1.
  355.     omega = mtof(p) * rsrxpi2;
  356.     alpha = (1 - q) * qsin(omega);
  357.     omega = qcos(omega);
  358.     b0    = 1/(alpha +1);
  359.     b1    = b0 * omega * -2;
  360.     b2    = b0 * (1 - alpha);
  361.     a1    = b0 * (omega + 1) * alpha * 40;
  362.     a0    = a1 * -.5;
  363.     a2    = a0;
  364.     return a0, a1, a0, b1, b2;
  365. }
  366. biquadval(a0, a1, a2, b1, b2, fc, q){        // value at point
  367. //  (not checked)
  368.     n = fc;
  369.     w = q; 
  370.     y = log(pow(a0+a1+a2, 2) 
  371.         - 4.*(a0 * a1 + 4.* a0 * a2 + a1 * a2) * pow(sin(w / 2), 2) 
  372.         + 16.* a0 * a2* pow(sin(w / 2), 4)) 
  373.         - log(pow(1. +b1 +b2, 2) 
  374.         - 4.*(b1 + 4.*b2 + b1 * b2) * pow(sin(w / 2), 2) 
  375.         + 16 * b2 * pow(sin(w / 2), 4));
  376.     y = y * 10 / log(10);
  377.     return y;
  378. }
  379. biquadamp(w, a0, a1, a2, b1, b2){        // filter gain at any freq
  380. // w        omega (fc * 2 * pi / samplerate)
  381. // a0-b2    biquad coefficents
  382.     num = a0 * a0 + a1 * a1 + a2 * a2 
  383.         + (a0 * a1 + a1 * a2) * cos(w) * 2 
  384.         + a0 * a2 * cos(2 * w) * 2;
  385.      nom = b1 * b1 + b2 * b2 + 1
  386.         + (b1 + b1 * b2) * cos(w) * 2
  387.         + b2 * cos(2 * w) * 2;
  388.      return sqrt(num / nom);   
  389. }
  390. biquadval(a0, a1, a2, b1, b2, fc, q){        // value at point
  391. //  (not checked)
  392.     n = fc;
  393.     w = q; 
  394.     y = log(pow(a0+a1+a2, 2) 
  395.         - 4.*(a0 * a1 + 4.* a0 * a2 + a1 * a2) * pow(sin(w / 2), 2) 
  396.         + 16.* a0 * a2* pow(sin(w / 2), 4)) 
  397.         - log(pow(1. +b1 +b2, 2) 
  398.         - 4.*(b1 + 4.*b2 + b1 * b2) * pow(sin(w / 2), 2) 
  399.         + 16 * b2 * pow(sin(w / 2), 4));
  400.     y = y * 10 / log(10);
  401.     return y;
  402. }
  403. biquadamp(w, a0, a1, a2, b1, b2){        // filter gain at any freq
  404. // w        omega (fc * 2 * pi / samplerate)
  405. // a0-b2    biquad coefficents
  406.     num = a0 * a0 + a1 * a1 + a2 * a2 
  407.         + (a0 * a1 + a1 * a2) * cos(w) * 2 
  408.         + a0 * a2 * cos(2 * w) * 2;
  409.      nom = b1 * b1 + b2 * b2 + 1
  410.         + (b1 + b1 * b2) * cos(w) * 2
  411.         + b2 * cos(2 * w) * 2;
  412.      return sqrt(num / nom);   
  413. }
  414. biquadplot(                                    // plots lp/bp/hp graph
  415.     fc, q, a0, a1, a2, b1, b2, rsrxpi2, period, isnotch){
  416. // filterdraw    the Max buffer name into which 
  417. //                filter is drawn, sizeinsamps = 110 
  418. // fc             filter cutoff in Hz
  419. // a0-b2        biquad coefficients
  420. // rsrxpi        constant, 2 * pi /samplerate
  421.     Buffer filterdraw;
  422.     History zi;
  423.     x, y = 0;
  424.     i = zi + 1;
  425.     if (i > period) 
  426.         i = 0;
  427.     zi = i;
  428.     if(i < 110){
  429.         x =    biquadamp(mtof(i +20) * rsrxpi2, 
  430.             a0, a1, a2, b1, b2);
  431.         filterdraw.poke(x, i);
  432.     }
  433.     return -1;
  434. }
  435. biquadplot2(    // plots LP/BP/HP/NOTCH filter graph with scaling
  436.     fc, q, a0, a1, a2, b1, b2, rsrxpi2, period, isnotch){
  437. // filterdraw    the Max buffer name into which 
  438. //                filter is drawn, sizeinsamps = 110 
  439. // fc             filter cutoff in Hz
  440. // a0-b2        biquad coefficients
  441. // rsrxpi        constant, 2 * pi /samplerate
  442.     Buffer filterdraw;
  443.     History zi;
  444.     x, y = 0;
  445.     i = zi + 1;
  446.     if (i > period) 
  447.         i = 0;
  448.     zi = i;
  449.     if(i < 110){
  450.         if (isnotch==0){
  451.             y = biquadamp(fc * rsrxpi2, // gain at fc
  452.                 a0, a1, a2, b1, b2);
  453.             x =    biquadamp(mtof(i +20) * rsrxpi2, 
  454.                 a0, a1, a2, b1, b2);
  455.             filterdraw.poke(atodb(x), i);
  456.         } else {
  457.             x =    biquadamp(mtof(i +20) * rsrxpi2, 
  458.                 a0, a1, a2, b1, b2);
  459.             if (i==round(ftom(fc)-20)) x = 0;
  460.             filterdraw.poke(atodb(x), i);
  461.         }
  462.         return 0;
  463.     }else {
  464.         return i;
  465.     }
  466. }
  467. /******************************************************************************/
  468. // SVF Filters
  469. upsample(input){                        // 3x upsampling with sinc coefficients
  470.     History ta1, ta2, ta3;
  471.     val2 = input * -0.074074074074074
  472.             + ta1 * 0.77777777777778
  473.             + ta2 * 0.33333333333333
  474.             + ta3 *-0.037037037037037;
  475.     val3 = input *  -0.037037037037037 
  476.             + ta1 * 0.33333333333333 
  477.             + ta2 * 0.77777777777778 
  478.             + ta3 *-0.074074074074074;
  479.     val1 = ta1;    // cascade history
  480.     ta3 = ta2;
  481.     ta2 = ta1;
  482.     ta1 = input;
  483.     return val1, val2, val3;
  484. } 
  485. downsample(val1, val2, val3){        // 3x downsampling with sinc coefficients
  486.     History    tb1, tb21, tb22, tb23, tb31, tb32, tb33;        
  487.     output = tb1  
  488.         + val2 *-0.074074074074074 // t01
  489.         + tb21 * 0.77777777777778  // t02
  490.         + tb22 * 0.33333333333333  // t02
  491.         + tb23 *-0.037037037037037 // t03
  492.         + val3 *-0.037037037037037 // t10 
  493.         + tb31 * 0.33333333333333  // t11 
  494.         + tb32 * 0.77777777777778  // t12 
  495.         + tb33 *-0.074074074074074;// t13
  496.     tb33 = tb32; tb32 = tb31; tb31 = val3; // delay line for downsampling
  497.     tb23 = tb22; tb22 = tb21; tb21 = val2;
  498.     tb1  = val1;
  499.     return output;
  500. }
  501. svf(input, wa, d1, ft1, ft1n, ft2, zlp, zbp){        // svf core
  502.     hp  = input - (zlp + d1 * zbp); 
  503.     x   = zbp + hp * wa;
  504.      lp  = x * wa + zlp; 
  505.     bp  = clip(x, ft1n, ft1);
  506.     bp  *= 1 - (abs(bp) * ft2); 
  507.     return lp, bp, hp;
  508. }
  509. svfCoeffs3x(f0, q0, s0, f4x, rsrx2pi){    // coefficents for 3x-oversampled SVF
  510.     History hq0(-1), hs0(-1), q1, q2, q3, s1;
  511.     f1   = mtof(f0);
  512.     // Q calculation
  513.     if(q0!=hq0){
  514.         q1  = (q0 <50)?  q0 *0.018032 : pow(q0 *.01, .3) *1.11;
  515.         q2  = 1 - max(1, q1);
  516.         q2  = 1 - (q2 * q2 -.0925);
  517.         q3  = 1 - q1;
  518.         q3 += q3;
  519.     }
  520.     hq0 = q0;
  521.     wa  = min(1, rsrx2pi * q2 * f1); 
  522.     ft1 = 1 / wa;
  523.     d1  = (2 - wa) * ft1;
  524.     d2  = min(d1, 1 - (f4x * q1));
  525.     d1  = min(d1, q3);
  526.     if(s0!=hs0){
  527.         s1 = dbtoa(s0 *.24 -.12);
  528.     }
  529.     hs0 = s0;
  530.     ft1 *= s1;
  531.     ft2  = .25 / ft1;
  532.     ft1 *= ft1;
  533.     ft1n = neg(ft1);
  534.     return ft1, ft1n, ft2, wa, d1, d2;
  535. }
  536. filt3x(input,f0, q0, s0,                 // 3x-oversampled 6-way 2p/4p SVF filter
  537.         lx, bx, hx, f2x, l4x, b4x, h4x, f4x, rsrx2pi){
  538.     History zl1, zb1, zl2, zb2;
  539.     o1, o2, o3 = upsample(input);
  540.     ft1, ft1n, ft2, wa, d1, d2 = svfCoeffs3x(f0, q0, s0, f4x, rsrx2pi);
  541.     // 1st 2-pole filter, 3x oversampled
  542.     l1, b1, h1 = svf(o1, wa, d1, ft1, ft1n, ft2, zl1, zb1);
  543.     l2, b2, h2 = svf(o2, wa, d1, ft1, ft1n, ft2, l1,  b1);
  544.     l3, b3, h3 = svf(o3, wa, d1, ft1, ft1n, ft2, l2,  b2);
  545.     zl1 = l3; 
  546.     zb1 = b3;
  547.     o1 = lx * l1 + bx * b1  + hx *  h1;    // LP/BP/HP mixing 
  548.     o2 = lx * l2 + bx * b2  + hx *  h2;
  549.     o3 = lx * l3 + bx * b3  + hx *  h3;
  550.     // 2nd 2-pole filter, 3x oversampled
  551.     l1, b1, h1 = svf(o1, wa, d2, ft1, ft1n, ft2, zl2, zb2);
  552.     l2, b2, h2 = svf(o2, wa, d2, ft1, ft1n, ft2, l1,  b1);
  553.     l3, b3, h3 = svf(o3, wa, d2, ft1, ft1n, ft2, l2,  b2);
  554.     zl2 = l3; 
  555.     zb2 = b3;
  556.     o1 = o1 * f2x + l4x * l1 + b4x * b1  + h4x *  h1; // output mix
  557.     o2 = o2 * f2x + l4x * l2 + b4x * b2  + h4x *  h2;
  558.     o3 = o3 * f2x + l4x * l3 + b4x * b3  + h4x *  h3;
  559.     return downsample(o1, o2, o3);
  560. }
  561. filt(input, type, poles, drive, fc, q, srflt){    //6-way SVF type and 0/2/4-pole mixers
  562. // type     -.01 = lpf, 0 = bpf, .01 = hpf
  563. // poles    -.01 = none, 0 = 2p, .01 = 4p
  564. // drive       sat in range 0~200
  565. // fc        pitch in midi units
  566. // q        res 0~100
  567. // srflt    constant, rsrxpi/3
  568.      Buffer svfgain("svfgain");
  569.     History lvl, f2, f4, l4, b4, h4, ox, zd;
  570.     l2, b2, h2, x, y = 0;
  571.     t  = smoother1(type);
  572.     p  = smoother1(poles);
  573.     if(t >0){
  574.         h2 = t * (4 - t) * .25;
  575.         x  = 2 - t;
  576.         b2 = x * (4 - x) * .25;
  577.        } else {
  578.         l2 = t * (4 + t) * -.25;
  579.         x  = 2 + t;
  580.         b2 = x * (4 - x) * .25;
  581.     }
  582.     if (change(p) != 0){
  583.         if (p >0){            // now make lvls for osc, 2poles, and 4poles
  584.             f2 = 1 - p;
  585.             f4 = p;            // make 4pole lp/bp/hp lvls
  586.             l4 = f4 * l2;    b4 = f4 * b2;    h4 = f4 * h2;
  587.             ox = 0;
  588.         } else {        // mix osc with 2pole
  589.             f2 = 1 + p;
  590.             f4 = 0;    l4 = 0;    b4 = 0;    h4 = 0;
  591.             ox = abs(p);
  592.         } 
  593.     }
  594.     output = filt3x(input,
  595.         fc, q, drive, l2, b2, h2, f2, l4, b4, h4, f4, srflt);
  596.     if(change(output >= 0) != 0){ //gain table lookup at sero crossing only
  597.         if (drive <=100){
  598.             x = floor(drive) *101 + round(q);
  599.             y =   l2 * peek(svfgain, x, 0, boundmode="clip")
  600.                 + b2 * peek(svfgain, x, 1, boundmode="clip")
  601.                 + h2 * peek(svfgain, x, 2, boundmode="clip");
  602.             y *= f2;
  603.             y +=  l4 * peek(svfgain, x, 3, boundmode="clip")
  604.                 + b4 * peek(svfgain, x, 4, boundmode="clip")
  605.                 + h4 * peek(svfgain, x, 5, boundmode="clip");
  606.         } else {
  607.             x = 10100 + round(q);
  608.             y =   l2 * peek(svfgain, x, 0, boundmode="clip")
  609.                 + b2 * peek(svfgain, x, 1, boundmode="clip")
  610.                 + h2 * peek(svfgain, x, 2, boundmode="clip");
  611.             y *= f2;
  612.             y +=  l4 * peek(svfgain, x, 3, boundmode="clip")
  613.                 + b4 * peek(svfgain, x, 4, boundmode="clip")
  614.                 + h4 * peek(svfgain, x, 5, boundmode="clip");
  615.             x = (drive - 100) * .01;
  616.             y =    mix(y, 1, (1 - x) * x * .00001);
  617.         }
  618.         output *= y;
  619.         lvl = y;
  620.         zd = drive * .01;
  621.     } else {
  622.         output *= lvl;
  623.     } 
  624.     if (ox !=0){            // osc mix into filter output
  625.         output += ox * input; 
  626.     }
  627.     if (zd >1){             // overdrive saturator
  628.         x = clip(output, -2,2); 
  629.         x = (x * (1 -(abs(x) * .25)));
  630.         output = mix(output, x, zd -1);
  631.     }
  632.     return output;
  633. }
  634. /******************************************************************************/
  635. // Ramp Oscillators
  636. ramp(inc){                                                // Ramp generator
  637.     History z1;
  638.     inc = wrap(inc + z1, 0, 1);
  639.     z1 = inc;
  640.     return inc;
  641. }
  642. rampsnc(inc, snc){                                        // Ramp, trig sync
  643. // snc    +ive transitions cause reset to 0
  644. // rsr  constant, 1/samplerate
  645. // resetmode "pre" is so accumulator wraps properly
  646. // inc must be set to 0 on sync so accum wraps properly rest of time
  647.     inc = (snc <=0)? inc : 0;
  648.     return accum(inc, snc, max=1, resetmode="pre");
  649. }
  650. rampgate(inc, gate){                                    // Ramp, gate sync
  651. // inc        ramp step size/ sample clock
  652. // gate        +vew transitions cause reset to 0
  653.     inc = (change(gate ==0) <=0)? inc : 0;
  654.     return accum(inc, snc, max=1, resetmode="pre");
  655. }
  656. rampphase(inc, phase, snc){                                // Ramp, phase snc
  657. // inc        ramp step size/ sample clock
  658. // snc        +ive transitions cause reset to phase val
  659.     inc  = (snc <= 0)? inc : inc * phase;
  660.     return accum(inc, snc, max=1, resetmode="pre");
  661. }
  662. rampsoft(inc, phase, thisosc, modosc){                    // Ramp, soft snc
  663. // inc        ramp step size/ sample clock
  664. // phase    when modulator transitions above this, snc occurs
  665. // mod        modulator signal, range ~1 ~1
  666.     snc = 0;
  667.     if (change(modosc > phase) >0 && thisosc > phase){
  668.         inc = 0;
  669.         snc = 1;
  670.     }
  671.     return accum(inc, snc, max=1, resetmode="pre");
  672. }
  673. rampsofter(inc, phase, thisosc, modosc){                    // Ramp, softer snc
  674. // inc        ramp step size/ sample clock
  675. // phase    when modulator transitions above this, snc occurs
  676. // mod        modulator signal, range ~1 ~1
  677.     snc = 0;
  678.     if (change(modosc > phase && thisosc > phase) >0){
  679.         inc = 0;
  680.         snc = 1;
  681.     }
  682.     return accum(inc, snc, max=1, resetmode="pre");
  683. }
  684. rampramp(inc, phase, mod){                                // Ramp ramped snc
  685. // inc        ramp step size/ sample clock
  686. // phase    when modulator transitions above this, snc occurs
  687. // mod        modulator signal, range ~1 ~1
  688.     History z1;
  689.     snc = 0;
  690.     if (change(z1 > phase) >0 && mod > phase){
  691.         inc = 0;
  692.         snc = 1;
  693.     }
  694.     ramp = accum(inc, snc, max=1, resetmode="pre");
  695.     z1 = ramp;
  696.     return ramp;
  697. }
  698. rampramper(inc, phase, mod){                            // Ramp, ramper snc
  699. // inc        ramp step size/ sample clock
  700. // phase    when modulator transitions above this, snc occurs
  701. // mod        modulator signal, range ~1 ~1
  702.     History z1;
  703.     snc = 0;
  704.     if (change(z1 > phase && mod > phase) > 0){
  705.         inc = 0;
  706.         snc = 1;
  707.     }
  708.     ramp = accum(inc, snc, max=1, resetmode="pre");
  709.     z1 = ramp;
  710.     return ramp;
  711. }
  712. // ******************************************************************************
  713. // Audio Oscillators
  714. parasine(inc){                    // a sine osc approximation. with much lower cpu
  715. // inc        increment, freq/samplerate * 4
  716.     History zinc;
  717.     zinc = wrap(zinc + inc, 0, 4);
  718.     x = 0;
  719.     if(zinc < 1) {
  720.          x = zinc * zinc;
  721.     } else if (zinc < 2){
  722.         x = 2 - zinc;
  723.         x = x * x;
  724.     } else if(zinc < 3){
  725.         x = zinc - 2;
  726.         x = neg(x * x);
  727.     } else {
  728.         x = 4 - zinc;
  729.         x = neg(x * x);
  730.     }
  731.     return x;
  732. }
  733. sine2sine(ramp, w1){                                 // sine shapes to octave doubler
  734. // ramp     from ramp osc
  735. // w1         sets waveshape
  736. // returns wave in range -1~+1
  737.     output = triangle(ramp, w1);
  738.     dx1 = delta(output);
  739.     output = cycle(wrap(output +.25, 0, 1), index="phase");
  740.     if (w1>0 && w1<1){
  741.         if (dx1>0 && w1<.5){
  742.              output *= (w1 *2);
  743.         } else if (dx1<0 && w1>.5){
  744.              output *= (2 - w1 *2);
  745.         }
  746.     } return output;
  747. }
  748. pulse(ramp, width){                                        // simple pulse
  749.     return (ramp > width)? 1 : -1;
  750. }
  751. pulse2(ramp, width){                                     // simple pulse
  752. // width in range 0~127
  753.     return (ramp * .007874 > width)? 1 : -1;
  754. }
  755. eptrpulse(ramp, inc, width){    //antialiasing slope for pulse osc
  756.     Buffer eptr("eptr");         // loads eptr buffer from Max
  757.     //d2 = twopi *.213332 / d1;    // transcendental coefficient;
  758.                                 // reading from precalculated 16384 buffer, so
  759.     d2 = 8192  / inc;            // buffer transition coefficient;
  760.     i2 = inc * .5;
  761.     //eptr equation: e0 = tanh(4 * sin(d2*(ramp -w1 +d1) -pi5)); 
  762.     if (ramp <= i2) return peek(eptr, d2 * (ramp + inc - width), 0);
  763.     else if (ramp <= width - i2) return 1; 
  764.     else if (ramp <= width + inc) 
  765.         return neg(peek(eptr, d2 * (ramp + inc -(1 - width)), 0));
  766.     else if (ramp < 1 -i2) return -1;
  767.     else return peek(eptr, d2 * (ramp + inc - width), 0);
  768. }
  769. eptrpulse3x(ramp, inc, width){                        // 3x Oversampled AA Pulse
  770.     History z0, zt, zr; 
  771.     t0, t1, t2, trans =0;
  772.     t0 = delta(ramp);
  773.     // input is linear ramp, so upsampling only needs linear interp!
  774.     if (t0>0){ 
  775.                 t2 = ramp -t0 *.6666667;            //z-2
  776.                 t1 = ramp -t0 *.3333333;            //z-1
  777.      } else {   
  778.                 t2 = wrap(zt *.3333333 +zr, 0, 1);  //z-2 
  779.                 t1 = wrap(zt *.6666667 +zr, 0, 1);  //z-1
  780.     }
  781.     zt = t0; // ramp and delta history for interp
  782.     zr = ramp; 
  783.     trans = inc * .5;
  784.     t2 = eptrpulse(t2,   trans, width); 
  785.     t1 = eptrpulse(t1,   trans, width); 
  786.     t0 = eptrpulse(ramp, trans, width);
  787.     // downsampling AA square needs unique consideration
  788.     if      (t2==t1 && t1==t0){
  789.                                                return t0;
  790.     }else if (t2!=-1 && t1==-1 && t0!=-1){ 
  791.                                             return -1;
  792.     }else if (t2!=1  && t1==1  && t0!=1){ 
  793.                                             return  1;
  794.     }
  795.     t0 = (t2 + t1 + t0) * .33333333;
  796.     return t0;
  797. }
  798. sawup (fc, r1, inc, srx3, sr3d3, rsr) {            // rising saw with EPTR AA
  799. // fc        freq, HZ
  800. // ramp        ramp osc (0~1)
  801. // inc        increment in each ramp step (needed to calculate EPTR vals)
  802. // srx3        constant, samplerate * 3
  803. // sr3d3    constant, samplerate ^3 /3
  804. // rsr        constant, 1 / samplerate
  805.     if (r1 < inc){
  806.         return pow(r1/ fc, 3) * sr3d3 
  807.             +r1 * fc * rsr 
  808.             + 1;
  809.     } else if(r1 < inc *2){
  810.         D = r1 *samplerate /fc;    
  811.         return D * D * D * .66666666666666666667 
  812.             - D * D *3 
  813.             + r1 *srx3/fc 
  814.             + r1 *2;        
  815.     } else if(r1 < inc *3) {
  816.         D = r1 *samplerate /fc;    
  817.         return D * D * D *-.33333333333333333333 
  818.             + D * D *3 
  819.             + D *inc *2 
  820.             - D *9 +8;    
  821.     } 
  822.     return r1 * 2 -1;
  823. }
  824. sawdown(fc, ramp, inc, srx3, sr3d3, rsr) {        // falling saw with EPTR AA
  825. // inputs same as for sawup
  826. // much same as sawup, with return values optimized 
  827.     if (ramp < inc){
  828.         return neg(
  829.             pow(ramp / fc, 3) * sr3d3 
  830.             + ramp * fc * rsr 
  831.             + 1);
  832.     } else if(ramp < inc *2){
  833.         D = ramp * samplerate /fc;    
  834.         return neg(
  835.             D * D * D * .66666666666666666667 
  836.             - D * D *3 
  837.             + ramp * srx3/fc 
  838.             + ramp *2);        
  839.     } else if(ramp < inc *3) {
  840.         D = ramp *samplerate /fc;    
  841.         return neg(
  842.             D * D * D *-.33333333333333333333
  843.             + D * D *3 
  844.             + D * inc *2 
  845.             - D *9 +8);    
  846.     }
  847.     return (1 - ramp) *2 -1;
  848. }
  849. tri(ramp, width){                            // simple variable saw/tri
  850.     return 
  851.         triangle(ramp, width) *2 -1;
  852. }
  853. tri2(ramp, width){                            // same, with w in range 0~127
  854.     return triangle(
  855.         ramp, width *0.0078740157480315) * 2 -1;
  856. }
  857. triwave(ramp, width){                         // variable tri/saw with simple AA
  858.     History zramp;
  859.     dx1 = ramp - zramp;    //dx1 = delta(r1);
  860.     zramp = ramp;
  861.     if (dx1 < 0) return -1;
  862.     else if (ramp > width && zramp < width) return 1;
  863.     return (ramp < width) ? ramp/width *2 -1 : (ramp - width)/(1 - width) *-2 +1;
  864. }
  865. sawtri(r1, w1, inc, fc, rsr, srx3, sr3d3){            // variable saw/tri with AA
  866. // see sawup for input descriptions
  867.     if (w1 ==0) {              // falling saw with AA
  868.         return sawdown(fc, r1, inc, srx3, sr3d3, rsr);
  869.     } else if (w1 == 1)  {     // rising saw with AA
  870.         return sawup (fc, r1, inc, srx3, sr3d3, rsr);
  871.     } // using ELSE at end of function causes compile errors
  872.     return triwave(r1, w1); // variable-slope tri with AA
  873. }
  874. karplus(impulse, fc, dampen){                        // Karplus oscillator
  875. // osc = karplus(impulse, fc, dampen);
  876. //        impulse:     noise impulse around 10msec
  877. //        fc:         frequency as samplerate/mtof(midi_pitch);
  878. //        dampen:     dampening as 0-.999999)
  879. //        osc:         karplus oscillator signal 
  880.     Delay karplus(960000, 1, feedback=1);
  881.     History hfilt;
  882.     x = karplus.read(fc, 0);
  883.     karplus.write(impulse + hfilt, 0);
  884.     y = hfilt;
  885.     hfilt = mix(x *.9999999999, y, dampen);
  886.     return x;
  887. }
  888. karplusd(impulse, fc, d){                        // diffused Karplus
  889.     Delay karplus(960000, 1, feedback=1);
  890.     History hfilt;
  891.     x = karplus.read(fc, 0);
  892.     x = diffdelay(x, fc, d);        // diffusions
  893.     // x = diffdelay(x, fc *2, d);
  894.     karplus.write(impulse + hfilt, 0);
  895.     y = hfilt;
  896.     hfilt = mix(x *.9999999999, y, .01);
  897.     return x;
  898. }
  899. karplusm(impulse, fc, d){                        // mod Karplus
  900.     Delay karplus(960000, 1, feedback=1);
  901.     History hfilt;
  902.     x = karplus.read(fc, 0);
  903.     x = diffdelay(x, fc *(d+1), d);        // diffusions
  904.     x = diffdelay(x, fc *1/(2 -d), d);    // diffusions
  905.     karplus.write(impulse + hfilt, 0);
  906.     y = hfilt;
  907.     hfilt = mix(x *.9999999999, y, .01);
  908.     return x;
  909. }
  910. waveset(sel, width, ramp){                                    // waveset oscillator
  911.     // sel:     waveset (1~47 in provided waveset)
  912.     // width:      waveform in waveset (0 ~127)
  913.     // ramp:     wavecycle in waveform (0 ~1)  
  914.      Buffer wavesets("wavesets");
  915.     i = floor(width) * 256;     // 256 samples/wave, 128 waves/waveset
  916.     return  mix(                 // return midpoint between two waveforms
  917.         sample(wavesets, ramp, i,      i +255, sel, index="wave", interp="spline"),
  918.          sample(wavesets, ramp, i +256, i +511, sel, index="wave", interp="spline"), 
  919.         fract(width)
  920.     ); 
  921. }
  922. noiselpf(fc,q,rsrxpi){                                // LPF noise osc
  923. // fc        Freq in HZ
  924. // q        typ range 1~21
  925. // rsrxpi    constant, pi / samplerate
  926.     q = q * .1 +1;
  927.     signal = noise();
  928.     a0, a1, a2, b1, b2 = biquadlo(
  929.         min(fc, 8372),
  930.         q,
  931.         rsrxpi);
  932.     y   = biquad(signal, a0, a1, a2, b1, b2);
  933.     y  *= .75;
  934.     return y;
  935. }
  936. noisebpf(fc,q,rsrxpi){                                // BPF noise osc
  937. // inputs as for noiselpf()
  938.     q = q * .2 +1;
  939.     signal = noise();
  940.     a0, a1, a2, b1, b2 = biquadband(
  941.         min(fc, 8372),
  942.         q,
  943.         rsrxpi);
  944.     y   = biquad(signal, a0, a1, a2, b1, b2);
  945.     y  *= 8;
  946.     return y;
  947. }
  948. noisehpf(fc,q,rsrxpi){                                // HPF noise osc
  949. // inputs as for noiselpf()
  950.     q = q * .2 +1;
  951.     signal = noise();
  952.     a0, a1, a2, b1, b2 = biquadhi(
  953.             min(fc, 8372),
  954.             q,
  955.             rsrxpi);
  956.     y   = biquad(signal, a0, a1, a2, b1, b2);
  957.     y  *= .5;
  958.     return y;
  959. }
  960. noisenotch(fc,q,rsrxpi){                            // notched noise osc
  961. // inputs as for noiselpf()
  962.     q = q * .2 +1;
  963.     n     = noise();
  964.     a0, a1, a2, b1, b2 = biquadnotch(
  965.             min(fc, 8372),
  966.             q,
  967.             rsrxpi);
  968.     y  = biquad(n, a0, a1, a2, b1, b2);
  969.     return y;
  970. }
  971. pinknoise(){
  972.     x = noise();
  973.     return static(x, -.267943, .633972, .633972) * .0473//lopass 16kHz
  974.         + static(x, .577352, .211324, .211324)* .125 //lopass 4khz
  975.         + static(x, .876977, .061511, .061511)* .25     //lopass 1kHz
  976.         + static(x, .967799, .0161, .0161)       * .5     //lopass 250Hz
  977.         + static(x, .991852, .004074, .004074)* 2;     //lopass 62.5Hz
  978. }
  979. noiseosc(type, p, fc, q, rsrxpi2){                            // noise osc
  980. // fc        Freq in HZ
  981. // q        typ range 0~1
  982. // rsrxpi2    constant, pi / samplerate *2
  983.     Buffer noisegain("noisegain");
  984.     History ha0, ha1, ha2, hb1, hb2, z1, z2, zg;
  985.     a0, a1, a2, b0, b1, b2 = 0;
  986.     if(change(type)!=0 || change(fc)!=0 || change(q)!=0){
  987.         omega = min(fc, 16744) * rsrxpi2;
  988.         omega1 = sin(omega);
  989.         omega2 = cos(omega);
  990.         alpha = (1 - q *.0095) * omega1;
  991.         b0    = 1 / (alpha + 1);
  992.         b1   = b0 * omega2 * -2;
  993.         b2   = b0 * (1 - alpha);
  994.         if (type <56){                    //low pass
  995.             a1  = b0 * (1 - omega2);
  996.             a0  = a1 * .5;
  997.             a2  = a0;
  998.         } else if (type <58){            //band pass
  999.             a1  = 0;
  1000.             a0  = b0 * omega1 * .5;
  1001.             a2  = neg(a0);
  1002.         } else if (type<60){            // hi pass
  1003.             a1  = b0 * neg(omega2 +1);
  1004.             a0  = a1 * -.5;
  1005.             a2  = a0;
  1006.         } else{        // notch
  1007.             a1  = b0 * b1;
  1008.             a0  = 1;
  1009.             a2  = 1;
  1010.         }
  1011.         ha0 = a0; ha1 = a1; ha2 = a2; hb1 = b1; hb2 = b2;
  1012.     }
  1013.     zg  = selector(type - 53,
  1014.         300/(p -12) * (1.1 -(q *.01)) * (1 + (q *.03)),    // lp white:
  1015.         300/(p -12) * (1.1 -(q *.01)) * (1 + (q *.03)),    // lp pink
  1016.         300/(p -12) * (1.1 -(q *.01)) * (1 + (q *.03)),    // bp white
  1017.         400/(p -12) * (1.1 -(q *.01)) * (1 + (q *.03)),    // bp pink
  1018.         2,                                                // hp white
  1019.         3,                                                // hp pink
  1020.         10 * q * .0025 +.1,                                // notch white
  1021.         15 * q * .0025 +.1                                // notch pink
  1022.     );
  1023.     if (type %2 == 0)
  1024.         return biquad(noise(), ha0, ha1, ha2, hb1, hb2) * zg;
  1025.     return biquad(pinknoise(), ha0, ha1, ha2, hb1, hb2) * zg;
  1026. }
  1027. osc(sel, p, fc, wide, ph, snc, trg, osc, mod1, mod2, env, rsrms, srx3, sr3d3, rsrxpi2, rsr){
  1028. // sel        wave select
  1029. // fc        pitch in midi units
  1030. // wid        morph, 9~1
  1031. // ph        phase, 0~1
  1032. // trg         sync trigger
  1033. // osc        this osc (prev cycle from history)
  1034. // osc2`    the osc used for sync
  1035. // rsrxpi, rsrms, rsr, sr3d3, srx3: constants
  1036.     History oinc, wid;
  1037.     output = 0;
  1038.     v, x, y = 0;
  1039.     if(sel >53){                                                        // noise
  1040.         output = noiseosc(sel, p, fc, wide, rsrxpi2);
  1041.     } else if(sel == 48){                                                // harp
  1042.             v = samplerate / fc;
  1043.             y  = noise() * env;
  1044.             output = karplus(y, v, wide * .008);
  1045.     } else if(sel == 49){                                                // env
  1046.             v = samplerate / fc;
  1047.             y  = noise() * (ramptrig(10, trg || (change(sel == 48) >0), rsrms));
  1048.             output = karplus(y, v, wide * .008);
  1049.     } else if(sel == 50){                                                // bowed
  1050.             v = samplerate / fc;
  1051.             y  = cycle(fc) * (1-(ramptrig(100, trg || (change(sel == 48) >0), rsrms)));
  1052.             output = karplus(y, v, wide * .008);
  1053.     } else if(sel == 51){                                                // diffuse env
  1054.             v = samplerate / fc;
  1055.             y  = noise() * env;
  1056.             output = karplusd(y, v, wide * .01);
  1057.     } else if(sel == 52){                                                // mod env
  1058.             v = samplerate / fc;
  1059.             y  = noise() * env;
  1060.             output = karplusm(y, v, wide * .01);
  1061.     } else {                                                        // ramped oscs
  1062.         v = min(fc, 16744) * rsr; //= ramp inc; max MIDI 132.
  1063.         x = wrap(oinc + v, 0, 1);
  1064.         if     (snc==2 && trg==1)                           x = ph; // gate snc
  1065.          else if(snc==3 && change(mod1 > ph) >0)             x = 0;    // soft snc 1
  1066.         else if(snc==4 && change(mod1 > ph && osc > ph) >0) x = 0;    // softer snc 1
  1067.         else if(snc==5 && change(mod1 > 0  && x   > ph) >0) x = 0;    // ramp snc 1
  1068.         else if(snc==6 && change(mod1 > ph && x   > ph) >0) x = 0;    // ramper snc 1
  1069.          else if(snc==7 && change(mod2 > ph) >0)             x = 0;    // soft snc 2
  1070.         else if(snc==8 && change(mod2 > ph && osc > ph) >0) x = 0;    // softer snc 2
  1071.         else if(snc==9 && change(mod2 > 0  && x   > ph) >0) x = 0;    // ramp snc 2
  1072.         else if(snc >9 && change(mod2 > ph && x   > ph) >0) x = 0;    // ramper snc 2
  1073.         oinc = x;
  1074.         wid  = sah(wide, change(x)==-1);
  1075.         if (sel ==1) {                                                         // PULSE
  1076.             if (v <.125) // if Fc > sr/16 (2756Hz @441000 sr), oversample
  1077.                  output = eptrpulse3x(x, v, scale(wid, 0, 100, .025, .975));
  1078.             else output = eptrpulse(  x, v, wid *.009 +.0005);
  1079.         } else if (sel ==2) {                                                 // SAW/TRI
  1080.             if (wid == 0) {                                 // falling saw
  1081.                 if (x < v){
  1082.                     output =neg(pow(x/fc, 3) *srx3 +x *fc *rsr +1);
  1083.                 } else if(x < v *2){
  1084.                     y = x / v;    
  1085.                     output =neg(y *y *y *.66666666666666666667 -y *y *3 +x *sr3d3/fc +x *2);        
  1086.                 } else if(x < v *3) {
  1087.                     y = x / v;    
  1088.                     output =neg(y *y *y *-.33333333333333333333 +y *y *3 +y *v *2 -y *9 +8);    
  1089.                 } else {
  1090.                     output = 1 -x *2;
  1091.                 } 
  1092.             } else if (wid == 100) {                         // rising saw
  1093.                 if (x < v){
  1094.                     x = pow(x/ fc, 3) *sr3d3 +x *fc *rsr +1;
  1095.                 } else if (x < v *2){
  1096.                     y = x / v;    
  1097.                     output = y *y *y *.66666666666666666667 -y *y *3 +x *srx3/fc +x *2;        
  1098.                 } else if(x < v *3) {
  1099.                     y = x / v;    
  1100.                     output = y *y *y *-.33333333333333333333 +y *y *3 +y *v *2 -y *9 +8;    
  1101.                 } else {
  1102.                     output =x *2 -1;
  1103.                 }
  1104.             } else output = triwave(x, wid *.01);             // triangle
  1105.         } else if (sel == 53){                                // noise/random
  1106.             output = mix(sah (noise(), change(x) <0), noise(), wid *.01);
  1107.         } else {                                             //WAVESET
  1108.             output  = waveset(sel, wid *1.27, x);
  1109.         }
  1110.         if(snc >2 || sel== 48){        //dcblock distorts waves, so only use it for synced waveforms
  1111.             output = dcblock(output);
  1112.         }
  1113.     }
  1114.     return output;
  1115. }
  1116. // ******************************************************************************
  1117. // IIRs
  1118. comb(input, delay, feedback, lvl){                     //feedforward comb with feedback
  1119. // input    signal to comb filter
  1120. // delay    delay time in samples
  1121. // feedback    values 1 or higher cause self oscillation
  1122. // lvl        comb amplitude, 0~1 
  1123.     Delay comb1(30000, 1, feedback = 0);// supports 8Hz at 192Khz samplerate
  1124.     Delay comb2(30000, 1, feedback = 1);
  1125.     comb1.write(input);
  1126.     if (lvl >0){
  1127.         delay     = smoother3(delay);
  1128.         feedback  = smoother1(feedback);
  1129.         output    = comb1.read(delay, 0, interp="spline") + input;
  1130.         output   += comb2.read(delay, 0, interp="spline") * feedback;
  1131.         comb2.write(output);
  1132.         return output;
  1133.     } else {
  1134.         return input;
  1135.     }
  1136. }
  1137. /******************************************************************************/
  1138. // LFOs 
  1139. lfo(sel,frq,wid,snc_en,trg,rsr,fourpi){                        // basic LFO
  1140. // sel            0 = off, 1 = sin, 2 = ramp, 3 = noise
  1141. // frq            Hz
  1142. // wid            waveshape
  1143. // syncen        boolean
  1144. // trg            trigger for sync
  1145. // fourpi         constant, twopi * 2;
  1146.     frq    = frq * rsr;
  1147.     x = accum(max (0, frq), (snc_en)? trg: 0, max=1);
  1148.     x = selector(sel,
  1149.         mix(sin(x * twopi), sin(x * fourpi), wid) *2,
  1150.         triangle(wrap(x +.25, 0, 1), wid) *2 -1,
  1151.         (wrap(x + wid, 0, 1) >(wid*.98 +.01))* 2 -1,
  1152.         sah(noise(), mix(x>wid,noise(),wid))
  1153.     );
  1154.     return x;    
  1155. }
  1156. lfopoly(sel, frq, sprd, sprdlvl, sprdtype, 
  1157.         wid, sncen, trg, fourpi, rsr){// LFO with amp and freq spread
  1158. // sel            0 = off, 1 = sin, 2 = ramp, 3 = noise
  1159. // frq            Hz
  1160. // sprd            the ampunt of spread for this poly instance
  1161. // sprdlvl        the panel control value for spread amount
  1162. // sprdtype        0 = freq spread, 1 =- amp spread
  1163. // wid            waveshape
  1164. // syncen        boolean
  1165. // trg            trigger for sync
  1166. // fourpi         constant, twopi * 2;
  1167. // rsr            constant, 1/samplerate 
  1168.     sprd   = sprd * sprdlvl + 1;
  1169.     frq    = frq * rsr;
  1170.     amod   = 1;
  1171.     if(sprdType==0){
  1172.         frq = frq * sprd;
  1173.     } else {
  1174.         amod = sprd;
  1175.     }
  1176.     x = accum(max (0, frq), (snc_en)? trg: 0, max=1);
  1177.     x = selector(sel, 
  1178.         mix(sin(x * twopi), sin(x * fourpi), wid) * amod, 
  1179.         triangle(wrap(x +.25, 0, 1), wid) *amod *2 -amod, 
  1180.         (wrap(x + wid, 0, 1) >(wid*.98 +.01))* amod * 2 -amod, 
  1181.         sah(noise1, mix(x>wid,noise1,wid))*amod * 2 - amod);
  1182.     return x;    
  1183. }
  1184. /******************************************************************************/
  1185. /* Envelopes ******************************************************************/
  1186. /******************************************************************************/
  1187. adsr(gate,predelay,att,dec,sus,susn,rel){                         // BASIC ADSR
  1188. // gate:         +ve transitions from prior value start gate
  1189. // predelay:     sample clock / sample cycles for 5 ms delay 
  1190. // att:         sample clock / sample cycles for attack
  1191. // dec:         sample clock / sample cycles for dec
  1192. // sus:         sustain between 0 & 1
  1193. // susn:        1 - sustain
  1194. // rel:            sample clock / sample cycles for release
  1195. // returns env level 0~1
  1196.     Buffer pow25("pow25");
  1197.     History hinc, henv, hlvl;
  1198.     inc = hinc;
  1199.     trg = change(gate);
  1200.         if (trg >0) {        // envelope on
  1201.         if (henv) {            //if trg and env already on, add 5ms decay
  1202.             inc = 1;
  1203.             hlvl = henv;
  1204.         } else inc = 2;    
  1205.     } else if (trg <0) {    // envelope off
  1206.         inc = 5;
  1207.         hlvl = henv;
  1208.     }
  1209.     inc += selector(hinc,    // set inc for each phase duration
  1210.         predelay,            // 1: pre-decay time
  1211.         att,                // 2: attack time
  1212.         dec,                   // 3: decay time
  1213.         0,                     // 4: hold on sustain
  1214.         rel,                  // 5: release time
  1215.         0);                    // 6: end of env cycle
  1216.     env = selector(floor(inc),                                // calc output levels
  1217.         sample (pow25, 1 - wrap(inc, 0, 1)) * hlvl,            // 1. pre-decay
  1218.         sample (pow25, wrap(inc, 0, 1)),                    // 2. attack
  1219.         sample (pow25, 1 - wrap(inc, 0, 1)) * susn + sus,    // 3. decay
  1220.         sus,                                                // 4. sustain
  1221.         sample (pow25, 1 - wrap(inc, 0,1)) * hlvl,            // 5. release
  1222.         0);                                                    // 6. end of cycle
  1223.     hinc = inc;
  1224.     henv = env;
  1225.     return env;
  1226. }
  1227. adsrloop(trg,gate,predelay,att,dec,sus,susn,rel,mode){ // ADSR with loop mode
  1228. // trg:            single-cycle trigger to start envelope
  1229. // gate:         HIGH while gate is on
  1230. // predelay:     sample clock / sample cycles for 5 ms delay 
  1231. // att:         sample clock / sample cycles for attack
  1232. // dec:         sample clock / sample cycles for dec
  1233. // sus:         sustain between 0 & 1
  1234. // susn:        1 - sustain
  1235. // rel:            sample clock / sample cycles for release
  1236. // mode:        if 2, loop is turned on, otherwise no loop
  1237. // returns env level 0~1
  1238.     Buffer pow25("pow25");
  1239.     History hinc, henv, hlvl;
  1240.     inc = hinc;
  1241.     if (trg >0) {
  1242.         if (henv) {    
  1243.             inc = 1;
  1244.             hlvl = henv;
  1245.         } else {
  1246.             inc = 2;    
  1247.         }
  1248.     } else if (trg < 0) {
  1249.         inc = 5;
  1250.         hlvl = henv;
  1251.     }
  1252.     inc += selector(hinc,    // set inc for each phase duration
  1253.         predelay,            // 1: pre-decay if env on
  1254.         att,                // 2: attack time
  1255.         dec,                   // 3: decay time
  1256.         0,                     // 4: hold on sustain
  1257.         rel,                  // 5: release time
  1258.         0);                    // 6: end of env cycle
  1259.     env = selector(floor(inc),                                // calc output levels
  1260.         sample (pow25, 1 - wrap(inc, 0, 1)) * hlvl,            // 1: pre-decay
  1261.         sample (pow25, wrap(inc, 0, 1)),                    // 2: attack
  1262.         sample (pow25, 1 - wrap(inc, 0, 1)) * susn + sus,    // 3: decay
  1263.         sus,                                                // 4: sustain
  1264.         sample (pow25, 1 - wrap(inc, 0,1)) * hlvl,            // 5: release
  1265.         0);                                                    // 5: end of cycle
  1266.     if (mode==2 && gate>0){    // loop mode
  1267.         if (inc >=4){     // at end of decay, loop to attack
  1268.             inc = 2 + att;
  1269.             henv = sus;
  1270.             hlvl = sus;
  1271.         }else if (inc <3){ //during attack, lvl increases from  sustain
  1272.             env = sus + susn * sample(pow25, wrap(hinc, 0, 1));
  1273.         }
  1274.         hinc = inc;
  1275.     } else {
  1276.         hinc = inc;
  1277.         henv = env;
  1278.     }
  1279.     return env;
  1280. }
  1281. padsrloop(trg,gate,pre1, pre2,att,dec,sus,rel,mode){//PADSR, loop & predelay
  1282. // trg:            single-cycle trigger to start envelope
  1283. // gate:         HIGH while gate is on
  1284. // pre1:         sample clock / sample cycles for 5 ms predecay 
  1285. // pre2:         sample clock / sample cycles for predelay 
  1286. // att:         sample clock / sample cycles for attack
  1287. // dec:         sample clock / sample cycles for dec
  1288. // sus:         sustain between 0 & 1
  1289. // rel:            sample clock / sample cycles for release
  1290. // mode:        if 2, loop is turned on, otherwise no loop
  1291. // returns env level 0~1
  1292.     Buffer pow25("pow25");
  1293.     History hinc, henv, hlvl;
  1294.     inc = hinc;
  1295.     if (trg >0){
  1296.         if (henv) {//if trg & env on, use pre1
  1297.             inc = 1;
  1298.             hlvl = henv;
  1299. // subtract pre1 from pre2
  1300.         } else {
  1301.             inc = 2;
  1302.         }
  1303.     } else if (trg < 0) {
  1304.         inc = 6;
  1305.         hlvl = henv;
  1306.     }
  1307.     inc += selector(hinc,
  1308.         pre1,        // 1: pre-decay
  1309.         pre2,        // 2: predelay
  1310.         att,        // 3: attack time
  1311.         dec,           // 4: decay time
  1312.         0,             // 5: hold on sustain
  1313.         rel,          // 6: release time
  1314.         0);            // 7: end of env cycle
  1315.     env = selector(floor(inc),
  1316.         sample (pow25, 1 - wrap(inc, 0, 1)) * hlvl,            // 1. pre-decay
  1317.         0,                                                    // 2. predelay
  1318.         sample (pow25, wrap(inc, 0, 1)),                    // 3. attack
  1319.         sample (pow25, 1 - wrap(inc, 0, 1)) *(1- sus) + sus,// 4. decay
  1320.         sus,                                                // 5. sustain
  1321.         sample (pow25, 1 - wrap(inc, 0,1)) * hlvl,            // 6. release
  1322.         0);                                                    // 7. end of cycle
  1323.     if (mode==2 && gate>0){    // loop mode
  1324.         if (inc >=5){     // at end of decay, loop to predelay
  1325.             inc = 2 + pre2;
  1326.             henv = sus;
  1327.             hlvl = sus;
  1328.         }else if (inc <3 && inc >=2){ //during att, lvl increases from sustain
  1329.             env = sus + (1 - sus) * sample(pow25, wrap(hinc, 0, 1));
  1330.         }
  1331.         hinc = inc;
  1332.     } else {
  1333.         hinc = inc;
  1334.         henv = env;
  1335.     }
  1336.     return env;
  1337. }
  1338. adbdsrloop(                                                        // ADBDSR with loop
  1339.     trg,gate,predelay,att,dec1,brk,dec2,sus,rel,mode){
  1340. // trg:            single-cycle trigger to start envelope
  1341. // gate:         HIGH while gate is on
  1342. // predelay:     sample clock / sample cycles for 5 ms delay 
  1343. // att:         sample clock / sample cycles for attack1
  1344. // dec1:         sample clock / sample cycles for dec1
  1345. // brk:         break level between 0 & 1
  1346. // brkn:        1 - break level
  1347. // dec2:         sample clock / sample cycles for dec2
  1348. // sus:         sustain between 0 & 1
  1349. // susn:        1 - sustain
  1350. // rel:            sample clock / sample cycles for release
  1351. // mode:        if 2, loop is turned on, otherwise no loop
  1352. // returns env level 0~1 AND current inc level
  1353.     Buffer pow25("pow25");
  1354.     History hinc(7), henv, hlvl;
  1355.     inc = hinc;
  1356.     if (trg >0) {
  1357.         if (henv) {            //if trg and env already on, add 25ms decay
  1358.             inc = 1;
  1359.             hlvl = henv;
  1360.         } else {                //otherwise  skip it
  1361.             inc = 2;    
  1362.         }
  1363.     } else if (trg <0) {
  1364.         inc = 6;
  1365.         hlvl = henv;
  1366.     } else if (henv == 0) {    // this is main envelope, so it also supplies inc.
  1367.         return 0, 7;        // and explicity sets 0 if env has not yet run. 
  1368.     }
  1369.     inc += selector(hinc,
  1370.         predelay,    // 1: pre-decay time
  1371.         att,        // 2: attack time
  1372.         dec1,       // 3: decay1 time
  1373.         dec2,       // 4: decay2 time
  1374.         0,             // 5: hold on sustain
  1375.         rel,          // 6: release time
  1376.         0);            // 7: end of env cycle
  1377.     env = selector(floor(inc),
  1378.         sample (pow25, 1 - wrap(inc, 0, 1)) * hlvl,                  // 1: pre-decay
  1379.         sample (pow25, wrap(inc, 0, 1)),                          // 2: att lvl
  1380.         sample (pow25, 1 - wrap(inc, 0, 1)) * (1 -brk) + brk,        // 3: dec1 lvl
  1381.         (brk > sus)?                                               // 4: dec2 lvl
  1382.             // decay from break to sus
  1383.             sample (pow25, 1 - wrap(inc, 0, 1)) * (brk - sus) + sus : 
  1384.              // attack from break to sus
  1385.             sample (pow25, wrap(inc, 0, 1)) * (sus - brk) + brk,
  1386.         sus,                                                      // 5: sustain
  1387.         sample (pow25, 1 - wrap(inc, 0,1)) * hlvl,                  // 6: rel lvl
  1388.         0                                                          // 7: cycle end
  1389.     );
  1390.     if (mode==2 && gate>0){    // loop mode
  1391.         if (inc >=5){     // at end of decay2, loop to attack
  1392.             inc = 2 + att;
  1393.             henv = sus;
  1394.             hlvl = sus;
  1395.             hinc = inc;
  1396.             return env, inc;
  1397.         } else if (inc <3){ //during attack, lvl increases from from sustain lvl
  1398.             env = sus + (1 -sus) * sample(pow25, wrap(hinc, 0, 1));
  1399.             henv = env;
  1400.             return env, inc;
  1401.         }
  1402.     } 
  1403.     hinc = inc;
  1404.     henv = env;
  1405.     return env, inc;
  1406. }
  1407. padbdsrloop(                                        // PADBDSR. predelay & loop
  1408.     trg,gate,pre1,pre2,att,dec1,brk,dec2,sus,rel,mode){
  1409. // trg:            single-cycle trigger to start envelope
  1410. // gate:         HIGH while gate is on
  1411. // pre1:         sample clock / sample cycles for 5 ms predecay 
  1412. // pre2:         sample clock / sample cycles for predelay 
  1413. // att:         sample clock / sample cycles for attack1
  1414. // dec1:         sample clock / sample cycles for dec1
  1415. // brk:         break level between 0 & 1
  1416. // dec2:         sample clock / sample cycles for dec2
  1417. // sus:         sustain between 0 & 1
  1418. // rel:            sample clock / sample cycles for release
  1419. // mode:        if 2, loop is turned on, otherwise no loop
  1420. // returns env level 0~1 AND current inc level
  1421.     Buffer pow25("pow25");
  1422.     History hinc(7), henv, hlvl;
  1423.     inc = hinc;
  1424.     if (trg >0) {
  1425.         if (henv) {            //if trg and env already on, add 25ms decay
  1426.             inc = 1;
  1427.             hlvl = henv;
  1428.         } else {                //otherwise  skip it
  1429.             inc = 2;    
  1430.         }
  1431.     } else if (trg <0) {
  1432.         inc = 7;
  1433.         hlvl = henv;
  1434.     }
  1435.     inc += selector(hinc, // env times
  1436.         pre1,        // 1: pre-attack time
  1437.         pre2,        // 2: predelay
  1438.         att,        // 3: attack time
  1439.         dec1,       // 4: decay1 time
  1440.         dec2,       // 5: decay2 time
  1441.         0,             // 6: hold on sustain
  1442.         rel,          // 7: release time
  1443.         0);            // 8: end of env cycle
  1444.     env = selector(floor(inc),                                    // env levels:
  1445.         sample (pow25, 1 - wrap(inc, 0, 1)) * hlvl,                  // 1: pre decay
  1446.         0,                                                           // 2. predelay
  1447.         sample (pow25, wrap(inc, 0, 1)),                          // 3: att lvl
  1448.         sample (pow25, 1 - wrap(inc, 0, 1)) * (1 -brk) + brk,        // 4: dec1 lvl
  1449.         (brk > sus)?                                               // 5: dec2 lvl
  1450.             // decay from break to sus
  1451.             sample (pow25, 1 - wrap(inc, 0, 1)) * (brk - sus) + sus : 
  1452.              // attack from break to sus
  1453.             sample (pow25, wrap(inc, 0, 1)) * (sus - brk) + brk,
  1454.         sus,                                                      // 6: sustain
  1455.         sample (pow25, 1 - wrap(inc, 0,1)) * hlvl,                  // 7: rel lvl
  1456.         0                                                          // 8: cycle end
  1457.     );
  1458.     if (mode==2 && gate>0){    // loop mode
  1459.         if (inc >=6){     // at end of decay, loop to predelay
  1460.             inc = 2 + att;
  1461.             henv = sus;
  1462.             hlvl = sus;
  1463.             hinc = inc;
  1464.             return env, inc;
  1465.         } else if (inc <3){ //during attack, lvl increases from from sustain lvl
  1466.             env = sus + (1 -sus) * sample(pow25, wrap(hinc, 0, 1));
  1467.             henv = env;
  1468.             return env;
  1469.         }
  1470.     } 
  1471.     hinc = inc;
  1472.     henv = env;
  1473.     return env;
  1474. }
  1475. // *******************************************************************************
  1476. // EFFECTS
  1477. glide(pitch, inc, scale, key, type, pat){ // glide
  1478. // pitch    current pitch, MIDI units
  1479. // inc        samples in one quarter beat
  1480. // rate        multiplier of inc for glide/glissando duration 
  1481. // key        c = 0, c# =1, etc
  1482. // type        0=glide fixed, 1=glide auto, 2=gliss fixed, >2=gliss auto
  1483. // scale    index to channel in scales buffer
  1484. // pat        index to channel in pattern buffer
  1485. // rsr96    constant, 24 / (samplerate * 60 * 96)
  1486. // returns pitch after glide/glissando 
  1487.     Buffer scales("scales"), patterns("patterns");
  1488.     Data gliss(128);
  1489.     History zp1, zp2, zinc(128), zstep, zdir, w;
  1490.     zp1   = latch(zp2, change(pitch)); // prior pitch
  1491.     p0    = pitch;
  1492.      y, z   = 0;
  1493.     if (change(type)){
  1494.         zinc = 128;        // stops weird things at init
  1495.     }
  1496.     if (type !=0){
  1497.         if(change(zp1)){                            // scales
  1498.             zinc  = 0;                                 // increment
  1499.             zstep = 0;
  1500.             w     = p0 - zp1;                        // change in pitch
  1501.             zdir  = sign(w);                        // direction
  1502.             gliss.poke(zp1, 0);                        // array of gliss values
  1503.             for (x = 1; x <= abs(w); x += 1){
  1504.                 y = x * zdir + zp1 + key;
  1505.                 z = scales.peek(y, scale);            // scale
  1506.                 if (z != scales.peek(y + zdir, scale)){
  1507.                     y = patterns.peek(zstep, pat);
  1508.                     if( y < abs(w)){    
  1509.                         gliss.poke(z - key, y);    
  1510.                         zstep += 1;                          // intervals
  1511.                     }
  1512.                 }
  1513.             }
  1514.         } else if (zp1 != p0){
  1515.             y   = inc;
  1516.             if (type==1){                            // fixed-rate glide
  1517.                 if (zinc <  abs(w)){
  1518.                     zinc += y * abs(w);
  1519.                     p0    = zp1 + zinc * zdir;
  1520.                 }
  1521.             } else if (type==2){                    // auto-rate rate
  1522.                 if (zinc < 1){
  1523.                     zinc += y;
  1524.                     p0    = zp1 + zinc * w;
  1525.                 }
  1526.             } else if (type==3){                    // fixed-rate glissando
  1527.                 if (zinc < zstep){
  1528.                     zinc += y;
  1529.                     p0    = gliss.peek(zinc);
  1530.                 }
  1531.             }else if (type==4){                        // auto-rate glissando, 
  1532.                 if (zinc < zstep){
  1533.                     p0    = gliss.peek(ceil(zinc));
  1534.                     zinc += y * zstep;
  1535.                 }
  1536.             }
  1537.         }
  1538.         zp2  = p0;      // last p from glide/gliss, if note changes while rinning 
  1539.     }
  1540.     return p0;
  1541. }
  1542. ping1(input1, input2, delayL, delayR, mix, cross,                 // simpler stereo delay
  1543.         inpan, feedback){
  1544. // input1/2        signals L and R
  1545. // delayL/R        delays in samples
  1546. // mix            mix of signals with delay (0 bypasses effect)
  1547. // cross        0, the L and R delay lines are separate
  1548. //                1, the delay fully ping pongs
  1549. // inpan        0, only left input is passed into delay. 1, only right
  1550. // feedback        the amount of feedback
  1551. // time            base delay, samples
  1552.     Delay ping(384000, 2, feedback=1);// allows 2 secs at 192khz
  1553.     u, v, w, x, y, z = 0;
  1554.     delayL = smoother3( delayL);    // delays
  1555.     delayR = smoother3( delayR);
  1556.     if(mix > 0){ // this part can be bypassed when not used. 
  1557.         x = ping.read(delayL, 0, interp="spline");
  1558.         y = ping.read(delayR, 1, interp="spline");
  1559.         w = 1 - cross;
  1560.         u = input1 * (1 - inpan);
  1561.         v = input2 * inpan;
  1562.         ping.write((x * z + y * cross) * feedback + u * w + v * cross, 0);
  1563.         ping.write((y * z + x * cross) * feedback + v * w + u * cross, 1);
  1564.         u = smoother1(mix);
  1565.         v = 1 - u; u *= 2;
  1566.         return input1 * v + x * u, input2 * v + y * u;
  1567.     } else {
  1568.         ping.write(input1, 0); ping.write(input2, 1);
  1569.         return input1, input2;
  1570.     }
  1571. }
  1572. ping2(input1, input2, delayL, delayR, mix, cross, inpan, // stereo delay with hi/lo cut
  1573.         feedback, locut, hicut, time){
  1574. // cutlo/hi        lo and cutoff in midi units 
  1575.     Delay ping(384000, 2, feedback=1);// allows 2 secs at 192khz
  1576.     History zlocut, zhicut, za1, zb0, zb1, z2a1, z2b0, z2b1;
  1577.     u, v, x, y, z = 0;
  1578.     delayL = smoother3( delayL);    // delays
  1579.     delayR = smoother3( delayR);
  1580.     if(mix > 0){ // this part can be bypassed when not used. 
  1581.         if (locut != zlocut){                // lo filter coefficients
  1582.             za1, zb0, zb1 = staticlo(mtof(locut), 12);
  1583.             zlocut = locut;
  1584.         }
  1585.         if (hicut != zhicut){                // hi filter coefficients
  1586.             z2a1, z2b0, z2b1 = statichi(mtof(hicut), 12);
  1587.             zhicut = hicut;
  1588.         }
  1589.         x = ping.read(delayL, 0, interp="spline");
  1590.         y = ping.read(delayR, 1, interp="spline");
  1591.         x = static(x, za1, zb0, zb1);
  1592.         x = static(x, z2a1, z2b0, z2b1);
  1593.         y = static(y, za1, zb0, zb1);
  1594.         y = static(y, z2a1, z2b0, z2b1);
  1595.         w = 1 - cross;
  1596.         u = input1 * (1 - inpan);
  1597.         v = input2 * inpan;
  1598.         ping.write((x * z + y * cross) * feedback + u * w + v * cross, 0);
  1599.         ping.write((y * z + x * cross) * feedback + v * w + u * cross, 1);
  1600.         u = smoother1(mix);
  1601.         v = 1 - u; u *=2;
  1602.         return input1 * v + x * u, input2 * v + y * u;
  1603.     } else {
  1604.         ping.write(input1, 0);    ping.write(input2, 1);
  1605.         return input1, input2;
  1606.     }
  1607. }
  1608. flange(input,f_deep, f_rate, f_fb, f_cntr, f_sat, f_mix){    //stereo flange
  1609.     Delay delayF(24000, 2, feedback=1); 
  1610.     fx1 = delayF.read(cycle(f_rate)* f_deep + f_cntr,          0, interp="linear");
  1611.     fx2 = delayF.read(cycle(f_rate * 1.31) * f_deep + f_cntr,1, interp="linear");
  1612.     if(f_sat!=0){ 
  1613.         fx1 = parabol(fx1 + fx2,f_sat);
  1614.     }else{
  1615.         fx1 = fx1 + fx2;
  1616.     }
  1617.     delayF.write(input + fx1 * f_fb);
  1618.     return mix(input,fx1,f_mix), neg(mix(fx1,input,f_mix));
  1619. }
  1620. chorus(left, right, cdel, deep, sprd, cmix,                        // simple stereo chorus
  1621.         s1, s2, s3, s4, s5, s6, s7, s8 ){
  1622. // left/right    signals L and R
  1623. // cdel            base delay, samples
  1624. // deep            depth of modulation, factor of cdel
  1625. // sprd            spread of delay, factor of cdel
  1626. // mix            output mix
  1627. // s1-s8        sine oscillators in range -1-1
  1628.     Delay ch(10000, 2, feedback=1); 
  1629.     ch.write(left);
  1630.     ch.write(right);
  1631.     x, y = 0;
  1632.     if(cmix != 0){                                                    // chorus
  1633.         cdel = smoother3(cdel);
  1634.         o1 =  ch.read(cdel + deep * s1,                 0, interp="linear") 
  1635.                + ch.read(cdel + deep * s2 + sprd * .25,     0, interp="linear")
  1636.                + ch.read(cdel + deep * s3 + sprd * .5,        0, interp="linear") 
  1637.                + ch.read(cdel + deep * s4 + sprd * .75,     0, interp="linear");
  1638.         o2 =  ch.read(cdel + deep * s5 + sprd * .125,    1, interp="linear") 
  1639.                + ch.read(cdel + deep * s6 + sprd * .375,    1, interp="linear")
  1640.                + ch.read(cdel + deep * s7 + sprd * .625,    1, interp="linear") 
  1641.                + ch.read(cdel + deep * s8 + sprd * .875,     1, interp="linear");
  1642.         x = smoother1(cmix);
  1643.         y = 1 - x; x *= .5;
  1644.         return  left * y + o1 * x, right * y + o2 * x;
  1645.     } else {
  1646.         return left, right;
  1647.     }
  1648. }
  1649. diffdelay(input, delay, diff){                //  diffusion delay
  1650. // input    signal to diffuse
  1651. // delay    diffuser delay in samples
  1652. // diff        diffusion amount
  1653.     Delay d(1000);
  1654.     x = d.read(delay);
  1655.     input = input - x * diff;
  1656.     d.write(input);
  1657.     input = x + input * diff;
  1658.     return input;
  1659. }
  1660. tankLeft(input, damp, decay){          // left late reflections
  1661. // input    signal to diffuse
  1662. // damp        typ. .5
  1663. // decay    typ. .7
  1664.     Delay d1(924, feedback=1),
  1665.     d2(4217,4, feedback=1),
  1666.     d3(2656,3, feedback=1),
  1667.     d4(5163,3, feedback=1);
  1668.     History z1;
  1669.     y = d1.read(908 + cycle(.07) *16);
  1670.     x = input * decay + y *.7;
  1671.     d1.write(x);
  1672.     x = y - x *.7;
  1673.      d2.write(x);            // diffuser 2
  1674.     x = d2.read(4217, 0);
  1675.     x = mix(x, z1, damp);    // damp
  1676.     z1 = x;
  1677.     y = d3.read(2656, 0);    // taps out
  1678.     x = x * decay - y *.5;
  1679.     d3.write(x);
  1680.     d4.write(y + x *.5);    // diffuser 3
  1681.     x = d4.read(3163, 0) * decay;
  1682.     y = d2.read(266,1) + d2.read(2974,2) + d4.read(1996,2)
  1683.         - d3.read(1913,2);
  1684.     z = d2.read(2111,3) + d3.read(335,1) + d4.read(121,1);
  1685.     return x, y, z;
  1686. }
  1687. tankRight(input, damp, decay){      // right late reflections
  1688. // input    signal to diffuse
  1689. // damp        typ. .5
  1690. // decay    typ. .7
  1691.     Delay d1(688, feedback=1),
  1692.     d2(4453,4, feedback=1),
  1693.     d3(1800,3, feedback=1),
  1694.     d4(3720,3, feedback=1);
  1695.     History z1;
  1696.     y = d1.read(672 + cycle(.10) *16);
  1697.     x = input * decay + y *.7;
  1698.     d1.write(x);
  1699.     x = y - x *.7;
  1700.      d2.write(x);            // diffuser 2
  1701.     x = d2.read(4453, 0);
  1702.     x = mix(x, z1, damp);    // damp
  1703.     z1 = x;
  1704.     y = d3.read(1800, 0);    // taps out
  1705.     x = x * decay - y *.5;
  1706.     d3.write(x);
  1707.     d4.write(y + x *.5);    // diffuser 3
  1708.     x = d4.read(3720, 0) * decay;
  1709.     y = d2.read(353,1) + d2.read(3627,2) + d4.read(2673,2)
  1710.          - d3.read(1228,2);
  1711.     z = d2.read(1990,3) + d3.read(187,1) + d4.read(1066,1);
  1712.     return x, y, z;
  1713. }
  1714. reverb(left, right, pre, cut, damp, decay, lvl){
  1715. // left, right        input signals
  1716. // pre                predelay, samples
  1717. // cut                input low-pass cut, midi pitch
  1718. // damp                late damping, typ. .5
  1719. // decay            reverb tail, typ. .7
  1720. // ilvl                output amplitude of input signal
  1721. // rlvl                output amplitude of reverb
  1722.     Delay d(19200,feedback=0); 
  1723.     History zy, zcut, za1, zb0, zb1;
  1724.     d.write((left + right) * .6);    // predelay
  1725.     if(lvl > 0){
  1726.         pre = smoother2(pre);
  1727.         y = d.read(pre);
  1728.         if (cut != zcut){                // static filter
  1729.             za1, zb0, zb1 = staticlo(mtof(cut), 12);
  1730.             zcut = cut;
  1731.         }
  1732.         y = static(y, za1, zb0, zb1);
  1733.         y = diffdelay(y, 142, .75);        // diffusions
  1734.         y = diffdelay(y, 107, .75);
  1735.         y = diffdelay(y, 379, .625);
  1736.         y = diffdelay(y, 277, .625);
  1737.         x,  o2, o3 = tankLeft (y + zy, damp, decay);
  1738.         zy, o1, o4 = tankRight(x + y,  damp, decay);
  1739.         u = smoother1(lvl);
  1740.         v = 1 - u; u *=2;
  1741.         x = left  * v + (o1 - o2) * u;
  1742.         y = right * v + (o3 - o4) * u;
  1743.         return x, y;
  1744.     } else {
  1745.         return left, right;
  1746.     }
  1747. }
  1748. limit(left, right, lvl, window, attlo, atthi, rello, relhi){
  1749.     History zl1(1), zr1(1), zl2(1), zr2(1), zl3(1), zr3(1), zl4(1), zr4(1);
  1750.     t = change(train(window));
  1751.     left  = dcblock(left);
  1752.     right = dcblock(right);
  1753.     if(change(t) !=0){
  1754.         zl3 = zl2;
  1755.         zr3 = zr2;
  1756.         zl2 = (zl1 > lvl)? lvl / zl1 : 1;
  1757.         zr2 = (zr1 > lvl)? lvl / zr1 : 1;
  1758.         zl1 = 1;
  1759.         zr1 = 1;
  1760.     } else {
  1761.         zl1 = max(abs (left ), zl1);
  1762.         zr1 = max(abs (right), zr1);
  1763.     }
  1764.     if (zl2 > zl3) zl4 = zl2 * attlo + zl4 * atthi;
  1765.     else zl4 = zl2 * rello + zl4 * relhi;
  1766.     left *=zl4;
  1767.     if (zr2 > zr3) zr4 = zr2 * attlo + zr4 * atthi;
  1768.     else zr4 = zr2 * rello + zr4 * relhi;
  1769.     right *= zr4;
  1770.     return left, right;
  1771. }
  1772. //*************************************************************************************
  1773. // Declarations
  1774. // ************************************************************************************
  1775. // sometimes compile errors are more detailed if the buffers used in funcionts
  1776. // are declared in main(). So you might wish to uncomment this.
  1777. //Buffer filterdraw(),     //the Max buffer name into which filterPlot2() draws biquads, 
  1778. //                                      sizeinsamps = 110 
  1779. //    svfgain(),    // the Max buffer from which the SVF gets gain-table data
  1780. //    eptr(),     // precalculated anti-aliasing data for pulse waves
  1781. //    wavesets(),    // the oscillator waveforms and morphs for the waveset oscillator
  1782. //    noisegain(),    // the buffer from which noisosc adjusts filtered noise levels
  1783. //    pow25(),    // precalculated values of pow(2.5) for envelope curve shaping
  1784. //    scales(),    // the scale values for tuned glissando 
  1785. //    patterns();    // the pattern values for pattern glissando. 
  1786. // ************************************************************************************
  1787. // Constants
  1788. rsrms  = 1000/samplerate;            // 1ms in samples
  1789. rsrx5  = 200/samplerate;             // 5ms in samples
  1790. srflt  = twopi/(samplerate * 3);      // SVF filter delay(x3 because oversampled)
  1791. srx3   = samplerate * 3;              // for anti-aliased saw oscillators
  1792. sr3d3  = pow(samplerate, 3) /3;
  1793. rsrxpi = pi/samplerate;                // for biquads
  1794. rsrxpi2= twopi/samplerate;            // for noise oscs
  1795. rsr96  = 1/samplerate/60/96*24;       // 96clk period in samples
  1796. rsr    = 1/samplerate;                // for all basic Hz->period calcs

Download

Download: Synthcore Library for Max 7.3.1
Title
Synthcore Library for Max 7.3.1 (Details)
File Type
zip
File Version
2.3c
File Size
6,352.48 Kb
Brief Description:
Yofile's synthcore library contains over a 100 audio functions for Cycling84 gen codebox, demos, and two complete synths based on it.