Skflneartrap paper

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

My cheap non linear version after finally (sort of) learning it.
nlskf.mp3

Code: Select all

       template <typename FloatType>
    class NLSKF {
    public:
        NLSKF() {
            
        }
        void init(FloatType srIn){
            ic1eq = 0.0;
            ic2eq = 0.0;
            sr = srIn;
            isr = 1.0/sr;
        }
        
        void setParams(FloatType cutoffIn, FloatType resIn) {
            cutoffIn=std::clamp(cutoffIn, static_cast<FloatType>(10.0), static_cast<FloatType>(22049.0));
            FloatType w = M_PI*cutoffIn*isr;
            FloatType co = sin(w*0.5);
            co = 1-2*(co*co);
            g = sin(w)/co;
            k = 2.2*resIn;
        }
        
        FloatType process(FloatType vin) {
            
            FloatType v1 = 0;
            FloatType v2 = 0;
            
            
            v2 = 0.0;
            FloatType base = ic2eq;
            FloatType tBase = tanh(ic2eq*k);
            FloatType b = 0.0;
            FloatType a = base == 0 ? 1.f * k : tBase/base;
            FloatType de = 1.0/(1+g*(2-a+g));
            
            v2 = (ic2eq+g*(b+ic1eq+ic2eq+g*vin)) * de;
            v1 = (b*(1+g)+a*ic2eq+(1+g)*(ic1eq+g*vin))*de;
            
            ic1eq = 2*(v1 - (a*v2)) - ic1eq;
            ic2eq = 2*(v2) - ic2eq;
            
            return v2;
        }
    private:
        
        FloatType ic1eq{0.0};
        FloatType ic2eq{0.0};
        FloatType sr{44100.0};
        FloatType isr{1.0/44100.0};
        FloatType g{0.0};
        FloatType k{0.0};
    };

Svf version with anti saturation. Use double precision for this one.

Svf version with tanh too. Antisaturation was too unstable for large values .
svf_pings.mp3

Code: Select all


    template <typename FloatType>
    class NLSVF {
    public:
        
        NLSVF() {
            
        }
        void init(FloatType srIn){
            ic1eq = 0.0;
            ic2eq = 0.0;
            sr = srIn;
            isr = 1.0/sr;
        }
        
        void setParams(FloatType cutoffIn, FloatType resIn) {
            FloatType w = M_PI*cutoffIn/sr;
            FloatType co = sin(w*0.5);
            co = 1-2*(co*co);
            g = sin(w)/co;
            k = 2.0-2.0*resIn;
            R = resIn;
            
        }
        
    
        
        FloatType process(FloatType vin) {
           
            FloatType v1 = 0;
            FloatType v2 = 0;
            
            vin = std::clamp(vin,static_cast<FloatType>(-3.0),static_cast<FloatType>(3.0));
            
            FloatType base = ic1eq;
            FloatType tBase = tanh((2*R)*base);
            FloatType b = 0.0;
            FloatType a = base == 0 ? 2-2*R : 2-tBase/base;

            
            FloatType de = 1.0/(1+g*(a+g));
            
            v1 = (ic1eq + g*(-ic2eq+vin))*de;
            v2 = (ic2eq + g*(ic1eq+a*ic2eq+g*vin))*de;
            
            ic1eq = 2*v1 - ic1eq;
            ic2eq = 2*v2 - ic2eq;
            
    
            
            return v1;
        }
    private:
        
        FloatType ic1eq{0.0};
        FloatType ic2eq{0.0};
        FloatType sr{44100.0};
        FloatType isr{1.0/44100.0};
        FloatType g{0.0};
        FloatType k{0.0};
        FloatType R{0.0};
       
    };
You do not have the required permissions to view the files attached to this post.

Post

I think I was able to sort of add a diode style clipper in the path instead of polynomial or tanh

sounds great driven too. has not broken on me yet.


Edit: another way to save time I believe if you just use the saturator 2 * sech(x)

Then you can shape it like so

2 * sech(x*s) * resonance


