/******************************************************************** ** ** 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]); }
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); } } }
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); }
/**************************************************************************** ** ** 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; } }
/******************************************************************** ** ** 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); }
/**************************************************************************** ** ** 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; }
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); }
/*************************************************************************** ** ** 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); }
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]; }