void apfilter(int16_t a[], /* (i) Q12 : prediction coefficients */ int16_t m, /* (i) : LPC order */ int16_t x[], /* (i) Q0 : input signal */ int16_t y[], /* (o) Q0 : output signal */ int16_t lg, /* (i) : size of filtering */ int16_t mem[], /* (i/o) Q0: filter memory */ int16_t update /* (i) : memory update flag */ ) { int16_t buf[BUFFERSIZE]; /* buffer for filter memory & signal */ int32_t a0; int16_t *fp1; int16_t i, n; /* copy filter memory to beginning part of temporary buffer */ W16copy(buf, mem, m); /* loop through every element of the current vector */ for (n = 0; n < lg; n++) { /* perform bv_multiply-bv_adds along the delay line of filter */ fp1 = &buf[n]; a0 = L_bv_mult0(4096, x[n]); // Q12 for (i = m; i > 0; i--) a0 = bv_L_msu0(a0, a[i], *fp1++); // Q12 /* update temporary buffer for filter memory */ *fp1 = intround(L_bv_shl(a0, 4)); } /* copy to output array */ W16copy(y, buf + m, lg); /* get the filter memory after filtering the current vector */ if (update) W16copy(mem, buf + lg, m); return; }
void BV16_Decode( struct BV16_Bit_Stream *bs, struct BV16_Decoder_State *ds, Word16 *x) { Word32 lgq, lg_el; Word16 gainq; /* Q3 */ Word16 pp; Word32 a0; Word16 gain_exp; Word16 i; Word16 a0hi, a0lo; Word16 ltsym[LTMOFF+FRSZ]; Word16 xq[LXQ]; Word16 a[LPCO+1]; Word16 lspq[LPCO]; /* Q15 */ Word16 cbs[VDIM*CBSZ]; Word16 bq[3]; /* Q15 */ Word32 bss; Word32 E; /* set frame erasure flags */ if (ds->cfecount != 0) { ds->ngfae = 1; } else { ds->ngfae++; if (ds->ngfae>LGPORDER) ds->ngfae=LGPORDER+1; } /* reset frame erasure counter */ ds->cfecount = 0; /* decode pitch period */ pp = (bs->ppidx + MINPP); /* decode spectral information */ lspdec(lspq,bs->lspidx,ds->lsppm,ds->lsplast); lsp2a(lspq,a); W16copy(ds->lsplast, lspq, LPCO); /* decode pitch taps */ pp3dec(bs->bqidx, bq); /* decode gain */ a0 = gaindec(&lgq,bs->gidx,ds->lgpm,ds->prevlg,ds->level, &ds->nggalgc,&lg_el); /* gain normalization */ gain_exp = sub(norm_l(a0), 2); /* scale down quantized gain by 1.5, 1/1.5=2/3 (21845 Q15) */ L_Extract(a0, &a0hi, &a0lo); a0 = Mpy_32_16(a0hi, a0lo, 21845); gainq = intround(L_shl(a0, gain_exp)); /* scale the scalar quantizer codebook to current signal level */ for (i=0;i<(VDIM*CBSZ);i++) cbs[i] = mult_r(gainq, cccb[i]); /* copy state memory to buffer */ W16copy(xq, ds->xq, XQOFF); W16copy(ltsym, ds->ltsym, LTMOFF); /* decoding of the excitation signal with integrated long-term */ /* and short-term synthesis */ excdec_w_synth(xq+XQOFF,ltsym+LTMOFF,ds->stsym,bs->qvidx,bq,cbs,pp, a,gain_exp,&E); ds->E = E; /* update the remaining state memory */ W16copy(ds->ltsym, ltsym+FRSZ, LTMOFF); W16copy(ds->xq, xq+FRSZ, XQOFF); ds->pp_last = pp; W16copy(ds->bq_last, bq, 3); /* level estimation */ estlevel(lg_el,&ds->level,&ds->lmax,&ds->lmin,&ds->lmean,&ds->x1, ds->ngfae, ds->nggalgc,&ds->estl_alpha_min); /* adaptive postfiltering */ postfilter(xq, pp, &(ds->ma_a), ds->b_prv, &(ds->pp_prv), x); /* scale signal up by 1.5 */ for(i=0; i<FRSZ; i++) x[i] = add(x[i], shr(x[i],1)); W16copy(ds->atplc, a, LPCO+1); bss = L_add(L_add(bq[0], bq[1]), bq[2]); if (bss > 32768) bss = 32768; else if (bss < 0) bss = 0; ds->per = add(shr(ds->per, 1), (Word16)L_shr(bss, 1)); }
void excdec_w_synth( Word16 *xq, /* (o) Q0 quantized signal vector */ Word16 *ltsym, /* (i/o) Q0 quantized excitation signal vector */ Word16 *stsym, /* (i/o) Q0 short-term predictor memory */ Word16 *idx, /* (o) quantizer codebook index for uq[] vector */ Word16 *b, /* (i) Q15 coefficient of 3-tap pitch predictor */ Word16 *cb, /* (i) Q0 codebook */ Word16 pp, /* pitch period (# of 8 kHz samples) */ Word16 *aq, /* (i) Q12 short-term predictor coefficients */ Word16 gain_exp, /* gain_exp of current sub-frame */ Word32 *EE ) { Word16 i, n, m, *ip, id; Word16 *fp1, *fp2, *fp3; Word32 a0; Word16 tt; Word32 E; Word32 a1; Word16 buf1[LPCO+FRSZ]; /* buffer for filter memory & signal */ Word16 uq[VDIM]; /* selected codebook vector (incl. sign) */ W16copy(buf1, stsym, LPCO); /* buffer is used to avoid memory shifts */ ip=idx; E = 0; /* Loop through every vector of the current subframe */ for (m = 0; m < FRSZ; m += VDIM) { /********************************************************************************/ /* Excitation vector */ /********************************************************************************/ id = *ip++; /* get codebook index of current vector */ fp1 = uq; if (id < CBSZ){ fp2 = &cb[id*VDIM]; for (n=0;n<VDIM;n++) { *fp1++ = *fp2++; // Q0 } } else { id -= CBSZ; fp2 = &cb[id*VDIM]; for (n=0;n<VDIM;n++) { *fp1++ = negate(*fp2++); // Q0 } } /********************************************************************************/ /* Long-term and short-term synthesis */ /********************************************************************************/ fp2 = uq; fp3 = ltsym + m; for (n = m; n < m + VDIM; n++) { /* Un-normalized excitation */ a0 = L_shr(L_deposit_h(*fp2++), gain_exp); // Q16 /* Excitation energy for PLC */ tt = intround(a0); // Q0 E = L_mac0(E, tt, tt); /* Long-term predicion */ fp1 = <sym[n-pp+1]; // Q0 a1 = L_mult(*fp1--, b[0]); // Q16 a1 = L_mac(a1, *fp1--, b[1]); a1 = L_mac(a1, *fp1--, b[2]); /* Update long-term filter synthesis memory */ a0 = L_add(a0, a1); *fp3++ = intround(a0); // Q0 /* Short-term prediction */ fp1 = &buf1[n]; // Q0 a1 = 0; // Q13 for(i = LPCO; i > 0; i--) a1 = L_msu(a1, *fp1++, aq[i]); // Q13 a1 = L_shl(a1, 3); // Q16 a1 = L_add(a0, a1); *fp1++ = intround(a1); // Q0 } } /* Update noise feedback filter memory after filtering current subframe */ W16copy(stsym, buf1+FRSZ, LPCO); /* copy to speech buffer */ W16copy(xq, buf1+LPCO, FRSZ); *EE = E; return; }
void a2lsp( Word16 pc[], /* (i) Q12: predictor coefficients */ Word16 lsp[], /* (o) Q15: line spectral pairs */ Word16 old_lsp[]) /* (i) Q15: old lsp */ { Word16 i, j, exp; Word16 fa_man[NAB], fa_exp[NAB], fb_man[NAB], fb_exp[NAB]; Word16 ta_man[NAB], ta_exp[NAB], tb_man[NAB], tb_exp[NAB]; Word16 *t_man, *t_exp; Word32 a0; Word16 nd2, nf, ngrd; Word16 xroot, xlow, ylow, ind, xhigh, yhigh, xmid, ymid, dx, dy, dxdy, x, sign; /* Find normalization for fa and fb */ /* fb[0] = fa[0] = 1.0; */ /* for (i = 1, j = LPCO; i <= (LPCO/2); i++, j--) { */ /* fa[i] = pc[i] + pc[j] - fa[i-1]; */ /* fb[i] = pc[i] - pc[j] + fb[i-1]; */ /* } */ fa_man[0] = 16384; fa_exp[0] = 6; // fa_man[0] in high 16-bits >> fa_exp[0] = 1.0 in Q24 fb_man[0] = 16384; fb_exp[0] = 6; // fb_man[0] in high 16-bits >> fb_exp[0] = 1.0 in Q24 for (i = 1, j = LPCO; i <= (LPCO/2); i++, j--) { a0 = L_mult0(pc[i], 4096); // Q24 a0 = L_mac0(a0, pc[j], 4096); // Q24 a0 = L_sub(a0, L_shr(L_deposit_h(fa_man[i-1]),fa_exp[i-1])); // Q24 fa_exp[i] = norm_l(a0); fa_man[i] = intround(L_shl(a0, fa_exp[i])); // Q(8+fb_exp[i]) a0 = L_mult0(pc[i], 4096); // Q24 a0 = L_msu0(a0, pc[j], 4096); // Q24 a0 = L_add(a0, L_shr(L_deposit_h(fb_man[i-1]),fb_exp[i-1])); // Q24 fb_exp[i] = norm_l(a0); fb_man[i] = intround(L_shl(a0, fb_exp[i])); // Q(8+fb_exp[i]) } nd2 = (LPCO)/2; /* ta[] and tb[] in Q(7+exp) */ /* ta[0] = fa[nab-1]; ta[i] = 2.0 * fa[j]; */ /* tb[0] = fb[nab-1]; tb[i] = 2.0 * fb[j]; */ ta_man[0] = fa_man[NAB-1]; ta_exp[0] = add(fa_exp[NAB-1], 1); tb_man[0] = fb_man[NAB-1]; tb_exp[0] = add(fb_exp[NAB-1], 1); for (i = 1, j = NAB - 2; i < NAB; ++i, --j) { ta_man[i] = fa_man[j]; ta_exp[i] = fa_exp[j]; tb_man[i] = fb_man[j]; tb_exp[i] = fb_exp[j]; } nf = 0; t_man = ta_man; t_exp = ta_exp; xroot = 0x7fff; ngrd = 0; xlow = grid[0]; // Q15 ylow = FNevChebP(xlow, t_man, t_exp, nd2); ind = 0; /* Root search loop */ while (ngrd<(Ngrd-1) && nf < LPCO) { ngrd++; xhigh = xlow; yhigh = ylow; xlow = grid[ngrd]; ylow = FNevChebP(xlow, t_man, t_exp, nd2); if ( L_mult(ylow ,yhigh) <= 0) { /* Bisections of the interval containing a sign change */ dx = xhigh - xlow; for (i = 1; i <= NBIS; ++i) { dx = shr(dx, 1); xmid = add(xlow, dx); ymid = FNevChebP(xmid, t_man, t_exp, nd2); if (L_mult(ylow,ymid) <= 0) { yhigh = ymid; xhigh = xmid; } else { ylow = ymid; xlow = xmid; } } /* * Linear interpolation in the subinterval with a sign change * (take care if yhigh=ylow=0) */ dx = sub(xhigh, xlow); dy = sub(ylow, yhigh); if (dy != 0) { sign = dy; dy = abs_s(dy); exp = norm_s(dy); dy = shl(dy, exp); /* The maximum grid distance is 1629 => */ /* Maximum dx=1629/2^4=101.8125, i.e. 16384/101.8125=160.92~128 (7 bits) */ /* However, due to the starting point for the search of a new root, */ /* xlow = xroot, 1 more bit of headroom for the division is required. */ dxdy = div_s(shl(dx,6), dy); a0 = L_mult(dxdy, ylow); a0 = L_shr(a0, sub(6, exp)); x = intround(a0); if(sign < 0) x = negate(x); xmid = add(xlow, x); } else { xmid = add(xlow, shr(dx,1)); } /* acos mapping for New lsp component */ while (( costable[ind] >= xmid ) && (ind < 63)) ind++; ind--; a0 = L_mult( sub(xmid, costable[ind]) , acosslope[ind] ); x = intround(L_shl(a0, 4)); lsp[nf] = add(x, shl(ind, 9)); ++nf; /* Start the search for the roots of next polynomial at the estimated * location of the root just found. We have to catch the case that the * two polynomials have roots at the same place to avoid getting stuck at * that root. */ if (xmid >= xroot) xmid = xlow - dx; xroot = xmid; if (t_man == ta_man){ t_man = tb_man; t_exp = tb_exp; } else{ t_man = ta_man; t_exp = ta_exp; } xlow = xmid; ylow = FNevChebP(xlow, t_man, t_exp, nd2); } } /* Check if all LSPs are found */ if( sub(nf, LPCO) < 0) { W16copy(lsp, old_lsp, LPCO); } return; }