/*******************************************************************************
* Copyright 2015-2018 Intel Corporation.
*
* This software and the related documents are Intel copyrighted  materials,  and
* your use of  them is  governed by the  express license  under which  they were
* provided to you (License).  Unless the License provides otherwise, you may not
* use, modify, copy, publish, distribute,  disclose or transmit this software or
* the related documents without Intel's prior written permission.
*
* This software and the related documents  are provided as  is,  with no express
* or implied  warranties,  other  than those  that are  expressly stated  in the
* License.
*******************************************************************************/

#include <stdio.h>
#include "ipps.h"

#define SMP_RATE 1000.f
#define F1 50.f
#define F2 120.f
#define AMPL 10
#define CUT_OFF 0.3
#define LEN 256
#define ORDER 3

int main( ){
    Ipp32f *x, *y, *f1, *f2;
    Ipp32f phase;
    int i, bufferSizeGen, bufferSizeIIRIIR;
    Ipp64f *pTaps;
    Ipp8u *pBufIIRIIR;
    IppsIIRState64f_32f *pStateIIRIIR;
    IppStatus st;

    /* generate test input signal - sum of 2 sinusoids with 50 & 120 Hz */
    f1 = ippsMalloc_32f( LEN );
    f2 = ippsMalloc_32f( LEN );
    x  = ippsMalloc_32f( LEN );
    phase = 3 * (Ipp32f)IPP_PI2; /* ippsTone generates cos, we want sin */
    st = ippsTone_32f( f1, LEN, AMPL, F1/SMP_RATE, &phase, ippAlgHintAccurate ); /* generate 50 Hz sin */
    phase = 3 * (Ipp32f)IPP_PI2; /* restore phase*/
    st |= ippsTone_32f( f2, LEN, AMPL, F2/SMP_RATE, &phase, ippAlgHintAccurate ); /* generate 120 Hz sin */
    st |= ippsAdd_32f( f1, f2, x, LEN ); /* add 50 & 120 Hz sin to form input signal */
    st |= ippsAbs_32f_I( x, LEN ); /* make positive, x contains input signal to be filtered with IIRIIR */
    ippsFree( f1 );
    ippsFree( f2 );
    /* get size of mem buffers for IIR and IIRGen functions */
    st |= ippsIIRIIRGetStateSize64f_32f( ORDER, &bufferSizeIIRIIR );
    st |= ippsIIRGenGetBufferSize      ( ORDER, &bufferSizeGen    );
    /* we can allocate MAX size from two - operations are sequential and therefore buffer can be reused */
    pBufIIRIIR = ippsMalloc_8u( IPP_MAX( bufferSizeGen, bufferSizeIIRIIR ));
    pTaps = ippsMalloc_64f( 2 * ( ORDER + 1 ));
    /* gen LowPass filter coefficients */
    st |= ippsIIRGenLowpass_64f( CUT_OFF/2, 0.0, ORDER, pTaps, ippButterworth, pBufIIRIIR );
    /* init state structure for IIRIIR */
    st |= ippsIIRIIRInit64f_32f( &pStateIIRIIR, pTaps, ORDER, NULL, pBufIIRIIR );
    y = ippsMalloc_32f( LEN ); /* output vector */
    st |=ippsIIRIIR64f_32f( x, y, LEN, pStateIIRIIR );
    printf("idx,\tinput,\toutput\n");
    for( i = 0; i < LEN; i++ ){
        printf("%d,\t%f,\t%f\n", i, x[i], y[i] );
    }
    if( ippStsNoErr != st )
        printf("\nCertain problems in Intel(R) Integrated Primitives (Intel(R) IPP) !\n");
    ippsFree( y );
    ippsFree( pTaps );
    ippsFree( pBufIIRIIR );
    ippsFree( x );
    return 0;
}