#include "stdio.h"
#include "string.h"
#include "omx_type1_decoder_com_func.h"

extern IIR_FILTER_COFF_T gtBW2OrderSampleRate2xFilter;
extern IIR_FILTER_COFF_T gtBW2OrderSampleRate4xFilter;
extern IIR_FILTER_COFF_T gtBW2OrderSampleRate8xFilter;

int i4IIR_Filter_Proc(IIR_FILTER_MAIN_T *ptIIRFilterMain, int i4Input, int *pi4Output)
{
    long long i8TmpVal = 0;
    unsigned int i = 0;
    unsigned int u4CoffCnt = 0;

    if (NULL == ptIIRFilterMain)
    {
        printf("[i4IIR_Filter_Proc]ptIIRFilterMain is null, err!\n");
        return -1;
    }
    u4CoffCnt = ptIIRFilterMain->tFilterCoff.u4CoffCnt;

    if((ptIIRFilterMain == NULL) || (pi4Output == NULL))
        return -1;

    for(i=0;i<u4CoffCnt-1;i++)
    {
        ptIIRFilterMain->pi4HistoryOutput[u4CoffCnt-1-i] = ptIIRFilterMain->pi4HistoryOutput[u4CoffCnt-2-i];
        ptIIRFilterMain->pi4HistoryInput[u4CoffCnt-1-i] = ptIIRFilterMain->pi4HistoryInput[u4CoffCnt-2-i];
    }
    ptIIRFilterMain->pi4HistoryInput[0] = i4Input;

    for(i=0;i<u4CoffCnt;i++)
    {
        i8TmpVal += (long long)ptIIRFilterMain->pi4HistoryInput[i]*(long long)ptIIRFilterMain->tFilterCoff.pi4NumeratorCoff[i];
        if(i>0)
            i8TmpVal -= (long long)ptIIRFilterMain->pi4HistoryOutput[i]*(long long)ptIIRFilterMain->tFilterCoff.pi4DenominatorCoff[i];
    }

    i8TmpVal += 1 << (32 - ptIIRFilterMain->tFilterCoff.u4FixedPointIwl - 1);
    i8TmpVal = i8TmpVal >> (32 - ptIIRFilterMain->tFilterCoff.u4FixedPointIwl);

    if(i8TmpVal < _MININTVAL(32))
        i8TmpVal = _MININTVAL(32);
    if(i8TmpVal > _MAXINTVAL(32))
        i8TmpVal = _MAXINTVAL(32);

    ptIIRFilterMain->pi4HistoryOutput[0] = (int)i8TmpVal;
    *pi4Output = ptIIRFilterMain->pi4HistoryOutput[0];

    return 0;
}

int i4AudUpsampleLinearInterpolationInit(AUD_UPSAMPLE_OBJ_T *pAudUpsampleObj, unsigned int u4RatioNum)
{
    int i = 0;
    if(pAudUpsampleObj == NULL)
    {
        printf("[AudUpsampleLinearInterpolationInit]pAudUpsampleObj is null, err!\n");
        return -1;
    }

    switch(u4RatioNum)
    {
    case 2:
        memcpy((void *)&(pAudUpsampleObj->tIIRFilterObj.tFilterCoff), (void *)&gtBW2OrderSampleRate2xFilter, sizeof(IIR_FILTER_COFF_T));
        pAudUpsampleObj->ai4UpsampleWeight[0] = 4;
        break;
    case 4:
        memcpy((void *)&(pAudUpsampleObj->tIIRFilterObj.tFilterCoff), (void *)&gtBW2OrderSampleRate4xFilter, sizeof(IIR_FILTER_COFF_T));
        pAudUpsampleObj->ai4UpsampleWeight[0] = 2;
        pAudUpsampleObj->ai4UpsampleWeight[1] = 4;
        pAudUpsampleObj->ai4UpsampleWeight[2] = 6;
        break;
    case 8:
        memcpy((void *)&(pAudUpsampleObj->tIIRFilterObj.tFilterCoff), (void *)&gtBW2OrderSampleRate8xFilter, sizeof(IIR_FILTER_COFF_T));
        pAudUpsampleObj->ai4UpsampleWeight[0] = 1;
        pAudUpsampleObj->ai4UpsampleWeight[1] = 2;
        pAudUpsampleObj->ai4UpsampleWeight[2] = 3;
        pAudUpsampleObj->ai4UpsampleWeight[3] = 4;
        pAudUpsampleObj->ai4UpsampleWeight[4] = 5;
        pAudUpsampleObj->ai4UpsampleWeight[5] = 6;
        pAudUpsampleObj->ai4UpsampleWeight[6] = 7;
        break;
    default:
        printf("[AudUpsampleLinearInterpolationInit]Only support x2 x4 x8 up-sample, not support x%d up-sample\n", u4RatioNum);
        return -1;
    }
    pAudUpsampleObj->tIIRFilterObj.pi4HistoryInput = pAudUpsampleObj->ai4FilterHInput;
    pAudUpsampleObj->tIIRFilterObj.pi4HistoryOutput = pAudUpsampleObj->ai4FilterHOutput;
    pAudUpsampleObj->i4HistoryInput = 0;
    pAudUpsampleObj->u4RatioNum = u4RatioNum;

    return 0;
}

