/*****************************************************************************
 * Copyright (c) 2018, Broadcom Inc.                                         *
 *                                                                           *
 * All Rights Reserved.                                                      *
 *                                                                           *
 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Inc.;             *
 * the contents of this file may not be disclosed to third parties, copied   *
 * or duplicated in any form, in whole or in part, without the prior         *
 * written permission of Broadcom Inc.                                       *
 *****************************************************************************/
/**
 * @file au_task_vend.c
 * @brief Wrapper for vendor libraries in audio path
 */

#include "dsp_sdk_types.h"
#include "overlay.h"
#include "dsp_sdk_trace.h"
#include "EQ_biquad_parameters_rx_8kHz.h"
#include "EQ_biquad_parameters_tx_8kHz.h"
#include "EQ_biquad_parameters_rx_16kHz.h"
#include "EQ_biquad_parameters_tx_16kHz.h"


/**
 * Prototypes
 */
INT32 au_task_vend_SpeechAlgoInit(OVERLAY_ST_t *p_overlay_parameter);
INT32 au_task_vend_SpeechAlgoForEnc(OVERLAY_ST_t *p_overlay_parameter);
#ifdef ENABLE_DYVE_ALGO_AND_BUFF
INT32 au_task_vend_SpeechAlgoForDec(OVERLAY_ST_t *p_overlay_parameter);
#endif

/**
 * Global Variables
 *
 * The only two global variables, long buffers, private parameters of algorithms and EQ parameters can be declared in this file
 */
FN_t *overlay_entry = (FN_t *) (&_iram0_overlay_entry_text_start);
OVERLAY_ST_t g_overlay_parameter;

UINT8 g_inear_in_main_long_buf[INEAR_LONG_BUF_LENGTH_BYTE] __attribute__((aligned(4)));       /* input 20ms buffer (allocate 30ms buffering)      */
UINT8 g_inear_in_sub_long_buf[INEAR_LONG_BUF_LENGTH_BYTE] __attribute__((aligned(4)));        /* input 20ms buffer (allocate 30ms buffering)      */
UINT8 g_inear_in_third_long_buf[INEAR_LONG_BUF_LENGTH_BYTE] __attribute__((aligned(4)));      /* input 20ms buffer (allocate 30ms buffering)      */
UINT8 g_inear_in_fourth_long_buf[INEAR_LONG_BUF_LENGTH_BYTE] __attribute__((aligned(4)));     /* input 20ms buffer (allocate 30ms buffering)      */
UINT8 g_inear_in_long_buf_rx[INEAR_LONG_BUF_LENGTH_BYTE] __attribute__((aligned(4)));         /* rxinput buffer                                   */
UINT8 g_inear_out_long_buf[INEAR_LONG_BUF_LENGTH_BYTE] __attribute__((aligned(4)));           /* output 20ms buffer (allocate 30ms buffering)     */
#ifdef ENABLE_DYVE_ALGO_AND_BUFF
UINT8 g_dyve_in_long_buf[DYVE_LONG_BUF_LENGTH_BYTE] __attribute__((aligned(4)));              /* input 20ms buffer (allocate 30ms buffering)      */
UINT8 g_dyve_in_long_buf_tx[DYVE_LONG_BUF_LENGTH_BYTE] __attribute__((aligned(4)));           /* input 20ms buffer (allocate 30ms buffering)      */
UINT8 g_dyve_out_long_buf[DYVE_LONG_BUF_LENGTH_BYTE] __attribute__((aligned(4)));             /* output 20ms buffer (allocate 30ms buffering)     */
#else
UINT8 g_inear_in_long_buf_rx_backup_two_frame[INEAR_LONG_BUF_LENGTH] __attribute__((aligned(4))); /* backup 15ms buffer for g_inear_in_long_buf_rx before encoder start */
#endif

UINT8 g_vend_private_param[VEND_PRIVATE_PARAM_SIZE_BYTE] __attribute__((aligned(4)));         /* Private parameters for SS algorithms             */

/* parametric EQ default coefficient. */
PEQ_PARAM_t g_peq_coef_tx_8k = { {EQ_coef_sos_tx_8kHz},
                                 {EQ_coef_g_tx_8kHz},
                                 EQ_gain_tx_8kHz };

