shithub: leaf

Download patch

ref: c4b3d6bb03cfc9ba708c7ed3db9348961a9eb220
parent: 1a26f591471711b6ba36625a296d485a7b5702d6
author: Matthew Wang <mjw7@princeton.edu>
date: Fri May 8 14:02:51 EDT 2020

trying polyblep oscillators

--- a/LEAF/Inc/leaf-filters.h
+++ b/LEAF/Inc/leaf-filters.h
@@ -386,78 +386,93 @@
 
 	//Vadim Zavalishin style from VA book (from implementation in RSlib posted to kvr forum)
 
-        typedef struct _tVZFilter
-        {
-            VZFilterType type;
-            // state:
-            float s1, s2;
-
-            // filter coefficients:
-            float g;          // embedded integrator gain
-            float R2;         // twice the damping coefficient (R2 == 2*R == 1/Q)
-            float h;          // factor for feedback (== 1/(1+2*R*g+g*g))
-            float cL, cB, cH; // coefficients for low-, band-, and highpass signals
-
-            // parameters:
-            float fs;    // sample-rate
-            float fc;    // characteristic frequency
-            float G;     // gain
-            float invG;     //1/gain
-            float B;     // bandwidth (in octaves)
-            float m;     // morph parameter (0...1)
-
-            float sr;    //local sampling rate of filter (may be different from leaf sr if oversampled)
-            float inv_sr;
-
-        } _tVZFilter;
-
-        typedef _tVZFilter* tVZFilter;
-
-        void    tVZFilter_init           (tVZFilter* const, VZFilterType type, float freq, float Q);
-        void    tVZFilter_free           (tVZFilter* const);
-        void    tVZFilter_initToPool     (tVZFilter* const, VZFilterType type, float freq, float Q, tMempool* const);
-        void    tVZFilter_freeFromPool   (tVZFilter* const, tMempool* const);
-        void    tVZFilter_setSampleRate  (tVZFilter* const, float sampleRate);
-        float   tVZFilter_tick              (tVZFilter* const, float input);
-        float   tVZFilter_tickEfficient             (tVZFilter* const vf, float in);
-        void   tVZFilter_calcCoeffs           (tVZFilter* const);
-        void   tVZFilter_setBandwidth           (tVZFilter* const, float bandWidth);
-        void   tVZFilter_setFreq           (tVZFilter* const, float freq);
-        void   tVZFilter_setFreqAndBandwidth    (tVZFilter* const vf, float freq, float bw);
-        void   tVZFilter_setGain                (tVZFilter* const, float gain);
-        void   tVZFilter_setType                (tVZFilter* const, VZFilterType type);
-        float   tVZFilter_BandwidthToR      (tVZFilter* const vf, float B);
-
-
-
-
-		//diode ladder filter
-		typedef struct _tDiodeFilter
-		    {
-
-			 	 float f;
-			 	 float r;
-			 	 float Vt;
-			 	 float n;
-			 	 float gamma;
-			 	 float zi;
-			 	 float g0inv;
-			 	 float g1inv;
-			 	 float g2inv;
-			 	 float s0, s1, s2, s3;
-
-		    } _tDiodeFilter;
-
-		    typedef _tDiodeFilter* tDiodeFilter;
-
-		    void    tDiodeFilter_init           (tDiodeFilter* const, float freq, float Q);
-			void    tDiodeFilter_free           (tDiodeFilter* const);
-			void    tDiodeFilter_initToPool     (tDiodeFilter* const, float freq, float Q, tMempool* const);
-			void    tDiodeFilter_freeFromPool   (tDiodeFilter* const, tMempool* const);
-
-			float   tDiodeFilter_tick           	(tDiodeFilter* const, float input);
-			void    tDiodeFilter_setFreq     (tDiodeFilter* const vf, float cutoff);
-			void    tDiodeFilter_setQ     (tDiodeFilter* const vf, float resonance);
+    typedef enum VZFilterType
+    {
+        Highpass = 0,
+        Lowpass,
+        BandpassSkirt,
+        BandpassPeak,
+        BandReject,
+        Bell,
+        Lowshelf,
+        Highshelf,
+        Morph,
+        Bypass,
+        Allpass
+    } VZFilterType;
+    
+    typedef struct _tVZFilter
+    {
+        VZFilterType type;
+        // state:
+        float s1, s2;
+        
+        // filter coefficients:
+        float g;          // embedded integrator gain
+        float R2;         // twice the damping coefficient (R2 == 2*R == 1/Q)
+        float h;          // factor for feedback (== 1/(1+2*R*g+g*g))
+        float cL, cB, cH; // coefficients for low-, band-, and highpass signals
+        
+        // parameters:
+        float fs;    // sample-rate
+        float fc;    // characteristic frequency
+        float G;     // gain
+        float invG;     //1/gain
+        float B;     // bandwidth (in octaves)
+        float m;     // morph parameter (0...1)
+        
+        float sr;    //local sampling rate of filter (may be different from leaf sr if oversampled)
+        float inv_sr;
+        
+    } _tVZFilter;
+    
+    typedef _tVZFilter* tVZFilter;
+    
+    void    tVZFilter_init           (tVZFilter* const, VZFilterType type, float freq, float Q);
+    void    tVZFilter_free           (tVZFilter* const);
+    void    tVZFilter_initToPool     (tVZFilter* const, VZFilterType type, float freq, float Q, tMempool* const);
+    void    tVZFilter_freeFromPool   (tVZFilter* const, tMempool* const);
+    void    tVZFilter_setSampleRate  (tVZFilter* const, float sampleRate);
+    float   tVZFilter_tick              (tVZFilter* const, float input);
+    float   tVZFilter_tickEfficient             (tVZFilter* const vf, float in);
+    void   tVZFilter_calcCoeffs           (tVZFilter* const);
+    void   tVZFilter_setBandwidth           (tVZFilter* const, float bandWidth);
+    void   tVZFilter_setFreq           (tVZFilter* const, float freq);
+    void   tVZFilter_setFreqAndBandwidth    (tVZFilter* const vf, float freq, float bw);
+    void   tVZFilter_setGain                (tVZFilter* const, float gain);
+    void   tVZFilter_setType                (tVZFilter* const, VZFilterType type);
+    float   tVZFilter_BandwidthToR      (tVZFilter* const vf, float B);
+    
+    
+    
+    
+    //diode ladder filter
+    typedef struct _tDiodeFilter
+    {
+        
+        float f;
+        float r;
+        float Vt;
+        float n;
+        float gamma;
+        float zi;
+        float g0inv;
+        float g1inv;
+        float g2inv;
+        float s0, s1, s2, s3;
+        
+    } _tDiodeFilter;
+    
+    typedef _tDiodeFilter* tDiodeFilter;
+    
+    void    tDiodeFilter_init           (tDiodeFilter* const, float freq, float Q);
+    void    tDiodeFilter_free           (tDiodeFilter* const);
+    void    tDiodeFilter_initToPool     (tDiodeFilter* const, float freq, float Q, tMempool* const);
+    void    tDiodeFilter_freeFromPool   (tDiodeFilter* const, tMempool* const);
+    
+    float   tDiodeFilter_tick               (tDiodeFilter* const, float input);
+    void    tDiodeFilter_setFreq     (tDiodeFilter* const vf, float cutoff);
+    void    tDiodeFilter_setQ     (tDiodeFilter* const vf, float resonance);
 
 
 #ifdef __cplusplus
