#include "BandLimit.hpp"

// The musicdsp.org page at http://www.musicdsp.org/showone.php?id=39 credits
// this to Dave from Muon Software
// Linked source: http://www.musicdsp.org/files/BandLimit.cpp

CAllPassFilter::CAllPassFilter(const double coefficient)
{
    a=coefficient;

    x0=0.0;
    x1=0.0;
    x2=0.0;
    
    y0=0.0;
    y1=0.0;
    y2=0.0;

};


CAllPassFilter::~CAllPassFilter()
{
};


double CAllPassFilter::process(const double input)
{
    //shuffle inputs
    x2=x1;
    x1=x0;
    x0=input;

    //shuffle outputs
    y2=y1;
    y1=y0;

    //allpass filter 1
    const double output=x2+((input-y2)*a);

    y0=output;

    return output;
};


CAllPassFilterCascade::CAllPassFilterCascade(const double* coefficient, const int N)
{
    allpassfilter=new CAllPassFilter*[N];

    for (int i=0;i<N;i++)
    {
        allpassfilter[i]=new CAllPassFilter(coefficient[i]);
    }

    numfilters=N;
};


CAllPassFilterCascade::~CAllPassFilterCascade()
{
   for (int i=0;i<numfilters;i++)
    {
        delete allpassfilter[i];
    }

    delete[] allpassfilter;
};


double CAllPassFilterCascade::process(const double input)
{
    double output=input;
    
    int i=0;

    do
    {
        output=allpassfilter[i]->process(output);
        i++;

    } while (i<numfilters);

    return output;
};