PEQ_PARAM_t g_peq_coef_tx_16k = { {EQ_coef_sos_tx_16kHz},
                                  {EQ_coef_g_tx_16kHz},
                                  EQ_gain_tx_16kHz };

PEQ_PARAM_t g_peq_coef_rx_8k = { {EQ_coef_sos_rx_8kHz},
                                 {EQ_coef_g_rx_8kHz},
                                 EQ_gain_rx_8kHz };


PEQ_PARAM_t g_peq_coef_rx_16k = { {EQ_coef_sos_rx_16kHz},
                                  {EQ_coef_g_rx_16kHz},
                                  EQ_gain_rx_16kHz };



INT32 au_task_vend_dummy()
{
    return 0;
}



/**
 * Fill long buffer
 */
INT32 au_task_vend_FillBuf(VEND_BUF_t *buf_st, INT16 *src, UINT16 samples)
{
    INT32 ret = VEND_SUCCESS;

    if(samples <= (buf_st->len - buf_st->offset))
    {
        memcpy((buf_st->buf + buf_st->offset), src, (samples<<1));
        buf_st->offset += samples;
    }
    else
    {
        ret = VEND_BUF_OVERFLOW;
        TRACE(TRACE_INFO, MODULE_ID_DSP, "[DSP] au_task_vend_FillBuf buffer overflow !!!");
    }

    return ret;
}



/**
 * Drain long buffer
 */
INT32 au_task_vend_DrainBuf(VEND_BUF_t *buf_st, INT16 *dest, UINT16 samples)
{
    INT32 ret = VEND_SUCCESS;

    if(samples <= buf_st->offset)
    {
        memcpy(dest, buf_st->buf, (samples<<1));
        memmove(buf_st->buf, (buf_st->buf + samples), ((buf_st->offset - samples)<<1));
        buf_st->offset -= samples;
    }
    else
    {
        ret = VEND_BUF_UNDERFLOW;
        TRACE(TRACE_INFO, MODULE_ID_DSP, "[DSP] au_task_vend_DrainBuf buffer underflow !!!");
    }

    return ret;
}


/**
 * Copy buffer data
 */
INT32 au_task_vend_CopyBuf(VEND_BUF_t *dest_buf_st, VEND_BUF_t *src_buf_st)
{
    INT32 ret = VEND_SUCCESS;

    dest_buf_st->offset = src_buf_st->offset;
    dest_buf_st->len    = src_buf_st->len;

    memcpy(dest_buf_st->buf, src_buf_st->buf, ((src_buf_st->offset)<<1));

    return ret;
}


/**
 * Pass buffer data
 */
INT32 au_task_vend_PassBuf(VEND_BUF_t *dest_buf_st, VEND_BUF_t *src_buf_st, UINT16 samples)
{
    INT32 ret = VEND_SUCCESS;

    if(src_buf_st->offset >= samples)
    {
        ret = au_task_vend_FillBuf(dest_buf_st, src_buf_st->buf, samples);
        if(ret == VEND_SUCCESS)
        {
            ret = au_task_vend_FlushBuf(src_buf_st, samples);
        }
    }
    else
    {
        ret = VEND_BUF_UNDERFLOW;
        TRACE(TRACE_INFO, MODULE_ID_DSP, "[DSP] au_task_vend_PassBuf buffer underflow !!!");
    }

    return ret;
}

/**
 * Flush long buffer
 */
INT32 au_task_vend_FlushBuf(VEND_BUF_t *buf_st, UINT16 samples)
{
    INT32 ret = VEND_SUCCESS;

    if(buf_st->offset >= samples)
    {
        memmove(buf_st->buf, (buf_st->buf + samples), ((buf_st->offset - samples)<<1));
        buf_st->offset -= samples;
    }
    else
    {
        buf_st->offset = 0;
        ret = VEND_BUF_UNDERFLOW;
        TRACE(TRACE_INFO, MODULE_ID_DSP, "[DSP] au_task_vend_FlushBuf buffer underflow !!!");
    }

    return ret;
}





/**
 * Initialization flow of ambient noise
 */