--- a/LEAF/Inc/leaf-math.h
+++ b/LEAF/Inc/leaf-math.h
@@ -151,6 +151,7 @@
     void LEAF_generate_sawtooth(float* buffer, float basefreq, int size);
     void LEAF_generate_triangle(float* buffer, float basefreq, int size);
     void LEAF_generate_square(float* buffer, float basefreq, int size);
+    float LEAF_poly_blep(float t, float dt);
     float LEAF_midiToFrequency(float f);
 
 
--- a/LEAF/Inc/leaf-oscillators.h
+++ b/LEAF/Inc/leaf-oscillators.h
@@ -92,73 +92,6 @@
     
     //==============================================================================
     
-    typedef struct _tSine
-    {
-        float* sine;
-        int size;
-        float phase;
-        float inc,freq;
-    } _tSine;
-    
-    typedef _tSine* tSine;
-    
-    /*!
-     * @defgroup tsine tSine
-     * @ingroup oscillators
-     * @brief A cycle/sine waveform oscillator.
-     * @{
-     */
-    
-    //! Initialize a tSine to the default LEAF mempool.
-    /*!
-     @param osc A pointer to the tSine to be initialized.
-     */
-    void    tSine_init         (tSine* const osc, int size);
-    
-    
-    //! Free a tSine from the default LEAF mempool.
-    /*!
-     @param osc A pointer to the tSine to be freed.
-     */
-    void    tSine_free         (tSine* const osc);
-    
-    
-    //! Initialize a tSine to a specified mempool.
-    /*!
-     @param osc A pointer to the tSine to be initialized.
-     @param pool A pointer to the tMempool to which the tSine should be initialized.
-     */
-    void    tSine_initToPool   (tSine* const osc, int size, tMempool* const pool);
-    
-    
-    //! Free a tSine from a specified mempool.
-    /*!
-     @param osc A pointer to the tSine to be freed.
-     @param pool A pointer to the tMempool from which the tSine should be freed.
-     */
-    void    tSine_freeFromPool (tSine* const osc, tMempool* const pool);
-    
-    
-    //! Tick a tSine oscillator.
-    /*!
-     @param osc A pointer to the relevant tSine.
-     @return The ticked sample as a float from -1 to 1.
-     */
-    float   tSine_tick         (tSine* const osc);
-    
-    
-    //! Set the frequency of a tSine oscillator.
-    /*!
-     @param osc A pointer to the relevant tSine.
-     @param freq The frequency to set the oscillator to.
-     */
-    void    tSine_setFreq      (tSine* const osc, float freq);
-    
-    /*! @} */
-    
-    
-    //==============================================================================
-    
     /* tTriangle: Anti-aliased Triangle waveform using wavetable interpolation. Wavetables constructed from sine components. */
     typedef struct _tTriangle
     {
@@ -358,6 +291,274 @@
      @param freq The frequency to set the oscillator to.
      */
     void    tSawtooth_setFreq       (tSawtooth* const osc, float freq);
+    
+    /*! @} */
+    
+    //==============================================================================
+    
+    typedef struct _tSine
+    {
+        float* sine;
+        int size;
+        float phase;
+        float inc,freq;
+    } _tSine;
+    
+    typedef _tSine* tSine;
+    
+    /*!
+     * @defgroup tsine tSine
+     * @ingroup oscillators
+     * @brief A cycle/sine waveform oscillator.
+     * @{
+     */
+    
+    //! Initialize a tSine to the default LEAF mempool.
+    /*!
+     @param osc A pointer to the tSine to be initialized.
+     */
+    void    tSine_init         (tSine* const osc, int size);
+    
+    
+    //! Free a tSine from the default LEAF mempool.
+    /*!
+     @param osc A pointer to the tSine to be freed.
+     */
+    void    tSine_free         (tSine* const osc);
+    
+    
+    //! Initialize a tSine to a specified mempool.
+    /*!
+     @param osc A pointer to the tSine to be initialized.
+     @param pool A pointer to the tMempool to which the tSine should be initialized.
+     */
+    void    tSine_initToPool   (tSine* const osc, int size, tMempool* const pool);
+    
+    
+    //! Free a tSine from a specified mempool.
+    /*!
+     @param osc A pointer to the tSine to be freed.
+     @param pool A pointer to the tMempool from which the tSine should be freed.
+     */
+    void    tSine_freeFromPool (tSine* const osc, tMempool* const pool);
+    
+    
+    //! Tick a tSine oscillator.
+    /*!
+     @param osc A pointer to the relevant tSine.
+     @return The ticked sample as a float from -1 to 1.
+     */
+    float   tSine_tick         (tSine* const osc);
+    
+    
+    //! Set the frequency of a tSine oscillator.
+    /*!
+     @param osc A pointer to the relevant tSine.
+     @param freq The frequency to set the oscillator to.
+     */
+    void    tSine_setFreq      (tSine* const osc, float freq);
+    
+    /*! @} */
+    
+    //==============================================================================
+    
+    /* tTri: Anti-aliased Triangle waveform using wavetable interpolation. */
+    typedef struct _tTri
+    {
+        float phase;
+        float inc,freq;
+        float skew;
+        float lastOut;
+    } _tTri;
+    
+    typedef _tTri* tTri;
+    
+    /*!
+     * @defgroup tTri tTri
+     * @ingroup oscillators
+     * @brief An anti-aliased triangle waveform oscillator.
+     * @{
+     */
+    
+    //! Initialize a tTri to the default LEAF mempool.
+    /*!
+     @param osc A pointer to the tTri to be initialized.
+     */
+    void    tTri_init          (tTri* const osc);
+    
+    
+    //! Free a tTri from the default LEAF mempool.
+    /*!
+     @param osc A pointer to the tTri to be freed.
+     */
+    void    tTri_free          (tTri* const osc);
+    
+    
+    //! Initialize a tTri to a specified mempool.
+    /*!
+     @param osc A pointer to the tTri to be initialized.
+     @param pool A pointer to the tMempool to which the tTri should be initialized.
+     */
+    void    tTri_initToPool    (tTri* const osc, tMempool* const pool);
+    
+    
+    //! Free a tTri from a specified mempool.
+    /*!
+     @param osc A pointer to the tTri to be freed.
+     @param pool A pointer to the tMempool from which the tTri should be freed.
+     */
+    void    tTri_freeFromPool  (tTri* const osc, tMempool* const pool);
+    
+    
+    //! Tick a tTri oscillator.
+    /*!
+     @param osc A pointer to the relevant tTri.
+     @return The ticked sample as a float from -1 to 1.
+     */
+    float   tTri_tick          (tTri* const osc);
+    
+    
+    //! Set the frequency of a tTri oscillator.
+    /*!
+     @param osc A pointer to the relevant tTriangle.
+     @param freq The frequency to set the oscillator to.
+     */
+    void    tTri_setFreq       (tTri* const osc, float freq);
+    
+    void    tTri_setSkew       (tTri* const osc, float skew);
+    
+    /*! @} */
+    
+    //==============================================================================
+    
+    /* tPulse: Anti-aliased Square waveform. */
+    typedef struct _tPulse
+    {
+        float phase;
+        float inc,freq;
+        float width;
+    } _tPulse;
+    
+    typedef _tPulse* tPulse;
+    
+    /*!
+     * @defgroup tPulse tPulse
+     * @ingroup oscillators
+     * @brief An anti-aliased pulse waveform oscillator with changeable pulse width.
+     * @{
+     */
+    
+    //! Initialize a tPulse to the default LEAF mempool.
+    /*!
+     @param osc A pointer to the tPulse to be initialized.
+     */
+    void    tPulse_init        (tPulse* const osc);
+    
+    
+    //! Free a tPulse from the default LEAF mempool.
+    /*!
+     @param osc A pointer to the tPulse to be freed.
+     */
+    void    tPulse_free        (tPulse* const osc);
+    
+    
+    //! Initialize a tPulse to a specified mempool.
+    /*!
+     @param osc A pointer to the tPulse to be initialized.
+     @param pool A pointer to the tMempool to which the tPulse should be initialized.
+     */
+    void    tPulse_initToPool  (tPulse* const osc, tMempool* const);
+    
+    
+    //! Free a tPulse from a specified mempool.
+    /*!
+     @param osc A pointer to the tPulse to be freed.
+     @param pool A pointer to the tMempool from which the tPulse should be freed.
+     */
+    void    tPulse_freeFromPool(tPulse* const osc, tMempool* const);
+    
+    
+    //! Tick a tPulse oscillator.
+    /*!
+     @param osc A pointer to the relevant tPulse.
+     @return The ticked sample as a float from -1 to 1.
+     */
+    float   tPulse_tick        (tPulse* const osc);
+    
+    
+    //! Set the frequency of a tPulse oscillator.
+    /*!
+     @param osc A pointer to the relevant tPulse.
+     @param freq The frequency to set the oscillator to.
+     */
+    void    tPulse_setFreq     (tPulse* const osc, float freq);
+    
+    void    tPulse_setWidth    (tPulse* const osc, float width);
+    
+    /*! @} */
+    
+    //==============================================================================
+    
+    /* tSawtooth: Anti-aliased Sawtooth waveform. */
+    typedef struct _tSaw
+    {
+        float phase;
+        float inc,freq;
+    } _tSaw;
+    
+    typedef _tSaw* tSaw;
+    
+    /*!
+     * @defgroup tsaw tSaw
+     * @ingroup oscillators
+     * @brief An anti-aliased sawtooth waveform oscillator. Uses wavetable synthesis.
+     * @{
+     */
+    
+    //! Initialize a tSaw to the default LEAF mempool.
+    /*!
+     @param osc A pointer to the tSaw to be initialized.
+     */
+    void    tSaw_init          (tSaw* const osc);
+    
+    
+    //! Free a tSaw from the default LEAF mempool.
+    /*!
+     @param osc A pointer to the tSaw to be freed.
+     */
+    void    tSaw_free          (tSaw* const osc);
+    
+    
+    //! Initialize a tSaw to a specified mempool.
+    /*!
+     @param osc A pointer to the tSaw to be initialized.
+     @param pool A pointer to the tMempool to which the tSaw should be initialized.
+     */
+    void    tSaw_initToPool    (tSaw* const osc, tMempool* const pool);
+    
+    
+    //! Free a tSaw from a specified mempool.
+    /*!
+     @param osc A pointer to the tSaw to be freed.
+     @param pool A pointer to the tMempool from which the tSaw should be freed.
+     */
+    void    tSaw_freeFromPool  (tSaw* const osc, tMempool* const pool);
+    
+    
+    //! Tick a tSaw oscillator.
+    /*!
+     @param osc A pointer to the relevant tSaw.
+     @return The ticked sample as a float from -1 to 1.
+     */
+    float   tSaw_tick          (tSaw* const osc);
+    
+    
+    //! Set the frequency of a tSaw oscillator.
+    /*!
+     @param osc A pointer to the relevant tSaw.
+     @param freq The frequency to set the oscillator to.
+     */
+    void    tSaw_setFreq       (tSaw* const osc, float freq);
     
     /*! @} */
     
--- a/LEAF/Src/leaf-distortion.c
+++ b/LEAF/Src/leaf-distortion.c
@@ -16,9 +16,6 @@
 #include "../Inc/leaf-distortion.h"
 #include "../Inc/leaf-tables.h"
 
-//testing
-#include "gpio.h"
-
 #endif
 
 //============================================================================================================
--- a/LEAF/Src/leaf-filters.c
+++ b/LEAF/Src/leaf-filters.c
@@ -17,7 +17,6 @@
 #include "../Inc/leaf-filters.h"
 #include "../Inc/leaf-tables.h"
 #include "../leaf.h"
-#include "tim.h"
 #endif
 
 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OnePole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
@@ -1697,24 +1696,24 @@
 
 	// This formula gives the result for y3 thanks to MATLAB
 	float y3 = (f->s2 + f->s3 + t2*(f->s1 + f->s2 + f->s3 + t1*(f->s0 + f->s1 + f->s2 + f->s3 + t0*in)) + t1*(2.0f*f->s2 + 2.0f*f->s3))*t3 + f->s3 + 2.0f*f->s3*t1 + t2*(2.0f*f->s3 + 3.0f*f->s3*t1);
-	if (isnan(y3))
-	{
-		__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
-	}
+//    if (isnan(y3))
+//    {
+//        __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
+//    }
 	float tempy3denom = (t4 + t1*(2.0f*t4 + 4.0f) + t2*(t4 + t1*(t4 + f->r*t0 + 4.0f) + 3.0f) + 2.0f)*t3 + t4 + t1*(2.0f*t4 + 2.0f) + t2*(2.0f*t4 + t1*(3.0f*t4 + 3.0f) + 2.0f) + 1.0f;
-	if (isnan(tempy3denom))
-	{
-		__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
-	}
+//    if (isnan(tempy3denom))
+//    {
+//        __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
+//    }
 	if (tempy3denom == 0.0f)
 	{
 		tempy3denom = 0.000001f;
 	}
 	y3 = y3 / tempy3denom;
-	if (isnan(y3))
-	{
-		__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
-	}
+//    if (isnan(y3))
+//    {
+//        __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
+//    }
 	if (t1 == 0.0f)
 	{
 		t1 = 0.000001f;
@@ -1735,15 +1734,15 @@
 
 	// update state
 	f->s0 += 2.0f * (t0*xx + t1*(y1-y0));
-	if (isnan(f->s0))
-	{
-		__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
-	}
+//    if (isnan(f->s0))
+//    {
+//        __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
+//    }
 
-	if (isinf(f->s0))
-	{
-		__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
-	}
+//    if (isinf(f->s0))
+//    {
+//        __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 400);
+//    }
 	f->s1 += 2.0f * (t2*(y2-y1) - t1*(y1-y0));
 	f->s2 += 2.0f * (t3*(y3-y2) - t2*(y2-y1));
 	f->s3 += 2.0f * (-t4*(y3) - t3*(y3-y2));
--- a/LEAF/Src/leaf-math.c
+++ b/LEAF/Src/leaf-math.c
@@ -403,6 +403,58 @@
     }
 }
 
