shithub: leaf

Download patch

ref: 7803edf0b50bd7e394b618d8eaa4fb97de600bd6
parent: 3b564d49db43601e7e6bbe0b013febbbd90217a4
author: Matthew Wang <Matthew@nat-oitwireless-inside-vapornet100-10-9-82-139.princeton.edu>
date: Fri Oct 25 08:17:42 EDT 2019

recategorization of objects, some objects renamed

binary files a/LEAF/Inc/.DS_Store b/LEAF/Inc/.DS_Store differ
--- a/LEAF/Inc/leaf-808.h
+++ /dev/null
@@ -1,184 +1,0 @@
-/*==============================================================================
-
-    leaf-808.h
-    Created: 30 Nov 2018 10:24:44am
-    Author:  airship
-
-==============================================================================*/
-
-#ifndef LEAF_808_H_INCLUDED
-#define LEAF_808_H_INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//==============================================================================
-    
-#include "leaf-math.h"
-#include "leaf-oscillator.h"
-#include "leaf-utilities.h"
-#include "leaf-filter.h"
-
-//==============================================================================
-    
-// 808 Cowbell
-typedef struct _t808Cowbell {
-    
-    tSquare p[2];
-    tNoise stick;
-    tSVF bandpassOsc;
-    tSVF bandpassStick;
-    tEnvelope envGain;
-    tEnvelope envStick;
-    tEnvelope envFilter;
-    tHighpass highpass;
-    float oscMix;
-    float filterCutoff;
-    oBool useStick;
-    
-} t808Cowbell;
-
-void    t808Cowbell_init             (t808Cowbell* const, int useStick);
-void    t808Cowbell_free             (t808Cowbell* const);
-float   t808Cowbell_tick             (t808Cowbell* const);
-void    t808Cowbell_on               (t808Cowbell* const, float vel);
-void    t808Cowbell_setDecay         (t808Cowbell* const, float decay);
-void    t808Cowbell_setHighpassFreq  (t808Cowbell* const, float freq);
-void    t808Cowbell_setBandpassFreq  (t808Cowbell* const, float freq);
-void    t808Cowbell_setFreq          (t808Cowbell* const, float freq);
-void    t808Cowbell_setOscMix        (t808Cowbell* const, float oscMix);
-void    t808Cowbell_setStick         (t808Cowbell* const, int useStick);
-
-//==============================================================================
-    
-// 808 Hihat
-typedef struct _t808Hihat {
-    
-    // 6 Square waves
-    tSquare p[6];
-    tNoise n;
-    tSVF bandpassOsc;
-    tSVF bandpassStick;
-    tEnvelope envGain;
-    tEnvelope envStick;
-    tEnvelope noiseFMGain;
-    tHighpass highpass;
-    tNoise stick;
-
-    float freq;
-    float stretch;
-    float FM_amount;
-    float oscNoiseMix;
-    
-} t808Hihat;
-
-void        t808Hihat_init               (t808Hihat* const);
-void        t808Hihat_free               (t808Hihat* const);
-
-float       t808Hihat_tick               (t808Hihat* const);
-void        t808Hihat_on                 (t808Hihat* const, float vel);
-void        t808Hihat_setOscNoiseMix     (t808Hihat* const, float oscNoiseMix);
-void        t808Hihat_setDecay           (t808Hihat* const, float decay);
-void        t808Hihat_setHighpassFreq    (t808Hihat* const, float freq);
-void        t808Hihat_setOscBandpassFreq  (t808Hihat* const, float freq);
-void 		t808Hihat_setOscBandpassQ		(t808Hihat* const hihat, float Q);
-void        t808Hihat_setStickBandPassFreq  (t808Hihat* const, float freq);
-void 		t808Hihat_setStickBandPassQ		(t808Hihat* const hihat, float Q);
-void        t808Hihat_setOscFreq         (t808Hihat* const, float freq);
-void 		t808Hihat_setStretch				(t808Hihat* const hihat, float stretch);
-void 		t808Hihat_setFM					(t808Hihat* const hihat, float FM_amount);
-
-//==============================================================================
-    
-// 808 Snare
-typedef struct _t808Snare {
-    
-    // Tone 1, Tone 2, Noise
-    tTriangle tone[2]; // Tri (not yet antialiased or wavetabled)
-    tNoise noiseOsc;
-    tSVF toneLowpass[2];
-    tSVF noiseLowpass; // Lowpass from SVF filter
-    tEnvelope toneEnvOsc[2];
-    tEnvelope toneEnvGain[2];
-    tEnvelope noiseEnvGain;
-    tEnvelope toneEnvFilter[2];
-    tEnvelope noiseEnvFilter;
-    
-    float toneGain[2];
-    float noiseGain;
-    
-    float toneNoiseMix;
-    
-    float tone1Freq, tone2Freq;
-    
-    float noiseFilterFreq;
-    
-    
-} t808Snare;
-
-void        t808Snare_init                  (t808Snare* const);
-void        t808Snare_free                  (t808Snare* const);
-
-float       t808Snare_tick                  (t808Snare* const);
-void        t808Snare_on                    (t808Snare* const, float vel);
-void        t808Snare_setTone1Freq          (t808Snare* const, float freq);
-void        t808Snare_setTone2Freq          (t808Snare* const, float freq);
-void        t808Snare_setTone1Decay         (t808Snare* const, float decay);
-void        t808Snare_setTone2Decay         (t808Snare* const, float decay);
-void        t808Snare_setNoiseDecay         (t808Snare* const, float decay);
-void        t808Snare_setToneNoiseMix       (t808Snare* const, float toneNoiseMix);
-void        t808Snare_setNoiseFilterFreq    (t808Snare* const, float noiseFilterFreq);
-void        t808Snare_setNoiseFilterQ       (t808Snare* const, float noiseFilterQ);
-
-//==============================================================================
-    
-// 808 Kick
-typedef struct _t808Kick {
-
-
-    tCycle tone; // Tri
-    tNoise noiseOsc;
-    tSVF toneLowpass;
-    tEnvelope toneEnvOscChirp;
-    tEnvelope toneEnvOscSigh;
-    tEnvelope toneEnvGain;
-    tEnvelope noiseEnvGain;
-    tEnvelope toneEnvFilter;
-
-    float toneGain;
-    float noiseGain;
-
-    float toneInitialFreq;
-    float sighAmountInHz;
-    float chirpRatioMinusOne;
-    float noiseFilterFreq;
-
-
-} t808Kick;
-
-void        t808Kick_init                  (t808Kick* const);
-void        t808Kick_free                  (t808Kick* const);
-
-float       t808Kick_tick                  (t808Kick* const);
-void        t808Kick_on                    (t808Kick* const, float vel);
-void        t808Kick_setToneFreq          (t808Kick* const, float freq);
-void        t808Kick_setToneDecay         (t808Kick* const, float decay);
-void        t808Kick_setNoiseDecay         (t808Kick* const, float decay);
-void        t808Kick_setSighAmount         (t808Kick* const, float sigh);
-void        t808Kick_setChirpAmount         (t808Kick* const, float chirp);
-void        t808Kick_setToneNoiseMix       (t808Kick* const, float toneNoiseMix);
-void        t808Kick_setNoiseFilterFreq    (t808Kick* const, float noiseFilterFreq);
-void        t808Kick_setNoiseFilterQ       (t808Kick* const, float noiseFilterQ);
-    
-//==============================================================================
-    
-#ifdef __cplusplus
-}
-#endif
-
-#endif // LEAF_808_H_INCLUDED
-
-//==============================================================================
-
-
--- a/LEAF/Inc/leaf-WDF.h
+++ /dev/null
@@ -1,89 +1,0 @@
-/*
- * leaf-WDF.h
- *
- *  Created on: Sep 25, 2019
- *      Author: jeffsnyder
- */
-
-#ifndef LEAF_INC_LEAF_WDF_H_
-#define LEAF_INC_LEAF_WDF_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//==============================================================================
-
-#include "leaf-global.h"
-#include "leaf-math.h"
-
-//==============================================================================
-
-typedef enum WDFComponentType
-{
-    SeriesAdaptor = 0,
-    ParallelAdaptor,
-    Resistor,
-    Capacitor,
-    Inductor,
-    Inverter,
-    ResistiveSource,
-    IdealSource,
-    Diode,
-    DiodePair,
-    RootNil,
-    WDFComponentNil
-} WDFComponentType;
-
-typedef struct _tWDF tWDF; // needed to allow tWDF pointers in struct
-struct _tWDF
-{
-    WDFComponentType type;
-    float port_resistance_up;
-    float port_resistance_left;
-    float port_resistance_right;
-    float port_conductance_up;
-    float port_conductance_left;
-    float port_conductance_right;
-    float incident_wave_up;
-    float incident_wave_left;
-    float incident_wave_right;
-    float reflected_wave_up;
-    float reflected_wave_left;
-    float reflected_wave_right;
-    float gamma_zero;
-    float sample_rate;
-    float value;
-    tWDF* child_left;
-    tWDF* child_right;
-    float (*get_port_resistance)(tWDF* const);
-    float (*get_reflected_wave_up)(tWDF* const, float);
-    float (*get_reflected_wave_down)(tWDF* const, float, float);
-    void (*set_incident_wave)(tWDF* const, float, float);
-};
-
-//WDF Linear Components
-void tWDF_init(tWDF* const r, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR);
-void tWDF_free(tWDF* const r);
-float tWDF_tick(tWDF* const r, float sample, tWDF* const outputPoint, uint8_t paramsChanged);
-
-void tWDF_setValue(tWDF* const r, float value);
-void tWDF_setSampleRate(tWDF* const r, float sample_rate);
-uint8_t tWDF_isLeaf(tWDF* const r);
-
-float tWDF_getPortResistance(tWDF* const r);
-float tWDF_getReflectedWaveUp(tWDF* const r, float input); //for tree, only uses input for resistive source
-float tWDF_getReflectedWaveDown(tWDF* const r, float input, float incident_wave); //for roots
-void tWDF_setIncidentWave(tWDF* const r, float incident_wave, float input);
-
-float tWDF_getVoltage(tWDF* const r);
-float tWDF_getCurrent(tWDF* const r);
-    
-
-//==============================================================================
-    
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* LEAF_INC_LEAF_WDF_H_ */
--- /dev/null
+++ b/LEAF/Inc/leaf-analysis.h
@@ -1,0 +1,226 @@
+/*==============================================================================
+ 
+ leaf-analysis.h
+ Created: 25 Oct 2019 10:30:52am
+ Author:  Matthew Wang
+ 
+ ==============================================================================*/
+
+#ifndef LEAF_ANALYSIS_H_INCLUDED
+#define LEAF_ANALYSIS_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+    
+//==============================================================================
+    
+#include "leaf-global.h"
+#include "leaf-mempool.h"
+#include "leaf-math.h"
+#include "leaf-filters.h"
+
+//==============================================================================
+
+/* Envelope Follower */
+typedef struct _tEnvelopeFollower
+{
+    float y;
+    float a_thresh;
+    float d_coeff;
+    
+} tEnvelopeFollower;
+
+void    tEnvelopeFollower_init           (tEnvelopeFollower*  const, float attackThreshold, float decayCoeff);
+void    tEnvelopeFollower_free           (tEnvelopeFollower*  const);
+
+float   tEnvelopeFollower_tick           (tEnvelopeFollower*  const, float x);
+int     tEnvelopeFollower_decayCoeff     (tEnvelopeFollower*  const, float decayCoeff);
+int     tEnvelopeFollower_attackThresh   (tEnvelopeFollower*  const, float attackThresh);
+    
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+/* PowerEnvelopeFollower */
+typedef struct _tPowerFollower {
+    float factor, oneminusfactor;
+    float curr;
+    
+} tPowerFollower;
+
+void    tPowerFollower_init      (tPowerFollower* const, float factor);
+void    tPowerFollower_free      (tPowerFollower* const);
+float   tPowerFollower_tick      (tPowerFollower* const, float input);
+float   tPowerFollower_sample    (tPowerFollower* const);
+int     tPowerFollower_setFactor   (tPowerFollower* const, float factor);
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+// ENV~ from PD, modified for LEAF
+#define MAXOVERLAP 32
+#define INITVSTAKEN 64
+#define ENV_WINDOW_SIZE 1024
+#define ENV_HOP_SIZE 256
+
+typedef struct _tEnvPD
+{
+    float buf[ENV_WINDOW_SIZE + INITVSTAKEN];
+    uint16_t x_phase;                    /* number of points since last output */
+    uint16_t x_period;                   /* requested period of output */
+    uint16_t x_realperiod;               /* period rounded up to vecsize multiple */
+    uint16_t x_npoints;                  /* analysis window size in samples */
+    float x_result;                 /* result to output */
+    float x_sumbuf[MAXOVERLAP];     /* summing buffer */
+    float x_f;
+    uint16_t windowSize, hopSize, blockSize;
+    uint16_t x_allocforvs;               /* extra buffer for DSP vector size */
+} tEnvPD;
+
+void    tEnvPD_init           (tEnvPD* const, int windowSize, int hopSize, int blockSize);
+void    tEnvPD_free           (tEnvPD* const);
+float   tEnvPD_tick           (tEnvPD* const);
+void    tEnvPD_processBlock   (tEnvPD* const, float* in);
+    
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+/* tAttackDetection */
+#define DEFBLOCKSIZE 1024
+#define DEFTHRESHOLD 6
+#define DEFATTACK    10
+#define DEFRELEASE    10
+
+typedef struct _tAttackDetection
+{
+    float env;
+    
+    //Attack & Release times in msec
+    int atk;
+    int rel;
+    
+    //Attack & Release coefficients based on times
+    float atk_coeff;
+    float rel_coeff;
+    
+    int blocksize;
+    int samplerate;
+    
+    //RMS amplitude of previous block - used to decide if attack is present
+    float prevAmp;
+    
+    float threshold;
+} tAttackDetection;
+
+void    tAttackDetection_init            (tAttackDetection* const, int blocksize);
+void    tAttackDetection_init_expanded   (tAttackDetection* const, int blocksize, int atk, int rel);
+void    tAttackDetection_free            (tAttackDetection* const);
+
+// set expected input blocksize
+void    tAttackDetection_setBlocksize    (tAttackDetection* const, int size);
+
+// change atkDetector sample rate
+void    tAttackDetection_setSamplerate   (tAttackDetection* const, int inRate);
+
+// set attack time and coeff
+void    tAttackDetection_setAtk          (tAttackDetection* const, int inAtk);
+
+// set release time and coeff
+void    tAttackDetection_setRel          (tAttackDetection* const, int inRel);
+
+// set level above which values are identified as attacks
+void    tAttackDetection_setThreshold    (tAttackDetection* const, float thres);
+
+// find largest transient in input block, return index of attack
+int     tAttackDetection_detect          (tAttackDetection* const, float *in);
+
+//==============================================================================
+
+// tSNAC: period detector
+#define SNAC_FRAME_SIZE 1024           // default analysis framesize // should be the same as (or smaller than?) PS_FRAME_SIZE
+#define DEFOVERLAP 1                // default overlap
+#define DEFBIAS 0.2f        // default bias
+#define DEFMINRMS 0.003f   // default minimum RMS
+#define SEEK 0.85f       // seek-length as ratio of framesize
+
+typedef struct _tSNAC
+{
+    float* inputbuf;
+    float* processbuf;
+    float* spectrumbuf;
+    float* biasbuf;
+    uint16_t timeindex;
+    uint16_t framesize;
+    uint16_t overlap;
+    uint16_t periodindex;
+    
+    float periodlength;
+    float fidelity;
+    float biasfactor;
+    float minrms;
+    
+} tSNAC;
+
+void    tSNAC_init          (tSNAC* const, int overlaparg);    // constructor
+void    tSNAC_free          (tSNAC* const);    // destructor
+
+void    tSNAC_ioSamples     (tSNAC *s, float *in, float *out, int size);
+void    tSNAC_setOverlap    (tSNAC *s, int lap);
+void    tSNAC_setBias       (tSNAC *s, float bias);
+void    tSNAC_setMinRMS     (tSNAC *s, float rms);
+
+/*To get freq, perform SAMPLE_RATE/snac_getperiod() */
+float   tSNAC_getPeriod     (tSNAC *s);
+float   tSNAC_getfidelity   (tSNAC *s);
+    
+#define DEFPITCHRATIO 2.0f
+#define DEFTIMECONSTANT 100.0f
+#define DEFHOPSIZE 64
+#define DEFWINDOWSIZE 64
+#define FBA 20
+#define HPFREQ 40.0f
+    
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+// Period detection
+typedef struct _tPeriodDetection
+{
+    tEnvPD env;
+    tSNAC snac;
+    float* inBuffer;
+    float* outBuffer;
+    int frameSize;
+    int bufSize;
+    int framesPerBuffer;
+    int curBlock;
+    int lastBlock;
+    int i;
+    int indexstore;
+    int iLast;
+    int index;
+    float period;
+    
+    uint16_t hopSize;
+    uint16_t windowSize;
+    uint8_t fba;
+    
+    float timeConstant;
+    float radius;
+    float max;
+    float lastmax;
+    float deltamax;
+    
+}tPeriodDetection;
+
+void       tPeriodDetection_init                    (tPeriodDetection* const, float* in, float* out, int bufSize, int frameSize);
+void       tPeriodDetection_free                    (tPeriodDetection* const);
+
+float      tPeriodDetection_findPeriod              (tPeriodDetection* const, float sample);
+void       tPeriodDetection_setHopSize              (tPeriodDetection* p, int hs);
+void       tPeriodDetection_setWindowSize           (tPeriodDetection* p, int ws);
+
+//==============================================================================
+    
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // LEAF_ANALYSIS_H_INCLUDED
+
+//==============================================================================
--- a/LEAF/Inc/leaf-crusher.h
+++ /dev/null
@@ -1,64 +1,0 @@
-/*
-  ==============================================================================
-
-    leaf-crusher.h
-    Created: 7 Feb 2019 10:58:22am
-    Author:  airship
-
-  ==============================================================================
-*/
-
-#ifndef LEAF_CRUSHER_H_INCLUDED
-#define LEAF_CRUSHER_H_INCLUDED
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//==============================================================================
-
-#include "leaf-global.h"
-#include "leaf-math.h"
-
-//==============================================================================
-    
-typedef struct _tCrusher
-{
-    float srr;
-    float mult, div;
-    float rnd;
-    
-    uint32_t  op; //which bitwise operation (0-7)
-    
-    float gain;
-    
-} tCrusher;
-    
-
-void    tCrusher_init    (tCrusher* const);
-void    tCrusher_free    (tCrusher* const);
-
-float   tCrusher_tick    (tCrusher* const, float input);
-    
-// 0.0 - 1.0
-void    tCrusher_setOperation (tCrusher* const, float op);
- 
-// 0.0 - 1.0
-void    tCrusher_setQuality (tCrusher* const, float val);
-    
-// what division to round to
-void    tCrusher_setRound (tCrusher* const, float rnd);
-    
-// sampling ratio
-void    tCrusher_setSamplingRatio (tCrusher* const, float ratio);
-    
-//==============================================================================
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // LEAF_WAVEFOLDER_H_INCLUDED
-
-//==============================================================================
--- a/LEAF/Inc/leaf-delay.h
+++ b/LEAF/Inc/leaf-delay.h
@@ -48,7 +48,7 @@
 //==============================================================================
     
 /* Linearly-interpolating delay, reimplemented from STK (Cook and Scavone). */
-typedef struct _tDelayL
+typedef struct _tLinearDelay
 {
     float gain;
     float* buff;
@@ -63,26 +63,26 @@
     
     float alpha, omAlpha;
     
-} tDelayL;
+} tLinearDelay;
 
-void        tDelayL_init        (tDelayL*  const, float delay, uint32_t maxDelay);
-void        tDelayL_free        (tDelayL* const);
+void        tLinearDelay_init        (tLinearDelay*  const, float delay, uint32_t maxDelay);
+void        tLinearDelay_free        (tLinearDelay* const);
 
-int         tDelayL_setDelay    (tDelayL*  const, float delay);
-float       tDelayL_getDelay    (tDelayL*  const);
-void        tDelayL_tapIn       (tDelayL*  const, float in, uint32_t tapDelay);
-float       tDelayL_tapOut      (tDelayL*  const, float tapDelay);
-float       tDelayL_addTo       (tDelayL*  const, float value, uint32_t tapDelay);
-float       tDelayL_tick        (tDelayL*  const, float sample);
-void   		tDelayL_tickIn 		(tDelayL* const d, float input);
-float   	tDelayL_tickOut 	(tDelayL* const d);
-float       tDelayL_getLastOut  (tDelayL*  const);
-float       tDelayL_getLastIn   (tDelayL*  const);
+int         tLinearDelay_setDelay    (tLinearDelay*  const, float delay);
+float       tLinearDelay_getDelay    (tLinearDelay*  const);
+void        tLinearDelay_tapIn       (tLinearDelay*  const, float in, uint32_t tapDelay);
+float       tLinearDelay_tapOut      (tLinearDelay*  const, float tapDelay);
+float       tLinearDelay_addTo       (tLinearDelay*  const, float value, uint32_t tapDelay);
+float       tLinearDelay_tick        (tLinearDelay*  const, float sample);
+void   		tLinearDelay_tickIn 		(tLinearDelay* const d, float input);
+float   	tLinearDelay_tickOut 	(tLinearDelay* const d);
+float       tLinearDelay_getLastOut  (tLinearDelay*  const);
+float       tLinearDelay_getLastIn   (tLinearDelay*  const);
 
 //==============================================================================
     
 /* Allpass-interpolating delay, reimplemented from STK (Cook and Scavone). */
-typedef struct _tDelayA
+typedef struct _tAllpassDelay
 {
     float gain;
     float* buff;
@@ -99,19 +99,19 @@
     
     float apInput;
     
-} tDelayA;
+} tAllpassDelay;
 
-void        tDelayA_init        (tDelayA*  const, float delay, uint32_t maxDelay);
-void        tDelayA_free        (tDelayA* const);
+void        tAllpassDelay_init        (tAllpassDelay*  const, float delay, uint32_t maxDelay);
+void        tAllpassDelay_free        (tAllpassDelay* const);
 
-int         tDelayA_setDelay    (tDelayA*  const, float delay);
-float       tDelayA_getDelay    (tDelayA*  const);
-void        tDelayA_tapIn       (tDelayA*  const, float in, uint32_t tapDelay);
-float       tDelayA_tapOut      (tDelayA*  const, uint32_t tapDelay);
-float       tDelayA_addTo       (tDelayA*  const, float value, uint32_t tapDelay);
-float       tDelayA_tick        (tDelayA*  const, float sample);
-float       tDelayA_getLastOut  (tDelayA*  const);
-float       tDelayA_getLastIn   (tDelayA*  const);
+int         tAllpassDelay_setDelay    (tAllpassDelay*  const, float delay);
+float       tAllpassDelay_getDelay    (tAllpassDelay*  const);
+void        tAllpassDelay_tapIn       (tAllpassDelay*  const, float in, uint32_t tapDelay);
+float       tAllpassDelay_tapOut      (tAllpassDelay*  const, uint32_t tapDelay);
+float       tAllpassDelay_addTo       (tAllpassDelay*  const, float value, uint32_t tapDelay);
+float       tAllpassDelay_tick        (tAllpassDelay*  const, float sample);
+float       tAllpassDelay_getLastOut  (tAllpassDelay*  const);
+float       tAllpassDelay_getLastIn   (tAllpassDelay*  const);
 
 //==============================================================================
     
--- /dev/null
+++ b/LEAF/Inc/leaf-distortion.h
@@ -1,0 +1,99 @@
+/*==============================================================================
+
+    leaf-distortion.h
+    Created: 25 Oct 2019 10:23:28am
+    Author:  Matthew Wang
+
+==============================================================================*/
+
+#ifndef LEAF_DISTORTION_H_INCLUDED
+#define LEAF_DISTORTION_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//==============================================================================
+    
+#include "leaf-global.h"
+#include "leaf-mempool.h"
+#include "leaf-math.h"
+
+//==============================================================================
+    
+/* tLockhartWavefolder */
+
+typedef struct _tLockhartWavefolder
+{
+    double Ln1;
+    double Fn1;
+    float xn1;
+    
+} tLockhartWavefolder;
+
+void    tLockhartWavefolder_init    (tLockhartWavefolder* const);
+void    tLockhartWavefolder_free    (tLockhartWavefolder* const);
+
+float   tLockhartWavefolder_tick    (tLockhartWavefolder* const, float samp);
+
+//==============================================================================
+    
+typedef struct _tCrusher
+{
+    float srr;
+    float mult, div;
+    float rnd;
+    
+    uint32_t  op; //which bitwise operation (0-7)
+    
+    float gain;
+    
+} tCrusher;
+
+
+void    tCrusher_init    (tCrusher* const);
+void    tCrusher_free    (tCrusher* const);
+
+float   tCrusher_tick    (tCrusher* const, float input);
+
+// 0.0 - 1.0
+void    tCrusher_setOperation (tCrusher* const, float op);
+
+// 0.0 - 1.0
+void    tCrusher_setQuality (tCrusher* const, float val);
+
+// what division to round to
+void    tCrusher_setRound (tCrusher* const, float rnd);
+
+// sampling ratio
+void    tCrusher_setSamplingRatio (tCrusher* const, float ratio);
+    
+//==============================================================================
+    
+typedef struct _tOversampler
+{
+    int ratio;
+    float* pCoeffs;
+    float* upState;
+    float* downState;
+    int numTaps;
+    int phaseLength;
+} tOversampler;
+
+void        tOversampler_init(tOversampler* const, int order, oBool extraQuality);
+void        tOversampler_free(tOversampler* const);
+void        tOversampler_upsample(tOversampler* const, float input, float* output);
+float       tOversampler_downsample(tOversampler *const os, float* input);
+float       tOversampler_tick(tOversampler* const, float input, float (*effectTick)(float));
+int         tOversampler_getLatency(tOversampler* const os);
+
+//==============================================================================
+    
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LEAF_DISTORTION_H_INCLUDED
+
+//==============================================================================
+
--- /dev/null
+++ b/LEAF/Inc/leaf-dynamics.h
@@ -1,0 +1,79 @@
+/*==============================================================================
+
+    leaf-dynamics.h
+    Created: 30 Nov 2018 11:57:05am
+    Author:  airship
+
+==============================================================================*/
+
+#ifndef LEAF_DYNAMICS_H_INCLUDED
+#define LEAF_DYNAMICS_H_INCLUDED
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//==============================================================================
+
+#include "leaf-global.h"
+#include "leaf-math.h"
+#include "leaf-analysis.h"
+
+//==============================================================================
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+/* Compressor */
+typedef struct _tCompressor
+{
+    float tauAttack, tauRelease;
+    float T, R, W, M; // Threshold, compression Ratio, decibel Width of knee transition, decibel Make-up gain
+    
+    float x_G[2], y_G[2], x_T[2], y_T[2];
+    
+    oBool isActive;
+    
+}tCompressor;
+
+void    tCompressor_init    (tCompressor* const);
+void    tCompressor_free    (tCompressor* const);
+float   tCompressor_tick    (tCompressor* const, float input);
+    
+///
+/* Feedback leveller */
+// An auto VCA that you put into a feedback circuit to make it stay at the same level.
+// It can enforce level bidirectionally (amplifying and attenuating as needed) or
+// just attenutating. The former option allows for infinite sustain strings, for example, while
+// The latter option allows for decaying strings, which can never exceed
+// a specific level.
+
+typedef struct _tFeedbackLeveler {
+    float targetLevel;    // target power level
+    float strength;        // how strongly level difference affects the VCA
+    int      mode;            // 0 for upwards limiting only, 1 for biderctional limiting
+    float curr;
+    tPowerFollower pwrFlw;    // internal power follower needed for level tracking
+    
+} tFeedbackLeveler;
+
+void    tFeedbackLeveler_init      (tFeedbackLeveler* const, float targetLevel, float factor, float strength, int mode);
+void    tFeedbackLeveler_free      (tFeedbackLeveler* const);
+
+float   tFeedbackLeveler_tick      (tFeedbackLeveler* const, float input);
+float   tFeedbackLeveler_sample    (tFeedbackLeveler* const);
+void     tFeedbackLeveler_setTargetLevel   (tFeedbackLeveler* const, float TargetLevel);
+void     tFeedbackLeveler_setFactor   (tFeedbackLeveler* const, float factor);
+void     tFeedbackLeveler_setMode   (tFeedbackLeveler* const, int mode); // 0 for upwards limiting only, 1 for biderctional limiting
+void     tFeedbackLeveler_setStrength   (tFeedbackLeveler* const, float strength);
+
+    
+//==============================================================================
+    
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LEAF_DYNAMICS_H_INCLUDED
+
+//==============================================================================
--- /dev/null
+++ b/LEAF/Inc/leaf-effects.h
@@ -1,0 +1,251 @@
+/*==============================================================================
+
+    leaf-effects.h
+    Created: 20 Jan 2017 12:01:54pm
+    Author:  Michael R Mulshine
+
+==============================================================================*/
+
+#ifndef LEAF_EFFECTS_H_INCLUDED
+#define LEAF_EFFECTS_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//==============================================================================
+
+#include "leaf-global.h"
+#include "leaf-math.h"
+#include "leaf-analysis.h"
+
+//==============================================================================
+
+/* tTalkbox */
+#define NUM_TALKBOX_PARAM 4
+
+typedef struct _tTalkbox
+{
+    float param[NUM_TALKBOX_PARAM];
+    
+    int bufsize;
+    float* car0;
+    float* car1;
+    float* window;
+    float* buf0;
+    float* buf1;
+    
+    float emphasis;
+    int32_t K, N, O, pos;
+    float wet, dry, FX;
+    float d0, d1, d2, d3, d4;
+    float u0, u1, u2, u3, u4;
+    
+} tTalkbox;
+
+void        tTalkbox_init        (tTalkbox* const, int bufsize);
+void        tTalkbox_free        (tTalkbox* const);
+float       tTalkbox_tick        (tTalkbox* const, float synth, float voice);
+void        tTalkbox_update      (tTalkbox* const);
+void        tTalkbox_suspend     (tTalkbox* const);
+void        tTalkbox_lpcDurbin   (float *r, int p, float *k, float *g);
+void        tTalkbox_lpc         (float *buf, float *car, int32_t n, int32_t o);
+void		tTalkbox_setQuality  (tTalkbox* const, float quality);
+
+//==============================================================================
+
+/* tVocoder */
+#define NUM_VOCODER_PARAM 8
+#define NBANDS 16
+
+typedef struct _tVocoder
+{
+    float param[NUM_VOCODER_PARAM];
+    
+    float gain;         //output level
+    float thru, high;   //hf thru
+    float kout;         //downsampled output
+    int32_t  kval;      //downsample counter
+    int32_t  nbnd;      //number of bands
+    
+    //filter coeffs and buffers - seems it's faster to leave this global than make local copy
+    float f[NBANDS][13]; //[0-8][0 1 2 | 0 1 2 3 | 0 1 2 3 | val rate]
+    
+} tVocoder;
+
+void        tVocoder_init        (tVocoder* const);
+void        tVocoder_free        (tVocoder* const);
+float       tVocoder_tick        (tVocoder* const, float synth, float voice);
+void        tVocoder_update      (tVocoder* const);
+void        tVocoder_suspend     (tVocoder* const);
+    
+//==============================================================================
+
+
+//==============================================================================
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+/* tSOLAD : pitch shifting algorithm that underlies tPitchShifter etc */
+#define LOOPSIZE (2048*2)      // (4096*2) // loop size must be power of two
+#define LOOPMASK (LOOPSIZE - 1)
+#define PITCHFACTORDEFAULT 1.0f
+#define INITPERIOD 64.0f
+#define MAXPERIOD (float)((LOOPSIZE - w->blocksize) * 0.8f)
+#define MINPERIOD 8.0f
+
+typedef struct _tSOLAD
+{
+    uint16_t timeindex;              // current reference time, write index
+    uint16_t blocksize;              // signal input / output block size
+    float pitchfactor;        // pitch factor between 0.25 and 4
+    float readlag;            // read pointer's lag behind write pointer
+    float period;             // period length in input signal
+    float jump;               // read pointer jump length and direction
+    float xfadelength;        // crossfade length expressed at input sample rate
+    float xfadevalue;         // crossfade phase and value
+    
+    float* delaybuf;
+    
+} tSOLAD;
+
+void    tSOLAD_init             (tSOLAD* const);
+void    tSOLAD_free             (tSOLAD* const);
+
+// send one block of input samples, receive one block of output samples
+void    tSOLAD_ioSamples        (tSOLAD *w, float* in, float* out, int blocksize);
+
+// set periodicity analysis data
+void    tSOLAD_setPeriod        (tSOLAD *w, float period);
+
+// set pitch factor between 0.25 and 4
+void    tSOLAD_setPitchFactor   (tSOLAD *w, float pitchfactor);
+
+// force readpointer lag
+void    tSOLAD_setReadLag       (tSOLAD *w, float readlag);
+
+// reset state variables
+void    tSOLAD_resetState       (tSOLAD *w);
+    
+// Pitch shifter
+typedef struct _tPitchShifter
+{
+    tEnvPD env;
+    tSNAC snac;
+    tSOLAD sola;
+    tHighpass hp;
+    
+    float* inBuffer;
+    float* outBuffer;
+    int frameSize;
+    int bufSize;
+    int framesPerBuffer;
+    int curBlock;
+    int lastBlock;
+    int index;
+    
+    uint16_t hopSize;
+    uint16_t windowSize;
+    uint8_t fba;
+    
+    float pitchFactor;
+    float timeConstant;
+    float radius;
+    float max;
+    float lastmax;
+    float deltamax;
+    
+} tPitchShifter;
+
+void        tPitchShifter_init              (tPitchShifter* const, float* in, float* out, int bufSize, int frameSize);
+void        tPitchShifter_free              (tPitchShifter* const);
+
+float       tPitchShifter_tick              (tPitchShifter* const, float sample);
+float       tPitchShifterToFreq_tick        (tPitchShifter* const, float sample, float freq);
+float       tPitchShifterToFunc_tick        (tPitchShifter* const, float sample, float (*fun)(float));
+void        tPitchShifter_ioSamples_toFreq  (tPitchShifter* const, float* in, float* out, int size, float toFreq);
+void        tPitchShifter_ioSamples_toPeriod(tPitchShifter* const, float* in, float* out, int size, float toPeriod);
+void        tPitchShifter_ioSamples_toFunc  (tPitchShifter* const, float* in, float* out, int size, float (*fun)(float));
+void        tPitchShifter_setPitchFactor    (tPitchShifter* const, float pf);
+void        tPitchShifter_setTimeConstant   (tPitchShifter* const, float tc);
+void        tPitchShifter_setHopSize        (tPitchShifter* const, int hs);
+void        tPitchShifter_setWindowSize     (tPitchShifter* const, int ws);
+float       tPitchShifter_getPeriod         (tPitchShifter* const);
+
+//==============================================================================
+
+// Pitch shift
+typedef struct _tPitchShift
+{
+    tSOLAD sola;
+    tHighpass hp;
+   tPeriodDetection* p;
+    
+    float* outBuffer;
+    int frameSize;
+    int bufSize;
+    
+    int framesPerBuffer;
+    int curBlock;
+    int lastBlock;
+    int index;
+    
+    float pitchFactor;
+    float timeConstant;
+    float radius;
+} tPitchShift;
+
+void        tPitchShift_init                (tPitchShift* const,tPeriodDetection* const, float* out, int bufSize);
+void        tPitchShift_free                (tPitchShift* const);
+
+float       tPitchShift_shift               (tPitchShift* const);
+float       tPitchShift_shiftToFunc         (tPitchShift* const, float (*fun)(float));
+float       tPitchShift_shiftToFreq         (tPitchShift* const, float freq);
+void        tPitchShift_setPitchFactor      (tPitchShift* const, float pf);
+
+//==============================================================================
+
+#define FORD 7
+#define FORMANT_BUFFER_SIZE 2048
+
+typedef struct _tFormantShifter
+{
+    int ford;
+    int bufsize;
+    float falph;
+    float flamb;
+    float* fk;
+    float* fb;
+    float* fc;
+    float* frb;
+    float* frc;
+    float* fsig;
+    float* fsmooth;
+    float fhp;
+    float flp;
+    float flpa;
+    float** fbuff;
+    float* ftvec;
+    float fmute;
+    float fmutealph;
+    unsigned int cbi;
+    
+} tFormantShifter;
+
+void        tFormantShifter_init            (tFormantShifter* const, int bufsize, int order);
+void        tFormantShifter_free            (tFormantShifter* const);
+
+float       tFormantShifter_tick            (tFormantShifter* const, float input, float fwarp);
+float       tFormantShifter_remove          (tFormantShifter* const, float input);
+float       tFormantShifter_add             (tFormantShifter* const, float input, float fwarp);
+void        tFormantShifter_ioSamples       (tFormantShifter* const, float* in, float* out, int size, float fwarp);
+
+//==============================================================================
+    
+#ifdef __cplusplus
+}
+#endif
+        
+#endif  // LEAF_EFFECTS_H_INCLUDED
+
+//==============================================================================
--- /dev/null
+++ b/LEAF/Inc/leaf-electrical.h
@@ -1,0 +1,89 @@
+/*
+ * leaf-electrical.h
+ *
+ *  Created on: Sep 25, 2019
+ *      Author: jeffsnyder
+ */
+
+#ifndef LEAF_INC_LEAF_ELECTRICAL_H_
+#define LEAF_INC_LEAF_ELECTRICAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//==============================================================================
+
+#include "leaf-global.h"
+#include "leaf-math.h"
+
+//==============================================================================
+
+typedef enum WDFComponentType
+{
+    SeriesAdaptor = 0,
+    ParallelAdaptor,
+    Resistor,
+    Capacitor,
+    Inductor,
+    Inverter,
+    ResistiveSource,
+    IdealSource,
+    Diode,
+    DiodePair,
+    RootNil,
+    WDFComponentNil
+} WDFComponentType;
+
+typedef struct _tWDF tWDF; // needed to allow tWDF pointers in struct
+struct _tWDF
+{
+    WDFComponentType type;
+    float port_resistance_up;
+    float port_resistance_left;
+    float port_resistance_right;
+    float port_conductance_up;
+    float port_conductance_left;
+    float port_conductance_right;
+    float incident_wave_up;
+    float incident_wave_left;
+    float incident_wave_right;
+    float reflected_wave_up;
+    float reflected_wave_left;
+    float reflected_wave_right;
+    float gamma_zero;
+    float sample_rate;
+    float value;
+    tWDF* child_left;
+    tWDF* child_right;
+    float (*get_port_resistance)(tWDF* const);
+    float (*get_reflected_wave_up)(tWDF* const, float);
+    float (*get_reflected_wave_down)(tWDF* const, float, float);
+    void (*set_incident_wave)(tWDF* const, float, float);
+};
+
+//WDF Linear Components
+void tWDF_init(tWDF* const r, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR);
+void tWDF_free(tWDF* const r);
+float tWDF_tick(tWDF* const r, float sample, tWDF* const outputPoint, uint8_t paramsChanged);
+
+void tWDF_setValue(tWDF* const r, float value);
+void tWDF_setSampleRate(tWDF* const r, float sample_rate);
+uint8_t tWDF_isLeaf(tWDF* const r);
+
+float tWDF_getPortResistance(tWDF* const r);
+float tWDF_getReflectedWaveUp(tWDF* const r, float input); //for tree, only uses input for resistive source
+float tWDF_getReflectedWaveDown(tWDF* const r, float input, float incident_wave); //for roots
+void tWDF_setIncidentWave(tWDF* const r, float incident_wave, float input);
+
+float tWDF_getVoltage(tWDF* const r);
+float tWDF_getCurrent(tWDF* const r);
+    
+
+//==============================================================================
+    
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LEAF_INC_LEAF_ELECTRICAL_H_ */
--- /dev/null
+++ b/LEAF/Inc/leaf-envelopes.h
@@ -1,0 +1,136 @@
+/*
+  ==============================================================================
+
+    leaf-envelopes.h
+    Created: 20 Jan 2017 12:02:17pm
+    Author:  Michael R Mulshine
+
+  ==============================================================================
+*/
+
+#ifndef LEAF_ENVELOPES_H_INCLUDED
+#define LEAF_ENVELOPES_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+#include "leaf-math.h"
+#include "leaf-filters.h"
+#include "leaf-delay.h"
+    
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+/* Attack-Decay envelope */
+typedef struct _tEnvelope {
+    
+    const float *exp_buff;
+    const float *inc_buff;
+    uint32_t buff_size;
+    
+    float next;
+    
+    float attackInc, decayInc, rampInc;
+    
+    oBool inAttack, inDecay, inRamp;
+    
+    oBool loop;
+    
+    float gain, rampPeak;
+    
+    float attackPhase, decayPhase, rampPhase;
+    
+} tEnvelope;
+
+void    tEnvelope_init      (tEnvelope* const, float attack, float decay, oBool loop);
+void    tEnvelope_free      (tEnvelope* const);
+
+float   tEnvelope_tick      (tEnvelope* const);
+int     tEnvelope_setAttack (tEnvelope*  const, float attack);
+int     tEnvelope_setDecay  (tEnvelope*  const, float decay);
+int     tEnvelope_loop      (tEnvelope*  const, oBool loop);
+int     tEnvelope_on        (tEnvelope*  const, float velocity);
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+/* ADSR */
+typedef struct _tADSR
+{
+    const float *exp_buff;
+    const float *inc_buff;
+    uint32_t buff_size;
+    
+    float next;
+    
+    float attackInc, decayInc, releaseInc, rampInc;
+    
+    oBool inAttack, inDecay, inSustain, inRelease, inRamp;
+    
+    float sustain, gain, rampPeak, releasePeak;
+    
+    float attackPhase, decayPhase, releasePhase, rampPhase;
+    
+} tADSR;
+
+void    tADSR_init      (tADSR*  const, float attack, float decay, float sustain, float release);
+void    tADSR_free      (tADSR*  const);
+
+float   tADSR_tick      (tADSR*  const);
+int     tADSR_setAttack (tADSR*  const, float attack);
+int     tADSR_setDecay  (tADSR*  const, float decay);
+int     tADSR_setSustain(tADSR*  const, float sustain);
+int     tADSR_setRelease(tADSR*  const, float release);
+int     tADSR_on        (tADSR*  const, float velocity);
+int     tADSR_off       (tADSR*  const);
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+/* Ramp */
+typedef struct _tRamp {
+    float inc;
+    float inv_sr_ms;
+    float minimum_time;
+    float curr,dest;
+    float time;
+    int samples_per_tick;
+    
+} tRamp;
+
+void    tRamp_init      (tRamp* const, float time, int samplesPerTick);
+void    tRamp_free      (tRamp* const);
+
+float   tRamp_tick      (tRamp* const);
+float   tRamp_sample    (tRamp* const);
+int     tRamp_setTime   (tRamp* const, float time);
+int     tRamp_setDest   (tRamp* const, float dest);
+int     tRamp_setVal    (tRamp* const, float val);
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+/* Exponential Smoother */
+typedef struct _tExpSmooth {
+    float factor, oneminusfactor;
+    float curr,dest;
+
+} tExpSmooth;
+
+void    tExpSmooth_init      (tExpSmooth* const, float val, float factor);
+void    tExpSmooth_free      (tExpSmooth* const);
+
+float   tExpSmooth_tick      (tExpSmooth* const);
+float   tExpSmooth_sample    (tExpSmooth* const);
+int     tExpSmooth_setFactor   (tExpSmooth* const, float factor);
+int     tExpSmooth_setDest   (tExpSmooth* const, float dest);
+int     tExpSmooth_setVal    (tExpSmooth* const, float val);
+    
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // LEAF_ENVELOPES_H_INCLUDED
+
+
--- a/LEAF/Inc/leaf-filter.h
+++ /dev/null
@@ -1,312 +1,0 @@
-/*==============================================================================
-
-    leaf-filter.h
-    Created: 20 Jan 2017 12:01:10pm
-    Author:  Michael R Mulshine
-
-==============================================================================*/
-
-#ifndef LEAF_FILTER_H_INCLUDED
-#define LEAF_FILTER_H_INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//==============================================================================
-    
-#include "leaf-math.h"
-#include "leaf-delay.h"
-#include "leaf-tables.h"
-
-//==============================================================================
-    
-/* tAllpass: Schroeder allpass. Comb-filter with feedforward and feedback. */
-typedef struct _tAllpass
-{
-    float gain;
-    
-    tDelayL delay;
-    
-    float lastOut;
-    
-} tAllpass;
-
-void        tAllpass_init           (tAllpass* const, float initDelay, uint32_t maxDelay);
-void        tAllpass_free           (tAllpass* const);
-
-float       tAllpass_tick           (tAllpass* const, float input);
-void        tAllpass_setGain        (tAllpass* const, float gain);
-void        tAllpass_setDelay       (tAllpass* const f, float delay);
-
-
-//==============================================================================
-    
-/* tOnePole: OnePole filter, reimplemented from STK (Cook and Scavone). */
-typedef struct _tOnePole
-{
-    float gain;
-    float a0,a1;
-    float b0,b1;
-    
-    float coef;
-    
-    float freq;
-    
-    float lastIn, lastOut;
-    
-} tOnePole;
-
-void        tOnePole_init           (tOnePole* const, float thePole);
-void        tOnePole_free           (tOnePole* const);
-
-float       tOnePole_tick           (tOnePole* const, float input);
-void        tOnePole_setB0          (tOnePole* const, float b0);
-void        tOnePole_setA1          (tOnePole* const, float a1);
-void        tOnePole_setPole        (tOnePole* const, float thePole);
-void        tOnePole_setFreq        (tOnePole* const, float freq);
-void        tOnePole_setCoefficients(tOnePole* const, float b0, float a1);
-void        tOnePole_setGain        (tOnePole* const, float gain);
-
-//==============================================================================
-    
-/* TwoPole filter, reimplemented from STK (Cook and Scavone). */
-typedef struct _tTwoPole
-{
-    float gain;
-    float a0, a1, a2;
-    float b0;
-    
-    float radius, frequency;
-    oBool normalize;
-    
-    float lastOut[2];
-    
-} tTwoPole;
-
-void        tTwoPole_init           (tTwoPole*  const);
-void        tTwoPole_free           (tTwoPole*  const);
-
-float       tTwoPole_tick           (tTwoPole*  const, float input);
-void        tTwoPole_setB0          (tTwoPole*  const, float b0);
-void        tTwoPole_setA1          (tTwoPole*  const, float a1);
-void        tTwoPole_setA2          (tTwoPole*  const, float a2);
-void        tTwoPole_setResonance   (tTwoPole*  const, float freq, float radius, oBool normalize);
-void        tTwoPole_setCoefficients(tTwoPole*  const, float b0, float a1, float a2);
-void        tTwoPole_setGain        (tTwoPole*  const, float gain);
-
-//==============================================================================
-    
-/* OneZero filter, reimplemented from STK (Cook and Scavone). */
-typedef struct _tOneZero
-{
-    float gain;
-    float b0,b1;
-    float lastIn, lastOut, frequency;
-    
-} tOneZero;
-
-void        tOneZero_init           (tOneZero*  const, float theZero);
-void        tOneZero_free           (tOneZero*  const);
-float       tOneZero_tick           (tOneZero*  const, float input);
-void        tOneZero_setB0          (tOneZero*  const, float b0);
-void        tOneZero_setB1          (tOneZero*  const, float b1);
-void        tOneZero_setZero        (tOneZero*  const, float theZero);
-void        tOneZero_setCoefficients(tOneZero*  const, float b0, float b1);
-void        tOneZero_setGain        (tOneZero*  const, float gain);
-float       tOneZero_getPhaseDelay(tOneZero *f, float frequency );
-
-//==============================================================================
-    
-/* TwoZero filter, reimplemented from STK (Cook and Scavone). */
-typedef struct _tTwoZero
-{
-    float gain;
-    float b0, b1, b2;
-    
-    float frequency, radius;
-    
-    float lastIn[2];
-    
-} tTwoZero;
-
-void        tTwoZero_init           (tTwoZero*  const);
-void        tTwoZero_free           (tTwoZero*  const);
-
-float       tTwoZero_tick           (tTwoZero*  const, float input);
-void        tTwoZero_setB0          (tTwoZero*  const, float b0);
-void        tTwoZero_setB1          (tTwoZero*  const, float b1);
-void        tTwoZero_setB2          (tTwoZero*  const, float b2);
-void        tTwoZero_setNotch       (tTwoZero*  const, float frequency, float radius);
-void        tTwoZero_setCoefficients(tTwoZero*  const, float b0, float b1, float b2);
-void        tTwoZero_setGain        (tTwoZero*  const, float gain);
-
-//==============================================================================
-    
-/* PoleZero filter, reimplemented from STK (Cook and Scavone). */
-typedef struct _tPoleZero
-{
-    float gain;
-    float a0,a1;
-    float b0,b1;
-    
-    float lastIn, lastOut;
-    
-} tPoleZero;
-
-void        tPoleZero_init              (tPoleZero*  const);
-void        tPoleZero_free              (tPoleZero*  const);
-
-float       tPoleZero_tick              (tPoleZero*  const, float input);
-void        tPoleZero_setB0             (tPoleZero*  const, float b0);
-void        tPoleZero_setB1             (tPoleZero*  const, float b1);
-void        tPoleZero_setA1             (tPoleZero*  const, float a1);
-void        tPoleZero_setCoefficients   (tPoleZero*  const, float b0, float b1, float a1);
-void        tPoleZero_setAllpass        (tPoleZero*  const, float coeff);
-void        tPoleZero_setBlockZero      (tPoleZero*  const, float thePole);
-void        tPoleZero_setGain           (tPoleZero*  const, float gain);
-
-//==============================================================================
-    
-/* BiQuad filter, reimplemented from STK (Cook and Scavone). */
-typedef struct _tBiQuad
-{
-    float gain;
-    float a0, a1, a2;
-    float b0, b1, b2;
-    
-    float lastIn[2];
-    float lastOut[2];
-    
-    float frequency, radius;
-    oBool normalize;
-} tBiQuad;
-
-void        tBiQuad_init           (tBiQuad*  const);
-void        tBiQuad_free           (tBiQuad*  const);
-
-float       tBiQuad_tick           (tBiQuad*  const, float input);
-void        tBiQuad_setB0          (tBiQuad*  const, float b0);
-void        tBiQuad_setB1          (tBiQuad*  const, float b1);
-void        tBiQuad_setB2          (tBiQuad*  const, float b2);
-void        tBiQuad_setA1          (tBiQuad*  const, float a1);
-void        tBiQuad_setA2          (tBiQuad*  const, float a2);
-void        tBiQuad_setNotch       (tBiQuad*  const, float freq, float radius);
-void        tBiQuad_setResonance   (tBiQuad*  const, float freq, float radius, oBool normalize);
-void        tBiQuad_setCoefficients(tBiQuad*  const, float b0, float b1, float b2, float a1, float a2);
-void        tBiQuad_setGain        (tBiQuad*  const, float gain);
-
-//==============================================================================
-    
-/* State Variable Filter, algorithm from Andy Simper. */
-typedef enum SVFType
-{
-    SVFTypeHighpass = 0,
-    SVFTypeLowpass,
-    SVFTypeBandpass,
-    SVFTypeNotch,
-    SVFTypePeak,
-} SVFType;
-
-typedef struct _tSVF
-{
-    SVFType type;
-    float cutoff, Q;
-    float ic1eq,ic2eq;
-    float g,k,a1,a2,a3;
-    
-} tSVF;
-
-void        tSVF_init       (tSVF*  const, SVFType type, float freq, float Q);
-void        tSVF_free       (tSVF*  const);
-
-float       tSVF_tick       (tSVF*  const, float v0);
-int         tSVF_setFreq    (tSVF*  const, float freq);
-int         tSVF_setQ       (tSVF*  const, float Q);
-
-//==============================================================================
-    
-/* Efficient State Variable Filter for 14-bit control input, [0, 4096). */
-typedef struct _tSVFE
-{
-    SVFType type;
-    float cutoff, Q;
-    float ic1eq,ic2eq;
-    float g,k,a1,a2,a3;
-    
-} tSVFE;
-
-void        tSVFE_init      (tSVFE*  const, SVFType type, uint16_t controlFreq, float Q);
-void        tSVFE_free      (tSVFE*  const);
-
-float       tSVFE_tick      (tSVFE*  const, float v0);
-int         tSVFE_setFreq   (tSVFE*  const, uint16_t controlFreq);
-int         tSVFE_setQ      (tSVFE*  const, float Q);
-
-//==============================================================================
-    
-/* Simple Highpass filter. */
-typedef struct _tHighpass
-{
-    float xs, ys, R;
-    float frequency;
-    
-} tHighpass;
-
-void        tHighpass_init      (tHighpass*  const, float freq);
-void        tHighpass_free      (tHighpass*  const);
-
-float       tHighpass_tick      (tHighpass*  const, float x);
-void        tHighpass_setFreq   (tHighpass*  const, float freq);
-float       tHighpass_getFreq   (tHighpass*  const);
-
-//==============================================================================
-    
-// Butterworth Filter
-#define NUM_SVF_BW 16
-typedef struct _tButterworth
-{
-    float gain;
-    
-    float N;
-    
-    tSVF low[NUM_SVF_BW];
-    tSVF high[NUM_SVF_BW];
-    
-    float f1,f2;
-    
-} tButterworth;
-
-void        tButterworth_init       (tButterworth* const, int N, float f1, float f2);
-void        tButterworth_free       (tButterworth* const);
-
-float       tButterworth_tick       (tButterworth* const, float input);
-void        tButterworth_setF1      (tButterworth* const, float in);
-void        tButterworth_setF2      (tButterworth* const, float in);
-void        tButterworth_setFreqs   (tButterworth* const, float f1, float f2);
-
-//==============================================================================
-
-typedef struct _tFIR
-{
-    float* past;
-    float* coeff;
-    int numTaps;
-
-} tFIR;
-
-void        tFIR_init       (tFIR* const, float* coeffs, int numTaps);
-void        tFIR_free       (tFIR* const);
-
-float       tFIR_tick       (tFIR* const, float input);
-void        tFIR_coeffs      (tFIR* const, float in);
-
-//==============================================================================
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif  // LEAF_FILTER_H_INCLUDED
-
-//==============================================================================
--- /dev/null
+++ b/LEAF/Inc/leaf-filters.h
@@ -1,0 +1,312 @@
+/*==============================================================================
+
+    leaf-filters.h
+    Created: 20 Jan 2017 12:01:10pm
+    Author:  Michael R Mulshine
+
+==============================================================================*/
+
+#ifndef LEAF_FILTERS_H_INCLUDED
+#define LEAF_FILTERS_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//==============================================================================
+    
+#include "leaf-math.h"
+#include "leaf-delay.h"
+#include "leaf-tables.h"
+
+//==============================================================================
+    
+/* tAllpass: Schroeder allpass. Comb-filter with feedforward and feedback. */
+typedef struct _tAllpass
+{
+    float gain;
+    
+    tLinearDelay delay;
+    
+    float lastOut;
+    
+} tAllpass;
+
+void        tAllpass_init           (tAllpass* const, float initDelay, uint32_t maxDelay);
+void        tAllpass_free           (tAllpass* const);
+
+float       tAllpass_tick           (tAllpass* const, float input);
+void        tAllpass_setGain        (tAllpass* const, float gain);
+void        tAllpass_setDelay       (tAllpass* const f, float delay);
+
+
+//==============================================================================
+    
+/* tOnePole: OnePole filter, reimplemented from STK (Cook and Scavone). */
+typedef struct _tOnePole
+{
+    float gain;
+    float a0,a1;
+    float b0,b1;
+    
+    float coef;
+    
+    float freq;
+    
+    float lastIn, lastOut;
+    
+} tOnePole;
+
+void        tOnePole_init           (tOnePole* const, float thePole);
+void        tOnePole_free           (tOnePole* const);
+
+float       tOnePole_tick           (tOnePole* const, float input);
+void        tOnePole_setB0          (tOnePole* const, float b0);
+void        tOnePole_setA1          (tOnePole* const, float a1);
+void        tOnePole_setPole        (tOnePole* const, float thePole);
+void        tOnePole_setFreq        (tOnePole* const, float freq);
+void        tOnePole_setCoefficients(tOnePole* const, float b0, float a1);
+void        tOnePole_setGain        (tOnePole* const, float gain);
+
+//==============================================================================
+    
+/* TwoPole filter, reimplemented from STK (Cook and Scavone). */
+typedef struct _tTwoPole
+{
+    float gain;
+    float a0, a1, a2;
+    float b0;
+    
+    float radius, frequency;
+    oBool normalize;
+    
+    float lastOut[2];
+    
+} tTwoPole;
+
+void        tTwoPole_init           (tTwoPole*  const);
+void        tTwoPole_free           (tTwoPole*  const);
+
+float       tTwoPole_tick           (tTwoPole*  const, float input);
+void        tTwoPole_setB0          (tTwoPole*  const, float b0);
+void        tTwoPole_setA1          (tTwoPole*  const, float a1);
+void        tTwoPole_setA2          (tTwoPole*  const, float a2);
+void        tTwoPole_setResonance   (tTwoPole*  const, float freq, float radius, oBool normalize);
+void        tTwoPole_setCoefficients(tTwoPole*  const, float b0, float a1, float a2);
+void        tTwoPole_setGain        (tTwoPole*  const, float gain);
+
+//==============================================================================
+    
+/* OneZero filter, reimplemented from STK (Cook and Scavone). */
+typedef struct _tOneZero
+{
+    float gain;
+    float b0,b1;
+    float lastIn, lastOut, frequency;
+    
+} tOneZero;
+
+void        tOneZero_init           (tOneZero*  const, float theZero);
+void        tOneZero_free           (tOneZero*  const);
+float       tOneZero_tick           (tOneZero*  const, float input);
+void        tOneZero_setB0          (tOneZero*  const, float b0);
+void        tOneZero_setB1          (tOneZero*  const, float b1);
+void        tOneZero_setZero        (tOneZero*  const, float theZero);
+void        tOneZero_setCoefficients(tOneZero*  const, float b0, float b1);
+void        tOneZero_setGain        (tOneZero*  const, float gain);
+float       tOneZero_getPhaseDelay(tOneZero *f, float frequency );
+
+//==============================================================================
+    
+/* TwoZero filter, reimplemented from STK (Cook and Scavone). */
+typedef struct _tTwoZero
+{
+    float gain;
+    float b0, b1, b2;
+    
+    float frequency, radius;
+    
+    float lastIn[2];
+    
+} tTwoZero;
+
+void        tTwoZero_init           (tTwoZero*  const);
+void        tTwoZero_free           (tTwoZero*  const);
+
+float       tTwoZero_tick           (tTwoZero*  const, float input);
+void        tTwoZero_setB0          (tTwoZero*  const, float b0);
+void        tTwoZero_setB1          (tTwoZero*  const, float b1);
+void        tTwoZero_setB2          (tTwoZero*  const, float b2);
+void        tTwoZero_setNotch       (tTwoZero*  const, float frequency, float radius);
+void        tTwoZero_setCoefficients(tTwoZero*  const, float b0, float b1, float b2);
+void        tTwoZero_setGain        (tTwoZero*  const, float gain);
+
+//==============================================================================
+    
+/* PoleZero filter, reimplemented from STK (Cook and Scavone). */
+typedef struct _tPoleZero
+{
+    float gain;
+    float a0,a1;
+    float b0,b1;
+    
+    float lastIn, lastOut;
+    
+} tPoleZero;
+
+void        tPoleZero_init              (tPoleZero*  const);
+void        tPoleZero_free              (tPoleZero*  const);
+
+float       tPoleZero_tick              (tPoleZero*  const, float input);
+void        tPoleZero_setB0             (tPoleZero*  const, float b0);
+void        tPoleZero_setB1             (tPoleZero*  const, float b1);
+void        tPoleZero_setA1             (tPoleZero*  const, float a1);
+void        tPoleZero_setCoefficients   (tPoleZero*  const, float b0, float b1, float a1);
+void        tPoleZero_setAllpass        (tPoleZero*  const, float coeff);
+void        tPoleZero_setBlockZero      (tPoleZero*  const, float thePole);
+void        tPoleZero_setGain           (tPoleZero*  const, float gain);
+
+//==============================================================================
+    
+/* BiQuad filter, reimplemented from STK (Cook and Scavone). */
+typedef struct _tBiQuad
+{
+    float gain;
+    float a0, a1, a2;
+    float b0, b1, b2;
+    
+    float lastIn[2];
+    float lastOut[2];
+    
+    float frequency, radius;
+    oBool normalize;
+} tBiQuad;
+
+void        tBiQuad_init           (tBiQuad*  const);
+void        tBiQuad_free           (tBiQuad*  const);
+
+float       tBiQuad_tick           (tBiQuad*  const, float input);
+void        tBiQuad_setB0          (tBiQuad*  const, float b0);
+void        tBiQuad_setB1          (tBiQuad*  const, float b1);
+void        tBiQuad_setB2          (tBiQuad*  const, float b2);
+void        tBiQuad_setA1          (tBiQuad*  const, float a1);
+void        tBiQuad_setA2          (tBiQuad*  const, float a2);
+void        tBiQuad_setNotch       (tBiQuad*  const, float freq, float radius);
+void        tBiQuad_setResonance   (tBiQuad*  const, float freq, float radius, oBool normalize);
+void        tBiQuad_setCoefficients(tBiQuad*  const, float b0, float b1, float b2, float a1, float a2);
+void        tBiQuad_setGain        (tBiQuad*  const, float gain);
+
+//==============================================================================
+    
+/* State Variable Filter, algorithm from Andy Simper. */
+typedef enum SVFType
+{
+    SVFTypeHighpass = 0,
+    SVFTypeLowpass,
+    SVFTypeBandpass,
+    SVFTypeNotch,
+    SVFTypePeak,
+} SVFType;
+
+typedef struct _tSVF
+{
+    SVFType type;
+    float cutoff, Q;
+    float ic1eq,ic2eq;
+    float g,k,a1,a2,a3;
+    
+} tSVF;
+
+void        tSVF_init       (tSVF*  const, SVFType type, float freq, float Q);
+void        tSVF_free       (tSVF*  const);
+
+float       tSVF_tick       (tSVF*  const, float v0);
+int         tSVF_setFreq    (tSVF*  const, float freq);
+int         tSVF_setQ       (tSVF*  const, float Q);
+
+//==============================================================================
+    
+/* Efficient State Variable Filter for 14-bit control input, [0, 4096). */
+typedef struct _tEfficientSVF
+{
+    SVFType type;
+    float cutoff, Q;
+    float ic1eq,ic2eq;
+    float g,k,a1,a2,a3;
+    
+} tEfficientSVF;
+
+void        tEfficientSVF_init      (tEfficientSVF*  const, SVFType type, uint16_t controlFreq, float Q);
+void        tEfficientSVF_free      (tEfficientSVF*  const);
+
+float       tEfficientSVF_tick      (tEfficientSVF*  const, float v0);
+int         tEfficientSVF_setFreq   (tEfficientSVF*  const, uint16_t controlFreq);
+int         tEfficientSVF_setQ      (tEfficientSVF*  const, float Q);
+
+//==============================================================================
+    
+/* Simple Highpass filter. */
+typedef struct _tHighpass
+{
+    float xs, ys, R;
+    float frequency;
+    
+} tHighpass;
+
+void        tHighpass_init      (tHighpass*  const, float freq);
+void        tHighpass_free      (tHighpass*  const);
+
+float       tHighpass_tick      (tHighpass*  const, float x);
+void        tHighpass_setFreq   (tHighpass*  const, float freq);
+float       tHighpass_getFreq   (tHighpass*  const);
+
+//==============================================================================
+    
+// Butterworth Filter
+#define NUM_SVF_BW 16
+typedef struct _tButterworth
+{
+    float gain;
+    
+    float N;
+    
+    tSVF low[NUM_SVF_BW];
+    tSVF high[NUM_SVF_BW];
+    
+    float f1,f2;
+    
+} tButterworth;
+
+void        tButterworth_init       (tButterworth* const, int N, float f1, float f2);
+void        tButterworth_free       (tButterworth* const);
+
+float       tButterworth_tick       (tButterworth* const, float input);
+void        tButterworth_setF1      (tButterworth* const, float in);
+void        tButterworth_setF2      (tButterworth* const, float in);
+void        tButterworth_setFreqs   (tButterworth* const, float f1, float f2);
+
+//==============================================================================
+
+typedef struct _tFIR
+{
+    float* past;
+    float* coeff;
+    int numTaps;
+
+} tFIR;
+
+void        tFIR_init       (tFIR* const, float* coeffs, int numTaps);
+void        tFIR_free       (tFIR* const);
+
+float       tFIR_tick       (tFIR* const, float input);
+void        tFIR_coeffs      (tFIR* const, float in);
+
+//==============================================================================
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // LEAF_FILTERS_H_INCLUDED
+
+//==============================================================================
--- a/LEAF/Inc/leaf-formant.h
+++ /dev/null
@@ -1,68 +1,0 @@
-/*==============================================================================
-
-    leaf-formant.h
-    Created: 30 Nov 2018 11:03:37am
-    Author:  airship
-
-==============================================================================*/
-
-#ifndef LEAF_FORMANT_H_INCLUDED
-#define LEAF_FORMANT_H_INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//==============================================================================
-    
-#include "leaf-global.h"
-#include "leaf-mempool.h"
-#include "leaf-math.h"
-
-//==============================================================================
-    
-#define FORD 7
-#define FORMANT_BUFFER_SIZE 2048
-
-typedef struct _tFormantShifter
-{
-    int ford;
-    int bufsize;
-    float falph;
-    float flamb;
-    float* fk;
-    float* fb;
-    float* fc;
-    float* frb;
-    float* frc;
-    float* fsig;
-    float* fsmooth;
-    float fhp;
-    float flp;
-    float flpa;
-    float** fbuff;
-    float* ftvec;
-    float fmute;
-    float fmutealph;
-    unsigned int cbi;
-    
-} tFormantShifter;
-
-void        tFormantShifter_init            (tFormantShifter* const, int bufsize, int order);
-void        tFormantShifter_free            (tFormantShifter* const);
-
-float       tFormantShifter_tick            (tFormantShifter* const, float input, float fwarp);
-float       tFormantShifter_remove          (tFormantShifter* const, float input);
-float       tFormantShifter_add             (tFormantShifter* const, float input, float fwarp);
-void        tFormantShifter_ioSamples       (tFormantShifter* const, float* in, float* out, int size, float fwarp);
-    
-//==============================================================================
-    
-#ifdef __cplusplus
-}
-#endif
-
-#endif // LEAF_FORMANT_H_INCLUDED
-
-//==============================================================================
-
--- /dev/null
+++ b/LEAF/Inc/leaf-instruments.h
@@ -1,0 +1,184 @@
+/*==============================================================================
+
+    leaf-instruments.h
+    Created: 30 Nov 2018 10:24:44am
+    Author:  airship
+
+==============================================================================*/
+
+#ifndef LEAF_INSTRUMENTS_H_INCLUDED
+#define LEAF_INSTRUMENTS_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//==============================================================================
+    
+#include "leaf-math.h"
+#include "leaf-oscillators.h"
+#include "leaf-filters.h"
+#include "leaf-envelopes.h"
+
+//==============================================================================
+    
+// 808 Cowbell
+typedef struct _t808Cowbell {
+    
+    tSquare p[2];
+    tNoise stick;
+    tSVF bandpassOsc;
+    tSVF bandpassStick;
+    tEnvelope envGain;
+    tEnvelope envStick;
+    tEnvelope envFilter;
+    tHighpass highpass;
+    float oscMix;
+    float filterCutoff;
+    oBool useStick;
+    
+} t808Cowbell;
+
+void    t808Cowbell_init             (t808Cowbell* const, int useStick);
+void    t808Cowbell_free             (t808Cowbell* const);
+float   t808Cowbell_tick             (t808Cowbell* const);
+void    t808Cowbell_on               (t808Cowbell* const, float vel);
+void    t808Cowbell_setDecay         (t808Cowbell* const, float decay);
+void    t808Cowbell_setHighpassFreq  (t808Cowbell* const, float freq);
+void    t808Cowbell_setBandpassFreq  (t808Cowbell* const, float freq);
+void    t808Cowbell_setFreq          (t808Cowbell* const, float freq);
+void    t808Cowbell_setOscMix        (t808Cowbell* const, float oscMix);
+void    t808Cowbell_setStick         (t808Cowbell* const, int useStick);
+
+//==============================================================================
+    
+// 808 Hihat
+typedef struct _t808Hihat {
+    
+    // 6 Square waves
+    tSquare p[6];
+    tNoise n;
+    tSVF bandpassOsc;
+    tSVF bandpassStick;
+    tEnvelope envGain;
+    tEnvelope envStick;
+    tEnvelope noiseFMGain;
+    tHighpass highpass;
+    tNoise stick;
+
+    float freq;
+    float stretch;
+    float FM_amount;
+    float oscNoiseMix;
+    
+} t808Hihat;
+
+void        t808Hihat_init               (t808Hihat* const);
+void        t808Hihat_free               (t808Hihat* const);
+
+float       t808Hihat_tick               (t808Hihat* const);
+void        t808Hihat_on                 (t808Hihat* const, float vel);
+void        t808Hihat_setOscNoiseMix     (t808Hihat* const, float oscNoiseMix);
+void        t808Hihat_setDecay           (t808Hihat* const, float decay);
+void        t808Hihat_setHighpassFreq    (t808Hihat* const, float freq);
+void        t808Hihat_setOscBandpassFreq  (t808Hihat* const, float freq);
+void 		t808Hihat_setOscBandpassQ		(t808Hihat* const hihat, float Q);
+void        t808Hihat_setStickBandPassFreq  (t808Hihat* const, float freq);
+void 		t808Hihat_setStickBandPassQ		(t808Hihat* const hihat, float Q);
+void        t808Hihat_setOscFreq         (t808Hihat* const, float freq);
+void 		t808Hihat_setStretch				(t808Hihat* const hihat, float stretch);
+void 		t808Hihat_setFM					(t808Hihat* const hihat, float FM_amount);
+
+//==============================================================================
+    
+// 808 Snare
+typedef struct _t808Snare {
+    
+    // Tone 1, Tone 2, Noise
+    tTriangle tone[2]; // Tri (not yet antialiased or wavetabled)
+    tNoise noiseOsc;
+    tSVF toneLowpass[2];
+    tSVF noiseLowpass; // Lowpass from SVF filter
+    tEnvelope toneEnvOsc[2];
+    tEnvelope toneEnvGain[2];
+    tEnvelope noiseEnvGain;
+    tEnvelope toneEnvFilter[2];
+    tEnvelope noiseEnvFilter;
+    
+    float toneGain[2];
+    float noiseGain;
+    
+    float toneNoiseMix;
+    
+    float tone1Freq, tone2Freq;
+    
+    float noiseFilterFreq;
+    
+    
+} t808Snare;
+
+void        t808Snare_init                  (t808Snare* const);
+void        t808Snare_free                  (t808Snare* const);
+
+float       t808Snare_tick                  (t808Snare* const);
+void        t808Snare_on                    (t808Snare* const, float vel);
+void        t808Snare_setTone1Freq          (t808Snare* const, float freq);
+void        t808Snare_setTone2Freq          (t808Snare* const, float freq);
+void        t808Snare_setTone1Decay         (t808Snare* const, float decay);
+void        t808Snare_setTone2Decay         (t808Snare* const, float decay);
+void        t808Snare_setNoiseDecay         (t808Snare* const, float decay);
+void        t808Snare_setToneNoiseMix       (t808Snare* const, float toneNoiseMix);
+void        t808Snare_setNoiseFilterFreq    (t808Snare* const, float noiseFilterFreq);
+void        t808Snare_setNoiseFilterQ       (t808Snare* const, float noiseFilterQ);
+
+//==============================================================================
+    
+// 808 Kick
+typedef struct _t808Kick {
+
+
+    tCycle tone; // Tri
+    tNoise noiseOsc;
+    tSVF toneLowpass;
+    tEnvelope toneEnvOscChirp;
+    tEnvelope toneEnvOscSigh;
+    tEnvelope toneEnvGain;
+    tEnvelope noiseEnvGain;
+    tEnvelope toneEnvFilter;
+
+    float toneGain;
+    float noiseGain;
+
+    float toneInitialFreq;
+    float sighAmountInHz;
+    float chirpRatioMinusOne;
+    float noiseFilterFreq;
+
+
+} t808Kick;
+
+void        t808Kick_init                  (t808Kick* const);
+void        t808Kick_free                  (t808Kick* const);
+
+float       t808Kick_tick                  (t808Kick* const);
+void        t808Kick_on                    (t808Kick* const, float vel);
+void        t808Kick_setToneFreq          (t808Kick* const, float freq);
+void        t808Kick_setToneDecay         (t808Kick* const, float decay);
+void        t808Kick_setNoiseDecay         (t808Kick* const, float decay);
+void        t808Kick_setSighAmount         (t808Kick* const, float sigh);
+void        t808Kick_setChirpAmount         (t808Kick* const, float chirp);
+void        t808Kick_setToneNoiseMix       (t808Kick* const, float toneNoiseMix);
+void        t808Kick_setNoiseFilterFreq    (t808Kick* const, float noiseFilterFreq);
+void        t808Kick_setNoiseFilterQ       (t808Kick* const, float noiseFilterQ);
+    
+//==============================================================================
+    
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LEAF_INSTRUMENTS_H_INCLUDED
+
+//==============================================================================
+
+
--- a/LEAF/Inc/leaf-midi.h
+++ b/LEAF/Inc/leaf-midi.h
@@ -18,9 +18,37 @@
 #include "leaf-global.h"
 #include "leaf-mempool.h"
 #include "leaf-math.h"
-#include "leaf-utilities.h"
+#include "leaf-envelopes.h"
 
 //==============================================================================
+    
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+// STACK implementation (fixed size)
+#define STACK_SIZE 128
+typedef struct _tStack
+{
+    int data[STACK_SIZE];
+    uint16_t pos;
+    uint16_t size;
+    uint16_t capacity;
+    oBool ordered;
+    
+} tStack;
+
+void    tStack_init                 (tStack* const);
+void    tStack_free                 (tStack* const);
+
+void    tStack_setCapacity          (tStack* const, uint16_t cap);
+int     tStack_addIfNotAlreadyThere (tStack* const, uint16_t item);
+void    tStack_add                  (tStack* const, uint16_t item);
+int     tStack_remove               (tStack* const, uint16_t item);
+void    tStack_clear                (tStack* const);
+int     tStack_first                (tStack* const);
+int     tStack_getSize              (tStack* const);
+int     tStack_contains             (tStack* const, uint16_t item);
+int     tStack_next                 (tStack* const);
+int     tStack_get                  (tStack* const, int which);
     
 /* tPoly */
 typedef struct _tPoly
--- a/LEAF/Inc/leaf-oscillator.h
+++ /dev/null
@@ -1,181 +1,0 @@
-/*==============================================================================
-
-    leaf-oscillator.h
-    Created: 20 Jan 2017 12:00:58pm
-    Author:  Michael R Mulshine
-
-==============================================================================*/
-
-#ifndef LEAF_OSCILLATOR_H_INCLUDED
-#define LEAF_OSCILLATOR_H_INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//==============================================================================
-
-#include "leaf-math.h"
-
-#include "leaf-filter.h"
-
-//==============================================================================
-
-/* tNeuron */
-typedef enum NeuronMode
-{
-    NeuronNormal = 0,
-    NeuronTanh,
-    NeuronAaltoShaper,
-    NeuronModeNil
-} NeuronMode;
-
-typedef struct _tNeuron
-{
-    tPoleZero f;
-    
-    NeuronMode mode;
-    
-    float voltage, current;
-    float timeStep;
-    
-    float alpha[3];
-    float beta[3];
-    float rate[3];
-    float V[3];
-    float P[3];
-    float gK, gN, gL, C;
-} tNeuron;
-
-void        tNeuron_init        (tNeuron* const);
-void        tNeuron_free        (tNeuron* const);
-
-void        tNeuron_reset       (tNeuron* const);
-float       tNeuron_Tick        (tNeuron* const);
-void        tNeuron_setMode     (tNeuron* const, NeuronMode mode);
-void        tNeuron_setCurrent  (tNeuron* const, float current);
-void        tNeuron_setK        (tNeuron* const, float K);
-void        tNeuron_setL        (tNeuron* const, float L);
-void        tNeuron_setN        (tNeuron* const, float N);
-void        tNeuron_setC        (tNeuron* const, float C);
-void        tNeuron_setV1       (tNeuron* const, float V1);
-void        tNeuron_setV2       (tNeuron* const, float V2);
-void        tNeuron_setV3       (tNeuron* const, float V3);
-void        tNeuron_setTimeStep (tNeuron* const, float timestep);
-
-//==============================================================================
-
-/* tPhasor: Aliasing phasor [0.0, 1.0) */
-typedef struct _tPhasor
-{
-    float phase;
-    float inc,freq;
-    
-} tPhasor;
-
-void        tPhasor_init        (tPhasor*  const);
-void        tPhasor_free        (tPhasor*  const);
-
-float       tPhasor_tick        (tPhasor*  const);
-int         tPhasor_setFreq     (tPhasor*  const, float freq);
-
-//==============================================================================
-
-/* tCycle: Cycle/Sine waveform. Wavetable synthesis.*/
-typedef struct _tCycle
-{
-    // Underlying phasor
-    float phase;
-    float inc,freq;
-    
-} tCycle;
-
-void        tCycle_init         (tCycle*  const);
-void        tCycle_free         (tCycle*  const);
-
-float       tCycle_tick         (tCycle*  const);
-int         tCycle_setFreq      (tCycle*  const, float freq);
-
-//==============================================================================
-
-/* tSawtooth: Anti-aliased Sawtooth waveform using wavetable interpolation. Wavetables constructed from sine components. */
-typedef struct _tSawtooth
-{
-    // Underlying phasor
-    float phase;
-    float inc,freq;
-    
-} tSawtooth;
-
-void        tSawtooth_init      (tSawtooth*  const);
-void        tSawtooth_free      (tSawtooth*  const);
-
-float       tSawtooth_tick      (tSawtooth*  const);
-int         tSawtooth_setFreq   (tSawtooth*  const, float freq);
-
-//==============================================================================
-
-/* tTriangle: Anti-aliased Triangle waveform using wavetable interpolation. Wavetables constructed from sine components. */
-typedef struct _tTriangle
-{
-    // Underlying phasor
-    float phase;
-    float inc,freq;
-    
-} tTriangle;
-
-void        tTriangle_init      (tTriangle*  const);
-void        tTriangle_free      (tTriangle*  const);
-
-float       tTriangle_tick      (tTriangle*  const);
-int         tTriangle_setFreq   (tTriangle*  const, float freq);
-
-//==============================================================================
-
-/* tSquare: Anti-aliased Square waveform using wavetable interpolation. Wavetables constructed from sine components. */
-typedef struct _tSquare
-{
-    // Underlying phasor
-    float phase;
-    float inc,freq;
-    
-} tSquare;
-
-void        tSquare_init        (tSquare*  const);
-void        tSquare_free        (tSquare*  const);
-
-float       tSquare_tick        (tSquare*  const);
-int         tSquare_setFreq     (tSquare*  const, float freq);
-
-//==============================================================================
-
-/* tNoise. WhiteNoise, PinkNoise. */
-typedef enum NoiseType
-{
-    WhiteNoise=0,
-    PinkNoise,
-    NoiseTypeNil,
-} NoiseType;
-
-typedef struct _tNoise
-{
-    NoiseType type;
-    float pinkb0, pinkb1, pinkb2;
-    float(*rand)();
-    
-} tNoise;
-
-void        tNoise_init          (tNoise* const, NoiseType type);
-void        tNoise_free          (tNoise* const);
-
-float       tNoise_tick          (tNoise*  const);
-
-//==============================================================================
-    
-#ifdef __cplusplus
-}
-#endif
-        
-#endif  // LEAF_OSCILLATOR_H_INCLUDED
-
-//==============================================================================
--- /dev/null
+++ b/LEAF/Inc/leaf-oscillators.h
@@ -1,0 +1,180 @@
+/*==============================================================================
+
+    leaf-oscillators.h
+    Created: 20 Jan 2017 12:00:58pm
+    Author:  Michael R Mulshine
+
+==============================================================================*/
+
+#ifndef LEAF_OSCILLATORS_H_INCLUDED
+#define LEAF_OSCILLATORS_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//==============================================================================
+
+#include "leaf-math.h"
+#include "leaf-filters.h"
+
+//==============================================================================
+
+/* tCycle: Cycle/Sine waveform. Wavetable synthesis.*/
+typedef struct _tCycle
+{
+    // Underlying phasor
+    float phase;
+    float inc,freq;
+    
+} tCycle;
+
+void        tCycle_init         (tCycle*  const);
+void        tCycle_free         (tCycle*  const);
+
+float       tCycle_tick         (tCycle*  const);
+int         tCycle_setFreq      (tCycle*  const, float freq);
+
+//==============================================================================
+
+/* tTriangle: Anti-aliased Triangle waveform using wavetable interpolation. Wavetables constructed from sine components. */
+typedef struct _tTriangle
+{
+    // Underlying phasor
+    float phase;
+    float inc,freq;
+    
+} tTriangle;
+
+void        tTriangle_init      (tTriangle*  const);
+void        tTriangle_free      (tTriangle*  const);
+
+float       tTriangle_tick      (tTriangle*  const);
+int         tTriangle_setFreq   (tTriangle*  const, float freq);
+
+//==============================================================================
+
+/* tSquare: Anti-aliased Square waveform using wavetable interpolation. Wavetables constructed from sine components. */
+typedef struct _tSquare
+{
+    // Underlying phasor
+    float phase;
+    float inc,freq;
+    
+} tSquare;
+
+void        tSquare_init        (tSquare*  const);
+void        tSquare_free        (tSquare*  const);
+
+float       tSquare_tick        (tSquare*  const);
+int         tSquare_setFreq     (tSquare*  const, float freq);
+    
+//==============================================================================
+
+/* tSawtooth: Anti-aliased Sawtooth waveform using wavetable interpolation. Wavetables constructed from sine components. */
+typedef struct _tSawtooth
+{
+    // Underlying phasor
+    float phase;
+    float inc,freq;
+    
+} tSawtooth;
+
+void        tSawtooth_init      (tSawtooth*  const);
+void        tSawtooth_free      (tSawtooth*  const);
+
+float       tSawtooth_tick      (tSawtooth*  const);
+int         tSawtooth_setFreq   (tSawtooth*  const, float freq);
+    
+//==============================================================================
+
+/* tPhasor: Aliasing phasor [0.0, 1.0) */
+typedef struct _tPhasor
+{
+    float phase;
+    float inc,freq;
+    
+} tPhasor;
+
+void        tPhasor_init        (tPhasor*  const);
+void        tPhasor_free        (tPhasor*  const);
+
+float       tPhasor_tick        (tPhasor*  const);
+int         tPhasor_setFreq     (tPhasor*  const, float freq);
+
+//==============================================================================
+
+/* tNoise. WhiteNoise, PinkNoise. */
+typedef enum NoiseType
+{
+    WhiteNoise=0,
+    PinkNoise,
+    NoiseTypeNil,
+} NoiseType;
+
+typedef struct _tNoise
+{
+    NoiseType type;
+    float pinkb0, pinkb1, pinkb2;
+    float(*rand)(void);
+    
+} tNoise;
+
+void        tNoise_init          (tNoise* const, NoiseType type);
+void        tNoise_free          (tNoise* const);
+
+float       tNoise_tick          (tNoise*  const);
+    
+//==============================================================================
+
+/* tNeuron */
+typedef enum NeuronMode
+{
+    NeuronNormal = 0,
+    NeuronTanh,
+    NeuronAaltoShaper,
+    NeuronModeNil
+} NeuronMode;
+
+typedef struct _tNeuron
+{
+    tPoleZero f;
+    
+    NeuronMode mode;
+    
+    float voltage, current;
+    float timeStep;
+    
+    float alpha[3];
+    float beta[3];
+    float rate[3];
+    float V[3];
+    float P[3];
+    float gK, gN, gL, C;
+} tNeuron;
+
+void        tNeuron_init        (tNeuron* const);
+void        tNeuron_free        (tNeuron* const);
+
+void        tNeuron_reset       (tNeuron* const);
+float       tNeuron_Tick        (tNeuron* const);
+void        tNeuron_setMode     (tNeuron* const, NeuronMode mode);
+void        tNeuron_setCurrent  (tNeuron* const, float current);
+void        tNeuron_setK        (tNeuron* const, float K);
+void        tNeuron_setL        (tNeuron* const, float L);
+void        tNeuron_setN        (tNeuron* const, float N);
+void        tNeuron_setC        (tNeuron* const, float C);
+void        tNeuron_setV1       (tNeuron* const, float V1);
+void        tNeuron_setV2       (tNeuron* const, float V2);
+void        tNeuron_setV3       (tNeuron* const, float V3);
+void        tNeuron_setTimeStep (tNeuron* const, float timestep);
+
+//==============================================================================
+    
+#ifdef __cplusplus
+}
+#endif
+        
+#endif  // LEAF_OSCILLATORS_H_INCLUDED
+
+//==============================================================================
--- a/LEAF/Inc/leaf-oversampler.h
+++ /dev/null
@@ -1,51 +1,0 @@
-//
-//  leaf-oversampler.h
-//  LEAF
-//
-//  Created by Matthew Wang and Joshua Becker on 2/28/19.
-//  Copyright © 2019 Princeton University. All rights reserved.
-//
-//==============================================================================
-
-#ifndef LEAF_OVERSAMPLER_H_INCLUDED
-#define LEAF_OVERSAMPLER_H_INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-    
-//==============================================================================
-    
-#include "leaf-global.h"
-#include "leaf-mempool.h"
-#include "leaf-math.h"
-#include "leaf-filter.h"
-    
-//==============================================================================
-
-typedef struct _tOversampler
-{
-    int ratio;
-    float* pCoeffs;
-    float* upState;
-    float* downState;
-    int numTaps;
-    int phaseLength;
-} tOversampler;
-
-void        tOversampler_init(tOversampler* const, int order, oBool extraQuality);
-void        tOversampler_free(tOversampler* const);
-void        tOversampler_upsample(tOversampler* const, float input, float* output);
-float       tOversampler_downsample(tOversampler *const os, float* input);
-float       tOversampler_tick(tOversampler* const, float input, float (*effectTick)(float));
-int         tOversampler_getLatency(tOversampler* const os);
-
-//==============================================================================
-    
-#ifdef __cplusplus
-}
-#endif
-
-#endif  // LEAF_OVERSAMPLER_H_INCLUDED
-
-//==============================================================================
--- /dev/null
+++ b/LEAF/Inc/leaf-physical.h
@@ -1,0 +1,221 @@
+/*
+  ==============================================================================
+
+    leaf-physical.h
+    Created: 30 Nov 2018 10:41:55am
+    Author:  airship
+
+  ==============================================================================
+*/
+
+#ifndef LEAF_PHYSICAL_H_INCLUDED
+#define LEAF_PHYSICAL_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+    
+//==============================================================================
+
+#include "leaf-global.h"
+#include "leaf-math.h"
+#include "leaf-delay.h"
+#include "leaf-filters.h"
+#include "leaf-oscillators.h"
+#include "leaf-envelopes.h"
+#include "leaf-dynamics.h"
+
+//==============================================================================
+
+/* Karplus Strong model */
+typedef struct _tPluck
+{
+    tAllpassDelay     delayLine; // Allpass or Linear??  big difference...
+    tOneZero    loopFilter;
+    tOnePole    pickFilter;
+    tNoise      noise;
+    
+    float lastOut;
+    float loopGain;
+    float lastFreq;
+    
+    float sr;
+    
+} tPluck;
+
+void        tPluck_init          (tPluck*  const, float lowestFrequency); //float delayBuff[DELAY_LENGTH]);
+void        tPluck_free          (tPluck*  const);
+
+float       tPluck_tick          (tPluck*  const);
+
+// Pluck the string.
+void        tPluck_pluck         (tPluck*  const, float amplitude);
+
+// Start a note with the given frequency and amplitude.;
+void        tPluck_noteOn        (tPluck*  const, float frequency, float amplitude );
+
+// Stop a note with the given amplitude (speed of decay).
+void        tPluck_noteOff       (tPluck*  const, float amplitude );
+
+// Set instrument parameters for a particular frequency.
+void        tPluck_setFrequency  (tPluck*  const, float frequency );
+
+// Perform the control change specified by \e number and \e value (0.0 - 128.0).
+void        tPluck_controlChange (tPluck*  const, int number, float value);
+
+// tPluck Utilities.
+float       tPluck_getLastOut    (tPluck*  const);
+
+//==============================================================================
+    
+/* Stif Karplus Strong model */
+typedef struct _tKarplusStrong
+{
+    tAllpassDelay  delayLine;
+    tLinearDelay combDelay;
+    tOneZero filter;
+    tNoise   noise;
+    tBiQuad  biquad[4];
+    
+    
+    
+    uint32_t length;
+    float loopGain;
+    float baseLoopGain;
+    float lastFrequency;
+    float lastLength;
+    float stretching;
+    float pluckAmplitude;
+    float pickupPosition;
+    
+    float lastOut;
+    
+} tKarplusStrong;
+
+typedef enum SKControlType
+{
+    SKPickPosition = 0,
+    SKStringDamping,
+    SKDetune,
+    SKControlTypeNil
+} SKControlType;
+
+void        tKarplusStrong_init               (tKarplusStrong* const, float lowestFrequency); // float delayBuff[2][DELAY_LENGTH]);
+void        tKarplusStrong_free               (tKarplusStrong* const);
+
+float       tKarplusStrong_tick               (tKarplusStrong*  const);
+
+// Pluck the string.
+void        tKarplusStrong_pluck              (tKarplusStrong*  const, float amplitude);
+
+// Start a note with the given frequency and amplitude.;
+void        tKarplusStrong_noteOn             (tKarplusStrong*  const, float frequency, float amplitude );
+
+// Stop a note with the given amplitude (speed of decay).
+void        tKarplusStrong_noteOff            (tKarplusStrong*  const, float amplitude );
+
+// Set instrument parameters for a particular frequency.
+void        tKarplusStrong_setFrequency       (tKarplusStrong*  const, float frequency );
+
+// Perform the control change specified by \e number and \e value (0.0 - 128.0).
+// Use SKPickPosition, SKStringDamping, or SKDetune for type.
+void        tKarplusStrong_controlChange      (tKarplusStrong*  const, SKControlType type, float value);
+
+// Set the stretch "factor" of the string (0.0 - 1.0).
+void        tKarplusStrong_setStretch         (tKarplusStrong*  const, float stretch );
+
+// Set the pluck or "excitation" position along the string (0.0 - 1.0).
+void        tKarplusStrong_setPickupPosition  (tKarplusStrong*  const, float position );
+
+// Set the base loop gain.
+void        tKarplusStrong_setBaseLoopGain    (tKarplusStrong*  const, float aGain );
+
+// tKarplusStrong utilities.
+float       tKarplusStrong_getLastOut         (tKarplusStrong*  const);
+    
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+/* Simple Living String */
+typedef struct _tSimpleLivingString {
+    float freq, waveLengthInSamples;        // the frequency of the string, determining delay length
+    float dampFreq;    // frequency for the bridge LP filter, in Hz
+    float decay; // amplitude damping factor for the string (only active in mode 0)
+    float levMode;
+    float curr;
+    tLinearDelay delayLine;
+    tOnePole bridgeFilter;
+    tHighpass DCblocker;
+    tFeedbackLeveler fbLev;
+    tExpSmooth wlSmooth;
+} tSimpleLivingString;
+
+void    tSimpleLivingString_init      (tSimpleLivingString* const, float freq, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode);
+void    tSimpleLivingString_free      (tSimpleLivingString* const);
+float   tSimpleLivingString_tick      (tSimpleLivingString* const, float input);
+float   tSimpleLivingString_sample    (tSimpleLivingString* const);
+int     tSimpleLivingString_setFreq               (tSimpleLivingString* const, float freq);
+int     tSimpleLivingString_setWaveLength        (tSimpleLivingString* const, float waveLength); // in samples
+int     tSimpleLivingString_setDampFreq           (tSimpleLivingString* const, float dampFreq);
+int     tSimpleLivingString_setDecay             (tSimpleLivingString* const, float decay); // should be near 1.0
+int     tSimpleLivingString_setTargetLev        (tSimpleLivingString* const, float targetLev);
+int     tSimpleLivingString_setLevSmoothFactor  (tSimpleLivingString* const, float levSmoothFactor);
+int     tSimpleLivingString_setLevStrength        (tSimpleLivingString* const, float levStrength);
+int     tSimpleLivingString_setLevMode        (tSimpleLivingString* const, int levMode);
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+/* Living String */
+typedef struct _tLivingString {
+    float freq, waveLengthInSamples;        // the frequency of the whole string, determining delay length
+    float pickPos;    // the pick position, dividing the string in two, in ratio
+    float prepIndex;    // the amount of pressure on the pickpoint of the string (near 0=soft obj, near 1=hard obj)
+    float dampFreq;    // frequency for the bridge LP filter, in Hz
+    float decay; // amplitude damping factor for the string (only active in mode 0)
+    float levMode;
+    float curr;
+    tLinearDelay delLF,delUF,delUB,delLB;    // delay for lower/upper/forward/backward part of the waveguide model
+    tOnePole bridgeFilter, nutFilter, prepFilterU, prepFilterL;
+    tHighpass DCblockerL, DCblockerU;
+    tFeedbackLeveler fbLevU, fbLevL;
+    tExpSmooth wlSmooth, ppSmooth;
+} tLivingString;
+
+void    tLivingString_init      (tLivingString* const, float freq, float pickPos, float prepIndex, float dampFreq, float decay,
+                                 float targetLev, float levSmoothFactor, float levStrength, int levMode);
+void    tLivingString_free      (tLivingString* const);
+float   tLivingString_tick      (tLivingString* const, float input);
+float   tLivingString_sample    (tLivingString* const);
+int     tLivingString_setFreq               (tLivingString* const, float freq);
+int     tLivingString_setWaveLength            (tLivingString* const, float waveLength); // in samples
+int     tLivingString_setPickPos               (tLivingString* const, float pickPos);
+int     tLivingString_setPrepIndex             (tLivingString* const, float prepIndex);
+int     tLivingString_setDampFreq           (tLivingString* const, float dampFreq);
+int     tLivingString_setDecay                 (tLivingString* const, float decay); // should be near 1.0
+int     tLivingString_setTargetLev            (tLivingString* const, float targetLev);
+int     tLivingString_setLevSmoothFactor      (tLivingString* const, float levSmoothFactor);
+int     tLivingString_setLevStrength        (tLivingString* const, float levStrength);
+int     tLivingString_setLevMode            (tLivingString* const, int levMode);
+    
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
+//Reed Table - borrowed from STK
+typedef struct _tReedTable {
+    float offset, slope;
+} tReedTable;
+
+void    tReedTable_init      (tReedTable* const, float offset, float slope);
+void    tReedTable_free      (tReedTable* const);
+float   tReedTable_tick      (tReedTable* const, float input);
+float   tReedTable_tanh_tick     (tReedTable* const p, float input); //tanh softclip version of reed table - replacing the hard clip in original stk code
+void     tReedTable_setOffset   (tReedTable* const, float offset);
+void     tReedTable_setSlope (tReedTable* const, float slope);
+
+//==============================================================================
+    
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LEAF_PHYSICAL_H_INCLUDED
+
+//==============================================================================
--- a/LEAF/Inc/leaf-pitch.h
+++ /dev/null
@@ -1,161 +1,0 @@
-/*
-  ==============================================================================
-
-    leaf-pitch.h
-    Created: 30 Nov 2018 11:03:13am
-    Author:  airship
-
-  ==============================================================================
-*/
-
-#ifndef LEAF_PITCH_H_INCLUDED
-#define LEAF_PITCH_H_INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//==============================================================================
-
-#include "leaf-global.h"
-#include "leaf-math.h"
-
-#include "leaf-filter.h"
-#include "leaf-utilities.h"
-
-//==============================================================================
-    
-#define DEFPITCHRATIO 2.0f
-#define DEFTIMECONSTANT 100.0f
-#define DEFHOPSIZE 64
-#define DEFWINDOWSIZE 64
-#define FBA 20
-#define HPFREQ 40.0f
-
-
-//==============================================================================
-    
-// Pitch shifter 
-typedef struct _tPitchShifter
-{
-    tEnv env;
-    tSNAC snac;
-    tSOLAD sola;
-    tHighpass hp;
-    
-    float* inBuffer;
-    float* outBuffer;
-    int frameSize;
-    int bufSize;
-    int framesPerBuffer;
-    int curBlock;
-    int lastBlock;
-    int index;
-    
-    uint16_t hopSize;
-    uint16_t windowSize;
-    uint8_t fba;
-    
-    float pitchFactor;
-    float timeConstant;
-    float radius;
-    float max;
-    float lastmax;
-    float deltamax;
-    
-} tPitchShifter;
-
-void        tPitchShifter_init              (tPitchShifter* const, float* in, float* out, int bufSize, int frameSize);
-void        tPitchShifter_free              (tPitchShifter* const);
-
-float       tPitchShifter_tick              (tPitchShifter* const, float sample);
-float       tPitchShifterToFreq_tick        (tPitchShifter* const, float sample, float freq);
-float       tPitchShifterToFunc_tick        (tPitchShifter* const, float sample, float (*fun)(float));
-void        tPitchShifter_ioSamples_toFreq  (tPitchShifter* const, float* in, float* out, int size, float toFreq);
-void        tPitchShifter_ioSamples_toPeriod(tPitchShifter* const, float* in, float* out, int size, float toPeriod);
-void        tPitchShifter_ioSamples_toFunc  (tPitchShifter* const, float* in, float* out, int size, float (*fun)(float));
-void        tPitchShifter_setPitchFactor    (tPitchShifter* const, float pf);
-void        tPitchShifter_setTimeConstant   (tPitchShifter* const, float tc);
-void        tPitchShifter_setHopSize        (tPitchShifter* const, int hs);
-void        tPitchShifter_setWindowSize     (tPitchShifter* const, int ws);
-float       tPitchShifter_getPeriod         (tPitchShifter* const);
-
-//==============================================================================
-    
-// Period detection
-typedef struct _tPeriod
-{
-    tEnv env;
-    tSNAC snac;
-    float* inBuffer;
-    float* outBuffer;
-    int frameSize;
-    int bufSize;
-    int framesPerBuffer;
-    int curBlock;
-    int lastBlock;
-    int i;
-    int indexstore;
-    int iLast;
-    int index;
-    float period;
-    
-    uint16_t hopSize;
-    uint16_t windowSize;
-    uint8_t fba;
-    
-    float timeConstant;
-    float radius;
-    float max;
-    float lastmax;
-    float deltamax;
-    
-}tPeriod;
-
-void        tPeriod_init                    (tPeriod* const, float* in, float* out, int bufSize, int frameSize);
-void        tPeriod_free                    (tPeriod* const);
-
-float       tPeriod_findPeriod              (tPeriod* const, float sample);
-void        tPeriod_setHopSize              (tPeriod* p, int hs);
-void        tPeriod_setWindowSize           (tPeriod* p, int ws);
-
-//==============================================================================
-    
-// Pitch shift
-typedef struct _tPitchShift
-{
-    tSOLAD sola;
-    tHighpass hp;
-    tPeriod* p;
-    
-    float* outBuffer;
-    int frameSize;
-    int bufSize;
-    
-    int framesPerBuffer;
-    int curBlock;
-    int lastBlock;
-    int index;
-    
-    float pitchFactor;
-    float timeConstant;
-    float radius;
-} tPitchShift;
-
-void        tPitchShift_init                (tPitchShift* const, tPeriod* const, float* out, int bufSize);
-void        tPitchShift_free                (tPitchShift* const);
-
-float       tPitchShift_shift               (tPitchShift* const);
-float       tPitchShift_shiftToFunc         (tPitchShift* const, float (*fun)(float));
-float       tPitchShift_shiftToFreq         (tPitchShift* const, float freq);
-void        tPitchShift_setPitchFactor      (tPitchShift* const, float pf);
-
-//==============================================================================
-    
-#ifdef __cplusplus
-}
-#endif
-
-#endif // LEAF_PITCH_H_INCLUDED
-
-//==============================================================================
--- a/LEAF/Inc/leaf-reverb.h
+++ b/LEAF/Inc/leaf-reverb.h
@@ -17,15 +17,14 @@
     
 #include "leaf-global.h"
 #include "leaf-math.h"
-
 #include "leaf-delay.h"
-#include "leaf-filter.h"
-#include "leaf-oscillator.h"
+#include "leaf-filters.h"
+#include "leaf-oscillators.h"
 
 //==============================================================================
 
-/* PRCRev: Reverb, reimplemented from STK (Cook and Scavone). */
-typedef struct _tPRCRev
+/* PRCReverb: Reverb, reimplemented from STK (Cook and Scavone). */
+typedef struct _tPRCReverb
 {
     float mix, t60;
     
@@ -38,23 +37,23 @@
     
     float lastIn, lastOut;
     
-} tPRCRev;
+} tPRCReverb;
 
-void    tPRCRev_init    (tPRCRev* const, float t60);
-void    tPRCRev_free    (tPRCRev* const);
+void    tPRCReverb_init    (tPRCReverb* const, float t60);
+void    tPRCReverb_free    (tPRCReverb* const);
 
-float   tPRCRev_tick    (tPRCRev* const, float input);
+float   tPRCReverb_tick    (tPRCReverb* const, float input);
 
 // Set reverb time in seconds.
-void    tPRCRev_setT60  (tPRCRev* const, float t60);
+void    tPRCReverb_setT60  (tPRCReverb* const, float t60);
 
 // Set mix between dry input and wet output signal.
-void    tPRCRev_setMix  (tPRCRev* const, float mix);
+void    tPRCReverb_setMix  (tPRCReverb* const, float mix);
 
 //==============================================================================
 
-/* NRev: Reverb, reimplemented from STK (Cook and Scavone). */
-typedef struct _tNRev
+/* NReverb: Reverb, reimplemented from STK (Cook and Scavone). */
+typedef struct _tNReverb
 {
     float mix, t60;
     
@@ -68,22 +67,22 @@
     
     float lastIn, lastOut;
     
-} tNRev;
+} tNReverb;
 
-void    tNRev_init      (tNRev* const, float t60);
-void    tNRev_free      (tNRev* const);
+void    tNReverb_init      (tNReverb* const, float t60);
+void    tNReverb_free      (tNReverb* const);
 
-float   tNRev_tick      (tNRev* const, float input);
+float   tNReverb_tick      (tNReverb* const, float input);
 
 // Set reverb time in seconds.
-void    tNRev_setT60    (tNRev* const, float t60);
+void    tNReverb_setT60    (tNReverb* const, float t60);
 
 // Set mix between dry input and wet output signal.
-void    tNRev_setMix    (tNRev*  const, float mix);
+void    tNReverb_setMix    (tNReverb*  const, float mix);
 
 //==============================================================================
 
-typedef struct _tDattorro
+typedef struct _tDattorroReverb
 {
     float   predelay;
     float   input_filter;
@@ -125,19 +124,19 @@
     
     tCycle      f2_lfo;
     
-} tDattorro;
+} tDattorroReverb;
 
-void    tDattorro_init              (tDattorro* const);
-void    tDattorro_free              (tDattorro* const);
+void    tDattorroReverb_init              (tDattorroReverb* const);
+void    tDattorroReverb_free              (tDattorroReverb* const);
 
-float   tDattorro_tick              (tDattorro* const, float input);
+float   tDattorroReverb_tick              (tDattorroReverb* const, float input);
 
-void    tDattorro_setMix            (tDattorro* const, float mix);
-void    tDattorro_setSize           (tDattorro* const, float size);
-void    tDattorro_setInputDelay     (tDattorro* const, float preDelay);
-void    tDattorro_setInputFilter    (tDattorro* const, float freq);
-void    tDattorro_setFeedbackFilter (tDattorro* const, float freq);
-void    tDattorro_setFeedbackGain   (tDattorro* const, float gain);
+void    tDattorroReverb_setMix            (tDattorroReverb* const, float mix);
+void    tDattorroReverb_setSize           (tDattorroReverb* const, float size);
+void    tDattorroReverb_setInputDelay     (tDattorroReverb* const, float preDelay);
+void    tDattorroReverb_setInputFilter    (tDattorroReverb* const, float freq);
+void    tDattorroReverb_setFeedbackFilter (tDattorroReverb* const, float freq);
+void    tDattorroReverb_setFeedbackGain   (tDattorroReverb* const, float gain);
     
 #ifdef __cplusplus
 }
--- a/LEAF/Inc/leaf-sample.h
+++ /dev/null
@@ -1,125 +1,0 @@
-/*==============================================================================
-
-    leaf-sample.h
-    Created: 23 Jan 2019 11:22:09am
-    Author:  Mike Mulshine
-
-==============================================================================*/
-
-
-#ifndef LEAF_SAMPLE_H_INCLUDED
-#define LEAF_SAMPLE_H_INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-    
-//==============================================================================
- 
-#include "leaf-global.h"
-#include "leaf-math.h"
-    
-#include "leaf-utilities.h"
-    
-//==============================================================================
-    
-    typedef enum RecordMode
-    {
-        RecordOneShot = 0,
-        RecordLoop,
-        RecordModeNil
-    } RecordMode;
-    
-    typedef struct _tBuffer
-    {
-        float* buff;
-        
-        uint32_t idx;
-        uint32_t length;
-        
-        RecordMode mode;
-        
-        int active;
-        
-    } tBuffer;
-
-    void  tBuffer_init (tBuffer* const, uint32_t length);
-    void  tBuffer_free (tBuffer* const);
-    
-    void  tBuffer_tick (tBuffer* const, float sample);
-    
-    void  tBuffer_read(tBuffer* const, float* buff, uint32_t len);
-    
-    float tBuffer_get (tBuffer* const, int idx);
-    
-    void  tBuffer_record (tBuffer* const);
-    void  tBuffer_stop (tBuffer* const);
-    
-    void  tBuffer_setRecordMode (tBuffer* const, RecordMode mode);
-    
-    void  tBuffer_clear (tBuffer* const);
-    
-//==============================================================================
-    
-    typedef enum PlayMode
-    {
-        PlayNormal,
-        PlayLoop,
-        PlayBackAndForth,
-        PlayModeNil
-    } PlayMode;
-    
-    typedef struct _tSampler
-    {
-        tBuffer* samp;
-        
-        tRamp gain;
-        
-        float idx;
-        float inc;
-        float last;
-        float iinc;
-        int8_t dir;
-        int8_t flip;
-        int8_t bnf;
-        
-        int32_t start;
-        int32_t end;
-        uint32_t len;
-        uint32_t cfxlen;
-    
-        PlayMode mode;
-        int retrigger;
-        
-        int active;
-
-    } tSampler;
-    
-    void    tSampler_init      (tSampler* const, tBuffer* const);
-    void    tSampler_free      (tSampler* const);
-    
-    float   tSampler_tick      (tSampler* const);
-
-    void    tSampler_setSample (tSampler* const, tBuffer* s);
-    
-    void    tSampler_setMode   (tSampler* const, PlayMode mode);
-    
-    void    tSampler_play      (tSampler* const);
-    void    tSampler_stop      (tSampler* const);
-    
-    void    tSampler_setStart  (tSampler* const, int32_t start);
-    void    tSampler_setEnd    (tSampler* const, int32_t end);
-    
-    void    tSampler_setCrossfadeLength  (tSampler* const p, uint32_t length);
-    
-    void    tSampler_setRate   (tSampler* const, float rate);
-    
-//==============================================================================
-    
-#ifdef __cplusplus
-}
-#endif
-
-#endif // LEAF_SAMPLE_H_INCLUDED
-
-//==============================================================================
--- /dev/null
+++ b/LEAF/Inc/leaf-sampling.h
@@ -1,0 +1,124 @@
+/*==============================================================================
+
+leaf-sampling.h
+Created: 23 Jan 2019 11:22:09am
+Author:  Mike Mulshine
+
+==============================================================================*/
+
+
+#ifndef LEAF_SAMPLING_H_INCLUDED
+#define LEAF_SAMPLING_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//==============================================================================
+
+#include "leaf-global.h"
+#include "leaf-math.h"
+#include "leaf-envelopes.h"
+
+//==============================================================================
+
+typedef enum RecordMode
+{
+    RecordOneShot = 0,
+    RecordLoop,
+    RecordModeNil
+} RecordMode;
+
+typedef struct _tBuffer
+{
+    float* buff;
+    
+    uint32_t idx;
+    uint32_t length;
+    
+    RecordMode mode;
+    
+    int active;
+    
+} tBuffer;
+
+void  tBuffer_init (tBuffer* const, uint32_t length);
+void  tBuffer_free (tBuffer* const);
+
+void  tBuffer_tick (tBuffer* const, float sample);
+
+void  tBuffer_read(tBuffer* const, float* buff, uint32_t len);
+
+float tBuffer_get (tBuffer* const, int idx);
+
+void  tBuffer_record (tBuffer* const);
+void  tBuffer_stop (tBuffer* const);
+
+void  tBuffer_setRecordMode (tBuffer* const, RecordMode mode);
+
+void  tBuffer_clear (tBuffer* const);
+
+//==============================================================================
+
+typedef enum PlayMode
+{
+    PlayNormal,
+    PlayLoop,
+    PlayBackAndForth,
+    PlayModeNil
+} PlayMode;
+
+typedef struct _tSampler
+{
+    tBuffer* samp;
+    
+    tRamp gain;
+    
+    float idx;
+    float inc;
+    float last;
+    float iinc;
+    int8_t dir;
+    int8_t flip;
+    int8_t bnf;
+    
+    int32_t start;
+    int32_t end;
+    uint32_t len;
+    uint32_t cfxlen;
+
+    PlayMode mode;
+    int retrigger;
+    
+    int active;
+
+} tSampler;
+
+void    tSampler_init      (tSampler* const, tBuffer* const);
+void    tSampler_free      (tSampler* const);
+
+float   tSampler_tick      (tSampler* const);
+
+void    tSampler_setSample (tSampler* const, tBuffer* s);
+
+void    tSampler_setMode   (tSampler* const, PlayMode mode);
+
+void    tSampler_play      (tSampler* const);
+void    tSampler_stop      (tSampler* const);
+
+void    tSampler_setStart  (tSampler* const, int32_t start);
+void    tSampler_setEnd    (tSampler* const, int32_t end);
+
+void    tSampler_setCrossfadeLength  (tSampler* const p, uint32_t length);
+
+void    tSampler_setRate   (tSampler* const, float rate);
+
+//==============================================================================
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LEAF_SAMPLING_H_INCLUDED
+
+//==============================================================================
--- a/LEAF/Inc/leaf-string.h
+++ /dev/null
@@ -1,143 +1,0 @@
-/*
-  ==============================================================================
-
-    leaf-string.h
-    Created: 30 Nov 2018 10:41:55am
-    Author:  airship
-
-  ==============================================================================
-*/
-
-#ifndef LEAF_STRING_H_INCLUDED
-#define LEAF_STRING_H_INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-    
-//==============================================================================
-
-#include "leaf-global.h"
-#include "leaf-math.h"
-
-#include "leaf-delay.h"
-#include "leaf-filter.h"
-#include "leaf-oscillator.h"
-
-//==============================================================================
-
-/* Karplus Strong model */
-typedef struct _tPluck
-{
-    tDelayA     delayLine; // Allpass or Linear??  big difference...
-    tOneZero    loopFilter;
-    tOnePole    pickFilter;
-    tNoise      noise;
-    
-    float lastOut;
-    float loopGain;
-    float lastFreq;
-    
-    float sr;
-    
-} tPluck;
-
-void        tPluck_init          (tPluck*  const, float lowestFrequency); //float delayBuff[DELAY_LENGTH]);
-void        tPluck_free          (tPluck*  const);
-
-float       tPluck_tick          (tPluck*  const);
-
-// Pluck the string.
-void        tPluck_pluck         (tPluck*  const, float amplitude);
-
-// Start a note with the given frequency and amplitude.;
-void        tPluck_noteOn        (tPluck*  const, float frequency, float amplitude );
-
-// Stop a note with the given amplitude (speed of decay).
-void        tPluck_noteOff       (tPluck*  const, float amplitude );
-
-// Set instrument parameters for a particular frequency.
-void        tPluck_setFrequency  (tPluck*  const, float frequency );
-
-// Perform the control change specified by \e number and \e value (0.0 - 128.0).
-void        tPluck_controlChange (tPluck*  const, int number, float value);
-
-// tPluck Utilities.
-float       tPluck_getLastOut    (tPluck*  const);
-
-//==============================================================================
-    
-/* Stif Karplus Strong model */
-typedef struct _tStifKarp
-{
-    tDelayA  delayLine;
-    tDelayL combDelay;
-    tOneZero filter;
-    tNoise   noise;
-    tBiQuad  biquad[4];
-    
-    
-    
-    uint32_t length;
-    float loopGain;
-    float baseLoopGain;
-    float lastFrequency;
-    float lastLength;
-    float stretching;
-    float pluckAmplitude;
-    float pickupPosition;
-    
-    float lastOut;
-    
-} tStifKarp;
-
-typedef enum SKControlType
-{
-    SKPickPosition = 0,
-    SKStringDamping,
-    SKDetune,
-    SKControlTypeNil
-} SKControlType;
-
-void        tStifKarp_init               (tStifKarp* const, float lowestFrequency); // float delayBuff[2][DELAY_LENGTH]);
-void        tStifKarp_free               (tStifKarp* const);
-
-float       tStifKarp_tick               (tStifKarp*  const);
-
-// Pluck the string.
-void        tStifKarp_pluck              (tStifKarp*  const, float amplitude);
-
-// Start a note with the given frequency and amplitude.;
-void        tStifKarp_noteOn             (tStifKarp*  const, float frequency, float amplitude );
-
-// Stop a note with the given amplitude (speed of decay).
-void        tStifKarp_noteOff            (tStifKarp*  const, float amplitude );
-
-// Set instrument parameters for a particular frequency.
-void        tStifKarp_setFrequency       (tStifKarp*  const, float frequency );
-
-// Perform the control change specified by \e number and \e value (0.0 - 128.0).
-// Use SKPickPosition, SKStringDamping, or SKDetune for type.
-void        tStifKarp_controlChange      (tStifKarp*  const, SKControlType type, float value);
-
-// Set the stretch "factor" of the string (0.0 - 1.0).
-void        tStifKarp_setStretch         (tStifKarp*  const, float stretch );
-
-// Set the pluck or "excitation" position along the string (0.0 - 1.0).
-void        tStifKarp_setPickupPosition  (tStifKarp*  const, float position );
-
-// Set the base loop gain.
-void        tStifKarp_setBaseLoopGain    (tStifKarp*  const, float aGain );
-
-// tStifKarp utilities.
-float       tStifKarp_getLastOut         (tStifKarp*  const);
-
-//==============================================================================
-    
-#ifdef __cplusplus
-}
-#endif
-
-#endif // LEAF_STRING_H_INCLUDED
-
-//==============================================================================
--- a/LEAF/Inc/leaf-tables.h
+++ b/LEAF/Inc/leaf-tables.h
@@ -6,8 +6,8 @@
 
 ==============================================================================*/
 
-#ifndef LEAF_WAVETABLES_H_INCLUDED
-#define LEAF_WAVETABLES_H_INCLUDED
+#ifndef LEAF_TABLES_H_INCLUDED
+#define LEAF_TABLES_H_INCLUDED
 
 #ifdef __cplusplus
 extern "C" {
@@ -95,6 +95,6 @@
 }
 #endif
 
-#endif  // LEAF_WAVETABLES_H_INCLUDED
+#endif  // LEAF_TABLES_H_INCLUDED
 
 //==============================================================================
--- a/LEAF/Inc/leaf-utilities.h
+++ /dev/null
@@ -1,483 +1,0 @@
-/*
-  ==============================================================================
-
-    LEAFUtilities.h
-    Created: 20 Jan 2017 12:02:17pm
-    Author:  Michael R Mulshine
-
-  ==============================================================================
-*/
-
-#ifndef LEAFUTILITIES_H_INCLUDED
-#define LEAFUTILITIES_H_INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
-#include "leaf-math.h"
-#include "leaf-filter.h"
-#include "leaf-delay.h"
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
-// STACK implementation (fixed size)
-#define STACK_SIZE 128
-typedef struct _tStack
-{
-    int data[STACK_SIZE];
-    uint16_t pos;
-    uint16_t size;
-    uint16_t capacity;
-    oBool ordered;
-    
-} tStack;
-
-void    tStack_init                 (tStack* const);
-void    tStack_free                 (tStack* const);
-
-void    tStack_setCapacity          (tStack* const, uint16_t cap);
-int     tStack_addIfNotAlreadyThere (tStack* const, uint16_t item);
-void    tStack_add                  (tStack* const, uint16_t item);
-int     tStack_remove               (tStack* const, uint16_t item);
-void    tStack_clear                (tStack* const);
-int     tStack_first                (tStack* const);
-int     tStack_getSize              (tStack* const);
-int     tStack_contains             (tStack* const, uint16_t item);
-int     tStack_next                 (tStack* const);
-int     tStack_get                  (tStack* const, int which);
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
-/* Ramp */
-typedef struct _tRamp {
-    float inc;
-    float inv_sr_ms;
-    float minimum_time;
-    float curr,dest;
-    float time;
-    int samples_per_tick;
-    
-} tRamp;
-
-void    tRamp_init      (tRamp* const, float time, int samplesPerTick);
-void    tRamp_free      (tRamp* const);
-
-float   tRamp_tick      (tRamp* const);
-float   tRamp_sample    (tRamp* const);
-int     tRamp_setTime   (tRamp* const, float time);
-int     tRamp_setDest   (tRamp* const, float dest);
-int     tRamp_setVal    (tRamp* const, float val);
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
-/* Exponential Smoother */
-typedef struct _tExpSmooth {
-    float factor, oneminusfactor;
-    float curr,dest;
-
-} tExpSmooth;
-
-void    tExpSmooth_init      (tExpSmooth* const, float val, float factor);
-void    tExpSmooth_free      (tExpSmooth* const);
-
-float   tExpSmooth_tick      (tExpSmooth* const);
-float   tExpSmooth_sample    (tExpSmooth* const);
-int     tExpSmooth_setFactor   (tExpSmooth* const, float factor);
-int     tExpSmooth_setDest   (tExpSmooth* const, float dest);
-int     tExpSmooth_setVal    (tExpSmooth* const, float val);
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
-/* PowerEnvelopeFollower */
-typedef struct _tPwrFollow {
-    float factor, oneminusfactor;
-    float curr;
-
-} tPwrFollow;
-
-void    tPwrFollow_init      (tPwrFollow* const, float factor);
-void    tPwrFollow_free      (tPwrFollow* const);
-float   tPwrFollow_tick      (tPwrFollow* const, float input);
-float   tPwrFollow_sample    (tPwrFollow* const);
-int     tPwrFollow_setFactor   (tPwrFollow* const, float factor);
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
-//Reed Table - borrowed from STK
-typedef struct _tReedTable {
-    float offset, slope;
-} tReedTable;
-
-void    tReedTable_init      (tReedTable* const, float offset, float slope);
-void    tReedTable_free      (tReedTable* const);
-float   tReedTable_tick      (tReedTable* const, float input);
-float   tReedTable_tanh_tick     (tReedTable* const p, float input); //tanh softclip version of reed table - replacing the hard clip in original stk code
-void     tReedTable_setOffset   (tReedTable* const, float offset);
-void     tReedTable_setSlope (tReedTable* const, float slope);
-
-
-
-///
-/* Feedback leveller */
-// An auto VCA that you put into a feedback circuit to make it stay at the same level.
-// It can enforce level bidirectionally (amplifying and attenuating as needed) or
-// just attenutating. The former option allows for infinite sustain strings, for example, while
-// The latter option allows for decaying strings, which can never exceed
-// a specific level.
-
-typedef struct _tFBleveller {
-    float targetLevel;	// target power level
-    float strength;		// how strongly level difference affects the VCA
-    int	  mode;			// 0 for upwards limiting only, 1 for biderctional limiting
-    float curr;
-    tPwrFollow pwrFlw;	// internal power follower needed for level tracking
-
-} tFBleveller;
-
-void    tFBleveller_init      (tFBleveller* const, float targetLevel, float factor, float strength, int mode);
-void    tFBleveller_free      (tFBleveller* const);
-
-float   tFBleveller_tick      (tFBleveller* const, float input);
-float   tFBleveller_sample    (tFBleveller* const);
-int     tFBleveller_setTargetLevel   (tFBleveller* const, float TargetLevel);
-int     tFBleveller_setFactor   (tFBleveller* const, float factor);
-int     tFBleveller_setMode   (tFBleveller* const, int mode); // 0 for upwards limiting only, 1 for biderctional limiting
-int     tFBleveller_setStrength   (tFBleveller* const, float strength);
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
-/* Simple Living String */
-typedef struct _tSimpleLivingString {
-	float freq, waveLengthInSamples;		// the frequency of the string, determining delay length
-	float dampFreq;	// frequency for the bridge LP filter, in Hz
-	float decay; // amplitude damping factor for the string (only active in mode 0)
-	float levMode;
-	float curr;
-	tDelayL delayLine;
-	tOnePole bridgeFilter;
-	tHighpass DCblocker;
-	tFBleveller fbLev;
-	tExpSmooth wlSmooth;
-} tSimpleLivingString;
-
-void    tSimpleLivingString_init      (tSimpleLivingString* const, float freq, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode);
-void    tSimpleLivingString_free      (tSimpleLivingString* const);
-float   tSimpleLivingString_tick      (tSimpleLivingString* const, float input);
-float   tSimpleLivingString_sample    (tSimpleLivingString* const);
-int     tSimpleLivingString_setFreq   			(tSimpleLivingString* const, float freq);
-int     tSimpleLivingString_setWaveLength		(tSimpleLivingString* const, float waveLength); // in samples
-int     tSimpleLivingString_setDampFreq   		(tSimpleLivingString* const, float dampFreq);
-int     tSimpleLivingString_setDecay     		(tSimpleLivingString* const, float decay); // should be near 1.0
-int     tSimpleLivingString_setTargetLev		(tSimpleLivingString* const, float targetLev);
-int     tSimpleLivingString_setLevSmoothFactor  (tSimpleLivingString* const, float levSmoothFactor);
-int     tSimpleLivingString_setLevStrength		(tSimpleLivingString* const, float levStrength);
-int     tSimpleLivingString_setLevMode		(tSimpleLivingString* const, int levMode);
-
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
-/* Living String */
-typedef struct _tLivingString {
-	float freq, waveLengthInSamples;		// the frequency of the whole string, determining delay length
-	float pickPos;	// the pick position, dividing the string in two, in ratio
-	float prepIndex;	// the amount of pressure on the pickpoint of the string (near 0=soft obj, near 1=hard obj)
-	float dampFreq;	// frequency for the bridge LP filter, in Hz
-	float decay; // amplitude damping factor for the string (only active in mode 0)
-	float levMode;
-	float curr;
-	tDelayL delLF,delUF,delUB,delLB;	// delay for lower/upper/forward/backward part of the waveguide model
-	tOnePole bridgeFilter, nutFilter, prepFilterU, prepFilterL;
-	tHighpass DCblockerL, DCblockerU;
-	tFBleveller fbLevU, fbLevL;
-	tExpSmooth wlSmooth, ppSmooth;
-} tLivingString;
-
-void    tLivingString_init      (tLivingString* const, float freq, float pickPos, float prepIndex, float dampFreq, float decay,
-												float targetLev, float levSmoothFactor, float levStrength, int levMode);
-void    tLivingString_free      (tLivingString* const);
-float   tLivingString_tick      (tLivingString* const, float input);
-float   tLivingString_sample    (tLivingString* const);
-int     tLivingString_setFreq   			(tLivingString* const, float freq);
-int     tLivingString_setWaveLength			(tLivingString* const, float waveLength); // in samples
-int     tLivingString_setPickPos   			(tLivingString* const, float pickPos);
-int     tLivingString_setPrepIndex 			(tLivingString* const, float prepIndex);
-int     tLivingString_setDampFreq   		(tLivingString* const, float dampFreq);
-int     tLivingString_setDecay     			(tLivingString* const, float decay); // should be near 1.0
-int     tLivingString_setTargetLev			(tLivingString* const, float targetLev);
-int     tLivingString_setLevSmoothFactor  	(tLivingString* const, float levSmoothFactor);
-int     tLivingString_setLevStrength		(tLivingString* const, float levStrength);
-int     tLivingString_setLevMode			(tLivingString* const, int levMode);
-
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
-/* Compressor */
-typedef struct _tCompressor
-{
-    float tauAttack, tauRelease;
-    float T, R, W, M; // Threshold, compression Ratio, decibel Width of knee transition, decibel Make-up gain
-    
-    float x_G[2], y_G[2], x_T[2], y_T[2];
-    
-    oBool isActive;
-
-}tCompressor;
-
-void    tCompressor_init    (tCompressor* const);
-void    tCompressor_free    (tCompressor* const);
-float   tCompressor_tick    (tCompressor* const, float input);
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
-/* Attack-Decay envelope */
-typedef struct _tEnvelope {
-    
-    const float *exp_buff;
-    const float *inc_buff;
-    uint32_t buff_size;
-    
-    float next;
-    
-    float attackInc, decayInc, rampInc;
-    
-    oBool inAttack, inDecay, inRamp;
-    
-    oBool loop;
-    
-    float gain, rampPeak;
-    
-    float attackPhase, decayPhase, rampPhase;
-    
-} tEnvelope;
-
-void    tEnvelope_init      (tEnvelope* const, float attack, float decay, oBool loop);
-void    tEnvelope_free      (tEnvelope* const);
-
-float   tEnvelope_tick      (tEnvelope* const);
-int     tEnvelope_setAttack (tEnvelope*  const, float attack);
-int     tEnvelope_setDecay  (tEnvelope*  const, float decay);
-int     tEnvelope_loop      (tEnvelope*  const, oBool loop);
-int     tEnvelope_on        (tEnvelope*  const, float velocity);
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
-/* ADSR */
-typedef struct _tADSR
-{
-    const float *exp_buff;
-    const float *inc_buff;
-    uint32_t buff_size;
-    
-    float next;
-    
-    float attackInc, decayInc, releaseInc, rampInc;
-    
-    oBool inAttack, inDecay, inSustain, inRelease, inRamp;
-    
-    float sustain, gain, rampPeak, releasePeak;
-    
-    float attackPhase, decayPhase, releasePhase, rampPhase;
-
-} tADSR;
-
-void    tADSR_init      (tADSR*  const, float attack, float decay, float sustain, float release);
-void    tADSR_free      (tADSR*  const);
-
-float   tADSR_tick      (tADSR*  const);
-int     tADSR_setAttack (tADSR*  const, float attack);
-int     tADSR_setDecay  (tADSR*  const, float decay);
-int     tADSR_setSustain(tADSR*  const, float sustain);
-int     tADSR_setRelease(tADSR*  const, float release);
-int     tADSR_on        (tADSR*  const, float velocity);
-int     tADSR_off       (tADSR*  const);
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
-/* Envelope Follower */
-typedef struct _tEnvelopeFollower
-{
-    float y;
-    float a_thresh;
-    float d_coeff;
-    
-} tEnvelopeFollower;
-
-void    tEnvelopeFollower_init           (tEnvelopeFollower*  const, float attackThreshold, float decayCoeff);
-void    tEnvelopeFollower_free           (tEnvelopeFollower*  const);
-
-float   tEnvelopeFollower_tick           (tEnvelopeFollower*  const, float x);
-int     tEnvelopeFollower_decayCoeff     (tEnvelopeFollower*  const, float decayCoeff);
-int     tEnvelopeFollower_attackThresh   (tEnvelopeFollower*  const, float attackThresh);
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
-/* tAtkDtk */
-#define DEFBLOCKSIZE 1024
-#define DEFTHRESHOLD 6
-#define DEFATTACK    10
-#define DEFRELEASE    10
-
-typedef struct _tAtkDtk
-{
-    float env;
-    
-    //Attack & Release times in msec
-    int atk;
-    int rel;
-    
-    //Attack & Release coefficients based on times
-    float atk_coeff;
-    float rel_coeff;
-    
-    int blocksize;
-    int samplerate;
-    
-    //RMS amplitude of previous block - used to decide if attack is present
-    float prevAmp;
-    
-    float threshold;
-} tAtkDtk;
-
-void    tAtkDtk_init            (tAtkDtk* const, int blocksize);
-void    tAtkDtk_init_expanded   (tAtkDtk* const, int blocksize, int atk, int rel);
-void    tAtkDtk_free            (tAtkDtk* const);
-
-// set expected input blocksize
-void    tAtkDtk_setBlocksize    (tAtkDtk* const, int size);
-
-// change atkDetector sample rate
-void    tAtkDtk_setSamplerate   (tAtkDtk* const, int inRate);
-
-// set attack time and coeff
-void    tAtkDtk_setAtk          (tAtkDtk* const, int inAtk);
-
-// set release time and coeff
-void    tAtkDtk_setRel          (tAtkDtk* const, int inRel);
-
-// set level above which values are identified as attacks
-void    tAtkDtk_setThreshold    (tAtkDtk* const, float thres);
-
-// find largest transient in input block, return index of attack
-int     tAtkDtk_detect          (tAtkDtk* const, float *in);
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
-// ENV~ from PD, modified for LEAF
-#define MAXOVERLAP 32
-#define INITVSTAKEN 64
-#define ENV_WINDOW_SIZE 1024
-#define ENV_HOP_SIZE 256
-
-typedef struct _tEnv
-{
-    float buf[ENV_WINDOW_SIZE + INITVSTAKEN];
-    uint16_t x_phase;                    /* number of points since last output */
-    uint16_t x_period;                   /* requested period of output */
-    uint16_t x_realperiod;               /* period rounded up to vecsize multiple */
-    uint16_t x_npoints;                  /* analysis window size in samples */
-    float x_result;                 /* result to output */
-    float x_sumbuf[MAXOVERLAP];     /* summing buffer */
-    float x_f;
-    uint16_t windowSize, hopSize, blockSize;
-    uint16_t x_allocforvs;               /* extra buffer for DSP vector size */
-} tEnv;
-
-void    tEnv_init           (tEnv* const, int windowSize, int hopSize, int blockSize);
-void    tEnv_free           (tEnv* const);
-float   tEnv_tick           (tEnv* const);
-void    tEnv_processBlock   (tEnv* const, float* in);
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
-/* tSOLAD : pitch shifting algorithm that underlies tPitchShifter etc */
-#define LOOPSIZE (2048*2)      // (4096*2) // loop size must be power of two
-#define LOOPMASK (LOOPSIZE - 1)
-#define PITCHFACTORDEFAULT 1.0f
-#define INITPERIOD 64.0f
-#define MAXPERIOD (float)((LOOPSIZE - w->blocksize) * 0.8f)
-#define MINPERIOD 8.0f
-    
-typedef struct _tSOLAD
-{
-    uint16_t timeindex;              // current reference time, write index
-    uint16_t blocksize;              // signal input / output block size
-    float pitchfactor;        // pitch factor between 0.25 and 4
-    float readlag;            // read pointer's lag behind write pointer
-    float period;             // period length in input signal
-    float jump;               // read pointer jump length and direction
-    float xfadelength;        // crossfade length expressed at input sample rate
-    float xfadevalue;         // crossfade phase and value
-    
-    float* delaybuf;
-    
-} tSOLAD;
-
-void    tSOLAD_init             (tSOLAD* const);
-void    tSOLAD_free             (tSOLAD* const);
-
-// send one block of input samples, receive one block of output samples
-void    tSOLAD_ioSamples        (tSOLAD *w, float* in, float* out, int blocksize);
-
-// set periodicity analysis data
-void    tSOLAD_setPeriod        (tSOLAD *w, float period);
-
-// set pitch factor between 0.25 and 4
-void    tSOLAD_setPitchFactor   (tSOLAD *w, float pitchfactor);
-
-// force readpointer lag
-void    tSOLAD_setReadLag       (tSOLAD *w, float readlag);
-
-// reset state variables
-void    tSOLAD_resetState       (tSOLAD *w);
-    
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
-// tSNAC: period detector
-#define SNAC_FRAME_SIZE 1024           // default analysis framesize // should be the same as (or smaller than?) PS_FRAME_SIZE
-#define DEFOVERLAP 1                // default overlap
-#define DEFBIAS 0.2f        // default bias
-#define DEFMINRMS 0.003f   // default minimum RMS
-#define SEEK 0.85f       // seek-length as ratio of framesize
-
-typedef struct _tSNAC
-{
-    float* inputbuf;
-    float* processbuf;
-    float* spectrumbuf;
-    float* biasbuf;
-    uint16_t timeindex;
-    uint16_t framesize;
-    uint16_t overlap;
-    uint16_t periodindex;
-    
-    float periodlength;
-    float fidelity;
-    float biasfactor;
-    float minrms;
-    
-} tSNAC;
-
-void    tSNAC_init          (tSNAC* const, int overlaparg);    // constructor
-void    tSNAC_free          (tSNAC* const);    // destructor
-
-void    tSNAC_ioSamples     (tSNAC *s, float *in, float *out, int size);
-void    tSNAC_setOverlap    (tSNAC *s, int lap);
-void    tSNAC_setBias       (tSNAC *s, float bias);
-void    tSNAC_setMinRMS     (tSNAC *s, float rms);
-
-/*To get freq, perform SAMPLE_RATE/snac_getperiod() */
-float   tSNAC_getPeriod     (tSNAC *s);
-float   tSNAC_getfidelity   (tSNAC *s);
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-    
-#ifdef __cplusplus
-}
-#endif
-
-#endif  // LEAFUTILITIES_H_INCLUDED
-
-
--- a/LEAF/Inc/leaf-vocoder.h
+++ /dev/null
@@ -1,89 +1,0 @@
-/*==============================================================================
-
-    leaf-vocoder.h
-    Created: 20 Jan 2017 12:01:54pm
-    Author:  Michael R Mulshine
-
-==============================================================================*/
-
-#ifndef LEAF_VOCODER_H_INCLUDED
-#define LEAF_VOCODER_H_INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//==============================================================================
-
-#include "leaf-global.h"
-#include "leaf-math.h"
-
-//==============================================================================
-
-/* tTalkbox */
-#define NUM_TALKBOX_PARAM 4
-
-typedef struct _tTalkbox
-{
-    float param[NUM_TALKBOX_PARAM];
-    
-    int bufsize;
-    float* car0;
-    float* car1;
-    float* window;
-    float* buf0;
-    float* buf1;
-    
-    float emphasis;
-    int32_t K, N, O, pos;
-    float wet, dry, FX;
-    float d0, d1, d2, d3, d4;
-    float u0, u1, u2, u3, u4;
-    
-} tTalkbox;
-
-void        tTalkbox_init        (tTalkbox* const, int bufsize);
-void        tTalkbox_free        (tTalkbox* const);
-float       tTalkbox_tick        (tTalkbox* const, float synth, float voice);
-void        tTalkbox_update      (tTalkbox* const);
-void        tTalkbox_suspend     (tTalkbox* const);
-void        tTalkbox_lpcDurbin   (float *r, int p, float *k, float *g);
-void        tTalkbox_lpc         (float *buf, float *car, int32_t n, int32_t o);
-void		tTalkbox_setQuality  (tTalkbox* const, float quality);
-
-//==============================================================================
-
-/* tVocoder */
-#define NUM_VOCODER_PARAM 8
-#define NBANDS 16
-
-typedef struct _tVocoder
-{
-    float param[NUM_VOCODER_PARAM];
-    
-    float gain;         //output level
-    float thru, high;   //hf thru
-    float kout;         //downsampled output
-    int32_t  kval;      //downsample counter
-    int32_t  nbnd;      //number of bands
-    
-    //filter coeffs and buffers - seems it's faster to leave this global than make local copy
-    float f[NBANDS][13]; //[0-8][0 1 2 | 0 1 2 3 | 0 1 2 3 | val rate]
-    
-} tVocoder;
-
-void        tVocoder_init        (tVocoder* const);
-void        tVocoder_free        (tVocoder* const);
-float       tVocoder_tick        (tVocoder* const, float synth, float voice);
-void        tVocoder_update      (tVocoder* const);
-void        tVocoder_suspend     (tVocoder* const);
-
-//==============================================================================
-
-#ifdef __cplusplus
-}
-#endif
-        
-#endif  // LEAF_VOCODER_H_INCLUDED
-
-//==============================================================================
--- a/LEAF/Inc/leaf-wavefolder.h
+++ /dev/null
@@ -1,48 +1,0 @@
-/*==============================================================================
-
-    leaf-wavefolder.h
-    Created: 30 Nov 2018 11:57:05am
-    Author:  airship
-
-==============================================================================*/
-
-#ifndef LEAF_WAVEFOLDER_H_INCLUDED
-#define LEAF_WAVEFOLDER_H_INCLUDED
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//==============================================================================
-
-#include "leaf-global.h"
-#include "leaf-math.h"
-
-//==============================================================================
-
-/* tLockhartWavefolder */
-
-typedef struct _tLockhartWavefolder
-{
-    double Ln1;
-    double Fn1;
-    float xn1;
-    
-} tLockhartWavefolder;
-
-void    tLockhartWavefolder_init    (tLockhartWavefolder* const);
-void    tLockhartWavefolder_free    (tLockhartWavefolder* const);
-
-float   tLockhartWavefolder_tick    (tLockhartWavefolder* const, float samp);
-
-    
-//==============================================================================
-    
-#ifdef __cplusplus
-}
-#endif
-
-#endif // LEAF_WAVEFOLDER_H_INCLUDED
-
-//==============================================================================
--- a/LEAF/Src/leaf-808.c
+++ /dev/null
@@ -1,460 +1,0 @@
-/*==============================================================================
-
-    leaf-808.c
-    Created: 30 Nov 2018 10:24:21am
-    Author:  airship
-
-==============================================================================*/
-
-#if _WIN32 || _WIN64
-
-#include "..\Inc\leaf-808.h"
-
-#else
-
-#include "../Inc/leaf-808.h"
-
-#endif
-
-// ----------------- COWBELL ----------------------------//
-
-void t808Cowbell_init(t808Cowbell* const cowbell, int useStick) {
-    
-    tSquare_init(&cowbell->p[0]);
-    tSquare_setFreq(&cowbell->p[0], 540.0f);
-    
-    tSquare_init(&cowbell->p[1]);
-    tSquare_setFreq(&cowbell->p[1], 1.48148f * 540.0f);
-    
-    cowbell->oscMix = 0.5f;
-    
-    tSVF_init(&cowbell->bandpassOsc, SVFTypeBandpass, 2500, 1.0f);
-    
-    tSVF_init(&cowbell->bandpassStick, SVFTypeBandpass, 1800, 1.0f);
-    
-    tEnvelope_init(&cowbell->envGain, 5.0f, 100.0f, OFALSE);
-    
-    tEnvelope_init(&cowbell->envFilter, 5.0, 100.0f, OFALSE);
-    
-    tHighpass_init(&cowbell->highpass, 1000.0f);
-    
-    tNoise_init(&cowbell->stick, WhiteNoise);
-    
-    tEnvelope_init(&cowbell->envStick, 5.0f, 5.0f, 0);
-    
-    cowbell->useStick = useStick;
-}
-
-void t808Cowebell_free(t808Cowbell* const cowbell)
-{
-    tSquare_free(&cowbell->p[0]);
-    tSquare_free(&cowbell->p[1]);
-    tSVF_free(&cowbell->bandpassOsc);
-    tSVF_free(&cowbell->bandpassStick);
-    tEnvelope_free(&cowbell->envGain);
-    tEnvelope_free(&cowbell->envFilter);
-    tHighpass_free(&cowbell->highpass);
-    tNoise_free(&cowbell->stick);
-    tEnvelope_free(&cowbell->envStick);
-}
-
-void t808Cowbell_on(t808Cowbell* const cowbell, float vel)
-{
-    tEnvelope_on(&cowbell->envGain, vel);
-    
-    if (cowbell->useStick)
-        tEnvelope_on(&cowbell->envStick,vel);
-}
-
-float t808Cowbell_tick(t808Cowbell* const cowbell) {
-    
-    float sample = 0.0f;
-    
-    // Mix oscillators.
-    sample = (cowbell->oscMix * tSquare_tick(&cowbell->p[0])) + ((1.0f-cowbell->oscMix) * tSquare_tick(&cowbell->p[1]));
-    
-    // Filter dive and filter.
-    tSVF_setFreq(&cowbell->bandpassOsc, cowbell->filterCutoff + 1000.0f * tEnvelope_tick(&cowbell->envFilter));
-    sample = tSVF_tick(&cowbell->bandpassOsc,sample);
-    
-    sample *= (0.9f * tEnvelope_tick(&cowbell->envGain));
-    
-    if (cowbell->useStick)
-        sample += (0.1f * tEnvelope_tick(&cowbell->envStick) * tSVF_tick(&cowbell->bandpassStick, tNoise_tick(&cowbell->stick)));
-
-    
-    sample = tHighpass_tick(&cowbell->highpass, sample);
-    
-    return sample;
-}
-
-void t808Cowbell_setDecay(t808Cowbell* const cowbell, float decay)
-{
-    tEnvelope_setDecay(&cowbell->envGain,decay);
-}
-
-void t808Cowbell_setHighpassFreq(t808Cowbell *cowbell, float freq)
-{
-    tHighpass_setFreq(&cowbell->highpass,freq);
-}
-
-void t808Cowbell_setBandpassFreq(t808Cowbell* const cowbell, float freq)
-{
-    cowbell->filterCutoff = freq;
-}
-
-void t808Cowbell_setFreq(t808Cowbell* const cowbell, float freq)
-{
-    
-    tSquare_setFreq(&cowbell->p[0],freq);
-    tSquare_setFreq(&cowbell->p[1],1.48148f*freq);
-}
-
-void t808Cowbell_setOscMix(t808Cowbell* const cowbell, float oscMix)
-{
-    cowbell->oscMix = oscMix;
-}
-
-void t808Cowbell_setStick(t808Cowbell* const cowbell, int useStick)
-{
-    cowbell->useStick = useStick;
-}
-
-// ----------------- HIHAT ----------------------------//
-
-void t808Hihat_init(t808Hihat* const hihat)
-{
-    for (int i = 0; i < 6; i++)
-    {
-        tSquare_init(&hihat->p[i]);
-    }
-    
-    tNoise_init(&hihat->stick, PinkNoise);
-    tNoise_init(&hihat->n, WhiteNoise);
-    
-    // need to fix SVF to be generic
-    tSVF_init(&hihat->bandpassStick, SVFTypeBandpass,2500.0f,1.2f);
-    tSVF_init(&hihat->bandpassOsc, SVFTypeBandpass,3500.0f,0.3f);
-    
-    tEnvelope_init(&hihat->envGain, 0.0f, 50.0f, OFALSE);
-    tEnvelope_init(&hihat->envStick, 0.0f, 7.0f, OFALSE);
-    
-    
-    tHighpass_init(&hihat->highpass, 7000.0f);
-    
-    hihat->freq = 40.0f;
-    hihat->stretch = 0.0f;
-    
-    tSquare_setFreq(&hihat->p[0], 2.0f * hihat->freq);
-    tSquare_setFreq(&hihat->p[1], 3.00f * hihat->freq);
-    tSquare_setFreq(&hihat->p[2], 4.16f * hihat->freq);
-    tSquare_setFreq(&hihat->p[3], 5.43f * hihat->freq);
-    tSquare_setFreq(&hihat->p[4], 6.79f * hihat->freq);
-    tSquare_setFreq(&hihat->p[5], 8.21f * hihat->freq);
-}
-
-void t808Hihat_free(t808Hihat* const hihat)
-{
-    for (int i = 0; i < 6; i++)
-    {
-        tSquare_free(&hihat->p[i]);
-    }
-    
-    tNoise_free(&hihat->stick);
-    tNoise_free(&hihat->n);
-    
-    // need to fix SVF to be generic
-    tSVF_free(&hihat->bandpassStick);
-    tSVF_free(&hihat->bandpassOsc);
-    tEnvelope_free(&hihat->envGain);
-    tEnvelope_free(&hihat->envStick);
-    
-    tHighpass_free(&hihat->highpass);
-}
-
-void t808Hihat_on(t808Hihat* const hihat, float vel) {
-    
-    tEnvelope_on(&hihat->envGain, vel);
-    tEnvelope_on(&hihat->envStick, vel);
-    
-}
-
-void t808Hihat_setOscNoiseMix(t808Hihat* const hihat, float oscNoiseMix) {
-    
-    hihat->oscNoiseMix = oscNoiseMix;
-    
-}
-
-float t808Hihat_tick(t808Hihat* const hihat) {
-    
-    float sample = 0.0f;
-    float gainScale = 0.1666f;
-    
-
-    float myNoise = tNoise_tick(&hihat->n);
-
-	tSquare_setFreq(&hihat->p[0], ((2.0f + hihat->stretch) * hihat->freq));
-	tSquare_setFreq(&hihat->p[1], ((3.00f + hihat->stretch) * hihat->freq));
-	tSquare_setFreq(&hihat->p[2], ((4.16f + hihat->stretch) * hihat->freq));
-	tSquare_setFreq(&hihat->p[3], ((5.43f + hihat->stretch) * hihat->freq));
-	tSquare_setFreq(&hihat->p[4], ((6.79f + hihat->stretch) * hihat->freq));
-	tSquare_setFreq(&hihat->p[5], ((8.21f + hihat->stretch) * hihat->freq));
-
-    for (int i = 0; i < 6; i++)
-    {
-        sample += tSquare_tick(&hihat->p[i]);
-    }
-    
-    sample *= gainScale;
-    
-    sample = (hihat->oscNoiseMix * sample) + ((1.0f-hihat->oscNoiseMix) * myNoise);
-    
-    sample = tSVF_tick(&hihat->bandpassOsc, sample);
-    
-    float myGain = tEnvelope_tick(&hihat->envGain);
-    sample *= (myGain*myGain);//square the output gain envelope
-    sample = tHighpass_tick(&hihat->highpass, sample);
-    sample += ((0.5f * tEnvelope_tick(&hihat->envStick)) * tSVF_tick(&hihat->bandpassStick, tNoise_tick(&hihat->stick)));
-    sample = tanhf(sample * 2.0f);
-
-    return sample;
-}
-
-void t808Hihat_setDecay(t808Hihat* const hihat, float decay)
-{
-    tEnvelope_setDecay(&hihat->envGain,decay);
-}
-
-void t808Hihat_setHighpassFreq(t808Hihat* const hihat, float freq)
-{
-    tHighpass_setFreq(&hihat->highpass,freq);
-}
-
-void t808Hihat_setStretch(t808Hihat* const hihat, float stretch)
-{
-    hihat->stretch = stretch;
-}
-
-void t808Hihat_setFM(t808Hihat* const hihat, float FM_amount)
-{
-    hihat->FM_amount = FM_amount;
-}
-
-void t808Hihat_setOscBandpassFreq(t808Hihat* const hihat, float freq)
-{
-    tSVF_setFreq(&hihat->bandpassOsc,freq);
-}
-
-void t808Hihat_setOscBandpassQ(t808Hihat* const hihat, float Q)
-{
-    tSVF_setQ(&hihat->bandpassOsc,Q);
-}
-
-void t808Hihat_setStickBandPassFreq(t808Hihat* const hihat, float freq)
-{
-    tSVF_setFreq(&hihat->bandpassStick,freq);
-}
-
-void t808Hihat_setStickBandPassQ(t808Hihat* const hihat, float Q)
-{
-    tSVF_setQ(&hihat->bandpassStick,Q);
-}
-
-
-
-void t808Hihat_setOscFreq(t808Hihat* const hihat, float freq)
-{
-		hihat->freq = freq;
-}
-
-// ----------------- SNARE ----------------------------//
-
-void t808Snare_init(t808Snare* const snare)
-{
-    float ratio[2] = {1.0, 1.5};
-    for (int i = 0; i < 2; i++)
-    {
-        tTriangle_init(&snare->tone[i]);
-        
-        tTriangle_setFreq(&snare->tone[i], ratio[i] * 400.0f);
-        tSVF_init(&snare->toneLowpass[i], SVFTypeLowpass, 4000, 1.0f);
-        tEnvelope_init(&snare->toneEnvOsc[i], 0.0f, 50.0f, OFALSE);
-        tEnvelope_init(&snare->toneEnvGain[i], 1.0f, 150.0f, OFALSE);
-        tEnvelope_init(&snare->toneEnvFilter[i], 1.0f, 2000.0f, OFALSE);
-        
-        snare->toneGain[i] = 0.5f;
-    }
-    
-    snare->tone1Freq = ratio[0] * 100.0f;
-    snare->tone2Freq = ratio[1] * 100.0f;
-    snare->noiseFilterFreq = 3000.0f;
-    tNoise_init(&snare->noiseOsc, WhiteNoise);
-    tSVF_init(&snare->noiseLowpass, SVFTypeLowpass, 12000.0f, 0.8f);
-    tEnvelope_init(&snare->noiseEnvGain, 0.0f, 100.0f, OFALSE);
-    tEnvelope_init(&snare->noiseEnvFilter, 0.0f, 1000.0f, OFALSE);
-    snare->noiseGain = 1.0f;
-}
-
-void        t808Snare_free                  (t808Snare* const snare)
-{
-    for (int i = 0; i < 2; i++)
-    {
-        tTriangle_free(&snare->tone[i]);
-        tSVF_free(&snare->toneLowpass[i]);
-        tEnvelope_free(&snare->toneEnvOsc[i]);
-        tEnvelope_free(&snare->toneEnvGain[i]);
-        tEnvelope_free(&snare->toneEnvFilter[i]);
-    }
-    
-    
-    tNoise_free(&snare->noiseOsc);
-    tSVF_free(&snare->noiseLowpass);
-    tEnvelope_free(&snare->noiseEnvGain);
-    tEnvelope_free(&snare->noiseEnvFilter);
-}
-
-void t808Snare_on(t808Snare* const snare, float vel)
-{
-    for (int i = 0; i < 2; i++)
-    {
-        tEnvelope_on(&snare->toneEnvOsc[i], vel);
-        tEnvelope_on(&snare->toneEnvGain[i], vel);
-        tEnvelope_on(&snare->toneEnvFilter[i], vel);
-    }
-    
-    tEnvelope_on(&snare->noiseEnvGain, vel);
-    tEnvelope_on(&snare->noiseEnvFilter, vel);
-}
-
-void t808Snare_setTone1Freq(t808Snare* const snare, float freq)
-{
-    snare->tone1Freq = freq;
-    tTriangle_setFreq(&snare->tone[0], freq);
-    
-}
-
-void t808Snare_setTone2Freq(t808Snare* const snare, float freq)
-{
-    snare->tone2Freq = freq;
-    tTriangle_setFreq(&snare->tone[1],freq);
-}
-
-void t808Snare_setTone1Decay(t808Snare* const snare, float decay)
-{
-    tEnvelope_setDecay(&snare->toneEnvGain[0],decay);
-}
-
-void t808Snare_setTone2Decay(t808Snare* const snare, float decay)
-{
-    tEnvelope_setDecay(&snare->toneEnvGain[1],decay);
-}
-
-void t808Snare_setNoiseDecay(t808Snare* const snare, float decay)
-{
-    tEnvelope_setDecay(&snare->noiseEnvGain,decay);
-}
-
-void t808Snare_setToneNoiseMix(t808Snare* const snare, float toneNoiseMix)
-{
-    snare->toneNoiseMix = toneNoiseMix;
-}
-
-void t808Snare_setNoiseFilterFreq(t808Snare* const snare, float noiseFilterFreq)
-{
-    snare->noiseFilterFreq = noiseFilterFreq;
-}
-
-void t808Snare_setNoiseFilterQ(t808Snare* const snare, float noiseFilterQ)
-{
-    tSVF_setQ(&snare->noiseLowpass, noiseFilterQ);
-}
-
-static float tone[2];
-
-float t808Snare_tick(t808Snare* const snare)
-{
-    for (int i = 0; i < 2; i++)
-    {
-        tTriangle_setFreq(&snare->tone[i], snare->tone1Freq + (20.0f * tEnvelope_tick(&snare->toneEnvOsc[i])));
-        tone[i] = tTriangle_tick(&snare->tone[i]);
-        
-        tSVF_setFreq(&snare->toneLowpass[i], 2000.0f + (500.0f * tEnvelope_tick(&snare->toneEnvFilter[i])));
-        tone[i] = tSVF_tick(&snare->toneLowpass[i], tone[i]) * tEnvelope_tick(&snare->toneEnvGain[i]);
-    }
-    
-    float noise = tNoise_tick(&snare->noiseOsc);
-    tSVF_setFreq(&snare->noiseLowpass, snare->noiseFilterFreq + (1000.0f * tEnvelope_tick(&snare->noiseEnvFilter)));
-    noise = tSVF_tick(&snare->noiseLowpass, noise) * tEnvelope_tick(&snare->noiseEnvGain);
-    
-    float sample = (snare->toneNoiseMix)*(tone[0] * snare->toneGain[0] + tone[1] * snare->toneGain[1]) + (1.0f-snare->toneNoiseMix) * (noise * snare->noiseGain);
-    sample = tanhf(sample * 2.0f);
-    return sample;
-}
-
-// ----------------- KICK ----------------------------//
-
-void        t808Kick_init        			(t808Kick* const kick)
-{
-	tCycle_init(&kick->tone);
-	kick->toneInitialFreq = 40.0f;
-	kick->sighAmountInHz = 7.0f;
-	kick->chirpRatioMinusOne = 3.3f;
-	tCycle_setFreq(&kick->tone, 50.0f);
-	tSVF_init(&kick->toneLowpass, SVFTypeLowpass, 2000.0f, 0.5f);
-	tEnvelope_init(&kick->toneEnvOscChirp, 0.0f, 20.0f, OFALSE);
-	tEnvelope_init(&kick->toneEnvOscSigh, 0.0f, 2500.0f, OFALSE);
-	tEnvelope_init(&kick->toneEnvGain, 0.0f, 800.0f, OFALSE);
-	tNoise_init(&kick->noiseOsc, PinkNoise);
-	tEnvelope_init(&kick->noiseEnvGain, 0.0f, 1.0f, OFALSE);
-	kick->noiseGain = 0.3f;
-}
-
-void        t808Kick_free                  (t808Kick* const kick)
-{
-	tCycle_free(&kick->tone);
-	tSVF_free(&kick->toneLowpass);
-	tEnvelope_free(&kick->toneEnvOscChirp);
-	tEnvelope_free(&kick->toneEnvOscSigh);
-	tEnvelope_free(&kick->toneEnvGain);
-	tNoise_free(&kick->noiseOsc);
-	tEnvelope_free(&kick->noiseEnvGain);
-}
-
-float       t808Kick_tick                  (t808Kick* const kick)
-{
-	tCycle_setFreq(&kick->tone, (kick->toneInitialFreq * (1.0f + (kick->chirpRatioMinusOne * tEnvelope_tick(&kick->toneEnvOscChirp)))) + (kick->sighAmountInHz * tEnvelope_tick(&kick->toneEnvOscSigh)));
-	float sample = tCycle_tick(&kick->tone) * tEnvelope_tick(&kick->toneEnvGain);
-	sample+= tNoise_tick(&kick->noiseOsc) * tEnvelope_tick(&kick->noiseEnvGain);
-	//add distortion here
-	sample = tSVF_tick(&kick->toneLowpass, sample);
-	return sample;
-}
-
-void        t808Kick_on                    (t808Kick* const kick, float vel)
-{
-	tEnvelope_on(&kick->toneEnvOscChirp, vel);
-	tEnvelope_on(&kick->toneEnvOscSigh, vel);
-	tEnvelope_on(&kick->toneEnvGain, vel);
-	tEnvelope_on(&kick->noiseEnvGain, vel);
-
-}
-void        t808Kick_setToneFreq          (t808Kick* const kick, float freq)
-{
-	kick->toneInitialFreq = freq;
-
-}
-
-void        t808Kick_setToneDecay         (t808Kick* const kick, float decay)
-{
-	tEnvelope_setDecay(&kick->toneEnvGain,decay);
-	tEnvelope_setDecay(&kick->toneEnvGain,decay * 3.0f);
-}
-
-void        t808Kick_setNoiseDecay         (t808Kick* const kick, float decay);
-void        t808Kick_setSighAmount         (t808Kick* const kick, float sigh);
-void        t808Kick_setChirpAmount         (t808Kick* const kick, float chirp);
-void        t808Kick_setToneNoiseMix       (t808Kick* const kick, float toneNoiseMix);
-void        t808Kick_setNoiseFilterFreq    (t808Kick* const kick, float noiseFilterFreq);
-void        t808Kick_setNoiseFilterQ       (t808Kick* const kick, float noiseFilterQ);
-
-
--- a/LEAF/Src/leaf-WDF.c
+++ /dev/null
@@ -1,469 +1,0 @@
-/*
- * leaf-WDF.c
- *
- *  Created on: Sep 25, 2019
- *      Author: jeffsnyder
- */
-
-
-#include "../Inc/leaf-WDF.h"
-
-static float get_port_resistance_for_resistor(tWDF* const r);
-static float get_port_resistance_for_capacitor(tWDF* const r);
-static float get_port_resistance_for_inductor(tWDF* const r);
-static float get_port_resistance_for_resistive(tWDF* const r);
-static float get_port_resistance_for_inverter(tWDF* const r);
-static float get_port_resistance_for_series(tWDF* const r);
-static float get_port_resistance_for_parallel(tWDF* const r);
-static float get_port_resistance_for_root(tWDF* const r);
-
-static void set_incident_wave_for_leaf(tWDF* const r, float incident_wave, float input);
-static void set_incident_wave_for_leaf_inverted(tWDF* const r, float incident_wave, float input);
-static void set_incident_wave_for_inverter(tWDF* const r, float incident_wave, float input);
-static void set_incident_wave_for_series(tWDF* const r, float incident_wave, float input);
-static void set_incident_wave_for_parallel(tWDF* const r, float incident_wave, float input);
-
-static float get_reflected_wave_for_resistor(tWDF* const r, float input);
-static float get_reflected_wave_for_capacitor(tWDF* const r, float input);
-static float get_reflected_wave_for_resistive(tWDF* const r, float input);
-static float get_reflected_wave_for_inverter(tWDF* const r, float input);
-static float get_reflected_wave_for_series(tWDF* const r, float input);
-static float get_reflected_wave_for_parallel(tWDF* const r, float input);
-
-static float get_reflected_wave_for_ideal(tWDF* const n, float input, float incident_wave);
-static float get_reflected_wave_for_diode(tWDF* const n, float input, float incident_wave);
-static float get_reflected_wave_for_diode_pair(tWDF* const n, float input, float incident_wave);
-
-//WDF
-void tWDF_init(tWDF* const r, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR)
-{
-	r->type = type;
-    r->child_left = rL;
-    r->child_right = rR;
-	r->incident_wave_up = 0.0f;
-	r->incident_wave_left = 0.0f;
-	r->incident_wave_right = 0.0f;
-	r->reflected_wave_up = 0.0f;
-	r->reflected_wave_left = 0.0f;
-	r->reflected_wave_right = 0.0f;
-	r->sample_rate = leaf.sampleRate;
-	r->value = value;
-    
-    tWDF* child;
-    if (r->child_left != NULL) child = r->child_left;
-    else child = r->child_right;
-    
-    if (r->type == Resistor)
-	{
-		r->port_resistance_up = r->value;
-		r->port_conductance_up = 1.0f / r->value;
-
-		r->get_port_resistance = &get_port_resistance_for_resistor;
-		r->get_reflected_wave_up = &get_reflected_wave_for_resistor;
-		r->set_incident_wave = &set_incident_wave_for_leaf;
-	}
-	else if (r->type == Capacitor)
-	{
-        r->port_conductance_up = r->sample_rate * 2.0f * r->value;
-		r->port_resistance_up = 1.0f / r->port_conductance_up; //based on trapezoidal discretization
-    
-		r->get_port_resistance = &get_port_resistance_for_capacitor;
-		r->get_reflected_wave_up = &get_reflected_wave_for_capacitor;
-		r->set_incident_wave = &set_incident_wave_for_leaf;
-	}
-    else if (r->type == Inductor)
-    {
-        r->port_resistance_up = r->sample_rate * 2.0f * r->value; //based on trapezoidal discretization
-        r->port_conductance_up = 1.0f / r->port_resistance_up;
-        
-        r->get_port_resistance = &get_port_resistance_for_inductor;
-        r->get_reflected_wave_up = &get_reflected_wave_for_capacitor; // same as capacitor
-        r->set_incident_wave = &set_incident_wave_for_leaf_inverted;
-    }
-	else if (r->type == ResistiveSource)
-	{
-        r->port_resistance_up = r->value;
-        r->port_conductance_up = 1.0f / r->port_resistance_up;
-        
-        r->get_port_resistance = &get_port_resistance_for_resistive;
-        r->get_reflected_wave_up = &get_reflected_wave_for_resistive;
-        r->set_incident_wave = &set_incident_wave_for_leaf;
-	}
-    else if (r->type == Inverter)
-    {
-        r->port_resistance_up = tWDF_getPortResistance(r->child_left);
-        r->port_conductance_up = 1.0f / r->port_resistance_up;
-        
-        r->get_port_resistance = &get_port_resistance_for_inverter;
-        r->get_reflected_wave_up = &get_reflected_wave_for_inverter;
-        r->set_incident_wave = &set_incident_wave_for_inverter;
-    }
-    else if (r->type == SeriesAdaptor)
-    {
-        r->port_resistance_left = tWDF_getPortResistance(r->child_left);
-        r->port_resistance_right = tWDF_getPortResistance(r->child_right);
-        r->port_resistance_up = r->port_resistance_left + r->port_resistance_right;
-        r->port_conductance_up  = 1.0f / r->port_resistance_up;
-        r->port_conductance_left = 1.0f / r->port_resistance_left;
-        r->port_conductance_right = 1.0f / r->port_resistance_right;
-        r->gamma_zero = 1.0f / (r->port_resistance_right + r->port_resistance_left);
-        
-        r->get_port_resistance = &get_port_resistance_for_series;
-        r->get_reflected_wave_up = &get_reflected_wave_for_series;
-        r->set_incident_wave = &set_incident_wave_for_series;
-    }
-    else if (r->type == ParallelAdaptor)
-    {
-        r->port_resistance_left = tWDF_getPortResistance(r->child_left);
-        r->port_resistance_right = tWDF_getPortResistance(r->child_right);
-        r->port_resistance_up = (r->port_resistance_left * r->port_resistance_right) / (r->port_resistance_left + r->port_resistance_right);
-        r->port_conductance_up  = 1.0f / r->port_resistance_up;
-        r->port_conductance_left = 1.0f / r->port_resistance_left;
-        r->port_conductance_right = 1.0f / r->port_resistance_right;
-        r->gamma_zero = 1.0f / (r->port_resistance_right + r->port_resistance_left);
-        
-        r->get_port_resistance = &get_port_resistance_for_parallel;
-        r->get_reflected_wave_up = &get_reflected_wave_for_parallel;
-        r->set_incident_wave = &set_incident_wave_for_parallel;
-    }
-    else if (r->type == IdealSource)
-    {
-        r->port_resistance_up = tWDF_getPortResistance(child);
-        r->port_conductance_up = 1.0f / r->port_resistance_up;
-        
-        r->get_reflected_wave_down = &get_reflected_wave_for_ideal;
-        r->get_port_resistance = &get_port_resistance_for_root;
-    }
-    else if (r->type == Diode)
-    {
-        r->port_resistance_up = tWDF_getPortResistance(child);
-        r->port_conductance_up = 1.0f / r->port_resistance_up;
-        
-        r->get_reflected_wave_down = &get_reflected_wave_for_diode;
-        r->get_port_resistance = &get_port_resistance_for_root;
-    }
-    else if (r->type == DiodePair)
-    {
-        r->port_resistance_up = tWDF_getPortResistance(child);
-        r->port_conductance_up = 1.0f / r->port_resistance_up;
-        
-        r->get_reflected_wave_down = &get_reflected_wave_for_diode_pair;
-        r->get_port_resistance = &get_port_resistance_for_root;
-    }
-}
-
-void tWDF_free(tWDF* const r)
-{
-
-}
-
-float tWDF_tick(tWDF* const r, float sample, tWDF* const outputPoint, uint8_t paramsChanged)
-{
-    tWDF* child;
-    if (r->child_left != NULL) child = r->child_left;
-    else child = r->child_right;
-    
-	//step 0 : update port resistances if something changed
-	if (paramsChanged) tWDF_getPortResistance(r);
-
-	//step 1 : set inputs to what they should be
-	float input = sample;
-
-	//step 2 : scan the waves up the tree
-	r->incident_wave_up = tWDF_getReflectedWaveUp(child, input);
-
-	//step 3 : do root scattering computation
-	r->reflected_wave_up = tWDF_getReflectedWaveDown(r, input, r->incident_wave_up);
-
-	//step 4 : propogate waves down the tree
-	tWDF_setIncidentWave(child, r->reflected_wave_up, input);
-
-	//step 5 : grab whatever voltages or currents we want as outputs
-    return tWDF_getVoltage(outputPoint);
-}
-
-void tWDF_setValue(tWDF* const r, float value)
-{
-	r->value = value;
-}
-
-void tWDF_setSampleRate(tWDF* const r, float sample_rate)
-{
-    r->sample_rate = sample_rate;
-}
-
-uint8_t tWDF_isLeaf(tWDF* const r)
-{
-    if (r->child_left == NULL && r->child_right == NULL) return 1;
-    return 0;
-}
-
-float tWDF_getPortResistance(tWDF* const r)
-{
-	return r->get_port_resistance(r);
-}
-
-void tWDF_setIncidentWave(tWDF* const r, float incident_wave, float input)
-{
-	r->set_incident_wave(r, incident_wave, input);
-}
-
-float tWDF_getReflectedWaveUp(tWDF* const r, float input)
-{
-	return r->get_reflected_wave_up(r, input);
-}
-
-float tWDF_getReflectedWaveDown(tWDF* const r, float input, float incident_wave)
-{
-    return r->get_reflected_wave_down(r, input, incident_wave);
-}
-
-float tWDF_getVoltage(tWDF* const r)
-{
-	return ((r->incident_wave_up * 0.5f) + (r->reflected_wave_up * 0.5f));
-}
-
-float tWDF_getCurrent(tWDF* const r)
-{
-	return (((r->incident_wave_up * 0.5f) - (r->reflected_wave_up * 0.5f)) * r->port_conductance_up);
-}
-
-//============ Static Functions to be Pointed To ====================
-//===================================================================
-//============ Get and Calculate Port Resistances ===================
-
-static float get_port_resistance_for_resistor(tWDF* const r)
-{
-	r->port_resistance_up = r->value;
-	r->port_conductance_up = 1.0f / r->value;
-
-	return r->port_resistance_up;
-}
-
-static float get_port_resistance_for_capacitor(tWDF* const r)
-{
-	r->port_conductance_up = r->sample_rate * 2.0f * r->value; //based on trapezoidal discretization
-	r->port_resistance_up = (1.0f / r->port_conductance_up);
-
-	return r->port_resistance_up;
-}
-
-static float get_port_resistance_for_inductor(tWDF* const r)
-{
-    r->port_resistance_up = r->sample_rate * 2.0f * r->value; //based on trapezoidal discretization
-    r->port_conductance_up = (1.0f / r->port_resistance_up);
-    
-    return r->port_resistance_up;
-}
-
-static float get_port_resistance_for_resistive(tWDF* const r)
-{
-    r->port_resistance_up = r->value;
-    r->port_conductance_up = 1.0f / r->port_resistance_up;
-    
-    return r->port_resistance_up;
-}
-
-static float get_port_resistance_for_inverter(tWDF* const r)
-{
-    r->port_resistance_up = tWDF_getPortResistance(r->child_left);
-    r->port_conductance_up = 1.0f / r->port_resistance_up;
-    
-    return r->port_resistance_up;
-}
-
-static float get_port_resistance_for_series(tWDF* const r)
-{
-	r->port_resistance_left = tWDF_getPortResistance(r->child_left);
-	r->port_resistance_right = tWDF_getPortResistance(r->child_right);
-	r->port_resistance_up = r->port_resistance_left + r->port_resistance_right;
-	r->port_conductance_up  = 1.0f / r->port_resistance_up;
-	r->port_conductance_left = 1.0f / r->port_resistance_left;
-	r->port_conductance_right = 1.0f / r->port_resistance_right;
-	r->gamma_zero = 1.0f / (r->port_resistance_right + r->port_resistance_left);
-
-	return r->port_resistance_up;
-}
-
-static float get_port_resistance_for_parallel(tWDF* const r)
-{
-	r->port_resistance_left = tWDF_getPortResistance(r->child_left);
-	r->port_resistance_right = tWDF_getPortResistance(r->child_right);
-	r->port_resistance_up = (r->port_resistance_left * r->port_resistance_right) / (r->port_resistance_left + r->port_resistance_right);
-	r->port_conductance_up  = 1.0f / r->port_resistance_up;
-	r->port_conductance_left = 1.0f / r->port_resistance_left;
-	r->port_conductance_right = 1.0f / r->port_resistance_right;
-	r->gamma_zero = 1.0f / (r->port_conductance_right + r->port_conductance_left);
-
-	return r->port_resistance_up;
-}
-
-static float get_port_resistance_for_root(tWDF* const r)
-{
-    tWDF* child;
-    if (r->child_left != NULL) child = r->child_left;
-    else child = r->child_right;
-    
-    r->port_resistance_up = tWDF_getPortResistance(child);
-    r->port_conductance_up = 1.0f / r->port_resistance_up;
-    
-    return r->port_resistance_up;
-}
-
-//===================================================================
-//================ Set Incident Waves ===============================
-
-static void set_incident_wave_for_leaf(tWDF* const r, float incident_wave, float input)
-{
-	r->incident_wave_up = incident_wave;
-}
-
-static void set_incident_wave_for_leaf_inverted(tWDF* const r, float incident_wave, float input)
-{
-    r->incident_wave_up = -1.0f * incident_wave;
-}
-
-static void set_incident_wave_for_inverter(tWDF* const r, float incident_wave, float input)
-{
-    r->incident_wave_up = incident_wave;
-    tWDF_setIncidentWave(r->child_left, -1.0f * incident_wave, input);
-}
-
-static void set_incident_wave_for_series(tWDF* const r, float incident_wave, float input)
-{
-    r->incident_wave_up = incident_wave;
-	float gamma_left = r->port_resistance_left * r->gamma_zero;
-	float gamma_right = r->port_resistance_right * r->gamma_zero;
-	float left_wave = tWDF_getReflectedWaveUp(r->child_left, input);
-	float right_wave = tWDF_getReflectedWaveUp(r->child_right, input);
-//    downPorts[0]->b = yl * ( downPorts[0]->a * ((1.0 / yl) - 1) - downPorts[1]->a - descendingWave );
-//    downPorts[1]->b = yr * ( downPorts[1]->a * ((1.0 / yr) - 1) - downPorts[0]->a - descendingWave );
-	tWDF_setIncidentWave(r->child_left, (-1.0f * gamma_left * incident_wave) + (gamma_right * left_wave) - (gamma_left * right_wave), input);
-	tWDF_setIncidentWave(r->child_right, (-1.0f * gamma_right * incident_wave) + (gamma_left * right_wave) - (gamma_right * left_wave), input);
-	// From rt-wdf
-//	tWDF_setIncidentWave(r->child_left, gamma_left * (left_wave * ((1.0f / gamma_left) - 1.0f) - right_wave - incident_wave));
-//	tWDF_setIncidentWave(r->child_right, gamma_right * (right_wave * ((1.0f / gamma_right) - 1.0f) - left_wave - incident_wave));
-
-}
-
-static void set_incident_wave_for_parallel(tWDF* const r, float incident_wave, float input)
-{
-    r->incident_wave_up = incident_wave;
-	float gamma_left = r->port_conductance_left * r->gamma_zero;
-	float gamma_right = r->port_conductance_right * r->gamma_zero;
-	float left_wave = tWDF_getReflectedWaveUp(r->child_left, input);
-	float right_wave = tWDF_getReflectedWaveUp(r->child_right, input);
-//    downPorts[0]->b = ( ( dl - 1 ) * downPorts[0]->a + dr * downPorts[1]->a + du * descendingWave );
-//    downPorts[1]->b = ( dl * downPorts[0]->a + ( dr - 1 ) * downPorts[1]->a + du * descendingWave );
-	tWDF_setIncidentWave(r->child_left, (gamma_left - 1.0f) * left_wave + gamma_right * right_wave + incident_wave, input);
-	tWDF_setIncidentWave(r->child_right, gamma_left * left_wave + (gamma_right - 1.0f) * right_wave + incident_wave, input);
-}
-
-//===================================================================
-//================ Get Reflected Waves ==============================
-
-static float get_reflected_wave_for_resistor(tWDF* const r, float input)
-{
-	r->reflected_wave_up = 0.0f;
-	return r->reflected_wave_up;
-}
-
-static float get_reflected_wave_for_capacitor(tWDF* const r, float input)
-{
-	r->reflected_wave_up = r->incident_wave_up;
-	return r->reflected_wave_up;
-}
-
-static float get_reflected_wave_for_resistive(tWDF* const r, float input)
-{
-    r->reflected_wave_up = input;
-    return r->reflected_wave_up;
-}
-
-static float get_reflected_wave_for_inverter(tWDF* const r, float input)
-{
-    r->reflected_wave_up = -1.0f * tWDF_getReflectedWaveUp(r->child_left, input);
-    return r->reflected_wave_up;
-}
-
-static float get_reflected_wave_for_series(tWDF* const r, float input)
-{
-	//-( downPorts[0]->a + downPorts[1]->a );
-    r->reflected_wave_up = (-1.0f * (tWDF_getReflectedWaveUp(r->child_left, input) + tWDF_getReflectedWaveUp(r->child_right, input)));
-	return r->reflected_wave_up;
-}
-
-static float get_reflected_wave_for_parallel(tWDF* const r, float input)
-{
-	float gamma_left = r->port_conductance_left * r->gamma_zero;
-	float gamma_right = r->port_conductance_right * r->gamma_zero;
-	//return ( dl * downPorts[0]->a + dr * downPorts[1]->a );
-    r->reflected_wave_up = (gamma_left * tWDF_getReflectedWaveUp(r->child_left, input) + gamma_right * tWDF_getReflectedWaveUp(r->child_right, input));
-	return r->reflected_wave_up;
-}
-
-static float get_reflected_wave_for_ideal(tWDF* const n, float input, float incident_wave)
-{
-    return (2.0f * input) - incident_wave;
-}
-
-#define l2A 0.1640425613334452f
-#define l2B -1.098865286222744f
-#define l2Y 3.148297929334117f
-#define l2K -2.213475204444817f
-static float log2Approximation(float x)
-{
-    return (l2A * x*x*x) + (l2B * x*x) + (l2Y * x) + l2K;
-}
-
-#define wX1 -3.684303659906469f
-#define wX2 1.972967391708859f
-#define wA  9.451797158780131e-3f
-#define wB  0.1126446405111627f
-#define wY  0.4451353886588814f
-#define wK  0.5836596684310648f
-static float wrightOmega3(float x)
-{
-    if (x <= wX1)
-    {
-        return 0;
-    }
-    else if (x < wX2)
-    {
-        return (wA * x*x*x) + (wB * x*x) + (wY * x) + wK;
-    }
-    else
-    {
-        return x - logf(x);
-    }
-}
-
-static float wrightOmegaApproximation(float x)
-{
-    float w3 = wrightOmega3(x);
-    return w3 - ((w3 - expf(x - w3)) / (w3 + 1.0f));
-}
-
-static float lambertW(float a, float r, float I, float iVT)
-{
-    return wrightOmegaApproximation(((a + r*I) * iVT) + log((r * I) * iVT));
-}
-
-#define Is_DIODE    2.52e-9f
-#define VT_DIODE    0.02585f
-static float get_reflected_wave_for_diode(tWDF* const n, float input, float incident_wave)
-{
-    float a = incident_wave;
-    float r = n->port_resistance_up;
-    return a + 2.0f*r*Is_DIODE - 2.0f*VT_DIODE*lambertW(a, r, Is_DIODE, 1.0f/VT_DIODE);
-}
-
-static float get_reflected_wave_for_diode_pair(tWDF* const n, float input, float incident_wave)
-{
-    float a = incident_wave;
-    float sgn = 0.0f;
-    if (a > 0.0f) sgn = 1.0f;
-    else if (a < 0.0f) sgn = -1.0f;
-    float r = n->port_resistance_up;
-    return a + 2 * sgn * (r*Is_DIODE - VT_DIODE*lambertW(sgn*a, r, Is_DIODE, 1.0f/VT_DIODE));
-}
--- /dev/null
+++ b/LEAF/Src/leaf-analysis.c
@@ -1,0 +1,733 @@
+/*==============================================================================
+
+    leaf-analysis.c
+    Created: 30 Nov 2018 11:56:49am
+    Author:  airship
+
+==============================================================================*/
+
+#if _WIN32 || _WIN64
+
+#include "..\Inc\leaf-analysis.h"
+#include "..\Externals\d_fft_mayer.h"
+
+#else
+
+#include "../Inc/leaf-analysis.h"
+#include "../Externals/d_fft_mayer.h"
+
+#endif
+
+//===========================================================================
+/* Envelope Follower */
+//===========================================================================
+
+void    tEnvelopeFollower_init(tEnvelopeFollower* const e, float attackThreshold, float decayCoeff)
+{
+    e->y = 0.0f;
+    e->a_thresh = attackThreshold;
+    e->d_coeff = decayCoeff;
+}
+
+void tEnvelopeFollower_free(tEnvelopeFollower* const e)
+{
+    
+}
+
+float   tEnvelopeFollower_tick(tEnvelopeFollower* const ef, float x)
+{
+    if (x < 0.0f ) x = -x;  /* Absolute value. */
+    
+    if ((x >= ef->y) && (x > ef->a_thresh)) ef->y = x;                      /* If we hit a peak, ride the peak to the top. */
+    else                                    ef->y = ef->y * ef->d_coeff;    /* Else, exponential decay of output. */
+    
+    //ef->y = envelope_pow[(uint16_t)(ef->y * (float)UINT16_MAX)] * ef->d_coeff; //not quite the right behavior - too much loss of precision?
+    //ef->y = powf(ef->y, 1.000009f) * ef->d_coeff;  // too expensive
+    
+    if( ef->y < VSF)   ef->y = 0.0f;
+    
+    return ef->y;
+}
+
+int     tEnvelopeFollower_decayCoeff(tEnvelopeFollower* const ef, float decayCoeff)
+{
+    return ef->d_coeff = decayCoeff;
+}
+
+int     tEnvelopeFollower_attackThresh(tEnvelopeFollower* const ef, float attackThresh)
+{
+    return ef->a_thresh = attackThresh;
+}
+
+
+
+
+
+//===========================================================================
+/* Power Follower */
+//===========================================================================
+void    tPowerFollower_init(tPowerFollower* const p, float factor)
+{
+    p->curr=0.0f;
+    p->factor=factor;
+    p->oneminusfactor=1.0f-factor;
+}
+
+void tPowerFollower_free(tPowerFollower* const p)
+{
+    
+}
+
+int     tPowerFollower_setFactor(tPowerFollower* const p, float factor)
+{
+    if (factor<0) factor=0;
+    if (factor>1) factor=1;
+    p->factor=factor;
+    p->oneminusfactor=1.0f-factor;
+    return 0;
+}
+
+float   tPowerFollower_tick(tPowerFollower* const p, float input)
+{
+    p->curr = p->factor*input*input+p->oneminusfactor*p->curr;
+    return p->curr;
+}
+
+float   tPowerFollower_sample(tPowerFollower* const p)
+{
+    return p->curr;
+}
+
+
+
+
+//===========================================================================
+/* ---------------- env~ - simple envelope follower. ----------------- */
+//===========================================================================
+
+void tEnvPD_init(tEnvPD* const x, int ws, int hs, int bs)
+{
+    int period = hs, npoints = ws;
+    
+    int i;
+    
+    if (npoints < 1) npoints = 1024;
+    if (period < 1) period = npoints/2;
+    if (period < npoints / MAXOVERLAP + 1)
+        period = npoints / MAXOVERLAP + 1;
+    
+    x->x_npoints = npoints;
+    x->x_phase = 0;
+    x->x_period = period;
+    
+    x->windowSize = npoints;
+    x->hopSize = period;
+    x->blockSize = bs;
+    
+    for (i = 0; i < MAXOVERLAP; i++) x->x_sumbuf[i] = 0;
+    for (i = 0; i < npoints; i++)
+        x->buf[i] = (1.0f - cosf((2 * PI * i) / npoints))/npoints;
+    for (; i < npoints+INITVSTAKEN; i++) x->buf[i] = 0;
+    
+    x->x_f = 0;
+    
+    x->x_allocforvs = INITVSTAKEN;
+    
+    // ~ ~ ~ dsp ~ ~ ~
+    if (x->x_period % x->blockSize)
+    {
+        x->x_realperiod = x->x_period + x->blockSize - (x->x_period % x->blockSize);
+    }
+    else
+    {
+        x->x_realperiod = x->x_period;
+    }
+    // ~ ~ ~ ~ ~ ~ ~ ~
+}
+
+void tEnvPD_free (tEnvPD* const x)
+{
+    
+}
+
+float tEnvPD_tick (tEnvPD* const x)
+{
+    return powtodb(x->x_result);
+}
+
+void tEnvPD_processBlock(tEnvPD* const x, float* in)
+{
+    int n = x->blockSize;
+    
+    int count;
+    t_sample *sump;
+    in += n;
+    for (count = x->x_phase, sump = x->x_sumbuf;
+         count < x->x_npoints; count += x->x_realperiod, sump++)
+    {
+        t_sample *hp = x->buf + count;
+        t_sample *fp = in;
+        t_sample sum = *sump;
+        int i;
+        
+        for (i = 0; i < n; i++)
+        {
+            fp--;
+            sum += *hp++ * (*fp * *fp);
+        }
+        *sump = sum;
+    }
+    sump[0] = 0;
+    x->x_phase -= n;
+    if (x->x_phase < 0)
+    {
+        x->x_result = x->x_sumbuf[0];
+        for (count = x->x_realperiod, sump = x->x_sumbuf;
+             count < x->x_npoints; count += x->x_realperiod, sump++)
+            sump[0] = sump[1];
+        sump[0] = 0;
+        x->x_phase = x->x_realperiod - n;
+    }
+}
+
+//===========================================================================
+// ATTACKDETECTION
+//===========================================================================
+/********Private function prototypes**********/
+static void atkdtk_init(tAttackDetection* const a, int blocksize, int atk, int rel);
+static void atkdtk_envelope(tAttackDetection* const a, float *in);
+
+/********Constructor/Destructor***************/
+
+void tAttackDetection_init(tAttackDetection* const a, int blocksize)
+{
+    atkdtk_init(a, blocksize, DEFATTACK, DEFRELEASE);
+}
+
+void tAttackDetection_init_expanded(tAttackDetection* const a, int blocksize, int atk, int rel)
+{
+    atkdtk_init(a, blocksize, atk, rel);
+}
+
+void tAttackDetection_free(tAttackDetection *a)
+{
+    
+}
+
+/*******Public Functions***********/
+
+
+void tAttackDetection_setBlocksize(tAttackDetection* const a, int size)
+{
+    
+    if(!((size==64)|(size==128)|(size==256)|(size==512)|(size==1024)|(size==2048)))
+        size = DEFBLOCKSIZE;
+    a->blocksize = size;
+    
+    return;
+    
+}
+
+void tAttackDetection_setSamplerate(tAttackDetection* const a, int inRate)
+{
+    a->samplerate = inRate;
+    
+    //Reset atk and rel to recalculate coeff
+    tAttackDetection_setAtk(a, a->atk);
+    tAttackDetection_setRel(a, a->rel);
+    
+    return;
+}
+
+void tAttackDetection_setThreshold(tAttackDetection* const a, float thres)
+{
+    a->threshold = thres;
+    return;
+}
+
+void tAttackDetection_setAtk(tAttackDetection* const a, int inAtk)
+{
+    a->atk = inAtk;
+    a->atk_coeff = pow(0.01, 1.0/(a->atk * a->samplerate * 0.001));
+    
+    return;
+}
+
+void tAttackDetection_setRel(tAttackDetection* const a, int inRel)
+{
+    a->rel = inRel;
+    a->rel_coeff = pow(0.01, 1.0/(a->rel * a->samplerate * 0.001));
+    
+    return;
+}
+
+
+int tAttackDetection_detect(tAttackDetection* const a, float *in)
+{
+    int result;
+    
+    atkdtk_envelope(a, in);
+    
+    if(a->env >= a->prevAmp*2) //2 times greater = 6dB increase
+        result = 1;
+    else
+        result = 0;
+    
+    a->prevAmp = a->env;
+    
+    return result;
+    
+}
+
+/*******Private Functions**********/
+
+static void atkdtk_init(tAttackDetection* const a, int blocksize, int atk, int rel)
+{
+    a->env = 0;
+    a->blocksize = blocksize;
+    a->threshold = DEFTHRESHOLD;
+    a->samplerate = leaf.sampleRate;
+    a->prevAmp = 0;
+    
+    a->env = 0;
+    
+    tAttackDetection_setAtk(a, atk);
+    tAttackDetection_setRel(a, rel);
+}
+
+static void atkdtk_envelope(tAttackDetection* const a, float *in)
+{
+    int i = 0;
+    float tmp;
+    for(i = 0; i < a->blocksize; ++i){
+        tmp = fastabs(in[i]);
+        
+        if(tmp > a->env)
+            a->env = a->atk_coeff * (a->env - tmp) + tmp;
+        else
+            a->env = a->rel_coeff * (a->env - tmp) + tmp;
+    }
+    
+}
+
+//===========================================================================
+// PERIODDETECTION
+//===========================================================================
+void    tPeriodDetection_init    (tPeriodDetection* const p, float* in, float* out, int bufSize, int frameSize)
+{
+    p->inBuffer = in;
+    p->outBuffer = out;
+    p->bufSize = bufSize;
+    p->frameSize = frameSize;
+    p->framesPerBuffer = p->bufSize / p->frameSize;
+    p->curBlock = 1;
+    p->lastBlock = 0;
+    p->index = 0;
+    
+    p->hopSize = DEFHOPSIZE;
+    p->windowSize = DEFWINDOWSIZE;
+    p->fba = FBA;
+    
+    tEnvPD_init(&p->env, p->windowSize, p->hopSize, p->frameSize);
+    
+    tSNAC_init(&p->snac, DEFOVERLAP);
+    
+    p->timeConstant = DEFTIMECONSTANT;
+    p->radius = expf(-1000.0f * p->hopSize * leaf.invSampleRate / p->timeConstant);
+}
+
+void tPeriodDetection_free (tPeriodDetection* const p)
+{
+    tEnvPD_free(&p->env);
+    tSNAC_free(&p->snac);
+}
+
+float tPeriodDetection_findPeriod (tPeriodDetection* p, float sample)
+{
+    int i, iLast;
+    
+    i = (p->curBlock*p->frameSize);
+    iLast = (p->lastBlock*p->frameSize)+p->index;
+    
+    p->i = i;
+    p->iLast = iLast;
+    
+    p->inBuffer[i+p->index] = sample;
+    
+    p->index++;
+    p->indexstore = p->index;
+    if (p->index >= p->frameSize)
+    {
+        p->index = 0;
+        
+        tEnvPD_processBlock(&p->env, &(p->inBuffer[i]));
+        
+        tSNAC_ioSamples(&p->snac, &(p->inBuffer[i]), &(p->outBuffer[i]), p->frameSize);
+        p->period = tSNAC_getPeriod(&p->snac);
+        
+        p->curBlock++;
+        if (p->curBlock >= p->framesPerBuffer) p->curBlock = 0;
+        p->lastBlock++;
+        if (p->lastBlock >= p->framesPerBuffer) p->lastBlock = 0;
+    }
+    
+    // changed from period to p->period
+    return p->period;
+}
+
+void tPeriodDetection_setHopSize(tPeriodDetection* p, int hs)
+{
+    p->hopSize = hs;
+}
+
+void tPeriodDetection_setWindowSize(tPeriodDetection* p, int ws)
+{
+    p->windowSize = ws;
+}
+
+
+
+
+
+
+
+
+
+//===========================================================================
+// SNAC
+//===========================================================================
+/******************************************************************************/
+/***************************** private procedures *****************************/
+/******************************************************************************/
+
+#define REALFFT mayer_realfft
+#define REALIFFT mayer_realifft
+
+static void snac_analyzeframe(tSNAC* const s);
+static void snac_autocorrelation(tSNAC* const s);
+static void snac_normalize(tSNAC* const s);
+static void snac_pickpeak(tSNAC* const s);
+static void snac_periodandfidelity(tSNAC* const s);
+static void snac_biasbuf(tSNAC* const s);
+static float snac_spectralpeak(tSNAC* const s, float periodlength);
+
+
+/******************************************************************************/
+/******************************** constructor, destructor *********************/
+/******************************************************************************/
+
+
+void tSNAC_init(tSNAC* const s, int overlaparg)
+{
+    s->biasfactor = DEFBIAS;
+    s->timeindex = 0;
+    s->periodindex = 0;
+    s->periodlength = 0.;
+    s->fidelity = 0.;
+    s->minrms = DEFMINRMS;
+    s->framesize = SNAC_FRAME_SIZE;
+    
+    s->inputbuf = (float*) leaf_alloc(sizeof(float) * SNAC_FRAME_SIZE);
+    s->processbuf = (float*) leaf_alloc(sizeof(float) * (SNAC_FRAME_SIZE * 2));
+    s->spectrumbuf = (float*) leaf_alloc(sizeof(float) * (SNAC_FRAME_SIZE / 2));
+    s->biasbuf = (float*) leaf_alloc(sizeof(float) * SNAC_FRAME_SIZE);
+    
+    snac_biasbuf(s);
+    tSNAC_setOverlap(s, overlaparg);
+}
+
+void tSNAC_free(tSNAC* const s)
+{
+    leaf_free(s->inputbuf);
+    leaf_free(s->processbuf);
+    leaf_free(s->spectrumbuf);
+    leaf_free(s->biasbuf);
+}
+/******************************************************************************/
+/************************** public access functions****************************/
+/******************************************************************************/
+
+
+void tSNAC_ioSamples(tSNAC* const s, float *in, float *out, int size)
+{
+    int timeindex = s->timeindex;
+    int mask = s->framesize - 1;
+    int outindex = 0;
+    float *inputbuf = s->inputbuf;
+    float *processbuf = s->processbuf;
+    
+    // call analysis function when it is time
+    if(!(timeindex & (s->framesize / s->overlap - 1))) snac_analyzeframe(s);
+    
+    while(size--)
+    {
+        inputbuf[timeindex] = *in++;
+        out[outindex++] = processbuf[timeindex++];
+        timeindex &= mask;
+    }
+    s->timeindex = timeindex;
+}
+
+void tSNAC_setOverlap(tSNAC* const s, int lap)
+{
+    if(!((lap==1)|(lap==2)|(lap==4)|(lap==8))) lap = DEFOVERLAP;
+    s->overlap = lap;
+}
+
+
+void tSNAC_setBias(tSNAC* const s, float bias)
+{
+    if(bias > 1.) bias = 1.;
+    if(bias < 0.) bias = 0.;
+    s->biasfactor = bias;
+    snac_biasbuf(s);
+    return;
+}
+
+
+void tSNAC_setMinRMS(tSNAC* const s, float rms)
+{
+    if(rms > 1.) rms = 1.;
+    if(rms < 0.) rms = 0.;
+    s->minrms = rms;
+    return;
+}
+
+
+float tSNAC_getPeriod(tSNAC* const s)
+{
+    return(s->periodlength);
+}
+
+
+float tSNAC_getFidelity(tSNAC* const s)
+{
+    return(s->fidelity);
+}
+
+
+/******************************************************************************/
+/***************************** private procedures *****************************/
+/******************************************************************************/
+
+
+// main analysis function
+static void snac_analyzeframe(tSNAC* const s)
+{
+    int n, tindex = s->timeindex;
+    int framesize = s->framesize;
+    int mask = framesize - 1;
+    float norm = 1. / sqrt((float)(framesize * 2));
+    
+    float *inputbuf = s->inputbuf;
+    float *processbuf = s->processbuf;
+    
+    // copy input to processing buffers
+    for(n=0; n<framesize; n++)
+    {
+        processbuf[n] = inputbuf[tindex] * norm;
+        tindex++;
+        tindex &= mask;
+    }
+    
+    // zeropadding
+    for(n=framesize; n<(framesize<<1); n++) processbuf[n] = 0.;
+    
+    // call analysis procedures
+    snac_autocorrelation(s);
+    snac_normalize(s);
+    snac_pickpeak(s);
+    snac_periodandfidelity(s);
+}
+
+
+static void snac_autocorrelation(tSNAC* const s)
+{
+    int n, m;
+    int framesize = s->framesize;
+    int fftsize = framesize * 2;
+    float *processbuf = s->processbuf;
+    float *spectrumbuf = s->spectrumbuf;
+    
+    REALFFT(fftsize, processbuf);
+    
+    // compute power spectrum
+    processbuf[0] *= processbuf[0];                      // DC
+    processbuf[framesize] *= processbuf[framesize];      // Nyquist
+    
+    for(n=1; n<framesize; n++)
+    {
+        processbuf[n] = processbuf[n] * processbuf[n]
+        + processbuf[fftsize-n] * processbuf[fftsize-n]; // imag coefficients appear reversed
+        processbuf[fftsize-n] = 0.;
+    }
+    
+    // store power spectrum up to SR/4 for possible later use
+    for(m=0; m<(framesize>>1); m++)
+    {
+        spectrumbuf[m] = processbuf[m];
+    }
+    
+    // transform power spectrum to autocorrelation function
+    REALIFFT(fftsize, processbuf);
+    return;
+}
+
+
+static void snac_normalize(tSNAC* const s)
+{
+    int framesize = s->framesize;
+    int framesizeplustimeindex = s->framesize + s->timeindex;
+    int timeindexminusone = s->timeindex - 1;
+    int n, m;
+    int mask = framesize - 1;
+    int seek = framesize * SEEK;
+    float *inputbuf = s->inputbuf;
+    float *processbuf= s->processbuf;
+    float signal1, signal2;
+    
+    // minimum RMS implemented as minimum autocorrelation at index 0
+    // functionally equivalent to white noise floor
+    float rms = s->minrms / sqrt(1.0f / (float)framesize);
+    float minrzero = rms * rms;
+    float rzero = processbuf[0];
+    if(rzero < minrzero) rzero = minrzero;
+    double normintegral = (double)rzero * 2.;
+    
+    // normalize biased autocorrelation function
+    // inputbuf is circular buffer: timeindex may be non-zero when overlap > 1
+    processbuf[0] = 1;
+    for(n=1, m=s->timeindex+1; n<seek; n++, m++)
+    {
+        signal1 = inputbuf[(n + timeindexminusone)&mask];
+        signal2 = inputbuf[(framesizeplustimeindex - n)&mask];
+        normintegral -= (double)(signal1 * signal1 + signal2 * signal2);
+        processbuf[n] /= (float)normintegral * 0.5f;
+    }
+    
+    // flush instable function tail
+    for(n = seek; n<framesize; n++) processbuf[n] = 0.;
+    return;
+}
+
+
+static void snac_periodandfidelity(tSNAC* const s)
+{
+    float periodlength;
+    
+    if(s->periodindex)
+    {
+        periodlength = (float)s->periodindex +
+        interpolate3phase(s->processbuf, s->periodindex);
+        if(periodlength < 8) periodlength = snac_spectralpeak(s, periodlength);
+        s->periodlength = periodlength;
+        s->fidelity = interpolate3max(s->processbuf, s->periodindex);
+    }
+    return;
+}
+
+// select the peak which most probably represents period length
+static void snac_pickpeak(tSNAC* const s)
+{
+    int n, peakindex=0;
+    int seek = s->framesize * SEEK;
+    float *processbuf= s->processbuf;
+    float maxvalue = 0.;
+    float biasedpeak;
+    float *biasbuf = s->biasbuf;
+    
+    // skip main lobe
+    for(n=1; n<seek; n++)
+    {
+        if(processbuf[n] < 0.) break;
+    }
+    
+    // find interpolated / biased maximum in SNAC function
+    // interpolation finds the 'real maximum'
+    // biasing favours the first candidate
+    for(; n<seek-1; n++)
+    {
+        if(processbuf[n] >= processbuf[n-1])
+        {
+            if(processbuf[n] > processbuf[n+1])     // we have a local peak
+            {
+                biasedpeak = interpolate3max(processbuf, n) * biasbuf[n];
+                
+                if(biasedpeak > maxvalue)
+                {
+                    maxvalue = biasedpeak;
+                    peakindex = n;
+                }
+            }
+        }
+    }
+    s->periodindex = peakindex;
+    return;
+}
+
+
+// verify period length via frequency domain (up till SR/4)
+// frequency domain is more precise than lag domain for period lengths < 8
+// argument 'periodlength' is initial estimation from autocorrelation
+static float snac_spectralpeak(tSNAC* const s, float periodlength)
+{
+    if(periodlength < 4.) return periodlength;
+    
+    float max = 0.;
+    int n, startbin, stopbin, peakbin = 0;
+    int spectrumsize = s->framesize>>1;
+    float *spectrumbuf = s->spectrumbuf;
+    float peaklocation = (float)(s->framesize * 2.) / periodlength;
+    
+    startbin = (int)(peaklocation * 0.8 + 0.5);
+    if(startbin < 1) startbin = 1;
+    stopbin = (int)(peaklocation * 1.25 + 0.5);
+    if(stopbin >= spectrumsize - 1) stopbin = spectrumsize - 1;
+    
+    for(n=startbin; n<stopbin; n++)
+    {
+        if(spectrumbuf[n] >= spectrumbuf[n-1])
+        {
+            if(spectrumbuf[n] > spectrumbuf[n+1])
+            {
+                if(spectrumbuf[n] > max)
+                {
+                    max = spectrumbuf[n];
+                    peakbin = n;
+                }
+            }
+        }
+    }
+    
+    // calculate amplitudes in peak region
+    for(n=(peakbin-1); n<(peakbin+2); n++)
+    {
+        spectrumbuf[n] = sqrt(spectrumbuf[n]);
+    }
+    
+    peaklocation = (float)peakbin + interpolate3phase(spectrumbuf, peakbin);
+    periodlength = (float)(s->framesize * 2.0f) / peaklocation;
+    
+    return periodlength;
+}
+
+
+// modified logarithmic bias function
+static void snac_biasbuf(tSNAC* const s)
+{
+    int n;
+    int maxperiod = (int)(s->framesize * (float)SEEK);
+    float bias = s->biasfactor / log((float)(maxperiod - 4));
+    float *biasbuf = s->biasbuf;
+    
+    for(n=0; n<5; n++)    // periods < 5 samples can't be tracked
+    {
+        biasbuf[n] = 0.;
+    }
+    
+    for(n=5; n<maxperiod; n++)
+    {
+        biasbuf[n] = 1.0f - (float)log(n - 4) * bias;
+    }
+}
+
--- a/LEAF/Src/leaf-crusher.c
+++ /dev/null
@@ -1,84 +1,0 @@
-/*==============================================================================
-
-    leaf-crusher.c
-    Created: 30 Nov 2018 11:56:49am
-    Author:  airship
-
-==============================================================================*/
-
-#if _WIN32 || _WIN64
-
-#include "..\Inc\leaf-crusher.h"
-
-#else
-
-#include "../Inc/leaf-crusher.h"
-
-#endif
-
-//==============================================================================
-
-#define SCALAR 5000.f
-
-void    tCrusher_init    (tCrusher* const c)
-{
-    c->op = 4;
-    c->div = SCALAR;
-    c->rnd = 0.25f;
-    c->srr = 0.25f;
-    
-    c->gain = (c->div / SCALAR) * 0.7f + 0.3f;
-}
-
-void    tCrusher_free    (tCrusher* const c)
-{
-
-}
-
-float   tCrusher_tick    (tCrusher* const c, float input)
-{
-    float sample = input;
-    
-    sample *= SCALAR; // SCALAR is 5000 by default
-    
-    sample = (int32_t) sample;
-    
-    sample /= c->div;
-
-    sample = LEAF_bitwise_xor(sample, c->op << 23);
-    
-    sample = LEAF_clip(-1.f, sample, 1.f);
-    
-    sample = LEAF_round(sample, c->rnd);
-    
-    sample = LEAF_reduct(sample, c->srr);
-    
-    return sample * c->gain;
-    
-}
-
-void    tCrusher_setOperation (tCrusher* const c, float op)
-{
-	c->op = (uint32_t) (op * 8.0f);
-}
-
-// 0.0 - 1.0
-void    tCrusher_setQuality (tCrusher* const c, float val)
-{
-    val = LEAF_clip(0.0f, val, 1.0f);
-    
-    c->div = 0.01f + val * SCALAR;
-    
-    c->gain = (c->div / SCALAR) * 0.7f + 0.3f;
-}
-
-// what decimal to round to
-void    tCrusher_setRound (tCrusher* const c, float rnd)
-{
-    c->rnd = fabsf(rnd);
-}
-
-void    tCrusher_setSamplingRatio (tCrusher* const c, float ratio)
-{
-    c->srr = ratio;
-}
--- a/LEAF/Src/leaf-delay.c
+++ b/LEAF/Src/leaf-delay.c
@@ -127,8 +127,8 @@
     return d->gain;
 }
 
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ DelayL ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
-void   tDelayL_init (tDelayL* const d, float delay, uint32_t maxDelay)
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ LinearDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
+void   tLinearDelay_init (tLinearDelay* const d, float delay, uint32_t maxDelay)
 {
     d->maxDelay = maxDelay;
 
@@ -146,15 +146,15 @@
     d->inPoint = 0;
     d->outPoint = 0;
     
-    tDelayL_setDelay(d, d->delay);
+    tLinearDelay_setDelay(d, d->delay);
 }
 
-void tDelayL_free(tDelayL* const d)
+void tLinearDelay_free(tLinearDelay* const d)
 {
     leaf_free(d->buff);
 }
 
-float   tDelayL_tick (tDelayL* const d, float input)
+float   tLinearDelay_tick (tLinearDelay* const d, float input)
 {
     d->buff[d->inPoint] = input * d->gain;
     
@@ -176,7 +176,7 @@
     return d->lastOut;
 }
 
-void   tDelayL_tickIn (tDelayL* const d, float input)
+void   tLinearDelay_tickIn (tLinearDelay* const d, float input)
 {
     d->buff[d->inPoint] = input * d->gain;
 
@@ -184,7 +184,7 @@
     if (++(d->inPoint) == d->maxDelay )    d->inPoint = 0;
 }
 
-float   tDelayL_tickOut (tDelayL* const d)
+float   tLinearDelay_tickOut (tLinearDelay* const d)
 {
     uint32_t idx = (uint32_t) d->outPoint;
 
@@ -200,7 +200,7 @@
     return d->lastOut;
 }
 
-int     tDelayL_setDelay (tDelayL* const d, float delay)
+int     tLinearDelay_setDelay (tLinearDelay* const d, float delay)
 {
     d->delay = LEAF_clip(0.0f, delay,  d->maxDelay);
     
@@ -219,7 +219,7 @@
     return 0;
 }
 
-float tDelayL_tapOut (tDelayL* const d, float tapDelay)
+float tLinearDelay_tapOut (tLinearDelay* const d, float tapDelay)
 {
     float tap = (float) d->inPoint - tapDelay - 1.f;
     
@@ -244,7 +244,7 @@
     
 }
 
-void tDelayL_tapIn (tDelayL* const d, float value, uint32_t tapDelay)
+void tLinearDelay_tapIn (tLinearDelay* const d, float value, uint32_t tapDelay)
 {
     int32_t tap = d->inPoint - tapDelay - 1;
     
@@ -254,7 +254,7 @@
     d->buff[tap] = value;
 }
 
-float tDelayL_addTo (tDelayL* const d, float value, uint32_t tapDelay)
+float tLinearDelay_addTo (tLinearDelay* const d, float value, uint32_t tapDelay)
 {
     int32_t tap = d->inPoint - tapDelay - 1;
     
@@ -264,34 +264,34 @@
     return (d->buff[tap] += value);
 }
 
-float   tDelayL_getDelay (tDelayL *d)
+float   tLinearDelay_getDelay (tLinearDelay *d)
 {
     return d->delay;
 }
 
-float   tDelayL_getLastOut (tDelayL* const d)
+float   tLinearDelay_getLastOut (tLinearDelay* const d)
 {
     return d->lastOut;
 }
 
-float   tDelayL_getLastIn (tDelayL* const d)
+float   tLinearDelay_getLastIn (tLinearDelay* const d)
 {
     return d->lastIn;
 }
 
-void tDelayL_setGain (tDelayL* const d, float gain)
+void tLinearDelay_setGain (tLinearDelay* const d, float gain)
 {
     if (gain < 0.0f)    d->gain = 0.0f;
     else                d->gain = gain;
 }
 
-float tDelayL_getGain (tDelayL* const d)
+float tLinearDelay_getGain (tLinearDelay* const d)
 {
     return d->gain;
 }
 
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ DelayA ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
-void  tDelayA_init (tDelayA* const d, float delay, uint32_t maxDelay)
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ AllpassDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
+void  tAllpassDelay_init (tAllpassDelay* const d, float delay, uint32_t maxDelay)
 {
     d->maxDelay = maxDelay;
     
@@ -309,17 +309,17 @@
     d->inPoint = 0;
     d->outPoint = 0;
     
-    tDelayA_setDelay(d, d->delay);
+    tAllpassDelay_setDelay(d, d->delay);
     
     d->apInput = 0.0f;
 }
 
-void tDelayA_free(tDelayA* const d)
+void tAllpassDelay_free(tAllpassDelay* const d)
 {
     leaf_free(d->buff);
 }
 
-float   tDelayA_tick (tDelayA* const d, float input)
+float   tAllpassDelay_tick (tAllpassDelay* const d, float input)
 {
     d->buff[d->inPoint] = input * d->gain;
     
@@ -340,7 +340,7 @@
     return d->lastOut;
 }
 
-int     tDelayA_setDelay (tDelayA* const d, float delay)
+int     tAllpassDelay_setDelay (tAllpassDelay* const d, float delay)
 {
     d->delay = LEAF_clip(0.5f, delay,  d->maxDelay);
     
@@ -373,7 +373,7 @@
     return 0;
 }
 
-float tDelayA_tapOut (tDelayA* const d, uint32_t tapDelay)
+float tAllpassDelay_tapOut (tAllpassDelay* const d, uint32_t tapDelay)
 {
     int32_t tap = d->inPoint - tapDelay - 1;
     
@@ -384,7 +384,7 @@
     
 }
 
-void tDelayA_tapIn (tDelayA* const d, float value, uint32_t tapDelay)
+void tAllpassDelay_tapIn (tAllpassDelay* const d, float value, uint32_t tapDelay)
 {
     int32_t tap = d->inPoint - tapDelay - 1;
     
@@ -394,7 +394,7 @@
     d->buff[tap] = value;
 }
 
-float tDelayA_addTo (tDelayA* const d, float value, uint32_t tapDelay)
+float tAllpassDelay_addTo (tAllpassDelay* const d, float value, uint32_t tapDelay)
 {
     int32_t tap = d->inPoint - tapDelay - 1;
     
@@ -404,28 +404,28 @@
     return (d->buff[tap] += value);
 }
 
-float   tDelayA_getDelay (tDelayA* const d)
+float   tAllpassDelay_getDelay (tAllpassDelay* const d)
 {
     return d->delay;
 }
 
-float   tDelayA_getLastOut (tDelayA* const d)
+float   tAllpassDelay_getLastOut (tAllpassDelay* const d)
 {
     return d->lastOut;
 }
 
-float   tDelayA_getLastIn (tDelayA* const d)
+float   tAllpassDelay_getLastIn (tAllpassDelay* const d)
 {
     return d->lastIn;
 }
 
-void tDelayA_setGain (tDelayA* const d, float gain)
+void tAllpassDelay_setGain (tAllpassDelay* const d, float gain)
 {
     if (gain < 0.0f)    d->gain = 0.0f;
     else                d->gain = gain;
 }
 
-float tDelayA_getGain (tDelayA* const d)
+float tAllpassDelay_getGain (tAllpassDelay* const d)
 {
     return d->gain;
 }
--- /dev/null
+++ b/LEAF/Src/leaf-distortion.c
@@ -1,0 +1,407 @@
+//
+//  leaf-oversampler.c
+//  LEAF
+//
+//  Created by Matthew Wang and Joshua Becker on 2/28/19.
+//  Copyright © 2019 Princeton University. All rights reserved.
+//
+
+#if _WIN32 || _WIN64
+
+#include "..\Inc\leaf-distortion.h"
+#include "..\Inc\leaf-tables.h"
+#else
+
+
+#include "../Inc/leaf-distortion.h"
+#include "../Inc/leaf-tables.h"
+
+#endif
+
+//============================================================================================================
+// WAVEFOLDER
+//============================================================================================================
+void tLockhartWavefolder_init(tLockhartWavefolder* const w)
+{
+    w->Ln1 = 0.0;
+    w->Fn1 = 0.0;
+    w->xn1 = 0.0f;
+}
+
+void tLockhardWavefolder_free(tLockhartWavefolder* const w)
+{
+    
+}
+
+double tLockhartWavefolderLambert(double x, double ln)
+{
+    double thresh, w, expw, p, r, s, err;
+    // Error threshold
+    thresh = 10e-6;
+    // Initial guess (use previous value)
+    w = ln;
+    
+    // Haley's method (Sec. 4.2 of the paper)
+    for(int i=0; i<100; i+=1) {
+        
+        expw = exp(w);
+        
+        p = w*expw - x;
+        r = (w+1.0)*expw;
+        s = (w+2.0)/(2.0*(w+1.0));        err = (p/(r-(p*s)));
+        
+        if (fabs(err)<thresh) {
+            break;
+        }
+        if (isnan(err))
+        {
+            break;
+        }
+        
+        w = w - err;
+    }
+    return w;
+}
+
+float tLockhartWavefolder_tick(tLockhartWavefolder* const w, float samp)
+{
+    
+    float out = 0.0f;
+    // Constants
+    double RL = 7.5e3;
+    double R = 15e3;
+    double VT = 26e-3;
+    double Is = 10e-16;
+    
+    double a = 2.0*RL/R;
+    double b = (R+2.0*RL)/(VT*R);
+    double d = (RL*Is)/VT;
+    
+    // Antialiasing error threshold
+    double thresh = 10e-10;
+    
+    // Compute Antiderivative
+    int l = (samp > 0) - (samp < 0);
+    double u = d*exp(l*b*samp);
+    double Ln = tLockhartWavefolderLambert(u,w->Ln1);
+    double Fn = (0.5*VT/b)*(Ln*(Ln + 2.0)) - 0.5*a*samp*samp;
+    
+    // Check for ill-conditioning
+    if (fabs(samp-w->xn1)<thresh) {
+        
+        // Compute Averaged Wavefolder Output
+        double xn = 0.5*(samp+w->xn1);
+        u = d*exp(l*b*xn);
+        Ln = tLockhartWavefolderLambert(u,w->Ln1);
+        out = (float) (l*VT*Ln - a*xn);
+        if (isnan(out))
+        {
+            ;
+        }
+        
+    }
+    else {
+        
+        // Apply AA Form
+        out = (float) ((Fn-w->Fn1)/(samp-w->xn1));
+        if (isnan(out))
+        {
+            ;
+        }
+    }
+    
+    // Update States
+    w->Ln1 = Ln;
+    w->Fn1 = Fn;
+    w->xn1 = samp;
+    
+    return out;
+}
+
+//============================================================================================================
+// CRUSHER
+//============================================================================================================
+#define SCALAR 5000.f
+
+void    tCrusher_init    (tCrusher* const c)
+{
+    c->op = 4;
+    c->div = SCALAR;
+    c->rnd = 0.25f;
+    c->srr = 0.25f;
+    
+    c->gain = (c->div / SCALAR) * 0.7f + 0.3f;
+}
+
+void    tCrusher_free    (tCrusher* const c)
+{
+    
+}
+
+float   tCrusher_tick    (tCrusher* const c, float input)
+{
+    float sample = input;
+    
+    sample *= SCALAR; // SCALAR is 5000 by default
+    
+    sample = (int32_t) sample;
+    
+    sample /= c->div;
+    
+    sample = LEAF_bitwise_xor(sample, c->op << 23);
+    
+    sample = LEAF_clip(-1.f, sample, 1.f);
+    
+    sample = LEAF_round(sample, c->rnd);
+    
+    sample = LEAF_reduct(sample, c->srr);
+    
+    return sample * c->gain;
+    
+}
+
+void    tCrusher_setOperation (tCrusher* const c, float op)
+{
+    c->op = (uint32_t) (op * 8.0f);
+}
+
+// 0.0 - 1.0
+void    tCrusher_setQuality (tCrusher* const c, float val)
+{
+    val = LEAF_clip(0.0f, val, 1.0f);
+    
+    c->div = 0.01f + val * SCALAR;
+    
+    c->gain = (c->div / SCALAR) * 0.7f + 0.3f;
+}
+
+// what decimal to round to
+void    tCrusher_setRound (tCrusher* const c, float rnd)
+{
+    c->rnd = fabsf(rnd);
+}
+
+void    tCrusher_setSamplingRatio (tCrusher* const c, float ratio)
+{
+    c->srr = ratio;
+}
+
+
+//============================================================================================================
+// Oversampler
+//============================================================================================================
+// Latency is equal to the phase length (numTaps / ratio)
+void tOversampler_init(tOversampler* const os, int ratio, oBool extraQuality)
+{
+    uint8_t offset = 0;
+    if (extraQuality) offset = 6;
+    if (ratio == 2 || ratio == 4  ||
+        ratio == 8 || ratio == 16 ||
+        ratio == 32 || ratio == 64) {
+        os->ratio = ratio;
+        int idx = (int)(log2f(os->ratio))-1+offset;
+        os->numTaps = firNumTaps[idx];
+        os->phaseLength = os->numTaps / os->ratio;
+        os->pCoeffs = (float*) firCoeffs[idx];
+        os->upState = leaf_alloc(sizeof(float) * os->phaseLength);
+        os->downState = leaf_alloc(sizeof(float) * os->phaseLength);
+    }
+}
+
+void tOversampler_free(tOversampler* const os)
+{
+    leaf_free(os->upState);
+    leaf_free(os->downState);
+}
+
+float tOversampler_tick(tOversampler* const os, float input, float (*effectTick)(float))
+{
+    float buf[os->ratio];
+    
+    tOversampler_upsample(os, input, buf);
+    
+    for (int i = 0; i < os->ratio; ++i) {
+        buf[i] = effectTick(buf[i]);
+    }
+    
+    return tOversampler_downsample(os, buf);
+}
+
+// From CMSIS DSP Library
+void tOversampler_upsample(tOversampler* const os, float input, float* output)
+{
+    float *pState = os->upState;                 /* State pointer */
+    const float *pCoeffs = os->pCoeffs;               /* Coefficient pointer */
+    float *pStateCur;
+    float *ptr1;                               /* Temporary pointer for state buffer */
+    const float *ptr2;                               /* Temporary pointer for coefficient buffer */
+    float sum0;                                /* Accumulators */
+    uint32_t i, tapCnt;                    /* Loop counters */
+    uint32_t phaseLen = os->phaseLength;            /* Length of each polyphase filter component */
+    uint32_t j;
+    
+    /* os->pState buffer contains previous frame (phaseLen - 1) samples */
+    /* pStateCur points to the location where the new input data should be written */
+    pStateCur = os->upState + (phaseLen - 1U);
+    
+    /* Copy new input sample into the state buffer */
+    *pStateCur = input;
+    
+    /* Address modifier index of coefficient buffer */
+    j = 1U;
+    
+    /* Loop over the Interpolation factor. */
+    i = os->ratio;
+    
+    while (i > 0U)
+    {
+        /* Set accumulator to zero */
+        sum0 = 0.0f;
+        
+        /* Initialize state pointer */
+        ptr1 = pState;
+        
+        /* Initialize coefficient pointer */
+        ptr2 = pCoeffs + (os->ratio - j);
+        
+        /* Loop over the polyPhase length.
+         Repeat until we've computed numTaps-(4*os->L) coefficients. */
+        
+        /* Initialize tapCnt with number of samples */
+        tapCnt = phaseLen;
+        
+        while (tapCnt > 0U)
+        {
+            /* Perform the multiply-accumulate */
+            sum0 += *ptr1++ * *ptr2;
+            
+            /* Upsampling is done by stuffing L-1 zeros between each sample.
+             * So instead of multiplying zeros with coefficients,
+             * Increment the coefficient pointer by interpolation factor times. */
+            ptr2 += os->ratio;
+            
+            /* Decrement loop counter */
+            tapCnt--;
+        }
+        
+        /* The result is in the accumulator, store in the destination buffer. */
+        *output++ = sum0 * os->ratio;
+        
+        /* Increment the address modifier index of coefficient buffer */
+        j++;
+        
+        /* Decrement the loop counter */
+        i--;
+    }
+    
+    /* Advance the state pointer by 1
+     * to process the next group of interpolation factor number samples */
+    pState = pState + 1;
+    
+    /* Processing is complete.
+     Now copy the last phaseLen - 1 samples to the satrt of the state buffer.
+     This prepares the state buffer for the next function call. */
+    
+    /* Points to the start of the state buffer */
+    pStateCur = os->upState;
+
+    /* Initialize tapCnt with number of samples */
+    tapCnt = (phaseLen - 1U);
+    
+    /* Copy data */
+    while (tapCnt > 0U)
+    {
+        *pStateCur++ = *pState++;
+        
+        /* Decrement loop counter */
+        tapCnt--;
+    }
+}
+
+// From CMSIS DSP Library
+float tOversampler_downsample(tOversampler *const os, float* input)
+{
+    float *pState = os->downState;                 /* State pointer */
+    const float *pCoeffs = os->pCoeffs;               /* Coefficient pointer */
+    float *pStateCur;                          /* Points to the current sample of the state */
+    float *px0;                                /* Temporary pointer for state buffer */
+    const float *pb;                                 /* Temporary pointer for coefficient buffer */
+    float x0, c0;                              /* Temporary variables to hold state and coefficient values */
+    float acc0;                                /* Accumulator */
+    uint32_t numTaps = os->numTaps;                 /* Number of filter coefficients in the filter */
+    uint32_t i, tapCnt;
+    float output;
+    
+    /* os->pState buffer contains previous frame (numTaps - 1) samples */
+    /* pStateCur points to the location where the new input data should be written */
+    pStateCur = os->downState + (numTaps - 1U);
+    
+    /* Copy decimation factor number of new input samples into the state buffer */
+    i = os->ratio;
+    
+    do
+    {
+        *pStateCur++ = *input++;
+        
+    } while (--i);
+    
+    /* Set accumulator to zero */
+    acc0 = 0.0f;
+    
+    /* Initialize state pointer */
+    px0 = pState;
+    
+    /* Initialize coeff pointer */
+    pb = pCoeffs;
+    
+    /* Initialize tapCnt with number of taps */
+    tapCnt = numTaps;
+    
+    while (tapCnt > 0U)
+    {
+        /* Read coefficients */
+        c0 = *pb++;
+        
+        /* Fetch 1 state variable */
+        x0 = *px0++;
+        
+        /* Perform the multiply-accumulate */
+        acc0 += x0 * c0;
+        
+        /* Decrement loop counter */
+        tapCnt--;
+    }
+    
+    /* Advance the state pointer by the decimation factor
+     * to process the next group of decimation factor number samples */
+    pState = pState + os->ratio;
+    
+    /* The result is in the accumulator, store in the destination buffer. */
+    output = acc0;
+    
+    /* Processing is complete.
+     Now copy the last numTaps - 1 samples to the satrt of the state buffer.
+     This prepares the state buffer for the next function call. */
+    
+    /* Points to the start of the state buffer */
+    pStateCur = os->downState;
+    
+    /* Initialize tapCnt with number of taps */
+    tapCnt = (numTaps - 1U);
+    
+    /* Copy data */
+    while (tapCnt > 0U)
+    {
+        *pStateCur++ = *pState++;
+        
+        /* Decrement loop counter */
+        tapCnt--;
+    }
+    
+    return output;
+}
+
+int tOversampler_getLatency(tOversampler* const os)
+{
+    return os->phaseLength;
+}
--- /dev/null
+++ b/LEAF/Src/leaf-dynamics.c
@@ -1,0 +1,172 @@
+/*==============================================================================
+
+    leaf-dynamics.c
+    Created: 30 Nov 2018 11:56:49am
+    Author:  airship
+
+==============================================================================*/
+
+#if _WIN32 || _WIN64
+
+#include "..\Inc\leaf-dynamics.h"
+
+#else
+
+#include "../Inc/leaf-dynamics.h"
+
+#endif
+
+//==============================================================================
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Compressor ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
+
+/*
+ tCompressor*    tCompressorInit(int tauAttack, int tauRelease)
+ {
+ tCompressor* c = &leaf.tCompressorRegistry[leaf.registryIndex[T_COMPRESSOR]++];
+ 
+ c->tauAttack = tauAttack;
+ c->tauRelease = tauRelease;
+ 
+ c->x_G[0] = 0.0f, c->x_G[1] = 0.0f,
+ c->y_G[0] = 0.0f, c->y_G[1] = 0.0f,
+ c->x_T[0] = 0.0f, c->x_T[1] = 0.0f,
+ c->y_T[0] = 0.0f, c->y_T[1] = 0.0f;
+ 
+ c->T = 0.0f; // Threshold
+ c->R = 1.0f; // compression Ratio
+ c->M = 0.0f; // decibel Make-up gain
+ c->W = 0.0f; // decibel Width of knee transition
+ 
+ return c;
+ }
+ */
+void    tCompressor_init(tCompressor* const c)
+{
+    c->tauAttack = 100;
+    c->tauRelease = 100;
+    
+    c->isActive = OFALSE;
+    
+    c->T = 0.0f; // Threshold
+    c->R = 0.5f; // compression Ratio
+    c->M = 3.0f; // decibel Width of knee transition
+    c->W = 1.0f; // decibel Make-up gain
+}
+
+void tCompressor_free(tCompressor* const c)
+{
+    
+}
+
+int ccount = 0;
+float tCompressor_tick(tCompressor* const c, float in)
+{
+    float slope, overshoot;
+    float alphaAtt, alphaRel;
+    
+    float in_db = 20.0f * log10f( fmaxf( fabsf( in), 0.000001f)), out_db = 0.0f;
+    
+    c->y_T[1] = c->y_T[0];
+    
+    slope = c->R - 1.0f; // feed-forward topology; was 1/C->R - 1
+    
+    overshoot = in_db - c->T;
+    
+    
+    if (overshoot <= -(c->W * 0.5f))
+    {
+        out_db = in_db;
+        c->isActive = OFALSE;
+    }
+    else if ((overshoot > -(c->W * 0.5f)) && (overshoot < (c->W * 0.5f)))
+    {
+        out_db = in_db + slope * (powf((overshoot + c->W*0.5f),2) / (2.0f * c->W)); // .^ 2 ???
+        c->isActive = OTRUE;
+    }
+    else if (overshoot >= (c->W * 0.5f))
+    {
+        out_db = in_db + slope * overshoot;
+        c->isActive = OTRUE;
+    }
+    
+    
+    
+    c->x_T[0] = out_db - in_db;
+    
+    alphaAtt = expf(-1.0f/(0.001f * c->tauAttack * leaf.sampleRate));
+    alphaRel = expf(-1.0f/(0.001f * c->tauRelease * leaf.sampleRate));
+    
+    if (c->x_T[0] > c->y_T[1])
+        c->y_T[0] = alphaAtt * c->y_T[1] + (1-alphaAtt) * c->x_T[0];
+    else
+        c->y_T[0] = alphaRel * c->y_T[1] + (1-alphaRel) * c->x_T[0];
+    
+    float attenuation = powf(10.0f, ((c->M - c->y_T[0])/20.0f));
+    
+    /*
+     if (++ccount > 5000)
+     {
+     
+     ccount = 0;
+     DBG(".5width: " + String(c->W * 0.5f));
+     DBG("slope: " + String(slope) + " overshoot: " + String(overshoot));
+     DBG("attenuation: " + String(attenuation));
+     }
+     */
+    return attenuation * in;
+    
+    
+}
+
+/* Feedback Leveler */
+
+void    tFeedbackLeveler_init(tFeedbackLeveler* const p, float targetLevel, float factor, float strength, int mode)
+{
+    p->curr=0.0f;
+    p->targetLevel=targetLevel;
+    tPowerFollower_init(&p->pwrFlw,factor);
+    p->mode=mode;
+    p->strength=strength;
+}
+
+void tFeedbackLeveler_free(tFeedbackLeveler* const p)
+{
+    tPowerFollower_free(&p->pwrFlw);
+}
+
+void     tFeedbackLeveler_setStrength(tFeedbackLeveler* const p, float strength)
+{    // strength is how strongly level diff is affecting the amp ratio
+    // try 0.125 for a start
+    p->strength=strength;
+}
+
+void     tFeedbackLeveler_setFactor(tFeedbackLeveler* const p, float factor)
+{
+    tPowerFollower_setFactor(&p->pwrFlw,factor);
+}
+
+void     tFeedbackLeveler_setMode(tFeedbackLeveler* const p, int mode)
+{    // 0 for decaying with upwards lev limiting, 1 for constrained absolute level (also downwards limiting)
+    p->mode=mode;
+}
+
+float   tFeedbackLeveler_tick(tFeedbackLeveler* const p, float input)
+{
+    float levdiff=(tPowerFollower_tick(&p->pwrFlw, input)-p->targetLevel);
+    if (p->mode==0 && levdiff<0) levdiff=0;
+    p->curr=input*(1-p->strength*levdiff);
+    return p->curr;
+}
+
+float   tFeedbackLeveler_sample(tFeedbackLeveler* const p)
+{
+    return p->curr;
+}
+
+
+void     tFeedbackLeveler_setTargetLevel   (tFeedbackLeveler* const p, float TargetLevel)
+{
+    p->targetLevel=TargetLevel;
+}
+
--- /dev/null
+++ b/LEAF/Src/leaf-effects.c
@@ -1,0 +1,1393 @@
+/*==============================================================================
+
+    leaf-vocoder.c
+    Created: 20 Jan 2017 12:01:54pm
+    Author:  Michael R Mulshine
+
+==============================================================================*/
+
+#if _WIN32 || _WIN64
+
+#include "..\Inc\leaf-effects.c"
+#include "..\leaf.h"
+
+#else
+
+#include "../Inc/leaf-effects.h"
+#include "../leaf.h"
+
+#endif
+
+
+
+//============================================================================================================
+// TALKBOX
+//============================================================================================================
+
+void tTalkbox_init(tTalkbox* const v, int bufsize)
+{
+    v->param[0] = 0.5f;  //wet
+    v->param[1] = 0.0f;  //dry
+    v->param[2] = 0; // Swap
+    v->param[3] = 1.0f;  //quality
+    
+    v->bufsize = bufsize;
+    
+    v->car0 =   (float*) leaf_alloc(sizeof(float) * v->bufsize);
+    v->car1 =   (float*) leaf_alloc(sizeof(float) * v->bufsize);
+    v->window = (float*) leaf_alloc(sizeof(float) * v->bufsize);
+    v->buf0 =   (float*) leaf_alloc(sizeof(float) * v->bufsize);
+    v->buf1 =   (float*) leaf_alloc(sizeof(float) * v->bufsize);
+    
+    tTalkbox_update(v);
+}
+
+void tTalkbox_free(tTalkbox* const v)
+{
+    leaf_free(v->car0);
+    leaf_free(v->car1);
+    leaf_free(v->window);
+    leaf_free(v->buf0);
+    leaf_free(v->buf1);
+}
+
+void tTalkbox_update(tTalkbox* const v) ///update internal parameters...
+{
+    float fs = leaf.sampleRate;
+    if(fs <  8000.0f) fs =  8000.0f;
+    if(fs > 96000.0f) fs = 96000.0f;
+    
+    int32_t n = (int32_t)(0.01633f * fs);
+    if(n > v->bufsize) n = v->bufsize;
+    
+    //O = (VstInt32)(0.0005f * fs);
+    v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * fs);
+    
+    if(n != v->N) //recalc hanning window
+    {
+        v->N = n;
+        float dp = TWO_PI / v->N;
+        float p = 0.0f;
+        for(n=0; n<v->N; n++)
+        {
+            v->window[n] = 0.5f - 0.5f * cosf(p);
+            p += dp;
+        }
+    }
+    v->wet = 0.5f * v->param[0] * v->param[0];
+    v->dry = 2.0f * v->param[1] * v->param[1];
+}
+
+void tTalkbox_suspend(tTalkbox* const v) ///clear any buffers...
+{
+    v->pos = v->K = 0;
+    v->emphasis = 0.0f;
+    v->FX = 0;
+    
+    v->u0 = v->u1 = v->u2 = v->u3 = v->u4 = 0.0f;
+    v->d0 = v->d1 = v->d2 = v->d3 = v->d4 = 0.0f;
+    
+    for (int32_t i = 0; i < v->bufsize; i++)
+    {
+        v->buf0[i] = 0;
+        v->buf1[i] = 0;
+        v->car0[i] = 0;
+        v->car1[i] = 0;
+    }
+}
+
+
+#define ORD_MAX           100 // Was 50. Increasing this gets rid of glitchiness, lowering it breaks it; not sure how it affects performance
+void tTalkbox_lpc(float *buf, float *car, int32_t n, int32_t o)
+{
+    float z[ORD_MAX], r[ORD_MAX], k[ORD_MAX], G, x;
+    int32_t i, j, nn=n;
+    
+    for(j=0; j<=o; j++, nn--)  //buf[] is already emphasized and windowed
+    {
+        z[j] = r[j] = 0.0f;
+        for(i=0; i<nn; i++) r[j] += buf[i] * buf[i+j]; //autocorrelation
+    }
+    r[0] *= 1.001f;  //stability fix
+    
+    float min = 0.00001f;
+    if(r[0] < min) { for(i=0; i<n; i++) buf[i] = 0.0f; return; }
+    
+    tTalkbox_lpcDurbin(r, o, k, &G);  //calc reflection coeffs
+    
+    for(i=0; i<=o; i++)
+    {
+        if(k[i] > 0.995f) k[i] = 0.995f; else if(k[i] < -0.995f) k[i] = -.995f;
+    }
+    
+    for(i=0; i<n; i++)
+    {
+        x = G * car[i];
+        for(j=o; j>0; j--)  //lattice filter
+        {
+            x -= k[j] * z[j-1];
+            z[j] = z[j-1] + k[j] * x;
+        }
+        buf[i] = z[0] = x;  //output buf[] will be windowed elsewhere
+    }
+}
+
+
+void tTalkbox_lpcDurbin(float *r, int p, float *k, float *g)
+{
+    int i, j;
+    float a[ORD_MAX], at[ORD_MAX], e=r[0];
+    
+    for(i=0; i<=p; i++) a[i] = at[i] = 0.0f; //probably don't need to clear at[] or k[]
+    
+    for(i=1; i<=p; i++)
+    {
+        k[i] = -r[i];
+        
+        for(j=1; j<i; j++)
+        {
+            at[j] = a[j];
+            k[i] -= a[j] * r[i-j];
+        }
+        if(fabs(e) < 1.0e-20f) { e = 0.0f;  break; }
+        k[i] /= e; // This might be costing us
+        
+        a[i] = k[i];
+        for(j=1; j<i; j++) a[j] = at[j] + k[i] * at[i-j];
+        
+        e *= 1.0f - k[i] * k[i];
+    }
+    
+    if(e < 1.0e-20f) e = 0.0f;
+    *g = sqrtf(e);
+}
+
+float tTalkbox_tick(tTalkbox* const v, float synth, float voice)
+{
+
+    int32_t  p0=v->pos, p1 = (v->pos + v->N/2) % v->N;
+    float e=v->emphasis, w, o, x, dr, fx=v->FX;
+    float p, q, h0=0.3f, h1=0.77f;
+    
+    o = voice;
+    x = synth;
+    
+    dr = o;
+    
+    p = v->d0 + h0 *  x; v->d0 = v->d1;  v->d1 = x  - h0 * p;
+    q = v->d2 + h1 * v->d4; v->d2 = v->d3;  v->d3 = v->d4 - h1 * q;
+    v->d4 = x;
+    x = p + q;
+    
+    if(v->K++)
+    {
+        v->K = 0;
+        
+        v->car0[p0] = v->car1[p1] = x; //carrier input
+        
+        x = o - e;  e = o;  //6dB/oct pre-emphasis
+        
+        w = v->window[p0]; fx = v->buf0[p0] * w;  v->buf0[p0] = x * w;  //50% overlapping hanning windows
+        if(++p0 >= v->N) { tTalkbox_lpc(v->buf0, v->car0, v->N, v->O);  p0 = 0; }
+        
+        w = 1.0f - w;  fx += v->buf1[p1] * w;  v->buf1[p1] = x * w;
+        if(++p1 >= v->N) { tTalkbox_lpc(v->buf1, v->car1, v->N, v->O);  p1 = 0; }
+    }
+    
+    p = v->u0 + h0 * fx; v->u0 = v->u1;  v->u1 = fx - h0 * p;
+    q = v->u2 + h1 * v->u4; v->u2 = v->u3;  v->u3 = v->u4 - h1 * q;
+    v->u4 = fx;
+    x = p + q;
+    
+    o = x;
+    
+    v->emphasis = e;
+    v->pos = p0;
+    v->FX = fx;
+
+    float den = 1.0e-10f; //(float)pow(10.0f, -10.0f * param[4]);
+    if(fabs(v->d0) < den) v->d0 = 0.0f; //anti-denormal (doesn't seem necessary but P4?)
+    if(fabs(v->d1) < den) v->d1 = 0.0f;
+    if(fabs(v->d2) < den) v->d2 = 0.0f;
+    if(fabs(v->d3) < den) v->d3 = 0.0f;
+    if(fabs(v->u0) < den) v->u0 = 0.0f;
+    if(fabs(v->u1) < den) v->u1 = 0.0f;
+    if(fabs(v->u2) < den) v->u2 = 0.0f;
+    if(fabs(v->u3) < den) v->u3 = 0.0f;
+    return o;
+}
+
+void tTalkbox_setQuality(tTalkbox* const v, float quality)
+{
+	v->param[3] = quality;
+	v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * leaf.sampleRate);
+}
+
+
+//============================================================================================================
+// VOCODER
+//============================================================================================================
+
+void   tVocoder_init        (tVocoder* const v)
+{
+    v->param[0] = 0.33f;  //input select
+    v->param[1] = 0.50f;  //output dB
+    v->param[2] = 0.40f;  //hi thru
+    v->param[3] = 0.40f;  //hi band
+    v->param[4] = 0.16f;  //envelope
+    v->param[5] = 0.55f;  //filter q
+    v->param[6] = 0.6667f;//freq range
+    v->param[7] = 0.33f;  //num bands
+    
+    tVocoder_update(v);
+}
+
+void tVocoder_free (tVocoder* const v)
+{
+    
+}
+
+void        tVocoder_update      (tVocoder* const v)
+{
+    float tpofs = 6.2831853f * leaf.invSampleRate;
+    
+    float rr, th, re;
+    
+    float sh;
+    
+    int32_t i;
+    
+    v->gain = (float)pow(10.0f, 2.0f * v->param[1] - 3.0f * v->param[5] - 2.0f);
+    
+    v->thru = (float)pow(10.0f, 0.5f + 2.0f * v->param[1]);
+    v->high =  v->param[3] * v->param[3] * v->param[3] * v->thru;
+    v->thru *= v->param[2] * v->param[2] * v->param[2];
+    
+    if(v->param[7]<0.5f)
+    {
+        v->nbnd=8;
+        re=0.003f;
+        v->f[1][2] = 3000.0f;
+        v->f[2][2] = 2200.0f;
+        v->f[3][2] = 1500.0f;
+        v->f[4][2] = 1080.0f;
+        v->f[5][2] = 700.0f;
+        v->f[6][2] = 390.0f;
+        v->f[7][2] = 190.0f;
+    }
+    else
+    {
+        v->nbnd=16;
+        re=0.0015f;
+        v->f[ 1][2] = 5000.0f; //+1000
+        v->f[ 2][2] = 4000.0f; //+750
+        v->f[ 3][2] = 3250.0f; //+500
+        v->f[ 4][2] = 2750.0f; //+450
+        v->f[ 5][2] = 2300.0f; //+300
+        v->f[ 6][2] = 2000.0f; //+250
+        v->f[ 7][2] = 1750.0f; //+250
+        v->f[ 8][2] = 1500.0f; //+250
+        v->f[ 9][2] = 1250.0f; //+250
+        v->f[10][2] = 1000.0f; //+250
+        v->f[11][2] =  750.0f; //+210
+        v->f[12][2] =  540.0f; //+190
+        v->f[13][2] =  350.0f; //+155
+        v->f[14][2] =  195.0f; //+100
+        v->f[15][2] =   95.0f;
+    }
+    
+    if(v->param[4]<0.05f) //freeze
+    {
+        for(i=0;i<v->nbnd;i++) v->f[i][12]=0.0f;
+    }
+    else
+    {
+        v->f[0][12] = (float)pow(10.0, -1.7 - 2.7f * v->param[4]); //envelope speed
+        
+        rr = 0.022f / (float)v->nbnd; //minimum proportional to frequency to stop distortion
+        for(i=1;i<v->nbnd;i++)
+        {
+            v->f[i][12] = (float)(0.025 - rr * (double)i);
+            if(v->f[0][12] < v->f[i][12]) v->f[i][12] = v->f[0][12];
+        }
+        v->f[0][12] = 0.5f * v->f[0][12]; //only top band is at full rate
+    }
+    
+    rr = 1.0 - pow(10.0f, -1.0f - 1.2f * v->param[5]);
+    sh = (float)pow(2.0f, 3.0f * v->param[6] - 1.0f); //filter bank range shift
+    
+    for(i=1;i<v->nbnd;i++)
+    {
+        v->f[i][2] *= sh;
+        th = acos((2.0 * rr * cos(tpofs * v->f[i][2])) / (1.0 + rr * rr));
+        v->f[i][0] = (float)(2.0 * rr * cos(th)); //a0
+        v->f[i][1] = (float)(-rr * rr);           //a1
+        //was .98
+        v->f[i][2] *= 0.96f; //shift 2nd stage slightly to stop high resonance peaks
+        th = acos((2.0 * rr * cos(tpofs * v->f[i][2])) / (1.0 + rr * rr));
+        v->f[i][2] = (float)(2.0 * rr * cos(th));
+    }
+}
+
+float       tVocoder_tick        (tVocoder* const v, float synth, float voice)
+{
+    float a, b, o=0.0f, aa, bb, oo = v->kout, g = v->gain, ht = v->thru, hh = v->high, tmp;
+    uint32_t i, k = v->kval, nb = v->nbnd;
+
+    a = voice; //speech
+    b = synth; //synth
+    
+    tmp = a - v->f[0][7]; //integrate modulator for HF band and filter bank pre-emphasis
+    v->f[0][7] = a;
+    a = tmp;
+    
+    if(tmp<0.0f) tmp = -tmp;
+    v->f[0][11] -= v->f[0][12] * (v->f[0][11] - tmp);      //high band envelope
+    o = v->f[0][11] * (ht * a + hh * (b - v->f[0][3])); //high band + high thru
+    
+    v->f[0][3] = b; //integrate carrier for HF band
+    
+    if(++k & 0x1) //this block runs at half sample rate
+    {
+        oo = 0.0f;
+        aa = a + v->f[0][9] - v->f[0][8] - v->f[0][8];  //apply zeros here instead of in each reson
+        v->f[0][9] = v->f[0][8];  v->f[0][8] = a;
+        bb = b + v->f[0][5] - v->f[0][4] - v->f[0][4];
+        v->f[0][5] = v->f[0][4];  v->f[0][4] = b;
+        
+        for(i=1; i<nb; i++) //filter bank: 4th-order band pass
+        {
+            tmp = v->f[i][0] * v->f[i][3] + v->f[i][1] * v->f[i][4] + bb;
+            v->f[i][4] = v->f[i][3];
+            v->f[i][3] = tmp;
+            tmp += v->f[i][2] * v->f[i][5] + v->f[i][1] * v->f[i][6];
+            v->f[i][6] = v->f[i][5];
+            v->f[i][5] = tmp;
+            
+            tmp = v->f[i][0] * v->f[i][7] + v->f[i][1] * v->f[i][8] + aa;
+            v->f[i][8] = v->f[i][7];
+            v->f[i][7] = tmp;
+            tmp += v->f[i][2] * v->f[i][9] + v->f[i][1] * v->f[i][10];
+            v->f[i][10] = v->f[i][9];
+            v->f[i][9] = tmp;
+            
+            if(tmp<0.0f) tmp = -tmp;
+            v->f[i][11] -= v->f[i][12] * (v->f[i][11] - tmp);
+            oo += v->f[i][5] * v->f[i][11];
+        }
+    }
+    o += oo * g; //effect of interpolating back up to Fs would be minimal (aliasing >16kHz)
+
+    v->kout = oo;
+    v->kval = k & 0x1;
+    if(fabs(v->f[0][11])<1.0e-10) v->f[0][11] = 0.0f; //catch HF envelope denormal
+    
+    for(i=1;i<nb;i++)
+        if(fabs(v->f[i][3])<1.0e-10 || fabs(v->f[i][7])<1.0e-10)
+            for(k=3; k<12; k++) v->f[i][k] = 0.0f; //catch reson & envelope denormals
+    
+    if(fabs(o)>10.0f) tVocoder_suspend(v); //catch instability
+    
+    return o;
+    
+}
+
+void        tVocoder_suspend     (tVocoder* const v)
+{
+    int32_t i, j;
+    
+    for(i=0; i<v->nbnd; i++) for(j=3; j<12; j++) v->f[i][j] = 0.0f; //zero band filters and envelopes
+    v->kout = 0.0f;
+    v->kval = 0;
+}
+
+//============================================================================================================
+// PITCHSHIFTER
+//============================================================================================================
+static int pitchshifter_attackdetect(tPitchShifter* ps);
+
+void tPitchShifter_init(tPitchShifter* const ps, float* in, float* out, int bufSize, int frameSize)
+{
+    ps->inBuffer = in;
+    ps->outBuffer = out;
+    ps->bufSize = bufSize;
+    ps->frameSize = frameSize;
+    ps->framesPerBuffer = ps->bufSize / ps->frameSize;
+    ps->curBlock = 1;
+    ps->lastBlock = 0;
+    ps->index = 0;
+    
+    ps->hopSize = DEFHOPSIZE;
+    ps->windowSize = DEFWINDOWSIZE;
+    ps->fba = FBA;
+    
+    tEnvPD_init(&ps->env, ps->windowSize, ps->hopSize, ps->frameSize);
+    
+    tSNAC_init(&ps->snac, DEFOVERLAP);
+    
+    tSOLAD_init(&ps->sola);
+    
+    tHighpass_init(&ps->hp, HPFREQ);
+    
+    tSOLAD_setPitchFactor(&ps->sola, DEFPITCHRATIO);
+    
+    tPitchShifter_setTimeConstant(ps, DEFTIMECONSTANT);
+}
+
+void tPitchShifter_free(tPitchShifter* const ps)
+{
+    tEnvPD_free(&ps->env);
+    tSNAC_free(&ps->snac);
+    tSOLAD_free(&ps->sola);
+    tHighpass_free(&ps->hp);
+}
+
+float tPitchShifter_tick(tPitchShifter* ps, float sample)
+{
+    float period, out;
+    int i, iLast;
+    
+    i = (ps->curBlock*ps->frameSize);
+    iLast = (ps->lastBlock*ps->frameSize)+ps->index;
+    
+    out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
+    ps->inBuffer[i+ps->index] = sample;
+    
+    ps->index++;
+    if (ps->index >= ps->frameSize)
+    {
+        ps->index = 0;
+        
+        tEnvPD_processBlock(&ps->env, &(ps->inBuffer[i]));
+        
+        if(pitchshifter_attackdetect(ps) == 1)
+        {
+            ps->fba = 5;
+            tSOLAD_setReadLag(&ps->sola, ps->windowSize);
+        }
+        
+        tSNAC_ioSamples(&ps->snac, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
+        period = tSNAC_getPeriod(&ps->snac);
+        
+        ps->curBlock++;
+        if (ps->curBlock >= ps->framesPerBuffer) ps->curBlock = 0;
+        ps->lastBlock++;
+        if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0;
+        
+        //separate here
+        
+        tSOLAD_setPeriod(&ps->sola, period);
+        
+        tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
+        tSOLAD_ioSamples(&ps->sola, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
+        
+    }
+    
+    return out;
+}
+
+float tPitchShifterToFreq_tick(tPitchShifter* ps, float sample, float freq)
+{
+    float period, out;
+    int i, iLast;
+    
+    i = (ps->curBlock*ps->frameSize);
+    iLast = (ps->lastBlock*ps->frameSize)+ps->index;
+    
+    out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
+    ps->inBuffer[i+ps->index] = sample;
+    
+    ps->index++;
+    if (ps->index >= ps->frameSize)
+    {
+        ps->index = 0;
+        
+        tEnvPD_processBlock(&ps->env, &(ps->inBuffer[i]));
+        
+        if(pitchshifter_attackdetect(ps) == 1)
+        {
+            ps->fba = 5;
+            tSOLAD_setReadLag(&ps->sola, ps->windowSize);
+        }
+        
+        tSNAC_ioSamples(&ps->snac, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
+        period = tSNAC_getPeriod(&ps->snac);
+        
+        tSOLAD_setPeriod(&ps->sola, period);
+        
+        ps->pitchFactor = period*freq*leaf.invSampleRate;
+        tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
+        tSOLAD_ioSamples(&ps->sola, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
+        
+        ps->curBlock++;
+        if (ps->curBlock >= ps->framesPerBuffer) ps->curBlock = 0;
+        ps->lastBlock++;
+        if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0;
+    }
+    
+    return out;
+}
+
+float tPitchShifterToFunc_tick(tPitchShifter* ps, float sample, float (*fun)(float))
+{
+    float period, out;
+    int i, iLast;
+    
+    i = (ps->curBlock*ps->frameSize);
+    iLast = (ps->lastBlock*ps->frameSize)+ps->index;
+    
+    out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
+    ps->inBuffer[i+ps->index] = sample;
+    
+    ps->index++;
+    if (ps->index >= ps->frameSize)
+    {
+        ps->index = 0;
+        
+        tEnvPD_processBlock(&ps->env, &(ps->inBuffer[i]));
+        
+        if(pitchshifter_attackdetect(ps) == 1)
+        {
+            ps->fba = 5;
+            tSOLAD_setReadLag(&ps->sola, ps->windowSize);
+        }
+        
+        tSNAC_ioSamples(&ps->snac, (&ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
+        period = tSNAC_getPeriod(&ps->snac);
+        
+        tSOLAD_setPeriod(&ps->sola, period);
+        
+        ps->pitchFactor = period/fun(period);
+        tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
+        tSOLAD_ioSamples(&ps->sola, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
+        
+        ps->curBlock++;
+        if (ps->curBlock >= ps->framesPerBuffer) ps->curBlock = 0;
+        ps->lastBlock++;
+        if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0;
+    }
+    
+    return out;
+}
+
+void tPitchShifter_ioSamples(tPitchShifter* ps, float* in, float* out, int size)
+{
+    float period;
+    
+    tEnvPD_processBlock(&ps->env, in);
+    
+    if(pitchshifter_attackdetect(ps) == 1)
+    {
+        ps->fba = 5;
+        tSOLAD_setReadLag(&ps->sola, ps->windowSize);
+    }
+    
+    tSNAC_ioSamples(&ps->snac, in, out, size);
+    period = tSNAC_getPeriod(&ps->snac);
+    
+    tSOLAD_setPeriod(&ps->sola, period);
+    
+    tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
+    tSOLAD_ioSamples(&ps->sola, in, out, size);
+    
+    for (int cc = 0; cc < size; ++cc)
+    {
+        out[cc] = tHighpass_tick(&ps->hp, out[cc]);
+    }
+}
+
+void tPitchShifter_ioSamples_toFreq(tPitchShifter* ps, float* in, float* out, int size, float toFreq)
+{
+    float period;
+    
+    tEnvPD_processBlock(&ps->env, in);
+    
+    if(pitchshifter_attackdetect(ps) == 1)
+    {
+        ps->fba = 5;
+        tSOLAD_setReadLag(&ps->sola, ps->windowSize);
+    }
+    
+    tSNAC_ioSamples(&ps->snac, in, out, size);
+    period = tSNAC_getPeriod(&ps->snac);
+    
+    tSOLAD_setPeriod(&ps->sola, period);
+    ps->pitchFactor = period*toFreq;
+    tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
+    tSOLAD_ioSamples(&ps->sola, in, out, size);
+    
+    for (int cc = 0; cc < size; ++cc)
+    {
+        out[cc] = tHighpass_tick(&ps->hp, out[cc]);
+    }
+}
+
+void tPitchShifter_ioSamples_toPeriod(tPitchShifter* ps, float* in, float* out, int size, float toPeriod)
+{
+    float period;
+    
+    tEnvPD_processBlock(&ps->env, in);
+    
+    if(pitchshifter_attackdetect(ps) == 1)
+    {
+        ps->fba = 5;
+        tSOLAD_setReadLag(&ps->sola, ps->windowSize);
+    }
+    
+    tSNAC_ioSamples(&ps->snac, in, out, size);
+    period = tSNAC_getPeriod(&ps->snac);
+    
+    tSOLAD_setPeriod(&ps->sola, period);
+    ps->pitchFactor = period/toPeriod;
+    tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
+    tSOLAD_ioSamples(&ps->sola, in, out, size);
+    
+    for (int cc = 0; cc < size; ++cc)
+    {
+        out[cc] = tHighpass_tick(&ps->hp, out[cc]);
+    }
+}
+
+void tPitchShifter_ioSamples_toFunc(tPitchShifter* ps, float* in, float* out, int size, float (*fun)(float))
+{
+    float period;
+    
+    tEnvPD_processBlock(&ps->env, in);
+    
+    if(pitchshifter_attackdetect(ps) == 1)
+    {
+        ps->fba = 5;
+        tSOLAD_setReadLag(&ps->sola, ps->windowSize);
+    }
+    
+    tSNAC_ioSamples(&ps->snac, in, out, size);
+    period = tSNAC_getPeriod(&ps->snac);
+    
+    tSOLAD_setPeriod(&ps->sola, period);
+    ps->pitchFactor = period/fun(period);
+    tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
+    tSOLAD_ioSamples(&ps->sola, in, out, size);
+    
+    for (int cc = 0; cc < size; ++cc)
+    {
+        out[cc] = tHighpass_tick(&ps->hp, out[cc]);
+    }
+}
+
+void tPitchShifter_setPitchFactor(tPitchShifter* ps, float pf)
+{
+    ps->pitchFactor = pf;
+}
+
+void tPitchShifter_setTimeConstant(tPitchShifter* ps, float tc)
+{
+    ps->timeConstant = tc;
+    ps->radius = expf(-1000.0f * ps->hopSize * leaf.invSampleRate / ps->timeConstant);
+}
+
+void tPitchShifter_setHopSize(tPitchShifter* ps, int hs)
+{
+    ps->hopSize = hs;
+}
+
+void tPitchShifter_setWindowSize(tPitchShifter* ps, int ws)
+{
+    ps->windowSize = ws;
+}
+
+float tPitchShifter_getPeriod(tPitchShifter* ps)
+{
+    return tSNAC_getPeriod(&ps->snac);
+}
+
+static int pitchshifter_attackdetect(tPitchShifter* ps)
+{
+    float envout;
+    
+    envout = tEnvPD_tick(&ps->env);
+    
+    if (envout >= 1.0f)
+    {
+        ps->lastmax = ps->max;
+        if (envout > ps->max)
+        {
+            ps->max = envout;
+        }
+        else
+        {
+            ps->deltamax = envout - ps->max;
+            ps->max = ps->max * ps->radius;
+        }
+        ps->deltamax = ps->max - ps->lastmax;
+    }
+    
+    ps->fba = ps->fba ? (ps->fba - 1) : 0;
+    
+    return (ps->fba == 0 && (ps->max > 60 && ps->deltamax > 6)) ? 1 : 0;
+}
+
+
+//============================================================================================================
+// PITCHSHIFT
+//============================================================================================================
+
+static int pitchshift_attackdetect(tPitchShift* ps)
+{
+    float envout;
+    
+    envout = tEnvPD_tick(&ps->p->env);
+    
+    if (envout >= 1.0f)
+    {
+        ps->p->lastmax = ps->p->max;
+        if (envout > ps->p->max)
+        {
+            ps->p->max = envout;
+        }
+        else
+        {
+            ps->p->deltamax = envout - ps->p->max;
+            ps->p->max = ps->p->max * ps->radius;
+        }
+        ps->p->deltamax = ps->p->max - ps->p->lastmax;
+    }
+    
+    ps->p->fba = ps->p->fba ? (ps->p->fba - 1) : 0;
+    
+    return (ps->p->fba == 0 && (ps->p->max > 60 && ps->p->deltamax > 6)) ? 1 : 0;
+}
+
+void tPitchShift_init (tPitchShift* const ps,tPeriodDetection* p, float* out, int bufSize)
+{
+    ps->p = p;
+    
+    ps->outBuffer = out;
+    ps->bufSize = bufSize;
+    ps->frameSize = p->frameSize;
+    ps->framesPerBuffer = ps->bufSize / ps->frameSize;
+    ps->curBlock = 1;
+    ps->lastBlock = 0;
+    ps->index = 0;
+    ps->pitchFactor = 1.0f;
+    
+    tSOLAD_init(&ps->sola);
+    
+    tHighpass_init(&ps->hp, HPFREQ);
+    
+    tSOLAD_setPitchFactor(&ps->sola, DEFPITCHRATIO);
+}
+
+void tPitchShift_free(tPitchShift* const ps)
+{
+    tSOLAD_free(&ps->sola);
+    tHighpass_free(&ps->hp);
+}
+
+void tPitchShift_setPitchFactor(tPitchShift* ps, float pf)
+{
+    ps->pitchFactor = pf;
+}
+
+float tPitchShift_shift (tPitchShift* ps)
+{
+    float period, out;
+    int i, iLast;
+    
+    i = ps->p->i;
+    iLast = ps->p->iLast;
+    
+    out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
+    
+    if (ps->p->indexstore >= ps->frameSize)
+    {
+        period = ps->p->period;
+        
+        if(pitchshift_attackdetect(ps) == 1)
+        {
+            ps->p->fba = 5;
+            tSOLAD_setReadLag(&ps->sola, ps->p->windowSize);
+        }
+        
+        tSOLAD_setPeriod(&ps->sola, period);
+        tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
+        
+        tSOLAD_ioSamples(&ps->sola, &(ps->p->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
+    }
+    
+    return out;
+}
+
+float tPitchShift_shiftToFreq (tPitchShift* ps, float freq)
+{
+    float period, out;
+    int i, iLast;
+    
+    i = ps->p->i;
+    iLast = ps->p->iLast;
+    
+    out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
+    
+    if (ps->p->indexstore >= ps->frameSize)
+    {
+        period = ps->p->period;
+        
+        if(pitchshift_attackdetect(ps) == 1)
+        {
+            ps->p->fba = 5;
+            tSOLAD_setReadLag(&ps->sola, ps->p->windowSize);
+        }
+        
+        tSOLAD_setPeriod(&ps->sola, period);
+        
+        ps->pitchFactor = period*freq*leaf.invSampleRate;
+        tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
+        
+        tSOLAD_ioSamples(&ps->sola, &(ps->p->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
+    }
+    return out;
+}
+
+float tPitchShift_shiftToFunc (tPitchShift* ps, float (*fun)(float))
+{
+    float period, out;
+    int i, iLast;
+    
+    i = ps->p->i;
+    iLast = ps->p->iLast;
+    
+    out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
+    
+    if (ps->p->indexstore >= ps->frameSize)
+    {
+        period = ps->p->period;
+        
+        if(pitchshift_attackdetect(ps) == 1)
+        {
+            ps->p->fba = 5;
+            tSOLAD_setReadLag(&ps->sola, ps->p->windowSize);
+        }
+        
+        tSOLAD_setPeriod(&ps->sola, period);
+        
+        ps->pitchFactor = period/fun(period);
+        tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
+        
+        tSOLAD_ioSamples(&ps->sola, &(ps->p->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
+        
+        ps->curBlock++;
+        if (ps->curBlock >= ps->p->framesPerBuffer) ps->curBlock = 0;
+        ps->lastBlock++;
+        if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0;
+    }
+    
+    return out;
+}
+
+//============================================================================================================
+// SOLAD
+//============================================================================================================
+/******************************************************************************/
+/***************** static function declarations *******************************/
+/******************************************************************************/
+
+static void solad_init(tSOLAD *w);
+static inline float read_sample(tSOLAD *w, float floatindex);
+static void pitchdown(tSOLAD *w, float *out);
+static void pitchup(tSOLAD *w, float *out);
+
+/******************************************************************************/
+/***************** public access functions ************************************/
+/******************************************************************************/
+
+// init
+void     tSOLAD_init(tSOLAD* const w)
+{
+    w->pitchfactor = 1.;
+    w->delaybuf = (float*) leaf_alloc(sizeof(float) * (LOOPSIZE+16));
+    solad_init(w);
+}
+
+void tSOLAD_free(tSOLAD* const w)
+{
+}
+
+// send one block of input samples, receive one block of output samples
+void tSOLAD_ioSamples(tSOLAD* const w, float* in, float* out, int blocksize)
+{
+    int i = w->timeindex;
+    int n = w->blocksize = blocksize;
+    
+    if(!i) w->delaybuf[LOOPSIZE] = in[0];   // copy one sample for interpolation
+    while(n--) w->delaybuf[i++] = *in++;    // copy one input block to delay buffer
+    
+    if(w->pitchfactor > 1) pitchup(w, out);
+    else pitchdown(w, out);
+    
+    w->timeindex += blocksize;
+    w->timeindex &= LOOPMASK;
+}
+
+// set periodicity analysis data
+void tSOLAD_setPeriod(tSOLAD* const w, float period)
+{
+    if(period > MAXPERIOD) period = MAXPERIOD;
+    if(period > MINPERIOD) w->period = period;  // ignore period when too small
+}
+
+// set pitch factor between 0.25 and 4
+void tSOLAD_setPitchFactor(tSOLAD* const w, float pitchfactor)
+{
+    if(pitchfactor < 0.25) pitchfactor = 0.25;
+    else if(pitchfactor > 4.) pitchfactor = 4.;
+    w->pitchfactor = pitchfactor;
+}
+
+// force readpointer lag
+void tSOLAD_setReadLag(tSOLAD* const w, float readlag)
+{
+    if(readlag < 0) readlag = 0;
+    if(readlag < w->readlag)               // do not jump backward, only forward
+    {
+        w->jump = w->readlag - readlag;
+        w->readlag = readlag;
+        w->xfadelength = readlag;
+        w->xfadevalue = 1;
+    }
+}
+
+// reset state variables
+void tSOLAD_resetState(tSOLAD* const w)
+{
+    int n = LOOPSIZE + 1;
+    float *buf = w->delaybuf;
+    
+    while(n--) *buf++ = 0;
+    solad_init(w);
+}
+
+/******************************************************************************/
+/******************** private procedures **************************************/
+/******************************************************************************/
+
+/*
+ Function pitchdown() is called to read samples from the delay buffer when pitch
+ factor is between 0.25 and 1. The read pointer lags behind because of the slowed
+ down speed, and it must jump forward towards the write pointer soon as there is
+ sufficient space to jump. That is, if there is at least one period of the input
+ signal between read pointer and write pointer.  When short periods follow up on
+ long periods, the read pointer may have space to jump over more than one period
+ lenghts. Jump length must be [periodlength ^ 2] in any case.
+ 
+ A linear crossfade function joins the jump-from point with the jump-to point.
+ The crossfade must be completed before another read pointer jump is allowed.
+ Length of the crossfade function is stored as a number of samples in terms of
+ the input sample rate. This length is dynamically translated
+ to a crossfade length expressed in output reading rate, according to pitch
+ factor which can change before the crossfade is completed. Crossfade length does
+ not cover an invariable length in periods for all pitch transposition factors.
+ For pitch factors from 0.5 till 1, crossfade length is stretched in the
+ output just as much as the signal itself, as crossfade speed is set to equal
+ pitch factor. For pitch factors below 0.5, the read pointer wants to jump
+ forward before one period is read, therefore the crossfade length as expressed
+ in output periods must be shorter. Crossfade speed is set to [1 - pitchfactor]
+ for those cases. Pitch factor 0.5 is the natural switch point between crossfade
+ speeds [pitchfactor] and [1 - pitchfactor] because 0.5 == 1 - 0.5. The crossfade
+ speed modification for pitch factors below 0.5 also means that much of the
+ original signal content will be skipped.
+ */
+
+
+static void pitchdown(tSOLAD* const w, float *out)
+{
+    int n = w->blocksize;
+    float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values!
+    float pitchfactor = w->pitchfactor;
+    float period = w->period;
+    float readlag = w->readlag;
+    float readlagstep = 1 - pitchfactor;
+    float jump = w->jump;
+    float xfadevalue = w->xfadevalue;
+    float xfadelength = w->xfadelength;
+    float xfadespeed, xfadestep, readindex, outputsample;
+    
+    if(pitchfactor > 0.5) xfadespeed = pitchfactor;
+    else xfadespeed = 1 - pitchfactor;
+    xfadestep = xfadespeed / xfadelength;
+    
+    while(n--)
+    {
+        if(readlag > period)        // check if read pointer may jump forward...
+        {
+            if(xfadevalue <= 0)      // ...but do not interrupt crossfade
+            {
+                jump = period;                           // jump forward
+                while((jump * 2) < readlag) jump *= 2;   // use available space
+                readlag -= jump;                         // reduce read pointer lag
+                xfadevalue = 1;                          // start crossfade
+                xfadelength = period - 1;
+                xfadestep = xfadespeed / xfadelength;
+            }
+        }
+        
+        readindex = refindex - readlag;
+        outputsample = read_sample(w, readindex);
+        
+        if(xfadevalue > 0)
+        {
+            outputsample *= (1 - xfadevalue);                               // fadein
+            outputsample += read_sample(w, readindex - jump) * xfadevalue;  // fadeout
+            xfadevalue -= xfadestep;
+        }
+        
+        *out++ = outputsample;
+        refindex += 1;
+        readlag += readlagstep;
+    }
+    
+    w->jump = jump;                 // state variables
+    w->readlag = readlag;
+    w->xfadevalue = xfadevalue;
+    w->xfadelength = xfadelength;
+}
+
+
+/*
+ Function pitchup() for pitch factors above 1 is more complicated than
+ pitchdown(). The read pointer increments faster than the write pointer and a
+ backward jump must happen in time, reckoning with the crossfade region. The read
+ pointer backward jump length is always one period. In order to minimize the area
+ of signal duplicates, crossfade length is aimed at [period / pitchfactor].
+ This leads to a crossfade speed of [pitchfactor * pitchfactor].
+ 
+ Some samples for the fade out (but not all of them) must already be in the
+ buffer, otherwise we will run out of input samples before the crossfade is
+ completed. The ratio of past samples and future samples for a crossfade of any
+ length is as follows:
+ 
+ past samples: xfadelength * (1 - 1 / pitchfactor)
+ future samples: xfadelength * (1 / pitchfactor)
+ 
+ For example in the case of pitch factor 1.5 this would be:
+ 
+ past samples: xfadelength * (1 - 1 / 1.5) = xfadelength * 1 / 3
+ future samples: xfadelength * (1 / 1.5) = xfadelength * 2 / 3
+ 
+ In the case of pitch factor 4 this would be:
+ 
+ past samples: xfadelength * (1 - 1 / 4) = xfadelength * 3 / 4
+ future samples: xfadelength * (1 / 4) = xfadelength * 1 / 4
+ 
+ The read pointer lag must therefore preserve a minimum dependent on pitch
+ factor. The minimum is called 'limit' here:
+ 
+ limit = period * (pitchfactor - 1) / pitchfactor * pitchfactor
+ 
+ Components of this expression are combined to reuse them in operations, while
+ (pitchfactor - 1) is changed to (pitchfactor - 0.99) to avoid numerical
+ resolution issues for pitch factors slightly above 1:
+ 
+ xfadespeed = pitchfactor * pitchfactor
+ limitfactor = (pitchfactor - 0.99) / xfadespeed
+ limit = period * limitfactor
+ 
+ When read lag is smaller than this limit, the read pointer must preferably
+ jump backward, unless a previous crossfade is not yet completed. Crossfades must
+ preferably be completed, unless the read pointer lag becomes smaller than zero.
+ With fluctuating period lengths and pitch factors, the readpointer lag limit may
+ change from one input block to the next in such a way that the actual lag is
+ suddenly much smaller than the limit, and the intended crossfade length can not
+ be applied. Therefore the crossfade length is simply calculated from the
+ available amount of samples for all cases, like so:
+ 
+ xfadelength = readlag / limitfactor
+ 
+ For most occurrences, this will amount to a crossfade length reduced to
+ [period / pitchfactor] in the output for pitch factors above 1, while in some
+ cases it will be considerably shorter. Fortunately, an incidental aberration of
+ the intended crossfade length hardly ever creates an audible artifact. The
+ reason to specify preferred crossfade length according to pitch factor is to
+ minimize the impression of echoes without sacrificing too much of the signal
+ content. The readpointer jump length remains one period in any case.
+ 
+ Sometimes, the input signal periodicity may decrease substantially between one
+ signal block and the next. In such cases it may be possible for the read pointer
+ to jump forward and reduce latency. For every signal block, a check on this
+ possibility is done. A previous crossfade must be completed before a forward
+ jump is allowed.
+ */
+static void pitchup(tSOLAD* const w, float *out)
+{
+    int n = w->blocksize;
+    float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values
+    float pitchfactor = w->pitchfactor;
+    float period = w->period;
+    float readlag = w->readlag;
+    float jump = w->jump;
+    float xfadevalue = w->xfadevalue;
+    float xfadelength = w->xfadelength;
+    
+    float readlagstep = pitchfactor - 1;
+    float xfadespeed = pitchfactor * pitchfactor;
+    float xfadestep = xfadespeed / xfadelength;
+    float limitfactor = (pitchfactor - (float)0.99) / xfadespeed;
+    float limit = period * limitfactor;
+    float readindex, outputsample;
+    
+    if((readlag > (period + 2 * limit)) & (xfadevalue < 0))
+    {
+        jump = period;                                        // jump forward
+        while((jump * 2) < (readlag - 2 * limit)) jump *= 2;  // use available space
+        readlag -= jump;                                      // reduce read pointer lag
+        xfadevalue = 1;                                       // start crossfade
+        xfadelength = period - 1;
+        xfadestep = xfadespeed / xfadelength;
+    }
+    
+    while(n--)
+    {
+        if(readlag < limit)  // check if read pointer should jump backward...
+        {
+            if((xfadevalue < 0) | (readlag < 0)) // ...but try not to interrupt crossfade
+            {
+                xfadelength = readlag / limitfactor;
+                if(xfadelength < 1) xfadelength = 1;
+                xfadestep = xfadespeed / xfadelength;
+                
+                jump = -period;         // jump backward
+                readlag += period;      // increase read pointer lag
+                xfadevalue = 1;         // start crossfade
+            }
+        }
+        
+        readindex = refindex - readlag;
+        outputsample = read_sample(w, readindex);
+        
+        if(xfadevalue > 0)
+        {
+            outputsample *= (1 - xfadevalue);
+            outputsample += read_sample(w, readindex - jump) * xfadevalue;
+            xfadevalue -= xfadestep;
+        }
+        
+        *out++ = outputsample;
+        refindex += 1;
+        readlag -= readlagstep;
+    }
+    
+    w->readlag = readlag;               // state variables
+    w->jump = jump;
+    w->xfadelength = xfadelength;
+    w->xfadevalue = xfadevalue;
+}
+
+// read one sample from delay buffer, with linear interpolation
+static inline float read_sample(tSOLAD* const w, float floatindex)
+{
+    int index = (int)floatindex;
+    float fraction = floatindex - (float)index;
+    float *buf = w->delaybuf;
+    index &= LOOPMASK;
+    
+    return (buf[index] + (fraction * (buf[index+1] - buf[index])));
+}
+
+static void solad_init(tSOLAD* const w)
+{
+    w->timeindex = 0;
+    w->xfadevalue = -1;
+    w->period = INITPERIOD;
+    w->readlag = INITPERIOD;
+    w->blocksize = INITPERIOD;
+}
+//============================================================================================================
+// FORMANTSHIFTER
+//============================================================================================================
+
+void tFormantShifter_init(tFormantShifter* const fs, int bufsize, int order)
+{
+    fs->ford = order;
+    fs->bufsize = bufsize;
+    fs->fk = (float*) leaf_alloc(sizeof(float) * fs->ford);
+    fs->fb = (float*) leaf_alloc(sizeof(float) * fs->ford);
+    fs->fc = (float*) leaf_alloc(sizeof(float) * fs->ford);
+    fs->frb = (float*) leaf_alloc(sizeof(float) * fs->ford);
+    fs->frc = (float*) leaf_alloc(sizeof(float) * fs->ford);
+    fs->fsig = (float*) leaf_alloc(sizeof(float) * fs->ford);
+    fs->fsmooth = (float*) leaf_alloc(sizeof(float) * fs->ford);
+    fs->ftvec = (float*) leaf_alloc(sizeof(float) * fs->ford);
+    
+    fs->fbuff = (float**) leaf_alloc(sizeof(float*) * fs->ford);
+    for (int i = 0; i < fs->ford; i++)
+    {
+        fs->fbuff[i] = (float*) leaf_alloc(sizeof(float) * fs->bufsize);
+    }
+    
+    
+    fs->falph = powf(0.001f, 80.0f / (leaf.sampleRate));
+    fs->flamb = -(0.8517f*sqrt(atanf(0.06583f*leaf.sampleRate))-0.1916f);
+    fs->fhp = 0.0f;
+    fs->flp = 0.0f;
+    fs->flpa = powf(0.001f, 10.0f / (leaf.sampleRate));
+    fs->fmute = 1.0f;
+    fs->fmutealph = powf(0.001f, 1.0f / (leaf.sampleRate));
+    fs->cbi = 0;
+}
+
+void tFormantShifter_free(tFormantShifter* const fs)
+{
+    leaf_free(fs->fk);
+    leaf_free(fs->fb);
+    leaf_free(fs->fc);
+    leaf_free(fs->frb);
+    leaf_free(fs->frc);
+    leaf_free(fs->fsig);
+    leaf_free(fs->fsmooth);
+    leaf_free(fs->ftvec);
+    for (int i = 0; i < fs->ford; i++)
+    {
+        leaf_free(fs->fbuff[i]);
+    }
+    leaf_free(fs->fbuff);
+}
+
+
+float tFormantShifter_tick(tFormantShifter* fs, float in, float fwarp)
+{
+    return tFormantShifter_add(fs, tFormantShifter_remove(fs, in), fwarp);
+}
+
+float tFormantShifter_remove(tFormantShifter* fs, float in)
+{
+    float fa, fb, fc, foma, falph, ford, flpa, flamb, tf, fk;
+    int ti4;
+    ford = fs->ford;
+    falph = fs->falph;
+    foma = (1.0f - falph);
+    flpa = fs->flpa;
+    flamb = fs->flamb;
+    
+    tf = in;
+    ti4 = fs->cbi;
+    
+    fa = tf - fs->fhp;
+    fs->fhp = tf;
+    fb = fa;
+    for(int i = 0; i < ford; i++)
+    {
+        fs->fsig[i] = fa*fa*foma + fs->fsig[i]*falph;
+        fc = (fb - fs->fc[i])*flamb + fs->fb[i];
+        fs->fc[i] = fc;
+        fs->fb[i] = fb;
+        fk = fa*fc*foma + fs->fk[i]*falph;
+        fs->fk[i] = fk;
+        tf = fk/(fs->fsig[i] + 0.000001f);
+        tf = tf*foma + fs->fsmooth[i]*falph;
+        fs->fsmooth[i] = tf;
+        fs->fbuff[i][ti4] = tf;
+        fb = fc - tf*fa;
+        fa = fa - tf*fc;
+    }
+    fs->cbi++;
+    if(fs->cbi >= fs->bufsize)
+    {
+        fs->cbi = 0;
+    }
+    
+    return fa;
+}
+
+float tFormantShifter_add(tFormantShifter* fs, float in, float fwarp)
+{
+    float fa, fb, fc, foma, falph, ford, flpa, flamb, tf, tf2, f0resp, f1resp, frlamb;
+    int ti4;
+    ford = fs->ford;
+    falph = fs->falph;
+    foma = (1.0f - falph);
+    flpa = fs->flpa;
+    flamb = fs->flamb;
+    tf = exp2(fwarp/2.0f) * (1+flamb)/(1-flamb);
+    frlamb = (tf-1)/(tf+1);
+    ti4 = fs->cbi;
+    
+    tf2 = in;
+    fa = 0;
+    fb = fa;
+    for (int i=0; i<ford; i++)
+    {
+        fc = (fb-fs->frc[i])*frlamb + fs->frb[i];
+        tf = fs->fbuff[i][ti4];
+        fb = fc - tf*fa;
+        fs->ftvec[i] = tf*fc;
+        fa = fa - fs->ftvec[i];
+    }
+    tf = -fa;
+    for (int i=ford-1; i>=0; i--)
+    {
+        tf = tf + fs->ftvec[i];
+    }
+    f0resp = tf;
+    
+    //  second time: compute 1-response
+    fa = 1;
+    fb = fa;
+    for (int i=0; i<ford; i++)
+    {
+        fc = (fb-fs->frc[i])*frlamb + fs->frb[i];
+        tf = fs->fbuff[i][ti4];
+        fb = fc - tf*fa;
+        fs->ftvec[i] = tf*fc;
+        fa = fa - fs->ftvec[i];
+    }
+    tf = -fa;
+    for (int i=ford-1; i>=0; i--)
+    {
+        tf = tf + fs->ftvec[i];
+    }
+    f1resp = tf;
+    
+    //  now solve equations for output, based on 0-response and 1-response
+    tf = (float)2*tf2;
+    tf2 = tf;
+    tf = ((float)1 - f1resp + f0resp);
+    if (tf!=0)
+    {
+        tf2 = (tf2 + f0resp) / tf;
+    }
+    else
+    {
+        tf2 = 0;
+    }
+    
+    //  third time: update delay registers
+    fa = tf2;
+    fb = fa;
+    for (int i=0; i<ford; i++)
+    {
+        fc = (fb-fs->frc[i])*frlamb + fs->frb[i];
+        fs->frc[i] = fc;
+        fs->frb[i] = fb;
+        tf = fs->fbuff[i][ti4];
+        fb = fc - tf*fa;
+        fa = fa - tf*fc;
+    }
+    tf = tf2;
+    tf = tf + flpa * fs->flp;  // lowpass post-emphasis filter
+    fs->flp = tf;
+    
+    // Bring up the gain slowly when formant correction goes from disabled
+    // to enabled, while things stabilize.
+    if (fs->fmute>0.5)
+    {
+        tf = tf*(fs->fmute - 0.5)*2;
+    }
+    else
+    {
+        tf = 0;
+    }
+    tf2 = fs->fmutealph;
+    fs->fmute = (1-tf2) + tf2*fs->fmute;
+    // now tf is signal output
+    // ...and we're done messing with formants
+    
+    return tf;
+}
--- /dev/null
+++ b/LEAF/Src/leaf-electrical.c
@@ -1,0 +1,480 @@
+/*
+ * leaf-electrical.c
+ *
+ *  Created on: Sep 25, 2019
+ *      Author: jeffsnyder
+ */
+
+#if _WIN32 || _WIN64
+
+#include "..\Inc\leaf-electrical.h"
+#include "..\leaf.h"
+
+#else
+
+#include "../Inc/leaf-electrical.h"
+#include "../leaf.h"
+
+#endif
+
+//==============================================================================
+
+static float get_port_resistance_for_resistor(tWDF* const r);
+static float get_port_resistance_for_capacitor(tWDF* const r);
+static float get_port_resistance_for_inductor(tWDF* const r);
+static float get_port_resistance_for_resistive(tWDF* const r);
+static float get_port_resistance_for_inverter(tWDF* const r);
+static float get_port_resistance_for_series(tWDF* const r);
+static float get_port_resistance_for_parallel(tWDF* const r);
+static float get_port_resistance_for_root(tWDF* const r);
+
+static void set_incident_wave_for_leaf(tWDF* const r, float incident_wave, float input);
+static void set_incident_wave_for_leaf_inverted(tWDF* const r, float incident_wave, float input);
+static void set_incident_wave_for_inverter(tWDF* const r, float incident_wave, float input);
+static void set_incident_wave_for_series(tWDF* const r, float incident_wave, float input);
+static void set_incident_wave_for_parallel(tWDF* const r, float incident_wave, float input);
+
+static float get_reflected_wave_for_resistor(tWDF* const r, float input);
+static float get_reflected_wave_for_capacitor(tWDF* const r, float input);
+static float get_reflected_wave_for_resistive(tWDF* const r, float input);
+static float get_reflected_wave_for_inverter(tWDF* const r, float input);
+static float get_reflected_wave_for_series(tWDF* const r, float input);
+static float get_reflected_wave_for_parallel(tWDF* const r, float input);
+
+static float get_reflected_wave_for_ideal(tWDF* const n, float input, float incident_wave);
+static float get_reflected_wave_for_diode(tWDF* const n, float input, float incident_wave);
+static float get_reflected_wave_for_diode_pair(tWDF* const n, float input, float incident_wave);
+
+//WDF
+void tWDF_init(tWDF* const r, WDFComponentType type, float value, tWDF* const rL, tWDF* const rR)
+{
+	r->type = type;
+    r->child_left = rL;
+    r->child_right = rR;
+	r->incident_wave_up = 0.0f;
+	r->incident_wave_left = 0.0f;
+	r->incident_wave_right = 0.0f;
+	r->reflected_wave_up = 0.0f;
+	r->reflected_wave_left = 0.0f;
+	r->reflected_wave_right = 0.0f;
+	r->sample_rate = leaf.sampleRate;
+	r->value = value;
+    
+    tWDF* child;
+    if (r->child_left != NULL) child = r->child_left;
+    else child = r->child_right;
+    
+    if (r->type == Resistor)
+	{
+		r->port_resistance_up = r->value;
+		r->port_conductance_up = 1.0f / r->value;
+
+		r->get_port_resistance = &get_port_resistance_for_resistor;
+		r->get_reflected_wave_up = &get_reflected_wave_for_resistor;
+		r->set_incident_wave = &set_incident_wave_for_leaf;
+	}
+	else if (r->type == Capacitor)
+	{
+        r->port_conductance_up = r->sample_rate * 2.0f * r->value;
+		r->port_resistance_up = 1.0f / r->port_conductance_up; //based on trapezoidal discretization
+    
+		r->get_port_resistance = &get_port_resistance_for_capacitor;
+		r->get_reflected_wave_up = &get_reflected_wave_for_capacitor;
+		r->set_incident_wave = &set_incident_wave_for_leaf;
+	}
+    else if (r->type == Inductor)
+    {
+        r->port_resistance_up = r->sample_rate * 2.0f * r->value; //based on trapezoidal discretization
+        r->port_conductance_up = 1.0f / r->port_resistance_up;
+        
+        r->get_port_resistance = &get_port_resistance_for_inductor;
+        r->get_reflected_wave_up = &get_reflected_wave_for_capacitor; // same as capacitor
+        r->set_incident_wave = &set_incident_wave_for_leaf_inverted;
+    }
+	else if (r->type == ResistiveSource)
+	{
+        r->port_resistance_up = r->value;
+        r->port_conductance_up = 1.0f / r->port_resistance_up;
+        
+        r->get_port_resistance = &get_port_resistance_for_resistive;
+        r->get_reflected_wave_up = &get_reflected_wave_for_resistive;
+        r->set_incident_wave = &set_incident_wave_for_leaf;
+	}
+    else if (r->type == Inverter)
+    {
+        r->port_resistance_up = tWDF_getPortResistance(r->child_left);
+        r->port_conductance_up = 1.0f / r->port_resistance_up;
+        
+        r->get_port_resistance = &get_port_resistance_for_inverter;
+        r->get_reflected_wave_up = &get_reflected_wave_for_inverter;
+        r->set_incident_wave = &set_incident_wave_for_inverter;
+    }
+    else if (r->type == SeriesAdaptor)
+    {
+        r->port_resistance_left = tWDF_getPortResistance(r->child_left);
+        r->port_resistance_right = tWDF_getPortResistance(r->child_right);
+        r->port_resistance_up = r->port_resistance_left + r->port_resistance_right;
+        r->port_conductance_up  = 1.0f / r->port_resistance_up;
+        r->port_conductance_left = 1.0f / r->port_resistance_left;
+        r->port_conductance_right = 1.0f / r->port_resistance_right;
+        r->gamma_zero = 1.0f / (r->port_resistance_right + r->port_resistance_left);
+        
+        r->get_port_resistance = &get_port_resistance_for_series;
+        r->get_reflected_wave_up = &get_reflected_wave_for_series;
+        r->set_incident_wave = &set_incident_wave_for_series;
+    }
+    else if (r->type == ParallelAdaptor)
+    {
+        r->port_resistance_left = tWDF_getPortResistance(r->child_left);
+        r->port_resistance_right = tWDF_getPortResistance(r->child_right);
+        r->port_resistance_up = (r->port_resistance_left * r->port_resistance_right) / (r->port_resistance_left + r->port_resistance_right);
+        r->port_conductance_up  = 1.0f / r->port_resistance_up;
+        r->port_conductance_left = 1.0f / r->port_resistance_left;
+        r->port_conductance_right = 1.0f / r->port_resistance_right;
+        r->gamma_zero = 1.0f / (r->port_resistance_right + r->port_resistance_left);
+        
+        r->get_port_resistance = &get_port_resistance_for_parallel;
+        r->get_reflected_wave_up = &get_reflected_wave_for_parallel;
+        r->set_incident_wave = &set_incident_wave_for_parallel;
+    }
+    else if (r->type == IdealSource)
+    {
+        r->port_resistance_up = tWDF_getPortResistance(child);
+        r->port_conductance_up = 1.0f / r->port_resistance_up;
+        
+        r->get_reflected_wave_down = &get_reflected_wave_for_ideal;
+        r->get_port_resistance = &get_port_resistance_for_root;
+    }
+    else if (r->type == Diode)
+    {
+        r->port_resistance_up = tWDF_getPortResistance(child);
+        r->port_conductance_up = 1.0f / r->port_resistance_up;
+        
+        r->get_reflected_wave_down = &get_reflected_wave_for_diode;
+        r->get_port_resistance = &get_port_resistance_for_root;
+    }
+    else if (r->type == DiodePair)
+    {
+        r->port_resistance_up = tWDF_getPortResistance(child);
+        r->port_conductance_up = 1.0f / r->port_resistance_up;
+        
+        r->get_reflected_wave_down = &get_reflected_wave_for_diode_pair;
+        r->get_port_resistance = &get_port_resistance_for_root;
+    }
+}
+
+void tWDF_free(tWDF* const r)
+{
+
+}
+
+float tWDF_tick(tWDF* const r, float sample, tWDF* const outputPoint, uint8_t paramsChanged)
+{
+    tWDF* child;
+    if (r->child_left != NULL) child = r->child_left;
+    else child = r->child_right;
+    
+	//step 0 : update port resistances if something changed
+	if (paramsChanged) tWDF_getPortResistance(r);
+
+	//step 1 : set inputs to what they should be
+	float input = sample;
+
+	//step 2 : scan the waves up the tree
+	r->incident_wave_up = tWDF_getReflectedWaveUp(child, input);
+
+	//step 3 : do root scattering computation
+	r->reflected_wave_up = tWDF_getReflectedWaveDown(r, input, r->incident_wave_up);
+
+	//step 4 : propogate waves down the tree
+	tWDF_setIncidentWave(child, r->reflected_wave_up, input);
+
+	//step 5 : grab whatever voltages or currents we want as outputs
+    return tWDF_getVoltage(outputPoint);
+}
+
+void tWDF_setValue(tWDF* const r, float value)
+{
+	r->value = value;
+}
+
+void tWDF_setSampleRate(tWDF* const r, float sample_rate)
+{
+    r->sample_rate = sample_rate;
+}
+
+uint8_t tWDF_isLeaf(tWDF* const r)
+{
+    if (r->child_left == NULL && r->child_right == NULL) return 1;
+    return 0;
+}
+
+float tWDF_getPortResistance(tWDF* const r)
+{
+	return r->get_port_resistance(r);
+}
+
+void tWDF_setIncidentWave(tWDF* const r, float incident_wave, float input)
+{
+	r->set_incident_wave(r, incident_wave, input);
+}
+
+float tWDF_getReflectedWaveUp(tWDF* const r, float input)
+{
+	return r->get_reflected_wave_up(r, input);
+}
+
+float tWDF_getReflectedWaveDown(tWDF* const r, float input, float incident_wave)
+{
+    return r->get_reflected_wave_down(r, input, incident_wave);
+}
+
+float tWDF_getVoltage(tWDF* const r)
+{
+	return ((r->incident_wave_up * 0.5f) + (r->reflected_wave_up * 0.5f));
+}
+
+float tWDF_getCurrent(tWDF* const r)
+{
+	return (((r->incident_wave_up * 0.5f) - (r->reflected_wave_up * 0.5f)) * r->port_conductance_up);
+}
+
+//============ Static Functions to be Pointed To ====================
+//===================================================================
+//============ Get and Calculate Port Resistances ===================
+
+static float get_port_resistance_for_resistor(tWDF* const r)
+{
+	r->port_resistance_up = r->value;
+	r->port_conductance_up = 1.0f / r->value;
+
+	return r->port_resistance_up;
+}
+
+static float get_port_resistance_for_capacitor(tWDF* const r)
+{
+	r->port_conductance_up = r->sample_rate * 2.0f * r->value; //based on trapezoidal discretization
+	r->port_resistance_up = (1.0f / r->port_conductance_up);
+
+	return r->port_resistance_up;
+}
+
+static float get_port_resistance_for_inductor(tWDF* const r)
+{
+    r->port_resistance_up = r->sample_rate * 2.0f * r->value; //based on trapezoidal discretization
+    r->port_conductance_up = (1.0f / r->port_resistance_up);
+    
+    return r->port_resistance_up;
+}
+
+static float get_port_resistance_for_resistive(tWDF* const r)
+{
+    r->port_resistance_up = r->value;
+    r->port_conductance_up = 1.0f / r->port_resistance_up;
+    
+    return r->port_resistance_up;
+}
+
+static float get_port_resistance_for_inverter(tWDF* const r)
+{
+    r->port_resistance_up = tWDF_getPortResistance(r->child_left);
+    r->port_conductance_up = 1.0f / r->port_resistance_up;
+    
+    return r->port_resistance_up;
+}
+
+static float get_port_resistance_for_series(tWDF* const r)
+{
+	r->port_resistance_left = tWDF_getPortResistance(r->child_left);
+	r->port_resistance_right = tWDF_getPortResistance(r->child_right);
+	r->port_resistance_up = r->port_resistance_left + r->port_resistance_right;
+	r->port_conductance_up  = 1.0f / r->port_resistance_up;
+	r->port_conductance_left = 1.0f / r->port_resistance_left;
+	r->port_conductance_right = 1.0f / r->port_resistance_right;
+	r->gamma_zero = 1.0f / (r->port_resistance_right + r->port_resistance_left);
+
+	return r->port_resistance_up;
+}
+
+static float get_port_resistance_for_parallel(tWDF* const r)
+{
+	r->port_resistance_left = tWDF_getPortResistance(r->child_left);
+	r->port_resistance_right = tWDF_getPortResistance(r->child_right);
+	r->port_resistance_up = (r->port_resistance_left * r->port_resistance_right) / (r->port_resistance_left + r->port_resistance_right);
+	r->port_conductance_up  = 1.0f / r->port_resistance_up;
+	r->port_conductance_left = 1.0f / r->port_resistance_left;
+	r->port_conductance_right = 1.0f / r->port_resistance_right;
+	r->gamma_zero = 1.0f / (r->port_conductance_right + r->port_conductance_left);
+
+	return r->port_resistance_up;
+}
+
+static float get_port_resistance_for_root(tWDF* const r)
+{
+    tWDF* child;
+    if (r->child_left != NULL) child = r->child_left;
+    else child = r->child_right;
+    
+    r->port_resistance_up = tWDF_getPortResistance(child);
+    r->port_conductance_up = 1.0f / r->port_resistance_up;
+    
+    return r->port_resistance_up;
+}
+
+//===================================================================
+//================ Set Incident Waves ===============================
+
+static void set_incident_wave_for_leaf(tWDF* const r, float incident_wave, float input)
+{
+	r->incident_wave_up = incident_wave;
+}
+
+static void set_incident_wave_for_leaf_inverted(tWDF* const r, float incident_wave, float input)
+{
+    r->incident_wave_up = -1.0f * incident_wave;
+}
+
+static void set_incident_wave_for_inverter(tWDF* const r, float incident_wave, float input)
+{
+    r->incident_wave_up = incident_wave;
+    tWDF_setIncidentWave(r->child_left, -1.0f * incident_wave, input);
+}
+
+static void set_incident_wave_for_series(tWDF* const r, float incident_wave, float input)
+{
+    r->incident_wave_up = incident_wave;
+	float gamma_left = r->port_resistance_left * r->gamma_zero;
+	float gamma_right = r->port_resistance_right * r->gamma_zero;
+	float left_wave = tWDF_getReflectedWaveUp(r->child_left, input);
+	float right_wave = tWDF_getReflectedWaveUp(r->child_right, input);
+//    downPorts[0]->b = yl * ( downPorts[0]->a * ((1.0 / yl) - 1) - downPorts[1]->a - descendingWave );
+//    downPorts[1]->b = yr * ( downPorts[1]->a * ((1.0 / yr) - 1) - downPorts[0]->a - descendingWave );
+	tWDF_setIncidentWave(r->child_left, (-1.0f * gamma_left * incident_wave) + (gamma_right * left_wave) - (gamma_left * right_wave), input);
+	tWDF_setIncidentWave(r->child_right, (-1.0f * gamma_right * incident_wave) + (gamma_left * right_wave) - (gamma_right * left_wave), input);
+	// From rt-wdf
+//	tWDF_setIncidentWave(r->child_left, gamma_left * (left_wave * ((1.0f / gamma_left) - 1.0f) - right_wave - incident_wave));
+//	tWDF_setIncidentWave(r->child_right, gamma_right * (right_wave * ((1.0f / gamma_right) - 1.0f) - left_wave - incident_wave));
+
+}
+
+static void set_incident_wave_for_parallel(tWDF* const r, float incident_wave, float input)
+{
+    r->incident_wave_up = incident_wave;
+	float gamma_left = r->port_conductance_left * r->gamma_zero;
+	float gamma_right = r->port_conductance_right * r->gamma_zero;
+	float left_wave = tWDF_getReflectedWaveUp(r->child_left, input);
+	float right_wave = tWDF_getReflectedWaveUp(r->child_right, input);
+//    downPorts[0]->b = ( ( dl - 1 ) * downPorts[0]->a + dr * downPorts[1]->a + du * descendingWave );
+//    downPorts[1]->b = ( dl * downPorts[0]->a + ( dr - 1 ) * downPorts[1]->a + du * descendingWave );
+	tWDF_setIncidentWave(r->child_left, (gamma_left - 1.0f) * left_wave + gamma_right * right_wave + incident_wave, input);
+	tWDF_setIncidentWave(r->child_right, gamma_left * left_wave + (gamma_right - 1.0f) * right_wave + incident_wave, input);
+}
+
+//===================================================================
+//================ Get Reflected Waves ==============================
+
+static float get_reflected_wave_for_resistor(tWDF* const r, float input)
+{
+	r->reflected_wave_up = 0.0f;
+	return r->reflected_wave_up;
+}
+
+static float get_reflected_wave_for_capacitor(tWDF* const r, float input)
+{
+	r->reflected_wave_up = r->incident_wave_up;
+	return r->reflected_wave_up;
+}
+
+static float get_reflected_wave_for_resistive(tWDF* const r, float input)
+{
+    r->reflected_wave_up = input;
+    return r->reflected_wave_up;
+}
+
+static float get_reflected_wave_for_inverter(tWDF* const r, float input)
+{
+    r->reflected_wave_up = -1.0f * tWDF_getReflectedWaveUp(r->child_left, input);
+    return r->reflected_wave_up;
+}
+
+static float get_reflected_wave_for_series(tWDF* const r, float input)
+{
+	//-( downPorts[0]->a + downPorts[1]->a );
+    r->reflected_wave_up = (-1.0f * (tWDF_getReflectedWaveUp(r->child_left, input) + tWDF_getReflectedWaveUp(r->child_right, input)));
+	return r->reflected_wave_up;
+}
+
+static float get_reflected_wave_for_parallel(tWDF* const r, float input)
+{
+	float gamma_left = r->port_conductance_left * r->gamma_zero;
+	float gamma_right = r->port_conductance_right * r->gamma_zero;
+	//return ( dl * downPorts[0]->a + dr * downPorts[1]->a );
+    r->reflected_wave_up = (gamma_left * tWDF_getReflectedWaveUp(r->child_left, input) + gamma_right * tWDF_getReflectedWaveUp(r->child_right, input));
+	return r->reflected_wave_up;
+}
+
+static float get_reflected_wave_for_ideal(tWDF* const n, float input, float incident_wave)
+{
+    return (2.0f * input) - incident_wave;
+}
+
+#define l2A 0.1640425613334452f
+#define l2B -1.098865286222744f
+#define l2Y 3.148297929334117f
+#define l2K -2.213475204444817f
+static float log2Approximation(float x)
+{
+    return (l2A * x*x*x) + (l2B * x*x) + (l2Y * x) + l2K;
+}
+
+#define wX1 -3.684303659906469f
+#define wX2 1.972967391708859f
+#define wA  9.451797158780131e-3f
+#define wB  0.1126446405111627f
+#define wY  0.4451353886588814f
+#define wK  0.5836596684310648f
+static float wrightOmega3(float x)
+{
+    if (x <= wX1)
+    {
+        return 0;
+    }
+    else if (x < wX2)
+    {
+        return (wA * x*x*x) + (wB * x*x) + (wY * x) + wK;
+    }
+    else
+    {
+        return x - logf(x);
+    }
+}
+
+static float wrightOmegaApproximation(float x)
+{
+    float w3 = wrightOmega3(x);
+    return w3 - ((w3 - expf(x - w3)) / (w3 + 1.0f));
+}
+
+static float lambertW(float a, float r, float I, float iVT)
+{
+    return wrightOmegaApproximation(((a + r*I) * iVT) + log((r * I) * iVT));
+}
+
+#define Is_DIODE    2.52e-9f
+#define VT_DIODE    0.02585f
+static float get_reflected_wave_for_diode(tWDF* const n, float input, float incident_wave)
+{
+    float a = incident_wave;
+    float r = n->port_resistance_up;
+    return a + 2.0f*r*Is_DIODE - 2.0f*VT_DIODE*lambertW(a, r, Is_DIODE, 1.0f/VT_DIODE);
+}
+
+static float get_reflected_wave_for_diode_pair(tWDF* const n, float input, float incident_wave)
+{
+    float a = incident_wave;
+    float sgn = 0.0f;
+    if (a > 0.0f) sgn = 1.0f;
+    else if (a < 0.0f) sgn = -1.0f;
+    float r = n->port_resistance_up;
+    return a + 2 * sgn * (r*Is_DIODE - VT_DIODE*lambertW(sgn*a, r, Is_DIODE, 1.0f/VT_DIODE));
+}
--- /dev/null
+++ b/LEAF/Src/leaf-envelopes.c
@@ -1,0 +1,629 @@
+/*
+  ==============================================================================
+
+    leaf-envelopes.c
+    Created: 20 Jan 2017 12:02:17pm
+    Author:  Michael R Mulshine
+
+  ==============================================================================
+*/
+
+
+#if _WIN32 || _WIN64
+
+#include "..\Inc\leaf-envelopes.h"
+#include "..\Inc\leaf-tables.h"
+#include "..\leaf.h"
+
+#else
+
+#include "../Inc/leaf-envelopes.h"
+#include "../Inc/leaf-tables.h"
+#include "../leaf.h"
+
+#endif
+
+#define LOGTEN 2.302585092994
+
+float mtof(float f)
+{
+    if (f <= -1500.0f) return(0);
+    else if (f > 1499.0f) return(mtof(1499.0f));
+    else return (8.17579891564f * expf(0.0577622650f * f));
+}
+
+float ftom(float f)
+{
+    return (f > 0 ? 17.3123405046f * logf(.12231220585f * f) : -1500.0f);
+}
+
+float powtodb(float f)
+{
+    if (f <= 0) return (0);
+    else
+    {
+        float val = 100 + 10.f/LOGTEN * logf(f);
+        return (val < 0 ? 0 : val);
+    }
+}
+
+float rmstodb(float f)
+{
+    if (f <= 0) return (0);
+    else
+    {
+        float val = 100 + 20.f/LOGTEN * log(f);
+        return (val < 0 ? 0 : val);
+    }
+}
+
+float dbtopow(float f)
+{
+    if (f <= 0)
+        return(0);
+    else
+    {
+        if (f > 870.0f)
+            f = 870.0f;
+        return (expf((LOGTEN * 0.1f) * (f-100.0f)));
+    }
+}
+
+float dbtorms(float f)
+{
+    if (f <= 0)
+        return(0);
+    else
+    {
+        if (f > 485.0f)
+            f = 485.0f;
+    }
+    return (expf((LOGTEN * 0.05f) * (f-100.0f)));
+}
+
+
+
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Envelope ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
+void    tEnvelope_init(tEnvelope* const env, float attack, float decay, oBool loop)
+{
+    env->exp_buff = exp_decay;
+    env->inc_buff = attack_decay_inc;
+    env->buff_size = sizeof(exp_decay);
+    
+    env->loop = loop;
+    
+    if (attack > 8192.0f)
+        attack = 8192.0f;
+    if (attack < 0.0f)
+        attack = 0.0f;
+    
+    if (decay > 8192.0f)
+        decay = 8192.0f;
+    if (decay < 0.0f)
+        decay = 0.0f;
+    
+    int16_t attackIndex = ((int16_t)(attack * 8.0f))-1;
+    int16_t decayIndex = ((int16_t)(decay * 8.0f))-1;
+    int16_t rampIndex = ((int16_t)(2.0f * 8.0f))-1;
+    
+    if (attackIndex < 0)
+        attackIndex = 0;
+    if (decayIndex < 0)
+        decayIndex = 0;
+    if (rampIndex < 0)
+        rampIndex = 0;
+    
+    env->inRamp = OFALSE;
+    env->inAttack = OFALSE;
+    env->inDecay = OFALSE;
+    
+    env->attackInc = env->inc_buff[attackIndex];
+    env->decayInc = env->inc_buff[decayIndex];
+    env->rampInc = env->inc_buff[rampIndex];
+
+}
+
+void tEnvelope_free(tEnvelope* const env)
+{
+    
+}
+
+int     tEnvelope_setAttack(tEnvelope* const env, float attack)
+{
+    int32_t attackIndex;
+    
+    if (attack < 0.0f) {
+        attackIndex = 0.0f;
+    } else if (attack < 8192.0f) {
+        attackIndex = ((int32_t)(attack * 8.0f))-1;
+    } else {
+        attackIndex = ((int32_t)(8192.0f * 8.0f))-1;
+    }
+    
+    env->attackInc = env->inc_buff[attackIndex];
+    
+    return 0;
+}
+
+int     tEnvelope_setDecay(tEnvelope* const env, float decay)
+{
+    int32_t decayIndex;
+    
+    if (decay < 0.0f) {
+        decayIndex = 0.0f;
+    } else if (decay < 8192.0f) {
+        decayIndex = ((int32_t)(decay * 8.0f)) - 1;
+    } else {
+        decayIndex = ((int32_t)(8192.0f * 8.0f)) - 1; 
+    }
+    
+    env->decayInc = env->inc_buff[decayIndex]; 
+    
+    return 0;
+}
+
+int     tEnvelope_loop(tEnvelope* const env, oBool loop)
+{
+    env->loop = loop;
+    
+    return 0;
+}
+
+
+int     tEnvelope_on(tEnvelope* const env, float velocity)
+{
+    if (env->inAttack || env->inDecay) // In case envelope retriggered while it is still happening.
+    {
+        env->rampPhase = 0;
+        env->inRamp = OTRUE;
+        env->rampPeak = env->next;
+    }
+    else // Normal start.
+    {
+        env->inAttack = OTRUE;
+    }
+    
+    
+    env->attackPhase = 0;
+    env->decayPhase = 0;
+    env->inDecay = OFALSE;
+    env->gain = velocity;
+    
+    return 0;
+}
+
+float   tEnvelope_tick(tEnvelope* const env)
+{
+    if (env->inRamp)
+    {
+        if (env->rampPhase > UINT16_MAX)
+        {
+            env->inRamp = OFALSE;
+            env->inAttack = OTRUE;
+            env->next = 0.0f;
+        }
+        else
+        {
+            env->next = env->rampPeak * env->exp_buff[(uint32_t)env->rampPhase];
+        }
+        
+        env->rampPhase += env->rampInc;
+    }
+    
+    if (env->inAttack)
+    {
+        
+        // If attack done, time to turn around.
+        if (env->attackPhase > UINT16_MAX)
+        {
+            env->inDecay = OTRUE;
+            env->inAttack = OFALSE;
+            env->next = env->gain * 1.0f;
+        }
+        else
+        {
+            // do interpolation !
+            env->next = env->gain * env->exp_buff[UINT16_MAX - (uint32_t)env->attackPhase]; // inverted and backwards to get proper rising exponential shape/perception
+        }
+        
+        // Increment envelope attack.
+        env->attackPhase += env->attackInc;
+        
+    }
+    
+    if (env->inDecay)
+    {
+        
+        // If decay done, finish.
+        if (env->decayPhase >= UINT16_MAX)
+        {
+            env->inDecay = OFALSE;
+            
+            if (env->loop)
+            {
+                env->attackPhase = 0;
+                env->decayPhase = 0;
+                env->inAttack = OTRUE;
+            }
+            else
+            {
+                env->next = 0.0f;
+            }
+            
+        } else {
+            
+            env->next = env->gain * (env->exp_buff[(uint32_t)env->decayPhase]); // do interpolation !
+        }
+        
+        // Increment envelope decay;
+        env->decayPhase += env->decayInc;
+    }
+    
+    return env->next;
+}
+
+/* ADSR */
+void    tADSR_init(tADSR* const adsr, float attack, float decay, float sustain, float release)
+{
+    adsr->exp_buff = exp_decay;
+    adsr->inc_buff = attack_decay_inc;
+    adsr->buff_size = sizeof(exp_decay);
+    
+    if (attack > 8192.0f)
+        attack = 8192.0f;
+    if (attack < 0.0f)
+        attack = 0.0f;
+    
+    if (decay > 8192.0f)
+        decay = 8192.0f;
+    if (decay < 0.0f)
+        decay = 0.0f;
+    
+    if (sustain > 1.0f)
+        sustain = 1.0f;
+    if (sustain < 0.0f)
+        sustain = 0.0f;
+    
+    if (release > 8192.0f)
+        release = 8192.0f;
+    if (release < 0.0f)
+        release = 0.0f;
+    
+    int16_t attackIndex = ((int16_t)(attack * 8.0f))-1;
+    int16_t decayIndex = ((int16_t)(decay * 8.0f))-1;
+    int16_t releaseIndex = ((int16_t)(release * 8.0f))-1;
+    int16_t rampIndex = ((int16_t)(2.0f * 8.0f))-1;
+    
+    if (attackIndex < 0)
+        attackIndex = 0;
+    if (decayIndex < 0)
+        decayIndex = 0;
+    if (releaseIndex < 0)
+        releaseIndex = 0;
+    if (rampIndex < 0)
+        rampIndex = 0;
+    
+    adsr->inRamp = OFALSE;
+    adsr->inAttack = OFALSE;
+    adsr->inDecay = OFALSE;
+    adsr->inSustain = OFALSE;
+    adsr->inRelease = OFALSE;
+    
+    adsr->sustain = sustain;
+    
+    adsr->attackInc = adsr->inc_buff[attackIndex];
+    adsr->decayInc = adsr->inc_buff[decayIndex];
+    adsr->releaseInc = adsr->inc_buff[releaseIndex];
+    adsr->rampInc = adsr->inc_buff[rampIndex];
+}
+
+void tADSR_free(tADSR* const adsr)
+{
+    
+}
+
+int     tADSR_setAttack(tADSR* const adsr, float attack)
+{
+    int32_t attackIndex;
+    
+    if (attack < 0.0f) {
+        attackIndex = 0.0f;
+    } else if (attack < 8192.0f) {
+        attackIndex = ((int32_t)(attack * 8.0f))-1;
+    } else {
+        attackIndex = ((int32_t)(8192.0f * 8.0f))-1;
+    }
+    
+    adsr->attackInc = adsr->inc_buff[attackIndex];
+    
+    return 0;
+}
+
+int     tADSR_detDecay(tADSR* const adsr, float decay)
+{
+    int32_t decayIndex;
+    
+    if (decay < 0.0f) {
+        decayIndex = 0.0f;
+    } else if (decay < 8192.0f) {
+        decayIndex = ((int32_t)(decay * 8.0f)) - 1;
+    } else {
+        decayIndex = ((int32_t)(8192.0f * 8.0f)) - 1;
+    }
+    
+    adsr->decayInc = adsr->inc_buff[decayIndex];
+    
+    return 0;
+}
+
+int     tADSR_setSustain(tADSR *const adsr, float sustain)
+{
+    if (sustain > 1.0f)      adsr->sustain = 1.0f;
+    else if (sustain < 0.0f) adsr->sustain = 0.0f;
+    else                     adsr->sustain = sustain;
+    
+    return 0;
+}
+
+int     tADSR_setRelease(tADSR* const adsr, float release)
+{
+    int32_t releaseIndex;
+    
+    if (release < 0.0f) {
+        releaseIndex = 0.0f;
+    } else if (release < 8192.0f) {
+        releaseIndex = ((int32_t)(release * 8.0f)) - 1;
+    } else {
+        releaseIndex = ((int32_t)(8192.0f * 8.0f)) - 1;
+    }
+    
+    adsr->releaseInc = adsr->inc_buff[releaseIndex];
+    
+    return 0;
+}
+
+int tADSR_on(tADSR* const adsr, float velocity)
+{
+    if ((adsr->inAttack || adsr->inDecay) || (adsr->inSustain || adsr->inRelease)) // In case ADSR retriggered while it is still happening.
+    {
+        adsr->rampPhase = 0;
+        adsr->inRamp = OTRUE;
+        adsr->rampPeak = adsr->next;
+    }
+    else // Normal start.
+    {
+        adsr->inAttack = OTRUE;
+    }
+    
+    adsr->attackPhase = 0;
+    adsr->decayPhase = 0;
+    adsr->releasePhase = 0;
+    adsr->inDecay = OFALSE;
+    adsr->inSustain = OFALSE;
+    adsr->inRelease = OFALSE;
+    adsr->gain = velocity;
+    
+    return 0;
+}
+
+int tADSR_off(tADSR* const adsr)
+{
+    if (adsr->inRelease) return 0;
+    
+    adsr->inAttack = OFALSE;
+    adsr->inDecay = OFALSE;
+    adsr->inSustain = OFALSE;
+    adsr->inRelease = OTRUE;
+    
+    adsr->releasePeak = adsr->next;
+    
+    return 0;
+}
+
+float   tADSR_tick(tADSR* const adsr)
+{
+    if (adsr->inRamp)
+    {
+        if (adsr->rampPhase > UINT16_MAX)
+        {
+            adsr->inRamp = OFALSE;
+            adsr->inAttack = OTRUE;
+            adsr->next = 0.0f;
+        }
+        else
+        {
+            adsr->next = adsr->rampPeak * adsr->exp_buff[(uint32_t)adsr->rampPhase];
+        }
+        
+        adsr->rampPhase += adsr->rampInc;
+    }
+    
+    if (adsr->inAttack)
+    {
+        
+        // If attack done, time to turn around.
+        if (adsr->attackPhase > UINT16_MAX)
+        {
+            adsr->inDecay = OTRUE;
+            adsr->inAttack = OFALSE;
+            adsr->next = adsr->gain * 1.0f;
+        }
+        else
+        {
+            // do interpolation !
+            adsr->next = adsr->gain * adsr->exp_buff[UINT16_MAX - (uint32_t)adsr->attackPhase]; // inverted and backwards to get proper rising exponential shape/perception
+        }
+        
+        // Increment ADSR attack.
+        adsr->attackPhase += adsr->attackInc;
+        
+    }
+    
+    if (adsr->inDecay)
+    {
+        
+        // If decay done, sustain.
+        if (adsr->decayPhase >= UINT16_MAX)
+        {
+            adsr->inDecay = OFALSE;
+            adsr->inSustain = OTRUE;
+            adsr->next = adsr->gain * adsr->sustain;
+        }
+        
+        else
+        {
+            adsr->next = adsr->gain * (adsr->sustain + ((adsr->exp_buff[(uint32_t)adsr->decayPhase]) * (1 - adsr->sustain))); // do interpolation !
+        }
+        
+        // Increment ADSR decay.
+        adsr->decayPhase += adsr->decayInc;
+    }
+
+    if (adsr->inRelease)
+    {
+        // If release done, finish.
+        if (adsr->releasePhase >= UINT16_MAX)
+        {
+            adsr->inRelease = OFALSE;
+            adsr->next = 0.0f;
+        }
+        else {
+            
+            adsr->next = adsr->releasePeak * (adsr->exp_buff[(uint32_t)adsr->releasePhase]); // do interpolation !
+        }
+        
+        // Increment envelope release;
+        adsr->releasePhase += adsr->releaseInc;
+    }
+
+    return adsr->next;
+}
+
+/* Ramp */
+void    tRamp_init(tRamp* const ramp, float time, int samples_per_tick)
+{
+    ramp->inv_sr_ms = 1.0f/(leaf.sampleRate*0.001f);
+	ramp->minimum_time = ramp->inv_sr_ms * samples_per_tick;
+    ramp->curr = 0.0f;
+    ramp->dest = 0.0f;
+    
+    if (time < ramp->minimum_time)
+    {
+        ramp->time = ramp->minimum_time;
+    }
+    else
+    {
+        ramp->time = time;
+    }
+    
+    ramp->samples_per_tick = samples_per_tick;
+    ramp->inc = ((ramp->dest - ramp->curr) / ramp->time * ramp->inv_sr_ms) * (float)ramp->samples_per_tick;
+}
+
+void tRamp_free(tRamp* const ramp)
+{
+    
+}
+
+int     tRamp_setTime(tRamp* const r, float time)
+{
+	if (time < r->minimum_time)
+	{
+		r->time = r->minimum_time;
+	}
+	else
+	{
+		r->time = time;
+	}
+    r->inc = ((r->dest-r->curr)/r->time * r->inv_sr_ms) * ((float)r->samples_per_tick);
+    return 0;
+}
+
+int     tRamp_setDest(tRamp* const r, float dest)
+{
+    r->dest = dest;
+    r->inc = ((r->dest-r->curr)/r->time * r->inv_sr_ms) * ((float)r->samples_per_tick);
+    return 0;
+}
+
+int     tRamp_setVal(tRamp* const r, float val)
+{
+    r->curr = val;
+    r->inc = ((r->dest-r->curr)/r->time * r->inv_sr_ms) * ((float)r->samples_per_tick);
+    return 0;
+}
+
+float   tRamp_tick(tRamp* const r) {
+    
+    r->curr += r->inc;
+    
+    if (((r->curr >= r->dest) && (r->inc > 0.0f)) || ((r->curr <= r->dest) && (r->inc < 0.0f))) r->inc = 0.0f;
+    // Palle: There is a slight risk that you overshoot here and stay on dest+inc, which with a large inc value could be a real problem
+    // I suggest you add: r->curr=r->dest in the true if case
+    
+    return r->curr;
+}
+
+float   tRamp_sample(tRamp* const r) {
+  
+    return r->curr;
+}
+
+void    tRampSampleRateChanged(tRamp* const r)
+{
+    r->inv_sr_ms = 1.0f / (leaf.sampleRate * 0.001f);
+    r->inc = ((r->dest-r->curr)/r->time * r->inv_sr_ms)*((float)r->samples_per_tick);
+}
+
+
+/* Exponential Smoother */
+void    tExpSmooth_init(tExpSmooth* const smooth, float val, float factor)
+{	// factor is usually a value between 0 and 0.1. Lower value is slower. 0.01 for example gives you a smoothing time of about 10ms
+	smooth->curr=val;
+	smooth->dest=val;
+	if (factor<0) factor=0;
+	if (factor>1) factor=1;
+	smooth->factor=factor;
+	smooth->oneminusfactor=1.0f-factor;
+}
+
+void tExpSmooth_free(tExpSmooth* const smooth)
+{
+    
+}
+
+int     tExpSmooth_setFactor(tExpSmooth* const smooth, float factor)
+{	// factor is usually a value between 0 and 0.1. Lower value is slower. 0.01 for example gives you a smoothing time of about 10ms
+	if (factor<0)
+		factor=0;
+	else
+		if (factor>1) factor=1;
+	smooth->factor=factor;
+	smooth->oneminusfactor=1.0f-factor;
+    return 0;
+}
+
+int     tExpSmooth_setDest(tExpSmooth* const smooth, float dest)
+{
+	smooth->dest=dest;
+    return 0;
+}
+
+int     tExpSmooth_setVal(tExpSmooth* const smooth, float val)
+{
+	smooth->curr=val;
+    return 0;
+}
+
+float   tExpSmooth_tick(tExpSmooth* const smooth)
+{
+    smooth->curr = smooth->factor*smooth->dest+smooth->oneminusfactor*smooth->curr;
+    return smooth->curr;
+}
+
+float   tExpSmooth_sample(tExpSmooth* const smooth)
+{
+    return smooth->curr;
+}
+
--- a/LEAF/Src/leaf-filter.c
+++ /dev/null
@@ -1,843 +1,0 @@
-/*==============================================================================
-
-    leaf-filter.c
-    Created: 20 Jan 2017 12:01:10pm
-    Author:  Michael R Mulshine
-
-==============================================================================*/
-
-#if _WIN32 || _WIN64
-
-#include "..\Inc\leaf-filter.h"
-#include "..\Inc\leaf-tables.h"
-#include "..\leaf.h"
-
-#else
-
-#include "../Inc/leaf-filter.h"
-#include "../Inc/leaf-tables.h"
-#include "../leaf.h"
-
-#endif
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OnePole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
-void    tAllpass_init(tAllpass* const f, float initDelay, uint32_t maxDelay)
-{
-    f->gain = 0.7f;
-    
-    f->lastOut = 0.0f;
-    
-    tDelayL_init(&f->delay, initDelay, maxDelay);
-}
-
-void tAllpass_free(tAllpass* const f)
-{
-    tDelayL_free(&f->delay);
-}
-
-void    tAllpass_setDelay(tAllpass* const f, float delay)
-{
-    tDelayL_setDelay(&f->delay, delay);
-}
-
-void    tAllpass_setGain(tAllpass* const f, float gain)
-{
-    f->gain = gain;
-}
-
-float   tAllpass_tick(tAllpass* const f, float input)
-{
-    float s1 = (-f->gain) * f->lastOut + input;
-    
-    float s2 = tDelayL_tick(&f->delay, s1) + (f->gain) * input;
-    
-    f->lastOut = s2;
-    
-    return f->lastOut;
-}
-
-void tButterworth_init(tButterworth* const f, int N, float f1, float f2)
-{
-	f->f1 = f1;
-	f->f2 = f2;
-	f->gain = 1.0f;
-    
-    f->N = N;
-    
-    if (f->N > NUM_SVF_BW) f->N = NUM_SVF_BW;
-
-	for(int i = 0; i < N/2; ++i)
-	{
-        tSVF_init(&f->low[i], SVFTypeHighpass, f1, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)));
-        tSVF_init(&f->high[i], SVFTypeLowpass, f2, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)));
-	}
-}
-
-void tButterworth_free(tButterworth* const f)
-{
-    for(int i = 0; i < f->N/2; ++i)
-    {
-        tSVF_free(&f->low[i]);
-        tSVF_free(&f->high[i]);
-    }
-}
-
-float tButterworth_tick(tButterworth* const f, float samp)
-{
-	for(int i = 0; i < ((f->N)/2); ++i)
-	{
-		samp = tSVF_tick(&f->low[i],samp);
-		samp = tSVF_tick(&f->high[i],samp);
-	}
-	return samp;
-}
-
-void tButterworth_setF1(tButterworth* const f, float f1)
-{
-	f->f1 = f1;
-	for(int i = 0; i < ((f->N)/2); ++i)		tSVF_setFreq(&f->low[i], f1);
-}
-
-void tButterworth_setF2(tButterworth* const f, float f2)
-{
-	f->f2 = f2;
-	for(int i = 0; i < ((f->N)/2); ++i)		tSVF_setFreq(&f->high[i], f2);
-}
-
-void tButterworth_setFreqs(tButterworth* const f, float f1, float f2)
-{
-	f->f1 = f1;
-	f->f2 = f2;
-	for(int i = 0; i < ((f->N)/2); ++i)
-	{
-		tSVF_setFreq(&f->low[i], f1);
-		tSVF_setFreq(&f->high[i], f2);
-	}
-}
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OneZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
-void    tOneZero_init(tOneZero* const f, float theZero)
-{
-    f->gain = 1.0f;
-    f->lastIn = 0.0f;
-    f->lastOut = 0.0f;
-    tOneZero_setZero(f, theZero);
-}
-
-void    tOneZero_free(tOneZero* const f)
-{
-    
-}
-
-float   tOneZero_tick(tOneZero* const f, float input)
-{
-    float in = input * f->gain;
-    float out = f->b1 * f->lastIn + f->b0 * in;
-    
-    f->lastIn = in;
-    
-    return out;
-}
-
-void    tOneZero_setZero(tOneZero* const f, float theZero)
-{
-    if (theZero > 0.0f) f->b0 = 1.0f / (1.0f + theZero);
-    else                f->b0 = 1.0f / (1.0f - theZero);
-    
-    f->b1 = -theZero * f->b0;
-    
-}
-
-void    tOneZero_setB0(tOneZero* const f, float b0)
-{
-    f->b0 = b0;
-}
-
-void    tOneZero_setB1(tOneZero* const f, float b1)
-{
-    f->b1 = b1;
-}
-
-void    tOneZero_setCoefficients(tOneZero* const f, float b0, float b1)
-{
-    f->b0 = b0;
-    f->b1 = b1;
-}
-
-void    tOneZero_setGain(tOneZero *f, float gain)
-{
-    f->gain = gain;
-}
-
-float   tOneZero_getPhaseDelay(tOneZero* const f, float frequency )
-{
-    if ( frequency <= 0.0f) frequency = 0.05f;
-    
-    f->frequency = frequency;
-    
-    float omegaT = 2 * PI * frequency * leaf.invSampleRate;
-    float real = 0.0, imag = 0.0;
-    
-    real += f->b0;
-    
-    real += f->b1 * cosf(omegaT);
-    imag -= f->b1 * sinf(omegaT);
-    
-    real *= f->gain;
-    imag *= f->gain;
-    
-    float phase = atan2f( imag, real );
-    
-    real = 0.0; imag = 0.0;
-    
-    phase -= atan2f( imag, real );
-    
-    phase = fmodf( -phase, 2 * PI );
-    
-    return phase / omegaT;
-}
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ TwoZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
-void    tTwoZero_init(tTwoZero* const f)
-{
-    f->gain = 1.0f;
-    f->lastIn[0] = 0.0f;
-    f->lastIn[1] = 0.0f;
-}
-
-void    tTwoZero_free(tTwoZero* const f)
-{
-    
-}
-
-float   tTwoZero_tick(tTwoZero* const f, float input)
-{
-    float in = input * f->gain;
-    float out = f->b2 * f->lastIn[1] + f->b1 * f->lastIn[0] + f->b0 * in;
-    
-    f->lastIn[1] = f->lastIn[0];
-    f->lastIn[0] = in;
-    
-    return out;
-}
-
-void    tTwoZero_setNotch(tTwoZero* const f, float freq, float radius)
-{
-    // Should also deal with frequency being > half sample rate / nyquist. See STK
-    if (freq < 0.0f)    freq = 0.0f;
-    if (radius < 0.0f)  radius = 0.0f;
-    
-    f->frequency = freq;
-    f->radius = radius;
-    
-    f->b2 = radius * radius;
-    f->b1 = -2.0f * radius * cosf(TWO_PI * freq * leaf.invSampleRate); // OPTIMIZE with LOOKUP or APPROXIMATION
-    
-    // Normalize the filter gain. From STK.
-    if ( f->b1 > 0.0f ) // Maximum at z = 0.
-        f->b0 = 1.0f / ( 1.0f + f->b1 + f->b2 );
-    else            // Maximum at z = -1.
-        f->b0 = 1.0f / ( 1.0f - f->b1 + f->b2 );
-    f->b1 *= f->b0;
-    f->b2 *= f->b0;
-    
-}
-
-void    tTwoZero_setB0(tTwoZero* const f, float b0)
-{
-    f->b0 = b0;
-}
-
-void    tTwoZero_setB1(tTwoZero* const f, float b1)
-{
-    f->b1 = b1;
-}
-
-void    tTwoZero_setCoefficients(tTwoZero* const f, float b0, float b1, float b2)
-{
-    f->b0 = b0;
-    f->b1 = b1;
-    f->b2 = b2;
-}
-
-void    tTwoZero_setGain(tTwoZero* const f, float gain)
-{
-    f->gain = gain;
-}
-
-void tTwoZeroSampleRateChanged(tTwoZero* const f)
-{
-    tTwoZero_setNotch(f, f->frequency, f->radius);
-}
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OnePole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
-void    tOnePole_init(tOnePole* const f, float freq)
-{
-    f->gain = 1.0f;
-    f->a0 = 1.0;
-    
-    tOnePole_setFreq(f, freq);
-    
-    f->lastIn = 0.0f;
-    f->lastOut = 0.0f;
-}
-
-void    tOnePole_free(tOnePole* const f)
-{
-    
-}
-
-void    tOnePole_setB0(tOnePole* const f, float b0)
-{
-    f->b0 = b0;
-}
-
-void    tOnePole_setA1(tOnePole* const f, float a1)
-{
-    if (a1 >= 1.0f)     a1 = 0.999999f;
-    
-    f->a1 = a1;
-}
-
-void    tOnePole_setPole(tOnePole* const f, float thePole)
-{
-    if (thePole >= 1.0f)    thePole = 0.999999f;
-    
-    // Normalize coefficients for peak unity gain.
-    if (thePole > 0.0f)     f->b0 = (1.0f - thePole);
-    else                    f->b0 = (1.0f + thePole);
-    
-    f->a1 = -thePole;
-}
-
-void        tOnePole_setFreq        (tOnePole* const f, float freq)
-{
-    f->b0 = freq * TWO_PI * leaf.invSampleRate;
-    
-    f->b0 = LEAF_clip(0.0f, f->b0, 1.0f);
-    
-    f->a1 = 1.0f - f->b0;
-}
-
-void    tOnePole_setCoefficients(tOnePole* const f, float b0, float a1)
-{
-    if (a1 >= 1.0f)     a1 = 0.999999f;
-    
-    f->b0 = b0;
-    f->a1 = a1;
-}
-
-void    tOnePole_setGain(tOnePole* const f, float gain)
-{
-    f->gain = gain;
-}
-
-float   tOnePole_tick(tOnePole* const f, float input)
-{
-    float in = input * f->gain;
-    float out = (f->b0 * in) + (f->a1 * f->lastOut);
-    
-    f->lastIn = in;
-    f->lastOut = out;
-    
-    return out;
-}
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ TwoPole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
-void    tTwoPole_init(tTwoPole* const f)
-{
-    f->gain = 1.0f;
-    f->a0 = 1.0;
-    f->b0 = 1.0;
-    
-    f->lastOut[0] = 0.0f;
-    f->lastOut[1] = 0.0f;
-}
-
-void    tTwoPole_free(tTwoPole* const f)
-{
-    
-}
-
-float   tTwoPole_tick(tTwoPole* const f, float input)
-{
-    float in = input * f->gain;
-    float out = (f->b0 * in) - (f->a1 * f->lastOut[0]) - (f->a2 * f->lastOut[1]);
-    
-    f->lastOut[1] = f->lastOut[0];
-    f->lastOut[0] = out;
-    
-    return out;
-}
-
-void    tTwoPole_setB0(tTwoPole* const f, float b0)
-{
-    f->b0 = b0;
-}
-
-void    tTwoPole_setA1(tTwoPole* const f, float a1)
-{
-    f->a1 = a1;
-}
-
-void    tTwoPole_setA2(tTwoPole* const f, float a2)
-{
-    f->a2 = a2;
-}
-
-
-void    tTwoPole_setResonance(tTwoPole* const f, float frequency, float radius, oBool normalize)
-{
-    if (frequency < 0.0f)   frequency = 0.0f; // need to also handle when frequency > nyquist
-    if (radius < 0.0f)      radius = 0.0f;
-    if (radius >= 1.0f)     radius = 0.999999f;
-    
-    f->radius = radius;
-    f->frequency = frequency;
-    f->normalize = normalize;
-    
-    f->a2 = radius * radius;
-    f->a1 =  -2.0f * radius * cos(TWO_PI * frequency * leaf.invSampleRate);
-    
-    if ( normalize )
-    {
-        // Normalize the filter gain ... not terribly efficient.
-        float real = 1 - radius + (f->a2 - radius) * cos(TWO_PI * 2 * frequency * leaf.invSampleRate);
-        float imag = (f->a2 - radius) * sin(TWO_PI * 2 * frequency * leaf.invSampleRate);
-        f->b0 = sqrt( pow(real, 2) + pow(imag, 2) );
-    }
-}
-
-void    tTwoPole_setCoefficients(tTwoPole* const f, float b0, float a1, float a2)
-{
-    f->b0 = b0;
-    f->a1 = a1;
-    f->a2 = a2;
-}
-
-void    tTwoPole_setGain(tTwoPole* const f, float gain)
-{
-    f->gain = gain;
-}
-
-void     tTwoPoleSampleRateChanged (tTwoPole* const f)
-{
-    f->a2 = f->radius * f->radius;
-    f->a1 =  -2.0f * f->radius * cos(TWO_PI * f->frequency * leaf.invSampleRate);
-    
-    if ( f->normalize )
-    {
-        // Normalize the filter gain ... not terribly efficient.
-        float real = 1 - f->radius + (f->a2 - f->radius) * cos(TWO_PI * 2 * f->frequency * leaf.invSampleRate);
-        float imag = (f->a2 - f->radius) * sin(TWO_PI * 2 * f->frequency * leaf.invSampleRate);
-        f->b0 = sqrt( pow(real, 2) + pow(imag, 2) );
-    }
-}
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ PoleZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
-void   tPoleZero_init(tPoleZero* const f)
-{
-    f->gain = 1.0f;
-    f->b0 = 1.0;
-    f->a0 = 1.0;
-    
-    f->lastIn = 0.0f;
-    f->lastOut = 0.0f;
-}
-
-void   tPoleZero_free(tPoleZero* const f)
-{
-    
-}
-
-void    tPoleZero_setB0(tPoleZero* const pzf, float b0)
-{
-    pzf->b0 = b0;
-}
-
-void    tPoleZero_setB1(tPoleZero* const pzf, float b1)
-{
-    pzf->b1 = b1;
-}
-
-void    tPoleZero_setA1(tPoleZero* const pzf, float a1)
-{
-    if (a1 >= 1.0f) // a1 should be less than 1.0
-    {
-        a1 = 0.999999f;
-    }
-    
-    pzf->a1 = a1;
-}
-
-void    tPoleZero_setCoefficients(tPoleZero* const pzf, float b0, float b1, float a1)
-{
-    if (a1 >= 1.0f) // a1 should be less than 1.0
-    {
-        a1 = 0.999999f;
-    }
-    
-    pzf->b0 = b0;
-    pzf->b1 = b1;
-    pzf->a1 = a1;
-}
-
-void    tPoleZero_setAllpass(tPoleZero* const pzf, float coeff)
-{
-    if (coeff >= 1.0f) // allpass coefficient >= 1.0 makes filter unstable
-    {
-        coeff = 0.999999f;
-    }
-    
-    pzf->b0 = coeff;
-    pzf->b1 = 1.0f;
-    pzf->a0 = 1.0f;
-    pzf->a1 = coeff;
-}
-
-void    tPoleZero_setBlockZero(tPoleZero* const pzf, float thePole)
-{
-    if (thePole >= 1.0f) // allpass coefficient >= 1.0 makes filter unstable
-    {
-        thePole = 0.999999f;
-    }
-    
-    pzf->b0 = 1.0f;
-    pzf->b1 = -1.0f;
-    pzf->a0 = 1.0f;
-    pzf->a1 = -thePole;
-}
-
-void    tPoleZero_setGain(tPoleZero* const pzf, float gain)
-{
-    pzf->gain = gain;
-}
-
-float   tPoleZero_tick(tPoleZero* const pzf, float input)
-{
-    float in = input * pzf->gain;
-    float out = (pzf->b0 * in) + (pzf->b1 * pzf->lastIn) - (pzf->a1 * pzf->lastOut);
-    
-    pzf->lastIn = in;
-    pzf->lastOut = out;
-    
-    return out;
-}
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ BiQuad Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
-void    tBiQuad_init(tBiQuad* const f)
-{
-    f->gain = 1.0f;
-    
-    f->b0 = 0.0f;
-    f->a0 = 0.0f;
-    
-    f->lastIn[0] = 0.0f;
-    f->lastIn[1] = 0.0f;
-    f->lastOut[0] = 0.0f;
-    f->lastOut[1] = 0.0f;
-}
-
-void    tBiQuad_free(tBiQuad* const f)
-{
-    
-}
-
-float   tBiQuad_tick(tBiQuad* const f, float input)
-{
-    float in = input * f->gain;
-    float out = f->b0 * in + f->b1 * f->lastIn[0] + f->b2 * f->lastIn[1];
-    out -= f->a2 * f->lastOut[1] + f->a1 * f->lastOut[0];
-    
-    f->lastIn[1] = f->lastIn[0];
-    f->lastIn[0] = in;
-    
-    f->lastOut[1] = f->lastOut[0];
-    f->lastOut[0] = out;
-    
-    return out;
-}
-
-void    tBiQuad_setResonance(tBiQuad* const f, float freq, float radius, oBool normalize)
-{
-    // Should also deal with frequency being > half sample rate / nyquist. See STK
-    if (freq < 0.0f)    freq = 0.0f;
-    if (radius < 0.0f)  radius = 0.0f;
-    if (radius >= 1.0f)  radius = 1.0f;
-    
-    f->frequency = freq;
-    f->radius = radius;
-    f->normalize = normalize;
-    
-    f->a2 = radius * radius;
-    f->a1 = -2.0f * radius * cosf(TWO_PI * freq * leaf.invSampleRate);
-    
-    if (normalize)
-    {
-        f->b0 = 0.5f - 0.5f * f->a2;
-        f->b1 = 0.0f;
-        f->b2 = -f->b0;
-    }
-}
-
-void    tBiQuad_setNotch(tBiQuad* const f, float freq, float radius)
-{
-    // Should also deal with frequency being > half sample rate / nyquist. See STK
-    if (freq < 0.0f)    freq = 0.0f;
-    if (radius < 0.0f)  radius = 0.0f;
-    
-    f->b2 = radius * radius;
-    f->b1 = -2.0f * radius * cosf(TWO_PI * freq * leaf.invSampleRate); // OPTIMIZE with LOOKUP or APPROXIMATION
-    
-    // Does not attempt to normalize filter gain.
-}
-
-void tBiQuad_setEqualGainZeros(tBiQuad* const f)
-{
-    f->b0 = 1.0f;
-    f->b1 = 0.0f;
-    f->b2 = -1.0f;
-}
-
-void    tBiQuad_setB0(tBiQuad* const f, float b0)
-{
-    f->b0 = b0;
-}
-
-void    tBiQuad_setB1(tBiQuad* const f, float b1)
-{
-    f->b1 = b1;
-}
-
-void    tBiQuad_setB2(tBiQuad* const f, float b2)
-{
-    f->b2 = b2;
-}
-
-void    tBiQuad_setA1(tBiQuad* const f, float a1)
-{
-    f->a1 = a1;
-}
-
-void    tBiQuad_setA2(tBiQuad* const f, float a2)
-{
-    f->a2 = a2;
-}
-
-void    tBiQuad_setCoefficients(tBiQuad* const f, float b0, float b1, float b2, float a1, float a2)
-{
-    f->b0 = b0;
-    f->b1 = b1;
-    f->b2 = b2;
-    f->a1 = a1;
-    f->a2 = a2;
-}
-
-void    tBiQuad_setGain(tBiQuad* const f, float gain)
-{
-    f->gain = gain;
-}
-
-void    tBiQuadSampleRateChanged(tBiQuad* const f)
-{
-    f->a2 = f->radius * f->radius;
-    f->a1 = -2.0f * f->radius * cosf(TWO_PI * f->frequency * leaf.invSampleRate);
-    
-    if (f->normalize)
-    {
-        f->b0 = 0.5f - 0.5f * f->a2;
-        f->b1 = 0.0f;
-        f->b2 = -f->b0;
-    }
-}
-
-/* Highpass */
-void    tHighpass_init(tHighpass* const f, float freq)
-{
-    f->R = (1.0f-((freq * 2.0f * 3.14f)* leaf.invSampleRate));
-    f->ys = 0.0f;
-    f->xs = 0.0f;
-    
-    f->frequency = freq;
-}
-
-void    tHighpass_free(tHighpass* const f)
-{
-    
-}
-
-void     tHighpass_setFreq(tHighpass* const f, float freq)
-{
-    f->frequency = freq;
-    f->R = (1.0f-((freq * 2.0f * 3.14f) * leaf.invSampleRate));
-    
-}
-
-float     tHighpass_getFreq(tHighpass* const f)
-{
-    return f->frequency;
-}
-
-// From JOS DC Blocker
-float   tHighpass_tick(tHighpass* const f, float x)
-{
-    f->ys = x - f->xs + f->R * f->ys;
-    f->xs = x;
-    return f->ys;
-}
-
-void tHighpassSampleRateChanged(tHighpass* const f)
-{
-    f->R = (1.0f-((f->frequency * 2.0f * 3.14f) * leaf.invSampleRate));
-}
-
-float   tSVF_tick(tSVF* const svf, float v0)
-{
-    float v1,v2,v3;
-    v3 = v0 - svf->ic2eq;
-    v1 = (svf->a1 * svf->ic1eq) + (svf->a2 * v3);
-    v2 = svf->ic2eq + (svf->a2 * svf->ic1eq) + (svf->a3 * v3);
-    svf->ic1eq = (2.0f * v1) - svf->ic1eq;
-    svf->ic2eq = (2.0f * v2) - svf->ic2eq;
-    
-    if (svf->type == SVFTypeLowpass)        return v2;
-    else if (svf->type == SVFTypeBandpass)  return v1;
-    else if (svf->type == SVFTypeHighpass)  return v0 - (svf->k * v1) - v2;
-    else if (svf->type == SVFTypeNotch)     return v0 - (svf->k * v1);
-    else if (svf->type == SVFTypePeak)      return v0 - (svf->k * v1) - (2.0f * v2);
-    else                                    return 0.0f;
-    
-}
-
-// Less efficient, more accurate version of SVF, in which cutoff frequency is taken as floating point Hz value and tanh
-// is calculated when frequency changes.
-void tSVF_init(tSVF* const svf, SVFType type, float freq, float Q)
-{
-    svf->type = type;
-    
-    svf->ic1eq = 0;
-    svf->ic2eq = 0;
-    
-    float a1,a2,a3,g,k;
-    g = tanf(PI * freq * leaf.invSampleRate);
-    k = 1.0f/Q;
-    a1 = 1.0f/(1.0f+g*(g+k));
-    a2 = g*a1;
-    a3 = g*a2;
-    
-    svf->g = g;
-    svf->k = k;
-    svf->a1 = a1;
-    svf->a2 = a2;
-    svf->a3 = a3;
-}
-
-void tSVF_free(tSVF* const svf)
-{
-    
-}
-
-int     tSVF_setFreq(tSVF* const svf, float freq)
-{
-    svf->g = tanf(PI * freq * leaf.invSampleRate);
-    svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
-    svf->a2 = svf->g * svf->a1;
-    svf->a3 = svf->g * svf->a2;
-    
-    return 0;
-}
-
-int     tSVF_setQ(tSVF* const svf, float Q)
-{
-    svf->k = 1.0f/Q;
-    svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
-    svf->a2 = svf->g * svf->a1;
-    svf->a3 = svf->g * svf->a2;
-    
-    return 0;
-}
-
-// Efficient version of tSVF where frequency is set based on 12-bit integer input for lookup in tanh wavetable.
-void   tSVFE_init(tSVFE* const svf, SVFType type, uint16_t input, float Q)
-{
-    svf->type = type;
-    
-    svf->ic1eq = 0;
-    svf->ic2eq = 0;
-    
-    float a1,a2,a3,g,k;
-    g = filtertan[input];
-    k = 1.0f/Q;
-    a1 = 1.0f/(1.0f+g*(g+k));
-    a2 = g*a1;
-    a3 = g*a2;
-    
-    svf->g = g;
-    svf->k = k;
-    svf->a1 = a1;
-    svf->a2 = a2;
-    svf->a3 = a3;
-}
-
-void tSVFE_free(tSVFE* const svf)
-{
-    
-}
-
-float   tSVFE_tick(tSVFE* const svf, float v0)
-{
-    float v1,v2,v3;
-    v3 = v0 - svf->ic2eq;
-    v1 = (svf->a1 * svf->ic1eq) + (svf->a2 * v3);
-    v2 = svf->ic2eq + (svf->a2 * svf->ic1eq) + (svf->a3 * v3);
-    svf->ic1eq = (2.0f * v1) - svf->ic1eq;
-    svf->ic2eq = (2.0f * v2) - svf->ic2eq;
-    
-    if (svf->type == SVFTypeLowpass)        return v2;
-    else if (svf->type == SVFTypeBandpass)  return v1;
-    else if (svf->type == SVFTypeHighpass)  return v0 - (svf->k * v1) - v2;
-    else if (svf->type == SVFTypeNotch)     return v0 - (svf->k * v1);
-    else if (svf->type == SVFTypePeak)      return v0 - (svf->k * v1) - (2.0f * v2);
-    else                                    return 0.0f;
-    
-}
-
-int     tSVFE_setFreq(tSVFE* const svf, uint16_t input)
-{
-    svf->g = filtertan[input];
-    svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
-    svf->a2 = svf->g * svf->a1;
-    svf->a3 = svf->g * svf->a2;
-    
-    return 0;
-}
-
-int     tSVFE_setQ(tSVFE* const svf, float Q)
-{
-    svf->k = 1.0f/Q;
-    svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
-    svf->a2 = svf->g * svf->a1;
-    svf->a3 = svf->g * svf->a2;
-    
-    return 0;
-}
-
-void	tFIR_init(tFIR* const fir, float* coeffs, int numTaps){
-    fir->numTaps = numTaps;
-    fir->coeff = coeffs;
-    fir->past = (float*)leaf_alloc(sizeof(float) * fir->numTaps);
-    for (int i = 0; i < fir->numTaps; ++i) fir->past[i] = 0.0f;
-}
-
-float	tFIR_tick(tFIR* const fir, float input){
-	fir->past[0] = input;
-	float y = 0.0f;
-	for (int i = 0; i < fir->numTaps; ++i) y += fir->past[i]*fir->coeff[i];
-	for (int i = fir->numTaps-1; i > 0; --i) fir->past[i] = fir->past[i-1];
-	return y;
-}
-
-void	tFIR_free(tFIR* const fir)
-{
-    leaf_free(fir->past);
-}
--- /dev/null
+++ b/LEAF/Src/leaf-filters.c
@@ -1,0 +1,843 @@
+/*==============================================================================
+
+    leaf-filter.c
+    Created: 20 Jan 2017 12:01:10pm
+    Author:  Michael R Mulshine
+
+==============================================================================*/
+
+#if _WIN32 || _WIN64
+
+#include "..\Inc\leaf-filters.h"
+#include "..\Inc\leaf-tables.h"
+#include "..\leaf.h"
+
+#else
+
+#include "../Inc/leaf-filters.h"
+#include "../Inc/leaf-tables.h"
+#include "../leaf.h"
+
+#endif
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OnePole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
+void    tAllpass_init(tAllpass* const f, float initDelay, uint32_t maxDelay)
+{
+    f->gain = 0.7f;
+    
+    f->lastOut = 0.0f;
+    
+    tLinearDelay_init(&f->delay, initDelay, maxDelay);
+}
+
+void tAllpass_free(tAllpass* const f)
+{
+    tLinearDelay_free(&f->delay);
+}
+
+void    tAllpass_setDelay(tAllpass* const f, float delay)
+{
+    tLinearDelay_setDelay(&f->delay, delay);
+}
+
+void    tAllpass_setGain(tAllpass* const f, float gain)
+{
+    f->gain = gain;
+}
+
+float   tAllpass_tick(tAllpass* const f, float input)
+{
+    float s1 = (-f->gain) * f->lastOut + input;
+    
+    float s2 = tLinearDelay_tick(&f->delay, s1) + (f->gain) * input;
+    
+    f->lastOut = s2;
+    
+    return f->lastOut;
+}
+
+void tButterworth_init(tButterworth* const f, int N, float f1, float f2)
+{
+	f->f1 = f1;
+	f->f2 = f2;
+	f->gain = 1.0f;
+    
+    f->N = N;
+    
+    if (f->N > NUM_SVF_BW) f->N = NUM_SVF_BW;
+
+	for(int i = 0; i < N/2; ++i)
+	{
+        tSVF_init(&f->low[i], SVFTypeHighpass, f1, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)));
+        tSVF_init(&f->high[i], SVFTypeLowpass, f2, 0.5f/cosf((1.0f+2.0f*i)*PI/(2*N)));
+	}
+}
+
+void tButterworth_free(tButterworth* const f)
+{
+    for(int i = 0; i < f->N/2; ++i)
+    {
+        tSVF_free(&f->low[i]);
+        tSVF_free(&f->high[i]);
+    }
+}
+
+float tButterworth_tick(tButterworth* const f, float samp)
+{
+	for(int i = 0; i < ((f->N)/2); ++i)
+	{
+		samp = tSVF_tick(&f->low[i],samp);
+		samp = tSVF_tick(&f->high[i],samp);
+	}
+	return samp;
+}
+
+void tButterworth_setF1(tButterworth* const f, float f1)
+{
+	f->f1 = f1;
+	for(int i = 0; i < ((f->N)/2); ++i)		tSVF_setFreq(&f->low[i], f1);
+}
+
+void tButterworth_setF2(tButterworth* const f, float f2)
+{
+	f->f2 = f2;
+	for(int i = 0; i < ((f->N)/2); ++i)		tSVF_setFreq(&f->high[i], f2);
+}
+
+void tButterworth_setFreqs(tButterworth* const f, float f1, float f2)
+{
+	f->f1 = f1;
+	f->f2 = f2;
+	for(int i = 0; i < ((f->N)/2); ++i)
+	{
+		tSVF_setFreq(&f->low[i], f1);
+		tSVF_setFreq(&f->high[i], f2);
+	}
+}
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OneZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
+void    tOneZero_init(tOneZero* const f, float theZero)
+{
+    f->gain = 1.0f;
+    f->lastIn = 0.0f;
+    f->lastOut = 0.0f;
+    tOneZero_setZero(f, theZero);
+}
+
+void    tOneZero_free(tOneZero* const f)
+{
+    
+}
+
+float   tOneZero_tick(tOneZero* const f, float input)
+{
+    float in = input * f->gain;
+    float out = f->b1 * f->lastIn + f->b0 * in;
+    
+    f->lastIn = in;
+    
+    return out;
+}
+
+void    tOneZero_setZero(tOneZero* const f, float theZero)
+{
+    if (theZero > 0.0f) f->b0 = 1.0f / (1.0f + theZero);
+    else                f->b0 = 1.0f / (1.0f - theZero);
+    
+    f->b1 = -theZero * f->b0;
+    
+}
+
+void    tOneZero_setB0(tOneZero* const f, float b0)
+{
+    f->b0 = b0;
+}
+
+void    tOneZero_setB1(tOneZero* const f, float b1)
+{
+    f->b1 = b1;
+}
+
+void    tOneZero_setCoefficients(tOneZero* const f, float b0, float b1)
+{
+    f->b0 = b0;
+    f->b1 = b1;
+}
+
+void    tOneZero_setGain(tOneZero *f, float gain)
+{
+    f->gain = gain;
+}
+
+float   tOneZero_getPhaseDelay(tOneZero* const f, float frequency )
+{
+    if ( frequency <= 0.0f) frequency = 0.05f;
+    
+    f->frequency = frequency;
+    
+    float omegaT = 2 * PI * frequency * leaf.invSampleRate;
+    float real = 0.0, imag = 0.0;
+    
+    real += f->b0;
+    
+    real += f->b1 * cosf(omegaT);
+    imag -= f->b1 * sinf(omegaT);
+    
+    real *= f->gain;
+    imag *= f->gain;
+    
+    float phase = atan2f( imag, real );
+    
+    real = 0.0; imag = 0.0;
+    
+    phase -= atan2f( imag, real );
+    
+    phase = fmodf( -phase, 2 * PI );
+    
+    return phase / omegaT;
+}
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ TwoZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
+void    tTwoZero_init(tTwoZero* const f)
+{
+    f->gain = 1.0f;
+    f->lastIn[0] = 0.0f;
+    f->lastIn[1] = 0.0f;
+}
+
+void    tTwoZero_free(tTwoZero* const f)
+{
+    
+}
+
+float   tTwoZero_tick(tTwoZero* const f, float input)
+{
+    float in = input * f->gain;
+    float out = f->b2 * f->lastIn[1] + f->b1 * f->lastIn[0] + f->b0 * in;
+    
+    f->lastIn[1] = f->lastIn[0];
+    f->lastIn[0] = in;
+    
+    return out;
+}
+
+void    tTwoZero_setNotch(tTwoZero* const f, float freq, float radius)
+{
+    // Should also deal with frequency being > half sample rate / nyquist. See STK
+    if (freq < 0.0f)    freq = 0.0f;
+    if (radius < 0.0f)  radius = 0.0f;
+    
+    f->frequency = freq;
+    f->radius = radius;
+    
+    f->b2 = radius * radius;
+    f->b1 = -2.0f * radius * cosf(TWO_PI * freq * leaf.invSampleRate); // OPTIMIZE with LOOKUP or APPROXIMATION
+    
+    // Normalize the filter gain. From STK.
+    if ( f->b1 > 0.0f ) // Maximum at z = 0.
+        f->b0 = 1.0f / ( 1.0f + f->b1 + f->b2 );
+    else            // Maximum at z = -1.
+        f->b0 = 1.0f / ( 1.0f - f->b1 + f->b2 );
+    f->b1 *= f->b0;
+    f->b2 *= f->b0;
+    
+}
+
+void    tTwoZero_setB0(tTwoZero* const f, float b0)
+{
+    f->b0 = b0;
+}
+
+void    tTwoZero_setB1(tTwoZero* const f, float b1)
+{
+    f->b1 = b1;
+}
+
+void    tTwoZero_setCoefficients(tTwoZero* const f, float b0, float b1, float b2)
+{
+    f->b0 = b0;
+    f->b1 = b1;
+    f->b2 = b2;
+}
+
+void    tTwoZero_setGain(tTwoZero* const f, float gain)
+{
+    f->gain = gain;
+}
+
+void tTwoZeroSampleRateChanged(tTwoZero* const f)
+{
+    tTwoZero_setNotch(f, f->frequency, f->radius);
+}
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OnePole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
+void    tOnePole_init(tOnePole* const f, float freq)
+{
+    f->gain = 1.0f;
+    f->a0 = 1.0;
+    
+    tOnePole_setFreq(f, freq);
+    
+    f->lastIn = 0.0f;
+    f->lastOut = 0.0f;
+}
+
+void    tOnePole_free(tOnePole* const f)
+{
+    
+}
+
+void    tOnePole_setB0(tOnePole* const f, float b0)
+{
+    f->b0 = b0;
+}
+
+void    tOnePole_setA1(tOnePole* const f, float a1)
+{
+    if (a1 >= 1.0f)     a1 = 0.999999f;
+    
+    f->a1 = a1;
+}
+
+void    tOnePole_setPole(tOnePole* const f, float thePole)
+{
+    if (thePole >= 1.0f)    thePole = 0.999999f;
+    
+    // Normalize coefficients for peak unity gain.
+    if (thePole > 0.0f)     f->b0 = (1.0f - thePole);
+    else                    f->b0 = (1.0f + thePole);
+    
+    f->a1 = -thePole;
+}
+
+void        tOnePole_setFreq        (tOnePole* const f, float freq)
+{
+    f->b0 = freq * TWO_PI * leaf.invSampleRate;
+    
+    f->b0 = LEAF_clip(0.0f, f->b0, 1.0f);
+    
+    f->a1 = 1.0f - f->b0;
+}
+
+void    tOnePole_setCoefficients(tOnePole* const f, float b0, float a1)
+{
+    if (a1 >= 1.0f)     a1 = 0.999999f;
+    
+    f->b0 = b0;
+    f->a1 = a1;
+}
+
+void    tOnePole_setGain(tOnePole* const f, float gain)
+{
+    f->gain = gain;
+}
+
+float   tOnePole_tick(tOnePole* const f, float input)
+{
+    float in = input * f->gain;
+    float out = (f->b0 * in) + (f->a1 * f->lastOut);
+    
+    f->lastIn = in;
+    f->lastOut = out;
+    
+    return out;
+}
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ TwoPole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
+void    tTwoPole_init(tTwoPole* const f)
+{
+    f->gain = 1.0f;
+    f->a0 = 1.0;
+    f->b0 = 1.0;
+    
+    f->lastOut[0] = 0.0f;
+    f->lastOut[1] = 0.0f;
+}
+
+void    tTwoPole_free(tTwoPole* const f)
+{
+    
+}
+
+float   tTwoPole_tick(tTwoPole* const f, float input)
+{
+    float in = input * f->gain;
+    float out = (f->b0 * in) - (f->a1 * f->lastOut[0]) - (f->a2 * f->lastOut[1]);
+    
+    f->lastOut[1] = f->lastOut[0];
+    f->lastOut[0] = out;
+    
+    return out;
+}
+
+void    tTwoPole_setB0(tTwoPole* const f, float b0)
+{
+    f->b0 = b0;
+}
+
+void    tTwoPole_setA1(tTwoPole* const f, float a1)
+{
+    f->a1 = a1;
+}
+
+void    tTwoPole_setA2(tTwoPole* const f, float a2)
+{
+    f->a2 = a2;
+}
+
+
+void    tTwoPole_setResonance(tTwoPole* const f, float frequency, float radius, oBool normalize)
+{
+    if (frequency < 0.0f)   frequency = 0.0f; // need to also handle when frequency > nyquist
+    if (radius < 0.0f)      radius = 0.0f;
+    if (radius >= 1.0f)     radius = 0.999999f;
+    
+    f->radius = radius;
+    f->frequency = frequency;
+    f->normalize = normalize;
+    
+    f->a2 = radius * radius;
+    f->a1 =  -2.0f * radius * cos(TWO_PI * frequency * leaf.invSampleRate);
+    
+    if ( normalize )
+    {
+        // Normalize the filter gain ... not terribly efficient.
+        float real = 1 - radius + (f->a2 - radius) * cos(TWO_PI * 2 * frequency * leaf.invSampleRate);
+        float imag = (f->a2 - radius) * sin(TWO_PI * 2 * frequency * leaf.invSampleRate);
+        f->b0 = sqrt( pow(real, 2) + pow(imag, 2) );
+    }
+}
+
+void    tTwoPole_setCoefficients(tTwoPole* const f, float b0, float a1, float a2)
+{
+    f->b0 = b0;
+    f->a1 = a1;
+    f->a2 = a2;
+}
+
+void    tTwoPole_setGain(tTwoPole* const f, float gain)
+{
+    f->gain = gain;
+}
+
+void     tTwoPoleSampleRateChanged (tTwoPole* const f)
+{
+    f->a2 = f->radius * f->radius;
+    f->a1 =  -2.0f * f->radius * cos(TWO_PI * f->frequency * leaf.invSampleRate);
+    
+    if ( f->normalize )
+    {
+        // Normalize the filter gain ... not terribly efficient.
+        float real = 1 - f->radius + (f->a2 - f->radius) * cos(TWO_PI * 2 * f->frequency * leaf.invSampleRate);
+        float imag = (f->a2 - f->radius) * sin(TWO_PI * 2 * f->frequency * leaf.invSampleRate);
+        f->b0 = sqrt( pow(real, 2) + pow(imag, 2) );
+    }
+}
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ PoleZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
+void   tPoleZero_init(tPoleZero* const f)
+{
+    f->gain = 1.0f;
+    f->b0 = 1.0;
+    f->a0 = 1.0;
+    
+    f->lastIn = 0.0f;
+    f->lastOut = 0.0f;
+}
+
+void   tPoleZero_free(tPoleZero* const f)
+{
+    
+}
+
+void    tPoleZero_setB0(tPoleZero* const pzf, float b0)
+{
+    pzf->b0 = b0;
+}
+
+void    tPoleZero_setB1(tPoleZero* const pzf, float b1)
+{
+    pzf->b1 = b1;
+}
+
+void    tPoleZero_setA1(tPoleZero* const pzf, float a1)
+{
+    if (a1 >= 1.0f) // a1 should be less than 1.0
+    {
+        a1 = 0.999999f;
+    }
+    
+    pzf->a1 = a1;
+}
+
+void    tPoleZero_setCoefficients(tPoleZero* const pzf, float b0, float b1, float a1)
+{
+    if (a1 >= 1.0f) // a1 should be less than 1.0
+    {
+        a1 = 0.999999f;
+    }
+    
+    pzf->b0 = b0;
+    pzf->b1 = b1;
+    pzf->a1 = a1;
+}
+
+void    tPoleZero_setAllpass(tPoleZero* const pzf, float coeff)
+{
+    if (coeff >= 1.0f) // allpass coefficient >= 1.0 makes filter unstable
+    {
+        coeff = 0.999999f;
+    }
+    
+    pzf->b0 = coeff;
+    pzf->b1 = 1.0f;
+    pzf->a0 = 1.0f;
+    pzf->a1 = coeff;
+}
+
+void    tPoleZero_setBlockZero(tPoleZero* const pzf, float thePole)
+{
+    if (thePole >= 1.0f) // allpass coefficient >= 1.0 makes filter unstable
+    {
+        thePole = 0.999999f;
+    }
+    
+    pzf->b0 = 1.0f;
+    pzf->b1 = -1.0f;
+    pzf->a0 = 1.0f;
+    pzf->a1 = -thePole;
+}
+
+void    tPoleZero_setGain(tPoleZero* const pzf, float gain)
+{
+    pzf->gain = gain;
+}
+
+float   tPoleZero_tick(tPoleZero* const pzf, float input)
+{
+    float in = input * pzf->gain;
+    float out = (pzf->b0 * in) + (pzf->b1 * pzf->lastIn) - (pzf->a1 * pzf->lastOut);
+    
+    pzf->lastIn = in;
+    pzf->lastOut = out;
+    
+    return out;
+}
+
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ BiQuad Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
+void    tBiQuad_init(tBiQuad* const f)
+{
+    f->gain = 1.0f;
+    
+    f->b0 = 0.0f;
+    f->a0 = 0.0f;
+    
+    f->lastIn[0] = 0.0f;
+    f->lastIn[1] = 0.0f;
+    f->lastOut[0] = 0.0f;
+    f->lastOut[1] = 0.0f;
+}
+
+void    tBiQuad_free(tBiQuad* const f)
+{
+    
+}
+
+float   tBiQuad_tick(tBiQuad* const f, float input)
+{
+    float in = input * f->gain;
+    float out = f->b0 * in + f->b1 * f->lastIn[0] + f->b2 * f->lastIn[1];
+    out -= f->a2 * f->lastOut[1] + f->a1 * f->lastOut[0];
+    
+    f->lastIn[1] = f->lastIn[0];
+    f->lastIn[0] = in;
+    
+    f->lastOut[1] = f->lastOut[0];
+    f->lastOut[0] = out;
+    
+    return out;
+}
+
+void    tBiQuad_setResonance(tBiQuad* const f, float freq, float radius, oBool normalize)
+{
+    // Should also deal with frequency being > half sample rate / nyquist. See STK
+    if (freq < 0.0f)    freq = 0.0f;
+    if (radius < 0.0f)  radius = 0.0f;
+    if (radius >= 1.0f)  radius = 1.0f;
+    
+    f->frequency = freq;
+    f->radius = radius;
+    f->normalize = normalize;
+    
+    f->a2 = radius * radius;
+    f->a1 = -2.0f * radius * cosf(TWO_PI * freq * leaf.invSampleRate);
+    
+    if (normalize)
+    {
+        f->b0 = 0.5f - 0.5f * f->a2;
+        f->b1 = 0.0f;
+        f->b2 = -f->b0;
+    }
+}
+
+void    tBiQuad_setNotch(tBiQuad* const f, float freq, float radius)
+{
+    // Should also deal with frequency being > half sample rate / nyquist. See STK
+    if (freq < 0.0f)    freq = 0.0f;
+    if (radius < 0.0f)  radius = 0.0f;
+    
+    f->b2 = radius * radius;
+    f->b1 = -2.0f * radius * cosf(TWO_PI * freq * leaf.invSampleRate); // OPTIMIZE with LOOKUP or APPROXIMATION
+    
+    // Does not attempt to normalize filter gain.
+}
+
+void tBiQuad_setEqualGainZeros(tBiQuad* const f)
+{
+    f->b0 = 1.0f;
+    f->b1 = 0.0f;
+    f->b2 = -1.0f;
+}
+
+void    tBiQuad_setB0(tBiQuad* const f, float b0)
+{
+    f->b0 = b0;
+}
+
+void    tBiQuad_setB1(tBiQuad* const f, float b1)
+{
+    f->b1 = b1;
+}
+
+void    tBiQuad_setB2(tBiQuad* const f, float b2)
+{
+    f->b2 = b2;
+}
+
+void    tBiQuad_setA1(tBiQuad* const f, float a1)
+{
+    f->a1 = a1;
+}
+
+void    tBiQuad_setA2(tBiQuad* const f, float a2)
+{
+    f->a2 = a2;
+}
+
+void    tBiQuad_setCoefficients(tBiQuad* const f, float b0, float b1, float b2, float a1, float a2)
+{
+    f->b0 = b0;
+    f->b1 = b1;
+    f->b2 = b2;
+    f->a1 = a1;
+    f->a2 = a2;
+}
+
+void    tBiQuad_setGain(tBiQuad* const f, float gain)
+{
+    f->gain = gain;
+}
+
+void    tBiQuadSampleRateChanged(tBiQuad* const f)
+{
+    f->a2 = f->radius * f->radius;
+    f->a1 = -2.0f * f->radius * cosf(TWO_PI * f->frequency * leaf.invSampleRate);
+    
+    if (f->normalize)
+    {
+        f->b0 = 0.5f - 0.5f * f->a2;
+        f->b1 = 0.0f;
+        f->b2 = -f->b0;
+    }
+}
+
+/* Highpass */
+void    tHighpass_init(tHighpass* const f, float freq)
+{
+    f->R = (1.0f-((freq * 2.0f * 3.14f)* leaf.invSampleRate));
+    f->ys = 0.0f;
+    f->xs = 0.0f;
+    
+    f->frequency = freq;
+}
+
+void    tHighpass_free(tHighpass* const f)
+{
+    
+}
+
+void     tHighpass_setFreq(tHighpass* const f, float freq)
+{
+    f->frequency = freq;
+    f->R = (1.0f-((freq * 2.0f * 3.14f) * leaf.invSampleRate));
+    
+}
+
+float     tHighpass_getFreq(tHighpass* const f)
+{
+    return f->frequency;
+}
+
+// From JOS DC Blocker
+float   tHighpass_tick(tHighpass* const f, float x)
+{
+    f->ys = x - f->xs + f->R * f->ys;
+    f->xs = x;
+    return f->ys;
+}
+
+void tHighpassSampleRateChanged(tHighpass* const f)
+{
+    f->R = (1.0f-((f->frequency * 2.0f * 3.14f) * leaf.invSampleRate));
+}
+
+float   tSVF_tick(tSVF* const svf, float v0)
+{
+    float v1,v2,v3;
+    v3 = v0 - svf->ic2eq;
+    v1 = (svf->a1 * svf->ic1eq) + (svf->a2 * v3);
+    v2 = svf->ic2eq + (svf->a2 * svf->ic1eq) + (svf->a3 * v3);
+    svf->ic1eq = (2.0f * v1) - svf->ic1eq;
+    svf->ic2eq = (2.0f * v2) - svf->ic2eq;
+    
+    if (svf->type == SVFTypeLowpass)        return v2;
+    else if (svf->type == SVFTypeBandpass)  return v1;
+    else if (svf->type == SVFTypeHighpass)  return v0 - (svf->k * v1) - v2;
+    else if (svf->type == SVFTypeNotch)     return v0 - (svf->k * v1);
+    else if (svf->type == SVFTypePeak)      return v0 - (svf->k * v1) - (2.0f * v2);
+    else                                    return 0.0f;
+    
+}
+
+// Less efficient, more accurate version of SVF, in which cutoff frequency is taken as floating point Hz value and tanh
+// is calculated when frequency changes.
+void tSVF_init(tSVF* const svf, SVFType type, float freq, float Q)
+{
+    svf->type = type;
+    
+    svf->ic1eq = 0;
+    svf->ic2eq = 0;
+    
+    float a1,a2,a3,g,k;
+    g = tanf(PI * freq * leaf.invSampleRate);
+    k = 1.0f/Q;
+    a1 = 1.0f/(1.0f+g*(g+k));
+    a2 = g*a1;
+    a3 = g*a2;
+    
+    svf->g = g;
+    svf->k = k;
+    svf->a1 = a1;
+    svf->a2 = a2;
+    svf->a3 = a3;
+}
+
+void tSVF_free(tSVF* const svf)
+{
+    
+}
+
+int     tSVF_setFreq(tSVF* const svf, float freq)
+{
+    svf->g = tanf(PI * freq * leaf.invSampleRate);
+    svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
+    svf->a2 = svf->g * svf->a1;
+    svf->a3 = svf->g * svf->a2;
+    
+    return 0;
+}
+
+int     tSVF_setQ(tSVF* const svf, float Q)
+{
+    svf->k = 1.0f/Q;
+    svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
+    svf->a2 = svf->g * svf->a1;
+    svf->a3 = svf->g * svf->a2;
+    
+    return 0;
+}
+
+// Efficient version of tSVF where frequency is set based on 12-bit integer input for lookup in tanh wavetable.
+void   tEfficientSVF_init(tEfficientSVF* const svf, SVFType type, uint16_t input, float Q)
+{
+    svf->type = type;
+    
+    svf->ic1eq = 0;
+    svf->ic2eq = 0;
+    
+    float a1,a2,a3,g,k;
+    g = filtertan[input];
+    k = 1.0f/Q;
+    a1 = 1.0f/(1.0f+g*(g+k));
+    a2 = g*a1;
+    a3 = g*a2;
+    
+    svf->g = g;
+    svf->k = k;
+    svf->a1 = a1;
+    svf->a2 = a2;
+    svf->a3 = a3;
+}
+
+void tEfficientSVF_free(tEfficientSVF* const svf)
+{
+    
+}
+
+float   tEfficientSVF_tick(tEfficientSVF* const svf, float v0)
+{
+    float v1,v2,v3;
+    v3 = v0 - svf->ic2eq;
+    v1 = (svf->a1 * svf->ic1eq) + (svf->a2 * v3);
+    v2 = svf->ic2eq + (svf->a2 * svf->ic1eq) + (svf->a3 * v3);
+    svf->ic1eq = (2.0f * v1) - svf->ic1eq;
+    svf->ic2eq = (2.0f * v2) - svf->ic2eq;
+    
+    if (svf->type == SVFTypeLowpass)        return v2;
+    else if (svf->type == SVFTypeBandpass)  return v1;
+    else if (svf->type == SVFTypeHighpass)  return v0 - (svf->k * v1) - v2;
+    else if (svf->type == SVFTypeNotch)     return v0 - (svf->k * v1);
+    else if (svf->type == SVFTypePeak)      return v0 - (svf->k * v1) - (2.0f * v2);
+    else                                    return 0.0f;
+    
+}
+
+int     tEfficientSVF_setFreq(tEfficientSVF* const svf, uint16_t input)
+{
+    svf->g = filtertan[input];
+    svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
+    svf->a2 = svf->g * svf->a1;
+    svf->a3 = svf->g * svf->a2;
+    
+    return 0;
+}
+
+int     tEfficientSVF_setQ(tEfficientSVF* const svf, float Q)
+{
+    svf->k = 1.0f/Q;
+    svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
+    svf->a2 = svf->g * svf->a1;
+    svf->a3 = svf->g * svf->a2;
+    
+    return 0;
+}
+
+void	tFIR_init(tFIR* const fir, float* coeffs, int numTaps){
+    fir->numTaps = numTaps;
+    fir->coeff = coeffs;
+    fir->past = (float*)leaf_alloc(sizeof(float) * fir->numTaps);
+    for (int i = 0; i < fir->numTaps; ++i) fir->past[i] = 0.0f;
+}
+
+float	tFIR_tick(tFIR* const fir, float input){
+	fir->past[0] = input;
+	float y = 0.0f;
+	for (int i = 0; i < fir->numTaps; ++i) y += fir->past[i]*fir->coeff[i];
+	for (int i = fir->numTaps-1; i > 0; --i) fir->past[i] = fir->past[i-1];
+	return y;
+}
+
+void	tFIR_free(tFIR* const fir)
+{
+    leaf_free(fir->past);
+}
--- a/LEAF/Src/leaf-formant.c
+++ /dev/null
@@ -1,206 +1,0 @@
-/*==============================================================================
-
-    leaf-formant.c
-    Created: 30 Nov 2018 11:03:30am
-    Author:  airship
-
-==============================================================================*/
-
-#if _WIN32 || _WIN64
-
-#include "..\Inc\leaf-formant.h"
-#else
-
-#include "../Inc/leaf-formant.h"
-
-#endif
-
-
-void tFormantShifter_init(tFormantShifter* const fs, int bufsize, int order)
-{
-    fs->ford = order;
-    fs->bufsize = bufsize;
-    fs->fk = (float*) leaf_alloc(sizeof(float) * fs->ford);
-    fs->fb = (float*) leaf_alloc(sizeof(float) * fs->ford);
-    fs->fc = (float*) leaf_alloc(sizeof(float) * fs->ford);
-    fs->frb = (float*) leaf_alloc(sizeof(float) * fs->ford);
-    fs->frc = (float*) leaf_alloc(sizeof(float) * fs->ford);
-    fs->fsig = (float*) leaf_alloc(sizeof(float) * fs->ford);
-    fs->fsmooth = (float*) leaf_alloc(sizeof(float) * fs->ford);
-    fs->ftvec = (float*) leaf_alloc(sizeof(float) * fs->ford);
-    
-    fs->fbuff = (float**) leaf_alloc(sizeof(float*) * fs->ford);
-    for (int i = 0; i < fs->ford; i++)
-    {
-        fs->fbuff[i] = (float*) leaf_alloc(sizeof(float) * fs->bufsize);
-    }
-    
-    
-    fs->falph = powf(0.001f, 80.0f / (leaf.sampleRate));
-    fs->flamb = -(0.8517f*sqrt(atanf(0.06583f*leaf.sampleRate))-0.1916f);
-    fs->fhp = 0.0f;
-    fs->flp = 0.0f;
-    fs->flpa = powf(0.001f, 10.0f / (leaf.sampleRate));
-    fs->fmute = 1.0f;
-    fs->fmutealph = powf(0.001f, 1.0f / (leaf.sampleRate));
-    fs->cbi = 0;
-}
-
-void tFormantShifter_free(tFormantShifter* const fs)
-{
-    leaf_free(fs->fk);
-    leaf_free(fs->fb);
-    leaf_free(fs->fc);
-    leaf_free(fs->frb);
-    leaf_free(fs->frc);
-    leaf_free(fs->fsig);
-    leaf_free(fs->fsmooth);
-    leaf_free(fs->ftvec);
-    for (int i = 0; i < fs->ford; i++)
-    {
-        leaf_free(fs->fbuff[i]);
-    }
-    leaf_free(fs->fbuff);
-}
-
-
-float tFormantShifter_tick(tFormantShifter* fs, float in, float fwarp)
-{
-    return tFormantShifter_add(fs, tFormantShifter_remove(fs, in), fwarp);
-}
-
-float tFormantShifter_remove(tFormantShifter* fs, float in)
-{
-    float fa, fb, fc, foma, falph, ford, flpa, flamb, tf, fk;
-    int ti4;
-    ford = fs->ford;
-    falph = fs->falph;
-    foma = (1.0f - falph);
-    flpa = fs->flpa;
-    flamb = fs->flamb;
-    
-    tf = in;
-    ti4 = fs->cbi;
-    
-    fa = tf - fs->fhp;
-    fs->fhp = tf;
-    fb = fa;
-    for(int i = 0; i < ford; i++)
-    {
-        fs->fsig[i] = fa*fa*foma + fs->fsig[i]*falph;
-        fc = (fb - fs->fc[i])*flamb + fs->fb[i];
-        fs->fc[i] = fc;
-        fs->fb[i] = fb;
-        fk = fa*fc*foma + fs->fk[i]*falph;
-        fs->fk[i] = fk;
-        tf = fk/(fs->fsig[i] + 0.000001f);
-        tf = tf*foma + fs->fsmooth[i]*falph;
-        fs->fsmooth[i] = tf;
-        fs->fbuff[i][ti4] = tf;
-        fb = fc - tf*fa;
-        fa = fa - tf*fc;
-    }
-    fs->cbi++;
-    if(fs->cbi >= fs->bufsize)
-    {
-        fs->cbi = 0;
-    }
-    
-    return fa;
-}
-
-float tFormantShifter_add(tFormantShifter* fs, float in, float fwarp)
-{
-    float fa, fb, fc, foma, falph, ford, flpa, flamb, tf, tf2, f0resp, f1resp, frlamb;
-    int ti4;
-    ford = fs->ford;
-    falph = fs->falph;
-    foma = (1.0f - falph);
-    flpa = fs->flpa;
-    flamb = fs->flamb;
-    tf = exp2(fwarp/2.0f) * (1+flamb)/(1-flamb);
-    frlamb = (tf-1)/(tf+1);
-    ti4 = fs->cbi;
-    
-    tf2 = in;
-    fa = 0;
-    fb = fa;
-    for (int i=0; i<ford; i++)
-    {
-        fc = (fb-fs->frc[i])*frlamb + fs->frb[i];
-        tf = fs->fbuff[i][ti4];
-        fb = fc - tf*fa;
-        fs->ftvec[i] = tf*fc;
-        fa = fa - fs->ftvec[i];
-    }
-    tf = -fa;
-    for (int i=ford-1; i>=0; i--)
-    {
-        tf = tf + fs->ftvec[i];
-    }
-    f0resp = tf;
-    
-    //  second time: compute 1-response
-    fa = 1;
-    fb = fa;
-    for (int i=0; i<ford; i++)
-    {
-        fc = (fb-fs->frc[i])*frlamb + fs->frb[i];
-        tf = fs->fbuff[i][ti4];
-        fb = fc - tf*fa;
-        fs->ftvec[i] = tf*fc;
-        fa = fa - fs->ftvec[i];
-    }
-    tf = -fa;
-    for (int i=ford-1; i>=0; i--)
-    {
-        tf = tf + fs->ftvec[i];
-    }
-    f1resp = tf;
-    
-    //  now solve equations for output, based on 0-response and 1-response
-    tf = (float)2*tf2;
-    tf2 = tf;
-    tf = ((float)1 - f1resp + f0resp);
-    if (tf!=0)
-    {
-        tf2 = (tf2 + f0resp) / tf;
-    }
-    else
-    {
-        tf2 = 0;
-    }
-    
-    //  third time: update delay registers
-    fa = tf2;
-    fb = fa;
-    for (int i=0; i<ford; i++)
-    {
-        fc = (fb-fs->frc[i])*frlamb + fs->frb[i];
-        fs->frc[i] = fc;
-        fs->frb[i] = fb;
-        tf = fs->fbuff[i][ti4];
-        fb = fc - tf*fa;
-        fa = fa - tf*fc;
-    }
-    tf = tf2;
-    tf = tf + flpa * fs->flp;  // lowpass post-emphasis filter
-    fs->flp = tf;
-    
-    // Bring up the gain slowly when formant correction goes from disabled
-    // to enabled, while things stabilize.
-    if (fs->fmute>0.5)
-    {
-        tf = tf*(fs->fmute - 0.5)*2;
-    }
-    else
-    {
-        tf = 0;
-    }
-    tf2 = fs->fmutealph;
-    fs->fmute = (1-tf2) + tf2*fs->fmute;
-    // now tf is signal output
-    // ...and we're done messing with formants
-    
-    return tf;
-}
--- /dev/null
+++ b/LEAF/Src/leaf-instruments.c
@@ -1,0 +1,460 @@
+/*==============================================================================
+
+    leaf-instruments.c
+    Created: 30 Nov 2018 10:24:21am
+    Author:  airship
+
+==============================================================================*/
+
+#if _WIN32 || _WIN64
+
+#include "..\Inc\leaf-instruments.h"
+
+#else
+
+#include "../Inc/leaf-instruments.h"
+
+#endif
+
+// ----------------- COWBELL ----------------------------//
+
+void t808Cowbell_init(t808Cowbell* const cowbell, int useStick) {
+    
+    tSquare_init(&cowbell->p[0]);
+    tSquare_setFreq(&cowbell->p[0], 540.0f);
+    
+    tSquare_init(&cowbell->p[1]);
+    tSquare_setFreq(&cowbell->p[1], 1.48148f * 540.0f);
+    
+    cowbell->oscMix = 0.5f;
+    
+    tSVF_init(&cowbell->bandpassOsc, SVFTypeBandpass, 2500, 1.0f);
+    
+    tSVF_init(&cowbell->bandpassStick, SVFTypeBandpass, 1800, 1.0f);
+    
+    tEnvelope_init(&cowbell->envGain, 5.0f, 100.0f, OFALSE);
+    
+    tEnvelope_init(&cowbell->envFilter, 5.0, 100.0f, OFALSE);
+    
+    tHighpass_init(&cowbell->highpass, 1000.0f);
+    
+    tNoise_init(&cowbell->stick, WhiteNoise);
+    
+    tEnvelope_init(&cowbell->envStick, 5.0f, 5.0f, 0);
+    
+    cowbell->useStick = useStick;
+}
+
+void t808Cowebell_free(t808Cowbell* const cowbell)
+{
+    tSquare_free(&cowbell->p[0]);
+    tSquare_free(&cowbell->p[1]);
+    tSVF_free(&cowbell->bandpassOsc);
+    tSVF_free(&cowbell->bandpassStick);
+    tEnvelope_free(&cowbell->envGain);
+    tEnvelope_free(&cowbell->envFilter);
+    tHighpass_free(&cowbell->highpass);
+    tNoise_free(&cowbell->stick);
+    tEnvelope_free(&cowbell->envStick);
+}
+
+void t808Cowbell_on(t808Cowbell* const cowbell, float vel)
+{
+    tEnvelope_on(&cowbell->envGain, vel);
+    
+    if (cowbell->useStick)
+        tEnvelope_on(&cowbell->envStick,vel);
+}
+
+float t808Cowbell_tick(t808Cowbell* const cowbell) {
+    
+    float sample = 0.0f;
+    
+    // Mix oscillators.
+    sample = (cowbell->oscMix * tSquare_tick(&cowbell->p[0])) + ((1.0f-cowbell->oscMix) * tSquare_tick(&cowbell->p[1]));
+    
+    // Filter dive and filter.
+    tSVF_setFreq(&cowbell->bandpassOsc, cowbell->filterCutoff + 1000.0f * tEnvelope_tick(&cowbell->envFilter));
+    sample = tSVF_tick(&cowbell->bandpassOsc,sample);
+    
+    sample *= (0.9f * tEnvelope_tick(&cowbell->envGain));
+    
+    if (cowbell->useStick)
+        sample += (0.1f * tEnvelope_tick(&cowbell->envStick) * tSVF_tick(&cowbell->bandpassStick, tNoise_tick(&cowbell->stick)));
+
+    
+    sample = tHighpass_tick(&cowbell->highpass, sample);
+    
+    return sample;
+}
+
+void t808Cowbell_setDecay(t808Cowbell* const cowbell, float decay)
+{
+    tEnvelope_setDecay(&cowbell->envGain,decay);
+}
+
+void t808Cowbell_setHighpassFreq(t808Cowbell *cowbell, float freq)
+{
+    tHighpass_setFreq(&cowbell->highpass,freq);
+}
+
+void t808Cowbell_setBandpassFreq(t808Cowbell* const cowbell, float freq)
+{
+    cowbell->filterCutoff = freq;
+}
+
+void t808Cowbell_setFreq(t808Cowbell* const cowbell, float freq)
+{
+    
+    tSquare_setFreq(&cowbell->p[0],freq);
+    tSquare_setFreq(&cowbell->p[1],1.48148f*freq);
+}
+
+void t808Cowbell_setOscMix(t808Cowbell* const cowbell, float oscMix)
+{
+    cowbell->oscMix = oscMix;
+}
+
+void t808Cowbell_setStick(t808Cowbell* const cowbell, int useStick)
+{
+    cowbell->useStick = useStick;
+}
+
+// ----------------- HIHAT ----------------------------//
+
+void t808Hihat_init(t808Hihat* const hihat)
+{
+    for (int i = 0; i < 6; i++)
+    {
+        tSquare_init(&hihat->p[i]);
+    }
+    
+    tNoise_init(&hihat->stick, PinkNoise);
+    tNoise_init(&hihat->n, WhiteNoise);
+    
+    // need to fix SVF to be generic
+    tSVF_init(&hihat->bandpassStick, SVFTypeBandpass,2500.0f,1.2f);
+    tSVF_init(&hihat->bandpassOsc, SVFTypeBandpass,3500.0f,0.3f);
+    
+    tEnvelope_init(&hihat->envGain, 0.0f, 50.0f, OFALSE);
+    tEnvelope_init(&hihat->envStick, 0.0f, 7.0f, OFALSE);
+    
+    
+    tHighpass_init(&hihat->highpass, 7000.0f);
+    
+    hihat->freq = 40.0f;
+    hihat->stretch = 0.0f;
+    
+    tSquare_setFreq(&hihat->p[0], 2.0f * hihat->freq);
+    tSquare_setFreq(&hihat->p[1], 3.00f * hihat->freq);
+    tSquare_setFreq(&hihat->p[2], 4.16f * hihat->freq);
+    tSquare_setFreq(&hihat->p[3], 5.43f * hihat->freq);
+    tSquare_setFreq(&hihat->p[4], 6.79f * hihat->freq);
+    tSquare_setFreq(&hihat->p[5], 8.21f * hihat->freq);
+}
+
+void t808Hihat_free(t808Hihat* const hihat)
+{
+    for (int i = 0; i < 6; i++)
+    {
+        tSquare_free(&hihat->p[i]);
+    }
+    
+    tNoise_free(&hihat->stick);
+    tNoise_free(&hihat->n);
+    
+    // need to fix SVF to be generic
+    tSVF_free(&hihat->bandpassStick);
+    tSVF_free(&hihat->bandpassOsc);
+    tEnvelope_free(&hihat->envGain);
+    tEnvelope_free(&hihat->envStick);
+    
+    tHighpass_free(&hihat->highpass);
+}
+
+void t808Hihat_on(t808Hihat* const hihat, float vel) {
+    
+    tEnvelope_on(&hihat->envGain, vel);
+    tEnvelope_on(&hihat->envStick, vel);
+    
+}
+
+void t808Hihat_setOscNoiseMix(t808Hihat* const hihat, float oscNoiseMix) {
+    
+    hihat->oscNoiseMix = oscNoiseMix;
+    
+}
+
+float t808Hihat_tick(t808Hihat* const hihat) {
+    
+    float sample = 0.0f;
+    float gainScale = 0.1666f;
+    
+
+    float myNoise = tNoise_tick(&hihat->n);
+
+	tSquare_setFreq(&hihat->p[0], ((2.0f + hihat->stretch) * hihat->freq));
+	tSquare_setFreq(&hihat->p[1], ((3.00f + hihat->stretch) * hihat->freq));
+	tSquare_setFreq(&hihat->p[2], ((4.16f + hihat->stretch) * hihat->freq));
+	tSquare_setFreq(&hihat->p[3], ((5.43f + hihat->stretch) * hihat->freq));
+	tSquare_setFreq(&hihat->p[4], ((6.79f + hihat->stretch) * hihat->freq));
+	tSquare_setFreq(&hihat->p[5], ((8.21f + hihat->stretch) * hihat->freq));
+
+    for (int i = 0; i < 6; i++)
+    {
+        sample += tSquare_tick(&hihat->p[i]);
+    }
+    
+    sample *= gainScale;
+    
+    sample = (hihat->oscNoiseMix * sample) + ((1.0f-hihat->oscNoiseMix) * myNoise);
+    
+    sample = tSVF_tick(&hihat->bandpassOsc, sample);
+    
+    float myGain = tEnvelope_tick(&hihat->envGain);
+    sample *= (myGain*myGain);//square the output gain envelope
+    sample = tHighpass_tick(&hihat->highpass, sample);
+    sample += ((0.5f * tEnvelope_tick(&hihat->envStick)) * tSVF_tick(&hihat->bandpassStick, tNoise_tick(&hihat->stick)));
+    sample = tanhf(sample * 2.0f);
+
+    return sample;
+}
+
+void t808Hihat_setDecay(t808Hihat* const hihat, float decay)
+{
+    tEnvelope_setDecay(&hihat->envGain,decay);
+}
+
+void t808Hihat_setHighpassFreq(t808Hihat* const hihat, float freq)
+{
+    tHighpass_setFreq(&hihat->highpass,freq);
+}
+
+void t808Hihat_setStretch(t808Hihat* const hihat, float stretch)
+{
+    hihat->stretch = stretch;
+}
+
+void t808Hihat_setFM(t808Hihat* const hihat, float FM_amount)
+{
+    hihat->FM_amount = FM_amount;
+}
+
+void t808Hihat_setOscBandpassFreq(t808Hihat* const hihat, float freq)
+{
+    tSVF_setFreq(&hihat->bandpassOsc,freq);
+}
+
+void t808Hihat_setOscBandpassQ(t808Hihat* const hihat, float Q)
+{
+    tSVF_setQ(&hihat->bandpassOsc,Q);
+}
+
+void t808Hihat_setStickBandPassFreq(t808Hihat* const hihat, float freq)
+{
+    tSVF_setFreq(&hihat->bandpassStick,freq);
+}
+
+void t808Hihat_setStickBandPassQ(t808Hihat* const hihat, float Q)
+{
+    tSVF_setQ(&hihat->bandpassStick,Q);
+}
+
+
+
+void t808Hihat_setOscFreq(t808Hihat* const hihat, float freq)
+{
+		hihat->freq = freq;
+}
+
+// ----------------- SNARE ----------------------------//
+
+void t808Snare_init(t808Snare* const snare)
+{
+    float ratio[2] = {1.0, 1.5};
+    for (int i = 0; i < 2; i++)
+    {
+        tTriangle_init(&snare->tone[i]);
+        
+        tTriangle_setFreq(&snare->tone[i], ratio[i] * 400.0f);
+        tSVF_init(&snare->toneLowpass[i], SVFTypeLowpass, 4000, 1.0f);
+        tEnvelope_init(&snare->toneEnvOsc[i], 0.0f, 50.0f, OFALSE);
+        tEnvelope_init(&snare->toneEnvGain[i], 1.0f, 150.0f, OFALSE);
+        tEnvelope_init(&snare->toneEnvFilter[i], 1.0f, 2000.0f, OFALSE);
+        
+        snare->toneGain[i] = 0.5f;
+    }
+    
+    snare->tone1Freq = ratio[0] * 100.0f;
+    snare->tone2Freq = ratio[1] * 100.0f;
+    snare->noiseFilterFreq = 3000.0f;
+    tNoise_init(&snare->noiseOsc, WhiteNoise);
+    tSVF_init(&snare->noiseLowpass, SVFTypeLowpass, 12000.0f, 0.8f);
+    tEnvelope_init(&snare->noiseEnvGain, 0.0f, 100.0f, OFALSE);
+    tEnvelope_init(&snare->noiseEnvFilter, 0.0f, 1000.0f, OFALSE);
+    snare->noiseGain = 1.0f;
+}
+
+void        t808Snare_free                  (t808Snare* const snare)
+{
+    for (int i = 0; i < 2; i++)
+    {
+        tTriangle_free(&snare->tone[i]);
+        tSVF_free(&snare->toneLowpass[i]);
+        tEnvelope_free(&snare->toneEnvOsc[i]);
+        tEnvelope_free(&snare->toneEnvGain[i]);
+        tEnvelope_free(&snare->toneEnvFilter[i]);
+    }
+    
+    
+    tNoise_free(&snare->noiseOsc);
+    tSVF_free(&snare->noiseLowpass);
+    tEnvelope_free(&snare->noiseEnvGain);
+    tEnvelope_free(&snare->noiseEnvFilter);
+}
+
+void t808Snare_on(t808Snare* const snare, float vel)
+{
+    for (int i = 0; i < 2; i++)
+    {
+        tEnvelope_on(&snare->toneEnvOsc[i], vel);
+        tEnvelope_on(&snare->toneEnvGain[i], vel);
+        tEnvelope_on(&snare->toneEnvFilter[i], vel);
+    }
+    
+    tEnvelope_on(&snare->noiseEnvGain, vel);
+    tEnvelope_on(&snare->noiseEnvFilter, vel);
+}
+
+void t808Snare_setTone1Freq(t808Snare* const snare, float freq)
+{
+    snare->tone1Freq = freq;
+    tTriangle_setFreq(&snare->tone[0], freq);
+    
+}
+
+void t808Snare_setTone2Freq(t808Snare* const snare, float freq)
+{
+    snare->tone2Freq = freq;
+    tTriangle_setFreq(&snare->tone[1],freq);
+}
+
+void t808Snare_setTone1Decay(t808Snare* const snare, float decay)
+{
+    tEnvelope_setDecay(&snare->toneEnvGain[0],decay);
+}
+
+void t808Snare_setTone2Decay(t808Snare* const snare, float decay)
+{
+    tEnvelope_setDecay(&snare->toneEnvGain[1],decay);
+}
+
+void t808Snare_setNoiseDecay(t808Snare* const snare, float decay)
+{
+    tEnvelope_setDecay(&snare->noiseEnvGain,decay);
+}
+
+void t808Snare_setToneNoiseMix(t808Snare* const snare, float toneNoiseMix)
+{
+    snare->toneNoiseMix = toneNoiseMix;
+}
+
+void t808Snare_setNoiseFilterFreq(t808Snare* const snare, float noiseFilterFreq)
+{
+    snare->noiseFilterFreq = noiseFilterFreq;
+}
+
+void t808Snare_setNoiseFilterQ(t808Snare* const snare, float noiseFilterQ)
+{
+    tSVF_setQ(&snare->noiseLowpass, noiseFilterQ);
+}
+
+static float tone[2];
+
+float t808Snare_tick(t808Snare* const snare)
+{
+    for (int i = 0; i < 2; i++)
+    {
+        tTriangle_setFreq(&snare->tone[i], snare->tone1Freq + (20.0f * tEnvelope_tick(&snare->toneEnvOsc[i])));
+        tone[i] = tTriangle_tick(&snare->tone[i]);
+        
+        tSVF_setFreq(&snare->toneLowpass[i], 2000.0f + (500.0f * tEnvelope_tick(&snare->toneEnvFilter[i])));
+        tone[i] = tSVF_tick(&snare->toneLowpass[i], tone[i]) * tEnvelope_tick(&snare->toneEnvGain[i]);
+    }
+    
+    float noise = tNoise_tick(&snare->noiseOsc);
+    tSVF_setFreq(&snare->noiseLowpass, snare->noiseFilterFreq + (1000.0f * tEnvelope_tick(&snare->noiseEnvFilter)));
+    noise = tSVF_tick(&snare->noiseLowpass, noise) * tEnvelope_tick(&snare->noiseEnvGain);
+    
+    float sample = (snare->toneNoiseMix)*(tone[0] * snare->toneGain[0] + tone[1] * snare->toneGain[1]) + (1.0f-snare->toneNoiseMix) * (noise * snare->noiseGain);
+    sample = tanhf(sample * 2.0f);
+    return sample;
+}
+
+// ----------------- KICK ----------------------------//
+
+void        t808Kick_init        			(t808Kick* const kick)
+{
+	tCycle_init(&kick->tone);
+	kick->toneInitialFreq = 40.0f;
+	kick->sighAmountInHz = 7.0f;
+	kick->chirpRatioMinusOne = 3.3f;
+	tCycle_setFreq(&kick->tone, 50.0f);
+	tSVF_init(&kick->toneLowpass, SVFTypeLowpass, 2000.0f, 0.5f);
+	tEnvelope_init(&kick->toneEnvOscChirp, 0.0f, 20.0f, OFALSE);
+	tEnvelope_init(&kick->toneEnvOscSigh, 0.0f, 2500.0f, OFALSE);
+	tEnvelope_init(&kick->toneEnvGain, 0.0f, 800.0f, OFALSE);
+	tNoise_init(&kick->noiseOsc, PinkNoise);
+	tEnvelope_init(&kick->noiseEnvGain, 0.0f, 1.0f, OFALSE);
+	kick->noiseGain = 0.3f;
+}
+
+void        t808Kick_free                  (t808Kick* const kick)
+{
+	tCycle_free(&kick->tone);
+	tSVF_free(&kick->toneLowpass);
+	tEnvelope_free(&kick->toneEnvOscChirp);
+	tEnvelope_free(&kick->toneEnvOscSigh);
+	tEnvelope_free(&kick->toneEnvGain);
+	tNoise_free(&kick->noiseOsc);
+	tEnvelope_free(&kick->noiseEnvGain);
+}
+
+float       t808Kick_tick                  (t808Kick* const kick)
+{
+	tCycle_setFreq(&kick->tone, (kick->toneInitialFreq * (1.0f + (kick->chirpRatioMinusOne * tEnvelope_tick(&kick->toneEnvOscChirp)))) + (kick->sighAmountInHz * tEnvelope_tick(&kick->toneEnvOscSigh)));
+	float sample = tCycle_tick(&kick->tone) * tEnvelope_tick(&kick->toneEnvGain);
+	sample+= tNoise_tick(&kick->noiseOsc) * tEnvelope_tick(&kick->noiseEnvGain);
+	//add distortion here
+	sample = tSVF_tick(&kick->toneLowpass, sample);
+	return sample;
+}
+
+void        t808Kick_on                    (t808Kick* const kick, float vel)
+{
+	tEnvelope_on(&kick->toneEnvOscChirp, vel);
+	tEnvelope_on(&kick->toneEnvOscSigh, vel);
+	tEnvelope_on(&kick->toneEnvGain, vel);
+	tEnvelope_on(&kick->noiseEnvGain, vel);
+
+}
+void        t808Kick_setToneFreq          (t808Kick* const kick, float freq)
+{
+	kick->toneInitialFreq = freq;
+
+}
+
+void        t808Kick_setToneDecay         (t808Kick* const kick, float decay)
+{
+	tEnvelope_setDecay(&kick->toneEnvGain,decay);
+	tEnvelope_setDecay(&kick->toneEnvGain,decay * 3.0f);
+}
+
+void        t808Kick_setNoiseDecay         (t808Kick* const kick, float decay);
+void        t808Kick_setSighAmount         (t808Kick* const kick, float sigh);
+void        t808Kick_setChirpAmount         (t808Kick* const kick, float chirp);
+void        t808Kick_setToneNoiseMix       (t808Kick* const kick, float toneNoiseMix);
+void        t808Kick_setNoiseFilterFreq    (t808Kick* const kick, float noiseFilterFreq);
+void        t808Kick_setNoiseFilterQ       (t808Kick* const kick, float noiseFilterQ);
+
+
--- a/LEAF/Src/leaf-math.c
+++ b/LEAF/Src/leaf-math.c
@@ -355,3 +355,5 @@
 
     return out;
 }
+
+
--- a/LEAF/Src/leaf-midi.c
+++ b/LEAF/Src/leaf-midi.c
@@ -305,3 +305,216 @@
     return (poly->voices[voice][0] > 0) ? 1 : 0;
 }
 
+
+//====================================================================================
+/* Stack */
+//====================================================================================
+
+void tStack_init(tStack* const ns)
+{
+    ns->ordered = OFALSE;
+    ns->size = 0;
+    ns->pos = 0;
+    ns->capacity = STACK_SIZE;
+    
+    for (int i = 0; i < STACK_SIZE; i++) ns->data[i] = -1;
+}
+
+void tStack_free(tStack* const ns)
+{
+    
+}
+
+// If stack contains note, returns index. Else returns -1;
+int tStack_contains(tStack* const ns, uint16_t noteVal)
+{
+    for (int i = 0; i < ns->size; i++)
+    {
+        if (ns->data[i] == noteVal)    return i;
+    }
+    return -1;
+}
+
+void tStack_add(tStack* const ns, uint16_t noteVal)
+{
+    uint8_t j;
+    
+    int whereToInsert = 0;
+    if (ns->ordered)
+    {
+        for (j = 0; j < ns->size; j++)
+        {
+            if (noteVal > ns->data[j])
+            {
+                if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1))
+                {
+                    whereToInsert = j+1;
+                    break;
+                }
+            }
+        }
+    }
+    
+    //first move notes that are already in the stack one position to the right
+    for (j = ns->size; j > whereToInsert; j--)
+    {
+        ns->data[j] = ns->data[(j - 1)];
+    }
+    
+    //then, insert the new note into the front of the stack
+    ns->data[whereToInsert] = noteVal;
+    
+    ns->size++;
+}
+
+int tStack_addIfNotAlreadyThere(tStack* const ns, uint16_t noteVal)
+{
+    uint8_t j;
+    
+    int added = 0;
+    
+    if (tStack_contains(ns, noteVal) == -1)
+    {
+        int whereToInsert = 0;
+        if (ns->ordered)
+        {
+            for (j = 0; j < ns->size; j++)
+            {
+                if (noteVal > ns->data[j])
+                {
+                    if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1))
+                    {
+                        whereToInsert = j+1;
+                        break;
+                    }
+                }
+            }
+        }
+        
+        //first move notes that are already in the stack one position to the right
+        for (j = ns->size; j > whereToInsert; j--)
+        {
+            ns->data[j] = ns->data[(j - 1)];
+        }
+        
+        //then, insert the new note into the front of the stack
+        ns->data[whereToInsert] = noteVal;
+        
+        ns->size++;
+        
+        added = 1;
+    }
+    
+    return added;
+}
+
+
+// Remove noteVal. return 1 if removed, 0 if not
+int tStack_remove(tStack* const ns, uint16_t noteVal)
+{
+    uint8_t k;
+    int foundIndex = tStack_contains(ns, noteVal);
+    int removed = 0;
+    
+    if (foundIndex >= 0)
+    {
+        for (k = 0; k < (ns->size - foundIndex); k++)
+        {
+            if ((k+foundIndex) >= (ns->capacity - 1))
+            {
+                ns->data[k + foundIndex] = -1;
+            }
+            else
+            {
+                ns->data[k + foundIndex] = ns->data[k + foundIndex + 1];
+                if ((k + foundIndex) == (ns->size - 1))
+                {
+                    ns->data[k + foundIndex + 1] = -1;
+                }
+            }
+            
+        }
+        // in case it got put on the stack multiple times
+        foundIndex--;
+        ns->size--;
+        removed = 1;
+    }
+    
+    
+    
+    return removed;
+}
+
+// Doesn't change size of data types
+void tStack_setCapacity(tStack* const ns, uint16_t cap)
+{
+    if (cap <= 0)
+        ns->capacity = 1;
+    else if (cap <= STACK_SIZE)
+        ns->capacity = cap;
+    else
+        ns->capacity = STACK_SIZE;
+    
+    for (int i = cap; i < STACK_SIZE; i++)
+    {
+        if ((int)ns->data[i] != -1)
+        {
+            ns->data[i] = -1;
+            ns->size -= 1;
+        }
+    }
+    
+    if (ns->pos >= cap)
+    {
+        ns->pos = 0;
+    }
+}
+
+int tStack_getSize(tStack* const ns)
+{
+    return ns->size;
+}
+
+void tStack_clear(tStack* const ns)
+{
+    for (int i = 0; i < STACK_SIZE; i++)
+    {
+        ns->data[i] = -1;
+    }
+    ns->pos = 0;
+    ns->size = 0;
+}
+
+// Next item in order of addition to stack. Return 0-31 if there is a next item to move to. Returns -1 otherwise.
+int tStack_next(tStack* const ns)
+{
+    int step = 0;
+    if (ns->size != 0) // if there is at least one note in the stack
+    {
+        if (ns->pos > 0) // if you're not at the most recent note (first one), then go backward in the array (moving from earliest to latest)
+        {
+            ns->pos--;
+        }
+        else
+        {
+            ns->pos = (ns->size - 1); // if you are the most recent note, go back to the earliest note in the array
+        }
+        
+        step = ns->data[ns->pos];
+        return step;
+    }
+    else
+    {
+        return -1;
+    }
+}
+
+int tStack_get(tStack* const ns, int which)
+{
+    return ns->data[which];
+}
+
+int tStack_first(tStack* const ns)
+{
+    return ns->data[0];
+}
--- a/LEAF/Src/leaf-oscillator.c
+++ /dev/null
@@ -1,638 +1,0 @@
-/*==============================================================================
-
-    leaf-oscillator.c
-    Created: 20 Jan 2017 12:00:58pm
-    Author:  Michael R Mulshine
-
-==============================================================================*/
-
-#if _WIN32 || _WIN64
-
-#include "..\Inc\leaf-tables.h"
-#include "..\Inc\leaf-oscillator.h"
-#include "..\leaf.h"
-
-#else
-
-#include "../Inc/leaf-tables.h"
-#include "../Inc/leaf-oscillator.h"
-#include "../leaf.h"
-
-#endif
-
-void     tNeuronSampleRateChanged(tNeuron* n)
-{
-    
-}
-
-void    tNeuron_init(tNeuron* const n)
-{
-    tPoleZero_init(&n->f);
-    
-    tPoleZero_setBlockZero(&n->f, 0.99f);
-    
-    n->timeStep = 1.0f / 50.0f;
-    
-    n->current = 0.0f; // 100.0f for sound
-    n->voltage = 0.0f;
-    
-    n->mode = NeuronNormal;
-    
-    n->P[0] = 0.0f;
-    n->P[1] = 0.0f;
-    n->P[2] = 1.0f;
-    
-    n->V[0] = -12.0f;
-    n->V[1] = 115.0f;
-    n->V[2] = 10.613f;
-    
-    n->gK = 36.0f;
-    n->gN = 120.0f;
-    n->gL = 0.3f;
-    n->C = 1.0f;
-    
-    n->rate[2] = n->gL/n->C;
-}
-
-void    tNeuron_free(tNeuron* const n)
-{
-    tPoleZero_free(&n->f);
-}
-
-void   tNeuron_reset(tNeuron* const n)
-{
-    
-    tPoleZero_setBlockZero(&n->f, 0.99f);
-    
-    n->timeStep = 1.0f / 50.0f;
-    
-    n->current = 0.0f; // 100.0f for sound
-    n->voltage = 0.0f;
-    
-    n->mode = NeuronNormal;
-    
-    n->P[0] = 0.0f;
-    n->P[1] = 0.0f;
-    n->P[2] = 1.0f;
-    
-    n->V[0] = -12.0f;
-    n->V[1] = 115.0f;
-    n->V[2] = 10.613f;
-    
-    n->gK = 36.0f;
-    n->gN = 120.0f;
-    n->gL = 0.3f;
-    n->C = 1.0f;
-    
-    n->rate[2] = n->gL/n->C;
-}
-
-
-void        tNeuron_setV1(tNeuron* const n, float V1)
-{
-    n->V[0] = V1;
-}
-
-
-void        tNeuron_setV2(tNeuron* const n, float V2)
-{
-    n->V[1] = V2;
-}
-
-void        tNeuron_setV3(tNeuron* const n, float V3)
-{
-    n->V[2] = V3;
-}
-
-void        tNeuron_setTimeStep(tNeuron* const n, float timeStep)
-{
-    n->timeStep = timeStep;
-}
-
-void        tNeuron_setK(tNeuron* const n, float K)
-{
-    n->gK = K;
-}
-
-void        tNeuron_setL(tNeuron* const n, float L)
-{
-    n->gL = L;
-    n->rate[2] = n->gL/n->C;
-}
-
-void        tNeuron_setN(tNeuron* const n, float N)
-{
-    n->gN = N;
-}
-
-void        tNeuron_setC(tNeuron* const n, float C)
-{
-    n->C = C;
-    n->rate[2] = n->gL/n->C;
-}
-
-float   tNeuron_tick(tNeuron* const n)
-{
-    float output = 0.0f;
-    float voltage = n->voltage;
-    
-    n->alpha[0] = (0.01f * (10.0f - voltage)) / (expf((10.0f - voltage)/10.0f) - 1.0f);
-    n->alpha[1] = (0.1f * (25.0f-voltage)) / (expf((25.0f-voltage)/10.0f) - 1.0f);
-    n->alpha[2] = (0.07f * expf((-1.0f * voltage)/20.0f));
-    
-    n->beta[0] = (0.125f * expf((-1.0f* voltage)/80.0f));
-    n->beta[1] = (4.0f * expf((-1.0f * voltage)/18.0f));
-    n->beta[2] = (1.0f / (expf((30.0f-voltage)/10.0f) + 1.0f));
-    
-    for (int i = 0; i < 3; i++)
-    {
-        n->P[i] = (n->alpha[i] * n->timeStep) + ((1.0f - ((n->alpha[i] + n->beta[i]) * n->timeStep)) * n->P[i]);
-        
-        if (n->P[i] > 1.0f)         n->P[i] = 0.0f;
-        else if (n->P[i] < -1.0f)   n->P[i] = 0.0f;
-    }
-    // rate[0]= k ; rate[1] = Na ; rate[2] = l
-    n->rate[0] = ((n->gK * powf(n->P[0], 4.0f)) / n->C);
-    n->rate[1] = ((n->gN * powf(n->P[1], 3.0f) * n->P[2]) / n->C);
-    
-    //calculate the final membrane voltage based on the computed variables
-    n->voltage = voltage +
-                (n->timeStep * n->current / n->C) -
-                (n->timeStep * ( n->rate[0] * (voltage - n->V[0]) + n->rate[1] * (voltage - n->V[1]) + n->rate[2] * (voltage - n->V[2])));
-    
-    if (n->mode == NeuronTanh)
-    {
-        n->voltage = 100.0f * tanhf(0.01f * n->voltage);
-    }
-    else if (n->mode == NeuronAaltoShaper)
-    {
-        float shapeVoltage = 0.01f * n->voltage;
-        
-        float w, c, xc, xc2, xc4;
-
-        float sqrt8 = 2.82842712475f;
-
-        float wscale = 1.30612244898f;
-        float m_drive = 1.0f;
-
-        xc = LEAF_clip(-sqrt8, shapeVoltage, sqrt8);
-
-        xc2 = xc*xc;
-
-        c = 0.5f * shapeVoltage * (3.0f - (xc2));
-
-        xc4 = xc2 * xc2;
-
-        w = (1.0f - xc2 * 0.25f + xc4 * 0.015625f) * wscale;
-
-        shapeVoltage = w * (c + 0.05f * xc2) * (m_drive + 0.75f);
-        
-        n->voltage = 100.0f * shapeVoltage;
-    }
-    
-    
-    if (n->voltage > 100.0f)  n->voltage = 100.0f;
-    else if (n->voltage < -100.) n->voltage = -100.0f;
-    
-    //(inputCurrent + (voltage - ((voltage * timeStep) / timeConstant)) + P[0] + P[1] + P[2]) => voltage;
-    // now we should have a result
-    //set the output voltage to the "step" ugen, which controls the DAC.
-    output = n->voltage * 0.01f; // volts
-    
-    output = tPoleZero_tick(&n->f, output);
-    
-    return output;
-
-}
-
-void        tNeuron_setMode  (tNeuron* const n, NeuronMode mode)
-{
-    n->mode = mode;
-}
-
-void        tNeuron_setCurrent  (tNeuron* const n, float current)
-{
-    n->current = current;
-}
-
-// Cycle
-void    tCycle_init(tCycle* const c)
-{
-    c->inc      =  0.0f;
-    c->phase    =  0.0f;
-}
-
-void    tCycle_free(tCycle* const c)
-{
-
-}
-
-int     tCycle_setFreq(tCycle* const c, float freq)
-{
-    if (freq < 0.0f) freq = 0.0f;
-    
-    c->freq = freq;
-    c->inc = freq * leaf.invSampleRate;
-    
-    return 0;
-}
-
-float   tCycle_tick(tCycle* const c)
-{
-    // Phasor increment
-    c->phase += c->inc;
-    while (c->phase >= 1.0f) c->phase -= 1.0f;
-    
-    // Wavetable synthesis
-    float temp = SINE_TABLE_SIZE * c->phase;
-    int intPart = (int)temp;
-    float fracPart = temp - (float)intPart;
-    float samp0 = sinewave[intPart];
-    if (++intPart >= SINE_TABLE_SIZE) intPart = 0;
-    float samp1 = sinewave[intPart];
-    return (samp0 + (samp1 - samp0) * fracPart);
-}
-
-void     tCycleSampleRateChanged (tCycle* const c)
-{
-    c->inc = c->freq * leaf.invSampleRate;
-}
-
-/* Phasor */
-void     tPhasorSampleRateChanged (tPhasor* const p)
-{
-    p->inc = p->freq * leaf.invSampleRate;
-};
-
-void    tPhasor_init(tPhasor* const p)
-{
-    p->phase = 0.0f;
-    p->inc = 0.0f;
-}
-
-void    tPhasor_free(tPhasor* const p)
-{
-    
-}
-
-int     tPhasor_setFreq(tPhasor* const p, float freq)
-{
-    if (freq < 0.0f) freq = 0.0f;
-    
-    p->freq = freq;
-    p->inc = freq * leaf.invSampleRate;
-    
-    return 0;
-}
-
-float   tPhasor_tick(tPhasor* const p)
-{
-    p->phase += p->inc;
-    
-    if (p->phase >= 1.0f) p->phase -= 1.0f;
-    
-    return p->phase;
-}
-
-
-
-void    tSawtooth_init(tSawtooth* const c)
-{
-    c->inc      = 0.0f;
-    c->phase    = 0.0f;
-}
-
-void    tSawtooth_free(tSawtooth* const c)
-{
-
-}
-
-int     tSawtooth_setFreq(tSawtooth* const c, float freq)
-{
-    if (freq < 0.0f) freq = 0.0f;
-    
-    c->freq = freq;
-    c->inc = freq * leaf.invSampleRate;
-    
-    return 0;
-}
-
-float   tSawtooth_tick(tSawtooth* const c)
-{
-    // Phasor increment
-    c->phase += c->inc;
-    while (c->phase >= 1.0f) c->phase -= 1.0f;
-    
-    float out = 0.0f;
-    float w;
-    
-    int idx = (int)(c->phase * TRI_TABLE_SIZE);
-    
-    // Wavetable synthesis
-    
-    if (c->freq <= 20.0f)
-    {
-        out = sawtooth[T20][idx];
-    }
-    else if (c->freq <= 40.0f)
-    {
-        w = ((40.0f - c->freq) * INV_20);
-        out = (sawtooth[T20][idx] * w) + (sawtooth[T40][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 80.0f)
-    {
-        w = ((80.0f - c->freq) * INV_40);
-        out = (sawtooth[T40][idx] * w) + (sawtooth[T80][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 160.0f)
-    {
-        w = ((160.0f - c->freq) * INV_80);
-        out = (sawtooth[T80][idx] * w) + (sawtooth[T160][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 320.0f)
-    {
-        w = ((320.0f - c->freq) * INV_160);
-        out = (sawtooth[T160][idx] * w) + (sawtooth[T320][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 640.0f)
-    {
-        w = ((640.0f - c->freq) * INV_320);
-        out = (sawtooth[T320][idx] * w) + (sawtooth[T640][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 1280.0f)
-    {
-        w = ((1280.0f - c->freq) * INV_640);
-        out = (sawtooth[T640][idx] * w) + (sawtooth[T1280][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 2560.0f)
-    {
-        w = ((2560.0f - c->freq) * INV_1280);
-        out = (sawtooth[T1280][idx] * w) + (sawtooth[T2560][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 5120.0f)
-    {
-        w = ((5120.0f - c->freq) * INV_2560);
-        out = (sawtooth[T2560][idx] * w) + (sawtooth[T5120][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 10240.0f)
-    {
-        w = ((10240.0f - c->freq) * INV_5120);
-        out = (sawtooth[T5120][idx] * w) + (sawtooth[T10240][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 20480.0f)
-    {
-        w = ((20480.0f - c->freq) * INV_10240);
-        out = (sawtooth[T10240][idx] * w) + (sawtooth[T20480][idx] * (1.0f - w));
-    }
-    else
-    {
-        out = sawtooth[T20480][idx];
-    }
-    
-    return out;
-}
-
-void     tSawtoothSampleRateChanged (tSawtooth* const c)
-{
-    c->inc = c->freq * leaf.invSampleRate;
-}
-
-/* Triangle */
-void    tTriangle_start(tTriangle* const c)
-{
-    
-}
-
-void   tTriangle_init(tTriangle* const c)
-{
-    c->inc      =  0.0f;
-    c->phase    =  0.0f;
-}
-
-void   tTriangle_free(tTriangle* const c)
-{
-    
-}
-
-int tTriangle_setFreq(tTriangle* const c, float freq)
-{
-    if (freq < 0.0f) freq = 0.0f;
-    
-    c->freq = freq;
-    c->inc = freq * leaf.invSampleRate;
-    
-    return 0;
-}
-
-
-float   tTriangle_tick(tTriangle* const c)
-{
-    // Phasor increment
-    c->phase += c->inc;
-    while (c->phase >= 1.0f) c->phase -= 1.0f;
-    
-    float out = 0.0f;
-    float w;
-    
-    int idx = (int)(c->phase * TRI_TABLE_SIZE);
-    
-    // Wavetable synthesis
-    
-    if (c->freq <= 20.0f)
-    {
-        out = triangle[T20][idx];
-    }
-    else if (c->freq <= 40.0f)
-    {
-        w = ((40.0f - c->freq) * INV_20);
-        out = (triangle[T20][idx] * w) + (triangle[T40][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 80.0f)
-    {
-        w = ((80.0f - c->freq) * INV_40);
-        out = (triangle[T40][idx] * w) + (triangle[T80][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 160.0f)
-    {
-        w = ((160.0f - c->freq) * INV_80);
-        out = (triangle[T80][idx] * w) + (triangle[T160][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 320.0f)
-    {
-        w = ((320.0f - c->freq) * INV_160);
-        out = (triangle[T160][idx] * w) + (triangle[T320][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 640.0f)
-    {
-        w = ((640.0f - c->freq) * INV_320);
-        out = (triangle[T320][idx] * w) + (triangle[T640][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 1280.0f)
-    {
-        w = ((1280.0f - c->freq) * INV_640);
-        out = (triangle[T640][idx] * w) + (triangle[T1280][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 2560.0f)
-    {
-        w = ((2560.0f - c->freq) * INV_1280);
-        out = (triangle[T1280][idx] * w) + (triangle[T2560][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 5120.0f)
-    {
-        w = ((5120.0f - c->freq) * INV_2560);
-        out = (triangle[T2560][idx] * w) + (triangle[T5120][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 10240.0f)
-    {
-        w = ((10240.0f - c->freq) * INV_5120);
-        out = (triangle[T5120][idx] * w) + (triangle[T10240][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 20480.0f)
-    {
-        w = ((20480.0f - c->freq) * INV_10240);
-        out = (triangle[T10240][idx] * w) + (triangle[T20480][idx] * (1.0f - w));
-    }
-    else
-    {
-        out = triangle[T20480][idx];
-    }
-    
-    return out;
-}
-
-void     tTriangleSampleRateChanged (tTriangle*  const c)
-{
-    c->inc = c->freq * leaf.invSampleRate;
-}
-
-/* Square */
-void   tSquare_init(tSquare* const c)
-{
-    c->inc      =  0.0f;
-    c->phase    =  0.0f;
-}
-
-void   tSquare_free(tSquare* const c)
-{
-   
-}
-
-int     tSquare_setFreq(tSquare*  const c, float freq)
-{
-    if (freq < 0.0f) freq = 0.0f;
-    
-    c->freq = freq;
-    c->inc = freq * leaf.invSampleRate;
-    
-    return 0;
-}
-
-float   tSquare_tick(tSquare* const c)
-{
-    // Phasor increment
-    c->phase += c->inc;
-    while (c->phase >= 1.0f) c->phase -= 1.0f;
-    
-    float out = 0.0f;
-    float w = 0.0f;
-    int idx = (int)(c->phase * TRI_TABLE_SIZE);
-    
-    // Wavetable synthesis
-    
-    if (c->freq <= 20.0f)
-    {
-        out = squarewave[T20][idx];
-    }
-    else if (c->freq <= 40.0f)
-    {
-        w = ((40.0f - c->freq) * INV_20);
-        out = (squarewave[T20][idx] * w) + (squarewave[T40][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 80.0f)
-    {
-        w = ((80.0f - c->freq) * INV_40);
-        out = (squarewave[T40][idx] * w) + (squarewave[T80][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 160.0f)
-    {
-        w = ((160.0f - c->freq) * INV_80);
-        out = (squarewave[T80][idx] * w) + (squarewave[T160][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 320.0f)
-    {
-        w = ((320.0f - c->freq) * INV_160);
-        out = (squarewave[T160][idx] * w) + (squarewave[T320][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 640.0f)
-    {
-        w = ((640.0f - c->freq) * INV_320);
-        out = (squarewave[T320][idx] * w) + (squarewave[T640][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 1280.0f)
-    {
-        w = ((1280.0f - c->freq) * INV_640);
-        out = (squarewave[T640][idx] * w) + (squarewave[T1280][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 2560.0f)
-    {
-        w = ((2560.0f - c->freq) * INV_1280);
-        out = (squarewave[T1280][idx] * w) + (squarewave[T2560][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 5120.0f)
-    {
-        w = ((5120.0f - c->freq) * INV_2560);
-        out = (squarewave[T2560][idx] * w) + (squarewave[T5120][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 10240.0f)
-    {
-        w = ((10240.0f - c->freq) * INV_5120);
-        out = (squarewave[T5120][idx] * w) + (squarewave[T10240][idx] * (1.0f - w));
-    }
-    else if (c->freq <= 20480.0f)
-    {
-        w = ((20480.0f - c->freq) * INV_10240);
-        out = (squarewave[T10240][idx] * w) + (squarewave[T20480][idx] * (1.0f - w));
-    }
-    else
-    {
-        out = squarewave[T20480][idx];
-    }
-    
-    return out;
-}
-
-void     tSquareSampleRateChanged (tSquare*  const c)
-{
-    c->inc = c->freq * leaf.invSampleRate;
-}
-
-/* Noise */
-void    tNoise_init(tNoise* const n, NoiseType type)
-{
-    n->type = type;
-    n->rand = leaf.random;
-}
-
-void    tNoise_free(tNoise* const n)
-{
-    
-}
-
-float   tNoise_tick(tNoise* const n)
-{
-    float rand = (n->rand() * 2.0f) - 1.0f;
-    
-    if (n->type == PinkNoise)
-    {
-        float tmp;
-        n->pinkb0 = 0.99765f * n->pinkb0 + rand * 0.0990460f;
-        n->pinkb1 = 0.96300f * n->pinkb1 + rand * 0.2965164f;
-        n->pinkb2 = 0.57000f * n->pinkb2 + rand * 1.0526913f;
-        tmp = n->pinkb0 + n->pinkb1 + n->pinkb2 + rand * 0.1848f;
-        return (tmp * 0.05f);
-    }
-    else // WhiteNoise
-    {
-        return rand;
-    }
-}
--- /dev/null
+++ b/LEAF/Src/leaf-oscillators.c
@@ -1,0 +1,644 @@
+/*==============================================================================
+
+    leaf-oscillators.c
+    Created: 20 Jan 2017 12:00:58pm
+    Author:  Michael R Mulshine
+
+==============================================================================*/
+
+#if _WIN32 || _WIN64
+
+#include "..\Inc\leaf-tables.h"
+#include "..\Inc\leaf-oscillators.h"
+#include "..\leaf.h"
+
+#else
+
+#include "../Inc/leaf-tables.h"
+#include "../Inc/leaf-oscillators.h"
+#include "../leaf.h"
+
+#endif
+
+// Cycle
+void    tCycle_init(tCycle* const c)
+{
+    c->inc      =  0.0f;
+    c->phase    =  0.0f;
+}
+
+void    tCycle_free(tCycle* const c)
+{
+
+}
+
+int     tCycle_setFreq(tCycle* const c, float freq)
+{
+    if (freq < 0.0f) freq = 0.0f;
+    
+    c->freq = freq;
+    c->inc = freq * leaf.invSampleRate;
+    
+    return 0;
+}
+
+float   tCycle_tick(tCycle* const c)
+{
+    // Phasor increment
+    c->phase += c->inc;
+    while (c->phase >= 1.0f) c->phase -= 1.0f;
+    
+    // Wavetable synthesis
+    float temp = SINE_TABLE_SIZE * c->phase;
+    int intPart = (int)temp;
+    float fracPart = temp - (float)intPart;
+    float samp0 = sinewave[intPart];
+    if (++intPart >= SINE_TABLE_SIZE) intPart = 0;
+    float samp1 = sinewave[intPart];
+    return (samp0 + (samp1 - samp0) * fracPart);
+}
+
+void     tCycleSampleRateChanged (tCycle* const c)
+{
+    c->inc = c->freq * leaf.invSampleRate;
+}
+
+//========================================================================
+/* Triangle */
+void    tTriangle_start(tTriangle* const c)
+{
+    
+}
+
+void   tTriangle_init(tTriangle* const c)
+{
+    c->inc      =  0.0f;
+    c->phase    =  0.0f;
+}
+
+void   tTriangle_free(tTriangle* const c)
+{
+    
+}
+
+int tTriangle_setFreq(tTriangle* const c, float freq)
+{
+    if (freq < 0.0f) freq = 0.0f;
+    
+    c->freq = freq;
+    c->inc = freq * leaf.invSampleRate;
+    
+    return 0;
+}
+
+
+float   tTriangle_tick(tTriangle* const c)
+{
+    // Phasor increment
+    c->phase += c->inc;
+    while (c->phase >= 1.0f) c->phase -= 1.0f;
+    
+    float out = 0.0f;
+    float w;
+    
+    int idx = (int)(c->phase * TRI_TABLE_SIZE);
+    
+    // Wavetable synthesis
+    
+    if (c->freq <= 20.0f)
+    {
+        out = triangle[T20][idx];
+    }
+    else if (c->freq <= 40.0f)
+    {
+        w = ((40.0f - c->freq) * INV_20);
+        out = (triangle[T20][idx] * w) + (triangle[T40][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 80.0f)
+    {
+        w = ((80.0f - c->freq) * INV_40);
+        out = (triangle[T40][idx] * w) + (triangle[T80][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 160.0f)
+    {
+        w = ((160.0f - c->freq) * INV_80);
+        out = (triangle[T80][idx] * w) + (triangle[T160][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 320.0f)
+    {
+        w = ((320.0f - c->freq) * INV_160);
+        out = (triangle[T160][idx] * w) + (triangle[T320][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 640.0f)
+    {
+        w = ((640.0f - c->freq) * INV_320);
+        out = (triangle[T320][idx] * w) + (triangle[T640][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 1280.0f)
+    {
+        w = ((1280.0f - c->freq) * INV_640);
+        out = (triangle[T640][idx] * w) + (triangle[T1280][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 2560.0f)
+    {
+        w = ((2560.0f - c->freq) * INV_1280);
+        out = (triangle[T1280][idx] * w) + (triangle[T2560][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 5120.0f)
+    {
+        w = ((5120.0f - c->freq) * INV_2560);
+        out = (triangle[T2560][idx] * w) + (triangle[T5120][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 10240.0f)
+    {
+        w = ((10240.0f - c->freq) * INV_5120);
+        out = (triangle[T5120][idx] * w) + (triangle[T10240][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 20480.0f)
+    {
+        w = ((20480.0f - c->freq) * INV_10240);
+        out = (triangle[T10240][idx] * w) + (triangle[T20480][idx] * (1.0f - w));
+    }
+    else
+    {
+        out = triangle[T20480][idx];
+    }
+    
+    return out;
+}
+
+void     tTriangleSampleRateChanged (tTriangle*  const c)
+{
+    c->inc = c->freq * leaf.invSampleRate;
+}
+
+//========================================================================
+/* Square */
+void   tSquare_init(tSquare* const c)
+{
+    c->inc      =  0.0f;
+    c->phase    =  0.0f;
+}
+
+void   tSquare_free(tSquare* const c)
+{
+    
+}
+
+int     tSquare_setFreq(tSquare*  const c, float freq)
+{
+    if (freq < 0.0f) freq = 0.0f;
+    
+    c->freq = freq;
+    c->inc = freq * leaf.invSampleRate;
+    
+    return 0;
+}
+
+float   tSquare_tick(tSquare* const c)
+{
+    // Phasor increment
+    c->phase += c->inc;
+    while (c->phase >= 1.0f) c->phase -= 1.0f;
+    
+    float out = 0.0f;
+    float w = 0.0f;
+    int idx = (int)(c->phase * TRI_TABLE_SIZE);
+    
+    // Wavetable synthesis
+    
+    if (c->freq <= 20.0f)
+    {
+        out = squarewave[T20][idx];
+    }
+    else if (c->freq <= 40.0f)
+    {
+        w = ((40.0f - c->freq) * INV_20);
+        out = (squarewave[T20][idx] * w) + (squarewave[T40][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 80.0f)
+    {
+        w = ((80.0f - c->freq) * INV_40);
+        out = (squarewave[T40][idx] * w) + (squarewave[T80][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 160.0f)
+    {
+        w = ((160.0f - c->freq) * INV_80);
+        out = (squarewave[T80][idx] * w) + (squarewave[T160][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 320.0f)
+    {
+        w = ((320.0f - c->freq) * INV_160);
+        out = (squarewave[T160][idx] * w) + (squarewave[T320][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 640.0f)
+    {
+        w = ((640.0f - c->freq) * INV_320);
+        out = (squarewave[T320][idx] * w) + (squarewave[T640][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 1280.0f)
+    {
+        w = ((1280.0f - c->freq) * INV_640);
+        out = (squarewave[T640][idx] * w) + (squarewave[T1280][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 2560.0f)
+    {
+        w = ((2560.0f - c->freq) * INV_1280);
+        out = (squarewave[T1280][idx] * w) + (squarewave[T2560][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 5120.0f)
+    {
+        w = ((5120.0f - c->freq) * INV_2560);
+        out = (squarewave[T2560][idx] * w) + (squarewave[T5120][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 10240.0f)
+    {
+        w = ((10240.0f - c->freq) * INV_5120);
+        out = (squarewave[T5120][idx] * w) + (squarewave[T10240][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 20480.0f)
+    {
+        w = ((20480.0f - c->freq) * INV_10240);
+        out = (squarewave[T10240][idx] * w) + (squarewave[T20480][idx] * (1.0f - w));
+    }
+    else
+    {
+        out = squarewave[T20480][idx];
+    }
+    
+    return out;
+}
+
+void     tSquareSampleRateChanged (tSquare*  const c)
+{
+    c->inc = c->freq * leaf.invSampleRate;
+}
+
+//=====================================================================
+// Sawtooth
+void    tSawtooth_init(tSawtooth* const c)
+{
+    c->inc      = 0.0f;
+    c->phase    = 0.0f;
+}
+
+void    tSawtooth_free(tSawtooth* const c)
+{
+
+}
+
+int     tSawtooth_setFreq(tSawtooth* const c, float freq)
+{
+    if (freq < 0.0f) freq = 0.0f;
+    
+    c->freq = freq;
+    c->inc = freq * leaf.invSampleRate;
+    
+    return 0;
+}
+
+float   tSawtooth_tick(tSawtooth* const c)
+{
+    // Phasor increment
+    c->phase += c->inc;
+    while (c->phase >= 1.0f) c->phase -= 1.0f;
+    
+    float out = 0.0f;
+    float w;
+    
+    int idx = (int)(c->phase * TRI_TABLE_SIZE);
+    
+    // Wavetable synthesis
+    
+    if (c->freq <= 20.0f)
+    {
+        out = sawtooth[T20][idx];
+    }
+    else if (c->freq <= 40.0f)
+    {
+        w = ((40.0f - c->freq) * INV_20);
+        out = (sawtooth[T20][idx] * w) + (sawtooth[T40][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 80.0f)
+    {
+        w = ((80.0f - c->freq) * INV_40);
+        out = (sawtooth[T40][idx] * w) + (sawtooth[T80][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 160.0f)
+    {
+        w = ((160.0f - c->freq) * INV_80);
+        out = (sawtooth[T80][idx] * w) + (sawtooth[T160][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 320.0f)
+    {
+        w = ((320.0f - c->freq) * INV_160);
+        out = (sawtooth[T160][idx] * w) + (sawtooth[T320][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 640.0f)
+    {
+        w = ((640.0f - c->freq) * INV_320);
+        out = (sawtooth[T320][idx] * w) + (sawtooth[T640][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 1280.0f)
+    {
+        w = ((1280.0f - c->freq) * INV_640);
+        out = (sawtooth[T640][idx] * w) + (sawtooth[T1280][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 2560.0f)
+    {
+        w = ((2560.0f - c->freq) * INV_1280);
+        out = (sawtooth[T1280][idx] * w) + (sawtooth[T2560][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 5120.0f)
+    {
+        w = ((5120.0f - c->freq) * INV_2560);
+        out = (sawtooth[T2560][idx] * w) + (sawtooth[T5120][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 10240.0f)
+    {
+        w = ((10240.0f - c->freq) * INV_5120);
+        out = (sawtooth[T5120][idx] * w) + (sawtooth[T10240][idx] * (1.0f - w));
+    }
+    else if (c->freq <= 20480.0f)
+    {
+        w = ((20480.0f - c->freq) * INV_10240);
+        out = (sawtooth[T10240][idx] * w) + (sawtooth[T20480][idx] * (1.0f - w));
+    }
+    else
+    {
+        out = sawtooth[T20480][idx];
+    }
+    
+    return out;
+}
+
+void     tSawtoothSampleRateChanged (tSawtooth* const c)
+{
+    c->inc = c->freq * leaf.invSampleRate;
+}
+
+//========================================================================
+/* Phasor */
+void     tPhasorSampleRateChanged (tPhasor* const p)
+{
+    p->inc = p->freq * leaf.invSampleRate;
+};
+
+void    tPhasor_init(tPhasor* const p)
+{
+    p->phase = 0.0f;
+    p->inc = 0.0f;
+}
+
+void    tPhasor_free(tPhasor* const p)
+{
+    
+}
+
+int     tPhasor_setFreq(tPhasor* const p, float freq)
+{
+    if (freq < 0.0f) freq = 0.0f;
+    
+    p->freq = freq;
+    p->inc = freq * leaf.invSampleRate;
+    
+    return 0;
+}
+
+float   tPhasor_tick(tPhasor* const p)
+{
+    p->phase += p->inc;
+    
+    if (p->phase >= 1.0f) p->phase -= 1.0f;
+    
+    return p->phase;
+}
+
+/* Noise */
+void    tNoise_init(tNoise* const n, NoiseType type)
+{
+    n->type = type;
+    n->rand = leaf.random;
+}
+
+void    tNoise_free(tNoise* const n)
+{
+    
+}
+
+float   tNoise_tick(tNoise* const n)
+{
+    float rand = (n->rand() * 2.0f) - 1.0f;
+    
+    if (n->type == PinkNoise)
+    {
+        float tmp;
+        n->pinkb0 = 0.99765f * n->pinkb0 + rand * 0.0990460f;
+        n->pinkb1 = 0.96300f * n->pinkb1 + rand * 0.2965164f;
+        n->pinkb2 = 0.57000f * n->pinkb2 + rand * 1.0526913f;
+        tmp = n->pinkb0 + n->pinkb1 + n->pinkb2 + rand * 0.1848f;
+        return (tmp * 0.05f);
+    }
+    else // WhiteNoise
+    {
+        return rand;
+    }
+}
+
+//=================================================================================
+/* Neuron */
+
+void     tNeuronSampleRateChanged(tNeuron* n)
+{
+    
+}
+
+void    tNeuron_init(tNeuron* const n)
+{
+    tPoleZero_init(&n->f);
+    
+    tPoleZero_setBlockZero(&n->f, 0.99f);
+    
+    n->timeStep = 1.0f / 50.0f;
+    
+    n->current = 0.0f; // 100.0f for sound
+    n->voltage = 0.0f;
+    
+    n->mode = NeuronNormal;
+    
+    n->P[0] = 0.0f;
+    n->P[1] = 0.0f;
+    n->P[2] = 1.0f;
+    
+    n->V[0] = -12.0f;
+    n->V[1] = 115.0f;
+    n->V[2] = 10.613f;
+    
+    n->gK = 36.0f;
+    n->gN = 120.0f;
+    n->gL = 0.3f;
+    n->C = 1.0f;
+    
+    n->rate[2] = n->gL/n->C;
+}
+
+void    tNeuron_free(tNeuron* const n)
+{
+    tPoleZero_free(&n->f);
+}
+
+void   tNeuron_reset(tNeuron* const n)
+{
+    
+    tPoleZero_setBlockZero(&n->f, 0.99f);
+    
+    n->timeStep = 1.0f / 50.0f;
+    
+    n->current = 0.0f; // 100.0f for sound
+    n->voltage = 0.0f;
+    
+    n->mode = NeuronNormal;
+    
+    n->P[0] = 0.0f;
+    n->P[1] = 0.0f;
+    n->P[2] = 1.0f;
+    
+    n->V[0] = -12.0f;
+    n->V[1] = 115.0f;
+    n->V[2] = 10.613f;
+    
+    n->gK = 36.0f;
+    n->gN = 120.0f;
+    n->gL = 0.3f;
+    n->C = 1.0f;
+    
+    n->rate[2] = n->gL/n->C;
+}
+
+
+void        tNeuron_setV1(tNeuron* const n, float V1)
+{
+    n->V[0] = V1;
+}
+
+
+void        tNeuron_setV2(tNeuron* const n, float V2)
+{
+    n->V[1] = V2;
+}
+
+void        tNeuron_setV3(tNeuron* const n, float V3)
+{
+    n->V[2] = V3;
+}
+
+void        tNeuron_setTimeStep(tNeuron* const n, float timeStep)
+{
+    n->timeStep = timeStep;
+}
+
+void        tNeuron_setK(tNeuron* const n, float K)
+{
+    n->gK = K;
+}
+
+void        tNeuron_setL(tNeuron* const n, float L)
+{
+    n->gL = L;
+    n->rate[2] = n->gL/n->C;
+}
+
+void        tNeuron_setN(tNeuron* const n, float N)
+{
+    n->gN = N;
+}
+
+void        tNeuron_setC(tNeuron* const n, float C)
+{
+    n->C = C;
+    n->rate[2] = n->gL/n->C;
+}
+
+float   tNeuron_tick(tNeuron* const n)
+{
+    float output = 0.0f;
+    float voltage = n->voltage;
+    
+    n->alpha[0] = (0.01f * (10.0f - voltage)) / (expf((10.0f - voltage)/10.0f) - 1.0f);
+    n->alpha[1] = (0.1f * (25.0f-voltage)) / (expf((25.0f-voltage)/10.0f) - 1.0f);
+    n->alpha[2] = (0.07f * expf((-1.0f * voltage)/20.0f));
+    
+    n->beta[0] = (0.125f * expf((-1.0f* voltage)/80.0f));
+    n->beta[1] = (4.0f * expf((-1.0f * voltage)/18.0f));
+    n->beta[2] = (1.0f / (expf((30.0f-voltage)/10.0f) + 1.0f));
+    
+    for (int i = 0; i < 3; i++)
+    {
+        n->P[i] = (n->alpha[i] * n->timeStep) + ((1.0f - ((n->alpha[i] + n->beta[i]) * n->timeStep)) * n->P[i]);
+        
+        if (n->P[i] > 1.0f)         n->P[i] = 0.0f;
+        else if (n->P[i] < -1.0f)   n->P[i] = 0.0f;
+    }
+    // rate[0]= k ; rate[1] = Na ; rate[2] = l
+    n->rate[0] = ((n->gK * powf(n->P[0], 4.0f)) / n->C);
+    n->rate[1] = ((n->gN * powf(n->P[1], 3.0f) * n->P[2]) / n->C);
+    
+    //calculate the final membrane voltage based on the computed variables
+    n->voltage = voltage +
+    (n->timeStep * n->current / n->C) -
+    (n->timeStep * ( n->rate[0] * (voltage - n->V[0]) + n->rate[1] * (voltage - n->V[1]) + n->rate[2] * (voltage - n->V[2])));
+    
+    if (n->mode == NeuronTanh)
+    {
+        n->voltage = 100.0f * tanhf(0.01f * n->voltage);
+    }
+    else if (n->mode == NeuronAaltoShaper)
+    {
+        float shapeVoltage = 0.01f * n->voltage;
+        
+        float w, c, xc, xc2, xc4;
+        
+        float sqrt8 = 2.82842712475f;
+        
+        float wscale = 1.30612244898f;
+        float m_drive = 1.0f;
+        
+        xc = LEAF_clip(-sqrt8, shapeVoltage, sqrt8);
+        
+        xc2 = xc*xc;
+        
+        c = 0.5f * shapeVoltage * (3.0f - (xc2));
+        
+        xc4 = xc2 * xc2;
+        
+        w = (1.0f - xc2 * 0.25f + xc4 * 0.015625f) * wscale;
+        
+        shapeVoltage = w * (c + 0.05f * xc2) * (m_drive + 0.75f);
+        
+        n->voltage = 100.0f * shapeVoltage;
+    }
+    
+    
+    if (n->voltage > 100.0f)  n->voltage = 100.0f;
+    else if (n->voltage < -100.) n->voltage = -100.0f;
+    
+    //(inputCurrent + (voltage - ((voltage * timeStep) / timeConstant)) + P[0] + P[1] + P[2]) => voltage;
+    // now we should have a result
+    //set the output voltage to the "step" ugen, which controls the DAC.
+    output = n->voltage * 0.01f; // volts
+    
+    output = tPoleZero_tick(&n->f, output);
+    
+    return output;
+    
+}
+
+void        tNeuron_setMode  (tNeuron* const n, NeuronMode mode)
+{
+    n->mode = mode;
+}
+
+void        tNeuron_setCurrent  (tNeuron* const n, float current)
+{
+    n->current = current;
+}
--- a/LEAF/Src/leaf-oversampler.c
+++ /dev/null
@@ -1,236 +1,0 @@
-//
-//  leaf-oversampler.c
-//  LEAF
-//
-//  Created by Matthew Wang and Joshua Becker on 2/28/19.
-//  Copyright © 2019 Princeton University. All rights reserved.
-//
-
-#if _WIN32 || _WIN64
-
-#include "..\Inc\leaf-oversampler.h"
-#include "..\Inc\leaf-tables.h"
-#else
-
-
-#include "../Inc/leaf-oversampler.h"
-#include "../Inc/leaf-tables.h"
-
-#endif
-
-// Oversampler
-// Latency is equal to the phase length (numTaps / ratio)
-void tOversampler_init(tOversampler* const os, int ratio, oBool extraQuality)
-{
-    uint8_t offset = 0;
-    if (extraQuality) offset = 6;
-    if (ratio == 2 || ratio == 4  ||
-        ratio == 8 || ratio == 16 ||
-        ratio == 32 || ratio == 64) {
-        os->ratio = ratio;
-        int idx = (int)(log2f(os->ratio))-1+offset;
-        os->numTaps = firNumTaps[idx];
-        os->phaseLength = os->numTaps / os->ratio;
-        os->pCoeffs = (float*) firCoeffs[idx];
-        os->upState = leaf_alloc(sizeof(float) * os->phaseLength);
-        os->downState = leaf_alloc(sizeof(float) * os->phaseLength);
-    }
-}
-
-void tOversampler_free(tOversampler* const os)
-{
-    leaf_free(os->upState);
-    leaf_free(os->downState);
-}
-
-float tOversampler_tick(tOversampler* const os, float input, float (*effectTick)(float))
-{
-    float buf[os->ratio];
-    
-    tOversampler_upsample(os, input, buf);
-    
-    for (int i = 0; i < os->ratio; ++i) {
-        buf[i] = effectTick(buf[i]);
-    }
-    
-    return tOversampler_downsample(os, buf);
-}
-
-// From CMSIS DSP Library
-void tOversampler_upsample(tOversampler* const os, float input, float* output)
-{
-    float *pState = os->upState;                 /* State pointer */
-    const float *pCoeffs = os->pCoeffs;               /* Coefficient pointer */
-    float *pStateCur;
-    float *ptr1;                               /* Temporary pointer for state buffer */
-    const float *ptr2;                               /* Temporary pointer for coefficient buffer */
-    float sum0;                                /* Accumulators */
-    uint32_t i, tapCnt;                    /* Loop counters */
-    uint32_t phaseLen = os->phaseLength;            /* Length of each polyphase filter component */
-    uint32_t j;
-    
-    /* os->pState buffer contains previous frame (phaseLen - 1) samples */
-    /* pStateCur points to the location where the new input data should be written */
-    pStateCur = os->upState + (phaseLen - 1U);
-    
-    /* Copy new input sample into the state buffer */
-    *pStateCur = input;
-    
-    /* Address modifier index of coefficient buffer */
-    j = 1U;
-    
-    /* Loop over the Interpolation factor. */
-    i = os->ratio;
-    
-    while (i > 0U)
-    {
-        /* Set accumulator to zero */
-        sum0 = 0.0f;
-        
-        /* Initialize state pointer */
-        ptr1 = pState;
-        
-        /* Initialize coefficient pointer */
-        ptr2 = pCoeffs + (os->ratio - j);
-        
-        /* Loop over the polyPhase length.
-         Repeat until we've computed numTaps-(4*os->L) coefficients. */
-        
-        /* Initialize tapCnt with number of samples */
-        tapCnt = phaseLen;
-        
-        while (tapCnt > 0U)
-        {
-            /* Perform the multiply-accumulate */
-            sum0 += *ptr1++ * *ptr2;
-            
-            /* Upsampling is done by stuffing L-1 zeros between each sample.
-             * So instead of multiplying zeros with coefficients,
-             * Increment the coefficient pointer by interpolation factor times. */
-            ptr2 += os->ratio;
-            
-            /* Decrement loop counter */
-            tapCnt--;
-        }
-        
-        /* The result is in the accumulator, store in the destination buffer. */
-        *output++ = sum0 * os->ratio;
-        
-        /* Increment the address modifier index of coefficient buffer */
-        j++;
-        
-        /* Decrement the loop counter */
-        i--;
-    }
-    
-    /* Advance the state pointer by 1
-     * to process the next group of interpolation factor number samples */
-    pState = pState + 1;
-    
-    /* Processing is complete.
-     Now copy the last phaseLen - 1 samples to the satrt of the state buffer.
-     This prepares the state buffer for the next function call. */
-    
-    /* Points to the start of the state buffer */
-    pStateCur = os->upState;
-
-    /* Initialize tapCnt with number of samples */
-    tapCnt = (phaseLen - 1U);
-    
-    /* Copy data */
-    while (tapCnt > 0U)
-    {
-        *pStateCur++ = *pState++;
-        
-        /* Decrement loop counter */
-        tapCnt--;
-    }
-}
-
-// From CMSIS DSP Library
-float tOversampler_downsample(tOversampler *const os, float* input)
-{
-    float *pState = os->downState;                 /* State pointer */
-    const float *pCoeffs = os->pCoeffs;               /* Coefficient pointer */
-    float *pStateCur;                          /* Points to the current sample of the state */
-    float *px0;                                /* Temporary pointer for state buffer */
-    const float *pb;                                 /* Temporary pointer for coefficient buffer */
-    float x0, c0;                              /* Temporary variables to hold state and coefficient values */
-    float acc0;                                /* Accumulator */
-    uint32_t numTaps = os->numTaps;                 /* Number of filter coefficients in the filter */
-    uint32_t i, tapCnt;
-    float output;
-    
-    /* os->pState buffer contains previous frame (numTaps - 1) samples */
-    /* pStateCur points to the location where the new input data should be written */
-    pStateCur = os->downState + (numTaps - 1U);
-    
-    /* Copy decimation factor number of new input samples into the state buffer */
-    i = os->ratio;
-    
-    do
-    {
-        *pStateCur++ = *input++;
-        
-    } while (--i);
-    
-    /* Set accumulator to zero */
-    acc0 = 0.0f;
-    
-    /* Initialize state pointer */
-    px0 = pState;
-    
-    /* Initialize coeff pointer */
-    pb = pCoeffs;
-    
-    /* Initialize tapCnt with number of taps */
-    tapCnt = numTaps;
-    
-    while (tapCnt > 0U)
-    {
-        /* Read coefficients */
-        c0 = *pb++;
-        
-        /* Fetch 1 state variable */
-        x0 = *px0++;
-        
-        /* Perform the multiply-accumulate */
-        acc0 += x0 * c0;
-        
-        /* Decrement loop counter */
-        tapCnt--;
-    }
-    
-    /* Advance the state pointer by the decimation factor
-     * to process the next group of decimation factor number samples */
-    pState = pState + os->ratio;
-    
-    /* The result is in the accumulator, store in the destination buffer. */
-    output = acc0;
-    
-    /* Processing is complete.
-     Now copy the last numTaps - 1 samples to the satrt of the state buffer.
-     This prepares the state buffer for the next function call. */
-    
-    /* Points to the start of the state buffer */
-    pStateCur = os->downState;
-    
-    /* Initialize tapCnt with number of taps */
-    tapCnt = (numTaps - 1U);
-    
-    /* Copy data */
-    while (tapCnt > 0U)
-    {
-        *pStateCur++ = *pState++;
-        
-        /* Decrement loop counter */
-        tapCnt--;
-    }
-    
-    return output;
-}
-
-int tOversampler_getLatency(tOversampler* const os)
-{
-    return os->phaseLength;
-}
--- /dev/null
+++ b/LEAF/Src/leaf-physical.c
@@ -1,0 +1,596 @@
+/*==============================================================================
+
+    leaf-string.c
+    Created: 30 Nov 2018 10:41:42am
+    Author:  airship
+
+==============================================================================*/
+
+#if _WIN32 || _WIN64
+
+#include "..\Inc\leaf-physical.h"
+
+#else
+
+#include "../Inc/leaf-physical.h"
+
+#endif
+
+/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ tPluck ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
+void    tPluck_init         (tPluck* const p, float lowestFrequency)
+{
+    if ( lowestFrequency <= 0.0f )  lowestFrequency = 10.0f;
+    
+    tNoise_init(&p->noise, WhiteNoise);
+    
+    tOnePole_init(&p->pickFilter, 0.0f);
+    
+    tOneZero_init(&p->loopFilter, 0.0f);
+    
+    tAllpassDelay_init(&p->delayLine, 0.0f, leaf.sampleRate * 2);
+    
+    tPluck_setFrequency(p, 220.0f);
+}
+
+void tPluck_free (tPluck* const p)
+{
+    tNoise_free(&p->noise);
+    tOnePole_free(&p->pickFilter);
+    tOneZero_free(&p->loopFilter);
+    tAllpassDelay_free(&p->delayLine);
+}
+
+float   tPluck_getLastOut    (tPluck *p)
+{
+    return p->lastOut;
+}
+
+float   tPluck_tick          (tPluck *p)
+{
+    return (p->lastOut = 3.0f * tAllpassDelay_tick(&p->delayLine, tOneZero_tick(&p->loopFilter, tAllpassDelay_getLastOut(&p->delayLine) * p->loopGain ) ));
+}
+
+void    tPluck_pluck         (tPluck* const p, float amplitude)
+{
+    if ( amplitude < 0.0f)      amplitude = 0.0f;
+    else if (amplitude > 1.0f)  amplitude = 1.0f;
+    
+    tOnePole_setPole(&p->pickFilter, 0.999f - (amplitude * 0.15f));
+    tOnePole_setGain(&p->pickFilter, amplitude * 0.5f );
+    
+    // Fill delay with noise additively with current contents.
+    for ( uint32_t i = 0; i < (uint32_t)tAllpassDelay_getDelay(&p->delayLine); i++ )
+        tAllpassDelay_tick(&p->delayLine, 0.6f * tAllpassDelay_getLastOut(&p->delayLine) + tOnePole_tick(&p->pickFilter, tNoise_tick(&p->noise) ) );
+}
+
+// Start a note with the given frequency and amplitude.;
+void    tPluck_noteOn        (tPluck* const p, float frequency, float amplitude )
+{
+    p->lastFreq = frequency;
+    tPluck_setFrequency( p, frequency );
+    tPluck_pluck( p, amplitude );
+}
+
+// Stop a note with the given amplitude (speed of decay).
+void    tPluck_noteOff       (tPluck* const p, float amplitude )
+{
+    if ( amplitude < 0.0f)      amplitude = 0.0f;
+    else if (amplitude > 1.0f)  amplitude = 1.0f;
+    
+    p->loopGain = 1.0f - amplitude;
+}
+
+// Set instrument parameters for a particular frequency.
+void    tPluck_setFrequency  (tPluck* const p, float frequency )
+{
+    if ( frequency <= 0.0f )   frequency = 0.001f;
+    
+    // Delay = length - filter delay.
+    float delay = ( leaf.sampleRate / frequency ) - tOneZero_getPhaseDelay(&p->loopFilter, frequency );
+    
+    tAllpassDelay_setDelay(&p->delayLine, delay );
+    
+    p->loopGain = 0.99f + (frequency * 0.000005f);
+    
+    if ( p->loopGain >= 0.999f ) p->loopGain = 0.999f;
+    
+}
+
+// Perform the control change specified by \e number and \e value (0.0 - 128.0).
+void    tPluck_controlChange (tPluck* const p, int number, float value)
+{
+    return;
+}
+
+void tPluckSampleRateChanged(tPluck* const p)
+{
+    //tPluckSetFrequency(p, p->lastFreq);
+}
+
+/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ tKarplusStrong ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
+void    tKarplusStrong_init          (tKarplusStrong* const p, float lowestFrequency)
+{
+    if ( lowestFrequency <= 0.0f )  lowestFrequency = 8.0f;
+    
+    tAllpassDelay_init(&p->delayLine, 0.0f, leaf.sampleRate * 2);
+
+    tLinearDelay_init(&p->combDelay, 0.0f, leaf.sampleRate * 2);
+    
+    tOneZero_init(&p->filter, 0.0f);
+    
+    tNoise_init(&p->noise, WhiteNoise);
+    
+    for (int i = 0; i < 4; i++)
+    {
+        tBiQuad_init(&p->biquad[i]);
+    }
+    
+    p->pluckAmplitude = 0.3f;
+    p->pickupPosition = 0.4f;
+    
+    p->stretching = 0.9999f;
+    p->baseLoopGain = 0.995f;
+    p->loopGain = 0.999f;
+    
+    tKarplusStrong_setFrequency( p, 220.0f );
+    
+}
+
+void tKarplusStrong_free (tKarplusStrong* const p)
+{
+    tAllpassDelay_free(&p->delayLine);
+    tLinearDelay_free(&p->combDelay);
+    tOneZero_free(&p->filter);
+    tNoise_free(&p->noise);
+    
+    for (int i = 0; i < 4; i++)
+    {
+        tBiQuad_free(&p->biquad[i]);
+    }
+}
+
+float   tKarplusStrong_getLastOut    (tKarplusStrong* const p)
+{
+    return p->lastOut;
+}
+
+float   tKarplusStrong_tick          (tKarplusStrong* const p)
+{
+    float temp = tAllpassDelay_getLastOut(&p->delayLine) * p->loopGain;
+    
+    // Calculate allpass stretching.
+    for (int i=0; i<4; i++)     temp = tBiQuad_tick(&p->biquad[i],temp);
+    
+    // Moving average filter.
+    temp = tOneZero_tick(&p->filter, temp);
+    
+    float out = tAllpassDelay_tick(&p->delayLine, temp);
+    out = out - tLinearDelay_tick(&p->combDelay, out);
+    p->lastOut = out;
+    
+    return p->lastOut;
+}
+
+void    tKarplusStrong_pluck         (tKarplusStrong* const p, float amplitude)
+{
+    if ( amplitude < 0.0f)      amplitude = 0.0f;
+    else if (amplitude > 1.0f)  amplitude = 1.0f;
+    
+    p->pluckAmplitude = amplitude;
+    
+    for ( uint32_t i=0; i < (uint32_t)tAllpassDelay_getDelay(&p->delayLine); i++ )
+    {
+        // Fill delay with noise additively with current contents.
+        tAllpassDelay_tick(&p->delayLine, (tAllpassDelay_getLastOut(&p->delayLine) * 0.6f) + 0.4f * tNoise_tick(&p->noise) * p->pluckAmplitude );
+        //delayLine_.tick( combDelay_.tick((delayLine_.lastOut() * 0.6) + 0.4 * noise->tick() * pluckAmplitude_) );
+    }
+}
+
+// Start a note with the given frequency and amplitude.;
+void    tKarplusStrong_noteOn        (tKarplusStrong* const p, float frequency, float amplitude )
+{
+    tKarplusStrong_setFrequency( p, frequency );
+    tKarplusStrong_pluck( p, amplitude );
+}
+
+// Stop a note with the given amplitude (speed of decay).
+void    tKarplusStrong_noteOff       (tKarplusStrong* const p, float amplitude )
+{
+    if ( amplitude < 0.0f)      amplitude = 0.0f;
+    else if (amplitude > 1.0f)  amplitude = 1.0f;
+    
+    p->loopGain = 1.0f - amplitude;
+}
+
+// Set instrument parameters for a particular frequency.
+void    tKarplusStrong_setFrequency  (tKarplusStrong* const p, float frequency )
+{
+    if ( frequency <= 0.0f )   frequency = 0.001f;
+    
+    p->lastFrequency = frequency;
+    p->lastLength = leaf.sampleRate / p->lastFrequency;
+    float delay = p->lastLength - 0.5f;
+    tAllpassDelay_setDelay(&p->delayLine, delay);
+    
+    // MAYBE MODIFY LOOP GAINS
+    p->loopGain = p->baseLoopGain + (frequency * 0.000005f);
+    if (p->loopGain >= 1.0f) p->loopGain = 0.99999f;
+    
+    tKarplusStrong_setStretch(p, p->stretching);
+    
+    tLinearDelay_setDelay(&p->combDelay, 0.5f * p->pickupPosition * p->lastLength );
+    
+}
+
+// Set the stretch "factor" of the string (0.0 - 1.0).
+void    tKarplusStrong_setStretch         (tKarplusStrong* const p, float stretch )
+{
+    p->stretching = stretch;
+    float coefficient;
+    float freq = p->lastFrequency * 2.0f;
+    float dFreq = ( (0.5f * leaf.sampleRate) - freq ) * 0.25f;
+    float temp = 0.5f + (stretch * 0.5f);
+    if ( temp > 0.9999f ) temp = 0.9999f;
+    
+    for ( int i=0; i<4; i++ )
+    {
+        coefficient = temp * temp;
+        tBiQuad_setA2(&p->biquad[i], coefficient);
+        tBiQuad_setB0(&p->biquad[i], coefficient);
+        tBiQuad_setB2(&p->biquad[i], 1.0f);
+        
+        coefficient = -2.0f * temp * cos(TWO_PI * freq / leaf.sampleRate);
+        tBiQuad_setA1(&p->biquad[i], coefficient);
+        tBiQuad_setB1(&p->biquad[i], coefficient);
+        
+        freq += dFreq;
+    }
+}
+
+// Set the pluck or "excitation" position along the string (0.0 - 1.0).
+void    tKarplusStrong_setPickupPosition  (tKarplusStrong* const p, float position )
+{
+    if (position < 0.0f)        p->pickupPosition = 0.0f;
+    else if (position <= 1.0f)  p->pickupPosition = position;
+    else                        p->pickupPosition = 1.0f;
+    
+    tLinearDelay_setDelay(&p->combDelay, 0.5f * p->pickupPosition * p->lastLength);
+}
+
+// Set the base loop gain.
+void    tKarplusStrong_setBaseLoopGain    (tKarplusStrong* const p, float aGain )
+{
+    p->baseLoopGain = aGain;
+    p->loopGain = p->baseLoopGain + (p->lastFrequency * 0.000005f);
+    if ( p->loopGain > 0.99999f ) p->loopGain = 0.99999f;
+}
+
+// Perform the control change specified by \e number and \e value (0.0 - 128.0).
+void    tKarplusStrong_controlChange (tKarplusStrong* const p, SKControlType type, float value)
+{
+    if ( value < 0.0f )         value = 0.0f;
+    else if (value > 128.0f)   value = 128.0f;
+    
+    float normalizedValue = value * INV_128;
+    
+    if (type == SKPickPosition) // 4
+        tKarplusStrong_setPickupPosition( p, normalizedValue );
+    else if (type == SKStringDamping) // 11
+        tKarplusStrong_setBaseLoopGain( p, 0.97f + (normalizedValue * 0.03f) );
+    else if (type == SKDetune) // 1
+        tKarplusStrong_setStretch( p, 0.91f + (0.09f * (1.0f - normalizedValue)) );
+    
+}
+
+void    tKarplusStrongSampleRateChanged (tKarplusStrong* const c)
+{
+    tKarplusStrong_setFrequency(c, c->lastFrequency);
+    tKarplusStrong_setStretch(c, c->stretching);
+}
+
+/* Simple Living String*/
+
+void    tSimpleLivingString_init(tSimpleLivingString* const p, float freq, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode)
+{
+    p->curr=0.0f;
+    tExpSmooth_init(&p->wlSmooth, leaf.sampleRate/freq, 0.01); // smoother for string wavelength (not freq, to avoid expensive divisions)
+    tSimpleLivingString_setFreq(p, freq);
+    tLinearDelay_init(&p->delayLine,p->waveLengthInSamples, 2400);
+    tOnePole_init(&p->bridgeFilter, dampFreq);
+    tHighpass_init(&p->DCblocker,13);
+    p->decay=decay;
+    tFeedbackLeveler_init(&p->fbLev, targetLev, levSmoothFactor, levStrength, levMode);
+    p->levMode=levMode;
+}
+
+void tSimpleLivingString_free(tSimpleLivingString* const p)
+{
+    tExpSmooth_free(&p->wlSmooth);
+    tLinearDelay_free(&p->delayLine);
+    tOnePole_free(&p->bridgeFilter);
+    tHighpass_free(&p->DCblocker);
+    tFeedbackLeveler_free(&p->fbLev);
+}
+
+int     tSimpleLivingString_setFreq(tSimpleLivingString* const p, float freq)
+{
+    if (freq<20) freq=20;
+    else if (freq>10000) freq=10000;
+    p->waveLengthInSamples = leaf.sampleRate/freq;
+    tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
+    return 0;
+}
+
+int     tSimpleLivingString_setWaveLength(tSimpleLivingString* const p, float waveLength)
+{
+    if (waveLength<4.8) waveLength=4.8;
+    else if (waveLength>2400) waveLength=2400;
+    p->waveLengthInSamples = waveLength;
+    tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
+    return 0;
+}
+
+int     tSimpleLivingString_setDampFreq(tSimpleLivingString* const p, float dampFreq)
+{
+    tOnePole_setFreq(&p->bridgeFilter, dampFreq);
+    return 0;
+}
+
+int     tSimpleLivingString_setDecay(tSimpleLivingString* const p, float decay)
+{
+    p->decay=decay;
+    return 0;
+}
+
+int     tSimpleLivingString_setTargetLev(tSimpleLivingString* const p, float targetLev)
+{
+    tFeedbackLeveler_setTargetLevel(&p->fbLev, targetLev);
+    return 0;
+}
+
+int     tSimpleLivingString_setLevSmoothFactor(tSimpleLivingString* const p, float levSmoothFactor)
+{
+    tFeedbackLeveler_setFactor(&p->fbLev, levSmoothFactor);
+    return 0;
+}
+
+int     tSimpleLivingString_setLevStrength(tSimpleLivingString* const p, float levStrength)
+{
+    tFeedbackLeveler_setStrength(&p->fbLev, levStrength);
+    return 0;
+}
+
+int     tSimpleLivingString_setLevMode(tSimpleLivingString* const p, int levMode)
+{
+    tFeedbackLeveler_setMode(&p->fbLev, levMode);
+    p->levMode=levMode;
+    return 0;
+}
+
+float   tSimpleLivingString_tick(tSimpleLivingString* const p, float input)
+{
+    float stringOut=tOnePole_tick(&p->bridgeFilter,tLinearDelay_tickOut(&p->delayLine));
+    float stringInput=tHighpass_tick(&p->DCblocker, tFeedbackLeveler_tick(&p->fbLev, (p->levMode==0?p->decay*stringOut:stringOut)+input));
+    tLinearDelay_tickIn(&p->delayLine, stringInput);
+    tLinearDelay_setDelay(&p->delayLine, tExpSmooth_tick(&p->wlSmooth));
+    p->curr = stringOut;
+    return p->curr;
+}
+
+float   tSimpleLivingString_sample(tSimpleLivingString* const p)
+{
+    return p->curr;
+}
+
+/* Living String*/
+
+void    tLivingString_init(tLivingString* const p, float freq, float pickPos, float prepIndex, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode)
+{
+    p->curr=0.0f;
+    tExpSmooth_init(&p->wlSmooth, leaf.sampleRate/freq, 0.01); // smoother for string wavelength (not freq, to avoid expensive divisions)
+    tLivingString_setFreq(p, freq);
+    tExpSmooth_init(&p->ppSmooth, pickPos, 0.01); // smoother for pick position
+    tLivingString_setPickPos(p, pickPos);
+    p->prepIndex=prepIndex;
+    tLinearDelay_init(&p->delLF,p->waveLengthInSamples, 2400);
+    tLinearDelay_init(&p->delUF,p->waveLengthInSamples, 2400);
+    tLinearDelay_init(&p->delUB,p->waveLengthInSamples, 2400);
+    tLinearDelay_init(&p->delLB,p->waveLengthInSamples, 2400);
+    tOnePole_init(&p->bridgeFilter, dampFreq);
+    tOnePole_init(&p->nutFilter, dampFreq);
+    tOnePole_init(&p->prepFilterU, dampFreq);
+    tOnePole_init(&p->prepFilterL, dampFreq);
+    tHighpass_init(&p->DCblockerU,13);
+    tHighpass_init(&p->DCblockerL,13);
+    p->decay=decay;
+    tFeedbackLeveler_init(&p->fbLevU, targetLev, levSmoothFactor, levStrength, levMode);
+    tFeedbackLeveler_init(&p->fbLevL, targetLev, levSmoothFactor, levStrength, levMode);
+    p->levMode=levMode;
+}
+
+void tLivingString_free(tLivingString* const p)
+{
+    tExpSmooth_free(&p->wlSmooth);
+    tExpSmooth_free(&p->ppSmooth);
+    tLinearDelay_free(&p->delLF);
+    tLinearDelay_free(&p->delUF);
+    tLinearDelay_free(&p->delUB);
+    tLinearDelay_free(&p->delLB);
+    tOnePole_free(&p->bridgeFilter);
+    tOnePole_free(&p->nutFilter);
+    tOnePole_free(&p->prepFilterU);
+    tOnePole_free(&p->prepFilterL);
+    tHighpass_free(&p->DCblockerU);
+    tHighpass_free(&p->DCblockerL);
+    tFeedbackLeveler_free(&p->fbLevU);
+    tFeedbackLeveler_free(&p->fbLevL);
+}
+
+int     tLivingString_setFreq(tLivingString* const p, float freq)
+{    // NOTE: It is faster to set wavelength in samples directly
+    if (freq<20) freq=20;
+    else if (freq>10000) freq=10000;
+    p->waveLengthInSamples = leaf.sampleRate/freq;
+    tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
+    return 0;
+}
+
+int     tLivingString_setWaveLength(tLivingString* const p, float waveLength)
+{
+    if (waveLength<4.8) waveLength=4.8;
+    else if (waveLength>2400) waveLength=2400;
+    p->waveLengthInSamples = waveLength;
+    tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
+    return 0;
+}
+
+int     tLivingString_setPickPos(tLivingString* const p, float pickPos)
+{    // between 0 and 1
+    if (pickPos<0.f) pickPos=0.f;
+    else if (pickPos>1.f) pickPos=1.f;
+    p->pickPos = pickPos;
+    tExpSmooth_setDest(&p->ppSmooth, p->pickPos);
+    return 0;
+}
+
+int     tLivingString_setPrepIndex(tLivingString* const p, float prepIndex)
+{    // between 0 and 1
+    if (prepIndex<0.f) prepIndex=0.f;
+    else if (prepIndex>1.f) prepIndex=1.f;
+    p->prepIndex = prepIndex;
+    return 0;
+}
+
+int     tLivingString_setDampFreq(tLivingString* const p, float dampFreq)
+{
+    tOnePole_setFreq(&p->bridgeFilter, dampFreq);
+    tOnePole_setFreq(&p->nutFilter, dampFreq);
+    tOnePole_setFreq(&p->prepFilterU, dampFreq);
+    tOnePole_setFreq(&p->prepFilterL, dampFreq);
+    return 0;
+}
+
+int     tLivingString_setDecay(tLivingString* const p, float decay)
+{
+    p->decay=decay;
+    return 0;
+}
+
+int     tLivingString_setTargetLev(tLivingString* const p, float targetLev)
+{
+    tFeedbackLeveler_setTargetLevel(&p->fbLevU, targetLev);
+    tFeedbackLeveler_setTargetLevel(&p->fbLevL, targetLev);
+    return 0;
+}
+
+int     tLivingString_setLevSmoothFactor(tLivingString* const p, float levSmoothFactor)
+{
+    tFeedbackLeveler_setFactor(&p->fbLevU, levSmoothFactor);
+    tFeedbackLeveler_setFactor(&p->fbLevL, levSmoothFactor);
+    return 0;
+}
+
+int     tLivingString_setLevStrength(tLivingString* const p, float levStrength)
+{
+    tFeedbackLeveler_setStrength(&p->fbLevU, levStrength);
+    tFeedbackLeveler_setStrength(&p->fbLevL, levStrength);
+    return 0;
+}
+
+int     tLivingString_setLevMode(tLivingString* const p, int levMode)
+{
+    tFeedbackLeveler_setMode(&p->fbLevU, levMode);
+    tFeedbackLeveler_setMode(&p->fbLevL, levMode);
+    p->levMode=levMode;
+    return 0;
+}
+
+float   tLivingString_tick(tLivingString* const p, float input)
+{
+    // from pickPos upwards=forwards
+    float fromLF=tLinearDelay_tickOut(&p->delLF);
+    float fromUF=tLinearDelay_tickOut(&p->delUF);
+    float fromUB=tLinearDelay_tickOut(&p->delUB);
+    float fromLB=tLinearDelay_tickOut(&p->delLB);
+    // into upper half of string, from nut, going backwards
+    float fromNut=-tFeedbackLeveler_tick(&p->fbLevU, (p->levMode==0?p->decay:1)*tHighpass_tick(&p->DCblockerU, tOnePole_tick(&p->nutFilter, fromUF)));
+    tLinearDelay_tickIn(&p->delUB, fromNut);
+    // into lower half of string, from pickpoint, going backwards
+    float fromLowerPrep=-tOnePole_tick(&p->prepFilterL, fromLF);
+    float intoLower=p->prepIndex*fromLowerPrep+(1-p->prepIndex)*fromUB+input;
+    tLinearDelay_tickIn(&p->delLB, intoLower);
+    // into lower half of string, from bridge
+    float fromBridge=-tFeedbackLeveler_tick(&p->fbLevL, (p->levMode==0?p->decay:1)*tHighpass_tick(&p->DCblockerL, tOnePole_tick(&p->bridgeFilter, fromLB)));
+    tLinearDelay_tickIn(&p->delLF, fromBridge);
+    // into upper half of string, from pickpoint, going forwards/upwards
+    float fromUpperPrep=-tOnePole_tick(&p->prepFilterU, fromUB);
+    float intoUpper=p->prepIndex*fromUpperPrep+(1-p->prepIndex)*fromLF+input;
+    tLinearDelay_tickIn(&p->delUF, intoUpper);
+    // update all delay lengths
+    float pickP=tExpSmooth_tick(&p->ppSmooth);
+    float wLen=tExpSmooth_tick(&p->wlSmooth);
+    float lowLen=pickP*wLen;
+    float upLen=(1-pickP)*wLen;
+    tLinearDelay_setDelay(&p->delLF, lowLen);
+    tLinearDelay_setDelay(&p->delLB, lowLen);
+    tLinearDelay_setDelay(&p->delUF, upLen);
+    tLinearDelay_setDelay(&p->delUB, upLen);
+    p->curr = fromBridge;
+    return p->curr;
+}
+
+float   tLivingString_sample(tLivingString* const p)
+{
+    return p->curr;
+}
+
+///Reed Table model
+//default values from STK are 0.6 offset and -0.8 slope
+
+void    tReedTable_init      (tReedTable* const p, float offset, float slope)
+{
+    p->offset = offset;
+    p->slope = slope;
+}
+
+void    tReedTable_free      (tReedTable* const p)
+{
+    ;
+}
+
+float   tReedTable_tick      (tReedTable* const p, float input)
+{
+    // The input is differential pressure across the reed.
+    float output = p->offset + (p->slope * input);
+    
+    // If output is > 1, the reed has slammed shut and the
+    // reflection function value saturates at 1.0.
+    if ( output > 1.0f) output = 1.0f;
+    
+    // This is nearly impossible in a physical system, but
+    // a reflection function value of -1.0 corresponds to
+    // an open end (and no discontinuity in bore profile).
+    if ( output < -1.0f) output = -1.0f;
+    
+    return output;
+}
+
+float   tReedTable_tanh_tick     (tReedTable* const p, float input)
+{
+    // The input is differential pressure across the reed.
+    float output = p->offset + (p->slope * input);
+    
+    // If output is > 1, the reed has slammed shut and the
+    // reflection function value saturates at 1.0.
+    return tanhf(output);
+}
+
+void     tReedTable_setOffset   (tReedTable* const p, float offset)
+{
+    p->offset = offset;
+}
+
+void     tReedTable_setSlope   (tReedTable* const p, float slope)
+{
+    p->slope = slope;
+}
--- a/LEAF/Src/leaf-pitch.c
+++ /dev/null
@@ -1,563 +1,0 @@
-/*==============================================================================
-
-    leaf-pitch.c
-    Created: 30 Nov 2018 11:02:59am
-    Author:  airship
-
-==============================================================================*/
-
-#if _WIN32 || _WIN64
-
-#include "..\Inc\leaf-pitch.h"
-#else
-
-#include "../Inc/leaf-pitch.h"
-
-#endif
-
-static int pitchshifter_attackdetect(tPitchShifter* ps);
-
-void tPitchShifter_init(tPitchShifter* const ps, float* in, float* out, int bufSize, int frameSize)
-{
-    ps->inBuffer = in;
-    ps->outBuffer = out;
-    ps->bufSize = bufSize;
-    ps->frameSize = frameSize;
-    ps->framesPerBuffer = ps->bufSize / ps->frameSize;
-    ps->curBlock = 1;
-    ps->lastBlock = 0;
-    ps->index = 0;
-    
-    ps->hopSize = DEFHOPSIZE;
-    ps->windowSize = DEFWINDOWSIZE;
-    ps->fba = FBA;
-
-    tEnv_init(&ps->env, ps->windowSize, ps->hopSize, ps->frameSize);
-    
-    tSNAC_init(&ps->snac, DEFOVERLAP);
-    
-    tSOLAD_init(&ps->sola);
-    
-    tHighpass_init(&ps->hp, HPFREQ);
-    
-    tSOLAD_setPitchFactor(&ps->sola, DEFPITCHRATIO);
-    
-    tPitchShifter_setTimeConstant(ps, DEFTIMECONSTANT);
-}
-
-void tPitchShifter_free(tPitchShifter* const ps)
-{
-    tEnv_free(&ps->env);
-    tSNAC_free(&ps->snac);
-    tSOLAD_free(&ps->sola);
-    tHighpass_free(&ps->hp);
-}
-
-float tPitchShifter_tick(tPitchShifter* ps, float sample)
-{
-    float period, out;
-    int i, iLast;
-    
-    i = (ps->curBlock*ps->frameSize);
-    iLast = (ps->lastBlock*ps->frameSize)+ps->index;
-    
-    out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
-    ps->inBuffer[i+ps->index] = sample;
-    
-    ps->index++;
-    if (ps->index >= ps->frameSize)
-    {
-        ps->index = 0;
-        
-        tEnv_processBlock(&ps->env, &(ps->inBuffer[i]));
-        
-        if(pitchshifter_attackdetect(ps) == 1)
-        {
-            ps->fba = 5;
-            tSOLAD_setReadLag(&ps->sola, ps->windowSize);
-        }
-        
-        tSNAC_ioSamples(&ps->snac, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
-        period = tSNAC_getPeriod(&ps->snac);
-        
-        ps->curBlock++;
-        if (ps->curBlock >= ps->framesPerBuffer) ps->curBlock = 0;
-        ps->lastBlock++;
-        if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0;
-        
-        //separate here
-        
-        tSOLAD_setPeriod(&ps->sola, period);
-        
-        tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
-        tSOLAD_ioSamples(&ps->sola, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
-        
-    }
-    
-    return out;
-}
-
-float tPitchShifterToFreq_tick(tPitchShifter* ps, float sample, float freq)
-{
-    float period, out;
-    int i, iLast;
-    
-    i = (ps->curBlock*ps->frameSize);
-    iLast = (ps->lastBlock*ps->frameSize)+ps->index;
-    
-    out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
-    ps->inBuffer[i+ps->index] = sample;
-    
-    ps->index++;
-    if (ps->index >= ps->frameSize)
-    {
-        ps->index = 0;
-        
-        tEnv_processBlock(&ps->env, &(ps->inBuffer[i]));
-        
-        if(pitchshifter_attackdetect(ps) == 1)
-        {
-            ps->fba = 5;
-            tSOLAD_setReadLag(&ps->sola, ps->windowSize);
-        }
-        
-        tSNAC_ioSamples(&ps->snac, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
-        period = tSNAC_getPeriod(&ps->snac);
-        
-        tSOLAD_setPeriod(&ps->sola, period);
-        
-        ps->pitchFactor = period*freq*leaf.invSampleRate;
-        tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
-        tSOLAD_ioSamples(&ps->sola, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
-        
-        ps->curBlock++;
-        if (ps->curBlock >= ps->framesPerBuffer) ps->curBlock = 0;
-        ps->lastBlock++;
-        if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0;
-    }
-    
-    return out;
-}
-
-float tPitchShifterToFunc_tick(tPitchShifter* ps, float sample, float (*fun)(float))
-{
-    float period, out;
-    int i, iLast;
-    
-    i = (ps->curBlock*ps->frameSize);
-    iLast = (ps->lastBlock*ps->frameSize)+ps->index;
-    
-    out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
-    ps->inBuffer[i+ps->index] = sample;
-    
-    ps->index++;
-    if (ps->index >= ps->frameSize)
-    {
-        ps->index = 0;
-        
-        tEnv_processBlock(&ps->env, &(ps->inBuffer[i]));
-        
-        if(pitchshifter_attackdetect(ps) == 1)
-        {
-            ps->fba = 5;
-            tSOLAD_setReadLag(&ps->sola, ps->windowSize);
-        }
-        
-        tSNAC_ioSamples(&ps->snac, (&ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
-        period = tSNAC_getPeriod(&ps->snac);
-        
-        tSOLAD_setPeriod(&ps->sola, period);
-        
-        ps->pitchFactor = period/fun(period);
-        tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
-        tSOLAD_ioSamples(&ps->sola, &(ps->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
-        
-        ps->curBlock++;
-        if (ps->curBlock >= ps->framesPerBuffer) ps->curBlock = 0;
-        ps->lastBlock++;
-        if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0;
-    }
-    
-    return out;
-}
-
-void tPitchShifter_ioSamples(tPitchShifter* ps, float* in, float* out, int size)
-{
-    float period;
-    
-    tEnv_processBlock(&ps->env, in);
-    
-    if(pitchshifter_attackdetect(ps) == 1)
-    {
-        ps->fba = 5;
-        tSOLAD_setReadLag(&ps->sola, ps->windowSize);
-    }
-    
-    tSNAC_ioSamples(&ps->snac, in, out, size);
-    period = tSNAC_getPeriod(&ps->snac);
-    
-    tSOLAD_setPeriod(&ps->sola, period);
-    
-    tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
-    tSOLAD_ioSamples(&ps->sola, in, out, size);
-    
-    for (int cc = 0; cc < size; ++cc)
-    {
-        out[cc] = tHighpass_tick(&ps->hp, out[cc]);
-    }
-}
-
-void tPitchShifter_ioSamples_toFreq(tPitchShifter* ps, float* in, float* out, int size, float toFreq)
-{
-    float period;
-    
-    tEnv_processBlock(&ps->env, in);
-    
-    if(pitchshifter_attackdetect(ps) == 1)
-    {
-        ps->fba = 5;
-        tSOLAD_setReadLag(&ps->sola, ps->windowSize);
-    }
-    
-    tSNAC_ioSamples(&ps->snac, in, out, size);
-    period = tSNAC_getPeriod(&ps->snac);
-    
-    tSOLAD_setPeriod(&ps->sola, period);
-    ps->pitchFactor = period*toFreq;
-    tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
-    tSOLAD_ioSamples(&ps->sola, in, out, size);
-    
-    for (int cc = 0; cc < size; ++cc)
-    {
-        out[cc] = tHighpass_tick(&ps->hp, out[cc]);
-    }
-}
-
-void tPitchShifter_ioSamples_toPeriod(tPitchShifter* ps, float* in, float* out, int size, float toPeriod)
-{
-    float period;
-    
-    tEnv_processBlock(&ps->env, in);
-    
-    if(pitchshifter_attackdetect(ps) == 1)
-    {
-        ps->fba = 5;
-        tSOLAD_setReadLag(&ps->sola, ps->windowSize);
-    }
-    
-    tSNAC_ioSamples(&ps->snac, in, out, size);
-    period = tSNAC_getPeriod(&ps->snac);
-    
-    tSOLAD_setPeriod(&ps->sola, period);
-    ps->pitchFactor = period/toPeriod;
-    tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
-    tSOLAD_ioSamples(&ps->sola, in, out, size);
-    
-    for (int cc = 0; cc < size; ++cc)
-    {
-        out[cc] = tHighpass_tick(&ps->hp, out[cc]);
-    }
-}
-
-void tPitchShifter_ioSamples_toFunc(tPitchShifter* ps, float* in, float* out, int size, float (*fun)(float))
-{
-    float period;
-    
-    tEnv_processBlock(&ps->env, in);
-    
-    if(pitchshifter_attackdetect(ps) == 1)
-    {
-        ps->fba = 5;
-        tSOLAD_setReadLag(&ps->sola, ps->windowSize);
-    }
-    
-    tSNAC_ioSamples(&ps->snac, in, out, size);
-    period = tSNAC_getPeriod(&ps->snac);
-    
-    tSOLAD_setPeriod(&ps->sola, period);
-    ps->pitchFactor = period/fun(period);
-    tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
-    tSOLAD_ioSamples(&ps->sola, in, out, size);
-    
-    for (int cc = 0; cc < size; ++cc)
-    {
-        out[cc] = tHighpass_tick(&ps->hp, out[cc]);
-    }
-}
-
-void tPitchShifter_setPitchFactor(tPitchShifter* ps, float pf)
-{
-    ps->pitchFactor = pf;
-}
-
-void tPitchShifter_setTimeConstant(tPitchShifter* ps, float tc)
-{
-    ps->timeConstant = tc;
-    ps->radius = expf(-1000.0f * ps->hopSize * leaf.invSampleRate / ps->timeConstant);
-}
-
-void tPitchShifter_setHopSize(tPitchShifter* ps, int hs)
-{
-    ps->hopSize = hs;
-}
-
-void tPitchShifter_setWindowSize(tPitchShifter* ps, int ws)
-{
-    ps->windowSize = ws;
-}
-
-float tPitchShifter_getPeriod(tPitchShifter* ps)
-{
-    return tSNAC_getPeriod(&ps->snac);
-}
-
-static int pitchshifter_attackdetect(tPitchShifter* ps)
-{
-    float envout;
-    
-    envout = tEnv_tick(&ps->env);
-    
-    if (envout >= 1.0f)
-    {
-        ps->lastmax = ps->max;
-        if (envout > ps->max)
-        {
-            ps->max = envout;
-        }
-        else
-        {
-            ps->deltamax = envout - ps->max;
-            ps->max = ps->max * ps->radius;
-        }
-        ps->deltamax = ps->max - ps->lastmax;
-    }
-    
-    ps->fba = ps->fba ? (ps->fba - 1) : 0;
-    
-    return (ps->fba == 0 && (ps->max > 60 && ps->deltamax > 6)) ? 1 : 0;
-}
-
-
-void     tPeriod_init    (tPeriod* const p, float* in, float* out, int bufSize, int frameSize)
-{
-    p->inBuffer = in;
-    p->outBuffer = out;
-    p->bufSize = bufSize;
-    p->frameSize = frameSize;
-    p->framesPerBuffer = p->bufSize / p->frameSize;
-    p->curBlock = 1;
-    p->lastBlock = 0;
-    p->index = 0;
-    
-    p->hopSize = DEFHOPSIZE;
-    p->windowSize = DEFWINDOWSIZE;
-    p->fba = FBA;
-    
-    tEnv_init(&p->env, p->windowSize, p->hopSize, p->frameSize);
-    
-    tSNAC_init(&p->snac, DEFOVERLAP);
-    
-    p->timeConstant = DEFTIMECONSTANT;
-    p->radius = expf(-1000.0f * p->hopSize * leaf.invSampleRate / p->timeConstant);
-}
-
-void tPeriod_free (tPeriod* const p)
-{
-    tEnv_free(&p->env);
-    tSNAC_free(&p->snac);
-}
-
-float tPeriod_findPeriod (tPeriod* p, float sample)
-{
-    int i, iLast;
-    
-    i = (p->curBlock*p->frameSize);
-    iLast = (p->lastBlock*p->frameSize)+p->index;
-    
-    p->i = i;
-    p->iLast = iLast;
-    
-    p->inBuffer[i+p->index] = sample;
-    
-    p->index++;
-    p->indexstore = p->index;
-    if (p->index >= p->frameSize)
-    {
-        p->index = 0;
-        
-        tEnv_processBlock(&p->env, &(p->inBuffer[i]));
-        
-        tSNAC_ioSamples(&p->snac, &(p->inBuffer[i]), &(p->outBuffer[i]), p->frameSize);
-        p->period = tSNAC_getPeriod(&p->snac);
-        
-        p->curBlock++;
-        if (p->curBlock >= p->framesPerBuffer) p->curBlock = 0;
-        p->lastBlock++;
-        if (p->lastBlock >= p->framesPerBuffer) p->lastBlock = 0;
-    }
-    
-    // changed from period to p->period
-    return p->period;
-}
-
-void tPeriod_setHopSize(tPeriod* p, int hs)
-{
-    p->hopSize = hs;
-}
-
-void tPeriod_setWindowSize(tPeriod* p, int ws)
-{
-    p->windowSize = ws;
-}
-
-void tPitchShift_setPitchFactor(tPitchShift* ps, float pf)
-{
-    ps->pitchFactor = pf;
-}
-
-static int pitchshift_attackdetect(tPitchShift* ps)
-{
-    float envout;
-    
-    envout = tEnv_tick(&ps->p->env);
-    
-    if (envout >= 1.0f)
-    {
-        ps->p->lastmax = ps->p->max;
-        if (envout > ps->p->max)
-        {
-            ps->p->max = envout;
-        }
-        else
-        {
-            ps->p->deltamax = envout - ps->p->max;
-            ps->p->max = ps->p->max * ps->radius;
-        }
-        ps->p->deltamax = ps->p->max - ps->p->lastmax;
-    }
-    
-    ps->p->fba = ps->p->fba ? (ps->p->fba - 1) : 0;
-    
-    return (ps->p->fba == 0 && (ps->p->max > 60 && ps->p->deltamax > 6)) ? 1 : 0;
-}
-
-void tPitchShift_init (tPitchShift* const ps, tPeriod* p, float* out, int bufSize)
-{
-    ps->p = p;
-    
-    ps->outBuffer = out;
-    ps->bufSize = bufSize;
-    ps->frameSize = p->frameSize;
-    ps->framesPerBuffer = ps->bufSize / ps->frameSize;
-    ps->curBlock = 1;
-    ps->lastBlock = 0;
-    ps->index = 0;
-    ps->pitchFactor = 1.0f;
-    
-    tSOLAD_init(&ps->sola);
-    
-    tHighpass_init(&ps->hp, HPFREQ);
-    
-    tSOLAD_setPitchFactor(&ps->sola, DEFPITCHRATIO);
-}
-
-void tPitchShift_free(tPitchShift* const ps)
-{
-    tSOLAD_free(&ps->sola);
-    tHighpass_free(&ps->hp);
-}
-
-float tPitchShift_shift (tPitchShift* ps)
-{
-    float period, out;
-    int i, iLast;
-    
-    i = ps->p->i;
-    iLast = ps->p->iLast;
-    
-    out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
-    
-    if (ps->p->indexstore >= ps->frameSize)
-    {
-        period = ps->p->period;
-        
-        if(pitchshift_attackdetect(ps) == 1)
-        {
-            ps->p->fba = 5;
-            tSOLAD_setReadLag(&ps->sola, ps->p->windowSize);
-        }
-        
-        tSOLAD_setPeriod(&ps->sola, period);
-        tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
-        
-        tSOLAD_ioSamples(&ps->sola, &(ps->p->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
-    }
-    
-    return out;
-}
-
-float tPitchShift_shiftToFreq (tPitchShift* ps, float freq)
-{
-    float period, out;
-    int i, iLast;
-    
-    i = ps->p->i;
-    iLast = ps->p->iLast;
-    
-    out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
-    
-    if (ps->p->indexstore >= ps->frameSize)
-    {
-        period = ps->p->period;
-        
-        if(pitchshift_attackdetect(ps) == 1)
-        {
-            ps->p->fba = 5;
-            tSOLAD_setReadLag(&ps->sola, ps->p->windowSize);
-        }
-        
-        tSOLAD_setPeriod(&ps->sola, period);
-        
-        ps->pitchFactor = period*freq*leaf.invSampleRate;
-        tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
-        
-        tSOLAD_ioSamples(&ps->sola, &(ps->p->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
-    }
-    return out;
-}
-
-float tPitchShift_shiftToFunc (tPitchShift* ps, float (*fun)(float))
-{
-    float period, out;
-    int i, iLast;
-    
-    i = ps->p->i;
-    iLast = ps->p->iLast;
-    
-    out = tHighpass_tick(&ps->hp, ps->outBuffer[iLast]);
-    
-    if (ps->p->indexstore >= ps->frameSize)
-    {
-        period = ps->p->period;
-        
-        if(pitchshift_attackdetect(ps) == 1)
-        {
-            ps->p->fba = 5;
-            tSOLAD_setReadLag(&ps->sola, ps->p->windowSize);
-        }
-        
-        tSOLAD_setPeriod(&ps->sola, period);
-        
-        ps->pitchFactor = period/fun(period);
-        tSOLAD_setPitchFactor(&ps->sola, ps->pitchFactor);
-        
-        tSOLAD_ioSamples(&ps->sola, &(ps->p->inBuffer[i]), &(ps->outBuffer[i]), ps->frameSize);
-        
-        ps->curBlock++;
-        if (ps->curBlock >= ps->p->framesPerBuffer) ps->curBlock = 0;
-        ps->lastBlock++;
-        if (ps->lastBlock >= ps->framesPerBuffer) ps->lastBlock = 0;
-    }
-    
-    return out;
-}
--- a/LEAF/Src/leaf-reverb.c
+++ b/LEAF/Src/leaf-reverb.c
@@ -18,8 +18,8 @@
 
 #endif
 
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ PRCRev ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
-void    tPRCRev_init(tPRCRev* const r, float t60)
+// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ PRCReverb ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
+void    tPRCReverb_init(tPRCReverb* const r, float t60)
 {
     if (t60 <= 0.0f) t60 = 0.001f;
     
@@ -47,13 +47,13 @@
     tDelay_init(&r->allpassDelays[1], lengths[1], lengths[1] * 2);
     tDelay_init(&r->combDelay, lengths[2], lengths[2] * 2);
     
-    tPRCRev_setT60(r, t60);
+    tPRCReverb_setT60(r, t60);
     
     r->allpassCoeff = 0.7f;
     r->mix = 0.5f;
 }
 
-void tPRCRev_free(tPRCRev* const r)
+void tPRCReverb_free(tPRCReverb* const r)
 {
     tDelay_free(&r->allpassDelays[0]);
     tDelay_free(&r->allpassDelays[1]);
@@ -60,7 +60,7 @@
     tDelay_free(&r->combDelay);
 }
 
-void    tPRCRev_setT60(tPRCRev* const r, float t60)
+void    tPRCReverb_setT60(tPRCReverb* const r, float t60)
 {
     if ( t60 <= 0.0f ) t60 = 0.001f;
     
@@ -70,12 +70,12 @@
     
 }
 
-void    tPRCRev_setMix(tPRCRev* const r, float mix)
+void    tPRCReverb_setMix(tPRCReverb* const r, float mix)
 {
     r->mix = mix;
 }
 
-float   tPRCRev_tick(tPRCRev* const r, float input)
+float   tPRCReverb_tick(tPRCReverb* const r, float input)
 {
     float temp, temp0, temp1, temp2;
     float out;
@@ -107,13 +107,13 @@
     return out;
 }
 
-void     tPRCRevSampleRateChanged (tPRCRev* const r)
+void     tPRCReverbSampleRateChanged (tPRCReverb* const r)
 {
     r->combCoeff = pow(10.0f, (-3.0f * tDelay_getDelay(&r->combDelay) * leaf.invSampleRate / r->t60 ));
 }
 
-/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ NRev ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
-void    tNRev_init(tNRev* const r, float t60)
+/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ NReverb ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
+void    tNReverb_init(tNReverb* const r, float t60)
 {
     if (t60 <= 0.0f) t60 = 0.001f;
     
@@ -150,12 +150,12 @@
         tDelay_setDelay(&r->combDelays[i], lengths[i+2]);
     }
     
-    tNRev_setT60(r, t60);
+    tNReverb_setT60(r, t60);
     r->allpassCoeff = 0.7f;
     r->mix = 0.3f;
 }
 
-void    tNRev_free(tNRev* const r)
+void    tNReverb_free(tNReverb* const r)
 {
     for (int i = 0; i < 6; i++)
     {
@@ -168,7 +168,7 @@
     }
 }
 
-void    tNRev_setT60(tNRev* const r, float t60)
+void    tNReverb_setT60(tNReverb* const r, float t60)
 {
     if (t60 <= 0.0f)           t60 = 0.001f;
     
@@ -178,12 +178,12 @@
     
 }
 
-void    tNRev_setMix(tNRev* const r, float mix)
+void    tNReverb_setMix(tNReverb* const r, float mix)
 {
     r->mix = mix;
 }
 
-float   tNRev_tick(tNRev* const r, float input)
+float   tNReverb_tick(tNReverb* const r, float input)
 {
     r->lastIn = input;
     
@@ -221,10 +221,10 @@
     out = r->mix * ( -( r->allpassCoeff * temp2 ) + temp );
     
     /*
-     temp = tDelayLGetLastOut(&r->allpassDelays[5]);
+     temp = tLinearDelayGetLastOut(&r->allpassDelays[5]);
      temp3 = r->allpassCoeff * temp;
      temp3 += temp1;
-     tDelayLTick(&r->allpassDelays[5], temp3 );
+     tLinearDelayTick(&r->allpassDelays[5], temp3 );
      lastFrame_[1] = effectMix_*( - ( r->allpassCoeff * temp3 ) + temp );
      */
     
@@ -237,7 +237,7 @@
     return out;
 }
 
-void     tNRevSampleRateChanged (tNRev* const r)
+void     tNReverbSampleRateChanged (tNReverb* const r)
 {
     for (int i=0; i<6; i++)   r->combCoeffs[i] = pow(10.0, (-3.0 * tDelay_getDelay(&r->combDelays[i]) * leaf.invSampleRate / r->t60 ));
 }
@@ -250,7 +250,7 @@
 float       in_allpass_gains[4] = { 0.75f, 0.75f, 0.625f, 0.625f };
 
 
-void    tDattorro_init              (tDattorro* const r)
+void    tDattorroReverb_init              (tDattorroReverb* const r)
 {
     r->size_max = 2.0f;
     r->size = 1.f;
@@ -298,20 +298,20 @@
     
     
     // PARAMETERS
-    tDattorro_setMix(r, 0.5f);
+    tDattorroReverb_setMix(r, 0.5f);
     
-    tDattorro_setInputDelay(r,  0.f);
+    tDattorroReverb_setInputDelay(r,  0.f);
     
-    tDattorro_setInputFilter(r, 10000.f);
+    tDattorroReverb_setInputFilter(r, 10000.f);
     
-    tDattorro_setFeedbackFilter(r, 5000.f);
+    tDattorroReverb_setFeedbackFilter(r, 5000.f);
     
-    tDattorro_setFeedbackGain(r, 0.4f);
+    tDattorroReverb_setFeedbackGain(r, 0.4f);
     
     
 }
 
-void    tDattorro_free              (tDattorro* const r)
+void    tDattorroReverb_free              (tDattorroReverb* const r)
 {
     // INPUT
     tTapeDelay_free(&r->in_delay);
@@ -349,7 +349,7 @@
     tCycle_free(&r->f2_lfo);
 }
 
-float   tDattorro_tick              (tDattorro* const r, float input)
+float   tDattorroReverb_tick              (tDattorroReverb* const r, float input)
 {
     // INPUT
     float in_sample = tTapeDelay_tick(&r->in_delay, input);
@@ -449,12 +449,12 @@
     return (input * (1.0f - r->mix) + sample * r->mix);
 }
 
-void    tDattorro_setMix            (tDattorro* const r, float mix)
+void    tDattorroReverb_setMix            (tDattorroReverb* const r, float mix)
 {
     r->mix = LEAF_clip(0.0f, mix, 1.0f);
 }
 
-void    tDattorro_setSize           (tDattorro* const r, float size)
+void    tDattorroReverb_setSize           (tDattorroReverb* const r, float size)
 {
     r->size = LEAF_clip(0.01f, size*r->size_max, r->size_max);
     r->t = r->size * leaf.sampleRate * 0.001f;
@@ -483,7 +483,7 @@
     tTapeDelay_setDelay(&r->f2_delay_3, SAMP(106.28f));
 }
 
-void    tDattorro_setInputDelay     (tDattorro* const r, float preDelay)
+void    tDattorroReverb_setInputDelay     (tDattorroReverb* const r, float preDelay)
 {
     r->predelay = LEAF_clip(0.0f, preDelay, 200.0f);
     
@@ -490,7 +490,7 @@
     tTapeDelay_setDelay(&r->in_delay, SAMP(r->predelay));
 }
 
-void    tDattorro_setInputFilter    (tDattorro* const r, float freq)
+void    tDattorroReverb_setInputFilter    (tDattorroReverb* const r, float freq)
 {
     r->input_filter = LEAF_clip(0.0f, freq, 20000.0f);
     
@@ -497,7 +497,7 @@
     tOnePole_setFreq(&r->in_filter, r->input_filter);
 }
 
-void    tDattorro_setFeedbackFilter (tDattorro* const r, float freq)
+void    tDattorroReverb_setFeedbackFilter (tDattorroReverb* const r, float freq)
 {
     r->feedback_filter = LEAF_clip(0.0f, freq, 20000.0f);
     
@@ -505,7 +505,7 @@
     tOnePole_setFreq(&r->f2_filter, r->feedback_filter);
 }
 
-void    tDattorro_setFeedbackGain   (tDattorro* const r, float gain)
+void    tDattorroReverb_setFeedbackGain   (tDattorroReverb* const r, float gain)
 {
     r->feedback_gain = gain;
 }
--- a/LEAF/Src/leaf-sample.c
+++ /dev/null
@@ -1,436 +1,0 @@
-/*
-  ==============================================================================
-
-    leaf-sample.c
-    Created: 20 Jan 2017 12:02:17pm
-    Author:  Michael R Mulshine
-
-  ==============================================================================
-*/
-
-
-#if _WIN32 || _WIN64
-
-#include "..\Inc\leaf-sample.h"
-#include "..\leaf.h"
-
-#else
-
-#include "../Inc/leaf-sample.h"
-#include "../leaf.h"
-
-#endif
-
-//==============================================================================
-
-void  tBuffer_init (tBuffer* const s, uint32_t length)
-{
-    s->buff = (float*) leaf_alloc( sizeof(float) * length);
-    
-    
-    s->length = length;
-    s->active = 0;
-    s->idx = 0;
-    s->mode = RecordOneShot;
-    
-    tBuffer_clear(s);
-}
-
-void  tBuffer_free (tBuffer* const s)
-{
-    leaf_free(s->buff);
-}
-
-void tBuffer_tick (tBuffer* const s, float sample)
-{
-    if (s->active == 1)
-    {
-        s->buff[s->idx] = sample;
-        
-        s->idx += 1;
-        
-        if (s->idx >= s->length)
-        {
-            if (s->mode == RecordOneShot)
-            {
-                tBuffer_stop(s);
-            }
-            else if (s->mode == RecordLoop)
-            {
-                s->idx = 0;
-            }
-        }
-    }
-}
-
-void  tBuffer_read(tBuffer* const s, float* buff, uint32_t len)
-{
-    for (int i = 0; i < s->length; i++)
-    {
-        if (i < len)    s->buff[i] = buff[i];
-        else            s->buff[i] = 0.f;
-    }
-}
-
-float tBuffer_get (tBuffer* const s, int idx)
-{
-    if ((idx < 0) || (idx >= s->length)) return 0.f;
-    
-    return s->buff[idx];
-}
-
-void  tBuffer_record(tBuffer* const s)
-{
-    s->active = 1;
-    s->idx = 0;
-}
-
-void  tBuffer_stop(tBuffer* const s)
-{
-    s->active = 0;
-}
-
-void  tBuffer_setRecordMode (tBuffer* const s, RecordMode mode)
-{
-    s->mode = mode;
-}
-
-void  tBuffer_clear (tBuffer* const s)
-{
-    for (int i = 0; i < s->length; i++)
-    {
-        s->buff[i] = 0.f;
-    }
-}
-
-//================================tSampler=====================================
-
-void tSampler_init(tSampler* const p, tBuffer* const s)
-{
-    p->samp = s;
-    
-    p->active = 0;
-    
-    p->start = 0;
-    p->end = p->samp->length - 1;
-    
-    p->len = p->end - p->start;
-    
-    p->idx = 0.f;
-    p->inc = 1.f;
-    p->iinc = 1.f;
-    
-    p->dir = 1;
-    p->flip = 1;
-    p->bnf = 1;
-    
-    p->mode = PlayNormal;
-    
-    p->cfxlen = 500; // default 300 sample crossfade
-    
-    tRamp_init(&p->gain, 7.0f, 1);
-    tRamp_setVal(&p->gain, 0.f);
-}
-
-void tSampler_free         (tSampler* const p)
-{
-    tRamp_free(&p->gain);
-}
-
-float tSampler_tick        (tSampler* const p)
-{
-    if (p->active == 0)         return 0.f;
-
-    if ((p->inc == 0.0f) || (p->len < 4))
-    {
-    	return p->last;
-    }
-
-    float sample = 0.f;
-    float cfxsample = 0.f;
-    int numsamps;
-    float g1 = 1.f, g2 = 0.f;
-    
-    float* buff = p->samp->buff;
-    
-    int dir = p->bnf * p->dir * p->flip;
-    
-    int idx;
-    float alpha;
-
-    if (dir > 0)
-    {
-    	idx = (int) p->idx;
-    	alpha = p->idx - idx;
-    }
-    else
-    {
-    	idx = (int) (p->idx+1.f); // we think this is because flooring on int works different when reading backwards
-    	alpha = (p->idx+1.f) - idx;
-    }
-    
-    int32_t start = p->start, end = p->end;
-    if (p->flip < 0)
-    {
-        start = p->end;
-        end = p->start;
-    }
-    
-    // Check dir (direction) to interpolate properly
-    if (dir > 0)
-    {
-        // FORWARD NORMAL SAMPLE
-        int i1 = ((idx-1) + p->len) % p->len;
-        int i3 = (idx+1) % p->len;
-        int i4 = (idx+2) % p->len;
-
-        sample =     LEAF_interpolate_hermite (buff[i1],
-                                               buff[idx],
-                                               buff[i3],
-                                               buff[i4],
-                                               alpha);
-        
-        // num samples to end of loop
-        numsamps = (idx - start) / p->inc;
-        //numsamps = (dir > 0) ? (end - idx) : (idx - start);
-        //numsamps *= p->iinc;
-        
-        if (p->mode == PlayLoop)
-        {
-            if (numsamps <= p->cfxlen)
-            {
-                // CROSSFADE SAMPLE
-                float idxx =  p->idx - p->len;
-                int cdx = ((int)(idxx) + p->len) % p->len;
-                
-                i1 = ((cdx-1) + p->len) % p->len;
-                i3 = (cdx+1) % p->len;
-                i4 = (cdx+2) % p->len;
-                
-                cfxsample =     LEAF_interpolate_hermite (buff[i1],
-                                                          buff[cdx],
-                                                          buff[i3],
-                                                          buff[i4],
-                                                          alpha);
-                
-                g2 = (float) (p->cfxlen - numsamps) / (float) p->cfxlen;
-            }
-        }
-    }
-    else
-    {
-        // REVERSE
-        int i1 = (idx+1) % p->len;
-        int i3 = ((idx-1) + p->len) % p->len;
-        int i4 = ((idx-2) + p->len) % p->len;
-    
-        sample =     LEAF_interpolate_hermite (buff[i1],
-                                               buff[idx],
-                                               buff[i3],
-                                               buff[i4],
-                                               1.0f-alpha);
-        
-        numsamps = (idx - start) / p->inc;
-        
-        if (p->mode == PlayLoop)
-        {
-            if (numsamps <= p->cfxlen)
-            {
-                // CROSSFADE SAMPLE
-                float idxx =  p->idx + p->len + 1.f;
-                int cdx = ((int)(idxx)) % p->len;
-                alpha = idxx - cdx;
-                
-                i1 = (cdx+1) % p->len;
-                i3 = ((cdx-1) + p->len) % p->len;
-                i4 = ((cdx-2) + p->len) % p->len;
-                
-                cfxsample =     LEAF_interpolate_hermite (buff[i1],
-                                                          buff[cdx],
-                                                          buff[i3],
-                                                          buff[i4],
-                                                          1.f-alpha);
-                
-                g2 = (float) (p->cfxlen - numsamps) / (float) p->cfxlen;
-            }
-        }
-    }
-    
-    p->idx += (dir * p->inc);
-    
-    if (p->mode == PlayNormal)
-    {
-        if (numsamps < (0.007f * leaf.sampleRate))
-        {
-            tRamp_setDest(&p->gain, 0.f);
-            p->active = -1;
-        }
-    }
-    else if (p->mode == PlayLoop )
-    {
-        if (idx <= start)
-        {
-            p->idx += (float)(p->len);
-        }
-        else if (idx >= end)
-        {
-            p->idx -= (float)(p->len);
-        }
-    }
-    else // == PlayBackAndForth
-    {
-        if (p->idx < start)
-        {
-            p->bnf = -p->bnf;
-            p->idx = start;
-        }
-        else if (p->idx > end)
-        {
-            p->bnf = -p->bnf;
-            p->idx = end;
-        }
-    }
-
-    g1 = 1.f - g2;
-    
-    sample = sample * g1 + cfxsample * g2;
-    
-    sample = sample * tRamp_tick(&p->gain);
-    
-    if (p->active < 0)
-    {
-        if (tRamp_sample(&p->gain) <= 0.00001f)
-        {
-            if (p->retrigger == 1)
-            {
-                p->active = 1;
-                p->retrigger = 0;
-                tRamp_setDest(&p->gain, 1.f);
-                
-                if (p->dir > 0)
-                {
-                    if (p->flip > 0)    p->idx = p->start;
-                    else                p->idx = p->end;
-                }
-                else
-                {
-                    if (p->flip > 0)    p->idx = p->end;
-                    else                p->idx = p->start;
-                }
-            }
-            else
-            {
-                p->active = 0;
-            }
-            
-        }
-    }
-    
-    p->last = sample;
-
-    return p->last;
-}
-
-void tSampler_setSample    (tSampler* const p, tBuffer* s)
-{
-    p->samp = s;
-}
-
-void tSampler_setMode      (tSampler* const p, PlayMode mode)
-{
-    p->mode = mode;
-}
-
-void tSampler_setCrossfadeLength  (tSampler* const p, uint32_t length)
-{
-    uint32_t cfxlen = LEAF_clip(0, length, 1000);
-    
-    //if (cfxlen > p->len)  cfxlen = p->len * 0.25f;
-    
-    p->cfxlen = cfxlen;
-}
-
-void tSampler_play         (tSampler* const p)
-{
-    if (p->active != 0)
-    {
-        p->active = -1;
-        p->retrigger = 1;
-        
-        tRamp_setDest(&p->gain, 0.f);
-    }
-    else
-    {
-        p->active = 1;
-        p->retrigger = 0;
-        
-        tRamp_setDest(&p->gain, 1.f);
-        
-        if (p->dir > 0)
-        {
-            if (p->flip > 0)    p->idx = p->start;
-            else                p->idx = p->end;
-        }
-        else
-        {
-            if (p->flip > 0)    p->idx = p->end;
-            else                p->idx = p->start;
-        }
-    }
-}
-
-void tSampler_stop         (tSampler* const p)
-{
-    p->active = -1;
-    
-    tRamp_setDest(&p->gain, 0.f);
-}
-
-static void handleStartEndChange(tSampler* const p)
-{
-    p->len = abs(p->end - p->start);
-    
-    //if (p->len < p->cfxlen) p->cfxlen = p->len * 0.9f;
-    
-    if (p->start > p->end)
-    {
-        p->flip = -1;
-    }
-    else
-    {
-        p->flip = 1;
-    }
-}
-
-void tSampler_setStart     (tSampler* const p, int32_t start)
-{
-    p->start = LEAF_clipInt(0, start, (p->samp->length - 1));
-    
-    handleStartEndChange(p);
-}
-
-void tSampler_setEnd       (tSampler* const p, int32_t end)
-{
-    p->end = LEAF_clipInt(0, end, (p->samp->length - 1));
-    
-    handleStartEndChange(p);
-}
-
-void tSampler_setRate      (tSampler* const p, float rate)
-{
-    if (rate < 0.f)
-    {
-        rate = -rate;
-        p->dir = -1;
-    }
-    else
-    {
-        p->dir = 1;
-    }
-    
-    p->inc = LEAF_clip(0.f, rate, 8.0f);
-    p->iinc = 1.f / p->inc;
-}
-
-
-//==============================================================================
--- /dev/null
+++ b/LEAF/Src/leaf-sampling.c
@@ -1,0 +1,436 @@
+/*
+  ==============================================================================
+
+    leaf-sampling.c
+    Created: 20 Jan 2017 12:02:17pm
+    Author:  Michael R Mulshine
+
+  ==============================================================================
+*/
+
+
+#if _WIN32 || _WIN64
+
+#include "..\Inc\leaf-sampling.h"
+#include "..\leaf.h"
+
+#else
+
+#include "../Inc/leaf-sampling.h"
+#include "../leaf.h"
+
+#endif
+
+//==============================================================================
+
+void  tBuffer_init (tBuffer* const s, uint32_t length)
+{
+    s->buff = (float*) leaf_alloc( sizeof(float) * length);
+    
+    
+    s->length = length;
+    s->active = 0;
+    s->idx = 0;
+    s->mode = RecordOneShot;
+    
+    tBuffer_clear(s);
+}
+
+void  tBuffer_free (tBuffer* const s)
+{
+    leaf_free(s->buff);
+}
+
+void tBuffer_tick (tBuffer* const s, float sample)
+{
+    if (s->active == 1)
+    {
+        s->buff[s->idx] = sample;
+        
+        s->idx += 1;
+        
+        if (s->idx >= s->length)
+        {
+            if (s->mode == RecordOneShot)
+            {
+                tBuffer_stop(s);
+            }
+            else if (s->mode == RecordLoop)
+            {
+                s->idx = 0;
+            }
+        }
+    }
+}
+
+void  tBuffer_read(tBuffer* const s, float* buff, uint32_t len)
+{
+    for (int i = 0; i < s->length; i++)
+    {
+        if (i < len)    s->buff[i] = buff[i];
+        else            s->buff[i] = 0.f;
+    }
+}
+
+float tBuffer_get (tBuffer* const s, int idx)
+{
+    if ((idx < 0) || (idx >= s->length)) return 0.f;
+    
+    return s->buff[idx];
+}
+
+void  tBuffer_record(tBuffer* const s)
+{
+    s->active = 1;
+    s->idx = 0;
+}
+
+void  tBuffer_stop(tBuffer* const s)
+{
+    s->active = 0;
+}
+
+void  tBuffer_setRecordMode (tBuffer* const s, RecordMode mode)
+{
+    s->mode = mode;
+}
+
+void  tBuffer_clear (tBuffer* const s)
+{
+    for (int i = 0; i < s->length; i++)
+    {
+        s->buff[i] = 0.f;
+    }
+}
+
+//================================tSampler=====================================
+
+void tSampler_init(tSampler* const p, tBuffer* const s)
+{
+    p->samp = s;
+    
+    p->active = 0;
+    
+    p->start = 0;
+    p->end = p->samp->length - 1;
+    
+    p->len = p->end - p->start;
+    
+    p->idx = 0.f;
+    p->inc = 1.f;
+    p->iinc = 1.f;
+    
+    p->dir = 1;
+    p->flip = 1;
+    p->bnf = 1;
+    
+    p->mode = PlayNormal;
+    
+    p->cfxlen = 500; // default 300 sample crossfade
+    
+    tRamp_init(&p->gain, 7.0f, 1);
+    tRamp_setVal(&p->gain, 0.f);
+}
+
+void tSampler_free         (tSampler* const p)
+{
+    tRamp_free(&p->gain);
+}
+
+float tSampler_tick        (tSampler* const p)
+{
+    if (p->active == 0)         return 0.f;
+
+    if ((p->inc == 0.0f) || (p->len < 4))
+    {
+    	return p->last;
+    }
+
+    float sample = 0.f;
+    float cfxsample = 0.f;
+    int numsamps;
+    float g1 = 1.f, g2 = 0.f;
+    
+    float* buff = p->samp->buff;
+    
+    int dir = p->bnf * p->dir * p->flip;
+    
+    int idx;
+    float alpha;
+
+    if (dir > 0)
+    {
+    	idx = (int) p->idx;
+    	alpha = p->idx - idx;
+    }
+    else
+    {
+    	idx = (int) (p->idx+1.f); // we think this is because flooring on int works different when reading backwards
+    	alpha = (p->idx+1.f) - idx;
+    }
+    
+    int32_t start = p->start, end = p->end;
+    if (p->flip < 0)
+    {
+        start = p->end;
+        end = p->start;
+    }
+    
+    // Check dir (direction) to interpolate properly
+    if (dir > 0)
+    {
+        // FORWARD NORMAL SAMPLE
+        int i1 = ((idx-1) + p->len) % p->len;
+        int i3 = (idx+1) % p->len;
+        int i4 = (idx+2) % p->len;
+
+        sample =     LEAF_interpolate_hermite (buff[i1],
+                                               buff[idx],
+                                               buff[i3],
+                                               buff[i4],
+                                               alpha);
+        
+        // num samples to end of loop
+        numsamps = (idx - start) / p->inc;
+        //numsamps = (dir > 0) ? (end - idx) : (idx - start);
+        //numsamps *= p->iinc;
+        
+        if (p->mode == PlayLoop)
+        {
+            if (numsamps <= p->cfxlen)
+            {
+                // CROSSFADE SAMPLE
+                float idxx =  p->idx - p->len;
+                int cdx = ((int)(idxx) + p->len) % p->len;
+                
+                i1 = ((cdx-1) + p->len) % p->len;
+                i3 = (cdx+1) % p->len;
+                i4 = (cdx+2) % p->len;
+                
+                cfxsample =     LEAF_interpolate_hermite (buff[i1],
+                                                          buff[cdx],
+                                                          buff[i3],
+                                                          buff[i4],
+                                                          alpha);
+                
+                g2 = (float) (p->cfxlen - numsamps) / (float) p->cfxlen;
+            }
+        }
+    }
+    else
+    {
+        // REVERSE
+        int i1 = (idx+1) % p->len;
+        int i3 = ((idx-1) + p->len) % p->len;
+        int i4 = ((idx-2) + p->len) % p->len;
+    
+        sample =     LEAF_interpolate_hermite (buff[i1],
+                                               buff[idx],
+                                               buff[i3],
+                                               buff[i4],
+                                               1.0f-alpha);
+        
+        numsamps = (idx - start) / p->inc;
+        
+        if (p->mode == PlayLoop)
+        {
+            if (numsamps <= p->cfxlen)
+            {
+                // CROSSFADE SAMPLE
+                float idxx =  p->idx + p->len + 1.f;
+                int cdx = ((int)(idxx)) % p->len;
+                alpha = idxx - cdx;
+                
+                i1 = (cdx+1) % p->len;
+                i3 = ((cdx-1) + p->len) % p->len;
+                i4 = ((cdx-2) + p->len) % p->len;
+                
+                cfxsample =     LEAF_interpolate_hermite (buff[i1],
+                                                          buff[cdx],
+                                                          buff[i3],
+                                                          buff[i4],
+                                                          1.f-alpha);
+                
+                g2 = (float) (p->cfxlen - numsamps) / (float) p->cfxlen;
+            }
+        }
+    }
+    
+    p->idx += (dir * p->inc);
+    
+    if (p->mode == PlayNormal)
+    {
+        if (numsamps < (0.007f * leaf.sampleRate))
+        {
+            tRamp_setDest(&p->gain, 0.f);
+            p->active = -1;
+        }
+    }
+    else if (p->mode == PlayLoop )
+    {
+        if (idx <= start)
+        {
+            p->idx += (float)(p->len);
+        }
+        else if (idx >= end)
+        {
+            p->idx -= (float)(p->len);
+        }
+    }
+    else // == PlayBackAndForth
+    {
+        if (p->idx < start)
+        {
+            p->bnf = -p->bnf;
+            p->idx = start;
+        }
+        else if (p->idx > end)
+        {
+            p->bnf = -p->bnf;
+            p->idx = end;
+        }
+    }
+
+    g1 = 1.f - g2;
+    
+    sample = sample * g1 + cfxsample * g2;
+    
+    sample = sample * tRamp_tick(&p->gain);
+    
+    if (p->active < 0)
+    {
+        if (tRamp_sample(&p->gain) <= 0.00001f)
+        {
+            if (p->retrigger == 1)
+            {
+                p->active = 1;
+                p->retrigger = 0;
+                tRamp_setDest(&p->gain, 1.f);
+                
+                if (p->dir > 0)
+                {
+                    if (p->flip > 0)    p->idx = p->start;
+                    else                p->idx = p->end;
+                }
+                else
+                {
+                    if (p->flip > 0)    p->idx = p->end;
+                    else                p->idx = p->start;
+                }
+            }
+            else
+            {
+                p->active = 0;
+            }
+            
+        }
+    }
+    
+    p->last = sample;
+
+    return p->last;
+}
+
+void tSampler_setSample    (tSampler* const p, tBuffer* s)
+{
+    p->samp = s;
+}
+
+void tSampler_setMode      (tSampler* const p, PlayMode mode)
+{
+    p->mode = mode;
+}
+
+void tSampler_setCrossfadeLength  (tSampler* const p, uint32_t length)
+{
+    uint32_t cfxlen = LEAF_clip(0, length, 1000);
+    
+    //if (cfxlen > p->len)  cfxlen = p->len * 0.25f;
+    
+    p->cfxlen = cfxlen;
+}
+
+void tSampler_play         (tSampler* const p)
+{
+    if (p->active != 0)
+    {
+        p->active = -1;
+        p->retrigger = 1;
+        
+        tRamp_setDest(&p->gain, 0.f);
+    }
+    else
+    {
+        p->active = 1;
+        p->retrigger = 0;
+        
+        tRamp_setDest(&p->gain, 1.f);
+        
+        if (p->dir > 0)
+        {
+            if (p->flip > 0)    p->idx = p->start;
+            else                p->idx = p->end;
+        }
+        else
+        {
+            if (p->flip > 0)    p->idx = p->end;
+            else                p->idx = p->start;
+        }
+    }
+}
+
+void tSampler_stop         (tSampler* const p)
+{
+    p->active = -1;
+    
+    tRamp_setDest(&p->gain, 0.f);
+}
+
+static void handleStartEndChange(tSampler* const p)
+{
+    p->len = abs(p->end - p->start);
+    
+    //if (p->len < p->cfxlen) p->cfxlen = p->len * 0.9f;
+    
+    if (p->start > p->end)
+    {
+        p->flip = -1;
+    }
+    else
+    {
+        p->flip = 1;
+    }
+}
+
+void tSampler_setStart     (tSampler* const p, int32_t start)
+{
+    p->start = LEAF_clipInt(0, start, (p->samp->length - 1));
+    
+    handleStartEndChange(p);
+}
+
+void tSampler_setEnd       (tSampler* const p, int32_t end)
+{
+    p->end = LEAF_clipInt(0, end, (p->samp->length - 1));
+    
+    handleStartEndChange(p);
+}
+
+void tSampler_setRate      (tSampler* const p, float rate)
+{
+    if (rate < 0.f)
+    {
+        rate = -rate;
+        p->dir = -1;
+    }
+    else
+    {
+        p->dir = 1;
+    }
+    
+    p->inc = LEAF_clip(0.f, rate, 8.0f);
+    p->iinc = 1.f / p->inc;
+}
+
+
+//==============================================================================
--- a/LEAF/Src/leaf-string.c
+++ /dev/null
@@ -1,289 +1,0 @@
-/*==============================================================================
-
-    leaf-string.c
-    Created: 30 Nov 2018 10:41:42am
-    Author:  airship
-
-==============================================================================*/
-
-#if _WIN32 || _WIN64
-
-#include "..\Inc\leaf-string.h"
-
-#else
-
-#include "../Inc/leaf-string.h"
-
-#endif
-
-/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ tPluck ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
-void    tPluck_init         (tPluck* const p, float lowestFrequency)
-{
-    if ( lowestFrequency <= 0.0f )  lowestFrequency = 10.0f;
-    
-    tNoise_init(&p->noise, WhiteNoise);
-    
-    tOnePole_init(&p->pickFilter, 0.0f);
-    
-    tOneZero_init(&p->loopFilter, 0.0f);
-    
-    tDelayA_init(&p->delayLine, 0.0f, leaf.sampleRate * 2);
-    
-    tPluck_setFrequency(p, 220.0f);
-}
-
-void tPluck_free (tPluck* const p)
-{
-    tNoise_free(&p->noise);
-    tOnePole_free(&p->pickFilter);
-    tOneZero_free(&p->loopFilter);
-    tDelayA_free(&p->delayLine);
-}
-
-float   tPluck_getLastOut    (tPluck *p)
-{
-    return p->lastOut;
-}
-
-float   tPluck_tick          (tPluck *p)
-{
-    return (p->lastOut = 3.0f * tDelayA_tick(&p->delayLine, tOneZero_tick(&p->loopFilter, tDelayA_getLastOut(&p->delayLine) * p->loopGain ) ));
-}
-
-void    tPluck_pluck         (tPluck* const p, float amplitude)
-{
-    if ( amplitude < 0.0f)      amplitude = 0.0f;
-    else if (amplitude > 1.0f)  amplitude = 1.0f;
-    
-    tOnePole_setPole(&p->pickFilter, 0.999f - (amplitude * 0.15f));
-    tOnePole_setGain(&p->pickFilter, amplitude * 0.5f );
-    
-    // Fill delay with noise additively with current contents.
-    for ( uint32_t i = 0; i < (uint32_t)tDelayA_getDelay(&p->delayLine); i++ )
-        tDelayA_tick(&p->delayLine, 0.6f * tDelayA_getLastOut(&p->delayLine) + tOnePole_tick(&p->pickFilter, tNoise_tick(&p->noise) ) );
-}
-
-// Start a note with the given frequency and amplitude.;
-void    tPluck_noteOn        (tPluck* const p, float frequency, float amplitude )
-{
-    p->lastFreq = frequency;
-    tPluck_setFrequency( p, frequency );
-    tPluck_pluck( p, amplitude );
-}
-
-// Stop a note with the given amplitude (speed of decay).
-void    tPluck_noteOff       (tPluck* const p, float amplitude )
-{
-    if ( amplitude < 0.0f)      amplitude = 0.0f;
-    else if (amplitude > 1.0f)  amplitude = 1.0f;
-    
-    p->loopGain = 1.0f - amplitude;
-}
-
-// Set instrument parameters for a particular frequency.
-void    tPluck_setFrequency  (tPluck* const p, float frequency )
-{
-    if ( frequency <= 0.0f )   frequency = 0.001f;
-    
-    // Delay = length - filter delay.
-    float delay = ( leaf.sampleRate / frequency ) - tOneZero_getPhaseDelay(&p->loopFilter, frequency );
-    
-    tDelayA_setDelay(&p->delayLine, delay );
-    
-    p->loopGain = 0.99f + (frequency * 0.000005f);
-    
-    if ( p->loopGain >= 0.999f ) p->loopGain = 0.999f;
-    
-}
-
-// Perform the control change specified by \e number and \e value (0.0 - 128.0).
-void    tPluck_controlChange (tPluck* const p, int number, float value)
-{
-    return;
-}
-
-void tPluckSampleRateChanged(tPluck* const p)
-{
-    //tPluckSetFrequency(p, p->lastFreq);
-}
-
-/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ tStifKarp ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
-void    tStifKarp_init          (tStifKarp* const p, float lowestFrequency)
-{
-    if ( lowestFrequency <= 0.0f )  lowestFrequency = 8.0f;
-    
-    tDelayA_init(&p->delayLine, 0.0f, leaf.sampleRate * 2);
-
-    tDelayL_init(&p->combDelay, 0.0f, leaf.sampleRate * 2);
-    
-    tOneZero_init(&p->filter, 0.0f);
-    
-    tNoise_init(&p->noise, WhiteNoise);
-    
-    for (int i = 0; i < 4; i++)
-    {
-        tBiQuad_init(&p->biquad[i]);
-    }
-    
-    p->pluckAmplitude = 0.3f;
-    p->pickupPosition = 0.4f;
-    
-    p->stretching = 0.9999f;
-    p->baseLoopGain = 0.995f;
-    p->loopGain = 0.999f;
-    
-    tStifKarp_setFrequency( p, 220.0f );
-    
-}
-
-void tStifKarp_free (tStifKarp* const p)
-{
-    tDelayA_free(&p->delayLine);
-    tDelayL_free(&p->combDelay);
-    tOneZero_free(&p->filter);
-    tNoise_free(&p->noise);
-    
-    for (int i = 0; i < 4; i++)
-    {
-        tBiQuad_free(&p->biquad[i]);
-    }
-}
-
-float   tStifKarp_getLastOut    (tStifKarp* const p)
-{
-    return p->lastOut;
-}
-
-float   tStifKarp_tick          (tStifKarp* const p)
-{
-    float temp = tDelayA_getLastOut(&p->delayLine) * p->loopGain;
-    
-    // Calculate allpass stretching.
-    for (int i=0; i<4; i++)     temp = tBiQuad_tick(&p->biquad[i],temp);
-    
-    // Moving average filter.
-    temp = tOneZero_tick(&p->filter, temp);
-    
-    float out = tDelayA_tick(&p->delayLine, temp);
-    out = out - tDelayL_tick(&p->combDelay, out);
-    p->lastOut = out;
-    
-    return p->lastOut;
-}
-
-void    tStifKarp_pluck         (tStifKarp* const p, float amplitude)
-{
-    if ( amplitude < 0.0f)      amplitude = 0.0f;
-    else if (amplitude > 1.0f)  amplitude = 1.0f;
-    
-    p->pluckAmplitude = amplitude;
-    
-    for ( uint32_t i=0; i < (uint32_t)tDelayA_getDelay(&p->delayLine); i++ )
-    {
-        // Fill delay with noise additively with current contents.
-        tDelayA_tick(&p->delayLine, (tDelayA_getLastOut(&p->delayLine) * 0.6f) + 0.4f * tNoise_tick(&p->noise) * p->pluckAmplitude );
-        //delayLine_.tick( combDelay_.tick((delayLine_.lastOut() * 0.6) + 0.4 * noise->tick() * pluckAmplitude_) );
-    }
-}
-
-// Start a note with the given frequency and amplitude.;
-void    tStifKarp_noteOn        (tStifKarp* const p, float frequency, float amplitude )
-{
-    tStifKarp_setFrequency( p, frequency );
-    tStifKarp_pluck( p, amplitude );
-}
-
-// Stop a note with the given amplitude (speed of decay).
-void    tStifKarp_noteOff       (tStifKarp* const p, float amplitude )
-{
-    if ( amplitude < 0.0f)      amplitude = 0.0f;
-    else if (amplitude > 1.0f)  amplitude = 1.0f;
-    
-    p->loopGain = 1.0f - amplitude;
-}
-
-// Set instrument parameters for a particular frequency.
-void    tStifKarp_setFrequency  (tStifKarp* const p, float frequency )
-{
-    if ( frequency <= 0.0f )   frequency = 0.001f;
-    
-    p->lastFrequency = frequency;
-    p->lastLength = leaf.sampleRate / p->lastFrequency;
-    float delay = p->lastLength - 0.5f;
-    tDelayA_setDelay(&p->delayLine, delay);
-    
-    // MAYBE MODIFY LOOP GAINS
-    p->loopGain = p->baseLoopGain + (frequency * 0.000005f);
-    if (p->loopGain >= 1.0f) p->loopGain = 0.99999f;
-    
-    tStifKarp_setStretch(p, p->stretching);
-    
-    tDelayL_setDelay(&p->combDelay, 0.5f * p->pickupPosition * p->lastLength );
-    
-}
-
-// Set the stretch "factor" of the string (0.0 - 1.0).
-void    tStifKarp_setStretch         (tStifKarp* const p, float stretch )
-{
-    p->stretching = stretch;
-    float coefficient;
-    float freq = p->lastFrequency * 2.0f;
-    float dFreq = ( (0.5f * leaf.sampleRate) - freq ) * 0.25f;
-    float temp = 0.5f + (stretch * 0.5f);
-    if ( temp > 0.9999f ) temp = 0.9999f;
-    
-    for ( int i=0; i<4; i++ )
-    {
-        coefficient = temp * temp;
-        tBiQuad_setA2(&p->biquad[i], coefficient);
-        tBiQuad_setB0(&p->biquad[i], coefficient);
-        tBiQuad_setB2(&p->biquad[i], 1.0f);
-        
-        coefficient = -2.0f * temp * cos(TWO_PI * freq / leaf.sampleRate);
-        tBiQuad_setA1(&p->biquad[i], coefficient);
-        tBiQuad_setB1(&p->biquad[i], coefficient);
-        
-        freq += dFreq;
-    }
-}
-
-// Set the pluck or "excitation" position along the string (0.0 - 1.0).
-void    tStifKarp_setPickupPosition  (tStifKarp* const p, float position )
-{
-    if (position < 0.0f)        p->pickupPosition = 0.0f;
-    else if (position <= 1.0f)  p->pickupPosition = position;
-    else                        p->pickupPosition = 1.0f;
-    
-    tDelayL_setDelay(&p->combDelay, 0.5f * p->pickupPosition * p->lastLength);
-}
-
-// Set the base loop gain.
-void    tStifKarp_setBaseLoopGain    (tStifKarp* const p, float aGain )
-{
-    p->baseLoopGain = aGain;
-    p->loopGain = p->baseLoopGain + (p->lastFrequency * 0.000005f);
-    if ( p->loopGain > 0.99999f ) p->loopGain = 0.99999f;
-}
-
-// Perform the control change specified by \e number and \e value (0.0 - 128.0).
-void    tStifKarp_controlChange (tStifKarp* const p, SKControlType type, float value)
-{
-    if ( value < 0.0f )         value = 0.0f;
-    else if (value > 128.0f)   value = 128.0f;
-    
-    float normalizedValue = value * INV_128;
-    
-    if (type == SKPickPosition) // 4
-        tStifKarp_setPickupPosition( p, normalizedValue );
-    else if (type == SKStringDamping) // 11
-        tStifKarp_setBaseLoopGain( p, 0.97f + (normalizedValue * 0.03f) );
-    else if (type == SKDetune) // 1
-        tStifKarp_setStretch( p, 0.91f + (0.09f * (1.0f - normalizedValue)) );
-    
-}
-
-void    tStifKarpSampleRateChanged (tStifKarp* const c)
-{
-    tStifKarp_setFrequency(c, c->lastFrequency);
-    tStifKarp_setStretch(c, c->stretching);
-}
--- a/LEAF/Src/leaf-utilities.c
+++ /dev/null
@@ -1,2227 +1,0 @@
-/*
-  ==============================================================================
-
-    LEAFUtilities.c
-    Created: 20 Jan 2017 12:02:17pm
-    Author:  Michael R Mulshine
-
-  ==============================================================================
-*/
-
-
-#if _WIN32 || _WIN64
-
-#include "..\Inc\leaf-utilities.h"
-#include "..\Inc\leaf-tables.h"
-#include "..\leaf.h"
-#include "..\Inc\d_fft_mayer.h"
-
-#else
-
-#include "../Inc/leaf-utilities.h"
-#include "../Inc/leaf-tables.h"
-#include "../leaf.h"
-#include "../Externals/d_fft_mayer.h"
-
-#endif
-
-#define LOGTEN 2.302585092994
-
-float mtof(float f)
-{
-    if (f <= -1500.0f) return(0);
-    else if (f > 1499.0f) return(mtof(1499.0f));
-    else return (8.17579891564f * expf(0.0577622650f * f));
-}
-
-float ftom(float f)
-{
-    return (f > 0 ? 17.3123405046f * logf(.12231220585f * f) : -1500.0f);
-}
-
-float powtodb(float f)
-{
-    if (f <= 0) return (0);
-    else
-    {
-        float val = 100 + 10.f/LOGTEN * logf(f);
-        return (val < 0 ? 0 : val);
-    }
-}
-
-float rmstodb(float f)
-{
-    if (f <= 0) return (0);
-    else
-    {
-        float val = 100 + 20.f/LOGTEN * log(f);
-        return (val < 0 ? 0 : val);
-    }
-}
-
-float dbtopow(float f)
-{
-    if (f <= 0)
-        return(0);
-    else
-    {
-        if (f > 870.0f)
-            f = 870.0f;
-        return (expf((LOGTEN * 0.1f) * (f-100.0f)));
-    }
-}
-
-float dbtorms(float f)
-{
-    if (f <= 0)
-        return(0);
-    else
-    {
-        if (f > 485.0f)
-            f = 485.0f;
-    }
-    return (expf((LOGTEN * 0.05f) * (f-100.0f)));
-}
-
-/* ---------------- env~ - simple envelope follower. ----------------- */
-void tEnv_init(tEnv* const x, int ws, int hs, int bs)
-{
-    int period = hs, npoints = ws;
-    
-    int i;
-    
-    if (npoints < 1) npoints = 1024;
-    if (period < 1) period = npoints/2;
-    if (period < npoints / MAXOVERLAP + 1)
-        period = npoints / MAXOVERLAP + 1;
-
-    x->x_npoints = npoints;
-    x->x_phase = 0;
-    x->x_period = period;
-    
-    x->windowSize = npoints;
-    x->hopSize = period;
-    x->blockSize = bs;
-    
-    for (i = 0; i < MAXOVERLAP; i++) x->x_sumbuf[i] = 0;
-    for (i = 0; i < npoints; i++)
-        x->buf[i] = (1.0f - cosf((2 * PI * i) / npoints))/npoints;
-    for (; i < npoints+INITVSTAKEN; i++) x->buf[i] = 0;
-    
-    x->x_f = 0;
-    
-    x->x_allocforvs = INITVSTAKEN;
-    
-    // ~ ~ ~ dsp ~ ~ ~
-    if (x->x_period % x->blockSize)
-    {
-        x->x_realperiod = x->x_period + x->blockSize - (x->x_period % x->blockSize);
-    }
-    else
-    {
-        x->x_realperiod = x->x_period;
-    }
-    // ~ ~ ~ ~ ~ ~ ~ ~
-}
-
-void tEnv_free (tEnv* const x)
-{
-
-}
-
-float tEnv_tick (tEnv* const x)
-{
-    return powtodb(x->x_result);
-}
-
-void tEnv_processBlock(tEnv* const x, float* in)
-{
-    int n = x->blockSize;
-    
-    int count;
-    t_sample *sump;
-    in += n;
-    for (count = x->x_phase, sump = x->x_sumbuf;
-         count < x->x_npoints; count += x->x_realperiod, sump++)
-    {
-        t_sample *hp = x->buf + count;
-        t_sample *fp = in;
-        t_sample sum = *sump;
-        int i;
-        
-        for (i = 0; i < n; i++)
-        {
-            fp--;
-            sum += *hp++ * (*fp * *fp);
-        }
-        *sump = sum;
-    }
-    sump[0] = 0;
-    x->x_phase -= n;
-    if (x->x_phase < 0)
-    {
-        x->x_result = x->x_sumbuf[0];
-        for (count = x->x_realperiod, sump = x->x_sumbuf;
-             count < x->x_npoints; count += x->x_realperiod, sump++)
-            sump[0] = sump[1];
-        sump[0] = 0;
-        x->x_phase = x->x_realperiod - n;
-    }
-}
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Compressor ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
-
-/*
-tCompressor*    tCompressorInit(int tauAttack, int tauRelease)
-{
-    tCompressor* c = &leaf.tCompressorRegistry[leaf.registryIndex[T_COMPRESSOR]++];
-    
-    c->tauAttack = tauAttack;
-    c->tauRelease = tauRelease;
-    
-    c->x_G[0] = 0.0f, c->x_G[1] = 0.0f,
-    c->y_G[0] = 0.0f, c->y_G[1] = 0.0f,
-    c->x_T[0] = 0.0f, c->x_T[1] = 0.0f,
-    c->y_T[0] = 0.0f, c->y_T[1] = 0.0f;
-    
-    c->T = 0.0f; // Threshold
-    c->R = 1.0f; // compression Ratio
-    c->M = 0.0f; // decibel Make-up gain
-    c->W = 0.0f; // decibel Width of knee transition
-    
-    return c;
-}
-*/
-void    tCompressor_init(tCompressor* const c)
-{
-    c->tauAttack = 100;
-    c->tauRelease = 100;
-	
-    c->isActive = OFALSE;
-    
-    c->T = 0.0f; // Threshold
-    c->R = 0.5f; // compression Ratio
-    c->M = 3.0f; // decibel Width of knee transition
-    c->W = 1.0f; // decibel Make-up gain
-}
-
-void tCompressor_free(tCompressor* const c)
-{
-    
-}
-
-int ccount = 0;
-float tCompressor_tick(tCompressor* const c, float in)
-{
-    float slope, overshoot;
-    float alphaAtt, alphaRel;
-    
-    float in_db = 20.0f * log10f( fmaxf( fabsf( in), 0.000001f)), out_db = 0.0f;
-    
-    c->y_T[1] = c->y_T[0];
-    
-    slope = c->R - 1.0f; // feed-forward topology; was 1/C->R - 1 
-    
-    overshoot = in_db - c->T;
-
-    
-    if (overshoot <= -(c->W * 0.5f))
-		{
-        out_db = in_db;
-			  c->isActive = OFALSE;
-		}
-    else if ((overshoot > -(c->W * 0.5f)) && (overshoot < (c->W * 0.5f)))
-		{
-        out_db = in_db + slope * (powf((overshoot + c->W*0.5f),2) / (2.0f * c->W)); // .^ 2 ???
-			  c->isActive = OTRUE;
-		}
-    else if (overshoot >= (c->W * 0.5f))
-		{
-        out_db = in_db + slope * overshoot;
-			  c->isActive = OTRUE;
-		}
-    
-    
-    
-    c->x_T[0] = out_db - in_db;
-    
-    alphaAtt = expf(-1.0f/(0.001f * c->tauAttack * leaf.sampleRate));
-    alphaRel = expf(-1.0f/(0.001f * c->tauRelease * leaf.sampleRate));
-    
-    if (c->x_T[0] > c->y_T[1])
-        c->y_T[0] = alphaAtt * c->y_T[1] + (1-alphaAtt) * c->x_T[0];
-    else
-        c->y_T[0] = alphaRel * c->y_T[1] + (1-alphaRel) * c->x_T[0];
-    
-    float attenuation = powf(10.0f, ((c->M - c->y_T[0])/20.0f));
-    
-    /*
-    if (++ccount > 5000)
-    {
-        
-        ccount = 0;
-        DBG(".5width: " + String(c->W * 0.5f));
-        DBG("slope: " + String(slope) + " overshoot: " + String(overshoot));
-        DBG("attenuation: " + String(attenuation));
-    }
-    */
-    return attenuation * in;
-    
-
-}
-
-// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Envelope ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
-void    tEnvelope_init(tEnvelope* const env, float attack, float decay, oBool loop)
-{
-    env->exp_buff = exp_decay;
-    env->inc_buff = attack_decay_inc;
-    env->buff_size = sizeof(exp_decay);
-    
-    env->loop = loop;
-    
-    if (attack > 8192.0f)
-        attack = 8192.0f;
-    if (attack < 0.0f)
-        attack = 0.0f;
-    
-    if (decay > 8192.0f)
-        decay = 8192.0f;
-    if (decay < 0.0f)
-        decay = 0.0f;
-    
-    int16_t attackIndex = ((int16_t)(attack * 8.0f))-1;
-    int16_t decayIndex = ((int16_t)(decay * 8.0f))-1;
-    int16_t rampIndex = ((int16_t)(2.0f * 8.0f))-1;
-    
-    if (attackIndex < 0)
-        attackIndex = 0;
-    if (decayIndex < 0)
-        decayIndex = 0;
-    if (rampIndex < 0)
-        rampIndex = 0;
-    
-    env->inRamp = OFALSE;
-    env->inAttack = OFALSE;
-    env->inDecay = OFALSE;
-    
-    env->attackInc = env->inc_buff[attackIndex];
-    env->decayInc = env->inc_buff[decayIndex];
-    env->rampInc = env->inc_buff[rampIndex];
-
-}
-
-void tEnvelope_free(tEnvelope* const env)
-{
-    
-}
-
-int     tEnvelope_setAttack(tEnvelope* const env, float attack)
-{
-    int32_t attackIndex;
-    
-    if (attack < 0.0f) {
-        attackIndex = 0.0f;
-    } else if (attack < 8192.0f) {
-        attackIndex = ((int32_t)(attack * 8.0f))-1;
-    } else {
-        attackIndex = ((int32_t)(8192.0f * 8.0f))-1;
-    }
-    
-    env->attackInc = env->inc_buff[attackIndex];
-    
-    return 0;
-}
-
-int     tEnvelope_setDecay(tEnvelope* const env, float decay)
-{
-    int32_t decayIndex;
-    
-    if (decay < 0.0f) {
-        decayIndex = 0.0f;
-    } else if (decay < 8192.0f) {
-        decayIndex = ((int32_t)(decay * 8.0f)) - 1;
-    } else {
-        decayIndex = ((int32_t)(8192.0f * 8.0f)) - 1; 
-    }
-    
-    env->decayInc = env->inc_buff[decayIndex]; 
-    
-    return 0;
-}
-
-int     tEnvelope_loop(tEnvelope* const env, oBool loop)
-{
-    env->loop = loop;
-    
-    return 0;
-}
-
-
-int     tEnvelope_on(tEnvelope* const env, float velocity)
-{
-    if (env->inAttack || env->inDecay) // In case envelope retriggered while it is still happening.
-    {
-        env->rampPhase = 0;
-        env->inRamp = OTRUE;
-        env->rampPeak = env->next;
-    }
-    else // Normal start.
-    {
-        env->inAttack = OTRUE;
-    }
-    
-    
-    env->attackPhase = 0;
-    env->decayPhase = 0;
-    env->inDecay = OFALSE;
-    env->gain = velocity;
-    
-    return 0;
-}
-
-float   tEnvelope_tick(tEnvelope* const env)
-{
-    if (env->inRamp)
-    {
-        if (env->rampPhase > UINT16_MAX)
-        {
-            env->inRamp = OFALSE;
-            env->inAttack = OTRUE;
-            env->next = 0.0f;
-        }
-        else
-        {
-            env->next = env->rampPeak * env->exp_buff[(uint32_t)env->rampPhase];
-        }
-        
-        env->rampPhase += env->rampInc;
-    }
-    
-    if (env->inAttack)
-    {
-        
-        // If attack done, time to turn around.
-        if (env->attackPhase > UINT16_MAX)
-        {
-            env->inDecay = OTRUE;
-            env->inAttack = OFALSE;
-            env->next = env->gain * 1.0f;
-        }
-        else
-        {
-            // do interpolation !
-            env->next = env->gain * env->exp_buff[UINT16_MAX - (uint32_t)env->attackPhase]; // inverted and backwards to get proper rising exponential shape/perception
-        }
-        
-        // Increment envelope attack.
-        env->attackPhase += env->attackInc;
-        
-    }
-    
-    if (env->inDecay)
-    {
-        
-        // If decay done, finish.
-        if (env->decayPhase >= UINT16_MAX)
-        {
-            env->inDecay = OFALSE;
-            
-            if (env->loop)
-            {
-                env->attackPhase = 0;
-                env->decayPhase = 0;
-                env->inAttack = OTRUE;
-            }
-            else
-            {
-                env->next = 0.0f;
-            }
-            
-        } else {
-            
-            env->next = env->gain * (env->exp_buff[(uint32_t)env->decayPhase]); // do interpolation !
-        }
-        
-        // Increment envelope decay;
-        env->decayPhase += env->decayInc;
-    }
-    
-    return env->next;
-}
-
-/* ADSR */
-void    tADSR_init(tADSR* const adsr, float attack, float decay, float sustain, float release)
-{
-    adsr->exp_buff = exp_decay;
-    adsr->inc_buff = attack_decay_inc;
-    adsr->buff_size = sizeof(exp_decay);
-    
-    if (attack > 8192.0f)
-        attack = 8192.0f;
-    if (attack < 0.0f)
-        attack = 0.0f;
-    
-    if (decay > 8192.0f)
-        decay = 8192.0f;
-    if (decay < 0.0f)
-        decay = 0.0f;
-    
-    if (sustain > 1.0f)
-        sustain = 1.0f;
-    if (sustain < 0.0f)
-        sustain = 0.0f;
-    
-    if (release > 8192.0f)
-        release = 8192.0f;
-    if (release < 0.0f)
-        release = 0.0f;
-    
-    int16_t attackIndex = ((int16_t)(attack * 8.0f))-1;
-    int16_t decayIndex = ((int16_t)(decay * 8.0f))-1;
-    int16_t releaseIndex = ((int16_t)(release * 8.0f))-1;
-    int16_t rampIndex = ((int16_t)(2.0f * 8.0f))-1;
-    
-    if (attackIndex < 0)
-        attackIndex = 0;
-    if (decayIndex < 0)
-        decayIndex = 0;
-    if (releaseIndex < 0)
-        releaseIndex = 0;
-    if (rampIndex < 0)
-        rampIndex = 0;
-    
-    adsr->inRamp = OFALSE;
-    adsr->inAttack = OFALSE;
-    adsr->inDecay = OFALSE;
-    adsr->inSustain = OFALSE;
-    adsr->inRelease = OFALSE;
-    
-    adsr->sustain = sustain;
-    
-    adsr->attackInc = adsr->inc_buff[attackIndex];
-    adsr->decayInc = adsr->inc_buff[decayIndex];
-    adsr->releaseInc = adsr->inc_buff[releaseIndex];
-    adsr->rampInc = adsr->inc_buff[rampIndex];
-}
-
-void tADSR_free(tADSR* const adsr)
-{
-    
-}
-
-int     tADSR_setAttack(tADSR* const adsr, float attack)
-{
-    int32_t attackIndex;
-    
-    if (attack < 0.0f) {
-        attackIndex = 0.0f;
-    } else if (attack < 8192.0f) {
-        attackIndex = ((int32_t)(attack * 8.0f))-1;
-    } else {
-        attackIndex = ((int32_t)(8192.0f * 8.0f))-1;
-    }
-    
-    adsr->attackInc = adsr->inc_buff[attackIndex];
-    
-    return 0;
-}
-
-int     tADSR_detDecay(tADSR* const adsr, float decay)
-{
-    int32_t decayIndex;
-    
-    if (decay < 0.0f) {
-        decayIndex = 0.0f;
-    } else if (decay < 8192.0f) {
-        decayIndex = ((int32_t)(decay * 8.0f)) - 1;
-    } else {
-        decayIndex = ((int32_t)(8192.0f * 8.0f)) - 1;
-    }
-    
-    adsr->decayInc = adsr->inc_buff[decayIndex];
-    
-    return 0;
-}
-
-int     tADSR_setSustain(tADSR *const adsr, float sustain)
-{
-    if (sustain > 1.0f)      adsr->sustain = 1.0f;
-    else if (sustain < 0.0f) adsr->sustain = 0.0f;
-    else                     adsr->sustain = sustain;
-    
-    return 0;
-}
-
-int     tADSR_setRelease(tADSR* const adsr, float release)
-{
-    int32_t releaseIndex;
-    
-    if (release < 0.0f) {
-        releaseIndex = 0.0f;
-    } else if (release < 8192.0f) {
-        releaseIndex = ((int32_t)(release * 8.0f)) - 1;
-    } else {
-        releaseIndex = ((int32_t)(8192.0f * 8.0f)) - 1;
-    }
-    
-    adsr->releaseInc = adsr->inc_buff[releaseIndex];
-    
-    return 0;
-}
-
-int tADSR_on(tADSR* const adsr, float velocity)
-{
-    if ((adsr->inAttack || adsr->inDecay) || (adsr->inSustain || adsr->inRelease)) // In case ADSR retriggered while it is still happening.
-    {
-        adsr->rampPhase = 0;
-        adsr->inRamp = OTRUE;
-        adsr->rampPeak = adsr->next;
-    }
-    else // Normal start.
-    {
-        adsr->inAttack = OTRUE;
-    }
-    
-    adsr->attackPhase = 0;
-    adsr->decayPhase = 0;
-    adsr->releasePhase = 0;
-    adsr->inDecay = OFALSE;
-    adsr->inSustain = OFALSE;
-    adsr->inRelease = OFALSE;
-    adsr->gain = velocity;
-    
-    return 0;
-}
-
-int tADSR_off(tADSR* const adsr)
-{
-    if (adsr->inRelease) return 0;
-    
-    adsr->inAttack = OFALSE;
-    adsr->inDecay = OFALSE;
-    adsr->inSustain = OFALSE;
-    adsr->inRelease = OTRUE;
-    
-    adsr->releasePeak = adsr->next;
-    
-    return 0;
-}
-
-float   tADSR_tick(tADSR* const adsr)
-{
-    if (adsr->inRamp)
-    {
-        if (adsr->rampPhase > UINT16_MAX)
-        {
-            adsr->inRamp = OFALSE;
-            adsr->inAttack = OTRUE;
-            adsr->next = 0.0f;
-        }
-        else
-        {
-            adsr->next = adsr->rampPeak * adsr->exp_buff[(uint32_t)adsr->rampPhase];
-        }
-        
-        adsr->rampPhase += adsr->rampInc;
-    }
-    
-    if (adsr->inAttack)
-    {
-        
-        // If attack done, time to turn around.
-        if (adsr->attackPhase > UINT16_MAX)
-        {
-            adsr->inDecay = OTRUE;
-            adsr->inAttack = OFALSE;
-            adsr->next = adsr->gain * 1.0f;
-        }
-        else
-        {
-            // do interpolation !
-            adsr->next = adsr->gain * adsr->exp_buff[UINT16_MAX - (uint32_t)adsr->attackPhase]; // inverted and backwards to get proper rising exponential shape/perception
-        }
-        
-        // Increment ADSR attack.
-        adsr->attackPhase += adsr->attackInc;
-        
-    }
-    
-    if (adsr->inDecay)
-    {
-        
-        // If decay done, sustain.
-        if (adsr->decayPhase >= UINT16_MAX)
-        {
-            adsr->inDecay = OFALSE;
-            adsr->inSustain = OTRUE;
-            adsr->next = adsr->gain * adsr->sustain;
-        }
-        
-        else
-        {
-            adsr->next = adsr->gain * (adsr->sustain + ((adsr->exp_buff[(uint32_t)adsr->decayPhase]) * (1 - adsr->sustain))); // do interpolation !
-        }
-        
-        // Increment ADSR decay.
-        adsr->decayPhase += adsr->decayInc;
-    }
-
-    if (adsr->inRelease)
-    {
-        // If release done, finish.
-        if (adsr->releasePhase >= UINT16_MAX)
-        {
-            adsr->inRelease = OFALSE;
-            adsr->next = 0.0f;
-        }
-        else {
-            
-            adsr->next = adsr->releasePeak * (adsr->exp_buff[(uint32_t)adsr->releasePhase]); // do interpolation !
-        }
-        
-        // Increment envelope release;
-        adsr->releasePhase += adsr->releaseInc;
-    }
-
-    return adsr->next;
-}
-
-/* Envelope Follower */
-void    tEnvelopeFollower_init(tEnvelopeFollower* const e, float attackThreshold, float decayCoeff)
-{
-    e->y = 0.0f;
-    e->a_thresh = attackThreshold;
-    e->d_coeff = decayCoeff;
-}
-
-void tEnvelopeFollower_free(tEnvelopeFollower* const e)
-{
-    
-}
-
-float   tEnvelopeFollower_tick(tEnvelopeFollower* const ef, float x)
-{
-    if (x < 0.0f ) x = -x;  /* Absolute value. */
-    
-    if ((x >= ef->y) && (x > ef->a_thresh)) ef->y = x;                      /* If we hit a peak, ride the peak to the top. */
-    else                                    ef->y = ef->y * ef->d_coeff;    /* Else, exponential decay of output. */
-    
-    //ef->y = envelope_pow[(uint16_t)(ef->y * (float)UINT16_MAX)] * ef->d_coeff; //not quite the right behavior - too much loss of precision?
-    //ef->y = powf(ef->y, 1.000009f) * ef->d_coeff;  // too expensive
-    
-    if( ef->y < VSF)   ef->y = 0.0f;
-    
-    return ef->y;
-}
-
-int     tEnvelopeFollower_decayCoeff(tEnvelopeFollower* const ef, float decayCoeff)
-{
-    return ef->d_coeff = decayCoeff;
-}
-
-int     tEnvelopeFollower_attackThresh(tEnvelopeFollower* const ef, float attackThresh)
-{
-    return ef->a_thresh = attackThresh;
-}
-
-/* Ramp */
-void    tRamp_init(tRamp* const ramp, float time, int samples_per_tick)
-{
-    ramp->inv_sr_ms = 1.0f/(leaf.sampleRate*0.001f);
-	ramp->minimum_time = ramp->inv_sr_ms * samples_per_tick;
-    ramp->curr = 0.0f;
-    ramp->dest = 0.0f;
-    
-    if (time < ramp->minimum_time)
-    {
-        ramp->time = ramp->minimum_time;
-    }
-    else
-    {
-        ramp->time = time;
-    }
-    
-    ramp->samples_per_tick = samples_per_tick;
-    ramp->inc = ((ramp->dest - ramp->curr) / ramp->time * ramp->inv_sr_ms) * (float)ramp->samples_per_tick;
-}
-
-void tRamp_free(tRamp* const ramp)
-{
-    
-}
-
-int     tRamp_setTime(tRamp* const r, float time)
-{
-	if (time < r->minimum_time)
-	{
-		r->time = r->minimum_time;
-	}
-	else
-	{
-		r->time = time;
-	}
-    r->inc = ((r->dest-r->curr)/r->time * r->inv_sr_ms) * ((float)r->samples_per_tick);
-    return 0;
-}
-
-int     tRamp_setDest(tRamp* const r, float dest)
-{
-    r->dest = dest;
-    r->inc = ((r->dest-r->curr)/r->time * r->inv_sr_ms) * ((float)r->samples_per_tick);
-    return 0;
-}
-
-int     tRamp_setVal(tRamp* const r, float val)
-{
-    r->curr = val;
-    r->inc = ((r->dest-r->curr)/r->time * r->inv_sr_ms) * ((float)r->samples_per_tick);
-    return 0;
-}
-
-float   tRamp_tick(tRamp* const r) {
-    
-    r->curr += r->inc;
-    
-    if (((r->curr >= r->dest) && (r->inc > 0.0f)) || ((r->curr <= r->dest) && (r->inc < 0.0f))) r->inc = 0.0f;
-    // Palle: There is a slight risk that you overshoot here and stay on dest+inc, which with a large inc value could be a real problem
-    // I suggest you add: r->curr=r->dest in the true if case
-    
-    return r->curr;
-}
-
-float   tRamp_sample(tRamp* const r) {
-  
-    return r->curr;
-}
-
-void    tRampSampleRateChanged(tRamp* const r)
-{
-    r->inv_sr_ms = 1.0f / (leaf.sampleRate * 0.001f);
-    r->inc = ((r->dest-r->curr)/r->time * r->inv_sr_ms)*((float)r->samples_per_tick);
-}
-
-
-/* Exponential Smoother */
-void    tExpSmooth_init(tExpSmooth* const smooth, float val, float factor)
-{	// factor is usually a value between 0 and 0.1. Lower value is slower. 0.01 for example gives you a smoothing time of about 10ms
-	smooth->curr=val;
-	smooth->dest=val;
-	if (factor<0) factor=0;
-	if (factor>1) factor=1;
-	smooth->factor=factor;
-	smooth->oneminusfactor=1.0f-factor;
-}
-
-void tExpSmooth_free(tExpSmooth* const smooth)
-{
-    
-}
-
-int     tExpSmooth_setFactor(tExpSmooth* const smooth, float factor)
-{	// factor is usually a value between 0 and 0.1. Lower value is slower. 0.01 for example gives you a smoothing time of about 10ms
-	if (factor<0)
-		factor=0;
-	else
-		if (factor>1) factor=1;
-	smooth->factor=factor;
-	smooth->oneminusfactor=1.0f-factor;
-    return 0;
-}
-
-int     tExpSmooth_setDest(tExpSmooth* const smooth, float dest)
-{
-	smooth->dest=dest;
-    return 0;
-}
-
-int     tExpSmooth_setVal(tExpSmooth* const smooth, float val)
-{
-	smooth->curr=val;
-    return 0;
-}
-
-float   tExpSmooth_tick(tExpSmooth* const smooth)
-{
-    smooth->curr = smooth->factor*smooth->dest+smooth->oneminusfactor*smooth->curr;
-    return smooth->curr;
-}
-
-float   tExpSmooth_sample(tExpSmooth* const smooth)
-{
-    return smooth->curr;
-}
-
-
-/* Power Follower */
-
-void    tPwrFollow_init(tPwrFollow* const p, float factor)
-{
-	p->curr=0.0f;
-	p->factor=factor;
-	p->oneminusfactor=1.0f-factor;
-}
-
-void tPwrFollow_free(tPwrFollow* const p)
-{
-    
-}
-
-int     tPwrFollow_setFactor(tPwrFollow* const p, float factor)
-{
-	if (factor<0) factor=0;
-	if (factor>1) factor=1;
-	p->factor=factor;
-	p->oneminusfactor=1.0f-factor;
-    return 0;
-}
-
-float   tPwrFollow_tick(tPwrFollow* const p, float input)
-{
-    p->curr = p->factor*input*input+p->oneminusfactor*p->curr;
-    return p->curr;
-}
-
-float   tPwrFollow_sample(tPwrFollow* const p)
-{
-    return p->curr;
-}
-
-/* Feedback Leveler */
-
-void    tFBleveller_init(tFBleveller* const p, float targetLevel, float factor, float strength, int mode)
-{
-	p->curr=0.0f;
-	p->targetLevel=targetLevel;
-	tPwrFollow_init(&p->pwrFlw,factor);
-	p->mode=mode;
-	p->strength=strength;
-}
-
-void tFBleveller_free(tFBleveller* const p)
-{
-    tPwrFollow_free(&p->pwrFlw);
-}
-
-int     tFBleveller_setStrength(tFBleveller* const p, float strength)
-{	// strength is how strongly level diff is affecting the amp ratio
-	// try 0.125 for a start
-	p->strength=strength;
-    return 0;
-}
-
-int     tFBleveller_setFactor(tFBleveller* const p, float factor)
-{
-	tPwrFollow_setFactor(&p->pwrFlw,factor);
-    return 0;
-}
-
-int     tFBleveller_setMode(tFBleveller* const p, int mode)
-{	// 0 for decaying with upwards lev limiting, 1 for constrained absolute level (also downwards limiting)
-	p->mode=mode;
-    return 0;
-}
-
-float   tFBleveller_tick(tFBleveller* const p, float input)
-{
-	float levdiff=(tPwrFollow_tick(&p->pwrFlw, input)-p->targetLevel);
-	if (p->mode==0 && levdiff<0) levdiff=0;
-	p->curr=input*(1-p->strength*levdiff);
-	return p->curr;
-}
-
-float   tFBleveller_sample(tFBleveller* const p)
-{
-    return p->curr;
-}
-
-
-int     tFBleveller_setTargetLevel   (tFBleveller* const p, float TargetLevel)
-{
-	p->targetLevel=TargetLevel;
-}
-
-///Reed Table model
-//default values from STK are 0.6 offset and -0.8 slope
-
-void    tReedTable_init      (tReedTable* const p, float offset, float slope)
-{
-	p->offset = offset;
-	p->slope = slope;
-}
-
-void    tReedTable_free      (tReedTable* const p)
-{
-	;
-}
-
-float   tReedTable_tick      (tReedTable* const p, float input)
-{
-	// The input is differential pressure across the reed.
-	float output = p->offset + (p->slope * input);
-
-	// If output is > 1, the reed has slammed shut and the
-	// reflection function value saturates at 1.0.
-	if ( output > 1.0f) output = 1.0f;
-
-	// This is nearly impossible in a physical system, but
-	// a reflection function value of -1.0 corresponds to
-	// an open end (and no discontinuity in bore profile).
-	if ( output < -1.0f) output = -1.0f;
-
-	return output;
-}
-
-float   tReedTable_tanh_tick     (tReedTable* const p, float input)
-{
-	// The input is differential pressure across the reed.
-	float output = p->offset + (p->slope * input);
-
-	// If output is > 1, the reed has slammed shut and the
-	// reflection function value saturates at 1.0.
-	return tanhf(output);
-}
-
-void     tReedTable_setOffset   (tReedTable* const p, float offset)
-{
-	p->offset = offset;
-}
-
-void     tReedTable_setSlope   (tReedTable* const p, float slope)
-{
-	p->slope = slope;
-}
-
-
-
-/* Simple Living String*/
-
-void    tSimpleLivingString_init(tSimpleLivingString* const p, float freq, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode)
-{
-	p->curr=0.0f;
-	tExpSmooth_init(&p->wlSmooth, leaf.sampleRate/freq, 0.01); // smoother for string wavelength (not freq, to avoid expensive divisions)
-	tSimpleLivingString_setFreq(p, freq);
-	tDelayL_init(&p->delayLine,p->waveLengthInSamples, 2400);
-	tOnePole_init(&p->bridgeFilter, dampFreq);
-	tHighpass_init(&p->DCblocker,13);
-	p->decay=decay;
-	tFBleveller_init(&p->fbLev, targetLev, levSmoothFactor, levStrength, levMode);
-	p->levMode=levMode;
-}
-
-void tSimpleLivingString_free(tSimpleLivingString* const p)
-{
-    tExpSmooth_free(&p->wlSmooth);
-    tDelayL_free(&p->delayLine);
-    tOnePole_free(&p->bridgeFilter);
-    tHighpass_free(&p->DCblocker);
-    tFBleveller_free(&p->fbLev);
-}
-
-int     tSimpleLivingString_setFreq(tSimpleLivingString* const p, float freq)
-{
-	if (freq<20) freq=20;
-	else if (freq>10000) freq=10000;
-	p->waveLengthInSamples = leaf.sampleRate/freq;
-	tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
-    return 0;
-}
-
-int     tSimpleLivingString_setWaveLength(tSimpleLivingString* const p, float waveLength)
-{
-	if (waveLength<4.8) waveLength=4.8;
-	else if (waveLength>2400) waveLength=2400;
-	p->waveLengthInSamples = waveLength;
-	tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
-    return 0;
-}
-
-int     tSimpleLivingString_setDampFreq(tSimpleLivingString* const p, float dampFreq)
-{
-	tOnePole_setFreq(&p->bridgeFilter, dampFreq);
-    return 0;
-}
-
-int     tSimpleLivingString_setDecay(tSimpleLivingString* const p, float decay)
-{
-	p->decay=decay;
-    return 0;
-}
-
-int     tSimpleLivingString_setTargetLev(tSimpleLivingString* const p, float targetLev)
-{
-	tFBleveller_setTargetLevel(&p->fbLev, targetLev);
-    return 0;
-}
-
-int     tSimpleLivingString_setLevSmoothFactor(tSimpleLivingString* const p, float levSmoothFactor)
-{
-	tFBleveller_setFactor(&p->fbLev, levSmoothFactor);
-    return 0;
-}
-
-int     tSimpleLivingString_setLevStrength(tSimpleLivingString* const p, float levStrength)
-{
-	tFBleveller_setStrength(&p->fbLev, levStrength);
-    return 0;
-}
-
-int     tSimpleLivingString_setLevMode(tSimpleLivingString* const p, int levMode)
-{
-	tFBleveller_setMode(&p->fbLev, levMode);
-	p->levMode=levMode;
-    return 0;
-}
-
-float   tSimpleLivingString_tick(tSimpleLivingString* const p, float input)
-{
-	float stringOut=tOnePole_tick(&p->bridgeFilter,tDelayL_tickOut(&p->delayLine));
-	float stringInput=tHighpass_tick(&p->DCblocker, tFBleveller_tick(&p->fbLev, (p->levMode==0?p->decay*stringOut:stringOut)+input));
-	tDelayL_tickIn(&p->delayLine, stringInput);
-	tDelayL_setDelay(&p->delayLine, tExpSmooth_tick(&p->wlSmooth));
-    p->curr = stringOut;
-    return p->curr;
-}
-
-float   tSimpleLivingString_sample(tSimpleLivingString* const p)
-{
-    return p->curr;
-}
-
-/* Living String*/
-
-void    tLivingString_init(tLivingString* const p, float freq, float pickPos, float prepIndex, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode)
-{
-	p->curr=0.0f;
-	tExpSmooth_init(&p->wlSmooth, leaf.sampleRate/freq, 0.01); // smoother for string wavelength (not freq, to avoid expensive divisions)
-	tLivingString_setFreq(p, freq);
-	tExpSmooth_init(&p->ppSmooth, pickPos, 0.01); // smoother for pick position
-	tLivingString_setPickPos(p, pickPos);
-	p->prepIndex=prepIndex;
-	tDelayL_init(&p->delLF,p->waveLengthInSamples, 2400);
-	tDelayL_init(&p->delUF,p->waveLengthInSamples, 2400);
-	tDelayL_init(&p->delUB,p->waveLengthInSamples, 2400);
-	tDelayL_init(&p->delLB,p->waveLengthInSamples, 2400);
-	tOnePole_init(&p->bridgeFilter, dampFreq);
-	tOnePole_init(&p->nutFilter, dampFreq);
-	tOnePole_init(&p->prepFilterU, dampFreq);
-	tOnePole_init(&p->prepFilterL, dampFreq);
-	tHighpass_init(&p->DCblockerU,13);
-	tHighpass_init(&p->DCblockerL,13);
-	p->decay=decay;
-	tFBleveller_init(&p->fbLevU, targetLev, levSmoothFactor, levStrength, levMode);
-	tFBleveller_init(&p->fbLevL, targetLev, levSmoothFactor, levStrength, levMode);
-	p->levMode=levMode;
-}
-
-void tLivingString_free(tLivingString* const p)
-{
-    tExpSmooth_free(&p->wlSmooth);
-    tExpSmooth_free(&p->ppSmooth);
-    tDelayL_free(&p->delLF);
-    tDelayL_free(&p->delUF);
-    tDelayL_free(&p->delUB);
-    tDelayL_free(&p->delLB);
-    tOnePole_free(&p->bridgeFilter);
-    tOnePole_free(&p->nutFilter);
-    tOnePole_free(&p->prepFilterU);
-    tOnePole_free(&p->prepFilterL);
-    tHighpass_free(&p->DCblockerU);
-    tHighpass_free(&p->DCblockerL);
-    tFBleveller_free(&p->fbLevU);
-    tFBleveller_free(&p->fbLevL);
-}
-
-int     tLivingString_setFreq(tLivingString* const p, float freq)
-{	// NOTE: It is faster to set wavelength in samples directly
-	if (freq<20) freq=20;
-	else if (freq>10000) freq=10000;
-	p->waveLengthInSamples = leaf.sampleRate/freq;
-	tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
-    return 0;
-}
-
-int     tLivingString_setWaveLength(tLivingString* const p, float waveLength)
-{
-	if (waveLength<4.8) waveLength=4.8;
-	else if (waveLength>2400) waveLength=2400;
-	p->waveLengthInSamples = waveLength;
-	tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
-    return 0;
-}
-
-int     tLivingString_setPickPos(tLivingString* const p, float pickPos)
-{	// between 0 and 1
-	if (pickPos<0.f) pickPos=0.f;
-	else if (pickPos>1.f) pickPos=1.f;
-	p->pickPos = pickPos;
-	tExpSmooth_setDest(&p->ppSmooth, p->pickPos);
-    return 0;
-}
-
-int     tLivingString_setPrepIndex(tLivingString* const p, float prepIndex)
-{	// between 0 and 1
-	if (prepIndex<0.f) prepIndex=0.f;
-	else if (prepIndex>1.f) prepIndex=1.f;
-	p->prepIndex = prepIndex;
-    return 0;
-}
-
-int     tLivingString_setDampFreq(tLivingString* const p, float dampFreq)
-{
-	tOnePole_setFreq(&p->bridgeFilter, dampFreq);
-	tOnePole_setFreq(&p->nutFilter, dampFreq);
-	tOnePole_setFreq(&p->prepFilterU, dampFreq);
-	tOnePole_setFreq(&p->prepFilterL, dampFreq);
-    return 0;
-}
-
-int     tLivingString_setDecay(tLivingString* const p, float decay)
-{
-	p->decay=decay;
-    return 0;
-}
-
-int     tLivingString_setTargetLev(tLivingString* const p, float targetLev)
-{
-	tFBleveller_setTargetLevel(&p->fbLevU, targetLev);
-	tFBleveller_setTargetLevel(&p->fbLevL, targetLev);
-    return 0;
-}
-
-int     tLivingString_setLevSmoothFactor(tLivingString* const p, float levSmoothFactor)
-{
-	tFBleveller_setFactor(&p->fbLevU, levSmoothFactor);
-	tFBleveller_setFactor(&p->fbLevL, levSmoothFactor);
-    return 0;
-}
-
-int     tLivingString_setLevStrength(tLivingString* const p, float levStrength)
-{
-	tFBleveller_setStrength(&p->fbLevU, levStrength);
-	tFBleveller_setStrength(&p->fbLevL, levStrength);
-    return 0;
-}
-
-int     tLivingString_setLevMode(tLivingString* const p, int levMode)
-{
-	tFBleveller_setMode(&p->fbLevU, levMode);
-	tFBleveller_setMode(&p->fbLevL, levMode);
-	p->levMode=levMode;
-    return 0;
-}
-
-float   tLivingString_tick(tLivingString* const p, float input)
-{
-	// from pickPos upwards=forwards
-	float fromLF=tDelayL_tickOut(&p->delLF);
-	float fromUF=tDelayL_tickOut(&p->delUF);
-	float fromUB=tDelayL_tickOut(&p->delUB);
-	float fromLB=tDelayL_tickOut(&p->delLB);
-	// into upper half of string, from nut, going backwards
-	float fromNut=-tFBleveller_tick(&p->fbLevU, (p->levMode==0?p->decay:1)*tHighpass_tick(&p->DCblockerU, tOnePole_tick(&p->nutFilter, fromUF)));
-	tDelayL_tickIn(&p->delUB, fromNut);
-	// into lower half of string, from pickpoint, going backwards
-	float fromLowerPrep=-tOnePole_tick(&p->prepFilterL, fromLF);
-	float intoLower=p->prepIndex*fromLowerPrep+(1-p->prepIndex)*fromUB+input;
-	tDelayL_tickIn(&p->delLB, intoLower);
-	// into lower half of string, from bridge
-	float fromBridge=-tFBleveller_tick(&p->fbLevL, (p->levMode==0?p->decay:1)*tHighpass_tick(&p->DCblockerL, tOnePole_tick(&p->bridgeFilter, fromLB)));
-	tDelayL_tickIn(&p->delLF, fromBridge);
-	// into upper half of string, from pickpoint, going forwards/upwards
-	float fromUpperPrep=-tOnePole_tick(&p->prepFilterU, fromUB);
-	float intoUpper=p->prepIndex*fromUpperPrep+(1-p->prepIndex)*fromLF+input;
-	tDelayL_tickIn(&p->delUF, intoUpper);
-	// update all delay lengths
-	float pickP=tExpSmooth_tick(&p->ppSmooth);
-	float wLen=tExpSmooth_tick(&p->wlSmooth);
-	float lowLen=pickP*wLen;
-	float upLen=(1-pickP)*wLen;
-	tDelayL_setDelay(&p->delLF, lowLen);
-	tDelayL_setDelay(&p->delLB, lowLen);
-	tDelayL_setDelay(&p->delUF, upLen);
-	tDelayL_setDelay(&p->delUB, upLen);
-    p->curr = fromBridge;
-    return p->curr;
-}
-
-float   tLivingString_sample(tLivingString* const p)
-{
-    return p->curr;
-}
-
-
-/* Stack */
-
-void tStack_init(tStack* const ns)
-{
-    ns->ordered = OFALSE;
-    ns->size = 0;
-    ns->pos = 0;
-    ns->capacity = STACK_SIZE;
-    
-    for (int i = 0; i < STACK_SIZE; i++) ns->data[i] = -1;
-}
-
-void tStack_free(tStack* const ns)
-{
-    
-}
-
-// If stack contains note, returns index. Else returns -1;
-int tStack_contains(tStack* const ns, uint16_t noteVal)
-{
-    for (int i = 0; i < ns->size; i++)
-    {
-        if (ns->data[i] == noteVal)    return i;
-    }
-    return -1;
-}
-
-void tStack_add(tStack* const ns, uint16_t noteVal)
-{
-    uint8_t j;
-    
-    int whereToInsert = 0;
-    if (ns->ordered)
-    {
-        for (j = 0; j < ns->size; j++)
-        {
-            if (noteVal > ns->data[j])
-            {
-                if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1))
-                {
-                    whereToInsert = j+1;
-                    break;
-                }
-            }
-        }
-    }
-    
-    //first move notes that are already in the stack one position to the right
-    for (j = ns->size; j > whereToInsert; j--)
-    {
-        ns->data[j] = ns->data[(j - 1)];
-    }
-    
-    //then, insert the new note into the front of the stack
-    ns->data[whereToInsert] = noteVal;
-    
-    ns->size++;
-}
-
-int tStack_addIfNotAlreadyThere(tStack* const ns, uint16_t noteVal)
-{
-    uint8_t j;
-
-    int added = 0;
-    
-    if (tStack_contains(ns, noteVal) == -1)
-    {
-        int whereToInsert = 0;
-        if (ns->ordered)
-        {
-            for (j = 0; j < ns->size; j++)
-            {
-                if (noteVal > ns->data[j])
-                {
-                    if ((noteVal < ns->data[j+1]) || (ns->data[j+1] == -1))
-                    {
-                        whereToInsert = j+1;
-                        break;
-                    }
-                }
-            }
-        }
-        
-        //first move notes that are already in the stack one position to the right
-        for (j = ns->size; j > whereToInsert; j--)
-        {
-            ns->data[j] = ns->data[(j - 1)];
-        }
-        
-        //then, insert the new note into the front of the stack
-        ns->data[whereToInsert] = noteVal;
-        
-        ns->size++;
-        
-        added = 1;
-    }
-    
-    return added;
-}
-
-
-// Remove noteVal. return 1 if removed, 0 if not
-int tStack_remove(tStack* const ns, uint16_t noteVal)
-{
-    uint8_t k;
-    int foundIndex = tStack_contains(ns, noteVal);
-    int removed = 0;
-    
-    if (foundIndex >= 0)
-    {
-        for (k = 0; k < (ns->size - foundIndex); k++)
-        {
-            if ((k+foundIndex) >= (ns->capacity - 1))
-            {
-                ns->data[k + foundIndex] = -1;
-            }
-            else
-            {
-                ns->data[k + foundIndex] = ns->data[k + foundIndex + 1];
-                if ((k + foundIndex) == (ns->size - 1))
-                {
-                    ns->data[k + foundIndex + 1] = -1;
-                }
-            }
-            
-        }
-        // in case it got put on the stack multiple times
-        foundIndex--;
-        ns->size--;
-        removed = 1;
-    }
-    
-    
-    
-    return removed;
-}
-
-// Doesn't change size of data types
-void tStack_setCapacity(tStack* const ns, uint16_t cap)
-{
-    if (cap <= 0)
-        ns->capacity = 1;
-    else if (cap <= STACK_SIZE)
-        ns->capacity = cap;
-    else
-        ns->capacity = STACK_SIZE;
-    
-    for (int i = cap; i < STACK_SIZE; i++)
-    {
-        if ((int)ns->data[i] != -1)
-        {
-            ns->data[i] = -1;
-            ns->size -= 1;
-        }
-    }
-    
-    if (ns->pos >= cap)
-    {
-        ns->pos = 0;
-    }
-}
-
-int tStack_getSize(tStack* const ns)
-{
-    return ns->size;
-}
-
-void tStack_clear(tStack* const ns)
-{
-    for (int i = 0; i < STACK_SIZE; i++)
-    {
-        ns->data[i] = -1;
-    }
-    ns->pos = 0;
-    ns->size = 0;
-}
-
-// Next item in order of addition to stack. Return 0-31 if there is a next item to move to. Returns -1 otherwise.
-int tStack_next(tStack* const ns)
-{
-    int step = 0;
-    if (ns->size != 0) // if there is at least one note in the stack
-    {
-        if (ns->pos > 0) // if you're not at the most recent note (first one), then go backward in the array (moving from earliest to latest)
-        {
-            ns->pos--;
-        }
-        else
-        {
-            ns->pos = (ns->size - 1); // if you are the most recent note, go back to the earliest note in the array
-        }
-        
-        step = ns->data[ns->pos];
-        return step;
-    }
-    else
-    {
-        return -1;
-    }
-}
-
-int tStack_get(tStack* const ns, int which)
-{
-    return ns->data[which];
-}
-
-int tStack_first(tStack* const ns)
-{
-    return ns->data[0];
-}
-/******************************************************************************/
-/***************** static function declarations *******************************/
-/******************************************************************************/
-
-static void solad_init(tSOLAD *w);
-static inline float read_sample(tSOLAD *w, float floatindex);
-static void pitchdown(tSOLAD *w, float *out);
-static void pitchup(tSOLAD *w, float *out);
-
-/******************************************************************************/
-/***************** public access functions ************************************/
-/******************************************************************************/
-
-// init
-void     tSOLAD_init(tSOLAD* const w)
-{
-    w->pitchfactor = 1.;
-    w->delaybuf = (float*) leaf_alloc(sizeof(float) * (LOOPSIZE+16));
-    solad_init(w);
-}
-
-void tSOLAD_free(tSOLAD* const w)
-{
-}
-
-// send one block of input samples, receive one block of output samples
-void tSOLAD_ioSamples(tSOLAD* const w, float* in, float* out, int blocksize)
-{
-    int i = w->timeindex;
-    int n = w->blocksize = blocksize;
-    
-    if(!i) w->delaybuf[LOOPSIZE] = in[0];   // copy one sample for interpolation
-    while(n--) w->delaybuf[i++] = *in++;    // copy one input block to delay buffer
-    
-    if(w->pitchfactor > 1) pitchup(w, out);
-    else pitchdown(w, out);
-    
-    w->timeindex += blocksize;
-    w->timeindex &= LOOPMASK;
-}
-
-// set periodicity analysis data
-void tSOLAD_setPeriod(tSOLAD* const w, float period)
-{
-    if(period > MAXPERIOD) period = MAXPERIOD;
-    if(period > MINPERIOD) w->period = period;  // ignore period when too small
-}
-
-// set pitch factor between 0.25 and 4
-void tSOLAD_setPitchFactor(tSOLAD* const w, float pitchfactor)
-{
-    if(pitchfactor < 0.25) pitchfactor = 0.25;
-    else if(pitchfactor > 4.) pitchfactor = 4.;
-    w->pitchfactor = pitchfactor;
-}
-
-// force readpointer lag
-void tSOLAD_setReadLag(tSOLAD* const w, float readlag)
-{
-    if(readlag < 0) readlag = 0;
-    if(readlag < w->readlag)               // do not jump backward, only forward
-    {
-        w->jump = w->readlag - readlag;
-        w->readlag = readlag;
-        w->xfadelength = readlag;
-        w->xfadevalue = 1;
-    }
-}
-
-// reset state variables
-void tSOLAD_resetState(tSOLAD* const w)
-{
-    int n = LOOPSIZE + 1;
-    float *buf = w->delaybuf;
-    
-    while(n--) *buf++ = 0;
-    solad_init(w);
-}
-
-/******************************************************************************/
-/******************** private procedures **************************************/
-/******************************************************************************/
-
-/*
- Function pitchdown() is called to read samples from the delay buffer when pitch
- factor is between 0.25 and 1. The read pointer lags behind because of the slowed
- down speed, and it must jump forward towards the write pointer soon as there is
- sufficient space to jump. That is, if there is at least one period of the input
- signal between read pointer and write pointer.  When short periods follow up on
- long periods, the read pointer may have space to jump over more than one period
- lenghts. Jump length must be [periodlength ^ 2] in any case.
- 
- A linear crossfade function joins the jump-from point with the jump-to point.
- The crossfade must be completed before another read pointer jump is allowed.
- Length of the crossfade function is stored as a number of samples in terms of
- the input sample rate. This length is dynamically translated
- to a crossfade length expressed in output reading rate, according to pitch
- factor which can change before the crossfade is completed. Crossfade length does
- not cover an invariable length in periods for all pitch transposition factors.
- For pitch factors from 0.5 till 1, crossfade length is stretched in the
- output just as much as the signal itself, as crossfade speed is set to equal
- pitch factor. For pitch factors below 0.5, the read pointer wants to jump
- forward before one period is read, therefore the crossfade length as expressed
- in output periods must be shorter. Crossfade speed is set to [1 - pitchfactor]
- for those cases. Pitch factor 0.5 is the natural switch point between crossfade
- speeds [pitchfactor] and [1 - pitchfactor] because 0.5 == 1 - 0.5. The crossfade
- speed modification for pitch factors below 0.5 also means that much of the
- original signal content will be skipped.
- */
-
-
-static void pitchdown(tSOLAD* const w, float *out)
-{
-    int n = w->blocksize;
-    float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values!
-    float pitchfactor = w->pitchfactor;
-    float period = w->period;
-    float readlag = w->readlag;
-    float readlagstep = 1 - pitchfactor;
-    float jump = w->jump;
-    float xfadevalue = w->xfadevalue;
-    float xfadelength = w->xfadelength;
-    float xfadespeed, xfadestep, readindex, outputsample;
-    
-    if(pitchfactor > 0.5) xfadespeed = pitchfactor;
-    else xfadespeed = 1 - pitchfactor;
-    xfadestep = xfadespeed / xfadelength;
-    
-    while(n--)
-    {
-        if(readlag > period)        // check if read pointer may jump forward...
-        {
-            if(xfadevalue <= 0)      // ...but do not interrupt crossfade
-            {
-                jump = period;                           // jump forward
-                while((jump * 2) < readlag) jump *= 2;   // use available space
-                readlag -= jump;                         // reduce read pointer lag
-                xfadevalue = 1;                          // start crossfade
-                xfadelength = period - 1;
-                xfadestep = xfadespeed / xfadelength;
-            }
-        }
-        
-        readindex = refindex - readlag;
-        outputsample = read_sample(w, readindex);
-        
-        if(xfadevalue > 0)
-        {
-            outputsample *= (1 - xfadevalue);                               // fadein
-            outputsample += read_sample(w, readindex - jump) * xfadevalue;  // fadeout
-            xfadevalue -= xfadestep;
-        }
-        
-        *out++ = outputsample;
-        refindex += 1;
-        readlag += readlagstep;
-    }
-    
-    w->jump = jump;                 // state variables
-    w->readlag = readlag;
-    w->xfadevalue = xfadevalue;
-    w->xfadelength = xfadelength;
-}
-
-
-/*
- Function pitchup() for pitch factors above 1 is more complicated than
- pitchdown(). The read pointer increments faster than the write pointer and a
- backward jump must happen in time, reckoning with the crossfade region. The read
- pointer backward jump length is always one period. In order to minimize the area
- of signal duplicates, crossfade length is aimed at [period / pitchfactor].
- This leads to a crossfade speed of [pitchfactor * pitchfactor].
- 
- Some samples for the fade out (but not all of them) must already be in the
- buffer, otherwise we will run out of input samples before the crossfade is
- completed. The ratio of past samples and future samples for a crossfade of any
- length is as follows:
- 
- past samples: xfadelength * (1 - 1 / pitchfactor)
- future samples: xfadelength * (1 / pitchfactor)
- 
- For example in the case of pitch factor 1.5 this would be:
- 
- past samples: xfadelength * (1 - 1 / 1.5) = xfadelength * 1 / 3
- future samples: xfadelength * (1 / 1.5) = xfadelength * 2 / 3
- 
- In the case of pitch factor 4 this would be:
- 
- past samples: xfadelength * (1 - 1 / 4) = xfadelength * 3 / 4
- future samples: xfadelength * (1 / 4) = xfadelength * 1 / 4
- 
- The read pointer lag must therefore preserve a minimum dependent on pitch
- factor. The minimum is called 'limit' here:
- 
- limit = period * (pitchfactor - 1) / pitchfactor * pitchfactor
- 
- Components of this expression are combined to reuse them in operations, while
- (pitchfactor - 1) is changed to (pitchfactor - 0.99) to avoid numerical
- resolution issues for pitch factors slightly above 1:
- 
- xfadespeed = pitchfactor * pitchfactor
- limitfactor = (pitchfactor - 0.99) / xfadespeed
- limit = period * limitfactor
- 
- When read lag is smaller than this limit, the read pointer must preferably
- jump backward, unless a previous crossfade is not yet completed. Crossfades must
- preferably be completed, unless the read pointer lag becomes smaller than zero.
- With fluctuating period lengths and pitch factors, the readpointer lag limit may
- change from one input block to the next in such a way that the actual lag is
- suddenly much smaller than the limit, and the intended crossfade length can not
- be applied. Therefore the crossfade length is simply calculated from the
- available amount of samples for all cases, like so:
- 
- xfadelength = readlag / limitfactor
- 
- For most occurrences, this will amount to a crossfade length reduced to
- [period / pitchfactor] in the output for pitch factors above 1, while in some
- cases it will be considerably shorter. Fortunately, an incidental aberration of
- the intended crossfade length hardly ever creates an audible artifact. The
- reason to specify preferred crossfade length according to pitch factor is to
- minimize the impression of echoes without sacrificing too much of the signal
- content. The readpointer jump length remains one period in any case.
- 
- Sometimes, the input signal periodicity may decrease substantially between one
- signal block and the next. In such cases it may be possible for the read pointer
- to jump forward and reduce latency. For every signal block, a check on this
- possibility is done. A previous crossfade must be completed before a forward
- jump is allowed.
- */
-static void pitchup(tSOLAD* const w, float *out)
-{
-    int n = w->blocksize;
-    float refindex = (float)(w->timeindex + LOOPSIZE); // no negative values
-    float pitchfactor = w->pitchfactor;
-    float period = w->period;
-    float readlag = w->readlag;
-    float jump = w->jump;
-    float xfadevalue = w->xfadevalue;
-    float xfadelength = w->xfadelength;
-    
-    float readlagstep = pitchfactor - 1;
-    float xfadespeed = pitchfactor * pitchfactor;
-    float xfadestep = xfadespeed / xfadelength;
-    float limitfactor = (pitchfactor - (float)0.99) / xfadespeed;
-    float limit = period * limitfactor;
-    float readindex, outputsample;
-    
-    if((readlag > (period + 2 * limit)) & (xfadevalue < 0))
-    {
-        jump = period;                                        // jump forward
-        while((jump * 2) < (readlag - 2 * limit)) jump *= 2;  // use available space
-        readlag -= jump;                                      // reduce read pointer lag
-        xfadevalue = 1;                                       // start crossfade
-        xfadelength = period - 1;
-        xfadestep = xfadespeed / xfadelength;
-    }
-    
-    while(n--)
-    {
-        if(readlag < limit)  // check if read pointer should jump backward...
-        {
-            if((xfadevalue < 0) | (readlag < 0)) // ...but try not to interrupt crossfade
-            {
-                xfadelength = readlag / limitfactor;
-                if(xfadelength < 1) xfadelength = 1;
-                xfadestep = xfadespeed / xfadelength;
-                
-                jump = -period;         // jump backward
-                readlag += period;      // increase read pointer lag
-                xfadevalue = 1;         // start crossfade
-            }
-        }
-        
-        readindex = refindex - readlag;
-        outputsample = read_sample(w, readindex);
-        
-        if(xfadevalue > 0)
-        {
-            outputsample *= (1 - xfadevalue);
-            outputsample += read_sample(w, readindex - jump) * xfadevalue;
-            xfadevalue -= xfadestep;
-        }
-        
-        *out++ = outputsample;
-        refindex += 1;
-        readlag -= readlagstep;
-    }
-    
-    w->readlag = readlag;               // state variables
-    w->jump = jump;
-    w->xfadelength = xfadelength;
-    w->xfadevalue = xfadevalue;
-}
-
-// read one sample from delay buffer, with linear interpolation
-static inline float read_sample(tSOLAD* const w, float floatindex)
-{
-    int index = (int)floatindex;
-    float fraction = floatindex - (float)index;
-    float *buf = w->delaybuf;
-    index &= LOOPMASK;
-    
-    return (buf[index] + (fraction * (buf[index+1] - buf[index])));
-}
-
-static void solad_init(tSOLAD* const w)
-{
-    w->timeindex = 0;
-    w->xfadevalue = -1;
-    w->period = INITPERIOD;
-    w->readlag = INITPERIOD;
-    w->blocksize = INITPERIOD;
-}
-
-/******************************************************************************/
-/***************************** private procedures *****************************/
-/******************************************************************************/
-
-#define REALFFT mayer_realfft
-#define REALIFFT mayer_realifft
-
-static void snac_analyzeframe(tSNAC* const s);
-static void snac_autocorrelation(tSNAC* const s);
-static void snac_normalize(tSNAC* const s);
-static void snac_pickpeak(tSNAC* const s);
-static void snac_periodandfidelity(tSNAC* const s);
-static void snac_biasbuf(tSNAC* const s);
-static float snac_spectralpeak(tSNAC* const s, float periodlength);
-
-
-/******************************************************************************/
-/******************************** constructor, destructor *********************/
-/******************************************************************************/
-
-
-void tSNAC_init(tSNAC* const s, int overlaparg)
-{
-    s->biasfactor = DEFBIAS;
-    s->timeindex = 0;
-    s->periodindex = 0;
-    s->periodlength = 0.;
-    s->fidelity = 0.;
-    s->minrms = DEFMINRMS;
-    s->framesize = SNAC_FRAME_SIZE;
-
-    s->inputbuf = (float*) leaf_alloc(sizeof(float) * SNAC_FRAME_SIZE);
-    s->processbuf = (float*) leaf_alloc(sizeof(float) * (SNAC_FRAME_SIZE * 2));
-    s->spectrumbuf = (float*) leaf_alloc(sizeof(float) * (SNAC_FRAME_SIZE / 2));
-    s->biasbuf = (float*) leaf_alloc(sizeof(float) * SNAC_FRAME_SIZE);
-    
-    snac_biasbuf(s);
-    tSNAC_setOverlap(s, overlaparg);
-}
-
-void tSNAC_free(tSNAC* const s)
-{
-    leaf_free(s->inputbuf);
-    leaf_free(s->processbuf);
-    leaf_free(s->spectrumbuf);
-    leaf_free(s->biasbuf);
-}
-/******************************************************************************/
-/************************** public access functions****************************/
-/******************************************************************************/
-
-
-void tSNAC_ioSamples(tSNAC* const s, float *in, float *out, int size)
-{
-    int timeindex = s->timeindex;
-    int mask = s->framesize - 1;
-    int outindex = 0;
-    float *inputbuf = s->inputbuf;
-    float *processbuf = s->processbuf;
-    
-    // call analysis function when it is time
-    if(!(timeindex & (s->framesize / s->overlap - 1))) snac_analyzeframe(s);
-    
-    while(size--)
-    {
-        inputbuf[timeindex] = *in++;
-        out[outindex++] = processbuf[timeindex++];
-        timeindex &= mask;
-    }
-    s->timeindex = timeindex;
-}
-
-void tSNAC_setOverlap(tSNAC* const s, int lap)
-{
-    if(!((lap==1)|(lap==2)|(lap==4)|(lap==8))) lap = DEFOVERLAP;
-    s->overlap = lap;
-}
-
-
-void tSNAC_setBias(tSNAC* const s, float bias)
-{
-    if(bias > 1.) bias = 1.;
-    if(bias < 0.) bias = 0.;
-    s->biasfactor = bias;
-    snac_biasbuf(s);
-    return;
-}
-
-
-void tSNAC_setMinRMS(tSNAC* const s, float rms)
-{
-    if(rms > 1.) rms = 1.;
-    if(rms < 0.) rms = 0.;
-    s->minrms = rms;
-    return;
-}
-
-
-float tSNAC_getPeriod(tSNAC* const s)
-{
-    return(s->periodlength);
-}
-
-
-float tSNAC_getFidelity(tSNAC* const s)
-{
-    return(s->fidelity);
-}
-
-
-/******************************************************************************/
-/***************************** private procedures *****************************/
-/******************************************************************************/
-
-
-// main analysis function
-static void snac_analyzeframe(tSNAC* const s)
-{
-    int n, tindex = s->timeindex;
-    int framesize = s->framesize;
-    int mask = framesize - 1;
-    float norm = 1. / sqrt((float)(framesize * 2));
-    
-    float *inputbuf = s->inputbuf;
-    float *processbuf = s->processbuf;
-    
-    // copy input to processing buffers
-    for(n=0; n<framesize; n++)
-    {
-        processbuf[n] = inputbuf[tindex] * norm;
-        tindex++;
-        tindex &= mask;
-    }
-    
-    // zeropadding
-    for(n=framesize; n<(framesize<<1); n++) processbuf[n] = 0.;
-    
-    // call analysis procedures
-    snac_autocorrelation(s);
-    snac_normalize(s);
-    snac_pickpeak(s);
-    snac_periodandfidelity(s);
-}
-
-
-static void snac_autocorrelation(tSNAC* const s)
-{
-    int n, m;
-    int framesize = s->framesize;
-    int fftsize = framesize * 2;
-    float *processbuf = s->processbuf;
-    float *spectrumbuf = s->spectrumbuf;
-    
-    REALFFT(fftsize, processbuf);
-    
-    // compute power spectrum
-    processbuf[0] *= processbuf[0];                      // DC
-    processbuf[framesize] *= processbuf[framesize];      // Nyquist
-    
-    for(n=1; n<framesize; n++)
-    {
-        processbuf[n] = processbuf[n] * processbuf[n]
-        + processbuf[fftsize-n] * processbuf[fftsize-n]; // imag coefficients appear reversed
-        processbuf[fftsize-n] = 0.;
-    }
-    
-    // store power spectrum up to SR/4 for possible later use
-    for(m=0; m<(framesize>>1); m++)
-    {
-        spectrumbuf[m] = processbuf[m];
-    }
-    
-    // transform power spectrum to autocorrelation function
-    REALIFFT(fftsize, processbuf);
-    return;
-}
-
-
-static void snac_normalize(tSNAC* const s)
-{
-    int framesize = s->framesize;
-    int framesizeplustimeindex = s->framesize + s->timeindex;
-    int timeindexminusone = s->timeindex - 1;
-    int n, m;
-    int mask = framesize - 1;
-    int seek = framesize * SEEK;
-    float *inputbuf = s->inputbuf;
-    float *processbuf= s->processbuf;
-    float signal1, signal2;
-    
-    // minimum RMS implemented as minimum autocorrelation at index 0
-    // functionally equivalent to white noise floor
-    float rms = s->minrms / sqrt(1.0f / (float)framesize);
-    float minrzero = rms * rms;
-    float rzero = processbuf[0];
-    if(rzero < minrzero) rzero = minrzero;
-    double normintegral = (double)rzero * 2.;
-    
-    // normalize biased autocorrelation function
-    // inputbuf is circular buffer: timeindex may be non-zero when overlap > 1
-    processbuf[0] = 1;
-    for(n=1, m=s->timeindex+1; n<seek; n++, m++)
-    {
-        signal1 = inputbuf[(n + timeindexminusone)&mask];
-        signal2 = inputbuf[(framesizeplustimeindex - n)&mask];
-        normintegral -= (double)(signal1 * signal1 + signal2 * signal2);
-        processbuf[n] /= (float)normintegral * 0.5f;
-    }
-    
-    // flush instable function tail
-    for(n = seek; n<framesize; n++) processbuf[n] = 0.;
-    return;
-}
-
-
-static void snac_periodandfidelity(tSNAC* const s)
-{
-    float periodlength;
-    
-    if(s->periodindex)
-    {
-        periodlength = (float)s->periodindex +
-        interpolate3phase(s->processbuf, s->periodindex);
-        if(periodlength < 8) periodlength = snac_spectralpeak(s, periodlength);
-        s->periodlength = periodlength;
-        s->fidelity = interpolate3max(s->processbuf, s->periodindex);
-    }
-    return;
-}
-
-// select the peak which most probably represents period length
-static void snac_pickpeak(tSNAC* const s)
-{
-    int n, peakindex=0;
-    int seek = s->framesize * SEEK;
-    float *processbuf= s->processbuf;
-    float maxvalue = 0.;
-    float biasedpeak;
-    float *biasbuf = s->biasbuf;
-    
-    // skip main lobe
-    for(n=1; n<seek; n++)
-    {
-        if(processbuf[n] < 0.) break;
-    }
-    
-    // find interpolated / biased maximum in SNAC function
-    // interpolation finds the 'real maximum'
-    // biasing favours the first candidate
-    for(; n<seek-1; n++)
-    {
-        if(processbuf[n] >= processbuf[n-1])
-        {
-            if(processbuf[n] > processbuf[n+1])     // we have a local peak
-            {
-                biasedpeak = interpolate3max(processbuf, n) * biasbuf[n];
-                
-                if(biasedpeak > maxvalue)
-                {
-                    maxvalue = biasedpeak;
-                    peakindex = n;
-                }
-            }
-        }
-    }
-    s->periodindex = peakindex;
-    return;
-}
-
-
-// verify period length via frequency domain (up till SR/4)
-// frequency domain is more precise than lag domain for period lengths < 8
-// argument 'periodlength' is initial estimation from autocorrelation
-static float snac_spectralpeak(tSNAC* const s, float periodlength)
-{
-    if(periodlength < 4.) return periodlength;
-    
-    float max = 0.;
-    int n, startbin, stopbin, peakbin = 0;
-    int spectrumsize = s->framesize>>1;
-    float *spectrumbuf = s->spectrumbuf;
-    float peaklocation = (float)(s->framesize * 2.) / periodlength;
-    
-    startbin = (int)(peaklocation * 0.8 + 0.5);
-    if(startbin < 1) startbin = 1;
-    stopbin = (int)(peaklocation * 1.25 + 0.5);
-    if(stopbin >= spectrumsize - 1) stopbin = spectrumsize - 1;
-    
-    for(n=startbin; n<stopbin; n++)
-    {
-        if(spectrumbuf[n] >= spectrumbuf[n-1])
-        {
-            if(spectrumbuf[n] > spectrumbuf[n+1])
-            {
-                if(spectrumbuf[n] > max)
-                {
-                    max = spectrumbuf[n];
-                    peakbin = n;
-                }
-            }
-        }
-    }
-    
-    // calculate amplitudes in peak region
-    for(n=(peakbin-1); n<(peakbin+2); n++)
-    {
-        spectrumbuf[n] = sqrt(spectrumbuf[n]);
-    }
-    
-    peaklocation = (float)peakbin + interpolate3phase(spectrumbuf, peakbin);
-    periodlength = (float)(s->framesize * 2.0f) / peaklocation;
-    
-    return periodlength;
-}
-
-
-// modified logarithmic bias function
-static void snac_biasbuf(tSNAC* const s)
-{
-    int n;
-    int maxperiod = (int)(s->framesize * (float)SEEK);
-    float bias = s->biasfactor / log((float)(maxperiod - 4));
-    float *biasbuf = s->biasbuf;
-    
-    for(n=0; n<5; n++)    // periods < 5 samples can't be tracked
-    {
-        biasbuf[n] = 0.;
-    }
-    
-    for(n=5; n<maxperiod; n++)
-    {
-        biasbuf[n] = 1.0f - (float)log(n - 4) * bias;
-    }
-}
-
-/********Private function prototypes**********/
-static void atkdtk_init(tAtkDtk* const a, int blocksize, int atk, int rel);
-static void atkdtk_envelope(tAtkDtk* const a, float *in);
-
-/********Constructor/Destructor***************/
-
-void tAtkDtk_init(tAtkDtk* const a, int blocksize)
-{
-    atkdtk_init(a, blocksize, DEFATTACK, DEFRELEASE);
-}
-
-void tAtkDtk_init_expanded(tAtkDtk* const a, int blocksize, int atk, int rel)
-{
-    atkdtk_init(a, blocksize, atk, rel);
-}
-
-void tAtkDtk_free(tAtkDtk *a)
-{
-    
-}
-
-/*******Public Functions***********/
-
-
-void tAtkDtk_setBlocksize(tAtkDtk* const a, int size)
-{
-    
-    if(!((size==64)|(size==128)|(size==256)|(size==512)|(size==1024)|(size==2048)))
-        size = DEFBLOCKSIZE;
-    a->blocksize = size;
-    
-    return;
-    
-}
-
-void tAtkDtk_setSamplerate(tAtkDtk* const a, int inRate)
-{
-    a->samplerate = inRate;
-    
-    //Reset atk and rel to recalculate coeff
-    tAtkDtk_setAtk(a, a->atk);
-    tAtkDtk_setRel(a, a->rel);
-    
-    return;
-}
-
-void tAtkDtk_setThreshold(tAtkDtk* const a, float thres)
-{
-    a->threshold = thres;
-    return;
-}
-
-void tAtkDtk_setAtk(tAtkDtk* const a, int inAtk)
-{
-    a->atk = inAtk;
-    a->atk_coeff = pow(0.01, 1.0/(a->atk * a->samplerate * 0.001));
-    
-    return;
-}
-
-void tAtkDtk_setRel(tAtkDtk* const a, int inRel)
-{
-    a->rel = inRel;
-    a->rel_coeff = pow(0.01, 1.0/(a->rel * a->samplerate * 0.001));
-    
-    return;
-}
-
-
-int tAtkDtk_detect(tAtkDtk* const a, float *in)
-{
-    int result;
-    
-    atkdtk_envelope(a, in);
-    
-    if(a->env >= a->prevAmp*2) //2 times greater = 6dB increase
-        result = 1;
-    else
-        result = 0;
-    
-    a->prevAmp = a->env;
-    
-    return result;
-    
-}
-
-/*******Private Functions**********/
-
-static void atkdtk_init(tAtkDtk* const a, int blocksize, int atk, int rel)
-{
-    a->env = 0;
-    a->blocksize = blocksize;
-    a->threshold = DEFTHRESHOLD;
-    a->samplerate = leaf.sampleRate;
-    a->prevAmp = 0;
-    
-    a->env = 0;
-    
-    tAtkDtk_setAtk(a, atk);
-    tAtkDtk_setRel(a, rel);
-}
-
-static void atkdtk_envelope(tAtkDtk* const a, float *in)
-{
-    int i = 0;
-    float tmp;
-    for(i = 0; i < a->blocksize; ++i){
-        tmp = fastabs(in[i]);
-        
-        if(tmp > a->env)
-            a->env = a->atk_coeff * (a->env - tmp) + tmp;
-        else
-            a->env = a->rel_coeff * (a->env - tmp) + tmp;
-    }
-    
-}
-
--- a/LEAF/Src/leaf-vocoder.c
+++ /dev/null
@@ -1,400 +1,0 @@
-/*==============================================================================
-
-    leaf-vocoder.c
-    Created: 20 Jan 2017 12:01:54pm
-    Author:  Michael R Mulshine
-
-==============================================================================*/
-
-#if _WIN32 || _WIN64
-
-#include "..\Inc\leaf-vocoder.h"
-#include "..\leaf.h"
-
-#else
-
-#include "../Inc/leaf-vocoder.h"
-#include "../leaf.h"
-
-#endif
-
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- *
- *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-void tTalkbox_init(tTalkbox* const v, int bufsize)
-{
-    v->param[0] = 0.5f;  //wet
-    v->param[1] = 0.0f;  //dry
-    v->param[2] = 0; // Swap
-    v->param[3] = 1.0f;  //quality
-    
-    v->bufsize = bufsize;
-    
-    v->car0 =   (float*) leaf_alloc(sizeof(float) * v->bufsize);
-    v->car1 =   (float*) leaf_alloc(sizeof(float) * v->bufsize);
-    v->window = (float*) leaf_alloc(sizeof(float) * v->bufsize);
-    v->buf0 =   (float*) leaf_alloc(sizeof(float) * v->bufsize);
-    v->buf1 =   (float*) leaf_alloc(sizeof(float) * v->bufsize);
-    
-    tTalkbox_update(v);
-}
-
-void tTalkbox_free(tTalkbox* const v)
-{
-    leaf_free(v->car0);
-    leaf_free(v->car1);
-    leaf_free(v->window);
-    leaf_free(v->buf0);
-    leaf_free(v->buf1);
-}
-
-void tTalkbox_update(tTalkbox* const v) ///update internal parameters...
-{
-    float fs = leaf.sampleRate;
-    if(fs <  8000.0f) fs =  8000.0f;
-    if(fs > 96000.0f) fs = 96000.0f;
-    
-    int32_t n = (int32_t)(0.01633f * fs);
-    if(n > v->bufsize) n = v->bufsize;
-    
-    //O = (VstInt32)(0.0005f * fs);
-    v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * fs);
-    
-    if(n != v->N) //recalc hanning window
-    {
-        v->N = n;
-        float dp = TWO_PI / v->N;
-        float p = 0.0f;
-        for(n=0; n<v->N; n++)
-        {
-            v->window[n] = 0.5f - 0.5f * cosf(p);
-            p += dp;
-        }
-    }
-    v->wet = 0.5f * v->param[0] * v->param[0];
-    v->dry = 2.0f * v->param[1] * v->param[1];
-}
-
-void tTalkbox_suspend(tTalkbox* const v) ///clear any buffers...
-{
-    v->pos = v->K = 0;
-    v->emphasis = 0.0f;
-    v->FX = 0;
-    
-    v->u0 = v->u1 = v->u2 = v->u3 = v->u4 = 0.0f;
-    v->d0 = v->d1 = v->d2 = v->d3 = v->d4 = 0.0f;
-    
-    for (int32_t i = 0; i < v->bufsize; i++)
-    {
-        v->buf0[i] = 0;
-        v->buf1[i] = 0;
-        v->car0[i] = 0;
-        v->car1[i] = 0;
-    }
-}
-
-
-#define ORD_MAX           100 // Was 50. Increasing this gets rid of glitchiness, lowering it breaks it; not sure how it affects performance
-void tTalkbox_lpc(float *buf, float *car, int32_t n, int32_t o)
-{
-    float z[ORD_MAX], r[ORD_MAX], k[ORD_MAX], G, x;
-    int32_t i, j, nn=n;
-    
-    for(j=0; j<=o; j++, nn--)  //buf[] is already emphasized and windowed
-    {
-        z[j] = r[j] = 0.0f;
-        for(i=0; i<nn; i++) r[j] += buf[i] * buf[i+j]; //autocorrelation
-    }
-    r[0] *= 1.001f;  //stability fix
-    
-    float min = 0.00001f;
-    if(r[0] < min) { for(i=0; i<n; i++) buf[i] = 0.0f; return; }
-    
-    tTalkbox_lpcDurbin(r, o, k, &G);  //calc reflection coeffs
-    
-    for(i=0; i<=o; i++)
-    {
-        if(k[i] > 0.995f) k[i] = 0.995f; else if(k[i] < -0.995f) k[i] = -.995f;
-    }
-    
-    for(i=0; i<n; i++)
-    {
-        x = G * car[i];
-        for(j=o; j>0; j--)  //lattice filter
-        {
-            x -= k[j] * z[j-1];
-            z[j] = z[j-1] + k[j] * x;
-        }
-        buf[i] = z[0] = x;  //output buf[] will be windowed elsewhere
-    }
-}
-
-
-void tTalkbox_lpcDurbin(float *r, int p, float *k, float *g)
-{
-    int i, j;
-    float a[ORD_MAX], at[ORD_MAX], e=r[0];
-    
-    for(i=0; i<=p; i++) a[i] = at[i] = 0.0f; //probably don't need to clear at[] or k[]
-    
-    for(i=1; i<=p; i++)
-    {
-        k[i] = -r[i];
-        
-        for(j=1; j<i; j++)
-        {
-            at[j] = a[j];
-            k[i] -= a[j] * r[i-j];
-        }
-        if(fabs(e) < 1.0e-20f) { e = 0.0f;  break; }
-        k[i] /= e; // This might be costing us
-        
-        a[i] = k[i];
-        for(j=1; j<i; j++) a[j] = at[j] + k[i] * at[i-j];
-        
-        e *= 1.0f - k[i] * k[i];
-    }
-    
-    if(e < 1.0e-20f) e = 0.0f;
-    *g = sqrtf(e);
-}
-
-float tTalkbox_tick(tTalkbox* const v, float synth, float voice)
-{
-
-    int32_t  p0=v->pos, p1 = (v->pos + v->N/2) % v->N;
-    float e=v->emphasis, w, o, x, dr, fx=v->FX;
-    float p, q, h0=0.3f, h1=0.77f;
-    
-    o = voice;
-    x = synth;
-    
-    dr = o;
-    
-    p = v->d0 + h0 *  x; v->d0 = v->d1;  v->d1 = x  - h0 * p;
-    q = v->d2 + h1 * v->d4; v->d2 = v->d3;  v->d3 = v->d4 - h1 * q;
-    v->d4 = x;
-    x = p + q;
-    
-    if(v->K++)
-    {
-        v->K = 0;
-        
-        v->car0[p0] = v->car1[p1] = x; //carrier input
-        
-        x = o - e;  e = o;  //6dB/oct pre-emphasis
-        
-        w = v->window[p0]; fx = v->buf0[p0] * w;  v->buf0[p0] = x * w;  //50% overlapping hanning windows
-        if(++p0 >= v->N) { tTalkbox_lpc(v->buf0, v->car0, v->N, v->O);  p0 = 0; }
-        
-        w = 1.0f - w;  fx += v->buf1[p1] * w;  v->buf1[p1] = x * w;
-        if(++p1 >= v->N) { tTalkbox_lpc(v->buf1, v->car1, v->N, v->O);  p1 = 0; }
-    }
-    
-    p = v->u0 + h0 * fx; v->u0 = v->u1;  v->u1 = fx - h0 * p;
-    q = v->u2 + h1 * v->u4; v->u2 = v->u3;  v->u3 = v->u4 - h1 * q;
-    v->u4 = fx;
-    x = p + q;
-    
-    o = x;
-    
-    v->emphasis = e;
-    v->pos = p0;
-    v->FX = fx;
-
-    float den = 1.0e-10f; //(float)pow(10.0f, -10.0f * param[4]);
-    if(fabs(v->d0) < den) v->d0 = 0.0f; //anti-denormal (doesn't seem necessary but P4?)
-    if(fabs(v->d1) < den) v->d1 = 0.0f;
-    if(fabs(v->d2) < den) v->d2 = 0.0f;
-    if(fabs(v->d3) < den) v->d3 = 0.0f;
-    if(fabs(v->u0) < den) v->u0 = 0.0f;
-    if(fabs(v->u1) < den) v->u1 = 0.0f;
-    if(fabs(v->u2) < den) v->u2 = 0.0f;
-    if(fabs(v->u3) < den) v->u3 = 0.0f;
-    return o;
-}
-
-void tTalkbox_setQuality(tTalkbox* const v, float quality)
-{
-	v->param[3] = quality;
-	v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * leaf.sampleRate);
-}
-
-void   tVocoder_init        (tVocoder* const v)
-{
-    v->param[0] = 0.33f;  //input select
-    v->param[1] = 0.50f;  //output dB
-    v->param[2] = 0.40f;  //hi thru
-    v->param[3] = 0.40f;  //hi band
-    v->param[4] = 0.16f;  //envelope
-    v->param[5] = 0.55f;  //filter q
-    v->param[6] = 0.6667f;//freq range
-    v->param[7] = 0.33f;  //num bands
-    
-    tVocoder_update(v);
-}
-
-void tVocoder_free (tVocoder* const v)
-{
-    
-}
-
-void        tVocoder_update      (tVocoder* const v)
-{
-    float tpofs = 6.2831853f * leaf.invSampleRate;
-    
-    float rr, th, re;
-    
-    float sh;
-    
-    int32_t i;
-    
-    v->gain = (float)pow(10.0f, 2.0f * v->param[1] - 3.0f * v->param[5] - 2.0f);
-    
-    v->thru = (float)pow(10.0f, 0.5f + 2.0f * v->param[1]);
-    v->high =  v->param[3] * v->param[3] * v->param[3] * v->thru;
-    v->thru *= v->param[2] * v->param[2] * v->param[2];
-    
-    if(v->param[7]<0.5f)
-    {
-        v->nbnd=8;
-        re=0.003f;
-        v->f[1][2] = 3000.0f;
-        v->f[2][2] = 2200.0f;
-        v->f[3][2] = 1500.0f;
-        v->f[4][2] = 1080.0f;
-        v->f[5][2] = 700.0f;
-        v->f[6][2] = 390.0f;
-        v->f[7][2] = 190.0f;
-    }
-    else
-    {
-        v->nbnd=16;
-        re=0.0015f;
-        v->f[ 1][2] = 5000.0f; //+1000
-        v->f[ 2][2] = 4000.0f; //+750
-        v->f[ 3][2] = 3250.0f; //+500
-        v->f[ 4][2] = 2750.0f; //+450
-        v->f[ 5][2] = 2300.0f; //+300
-        v->f[ 6][2] = 2000.0f; //+250
-        v->f[ 7][2] = 1750.0f; //+250
-        v->f[ 8][2] = 1500.0f; //+250
-        v->f[ 9][2] = 1250.0f; //+250
-        v->f[10][2] = 1000.0f; //+250
-        v->f[11][2] =  750.0f; //+210
-        v->f[12][2] =  540.0f; //+190
-        v->f[13][2] =  350.0f; //+155
-        v->f[14][2] =  195.0f; //+100
-        v->f[15][2] =   95.0f;
-    }
-    
-    if(v->param[4]<0.05f) //freeze
-    {
-        for(i=0;i<v->nbnd;i++) v->f[i][12]=0.0f;
-    }
-    else
-    {
-        v->f[0][12] = (float)pow(10.0, -1.7 - 2.7f * v->param[4]); //envelope speed
-        
-        rr = 0.022f / (float)v->nbnd; //minimum proportional to frequency to stop distortion
-        for(i=1;i<v->nbnd;i++)
-        {
-            v->f[i][12] = (float)(0.025 - rr * (double)i);
-            if(v->f[0][12] < v->f[i][12]) v->f[i][12] = v->f[0][12];
-        }
-        v->f[0][12] = 0.5f * v->f[0][12]; //only top band is at full rate
-    }
-    
-    rr = 1.0 - pow(10.0f, -1.0f - 1.2f * v->param[5]);
-    sh = (float)pow(2.0f, 3.0f * v->param[6] - 1.0f); //filter bank range shift
-    
-    for(i=1;i<v->nbnd;i++)
-    {
-        v->f[i][2] *= sh;
-        th = acos((2.0 * rr * cos(tpofs * v->f[i][2])) / (1.0 + rr * rr));
-        v->f[i][0] = (float)(2.0 * rr * cos(th)); //a0
-        v->f[i][1] = (float)(-rr * rr);           //a1
-        //was .98
-        v->f[i][2] *= 0.96f; //shift 2nd stage slightly to stop high resonance peaks
-        th = acos((2.0 * rr * cos(tpofs * v->f[i][2])) / (1.0 + rr * rr));
-        v->f[i][2] = (float)(2.0 * rr * cos(th));
-    }
-}
-
-float       tVocoder_tick        (tVocoder* const v, float synth, float voice)
-{
-    float a, b, o=0.0f, aa, bb, oo = v->kout, g = v->gain, ht = v->thru, hh = v->high, tmp;
-    uint32_t i, k = v->kval, nb = v->nbnd;
-
-    a = voice; //speech
-    b = synth; //synth
-    
-    tmp = a - v->f[0][7]; //integrate modulator for HF band and filter bank pre-emphasis
-    v->f[0][7] = a;
-    a = tmp;
-    
-    if(tmp<0.0f) tmp = -tmp;
-    v->f[0][11] -= v->f[0][12] * (v->f[0][11] - tmp);      //high band envelope
-    o = v->f[0][11] * (ht * a + hh * (b - v->f[0][3])); //high band + high thru
-    
-    v->f[0][3] = b; //integrate carrier for HF band
-    
-    if(++k & 0x1) //this block runs at half sample rate
-    {
-        oo = 0.0f;
-        aa = a + v->f[0][9] - v->f[0][8] - v->f[0][8];  //apply zeros here instead of in each reson
-        v->f[0][9] = v->f[0][8];  v->f[0][8] = a;
-        bb = b + v->f[0][5] - v->f[0][4] - v->f[0][4];
-        v->f[0][5] = v->f[0][4];  v->f[0][4] = b;
-        
-        for(i=1; i<nb; i++) //filter bank: 4th-order band pass
-        {
-            tmp = v->f[i][0] * v->f[i][3] + v->f[i][1] * v->f[i][4] + bb;
-            v->f[i][4] = v->f[i][3];
-            v->f[i][3] = tmp;
-            tmp += v->f[i][2] * v->f[i][5] + v->f[i][1] * v->f[i][6];
-            v->f[i][6] = v->f[i][5];
-            v->f[i][5] = tmp;
-            
-            tmp = v->f[i][0] * v->f[i][7] + v->f[i][1] * v->f[i][8] + aa;
-            v->f[i][8] = v->f[i][7];
-            v->f[i][7] = tmp;
-            tmp += v->f[i][2] * v->f[i][9] + v->f[i][1] * v->f[i][10];
-            v->f[i][10] = v->f[i][9];
-            v->f[i][9] = tmp;
-            
-            if(tmp<0.0f) tmp = -tmp;
-            v->f[i][11] -= v->f[i][12] * (v->f[i][11] - tmp);
-            oo += v->f[i][5] * v->f[i][11];
-        }
-    }
-    o += oo * g; //effect of interpolating back up to Fs would be minimal (aliasing >16kHz)
-
-    v->kout = oo;
-    v->kval = k & 0x1;
-    if(fabs(v->f[0][11])<1.0e-10) v->f[0][11] = 0.0f; //catch HF envelope denormal
-    
-    for(i=1;i<nb;i++)
-        if(fabs(v->f[i][3])<1.0e-10 || fabs(v->f[i][7])<1.0e-10)
-            for(k=3; k<12; k++) v->f[i][k] = 0.0f; //catch reson & envelope denormals
-    
-    if(fabs(o)>10.0f) tVocoder_suspend(v); //catch instability
-    
-    return o;
-    
-}
-
-void        tVocoder_suspend     (tVocoder* const v)
-{
-    int32_t i, j;
-    
-    for(i=0; i<v->nbnd; i++) for(j=3; j<12; j++) v->f[i][j] = 0.0f; //zero band filters and envelopes
-    v->kout = 0.0f;
-    v->kval = 0;
-}
-
--- a/LEAF/Src/leaf-wavefolder.c
+++ /dev/null
@@ -1,114 +1,0 @@
-/*==============================================================================
-
-    leaf-wavefolder.c
-    Created: 30 Nov 2018 11:56:49am
-    Author:  airship
-
-==============================================================================*/
-
-#if _WIN32 || _WIN64
-
-#include "..\Inc\leaf-wavefolder.h"
-
-#else
-
-#include "../Inc/leaf-wavefolder.h"
-
-#endif
-
-void tLockhartWavefolder_init(tLockhartWavefolder* const w)
-{
-    w->Ln1 = 0.0;
-    w->Fn1 = 0.0;
-    w->xn1 = 0.0f;
-}
-
-void tLockhardWavefolder_free(tLockhartWavefolder* const w)
-{
-    
-}
-
-double tLockhartWavefolderLambert(double x, double ln)
-{
-    double thresh, w, expw, p, r, s, err;
-    // Error threshold
-    thresh = 10e-6;
-    // Initial guess (use previous value)
-    w = ln;
-    
-    // Haley's method (Sec. 4.2 of the paper)
-    for(int i=0; i<100; i+=1) {
-        
-        expw = exp(w);
-        
-        p = w*expw - x;
-        r = (w+1.0)*expw;
-        s = (w+2.0)/(2.0*(w+1.0));        err = (p/(r-(p*s)));
-        
-        if (fabs(err)<thresh) {
-            break;
-        }
-        if (isnan(err))
-        {
-            break;
-        }
-        
-        w = w - err;
-    }
-    return w;
-}
-
-float tLockhartWavefolder_tick(tLockhartWavefolder* const w, float samp)
-{
-    
-    float out = 0.0f;
-    // Constants
-    double RL = 7.5e3;
-    double R = 15e3;
-    double VT = 26e-3;
-    double Is = 10e-16;
-    
-    double a = 2.0*RL/R;
-    double b = (R+2.0*RL)/(VT*R);
-    double d = (RL*Is)/VT;
-    
-    // Antialiasing error threshold
-    double thresh = 10e-10;
-    
-    // Compute Antiderivative
-    int l = (samp > 0) - (samp < 0);
-    double u = d*exp(l*b*samp);
-    double Ln = tLockhartWavefolderLambert(u,w->Ln1);
-    double Fn = (0.5*VT/b)*(Ln*(Ln + 2.0)) - 0.5*a*samp*samp;
-    
-    // Check for ill-conditioning
-    if (fabs(samp-w->xn1)<thresh) {
-        
-        // Compute Averaged Wavefolder Output
-        double xn = 0.5*(samp+w->xn1);
-        u = d*exp(l*b*xn);
-        Ln = tLockhartWavefolderLambert(u,w->Ln1);
-        out = (float) (l*VT*Ln - a*xn);
-        if (isnan(out))
-        {
-            ;
-        }
-        
-    }
-    else {
-        
-        // Apply AA Form
-        out = (float) ((Fn-w->Fn1)/(samp-w->xn1));
-        if (isnan(out))
-        {
-            ;
-        }
-    }
-    
-    // Update States
-    w->Ln1 = Ln;
-    w->Fn1 = Fn;
-    w->xn1 = samp;
-    
-    return out;
-}
--- a/LEAF/leaf.h
+++ b/LEAF/leaf.h
@@ -22,22 +22,21 @@
 #include ".\Inc\leaf-global.h"
 #include ".\Inc\leaf-math.h"
 #include ".\Inc\leaf-mempool.h"
-#include ".\Inc\leaf-utilities.h"
+#include ".\Inc\leaf-tables.h"
+#include ".\Inc\leaf-tables.h"
+#include ".\Inc\leaf-oscillators.h"
+#include ".\Inc\leaf-filters.h"
 #include ".\Inc\leaf-delay.h"
-#include ".\Inc\leaf-filter.h"
-#include ".\Inc\leaf-oscillator.h"
-#include ".\Inc\leaf-oversampler.h"
 #include ".\Inc\leaf-reverb.h"
-#include ".\Inc\leaf-vocoder.h"
-#include ".\Inc\leaf-808.h"
-#include ".\Inc\leaf-string.h"
-#include ".\Inc\leaf-pitch.h"
-#include ".\Inc\leaf-formant.h"
+#include ".\Inc\leaf-effects.h"
+#include ".\Inc\leaf-envelopes.h"
+#include ".\Inc\leaf-dynamics.h"
+#include ".\Inc\leaf-analysis.h"
+#include ".\Inc\leaf-instruments.h"
 #include ".\Inc\leaf-midi.h"
-#include ".\Inc\leaf-sample.h"
-#include ".\Inc\leaf-crusher.h"
-#include ".\Inc\leaf-wavefolder.h"
-#include ".\Inc\leaf-tables.h"
+#include ".\Inc\leaf-sampling.h"
+#include ".\Inc\leaf-physical.h"
+#include ".\Inc\leaf-electrical.h"
 
 #else
 
@@ -44,23 +43,21 @@
 #include "./Inc/leaf-global.h"
 #include "./Inc/leaf-math.h"
 #include "./Inc/leaf-mempool.h"
-#include "./Inc/leaf-utilities.h"
+#include "./Inc/leaf-tables.h"
+#include "./Inc/leaf-tables.h"
+#include "./Inc/leaf-oscillators.h"
+#include "./Inc/leaf-filters.h"
 #include "./Inc/leaf-delay.h"
-#include "./Inc/leaf-filter.h"
-#include "./Inc/leaf-oscillator.h"
-#include "./Inc/leaf-oversampler.h"
 #include "./Inc/leaf-reverb.h"
-#include "./Inc/leaf-vocoder.h"
-#include "./Inc/leaf-808.h"
-#include "./Inc/leaf-string.h"
-#include "./Inc/leaf-pitch.h"
-#include "./Inc/leaf-formant.h"
+#include "./Inc/leaf-effects.h"
+#include "./Inc/leaf-envelopes.h"
+#include "./Inc/leaf-dynamics.h"
+#include "./Inc/leaf-analysis.h"
+#include "./Inc/leaf-instruments.h"
 #include "./Inc/leaf-midi.h"
-#include "./Inc/leaf-sample.h"
-#include "./Inc/leaf-crusher.h"
-#include "./Inc/leaf-wavefolder.h"
-#include "./Inc/leaf-tables.h"
-#include "./Inc/leaf-WDF.h"
+#include "./Inc/leaf-sampling.h"
+#include "./Inc/leaf-physical.h"
+#include "./Inc/leaf-electrical.h"
 
 #endif
 
--- a/LEAF_JUCEPlugin/LEAF.jucer
+++ b/LEAF_JUCEPlugin/LEAF.jucer
@@ -26,53 +26,51 @@
           <FILE id="IwBoc4" name="leaf-global.h" compile="0" resource="0" file="../LEAF/Inc/leaf-global.h"/>
           <FILE id="cmehFw" name="leaf-math.h" compile="0" resource="0" file="../LEAF/Inc/leaf-math.h"/>
           <FILE id="XQTGHV" name="leaf-mempool.h" compile="0" resource="0" file="../LEAF/Inc/leaf-mempool.h"/>
-          <FILE id="k0yQ8k" name="leaf-808.h" compile="0" resource="0" file="../LEAF/Inc/leaf-808.h"/>
+          <FILE id="JvZKsP" name="leaf-tables.h" compile="0" resource="0" file="../LEAF/Inc/leaf-tables.h"/>
+          <FILE id="ZBcTKF" name="leaf-oscillators.h" compile="0" resource="0"
+                file="../LEAF/Inc/leaf-oscillators.h"/>
+          <FILE id="EnRmjE" name="leaf-filters.h" compile="0" resource="0" file="../LEAF/Inc/leaf-filters.h"/>
           <FILE id="wn8tAr" name="leaf-delay.h" compile="0" resource="0" file="../LEAF/Inc/leaf-delay.h"/>
-          <FILE id="EnRmjE" name="leaf-filter.h" compile="0" resource="0" file="../LEAF/Inc/leaf-filter.h"/>
-          <FILE id="dWHebV" name="leaf-formant.h" compile="0" resource="0" file="../LEAF/Inc/leaf-formant.h"/>
-          <FILE id="pXe6b5" name="leaf-midi.h" compile="0" resource="0" file="../LEAF/Inc/leaf-midi.h"/>
-          <FILE id="ZBcTKF" name="leaf-oscillator.h" compile="0" resource="0"
-                file="../LEAF/Inc/leaf-oscillator.h"/>
-          <FILE id="LPMRGU" name="leaf-oversampler.h" compile="0" resource="0"
-                file="../LEAF/Inc/leaf-oversampler.h"/>
-          <FILE id="NekKkK" name="leaf-pitch.h" compile="0" resource="0" file="../LEAF/Inc/leaf-pitch.h"/>
           <FILE id="XmL4ZE" name="leaf-reverb.h" compile="0" resource="0" file="../LEAF/Inc/leaf-reverb.h"/>
-          <FILE id="KQca5l" name="leaf-string.h" compile="0" resource="0" file="../LEAF/Inc/leaf-string.h"/>
-          <FILE id="OS2D83" name="leaf-utilities.h" compile="0" resource="0"
-                file="../LEAF/Inc/leaf-utilities.h"/>
-          <FILE id="Szb5LP" name="leaf-vocoder.h" compile="0" resource="0" file="../LEAF/Inc/leaf-vocoder.h"/>
-          <FILE id="T6KXi7" name="leaf-sample.h" compile="0" resource="0" file="../LEAF/Inc/leaf-sample.h"/>
-          <FILE id="bpUZCA" name="leaf-crusher.h" compile="0" resource="0" file="../LEAF/Inc/leaf-crusher.h"/>
-          <FILE id="PRkOp2" name="leaf-wavefolder.h" compile="0" resource="0"
-                file="../LEAF/Inc/leaf-wavefolder.h"/>
-          <FILE id="lJdTFA" name="leaf-WDF.h" compile="0" resource="0" file="../LEAF/Inc/leaf-WDF.h"/>
-          <FILE id="JvZKsP" name="leaf-tables.h" compile="0" resource="0" file="../LEAF/Inc/leaf-tables.h"/>
+          <FILE id="dWHebV" name="leaf-distortion.h" compile="0" resource="0"
+                file="../LEAF/Inc/leaf-distortion.h"/>
+          <FILE id="Szb5LP" name="leaf-effects.h" compile="0" resource="0" file="../LEAF/Inc/leaf-effects.h"/>
+          <FILE id="OS2D83" name="leaf-envelopes.h" compile="0" resource="0"
+                file="../LEAF/Inc/leaf-envelopes.h"/>
+          <FILE id="PRkOp2" name="leaf-dynamics.h" compile="0" resource="0" file="../LEAF/Inc/leaf-dynamics.h"/>
+          <FILE id="LPMRGU" name="leaf-analysis.h" compile="0" resource="0" file="../LEAF/Inc/leaf-analysis.h"/>
+          <FILE id="k0yQ8k" name="leaf-instruments.h" compile="0" resource="0"
+                file="../LEAF/Inc/leaf-instruments.h"/>
+          <FILE id="pXe6b5" name="leaf-midi.h" compile="0" resource="0" file="../LEAF/Inc/leaf-midi.h"/>
+          <FILE id="T6KXi7" name="leaf-sampling.h" compile="0" resource="0" file="../LEAF/Inc/leaf-sampling.h"/>
+          <FILE id="KQca5l" name="leaf-physical.h" compile="0" resource="0" file="../LEAF/Inc/leaf-physical.h"/>
+          <FILE id="lJdTFA" name="leaf-electrical.h" compile="0" resource="0"
+                file="../LEAF/Inc/leaf-electrical.h"/>
         </GROUP>
         <GROUP id="{A3AE8C8C-29BA-ADB3-DD7D-EEDC2F7B58F3}" name="Src">
-          <FILE id="HbG7LO" name="leaf-808.c" compile="1" resource="0" file="../LEAF/Src/leaf-808.c"/>
-          <FILE id="lLb7eq" name="leaf-delay.c" compile="1" resource="0" file="../LEAF/Src/leaf-delay.c"/>
-          <FILE id="nh9xAo" name="leaf-filter.c" compile="1" resource="0" file="../LEAF/Src/leaf-filter.c"/>
-          <FILE id="DPGZGc" name="leaf-formant.c" compile="1" resource="0" file="../LEAF/Src/leaf-formant.c"/>
+          <FILE id="BFkVGu" name="leaf.c" compile="1" resource="0" file="../LEAF/Src/leaf.c"/>
           <FILE id="g41P2E" name="leaf-math.c" compile="1" resource="0" file="../LEAF/Src/leaf-math.c"/>
           <FILE id="Uc4jO6" name="leaf-mempool.c" compile="1" resource="0" file="../LEAF/Src/leaf-mempool.c"/>
-          <FILE id="LuoIDh" name="leaf-midi.c" compile="1" resource="0" file="../LEAF/Src/leaf-midi.c"/>
-          <FILE id="q5y59A" name="leaf-oscillator.c" compile="1" resource="0"
-                file="../LEAF/Src/leaf-oscillator.c"/>
-          <FILE id="E8JjWS" name="leaf-oversampler.c" compile="1" resource="0"
-                file="../LEAF/Src/leaf-oversampler.c"/>
-          <FILE id="eHUTvP" name="leaf-pitch.c" compile="1" resource="0" file="../LEAF/Src/leaf-pitch.c"/>
-          <FILE id="uyYwEd" name="leaf-reverb.c" compile="1" resource="0" file="../LEAF/Src/leaf-reverb.c"/>
-          <FILE id="dgAVr5" name="leaf-string.c" compile="1" resource="0" file="../LEAF/Src/leaf-string.c"/>
-          <FILE id="uKHzgz" name="leaf-utilities.c" compile="1" resource="0"
-                file="../LEAF/Src/leaf-utilities.c"/>
-          <FILE id="u1aLLR" name="leaf-vocoder.c" compile="1" resource="0" file="../LEAF/Src/leaf-vocoder.c"/>
-          <FILE id="nmtoFJ" name="leaf-sample.c" compile="1" resource="0" file="../LEAF/Src/leaf-sample.c"/>
-          <FILE id="Oymcac" name="leaf-crusher.c" compile="1" resource="0" file="../LEAF/Src/leaf-crusher.c"/>
-          <FILE id="LVoaGm" name="leaf-wavefolder.c" compile="1" resource="0"
-                file="../LEAF/Src/leaf-wavefolder.c"/>
-          <FILE id="Oh72PT" name="leaf-WDF.c" compile="1" resource="0" file="../LEAF/Src/leaf-WDF.c"/>
           <FILE id="TxA1Gg" name="leaf-tables.c" compile="1" resource="0" file="../LEAF/Src/leaf-tables.c"/>
-          <FILE id="BFkVGu" name="leaf.c" compile="1" resource="0" file="../LEAF/Src/leaf.c"/>
+          <FILE id="q5y59A" name="leaf-oscillators.c" compile="1" resource="0"
+                file="../LEAF/Src/leaf-oscillators.c"/>
+          <FILE id="nh9xAo" name="leaf-filters.c" compile="1" resource="0" file="../LEAF/Src/leaf-filters.c"/>
+          <FILE id="lLb7eq" name="leaf-delay.c" compile="1" resource="0" file="../LEAF/Src/leaf-delay.c"/>
+          <FILE id="uyYwEd" name="leaf-reverb.c" compile="1" resource="0" file="../LEAF/Src/leaf-reverb.c"/>
+          <FILE id="E8JjWS" name="leaf-distortion.c" compile="1" resource="0"
+                file="../LEAF/Src/leaf-distortion.c"/>
+          <FILE id="u1aLLR" name="leaf-effects.c" compile="1" resource="0" file="../LEAF/Src/leaf-effects.c"/>
+          <FILE id="uKHzgz" name="leaf-envelopes.c" compile="1" resource="0"
+                file="../LEAF/Src/leaf-envelopes.c"/>
+          <FILE id="Oymcac" name="leaf-dynamics.c" compile="1" resource="0" file="../LEAF/Src/leaf-dynamics.c"/>
+          <FILE id="LVoaGm" name="leaf-analysis.c" compile="1" resource="0" file="../LEAF/Src/leaf-analysis.c"/>
+          <FILE id="HbG7LO" name="leaf-instruments.c" compile="1" resource="0"
+                file="../LEAF/Src/leaf-instruments.c"/>
+          <FILE id="LuoIDh" name="leaf-midi.c" compile="1" resource="0" file="../LEAF/Src/leaf-midi.c"/>
+          <FILE id="nmtoFJ" name="leaf-sampling.c" compile="1" resource="0" file="../LEAF/Src/leaf-sampling.c"/>
+          <FILE id="dgAVr5" name="leaf-physical.c" compile="1" resource="0" file="../LEAF/Src/leaf-physical.c"/>
+          <FILE id="Oh72PT" name="leaf-electrical.c" compile="1" resource="0"
+                file="../LEAF/Src/leaf-electrical.c"/>
         </GROUP>
         <FILE id="dmljDQ" name="leaf.h" compile="0" resource="0" file="../LEAF/leaf.h"/>
       </GROUP>
--- a/LEAF_JUCEPlugin/Source/MyTest.cpp
+++ b/LEAF_JUCEPlugin/Source/MyTest.cpp
@@ -37,6 +37,8 @@
     tCycle_init(&sine);
     tCycle_setFreq(&sine, 200);
     tDelay_init(&delay, 44100, 44100);
+    tDelay_free(&delay); //most basic free test
+    tDelay_init(&delay, 44100, 44100);
 }
 
 float   LEAFTest_tick            (float input)
@@ -98,7 +100,7 @@
 void leaf_pool_dump(void)
 {
     float* buff = (float*)leaf_pool_get_pool();
-    int siz = leaf_pool_get_size();
+    unsigned long siz = leaf_pool_get_size();
     siz /= sizeof(float);
     for (int i = 0; i < siz; i++)
     {