INT32 au_task_vend_AmbInit(OVERLAY_ST_t *p_overlay_parameter)
{
    INT32 ret;

    /* Init Ambient noise */
    CALL_ENTRY(ret, p_overlay_parameter, ALGO_IDX_AMBIENT_INIT);

    if(ret != VEND_SUCCESS)
    {
        TRACE(TRACE_INFO, MODULE_ID_DSP, "[DSP VEND] Ambient noise init fail");
        //return ret;
    }


    return ret;
}



/**
 * Execution flow of ambient noise
 */
INT32 au_task_vend_AmbExec(OVERLAY_ST_t *p_overlay_parameter)
{
    INT32 ret;

    /* Get input frame */
    ret = au_task_GetAmbientInputFrame(p_overlay_parameter);

    /* Check input frame status */
    if(ret != VEND_SUCCESS)
    {
        TRACE(TRACE_INFO, MODULE_ID_DSP, "[DSP VEND] Ambient noise no input");
    }

    if(ret == VEND_SUCCESS)
    {
        /* Execute Ambient noise */
        CALL_ENTRY(ret, p_overlay_parameter, ALGO_IDX_AMBIENT_EXEC);

        //ret must be VEND_SUCCESS because the execution funciton is void

        /* Send output frame */
        ret = au_task_SendAmbientOutputFrame(p_overlay_parameter);


        if(ret != VEND_SUCCESS)
        {
            TRACE(TRACE_INFO, MODULE_ID_DSP, "[DSP VEND] Ambient noise output fail");
        }
    }

    return ret;
}


/**
 * Trigger SBM for the next SSC decoding
 */
INT32 au_task_vend_TriggerSBM(OVERLAY_ST_t *overlay_parameter, UINT16 current_buffer_depth, UINT16 target_buffer_depth)
{
    INT32 ret = VEND_SUCCESS;

    SS_AUDIO_EXT_ST_t *p_ss_audio_external_param = &overlay_parameter->ovl_paramter.ovl_au.ss_audio_external_parameter;

    p_ss_audio_external_param->trigger_SBM = 1;
    p_ss_audio_external_param->current_buffer_depth = current_buffer_depth;
    p_ss_audio_external_param->target_buffer_depth = target_buffer_depth;

    return ret;
}



/**
 * Get output samples of SSC
 */
INT16 au_task_vend_GetNumOfOutputSamples(OVERLAY_ST_t *overlay_parameter)
{
    SS_AUDIO_EXT_ST_t *p_ss_audio_external_param = &overlay_parameter->ovl_paramter.ovl_au.ss_audio_external_parameter;

    return p_ss_audio_external_param->output_samples;
}




/**
 * Audio initialization flow with vendor audio decoder and algorithm
 */
INT32 au_task_vend_AudioInit(OVERLAY_ST_t *p_overlay_parameter)
{

    INT32 ret;

    /* Init SS Audio */
    CALL_ENTRY(ret, p_overlay_parameter, ALGO_IDX_SS_AUDIO_INIT);

    if(ret != VEND_SUCCESS)
    {
        TRACE(TRACE_INFO, MODULE_ID_DSP, "[DSP VEND] SS audio init fail");
        return ret;
    }

    //ret = au_task_vend_AmbInit(p_overlay_parameter);

    return ret;
}

/**
 * Audio decoding flow with vendor audio decoder
 */
INT32 au_task_vend_AudioDecode(OVERLAY_ST_t *p_overlay_parameter, UINT16 plc_frame)
{
    INT32 ret;
    SS_AUDIO_EXT_ST_t *p_ss_audio_external_param = &p_overlay_parameter->ovl_paramter.ovl_au.ss_audio_external_parameter;

    if(plc_frame == VEND_GOOD_FRAME)
    {
        p_ss_audio_external_param->plc_frame = 0;
    }
    else  //VEND_LOST_FRAME
    {
        p_ss_audio_external_param->plc_frame = 1;
    }
    /* Execute SS Audio */
    CALL_ENTRY(ret, p_overlay_parameter, ALGO_IDX_SS_AUDIO_EXEC);

    if(ret != VEND_SUCCESS)
    {
        TRACE(TRACE_INFO, MODULE_ID_DSP, "[DSP VEND] SS audio execution fail");
        return ret;
    }

    //TRACE(TRACE_DEBUG, MODULE_ID_DSP, "[DSP VEND][SS AUDIO] done");

    return ret;
}