CHalfBandFilter::CHalfBandFilter(const int order, const bool steep)
{
    if (steep==true)
    {
        if (order==12)    //rejection=104dB, transition band=0.01
        {
            double a_coefficients[6]=
            {0.036681502163648017
            ,0.2746317593794541
            ,0.56109896978791948
            ,0.769741833862266
            ,0.8922608180038789
            ,0.962094548378084
            };

            double b_coefficients[6]=
            {0.13654762463195771
            ,0.42313861743656667
            ,0.6775400499741616
            ,0.839889624849638
            ,0.9315419599631839
            ,0.9878163707328971
            };
    
            filter_a=new CAllPassFilterCascade(a_coefficients,6);
            filter_b=new CAllPassFilterCascade(b_coefficients,6);
        }
        else if (order==10)    //rejection=86dB, transition band=0.01
        {
            double a_coefficients[5]=
            {0.051457617441190984
            ,0.35978656070567017
            ,0.6725475931034693
            ,0.8590884928249939
            ,0.9540209867860787
            };

            double b_coefficients[5]=
            {0.18621906251989334
            ,0.529951372847964
            ,0.7810257527489514
            ,0.9141815687605308
            ,0.985475023014907
            };
    
            filter_a=new CAllPassFilterCascade(a_coefficients,5);
            filter_b=new CAllPassFilterCascade(b_coefficients,5);
        }
        else if (order==8)    //rejection=69dB, transition band=0.01
        {
            double a_coefficients[4]=
            {0.07711507983241622
            ,0.4820706250610472
            ,0.7968204713315797
            ,0.9412514277740471
            };

            double b_coefficients[4]=
            {0.2659685265210946
            ,0.6651041532634957
            ,0.8841015085506159
            ,0.9820054141886075
            };
    
            filter_a=new CAllPassFilterCascade(a_coefficients,4);
            filter_b=new CAllPassFilterCascade(b_coefficients,4);
        }
        else if (order==6)    //rejection=51dB, transition band=0.01
        {
            double a_coefficients[3]=
            {0.1271414136264853
            ,0.6528245886369117
            ,0.9176942834328115
            };

            double b_coefficients[3]=
            {0.40056789819445626
            ,0.8204163891923343
            ,0.9763114515836773
            };
    
            filter_a=new CAllPassFilterCascade(a_coefficients,3);
            filter_b=new CAllPassFilterCascade(b_coefficients,3);
        }
        else if (order==4)    //rejection=53dB,transition band=0.05
        {
            double a_coefficients[2]=
            {0.12073211751675449
            ,0.6632020224193995
            };

            double b_coefficients[2]=
            {0.3903621872345006
            ,0.890786832653497
            };
    
            filter_a=new CAllPassFilterCascade(a_coefficients,2);
            filter_b=new CAllPassFilterCascade(b_coefficients,2);
        }
    
        else    //order=2, rejection=36dB, transition band=0.1
        {
            double a_coefficients=0.23647102099689224;
            double b_coefficients=0.7145421497126001;

            filter_a=new CAllPassFilterCascade(&a_coefficients,1);
            filter_b=new CAllPassFilterCascade(&b_coefficients,1);
        }
    }
    else    //softer slopes, more attenuation and less stopband ripple
    {
        if (order==12)    //rejection=150dB, transition band=0.05
        {
            double a_coefficients[6]=
            {0.01677466677723562
            ,0.13902148819717805
            ,0.3325011117394731
            ,0.53766105314488
            ,0.7214184024215805
            ,0.8821858402078155
            };

            double b_coefficients[6]=
            {0.06501319274445962
            ,0.23094129990840923
            ,0.4364942348420355
//            ,0.06329609551399348
            ,0.6329609551399348
            ,0.80378086794111226
            ,0.9599687404800694
            };
    
            filter_a=new CAllPassFilterCascade(a_coefficients,6);
            filter_b=new CAllPassFilterCascade(b_coefficients,6);
        }
        else if (order==10)    //rejection=133dB, transition band=0.05
        {
            double a_coefficients[5]=
            {0.02366831419883467
            ,0.18989476227180174
            ,0.43157318062118555
            ,0.6632020224193995
            ,0.860015542499582
            };

            double b_coefficients[5]=
            {0.09056555904993387
            ,0.3078575723749043
            ,0.5516782402507934
            ,0.7652146863779808
            ,0.95247728378667541
            };
    
            filter_a=new CAllPassFilterCascade(a_coefficients,5);
            filter_b=new CAllPassFilterCascade(b_coefficients,5);
        }
        else if (order==8)    //rejection=106dB, transition band=0.05
        {
            double a_coefficients[4]=
            {0.03583278843106211
            ,0.2720401433964576
            ,0.5720571972357003
            ,0.827124761997324
            };

            double b_coefficients[4]=
            {0.1340901419430669
            ,0.4243248712718685
            ,0.7062921421386394
            ,0.9415030941737551
            };
    
            filter_a=new CAllPassFilterCascade(a_coefficients,4);
            filter_b=new CAllPassFilterCascade(b_coefficients,4);
        }
        else if (order==6)    //rejection=80dB, transition band=0.05
        {
            double a_coefficients[3]=
            {0.06029739095712437
            ,0.4125907203610563
            ,0.7727156537429234
            };

            double b_coefficients[3]=
            {0.21597144456092948
            ,0.6043586264658363
            ,0.9238861386532906
            };
    
            filter_a=new CAllPassFilterCascade(a_coefficients,3);
            filter_b=new CAllPassFilterCascade(b_coefficients,3);
        }
        else if (order==4)    //rejection=70dB,transition band=0.1
        {
            double a_coefficients[2]=
            {0.07986642623635751
            ,0.5453536510711322
            };

            double b_coefficients[2]=
            {0.28382934487410993
            ,0.8344118914807379
            };
    
            filter_a=new CAllPassFilterCascade(a_coefficients,2);
            filter_b=new CAllPassFilterCascade(b_coefficients,2);
        }
    
        else    //order=2, rejection=36dB, transition band=0.1
        {
            double a_coefficients=0.23647102099689224;
            double b_coefficients=0.7145421497126001;

            filter_a=new CAllPassFilterCascade(&a_coefficients,1);
            filter_b=new CAllPassFilterCascade(&b_coefficients,1);
        }
    }

    oldout=0.0;
};


CHalfBandFilter::~CHalfBandFilter()
{
    delete filter_a;
    delete filter_b;
};


double CHalfBandFilter::process(const double input)
{
    const double output=(filter_a->process(input)+oldout)*0.5;
    oldout=filter_b->process(input);

    return output;
}