+// http://www.martin-finke.de/blog/articles/audio-plugins-018-polyblep-oscillator/
+// http://www.kvraudio.com/forum/viewtopic.php?t=375517
+// t = phase, dt = inc, assuming 0-1 phase
+// assumes discontinuity at 0, so offset inputs as needed
+float LEAF_poly_blep(float t, float dt)
+{
+    // 0 <= t < 1
+    if (t < dt) {
+        t /= dt;
+        return t+t - t*t - 1.0f;
+    }
+    // -1 < t < 0
+    else if (t > 1.0f - dt) {
+        t = (t - 1.0f) / dt;
+        return t*t + t+t + 1.0f;
+    }
+    // 0 otherwise
+    else return 0.0f;
+    
+//
+//    float y = 0.0f;
+//    if (t < 2.0f * dt)
+//    {
+//        float x = t / dt;
+//        float u = 2.0f - x;
+//        u *= u;
+//        u *= u;
+//        y += u;
+//        if (t < dt) {
+//            float v = 1.0f - x;
+//            v *= v;
+//            v *= v;
+//            y -= 4.0f * v;
+//        }
+//    }
+//    else if (t > 1.0f - (2.0f * dt))
+//    {
+//        float x = (t - 1.0f) / dt;
+//        float u = 2.0f - x;
+//        u *= u;
+//        u *= u;
+//        y += u;
+//        if (t > 1.0f - dt) {
+//            float v = 1.0f - x;
+//            v *= v;
+//            v *= v;
+//            y += 4.0f * v;
+//        }
+//    }
+//    return y / 12.0f;
+}
+
 
 //-----------------------------------------------------------------------------
 // name: mtof()