/**
 * Speech initialization flow with vendor speech codec and algorithm
 */
INT32 au_task_vend_SpeechCodecAlgoInit(OVERLAY_ST_t *p_overlay_parameter)
{
    INT32 ret;
    SS_SPEECH_DEC_EXT_ST_t *p_ss_speech_dec_external_param = &p_overlay_parameter->ovl_paramter.ovl_sp.ss_speech_dec_external_parameter;
    SS_SPEECH_ENC_EXT_ST_t *p_ss_speech_enc_external_param = &p_overlay_parameter->ovl_paramter.ovl_sp.ss_speech_enc_external_parameter;
    INEAR_EXT_ST_t *p_inear_external_param = &g_overlay_parameter.ovl_paramter.ovl_sp.inear_external_parameter;
#ifdef ENABLE_DYVE_ALGO_AND_BUFF
    DYVE_EXT_ST_t *p_dyve_external_param = &g_overlay_parameter.ovl_paramter.ovl_sp.dyve_external_parameter;
#endif
    p_ss_speech_dec_external_param->frame_cnt = 0;
    p_ss_speech_enc_external_param->frame_cnt = 0;

    /* Init SS speech decoder */
    CALL_ENTRY(ret, p_overlay_parameter, ALGO_IDX_SS_SPEECH_DEC_INIT);

    if(ret != VEND_SUCCESS)
    {
        TRACE(TRACE_INFO, MODULE_ID_DSP, "[DSP VEND] SS speech decoder init fail");
        return ret;
    }

    /* Init SS speech encoder */
    CALL_ENTRY(ret, p_overlay_parameter, ALGO_IDX_SS_SPEECH_ENC_INIT);

    if(ret != VEND_SUCCESS)
    {
        TRACE(TRACE_INFO, MODULE_ID_DSP, "[DSP VEND] SS speech encoder init fail");
        return ret;
    }

    /* Init speech algorithm */

    p_inear_external_param->enc_frame_size = SS_SPEECH_FRAME_SIZE;
    p_inear_external_param->frame_size = INEAR_FRAME_SIZE_WB;
    p_inear_external_param->sampling_rate = SS_SPEECH_FS;

#ifdef ENABLE_DYVE_ALGO_AND_BUFF
    p_dyve_external_param->dec_frame_size = SS_SPEECH_FRAME_SIZE;
    p_dyve_external_param->frame_size = DYVE_DIAMONDVOICE_FRAME_WB;
    p_dyve_external_param->sampling_rate = SS_SPEECH_FS;
#endif
    ret = au_task_vend_SpeechAlgoInit(p_overlay_parameter);

    return ret;
}





/**
 * Speech decoding flow with vendor speech decoder and algorithm
 */
INT32 au_task_vend_SpeechDecode(OVERLAY_ST_t *p_overlay_parameter)
{
    INT32 ret;
    SS_SPEECH_DEC_EXT_ST_t *p_ss_speech_dec_external_param = &p_overlay_parameter->ovl_paramter.ovl_sp.ss_speech_dec_external_parameter;
#ifdef ENABLE_DYVE_ALGO_AND_BUFF
    DYVE_EXT_ST_t *p_dyve_external_param = &p_overlay_parameter->ovl_paramter.ovl_sp.dyve_external_parameter;
    VEND_BUF_t *p_long_buf_dyve_in_speech = &p_overlay_parameter->ovl_paramter.ovl_sp.long_buf[IDX_DYVE_IN_SPEECH];
#endif
    p_ss_speech_dec_external_param->plc_frame = 0;

    /* Get input frame */
    ret = au_task_GetSpeechDecVendInputFrame(p_overlay_parameter);

    /* Check input frame status */
    //if(ret == VEND_WAIT_NEXT_FRAME)
    //{
    //    TRACE(TRACE_DEBUG, MODULE_ID_DSP, "[DSP VEND][SS SPEECH DEC] waiting for next input frame");
    //    return ret;
    //}

#ifdef ENABLE_DYVE_ALGO_AND_BUFF
    if(p_dyve_external_param->dec_cnt)
#else
    if (p_ss_speech_dec_external_param->dec_cnt)
#endif
    {
        if(ret == VEND_LOST_FRAME)
        {
            p_ss_speech_dec_external_param->plc_frame = 1;
        }


        /* Execute SS Speech decoder */
        CALL_ENTRY(ret, p_overlay_parameter, ALGO_IDX_SS_SPEECH_DEC_EXEC);

        if(ret != VEND_SUCCESS)
        {
            TRACE(TRACE_DEBUG, MODULE_ID_DSP, "[DSP VEND][SS SPEECH DEC] SS speech execution fail");
        }

        p_ss_speech_dec_external_param->frame_cnt++;

#ifdef ENABLE_DYVE_ALGO_AND_BUFF
        /* Input 7.5ms frame from decoder output to 30ms buffer */
        ret = au_task_vend_FillBuf(p_long_buf_dyve_in_speech, (INT16 *)p_ss_speech_dec_external_param->out_buf, p_dyve_external_param->dec_frame_size);

        /* Call speech algorithm for decoder (DyVE) */
        ret = au_task_vend_SpeechAlgoForDec(p_overlay_parameter);
#else
        ret = au_task_SendSpeechDecVendOutputFrame(p_overlay_parameter);
#endif
    }

   return ret;
}



