示例#1
0
文件: qnt12.c 项目: ZF0085/onionphone
/********************************************************************
**
** Function: InsertCand ()
**
** Description:
**
**	Inserts the indeces corresponding to a candidate into the
**	candidate index list, which is sorted in order of increasing
**	distortion.
**
** Arguments:
**
**	int16_t c1		: index of candidate to insert into list
**	int16_t s1		: index of current stage we are searching
**	int16_t dMin[]	: list of distortions of best nc candidates (Q11)
**	int16_t distortion[]	: distortion of candidate c when used with
**							  "entry" from current stage (Q11)
**	int16_t entry		: current stage entry which results in lower
**						  distortion
**	int16_t	**index	: list of past indices for each candidate
**	int16_t	**nextIndex : indices for next stage (output)
**
** Return value:	int16_t
**
***********************************************************************/
static int16_t InsertCand(int16_t c1, int16_t s1, int16_t dMin[],
                          int16_t distortion, int16_t entry,
                          int16_t nextIndex[], int16_t index[])
{
    register int16_t i, j;
    int16_t ptr_offset;
    int16_t temp1, temp2;
    int16_t *ptr1, *ptr2;
    int32_t L_temp;

    /*==================================================================*
    *	First find the index into the distortion array where this		*
    *	candidate fits. Note that we assume it has been previously		*
    *	verified that this error falls in the range of the candidate	*
    *	errors. 														*
    *==================================================================*/
    for (i = 0; (i < LSP_VQ_CAND) && (distortion > dMin[i]); i++) ;

    /* shift the distortions and indices down to make room for the new one */
    /*      ptr_offset = (LSP_VQ_CAND - 1) * vq_stages; */

    L_temp = melpe_L_mult((LSP_VQ_CAND - 1), LSP_VQ_STAGES);
    L_temp = melpe_L_shr(L_temp, 1);
    ptr_offset = melpe_extract_l(L_temp);
    temp2 = melpe_add(s1, 1);
    for (j = (LSP_VQ_CAND - 1); j > i; j--) {
        dMin[j] = dMin[j - 1];
        temp1 = melpe_sub(ptr_offset, LSP_VQ_STAGES);
        ptr1 = nextIndex + ptr_offset;	/* Pointer arithmetics. */
        ptr2 = nextIndex + temp1;
        /*      v_equ(nextIndex + j * vq_stages, nextIndex + (j - 1)*vq_stages,
           s1 + 1); */
        v_equ(ptr1, ptr2, temp2);
        ptr_offset = temp1;
    }

    /* insert the index and distortion into the ith candidate */
    dMin[i] = distortion;
    /*      v_equ(nextIndex + i * vq_stages, index + c1 * vq_stages, s1); */
    L_temp = melpe_L_mult(i, LSP_VQ_STAGES);	/* temp1 = i * vq_stages; */
    L_temp = melpe_L_shr(L_temp, 1);
    temp1 = melpe_extract_l(L_temp);
    L_temp = melpe_L_mult(c1, LSP_VQ_STAGES);
    L_temp = melpe_L_shr(L_temp, 1);
    temp2 = melpe_extract_l(L_temp);
    ptr1 = nextIndex + temp1;	/* Pointer arithmetics. */
    ptr2 = index + temp2;
    v_equ(ptr1, ptr2, s1);
    /*      *(nextIndex + i*vq_stages + s1) = entry; */
    ptr1 += s1;		/* Pointer arithmetics. */
    *ptr1 = entry;

    return (dMin[LSP_VQ_CAND - 1]);
}
示例#2
0
void interp_array(int16_t prev[], int16_t curr[], int16_t out[],
		  int16_t ifact, int16_t size)
{
	register int16_t i;
	int16_t ifact2;
	int16_t temp1, temp2;

	if (ifact == 0)
		v_equ(out, prev, size);
	else if (ifact == ONE_Q15)
		v_equ(out, curr, size);
	else {
		ifact2 = melpe_sub(ONE_Q15, ifact);
		for (i = 0; i < size; i++) {
			temp1 = melpe_mult(ifact, curr[i]);
			temp2 = melpe_mult(ifact2, prev[i]);
			out[i] = melpe_add(temp1, temp2);
		}
	}
}
示例#3
0
文件: qnt12.c 项目: ZF0085/onionphone
void lsf_vq(struct melp_param *par)
{
    register int16_t i, j, k;
    static BOOLEAN firstTime = TRUE;
    static int16_t qplsp[LPC_ORD];	/* Q15 */
    const int16_t melp_cb_size[4] = { 256, 64, 32, 32 };	/* !!! (12/15/99) */
    const int16_t res_cb_size[4] = { 256, 64, 64, 64 };
    const int16_t melp_uv_cb_size[1] = { 512 };
    int16_t uv_config;	/* Bits of uv_config replace uv1, uv2 and cuv. */
    int16_t *lsp[NF];
    int32_t err, minErr, acc, bcc;	/* !!! (12/15/99), Q11 */
    int16_t temp1, temp2;
    int16_t lpc[LPC_ORD];	/* Q12 */
    int16_t wgt[NF][LPC_ORD];	/* Q11 */
    int16_t mwgt[2 * LPC_ORD];	/* Q11 */
    int16_t bestlsp0[LPC_ORD], bestlsp1[LPC_ORD];	/* Q15 */
    int16_t res[2 * LPC_ORD];	/* Q17 */

    /* The original program declares lsp_cand[LSP_VQ_CAND][] and              */
    /* lsp_index_cand[LSP_VQ_CAND*LSP_VQ_STAGES] with LSP_VQ_CAND == 8.  The  */
    /* program only uses up to LSP_INP_CAND == 5 and the declaration is       */
    /* modified.                                                              */

    int16_t lsp_cand[LSP_INP_CAND][LPC_ORD];	/* Q15 */
    int16_t lsp_index_cand[LSP_INP_CAND * LSP_VQ_STAGES];
    int16_t ilsp0[LPC_ORD], ilsp1[LPC_ORD];	/* Q15 */
    int16_t cand, inp_index_cand, tos, intfact;

    if (firstTime) {
        temp2 = melpe_shl(LPC_ORD, 10);	/* Q10 */
        temp1 = X08_Q10;	/* Q10 */
        for (i = 0; i < LPC_ORD; i++) {
            /*      qplsp[i] = (i+1)*0.8/LPC_ORD; */
            qplsp[i] = melpe_divide_s(temp1, temp2);
            temp1 = melpe_add(temp1, X08_Q10);
        }
        firstTime = FALSE;
    }

    /* ==== Compute weights ==== */
    for (i = 0; i < NF; i++) {
        lsp[i] = par[i].lsf;
        lpc_lsp2pred(lsp[i], lpc, LPC_ORD);
        vq_lspw(wgt[i], lsp[i], lpc, LPC_ORD);
    }

    uv_config = 0;
    for (i = 0; i < NF; i++) {
        uv_config = melpe_shl(uv_config, 1);
        if (par[i].uv_flag) {
            uv_config |= 0x0001;

            /* ==== Adjust weights ==== */
            if (i == 0)	/* Testing for par[0].uv_flag == 1 */
                v_scale(wgt[0], X02_Q15, LPC_ORD);
            else if (i == 1)
                v_scale(wgt[1], X02_Q15, LPC_ORD);
        }
    }

    /* ==== Quantize the lsp according to the UV decisions ==== */
    switch (uv_config) {
    case 7:		/* 111, all frames are NOT voiced ---- */
        lspVQ(lsp[0], wgt[0], lsp[0], lsp_uv_9, 1, melp_uv_cb_size,
              quant_par.lsf_index[0], LPC_ORD, FALSE);
        lspVQ(lsp[1], wgt[1], lsp[1], lsp_uv_9, 1, melp_uv_cb_size,
              quant_par.lsf_index[1], LPC_ORD, FALSE);
        lspVQ(lsp[2], wgt[2], lsp[2], lsp_uv_9, 1, melp_uv_cb_size,
              quant_par.lsf_index[2], LPC_ORD, FALSE);
        break;
    case 6:		/* 110 */
        lspVQ(lsp[0], wgt[0], lsp[0], lsp_uv_9, 1, melp_uv_cb_size,
              quant_par.lsf_index[0], LPC_ORD, FALSE);
        lspVQ(lsp[1], wgt[1], lsp[1], lsp_uv_9, 1, melp_uv_cb_size,
              quant_par.lsf_index[1], LPC_ORD, FALSE);
        lspVQ(lsp[2], wgt[2], lsp[2], lsp_v_256x64x32x32, 4, melp_cb_size,	/* !!! (12/15/99) */
              quant_par.lsf_index[2], LPC_ORD, FALSE);
        break;
    case 5:		/* 101 */
        lspVQ(lsp[0], wgt[0], lsp[0], lsp_uv_9, 1, melp_uv_cb_size,
              quant_par.lsf_index[0], LPC_ORD, FALSE);
        lspVQ(lsp[1], wgt[1], lsp[1], lsp_v_256x64x32x32, 4, melp_cb_size,	/* !!! (12/15/99) */
              quant_par.lsf_index[1], LPC_ORD, FALSE);
        lspVQ(lsp[2], wgt[2], lsp[2], lsp_uv_9, 1, melp_uv_cb_size,
              quant_par.lsf_index[2], LPC_ORD, FALSE);
        break;
    case 3:		/* 011 */
        lspVQ(lsp[0], wgt[0], lsp[0], lsp_v_256x64x32x32, 4, melp_cb_size,	/* !!! (12/15/99) */
              quant_par.lsf_index[0], LPC_ORD, FALSE);
        lspVQ(lsp[1], wgt[1], lsp[1], lsp_uv_9, 1, melp_uv_cb_size,
              quant_par.lsf_index[1], LPC_ORD, FALSE);
        lspVQ(lsp[2], wgt[2], lsp[2], lsp_uv_9, 1, melp_uv_cb_size,
              quant_par.lsf_index[2], LPC_ORD, FALSE);
        break;
    default:
        if (uv_config == 1) {	/* 001 case, if (!uv1 && !uv2 && uv3). */
            /* ---- Interpolation [4 inp + (8+6+6+6) res + 9 uv] ---- */
            tos = 1;
            lspVQ(lsp[2], wgt[2], lsp_cand[0], lsp_uv_9, tos,
                  melp_uv_cb_size, lsp_index_cand, LPC_ORD, TRUE);
        } else {
            tos = 4;
            lspVQ(lsp[2], wgt[2], lsp_cand[0], lsp_v_256x64x32x32, tos,	/* !!! (12/15/99) */
                  melp_cb_size, lsp_index_cand, LPC_ORD, TRUE);
        }

        minErr = LW_MAX;
        cand = 0;
        inp_index_cand = 0;
        for (k = 0; k < LSP_INP_CAND; k++) {
            for (i = 0; i < 16; i++) {

                err = 0;

                /* Originally we have two for loops here.  One computes       */
                /* ilsp0[] and ilsp1[] and the other one computes "err".  If  */
                /* "err" already exceeds minErr, we can stop the loop and     */
                /* there is no need to compute the remaining ilsp0[] and      */
                /* ilsp1[] entries.  Hence the two for loops are joined.      */

                for (j = 0; j < LPC_ORD; j++) {

                    /*      ilsp0[j] = (inpCoef[i][j] * qplsp[j] +
                       (1.0 - inpCoef[i][j]) * lsp_cand[k][j]); */
                    intfact = inpCoef[i][j];	/* Q14 */
                    acc = melpe_L_mult(intfact, qplsp[j]);	/* Q30 */
                    intfact = melpe_sub(ONE_Q14, intfact);	/* Q14 */
                    acc = melpe_L_mac(acc, intfact, lsp_cand[k][j]);	/* Q30 */
                    ilsp0[j] = melpe_extract_h(melpe_L_shl(acc, 1));
                    acc =
                        melpe_L_sub(acc,
                                    melpe_L_shl(melpe_L_deposit_l(lsp[0][j]),
                                                15));

                    /*      ilsp1[j] = inpCoef[i][j + LPC_ORD] * qplsp[j] +
                       (1.0 - inpCoef[i][j + LPC_ORD]) * lsp_cand[k][j]; */
                    intfact = inpCoef[i][j + LPC_ORD];	/* Q14 */
                    bcc = melpe_L_mult(intfact, qplsp[j]);
                    intfact = melpe_sub(ONE_Q14, intfact);
                    bcc = melpe_L_mac(bcc, intfact, lsp_cand[k][j]);	/* Q30 */
                    ilsp1[j] = melpe_extract_h(melpe_L_shl(bcc, 1));
                    bcc =
                        melpe_L_sub(bcc,
                                    melpe_L_shl(melpe_L_deposit_l(lsp[1][j]),
                                                15));

                    /*      err += wgt0[j]*(lsp0[j] - ilsp0[j])*
                       (lsp0[j] - ilsp0[j]); */
                    temp1 = melpe_norm_l(acc);
                    temp2 = melpe_extract_h(melpe_L_shl(acc, temp1));
                    if (temp2 == MONE_Q15)
                        temp2 = -32767;
                    temp2 = melpe_mult(temp2, temp2);
                    acc = melpe_L_mult(temp2, wgt[0][j]);
                    temp1 = melpe_shl(melpe_sub(1, temp1), 1);
                    acc = melpe_L_shl(acc, melpe_sub(temp1, 3));	/* Q24 */
                    err = melpe_L_add(err, acc);

                    /*      err += wgt1[j]*(lsp1[j] - ilsp1[j])*
                       (lsp1[j] - ilsp1[j]); */
                    temp1 = melpe_norm_l(bcc);
                    temp2 = melpe_extract_h(melpe_L_shl(bcc, temp1));
                    if (temp2 == MONE_Q15)
                        temp2 = -32767;
                    temp2 = melpe_mult(temp2, temp2);
                    bcc = melpe_L_mult(temp2, wgt[1][j]);
                    temp1 = melpe_shl(melpe_sub(1, temp1), 1);
                    bcc = melpe_L_shl(bcc, melpe_sub(temp1, 3));	/* Q24 */
                    err = melpe_L_add(err, bcc);

                    /* computer the err for the last frame */
                    acc = melpe_L_shl(melpe_L_deposit_l(lsp[2][j]), 15);
                    acc =
                        melpe_L_sub(acc,
                                    melpe_L_shl(melpe_L_deposit_l
                                                (lsp_cand[k][j]), 15));
                    temp1 = melpe_norm_l(acc);
                    temp2 = melpe_extract_h(melpe_L_shl(acc, temp1));
                    if (temp2 == MONE_Q15)
                        temp2 = -32767;
                    temp2 = melpe_mult(temp2, temp2);
                    acc = melpe_L_mult(temp2, wgt[2][j]);
                    temp1 = melpe_shl(melpe_sub(1, temp1), 1);
                    acc = melpe_L_shl(acc, melpe_sub(temp1, 3));	/* Q24 */
                    err = melpe_L_add(err, acc);
                }

                if (err < minErr) {
                    minErr = err;
                    cand = k;
                    inp_index_cand = i;
                    v_equ(bestlsp0, ilsp0, LPC_ORD);
                    v_equ(bestlsp1, ilsp1, LPC_ORD);
                }
            }
        }

        v_equ(lsp[2], lsp_cand[cand], LPC_ORD);
        v_equ(quant_par.lsf_index[0], &(lsp_index_cand[cand * tos]),
              tos);
        quant_par.lsf_index[1][0] = inp_index_cand;

        for (i = 0; i < LPC_ORD; i++) {
            temp1 = melpe_sub(lsp[0][i], bestlsp0[i]);	/* Q15 */
            temp2 = melpe_sub(lsp[1][i], bestlsp1[i]);	/* Q15 */
            res[i] = melpe_shl(temp1, 2);	/* Q17 */
            res[i + LPC_ORD] = melpe_shl(temp2, 2);	/* Q17 */
        }
        v_equ(mwgt, wgt[0], LPC_ORD);
        v_equ(mwgt + LPC_ORD, wgt[1], LPC_ORD);

        /* Note that in the following IF block, the lspVQ() is quantizing on  */
        /* res[] and res256x64x64x64[], and both of them are Q17 instead of   */
        /* Q15, unlike the other calling instances in this function.          */

        if (uv_config == 1)	/* if (!uv1 && !uv2 && uv3) */
            lspVQ(res, mwgt, res, res256x64x64x64, 4, res_cb_size,
                  quant_par.lsf_index[2], 2 * LPC_ORD, FALSE);
        else
            lspVQ(res, mwgt, res, res256x64x64x64, 2, res_cb_size,
                  quant_par.lsf_index[2], 2 * LPC_ORD, FALSE);

        /* ---- reconstruct lsp for later stability check ---- */
        for (i = 0; i < LPC_ORD; i++) {
            temp1 = melpe_shr(res[i], 2);
            lsp[0][i] = melpe_add(temp1, bestlsp0[i]);
            temp2 = melpe_shr(res[i + LPC_ORD], 2);
            lsp[1][i] = melpe_add(temp2, bestlsp1[i]);
        }
        break;
    }

    /* ---- Stability checking ---- */
    /* The sortings on lsp[0] and lsp[1] are not necessary because they are   */
    /* variables local to this function and they are discarded upon exit.     */
    /* We only check whether they fit the stability test and issue a warning. */

    (void)lspStable(lsp[0], LPC_ORD);
    (void)lspStable(lsp[1], LPC_ORD);
    if (!lspStable(lsp[2], LPC_ORD))
        lspSort(lsp[2], LPC_ORD);

    v_equ(qplsp, lsp[2], LPC_ORD);
}
示例#4
0
文件: qnt12.c 项目: ZF0085/onionphone
/****************************************************************************
**
** Function:		pitch_vq
**
** Description: 	Pitch values of three frames are vector quantized
**
** Arguments:
**
**	melp_param *par ---- input/output melp parameters
**
** Return value:	None
**
*****************************************************************************/
void pitch_vq(struct melp_param *par)
{
    register int16_t i;
    static BOOLEAN prev_uv_flag = TRUE;
    static int16_t prev_pitch = LOG_UV_PITCH_Q12;	/* Q12 */
    static int16_t prev_qpitch = LOG_UV_PITCH_Q12;	/* Q12 */
    const int16_t *codebook;
    int16_t cnt, size, pitch_index;
    int16_t temp1, temp2;
    int32_t L_temp;
    int16_t dcb[PITCH_VQ_CAND * NF];	/* Q12 */
    int16_t target[NF], deltp[NF];	/* Q12 */
    int16_t deltw[NF];	/* Q0 */
    int16_t weights[NF];	/* Q0 */
    int16_t indexlist[PITCH_VQ_CAND];
    int32_t distlist[PITCH_VQ_CAND];	/* Q25 */

    /* ---- Compute pitch in log domain ---- */
    for (i = 0; i < NF; i++)
        target[i] = log10_fxp(par[i].pitch, 7);	/* Q12 */

    cnt = 0;
    for (i = 0; i < NF; i++) {
        if (par[i].uv_flag)
            weights[i] = 0;	/* Q0 */
        else {
            weights[i] = 1;
            cnt++;
        }
    }

    /* ---- calculate delta ---- */
    for (i = 0; i < NF; i++) {
        if (prev_uv_flag || par[i].uv_flag) {
            deltp[i] = 0;
            deltw[i] = 0;
        } else {
            deltp[i] = melpe_sub(target[i], prev_pitch);
            deltw[i] = DELTA_PITCH_WEIGHT_Q0;
        }
        prev_pitch = target[i];
        prev_uv_flag = par[i].uv_flag;
    }

    if (cnt == 0) {

        for (i = 0; i < NF; i++)
            par[i].pitch = UV_PITCH;
        prev_qpitch = LOG_UV_PITCH_Q12;

    } else if (cnt == 1) {

        for (i = 0; i < NF; i++) {
            if (!par[i].uv_flag) {
                quant_u(&target[i], &(quant_par.pitch_index),
                        PIT_QLO_Q12, PIT_QUP_Q12, PIT_QLEV_M1,
                        PIT_QLEV_M1_Q8, TRUE, 7);
                quant_u_dec(quant_par.pitch_index,
                            &par[i].pitch, PIT_QLO_Q12,
                            PIT_QUP_Q12, PIT_QLEV_M1_Q8, 7);
            } else
                par[i].pitch = LOG_UV_PITCH_Q12;
        }

        /* At this point par[].pitch temporarily holds the pitches in the     */
        /* log domain with Q12.                                               */

        prev_qpitch = par[NF - 1].pitch;	/* Q12 */

        for (i = 0; i < NF; i++)
            par[i].pitch = pow10_fxp(par[i].pitch, 7);	/* Q7 */

    } else if (cnt > 1) {	/* cnt == 2, 3, ......, (NF - 1) */
        /* ----- set pointer ----- */
        if (cnt == NF) {	/* All NF frames are voiced. */
            codebook = pitch_vq_cb_vvv;
            size = PITCH_VQ_LEVEL_VVV;
        } else {
            codebook = pitch_vq_cb_uvv;
            size = PITCH_VQ_LEVEL_UVV;
        }		/* This part changed !!! (12/13/99) */

        /* ---- select candidate using static pitch distortion ---- */
        wvq1(target, weights, codebook, NF, size, indexlist, distlist,
             PITCH_VQ_CAND);

        /* -- select index using static and delta pitch distortion -- */
        temp1 = 0;
        for (i = 0; i < PITCH_VQ_CAND; i++) {
            L_temp = melpe_L_mult(indexlist[i], NF);
            L_temp = melpe_L_shr(L_temp, 1);
            temp2 = melpe_extract_l(L_temp);

            /* Now temp1 is (i*NF) and temp2 is (indexlist[i]*NF).            */

            dcb[temp1] = melpe_sub(codebook[temp2], prev_qpitch);	/* Q12 */
            v_equ(&dcb[temp1 + 1], &codebook[temp2 + 1], NF - 1);
            v_sub(&dcb[temp1 + 1], &codebook[temp2], NF - 1);
            temp1 = melpe_add(temp1, NF);
        }

        pitch_index = wvq2(deltp, deltw, dcb, NF, indexlist, distlist,
                           PITCH_VQ_CAND);

        if (par[NF - 1].uv_flag)
            prev_qpitch = LOG_UV_PITCH_Q12;
        else
            prev_qpitch = codebook[pitch_index * NF + NF - 1];	/* Q12 */

        for (i = 0; i < NF; i++) {
            if (par[i].uv_flag)
                par[i].pitch = UV_PITCH_Q7;
            else
                par[i].pitch =
                    pow10_fxp(codebook[pitch_index * NF + i],
                              7);
        }

        quant_par.pitch_index = pitch_index;
    }
}
示例#5
0
文件: qnt12.c 项目: ZF0085/onionphone
/********************************************************************
**
** Function: lspVQ ()
**
** Description:
**		Vector quantizes a set of int term filter coefficients
**		using a multi-stage M-L tree search algorithm.
**
** Arguments:
**
**	int16_t	target[]	: the target coefficients to be quantized (Q15/Q17)
**	int16_t	weight[]	: weights for mse calculation (Q11)
**	int16_t	qout[]		: the output array (Q15/Q17)
**	int16_t	codebook[]	: codebooks,   cb[0..numStages-1] (Q15/Q17)
**	int16_t	tos 		: the number of stages
**  int16_t	cb_size[]	: codebook size (multistages)
**	int16_t	cb_index[]	: codebook indeces; cb_index[0..numStages-1]
**                            (output)
**  int16_t	dim
**  BOOLEAN		flag
**
** Return value:	None
**
***********************************************************************/
static void lspVQ(int16_t target[], int16_t weight[], int16_t qout[],
                  const int16_t codebook[], int16_t tos,
                  const int16_t cb_size[], int16_t cb_index[],
                  int16_t dim, BOOLEAN flag)
{
    register int16_t i, entry;
    register int16_t c1, s1;
    const int16_t *cdbk_ptr, *cdbk_ptr2, *ptr1;
    int16_t index[LSP_VQ_CAND][LSP_VQ_STAGES];
    int16_t nextIndex[LSP_VQ_CAND][LSP_VQ_STAGES];
    int16_t ncPrev;
    int16_t cand[LSP_VQ_CAND][2 * LPC_ORD];
    int16_t max_dMin, dMin[LSP_VQ_CAND], distortion;
    int16_t *cand_target;
    int32_t L_temp;
    int16_t ptr_offset = 0;
    int16_t temp1, temp2;

    /*==================================================================*
    *	Initialize the data before starting the tree search.			*
    *	  - the number of candidates from the "previous" stage is set	*
    *		to 1 since there is no previous stage!						*
    *	  - the candidate vector from the previous stage is set to zero *
    *	  - the list of indeces for each candidate is set to 1			*
    *==================================================================*/
    for (i = 0; i < LSP_VQ_CAND; i++) {
        v_zap(cand[i], dim);
        v_zap(index[i], LSP_VQ_STAGES);
        v_zap(nextIndex[i], LSP_VQ_STAGES);
    }
    cand_target = v_get(dim);
    ncPrev = 1;

    /*==================================================================*
    *	Now we start the search:										*
    *		For each stage												*
    *			For each candidate from the previous stage				*
    *				For each entry in the current stage codebook		*
    *					* add codebook vector to current candidate		*
    *					* compute the distortion with the target		*
    *					* retain candidate if one of the best so far	*
    *==================================================================*/
    cdbk_ptr = codebook;

    /* An observation for lspVQ() shows that if "flag" is FALSE, then we only */
    /* need to keep track of the best one (instead of the best LSP_VQ_CAND,   */
    /* 8) cand[][] and index[][].  This has significant influence on          */
    /* execution speed.                                                       */

    for (s1 = 0; s1 < tos; s1++) {
        /* set the distortions to huge values */
        fill(dMin, SW_MAX, LSP_VQ_CAND);
        max_dMin = SW_MAX;

        /* Loop for each previous candidate selected, and try each entry */
        for (c1 = 0; c1 < ncPrev; c1++) {
            ptr_offset = 0;

            /* cand_target[] is the target vector with cand[c1] removed.      */
            /* This moves some operations from the for-entry loop here.       */
            /* save_saturation(); */
            v_equ(cand_target, target, dim);
            v_sub(cand_target, cand[c1], dim);
            /* restore_saturation(); */

            for (entry = 0; entry < cb_size[s1]; entry++) {
                ptr1 = cdbk_ptr + ptr_offset;	/* Pointer arithmetics. */

                /* compute the distortion */
                distortion =
                    WeightedMSE(dim, weight, ptr1, cand_target,
                                max_dMin);

                /*======================================================*
                * If the error for this entry is less than the worst	*
                * retained candidate so far, keep it. Note that the 	*
                * error list is maintained in order of best to worst.	*
                *=======================================================*/
                if (distortion < max_dMin) {
                    max_dMin =
                        InsertCand(c1, s1, dMin, distortion,
                                   entry, nextIndex[0],
                                   index[0]);
                }
                ptr_offset = melpe_add(ptr_offset, dim);
            }
        }

        /* At this point ptr_offset is (cb_size[s1]*dim).                     */

        /*==================================================================*
        *	Compute the number of candidate vectors which we kept for the	*
        *	next stage. Note that if the size of the stages is less than	*
        *	the number of candidates, we build them up using all entries	*
        *	until we have kept numCand candidates.  On the other hand, if   *
        *   flag is FALSE and (s1 == tos - 1), then we only need to use     *
        *   ncPrev = 1 because we only copy the best candidate before       *
        *   exiting lspVQ().                                                *
        *==================================================================*/

        if (!flag && s1 == tos - 1)
            ncPrev = 1;
        else {
            /* ncPrev = Min(ncPrev*cb_size[s1], LSP_VQ_CAND) for regular      */
            /* loops, and ncPrev = Min(ncPrev*cb_size[s1], LSP_INP_CAND) for  */
            /* the last lap.  Explanations are available near the end of this *//* function.                                                      */

            L_temp = melpe_L_mult(ncPrev, cb_size[s1]);
            L_temp = melpe_L_shr(L_temp, 1);
            temp1 = melpe_extract_l(L_temp);	/* temp1 = ncPrev * cb_size[s1] */
            if (s1 == tos - 1)
                temp2 = LSP_INP_CAND;
            else
                temp2 = LSP_VQ_CAND;
            if (temp1 < temp2)
                ncPrev = temp1;
            else
                ncPrev = temp2;
        }

        /*==================================================================*
        *	We now have the  best indices for the stage just completed, so	*
        *	compute the new candidate vectors for the next stage... 		*
        *==================================================================*/
        for (c1 = 0; c1 < ncPrev; c1++) {
            v_zap(cand[c1], dim);
            cdbk_ptr2 = codebook;
            temp1 = melpe_add(s1, 1);
            v_equ(index[c1], nextIndex[c1], temp1);
            for (i = 0; i < temp1; i++) {
                /*      v_add(cand[c1], cdbk_ptr2 + index[c1][i]*dim, dim); */
                L_temp = melpe_L_mult(index[c1][i], dim);
                L_temp = melpe_L_shr(L_temp, 1);
                temp2 = melpe_extract_l(L_temp);
                ptr1 = cdbk_ptr2 + temp2;
                v_add(cand[c1], ptr1, dim);
                /*      cdbk_ptr2 += cb_size[i]*dim; */
                L_temp = melpe_L_mult(cb_size[i], dim);
                L_temp = melpe_L_shr(L_temp, 1);
                temp2 = melpe_extract_l(L_temp);
                cdbk_ptr2 += temp2;
            }
        }

        /*      cdbk_ptr += cb_size[s1] * dim; */
        cdbk_ptr += ptr_offset;
    }

    /* Copy best candidate and indices into output.  Here we use temp1 and    */
    /* temp2 to compute (c1*tos) and (c1*dim).                                */

    /* Originally this function copies LSP_VQ_CAND (== 8) vectors before      */
    /* exiting if flag is TRUE.  However, in the calling environment of       */
    /* lspVQ() when flag is passed in as TRUE, we only used LSP_INP_CAND      */
    /* (== 5).                                                                */

    temp1 = 0;
    temp2 = 0;
    for (i = 0; i < ncPrev; i++) {
        v_equ(&(cb_index[temp1]), index[i], tos);
        v_equ(&qout[temp2], cand[i], dim);
        temp1 = melpe_add(temp1, tos);
        temp2 = melpe_add(temp2, dim);
    }

    v_free(cand_target);
}
示例#6
0
文件: qnt12.c 项目: ZF0085/onionphone
/****************************************************************************
**
** Function:		gain_vq
**
** Description: 	Gain quantization for 1200bps
**
** Arguments:
**
**	melp_param *par ---- input/output melp parameters
**
** Return value:	None
**
*****************************************************************************/
void gain_vq(struct melp_param *par)
{
    register int16_t i, j;
    int16_t index;
    int16_t temp, temp2;
    int16_t gain_target[NF_X_NUM_GAINFR];
    int32_t err, minErr;	/* Q17 */
    int32_t L_temp;

    /* Reshape par[i].gain[j] into a one-dimensional vector gain_target[]. */
    temp = 0;
    for (i = 0; i < NF; i++) {
        v_equ(&(gain_target[temp]), par[i].gain, NUM_GAINFR);
        temp = melpe_add(temp, NUM_GAINFR);
    }

    minErr = LW_MAX;
    index = 0;
    temp2 = 0;
    for (i = 0; i < GAIN_VQ_SIZE; i++) {

        /*      temp2 = i * NF * NUM_GAINFR; */

        err = 0;

        /* j = 0 for the following for loop. */
        temp = melpe_sub(gain_target[0], gain_vq_cb[temp2]);	/* Q8 */
        L_temp = melpe_L_mult(temp, temp);	/* Q17 */
        L_temp = melpe_L_shr(L_temp, 3);	/* Q14 */
        err = melpe_L_add(err, L_temp);	/* Q14 */

        /* For the sum of 6 terms, if the first term already exceeds minErr,  */
        /* there is no need to keep computing.                                */

        if (err < minErr) {
            for (j = 1; j < NF_X_NUM_GAINFR; j++) {
                /*      err += SQR(par[j].gain[k] -
                   gain_vq_cb[i*NUM_GAINFR*NF + j*NUM_GAINFR + k]); */
                temp = melpe_sub(gain_target[j], gain_vq_cb[temp2 + j]);	/* Q8 */
                L_temp = melpe_L_mult(temp, temp);	/* Q17 */
                L_temp = melpe_L_shr(L_temp, 3);	/* Q14 */
                err = melpe_L_add(err, L_temp);	/* Q14 */
            }
            if (err < minErr) {
                minErr = err;
                index = i;
            }
        }
        temp2 = melpe_add(temp2, NF_X_NUM_GAINFR);
    }

    /*      temp2 = index * NF * NUM_GAINFR; */
    L_temp = melpe_L_mult(index, NF_X_NUM_GAINFR);
    L_temp = melpe_L_shr(L_temp, 1);
    temp2 = melpe_extract_l(L_temp);
    for (i = 0; i < NF; i++) {
        /*      v_equ(par[i].gain, &(gain_vq_cb[index*NUM_GAINFR*NF +
           i*NUM_GAINFR]), NUM_GAINFR); */
        v_equ(par[i].gain, &(gain_vq_cb[temp2]), NUM_GAINFR);
        temp2 = melpe_add(temp2, NUM_GAINFR);
    }

    quant_par.gain_index[0] = index;
}
示例#7
0
文件: qnt12.c 项目: ZF0085/onionphone
void quant_fsmag(struct melp_param *par)
{
    static BOOLEAN prev_uv = TRUE;
    register int16_t i;
    static int16_t prev_fsmag[NUM_HARM];
    int16_t qmag[NUM_HARM];	/* Q13 */
    int16_t temp1, temp2;
    int16_t p_value, q_value;
    int16_t count, last;

    count = 0;
    last = -1;
    for (i = 0; i < NF; i++) {
        if (par[i].uv_flag)
            fill(par[i].fs_mag, ONE_Q13, NUM_HARM);
        else {
            window_Q(par[i].fs_mag, w_fs, par[i].fs_mag, NUM_HARM,
                     14);
            last = i;
            count++;
        }
    }

    /*      fsvq_enc(par[last].fs_mag, qmag, fs_vq_par); */
    /* Later it is found that we do not need the structured variable          */
    /* fs_vq_par at all.  References to its individual fields can be replaced */
    /* directly with constants or other variables.                            */

    if (count > 0)
        vq_enc(fsvq_cb, par[last].fs_mag, FS_LEVELS, NUM_HARM, qmag,
               &quant_par.fs_index);

    if (count > 1) {
        if (prev_uv || par[0].uv_flag) {
            for (i = 0; i <= last; i++) {
                if (!par[i].uv_flag)
                    v_equ(par[i].fs_mag, qmag, NUM_HARM);
            }
        } else {
            if (par[1].uv_flag) {	/* V VUV */
                v_equ(par[0].fs_mag, prev_fsmag, NUM_HARM);
                v_equ(par[last].fs_mag, qmag, NUM_HARM);
            } else if (par[2].uv_flag) {	/* V VVU */
                v_equ(par[1].fs_mag, qmag, NUM_HARM);
                for (i = 0; i < NUM_HARM; i++) {
                    /*      par[0].fs_mag[i] = 0.5*(qmag[i] + prev_fsmag[i]); */
                    temp1 = melpe_shr(qmag[i], 1);	/* 0.5*qmag[i], Q13 */
                    temp2 = melpe_shr(prev_fsmag[i], 1);	/* Q13 */
                    par[0].fs_mag[i] = melpe_add(temp1, temp2);	/* Q13 */
                }
            } else {	/* V VVV */
                v_equ(par[2].fs_mag, qmag, NUM_HARM);
                for (i = 0; i < NUM_HARM; i++) {
                    p_value = prev_fsmag[i];
                    q_value = qmag[i];	/* Q13 */

                    /* Note that (par[0].fs_mag[i] + par[1].fs_mag[i]) ==     */
                    /* (p + q).  We might replace some multiplications with   */
                    /* additions.                                             */

                    /*      par[0].fs_mag[i] = (p + p + q)/3.0; */
                    temp1 = melpe_mult(p_value, X0667_Q15);	/* Q13 */
                    temp2 = melpe_mult(q_value, X0333_Q15);	/* Q13 */
                    par[0].fs_mag[i] = melpe_add(temp1, temp2);
                    /*      par[1].fs_mag[i] = (p + q + q)/3.0; */
                    temp1 = melpe_mult(p_value, X0333_Q15);
                    temp2 = melpe_mult(q_value, X0667_Q15);
                    par[1].fs_mag[i] = melpe_add(temp1, temp2);
                }
            }
        }
    } else if (count == 1)
        v_equ(par[last].fs_mag, qmag, NUM_HARM);

    prev_uv = par[NF - 1].uv_flag;
    if (prev_uv)
        fill(prev_fsmag, ONE_Q13, NUM_HARM);
    else
        v_equ(prev_fsmag, par[NF - 1].fs_mag, NUM_HARM);
}
示例#8
0
文件: harm.c 项目: gegel/pairphone
/***************************************************************************
**
** Function:		harm_syn_pitch()
**
** Description:		harmonic synthesis for one pitch
**
** Arguments:
**
**	int16_t amp[]			input harmonic mags (Q13)
**	int16_t signal[]		output synthesized signal buffer (Q15)
**	int16_t fc			The cut-off frequency (Q3)
**	int16_t length		The pitch length
**
** Return value:			None
**
*****************************************************************************/
void harm_syn_pitch(int16_t amp[], int16_t signal[], int16_t fc,
		    int16_t length)
{
	register int16_t i;
	int16_t rndphase[SYN_FFT_SIZE / 2 + 1];	/* Q0 */
	int16_t factor, fn;	/* Q15 */
	int16_t temp1, temp2;
	int16_t totalCnt, voicedCnt, mixedCnt, index;
	int16_t mag[SYN_FFT_SIZE / 2 + 1];
	int16_t phase[SYN_FFT_SIZE / 2 + 1];	/* Q0 */
	int16_t fc1, fc2;

	memzero(phase, (SYN_FFT_SIZE / 2 + 1) * sizeof(int16_t));

	/* ====== Generate random phase for unvoiced segment ====== */
	/* Note that phase[] and rndphase[] computed in harm_syn_pitch() are now  */
	/* the actual phases divided by (2*PI)/length.                            */

	for (i = 0; i < length / 2 + 1; i++)
		rndphase[i] = melpe_mult(length, rand_minstdgen());

	/* ====== Harmonic Synthesis ====== */
	/* The fc1 and fc2 computed in the if block below are Q2 */

	if (fc <= X500_Q3) {
		fc1 = melpe_mult(X085_Q14, fc);
		fc2 = melpe_mult(X105_Q14, fc);
		factor = ONE_Q15;
	} else if (fc <= X1000_Q3) {
		fc1 = melpe_mult(X095_Q14, fc);
		fc2 = melpe_mult(X105_Q14, fc);
		factor = X09_Q15;
	} else if (fc <= X2000_Q3) {
		fc1 = melpe_mult(X098_Q14, fc);
		fc2 = melpe_mult(X102_Q14, fc);
		factor = X08_Q15;
	} else if (fc <= X3000_Q3) {
		fc1 = melpe_mult(X095_Q14, fc);
		fc2 = melpe_mult(X105_Q14, fc);
		factor = X075_Q15;
	} else {
		fc1 = melpe_mult(X092_Q14, fc);
		fc2 = melpe_shift_r(fc, -1);	/* We map fc (Q3) to fc2 (Q2) with r_ounding. */
		factor = X07_Q15;
	}

	/* fc1 and fc2 are now Q2. */

	temp1 = melpe_divide_s(fc1, melpe_shl(FSAMP, 2));
	temp2 = melpe_divide_s(fc2, melpe_shl(FSAMP, 2));	/* Now temp1 and temp2 are Q15. */
	voicedCnt = melpe_mult(temp1, length);
	mixedCnt = melpe_mult(temp2, length);
	totalCnt = (int16_t) ((length / 2) + 1);

	/* ====== set values to mag and phase ====== */
	v_equ(mag, amp, melpe_add(voicedCnt, 1));	/* Q13 */

	/* Now we compute phase[] in multiples of w = (2*PI)/length.  Therefore   */
	/* phase[] -> (i*FIXED_PHASE)*length/(2*PI).                              */
	temp1 = 0;		/* temp1 = i * temp2 in the following for loop. */
	temp2 = melpe_extract_l(melpe_L_mult(FIXED_PHASE, length));
	temp2 = melpe_shr(temp2, 1);	/* temp2 = FIXED_PHASE * length */
	while (temp2 >= 2 * length)
		temp2 = melpe_sub(temp2, (int16_t) (2 * length));
	for (i = 0; i < mixedCnt + 1; i++) {
		phase[i] = melpe_shr(temp1, 1);
		temp1 = melpe_add(temp1, temp2);
		if (temp1 >= 2 * length)
			temp1 = melpe_sub(temp1, (int16_t) (2 * length));
	}
	index = 0;
	for (i = melpe_add(voicedCnt, 1); i < melpe_add(mixedCnt, 1); i++, index++) {
		temp1 = melpe_sub(i, voicedCnt);
		temp2 = melpe_sub(mixedCnt, voicedCnt);
		fn = melpe_divide_s(temp1, temp2);	/* Q15 */
		temp1 = melpe_mult(factor, fn);
		temp2 = melpe_sub(ONE_Q15, fn);
		temp1 = melpe_add(temp1, temp2);
		mag[i] = melpe_mult(amp[i], temp1);	/* Q13 */
		temp1 = melpe_mult(fn, rndphase[index]);	/* Q0 */
		temp2 = melpe_sub(phase[i], temp1);
		if (temp2 < 0)
			temp2 = melpe_add(temp2, length);
		phase[i] = temp2;
	}
	for (i = melpe_add(mixedCnt, 1); i < totalCnt; i++, index++) {
		mag[i] = melpe_mult(amp[i], factor);	/* Q13 */
		temp2 = melpe_negate(rndphase[index]);	/* Q0 */
		if (temp2 < 0)
			temp2 = melpe_add(temp2, length);
		phase[i] = temp2;	/* This moves phase[i] from */
		/* negative to positive. */
	}

	/* ====== getting one pitch cycle ====== */
	realIDFT(mag, phase, signal, length);
}
void *analyzer()
{
    clock_t t1, t2;
    //short ana_arr[540] = {0};
    float act_time,msec;
    unsigned char enc_speech[11];
    unsigned char array1[176] = {0x00};
    int b = 0, loc = 0, count_64blocks = 0;
    int i = 0;

    while(count != 0)
    {
        sem_wait(&id_analyzer);
        //sem_wait(&mutx);
        //if (count_64blocks == 0)

        t1 = clock();

        memcpy(ana_arr, buff, 1080);

        sem_post(&empty);

        //t1 = clock();
        num_frames = (int16_t) ((rate == RATE2400) ? 1 : NF);

        //for (i = 0; i < num_frames; i++)
        //{
        //	dc_rmv(&ana_arr[i * FRAME], &hpspeech[IN_BEG + i * FRAME],
        //			dcdelin, dcdelout_hi, dcdelout_lo, FRAME);
        //	//melp_ana(&hpspeech[i * FRAME], &melp_par[i], i);
        //}

        dc_rmv(&ana_arr[0], &hpspeech[IN_BEG + 0],
               dcdelin, dcdelout_hi, dcdelout_lo, FRAME);
        melp_ana(&hpspeech[0], &melp_par[0],0);

        dc_rmv(&ana_arr[FRAME], &hpspeech[IN_BEG + FRAME],
               dcdelin, dcdelout_hi, dcdelout_lo, FRAME);
        melp_ana(&hpspeech[FRAME], &melp_par[1], 1);

        dc_rmv(&ana_arr[2 * FRAME], &hpspeech[IN_BEG + 2 * FRAME],
               dcdelin, dcdelout_hi, dcdelout_lo, FRAME);
        melp_ana(&hpspeech[2 * FRAME], &melp_par[2], 2);

        /*sem_post(&start_melp_1ana);
        sem_post(&start_melp_2ana);
        sem_post(&start_melp_3ana);


        sem_wait(&melp_1ana);
        sem_wait(&melp_2ana);
        sem_wait(&melp_3ana);*/


        sc_ana(melp_par);

        /* ======== Quantization ======== */

        lpc[0] = ONE_Q12;

        lsf_vq(melp_par);

        pitch_vq(melp_par);

        gain_vq(melp_par);

        quant_u(&melp_par[0].jitter, &(quant_par.jit_index[0]), 0,
                MAX_JITTER_Q15, 2, ONE_Q15, 1, 7);
        quant_u(&melp_par[1].jitter, &(quant_par.jit_index[1]), 0,
                MAX_JITTER_Q15, 2, ONE_Q15, 1, 7);
        quant_u(&melp_par[2].jitter, &(quant_par.jit_index[2]), 0,
                MAX_JITTER_Q15, 2, ONE_Q15, 1, 7);

        //for (i = 0; i < NF; i++)
        //	quant_u(&melp_par[i].jitter, &(quant_par.jit_index[i]), 0,
        //		MAX_JITTER_Q15, 2, ONE_Q15, 1, 7);

        /* Quantize bandpass voicing */

        quant_bp(melp_par, num_frames);

        quant_jitter(melp_par);

        /* Calculate Fourier coeffs of residual from quantized LPC */
        //for (i = 0; i < num_frames; i++)
        //{
        //	/* The following fill() action is believed to be unnecessary. */
        //	//fill(melp_par[i].fs_mag, ONE_Q13, NUM_HARM);
        //
        //	if (!melp_par[i].uv_flag)
        //	{
        //		lpc_lsp2pred(melp_par[i].lsf, &(lpc[1]), LPC_ORD);
        //		zerflt(&hpspeech
        //			   [(i * FRAME + FRAME_END - (LPC_FRAME / 2))], lpc,
        //			   sigbuf, LPC_ORD, LPC_FRAME);
        //
        //		window(sigbuf, win_cof, sigbuf, LPC_FRAME);
        //
        //		find_harm(sigbuf, melp_par[i].fs_mag, melp_par[i].pitch, NUM_HARM,
        //			  LPC_FRAME);
        //	}
        //}
        i = 0;
        if (!melp_par[i].uv_flag)
        {
            lpc_lsp2pred(melp_par[i].lsf, &(lpc[1]), LPC_ORD);
            zerflt(&hpspeech
                   [(i * FRAME + FRAME_END - (LPC_FRAME / 2))], lpc,
                   sigbuf, LPC_ORD, LPC_FRAME);

            window(sigbuf, win_cof, sigbuf, LPC_FRAME);

            find_harm(sigbuf, melp_par[i].fs_mag, melp_par[i].pitch, NUM_HARM,
                      LPC_FRAME);
        }
        i = 1;
        if (!melp_par[i].uv_flag)
        {
            lpc_lsp2pred(melp_par[i].lsf, &(lpc[1]), LPC_ORD);
            zerflt(&hpspeech
                   [(i * FRAME + FRAME_END - (LPC_FRAME / 2))], lpc,
                   sigbuf, LPC_ORD, LPC_FRAME);

            window(sigbuf, win_cof, sigbuf, LPC_FRAME);

            find_harm(sigbuf, melp_par[i].fs_mag, melp_par[i].pitch, NUM_HARM,
                      LPC_FRAME);
        }
        i = 2;
        if (!melp_par[i].uv_flag)
        {
            lpc_lsp2pred(melp_par[i].lsf, &(lpc[1]), LPC_ORD);
            zerflt(&hpspeech
                   [(i * FRAME + FRAME_END - (LPC_FRAME / 2))], lpc,
                   sigbuf, LPC_ORD, LPC_FRAME);

            window(sigbuf, win_cof, sigbuf, LPC_FRAME);

            find_harm(sigbuf, melp_par[i].fs_mag, melp_par[i].pitch, NUM_HARM,
                      LPC_FRAME);
        }

        quant_fsmag(melp_par);

        //for (i = 0; i < num_frames; i++)
        //	quant_par.uv_flag[i] = melp_par[i].uv_flag;
        quant_par.uv_flag[0] = melp_par[0].uv_flag;
        quant_par.uv_flag[1] = melp_par[1].uv_flag;
        quant_par.uv_flag[2] = melp_par[2].uv_flag;

        /* Write channel bitstream */

#if !SKIP_CHANNEL
        low_rate_chn_write(&quant_par);
#endif

        /* Update delay buffers for next block */
        v_equ(hpspeech, &(hpspeech[num_frames * FRAME]), IN_BEG);

        memcpy(enc_speech,chbuf,11);



        /*======================old content of melp thread======================*/
        //melpe_a(enc_speech, buff);
        //fwrite(enc_speech,sizeof(char),11,fptr);
        //=======================================================================
        // ather_jawad work for 2400 baudrate
        //=======================================================================
        for (b=0; b<11; b++)
        {
            array1[loc] = enc_speech[b];
            loc++;
        }

        count_64blocks = count_64blocks + 1;
        if(count_64blocks == 16)
        {
            loc = 0;
            memcpy(array2,array1,176);
            sem_post(&last);

            count_64blocks = 0;
        }

        t2 = clock() - t1;
        //printf("Time %d = %f\n\n",count_64blocks,(float)t2/CLOCKS_PER_SEC);

        //sem_post(&full);
    }
    pthread_exit(NULL);
}
示例#10
0
void melp_ana(float sp_in[],struct melp_param *par)
{

    int i;
    int begin;
    float sub_pitch;
    float temp,pcorr,bpthresh;
    float r[LPC_ORD+1],refc[LPC_ORD+1],lpc[LPC_ORD+1];
    float weights[LPC_ORD];
        
    /* Remove DC from input speech */
    dc_rmv(sp_in,&speech[IN_BEG],dcdel,FRAME);
    
    /* Copy input speech to pitch window and lowpass filter */
    v_equ(&sigbuf[LPF_ORD],&speech[PITCH_BEG],PITCH_FR);
    v_equ(sigbuf,lpfsp_del,LPF_ORD);
    polflt(&sigbuf[LPF_ORD],lpf_den,&sigbuf[LPF_ORD],LPF_ORD,PITCH_FR);
    v_equ(lpfsp_del,&sigbuf[FRAME],LPF_ORD);
    zerflt(&sigbuf[LPF_ORD],lpf_num,&sigbuf[LPF_ORD],LPF_ORD,PITCH_FR);
    
    /* Perform global pitch search at frame end on lowpass speech signal */
    /* Note: avoid short pitches due to formant tracking */
    fpitch[END] = find_pitch(&sigbuf[LPF_ORD+(PITCH_FR/2)],&temp,
			     (2*PITCHMIN),PITCHMAX,PITCHMAX);
    
    /* Perform bandpass voicing analysis for end of frame */
    bpvc_ana(&speech[FRAME_END], fpitch, &par->bpvc[0], &sub_pitch);
    
    /* Force jitter if lowest band voicing strength is weak */    
    if (par->bpvc[0] < VJIT)
	par->jitter = MAX_JITTER;
    else
	par->jitter = 0.0;
    
    /* Calculate LPC for end of frame */
    window(&speech[(FRAME_END-(LPC_FRAME/2))],win_cof,sigbuf,LPC_FRAME);
    autocorr(sigbuf,r,LPC_ORD,LPC_FRAME);
    lpc[0] = 1.0;
    lpc_schur(r,lpc,refc,LPC_ORD);
    lpc_bw_expand(lpc,lpc,BWFACT,LPC_ORD);
    
    /* Calculate LPC residual */
    zerflt(&speech[PITCH_BEG],lpc,&sigbuf[LPF_ORD],LPC_ORD,PITCH_FR);
        
    /* Check peakiness of residual signal */
    begin = (LPF_ORD+(PITCHMAX/2));
    temp = peakiness(&sigbuf[begin],PITCHMAX);
    
    /* Peakiness: force lowest band to be voiced  */
    if (temp > PEAK_THRESH) {
	par->bpvc[0] = 1.0;
    }
    
    /* Extreme peakiness: force second and third bands to be voiced */
    if (temp > PEAK_THR2) {
	par->bpvc[1] = 1.0;
	par->bpvc[2] = 1.0;
    }
		
    /* Calculate overall frame pitch using lowpass filtered residual */
    par->pitch = pitch_ana(&speech[FRAME_END], &sigbuf[LPF_ORD+PITCHMAX], 
			   sub_pitch,pitch_avg,&pcorr);
    bpthresh = BPTHRESH;
    
    /* Calculate gain of input speech for each gain subframe */
    for (i = 0; i < NUM_GAINFR; i++) {
	if (par->bpvc[0] > bpthresh) {

	    /* voiced mode: pitch synchronous window length */
	    temp = sub_pitch;
	    par->gain[i] = gain_ana(&speech[FRAME_BEG+(i+1)*GAINFR],
				    temp,MIN_GAINFR,2*PITCHMAX);
	}
	else {
	    temp = 1.33*GAINFR - 0.5;
	    par->gain[i] = gain_ana(&speech[FRAME_BEG+(i+1)*GAINFR],
				    temp,0,2*PITCHMAX);
	}
    }
    
    /* Update average pitch value */
    if (par->gain[NUM_GAINFR-1] > SILENCE_DB)
      temp = pcorr;
    else
      temp = 0.0;
    pitch_avg = p_avg_update(par->pitch, temp, VMIN);
    
    /* Calculate Line Spectral Frequencies */
    lpc_pred2lsp(lpc,par->lsf,LPC_ORD);
    
    /* Force minimum LSF bandwidth (separation) */
    lpc_clamp(par->lsf,BWMIN,LPC_ORD);
    
    /* Quantize MELP parameters to 2400 bps and generate bitstream */
    
    /* Quantize LSF's with MSVQ */
    vq_lspw(weights, &par->lsf[1], lpc, LPC_ORD);
    msvq_enc(&par->lsf[1], weights, &par->lsf[1], vq_par);
    par->msvq_index = vq_par.indices;
    
    /* Force minimum LSF bandwidth (separation) */
    lpc_clamp(par->lsf,BWMIN,LPC_ORD);
    
    /* Quantize logarithmic pitch period */
    /* Reserve all zero code for completely unvoiced */
    par->pitch = log10(par->pitch);
    quant_u(&par->pitch,&par->pitch_index,PIT_QLO,PIT_QUP,PIT_QLEV);
    par->pitch = pow(10.0,par->pitch);
    
    /* Quantize gain terms with uniform log quantizer	*/
    q_gain(par->gain, par->gain_index,GN_QLO,GN_QUP,GN_QLEV);
    
    /* Quantize jitter and bandpass voicing */
    quant_u(&par->jitter,&par->jit_index,0.0,MAX_JITTER,2);
    par->uv_flag = q_bpvc(&par->bpvc[0],&par->bpvc_index,bpthresh,
			  NUM_BANDS);
    
    /*	Calculate Fourier coefficients of residual signal from quantized LPC */
    fill(par->fs_mag,1.0,NUM_HARM);
    if (par->bpvc[0] > bpthresh) {
	lpc_lsp2pred(par->lsf,lpc,LPC_ORD);
	zerflt(&speech[(FRAME_END-(LPC_FRAME/2))],lpc,sigbuf,
	       LPC_ORD,LPC_FRAME);
	window(sigbuf,win_cof,sigbuf,LPC_FRAME);
	find_harm(sigbuf, par->fs_mag, par->pitch, NUM_HARM, LPC_FRAME);
    }
    
    /* quantize Fourier coefficients */
    /* pre-weight vector, then use Euclidean distance */
    window(&par->fs_mag[0],w_fs,&par->fs_mag[0],NUM_HARM);
    fsvq_enc(&par->fs_mag[0], &par->fs_mag[0], fs_vq_par);
    
    /* Set MELP indeces to point to same array */
    par->fsvq_index = fs_vq_par.indices;

    /* Update MSVQ information */
    par->msvq_stages = vq_par.num_stages;
    par->msvq_bits = vq_par.num_bits;

    /* Write channel bitstream */
    melp_chn_write(par);

    /* Update delay buffers for next frame */
    v_equ(&speech[0],&speech[FRAME],IN_BEG);
    fpitch[BEGIN] = fpitch[END];
}