--- a/LEAF/Src/leaf-oscillators.c
+++ b/LEAF/Src/leaf-oscillators.c
@@ -90,84 +90,6 @@
 }
 
 //========================================================================
-// Sine
-void    tSine_init(tSine* const cy, int size)
-{
-    tSine_initToPool(cy, size, &leaf.mempool);
-}
-
-void    tSine_free(tSine* const cy)
-{
-    tSine_freeFromPool(cy, &leaf.mempool);
-}
-
-void    tSine_initToPool   (tSine* const cy, int size, tMempool* const mp)
-{
-    _tMempool* m = *mp;
-    _tSine* c = *cy = (_tSine*) mpool_alloc(sizeof(_tSine), m);
-    
-    c->size = size;
-    c->sine = (float*) mpool_alloc(sizeof(float) * c->size, m);
-    LEAF_generate_sine(c->sine, size);
-    c->inc      =  0.0f;
-    c->phase    =  0.0f;
-    
-}
-
-void    tSine_freeFromPool (tSine* const cy, tMempool* const mp)
-{
-    _tMempool* m = *mp;
-    _tSine* c = *cy;
-    
-    mpool_free(c->sine, m);
-    mpool_free(c, m);
-}
-
-void     tSine_setFreq(tSine* const cy, float freq)
-{
-    _tSine* c = *cy;
-    
-
-    c->freq  = freq;
-    
-    c->inc = freq * leaf.invSampleRate;
-}
-
-float   tSine_tick(tSine* const cy)
-{
-    _tSine* c = *cy;
-    float temp;
-    int intPart;
-    float fracPart;
-    float samp0;
-    float samp1;
-    
-    // Phasor increment
-    c->phase += c->inc;
-    while (c->phase >= 1.0f) c->phase -= 1.0f;
-    while (c->phase < 0.0f) c->phase += 1.0f;
-    
-    // Wavetable synthesis
-    
-    temp = c->size * c->phase;
-    intPart = (int)temp;
-    fracPart = temp - (float)intPart;
-    samp0 = c->sine[intPart];
-    if (++intPart >= c->size) intPart = 0;
-    samp1 = c->sine[intPart];
-    
-    return (samp0 + (samp1 - samp0) * fracPart);
-    
-}
-
-void     tSineSampleRateChanged (tSine* const cy)
-{
-    _tSine* c = *cy;
-    
-    c->inc = c->freq * leaf.invSampleRate;
-}
-
-//========================================================================
 /* Triangle */
 void   tTriangle_init(tTriangle* const cy)
 {
@@ -385,6 +307,281 @@
     _tSawtooth* c = *cy;
     
     c->inc = c->freq * leaf.invSampleRate;
+}
+
+//========================================================================
+// Sine
+void    tSine_init(tSine* const cy, int size)
+{
+    tSine_initToPool(cy, size, &leaf.mempool);
+}
+
+void    tSine_free(tSine* const cy)
+{
+    tSine_freeFromPool(cy, &leaf.mempool);
+}
+
+void    tSine_initToPool   (tSine* const cy, int size, tMempool* const mp)
+{
+    _tMempool* m = *mp;
+    _tSine* c = *cy = (_tSine*) mpool_alloc(sizeof(_tSine), m);
+    
+    c->size = size;
+    c->sine = (float*) mpool_alloc(sizeof(float) * c->size, m);
+    LEAF_generate_sine(c->sine, size);
+    c->inc      =  0.0f;
+    c->phase    =  0.0f;
+}
+
+void    tSine_freeFromPool (tSine* const cy, tMempool* const mp)
+{
+    _tMempool* m = *mp;
+    _tSine* c = *cy;
+    
+    mpool_free(c->sine, m);
+    mpool_free(c, m);
+}
+
+void     tSine_setFreq(tSine* const cy, float freq)
+{
+    _tSine* c = *cy;
+    
+    c->freq  = freq;
+    c->inc = freq * leaf.invSampleRate;
+}
+
+float   tSine_tick(tSine* const cy)
+{
+    _tSine* c = *cy;
+    float temp;
+    int intPart;
+    float fracPart;
+    float samp0;
+    float samp1;
+    
+    // Phasor increment
+    c->phase += c->inc;
+    while (c->phase >= 1.0f) c->phase -= 1.0f;
+    while (c->phase < 0.0f) c->phase += 1.0f;
+    
+    // Wavetable synthesis
+    
+    temp = c->size * c->phase;
+    intPart = (int)temp;
+    fracPart = temp - (float)intPart;
+    samp0 = c->sine[intPart];
+    if (++intPart >= c->size) intPart = 0;
+    samp1 = c->sine[intPart];
+    
+    return (samp0 + (samp1 - samp0) * fracPart);
+    
+}
+
+void     tSineSampleRateChanged (tSine* const cy)
+{
+    _tSine* c = *cy;
+    
+    c->inc = c->freq * leaf.invSampleRate;
+}
+
+//==============================================================================
+
+/* tTri: Anti-aliased Triangle waveform. */
+void    tTri_init          (tTri* const osc)
+{
+    tTri_initToPool(osc, &leaf.mempool);
+}
+
+void    tTri_free          (tTri* const osc)
+{
+    tTri_freeFromPool(osc, &leaf.mempool);
+}
+
+void    tTri_initToPool    (tTri* const osc, tMempool* const mp)
+{
+    _tMempool* m = *mp;
+    _tTri* c = *osc = (_tTri*) mpool_alloc(sizeof(_tTri), m);
+
+    c->inc      =  0.0f;
+    c->phase    =  0.0f;
+    c->skew     =  0.5f;
+    c->lastOut  =  0.0f;
+}
+
+void    tTri_freeFromPool  (tTri* const cy, tMempool* const mp)
+{
+    _tMempool* m = *mp;
+    _tTri* c = *cy;
+    
+    mpool_free(c, m);
+}
+
+float   tTri_tick          (tTri* const osc)
+{
+    _tTri* c = *osc;
+    
+    float out;
+    float skew;
+    
+    if (c->phase < c->skew)
+    {
+        out = 1.0f;
+        skew = (1.0f - c->skew) * 2.0f;
+    }
+    else
+    {
+        out = -1.0f;
+        skew = c->skew * 2.0f;
+    }
+    
+    out += LEAF_poly_blep(c->phase, c->inc);
+    out -= LEAF_poly_blep(fmod(c->phase + (1.0f - c->skew), 1.0f), c->inc);
+    
+    out = (skew * c->inc * out) + ((1 - c->inc) * c->lastOut);
+    c->lastOut = out;
+    
+    c->phase += c->inc;
+    if (c->phase >= 1.0f)
+    {
+        c->phase -= 1.0f;
+    }
+    
+    return out;
+}
+
+void    tTri_setFreq       (tTri* const osc, float freq)
+{
+    _tTri* c = *osc;
+    
+    c->freq  = freq;
+    c->inc = freq * leaf.invSampleRate;
+}
+
+void    tTri_setSkew       (tTri* const osc, float skew)
+{
+    _tTri* c = *osc;
+    c->skew = (skew + 1.0f) * 0.5f;
+}
+
+
+//==============================================================================
+
+/* tPulse: Anti-aliased pulse waveform. */
+void    tPulse_init        (tPulse* const osc)
+{
+    tPulse_initToPool(osc, &leaf.mempool);
+}
+
+void    tPulse_free        (tPulse* const osc)
+{
+    tPulse_freeFromPool(osc, &leaf.mempool);
+}
+
+void    tPulse_initToPool  (tPulse* const osc, tMempool* const mp)
+{
+    _tMempool* m = *mp;
+    _tPulse* c = *osc = (_tPulse*) mpool_alloc(sizeof(_tPulse), m);
+    
+    c->inc      =  0.0f;
+    c->phase    =  0.0f;
+    c->width     =  0.5f;
+}
+
+void    tPulse_freeFromPool(tPulse* const osc, tMempool* const mp)
+{
+    _tMempool* m = *mp;
+    _tPulse* c = *osc;
+    
+    mpool_free(c, m);
+}
+
+float   tPulse_tick        (tPulse* const osc)
+{
+    _tPulse* c = *osc;
+    
+    float out;
+    if (c->phase < c->width) out = 1.0f;
+    else out = -1.0f;
+    out += LEAF_poly_blep(c->phase, c->inc);
+    out -= LEAF_poly_blep(fmod(c->phase + (1.0f - c->width), 1.0f), c->inc);
+    
+    c->phase += c->inc;
+    if (c->phase >= 1.0f)
+    {
+        c->phase -= 1.0f;
+    }
+    
+    return out;
+}
+
+void    tPulse_setFreq     (tPulse* const osc, float freq)
+{
+    _tPulse* c = *osc;
+    
+    c->freq  = freq;
+    c->inc = freq * leaf.invSampleRate;
+}
+
+void    tPulse_setWidth    (tPulse* const osc, float width)
+{
+    _tPulse* c = *osc;
+    c->width = width;
+}
+
+
+//==============================================================================
+
+/* tSawtooth: Anti-aliased Sawtooth waveform. */
+void    tSaw_init          (tSaw* const osc)
+{
+    tSaw_initToPool(osc, &leaf.mempool);
+}
+
+void    tSaw_free          (tSaw* const osc)
+{
+    tSaw_freeFromPool(osc, &leaf.mempool);
+}
+
+void    tSaw_initToPool    (tSaw* const osc, tMempool* const mp)
+{
+    _tMempool* m = *mp;
+    _tSaw* c = *osc = (_tSaw*) mpool_alloc(sizeof(_tSaw), m);
+    
+    c->inc      =  0.0f;
+    c->phase    =  0.0f;
+}
+
+void    tSaw_freeFromPool  (tSaw* const osc, tMempool* const mp)
+{
+    _tMempool* m = *mp;
+    _tSaw* c = *osc;
+    
+    mpool_free(c, m);
+}
+
+float   tSaw_tick          (tSaw* const osc)
+{
+    _tSaw* c = *osc;
+    
+    float out = (c->phase * 2.0f) - 1.0f;
+    out -= LEAF_poly_blep(c->phase, c->inc);
+    
+    c->phase += c->inc;
+    if (c->phase >= 1.0f)
+    {
+        c->phase -= 1.0f;
+    }
+    
+    return out;
+}
+
+void    tSaw_setFreq       (tSaw* const osc, float freq)
+{
+    _tSaw* c = *osc;
+    
+    c->freq  = freq;
+    
+    c->inc = freq * leaf.invSampleRate;
 }
 
 //========================================================================