/**
 * Speech encoding flow with vendor speech encoder and algorithm
 */
INT32 au_task_vend_SpeechEncode(OVERLAY_ST_t *p_overlay_parameter)
{
    INT32 ret;
    INEAR_EXT_ST_t *p_inear_external_param = &p_overlay_parameter->ovl_paramter.ovl_sp.inear_external_parameter;
    VEND_BUF_t *p_long_buf_inear_out = &p_overlay_parameter->ovl_paramter.ovl_sp.long_buf[IDX_INEAR_OUT];

    SS_SPEECH_ENC_EXT_ST_t *p_ss_speech_enc_external_param = &p_overlay_parameter->ovl_paramter.ovl_sp.ss_speech_enc_external_parameter;

    ret = au_task_vend_SpeechAlgoForEnc(&g_overlay_parameter);

    if((p_inear_external_param->enc_start == 0) && (p_long_buf_inear_out->offset > 0)) /* p_long_buf_inear_out->offset > 0 means that output buffer have data for codec encoder */
    {
        p_inear_external_param->enc_start = 1;
    }

    if(p_inear_external_param->enc_start == 1)
    {
        /* Execute SS Speech encoder */
        CALL_ENTRY(ret, p_overlay_parameter, ALGO_IDX_SS_SPEECH_ENC_EXEC);

        ret = au_task_SendSpeechEncVendOutputFrame(p_overlay_parameter);

        /* Check Output frame status */
        if(ret != VEND_SUCCESS)
        {
            TRACE(TRACE_DEBUG, MODULE_ID_DSP, "[DSP VEND][SS SPEECH ENC] output encoded frame fail");
            return ret;
        }
        p_ss_speech_enc_external_param->frame_cnt++;
    }

    return ret;
}




/**
 * Speech algorithm for encoding flow
 */