int i4AudUpsampleLinearInterpolationProc(AUD_UPSAMPLE_OBJ_T *pAudUpsampleObj, int i4Input, int *pai4Output)
{
    unsigned int i = 0;
    long long i8TmpVal = 0;
    int i4TmpVal = 0;

    if(pAudUpsampleObj == NULL)
    {
        printf("[AudUpsampleLinearInterpolationProc]pAudUpsampleObj is null, err!\n");
        return -1;
    }

    for(i=0;i<pAudUpsampleObj->u4RatioNum-1;i++)
    {
        // below i4HistoryInput[0]
        i8TmpVal = (long long)pAudUpsampleObj->i4HistoryInput + (long long)(i4Input - pAudUpsampleObj->i4HistoryInput) * pAudUpsampleObj->ai4UpsampleWeight[i] / 8;
        if(i8TmpVal < _MININTVAL(32))
            i8TmpVal = _MININTVAL(32);
        if(i8TmpVal > _MAXINTVAL(32))
            i8TmpVal = _MAXINTVAL(32);
        i4TmpVal = (int)i8TmpVal;
        i4IIR_Filter_Proc(&(pAudUpsampleObj->tIIRFilterObj), i4TmpVal, &pai4Output[i]);
    }
    i4IIR_Filter_Proc(&(pAudUpsampleObj->tIIRFilterObj), i4Input, &pai4Output[pAudUpsampleObj->u4RatioNum-1]);
    pAudUpsampleObj->i4HistoryInput = i4Input;

    return 0;
}

int i4AudDownsampleInit(AUD_DOWNSAMPLE_OBJ_T *pAudDownsampleObj, unsigned int u4RatioNum)
{
    if(pAudDownsampleObj == NULL)
        return -1;

    switch(u4RatioNum)
    {
    case 2:
        memcpy((void *)&(pAudDownsampleObj->tIIRFilterObj.tFilterCoff), (void *)&gtBW2OrderSampleRate2xFilter, sizeof(IIR_FILTER_COFF_T));
        break;
    case 4:
        memcpy((void *)&(pAudDownsampleObj->tIIRFilterObj.tFilterCoff), (void *)&gtBW2OrderSampleRate4xFilter, sizeof(IIR_FILTER_COFF_T));
        break;
    case 8:
        memcpy((void *)&(pAudDownsampleObj->tIIRFilterObj.tFilterCoff), (void *)&gtBW2OrderSampleRate8xFilter, sizeof(IIR_FILTER_COFF_T));
        break;
    default:
        printf("[AudDownsampleObjInit]Only support x2 x4 x8 down-sample, not support x%d down-sample\n", u4RatioNum);
        return -1;
    }
    pAudDownsampleObj->tIIRFilterObj.pi4HistoryInput = pAudDownsampleObj->ai4FilterHInput;
    pAudDownsampleObj->tIIRFilterObj.pi4HistoryOutput = pAudDownsampleObj->ai4FilterHOutput;
    pAudDownsampleObj->ai4FilterHInput[0] = 0;
    pAudDownsampleObj->ai4FilterHInput[1] = 0;
    pAudDownsampleObj->ai4FilterHInput[2] = 0;
    pAudDownsampleObj->ai4FilterHOutput[0] = 0;
    pAudDownsampleObj->ai4FilterHOutput[1] = 0;
    pAudDownsampleObj->ai4FilterHOutput[2] = 0;

    pAudDownsampleObj->u4InputCnt = 0;
    pAudDownsampleObj->u4RatioNum = u4RatioNum;
    return 0;
}

int i4AudDownsampleJudgeOutput(AUD_DOWNSAMPLE_OBJ_T *pAudDownsampleObj, int i4Input, int *i4Output)
{
    int i4JudgeRet = 0;
    int i4OutputPre = 0;

    if(pAudDownsampleObj == NULL)
        return -1;

    i4IIR_Filter_Proc(&(pAudDownsampleObj->tIIRFilterObj), i4Input, &i4OutputPre);
    if(pAudDownsampleObj->u4InputCnt == 0)
    {
        *i4Output = i4OutputPre;
        i4JudgeRet = 0;
    }
    else
        i4JudgeRet = -1;

    pAudDownsampleObj->u4InputCnt++;
    if(pAudDownsampleObj->u4InputCnt == pAudDownsampleObj->u4RatioNum)
        pAudDownsampleObj->u4InputCnt = 0;

    return i4JudgeRet;
}

int i4AudDropsampleInit(AUD_DROPSAMPLE_OBJ_T *pAudDropsampleObj, unsigned int u4RatioNum, unsigned int u4IsBypassFilter)
{
    if(pAudDropsampleObj == NULL)
        return -1;

    pAudDropsampleObj->u4InputCnt = 0;
    pAudDropsampleObj->u4RatioNum = u4RatioNum;
    pAudDropsampleObj->u4IsBypassFilter = u4IsBypassFilter;
    return 0;
}

int i4AudDropsampleJudgeOutput(AUD_DROPSAMPLE_OBJ_T *pAudDropsampleObj, int i4Input, int *i4Output)
{
    int i4JudgeRet = 0;
    int i4OutputPre = 0;

    if(pAudDropsampleObj == NULL)
        return -1;

    //if(0 == pAudDropsampleObj->u4IsBypassFilter)
        //i4IIR_Filter_Proc(&(pAudDropsampleObj->tIIRFilterObj), i4Input, &i4OutputPre);
    if(pAudDropsampleObj->u4InputCnt == 0)
    {
        *i4Output = i4Input;
        if(0 == pAudDropsampleObj->u4IsBypassFilter)
            *i4Output = i4OutputPre;
        i4JudgeRet = 0;
    }
    else
        i4JudgeRet = -1;

    pAudDropsampleObj->u4InputCnt++;
    if(pAudDropsampleObj->u4InputCnt == pAudDropsampleObj->u4RatioNum)
        pAudDropsampleObj->u4InputCnt = 0;

    return i4JudgeRet;
}

