shithub: leaf

ref: ce517563012c1a25e86cea537304e9fd7c91c969
dir: /LEAF/Src/leaf-wavefolder.c/

View raw version
/*==============================================================================

    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;
}

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;
}