--- a/LEAF_JUCEPlugin/Source/MyTest.cpp
+++ b/LEAF_JUCEPlugin/Source/MyTest.cpp
@@ -17,7 +17,12 @@
 static void run_pool_test(void);
 
 tSine sine;
+tSaw saw;
+tTri tri;
+tPulse pulse;
 
+tPhasor phasor;
+
 float gain;
 float freq;
 float dtime;
@@ -36,13 +41,34 @@
 
     
     tSine_init(&sine, 1000);
-    tSine_setFreq(&sine, 400);
+    tSine_setFreq(&sine, 200);
+    
+    tSaw_init(&saw);
+    tSaw_setFreq(&saw, 200);
+    
+    tPulse_init(&pulse);
+    tPulse_setFreq(&pulse, 200);
+    
+    tTri_init(&tri);
+    tTri_setFreq(&tri, 200);
+    
+    tPhasor_init(&phasor);
 }
 
 float   LEAFTest_tick            (float input)
 {
+//    return tSine_tick(&sine);
+    tSaw_setFreq(&saw, x);
+    tPhasor_setFreq(&phasor, x);
+    return tSaw_tick(&saw);
+
+//    tTri_setFreq(&tri, x);
+//    tTri_setSkew(&tri, (y * 2.0f) - 1.0f);
+//    return tTri_tick(&tri);
     
-    return tSine_tick(&sine);
+//    tPulse_setFreq(&pulse, x);
+//    tPulse_setWidth(&pulse, y);
+//    return tPulse_tick(&pulse);
 }
 
 int firstFrame = 1;
@@ -49,35 +75,15 @@
 bool lastState = false, lastPlayState = false;
 void    LEAFTest_block           (void)
 {
-//    if (firstFrame == 1)
-//    {
-//        tBuffer_record(&buff); // starts recording
-//        tSampler_play(&samp); // start spitting samples out
-//        firstFrame = 0;
-//    }
-    
     float val = getSliderValue("mod freq");
     
-    x = val ;
+    x = val * 20000;
     
-//    a = val * tBuffer_getBufferLength(&buff);
+    DBG(String(x));
     
-    DBG("start: " + String(a));
-    
     val = getSliderValue("mod depth");
     
-    y = val * 20000.0f + 20.0f;
-//    b = val * tBuffer_getBufferLength(&buff);
-    
-    DBG("rate: " + String(b));
-//    
-//    tSampler_setStart(&samp, a);
-//    tSampler_setEnd(&samp, b);
-//    tSampler_setRate(&samp, b);
-    
-//    tFormantShifter_setShiftFactor(&fs, x);
-//    tFormantShifter_setIntensity(&fs, y);
-    
+    y = val;;
 }
 
 void    LEAFTest_controllerInput (int cnum, float cval)