Once I got the hang of this pivot method it’s all clamping 2 to 0 or 0 to 2 in the resonance


Code: Select all

template <typename FloatType>
    class NLSVF {
    public:
        
        NLSVF() {
            
        }
        void init(FloatType srIn){
            ic1eq = 0.0;
            ic2eq = 0.0;
            sr = srIn;
            isr = 1.0/sr;
        }
        
        void setParams(FloatType cutoffIn, FloatType resIn) {
            FloatType w = M_PI*cutoffIn/sr;
            FloatType co = sin(w*0.5);
            co = 1-2*(co*co);
            g = sin(w)/co;
            k = 2.0-2.0*resIn;
            R = resIn;
            
        }
        
        
        FloatType process(FloatType vin) {
           
            FloatType v1 = 0;
            FloatType v2 = 0;
            
           
            
            FloatType x = ic1eq;
            FloatType s = 10e-17;
            FloatType vt = 1.0/26.0e-3;
            FloatType eq = (1.0/(1.0+(s*exp(-vt*x)-s)+(s*exp(vt*x)-s)))-1;
            FloatType a = x == 0 ? 2-2*R : 1-R-eq;

            
            FloatType de = 1.0/(1+g*(a+g));
            
            v1 = (ic1eq + g*(-ic2eq+vin))*de;
            v2 = (ic2eq + g*(ic1eq+a*ic2eq+g*vin))*de;
            
            ic1eq = 2*v1 - ic1eq;
            ic2eq = 2*v2 - ic2eq;
            
    
            
            return v1;
        }
    private:
        
        FloatType ic1eq{0.0};
        FloatType ic2eq{0.0};
        FloatType sr{44100.0};
        FloatType isr{1.0/44100.0};
        FloatType g{0.0};
        FloatType k{0.0};
        FloatType R{0.0};
       
    };
    

This is the skf using the same diode style equation to solve.

k cannot exceed 2 or else it will break, but you lose the screaming more apparent on tanh with newton

Code: Select all

    template <typename FloatType>
       class NLSKF {
       public:
           NLSKF() {
               
           }
           void init(FloatType srIn){
               ic1eq = 0.0;
               ic2eq = 0.0;
               sr = srIn;
               isr = 1.0/sr;
           }
           
           void setParams(FloatType cutoffIn, FloatType resIn) {
               cutoffIn=std::clamp(cutoffIn, static_cast<FloatType>(10.0), static_cast<FloatType>(22049.0));
               
               FloatType w = M_PI*cutoffIn*isr;
               FloatType co = sin(w*0.5);
               co = 1-2*(co*co);
               g = sin(w)/co;
               k = 2.0*resIn;
           }
           
           FloatType process(FloatType vin) {
               
               
               
               FloatType v1 = 0;
               FloatType v2 = 0;
               
               
               FloatType is = 2.52e-9;
               FloatType vt = 25.865e-3*1.752;
               FloatType x      = ic2eq;
               FloatType fk     = 0;
               FloatType gk     = x == 0 ? 1 : k/(1+is*((exp(-x*k/vt)-1)+is*(exp(x*k/vt)-1)));
               FloatType gkeq   = 0;

               FloatType de = 1.0/((1+g)*(1+g)-g*gk);
               
               v2 = ic2eq + g*(gkeq+ic1eq+ic2eq+g*vin);
               v2 *= de;
               
               v1 = (1+g)*gkeq + gk*ic2eq+(1+g)*(ic1eq+g*vin);
               v1 *= de;
               
               ic1eq = 2*(v1 - (gk*v2+gkeq)) - ic1eq;
               ic2eq = 2*(v2) - ic2eq;
               
               return v2;
           }
       private:
           
           FloatType ic1eq{0.0};
           FloatType ic2eq{0.0};
           FloatType sr{44100.0};
           FloatType isr{1.0/44100.0};
           FloatType g{0.0};
           FloatType k{0.0};
       };

Post Reply

Return to “DSP and Plugin Development”