INT32 au_task_vend_SpeechAlgoForEnc(OVERLAY_ST_t *p_overlay_parameter)
{
    INT32 ret;
    INEAR_EXT_ST_t *p_inear_external_param = &p_overlay_parameter->ovl_paramter.ovl_sp.inear_external_parameter;
    VEND_BUF_t *p_long_buf_inear_in_main_mic = &p_overlay_parameter->ovl_paramter.ovl_sp.long_buf[IDX_INEAR_IN_MAIN_MIC];
    VEND_BUF_t *p_long_buf_inear_in_sub_mic = &p_overlay_parameter->ovl_paramter.ovl_sp.long_buf[IDX_INEAR_IN_SUB_MIC];
    VEND_BUF_t *p_long_buf_inear_in_3rd_mic = &p_overlay_parameter->ovl_paramter.ovl_sp.long_buf[IDX_INEAR_IN_THIRD_MIC];
    VEND_BUF_t *p_long_buf_inear_in_4th_mic = &p_overlay_parameter->ovl_paramter.ovl_sp.long_buf[IDX_INEAR_IN_FOURTH_MIC];
    VEND_BUF_t *p_long_buf_inear_in_farend = &p_overlay_parameter->ovl_paramter.ovl_sp.long_buf[IDX_INEAR_IN_FAREND];
    VEND_BUF_t *p_long_buf_inear_out = &p_overlay_parameter->ovl_paramter.ovl_sp.long_buf[IDX_INEAR_OUT];
#ifdef ENABLE_DYVE_ALGO_AND_BUFF
    VEND_BUF_t *p_long_buf_dyve_in_noise = &p_overlay_parameter->ovl_paramter.ovl_sp.long_buf[IDX_DYVE_IN_NOISE];
#endif

    p_inear_external_param->short_in_main_frame_cnt++;

    /* Get input frame */
    ret = au_task_GetSpeechEncVendInputFrame(p_overlay_parameter);

#ifdef ENABLE_DYVE_ALGO_AND_BUFF
    au_task_vend_FillBuf(p_long_buf_dyve_in_noise, (p_long_buf_inear_in_main_mic->buf+p_long_buf_inear_in_main_mic->offset-p_inear_external_param->enc_frame_size), p_inear_external_param->enc_frame_size);
#endif
    /* Check input frame status */
    //if(ret != VEND_SUCCESS)
    //{
    //    TRACE(TRACE_INFO, MODULE_ID_DSP, "[DSP VEND][SS SPEECH ENC] waiting for next input frame");
    //    return ret;
    //}

    //buffer 20ms data for Inear, return when frame cnt = 1 2 3
    if(p_inear_external_param->short_in_main_frame_cnt >= p_inear_external_param->inear_start_threshold)
    {
        if(p_long_buf_inear_in_main_mic->offset >= p_inear_external_param->frame_size)
        {
            p_inear_external_param->long_in_main_frame_cnt++;

            p_inear_external_param->dump_inear_in_cnt++;
            /* Dump the audio packets for inear inputs */
            au_task_AudioPktDumpObtainFrames(p_overlay_parameter, SRC_AUDIO_PKT_DUMP_INEAR_INPUT);

            if(p_overlay_parameter->vend_inear_enable)
            {
                /* Call inear execustion*/
                CALL_ENTRY(ret, p_overlay_parameter, ALGO_IDX_INEAR_EXEC);

                if(ret != VEND_SUCCESS)
                {
                    TRACE(TRACE_INFO, MODULE_ID_DSP, "[DSP VEND][Inear] Inear execution fail");
                    p_inear_external_param->inear_fail_cnt++;
                    return ret;
                }
            }
            else
            {
#if 0
                au_task_vend_PassBuf(p_long_buf_inear_out, p_long_buf_inear_in_main_mic, p_inear_external_param->frame_size);
                au_task_vend_FlushBuf(p_long_buf_inear_in_sub_mic, p_inear_external_param->frame_size);
                if(g_overlay_parameter.vend_the3rdmic_enable)
                {
                    au_task_vend_FlushBuf(p_long_buf_inear_in_3rd_mic, p_inear_external_param->frame_size);
                    au_task_vend_FlushBuf(p_long_buf_inear_in_4th_mic, p_inear_external_param->frame_size);
                }
                au_task_vend_FlushBuf(p_long_buf_inear_in_farend, p_inear_external_param->frame_size);
#else
                au_task_vend_PassBuf(p_long_buf_inear_out, p_long_buf_inear_in_main_mic, p_inear_external_param->frame_size);
				au_task_vend_FlushBuf(p_long_buf_inear_in_sub_mic, p_inear_external_param->frame_size);
                au_task_vend_FlushBuf(p_long_buf_inear_in_farend, p_inear_external_param->frame_size);
                if(g_overlay_parameter.vend_the3rdmic_enable)
                {
                    au_task_vend_FlushBuf(p_long_buf_inear_in_3rd_mic, p_inear_external_param->frame_size);
                    au_task_vend_FlushBuf(p_long_buf_inear_in_4th_mic, p_inear_external_param->frame_size);
                }
#endif
            }

            p_inear_external_param->dump_inear_in_cnt++;
            /* Dump output packets only after inear success */
            au_task_AudioPktDumpObtainFrames(p_overlay_parameter, SRC_AUDIO_PKT_DUMP_INEAR_OUTPUT);

            p_inear_external_param->long_output_frame_cnt++;
        }

        /* Output 7.5ms frame */
        ret = au_task_SendVendInearOutputFrame(p_overlay_parameter);
    }
    else
    {
        ret = VEND_WAIT_NEXT_FRAME;
    }

    return ret;
}




INT32 au_task_vend_SpeechAlgoInit(OVERLAY_ST_t *p_overlay_parameter)
{
    INT32 ret = VEND_SUCCESS;

#ifdef ENABLE_DYVE_ALGO_AND_BUFF
    if(p_overlay_parameter->vend_dyve_enable)
    {
        /* Init DyVE algorithm*/
        CALL_ENTRY(ret, p_overlay_parameter, ALGO_IDX_DYVE_INIT);

        if(ret != VEND_SUCCESS)
        {
            TRACE(TRACE_INFO, MODULE_ID_DSP, "[DSP VEND] DyVE init fail");
            return ret;
        }
    }
#endif

    if(p_overlay_parameter->vend_inear_enable)
    {
        /* Init Inear algorithm*/
        CALL_ENTRY(ret, p_overlay_parameter, ALGO_IDX_INEAR_INIT);

        if(ret != VEND_SUCCESS)
        {
            TRACE(TRACE_INFO, MODULE_ID_DSP, "[DSP VEND] Inear init fail");
            //return ret;
        }
    }

    return ret;
}


#ifdef ENABLE_DYVE_ALGO_AND_BUFF
/**
 * Speech decoding flow with vendor speech algorithm
 */
INT32 au_task_vend_SpeechAlgoForDec(OVERLAY_ST_t *p_overlay_parameter)
{
    INT32 ret = VEND_SUCCESS;
    DYVE_EXT_ST_t *p_dyve_external_param = &p_overlay_parameter->ovl_paramter.ovl_sp.dyve_external_parameter;
    VEND_BUF_t *p_long_buf_dyve_in_speech = &p_overlay_parameter->ovl_paramter.ovl_sp.long_buf[IDX_DYVE_IN_SPEECH];
    VEND_BUF_t *p_long_buf_dyve_in_noise = &p_overlay_parameter->ovl_paramter.ovl_sp.long_buf[IDX_DYVE_IN_NOISE];
    VEND_BUF_t *p_long_buf_dyve_out = &p_overlay_parameter->ovl_paramter.ovl_sp.long_buf[IDX_DYVE_OUT];
    VEND_BUF_t *p_long_buf_inear_in_farend = &p_overlay_parameter->ovl_paramter.ovl_sp.long_buf[IDX_INEAR_IN_FAREND];

    p_dyve_external_param->short_input_frame_cnt++;

    /* buffer 30ms data for DyVE input, return when frame cnt = 1 2 3 */
    if(p_dyve_external_param->short_input_frame_cnt >= p_dyve_external_param->dyve_start_threshold)
    {
        if(p_long_buf_dyve_in_speech->offset >= p_dyve_external_param->frame_size)
        {
            p_dyve_external_param->long_input_frame_cnt++;

            if(p_overlay_parameter->vend_dyve_enable)
            {
                /* Call DyVE execustion*/
                CALL_ENTRY(ret, p_overlay_parameter, ALGO_IDX_DYVE_EXEC);
            }
            else
            {
                au_task_vend_PassBuf(p_long_buf_dyve_out, p_long_buf_dyve_in_speech, p_dyve_external_param->frame_size);
                ret = au_task_vend_FlushBuf(p_long_buf_dyve_in_noise, p_dyve_external_param->frame_size);
            }

            p_dyve_external_param->long_output_frame_cnt++;
        }

        /* Output to Mixer */
        /* Output to I2S */
        /* Output 7.5ms frame to I2S */
        ret = au_task_SendSpeechDecVendOutputFrame(p_overlay_parameter);

        if(ret != VEND_SUCCESS)
        {
            TRACE(TRACE_INFO, MODULE_ID_DSP, "[DSP] DyVE output 7.5ms frame fail");
            return ret;
        }
        p_dyve_external_param->short_output_frame_cnt++;
    }
    else if (p_dyve_external_param->short_input_frame_cnt > INEAR_BUFFER_START_CNT)
    {
        p_long_buf_inear_in_farend->offset += p_dyve_external_param->dec_frame_size; /* In the beginning, the buffer elements are all zeros, only need to add offset */
    }

    return ret;
}
#endif
