void azfilter( Word16 a[], /* (i) Q12 : prediction coefficients */ Word16 m, /* (i) : LPC order */ Word16 x[], /* (i) Q0 : input signal samples, incl. past */ Word16 y[], /* (o) Q0 : filtered output signal */ Word16 lg /* (i) : size of filtering */ ) { Word16 i, n; Word32 a0; Word16 *fp1; /* loop through every element of the current vector */ for (n = 0; n < lg; n++) { /* perform multiply-adds along the delay line of filter */ fp1 = x + n; a0 = L_mult0(a[0], *fp1--); // Q12 for (i = 1; i <= m; i++) a0 = L_mac0(a0, a[i], *fp1--); // Q12 /* get the output with rounding */ y[n] = intround(L_shl(a0, 4)); // Q0 } return; }
/** * \brief 31x16 Bit multiply (x*y) * * \param[i] xh high part, bit [30..15] * \param[i] xl low part, 15 LSBits * \param[i] y * * \return x*y */ Word32 L_multi31x16_X2(Word16 xh, Word16 xl, Word16 y) { Word32 z; z = L_shl(L_mult0(xh,y),15); z = L_mac0(z,xl,y); return z; }
/**************************************************************************************** Function: categorize Syntax: void categorize(Word16 number_of_available_bits, Word16 number_of_regions, Word16 num_categorization_control_possibilities, Word16 rms_index, Word16 power_categories, Word16 category_balances) inputs: number_of_regions num_categorization_control_possibilities number_of_available_bits rms_index[MAX_NUMBER_OF_REGIONS] outputs: power_categories[MAX_NUMBER_OF_REGIONS] category_balances[MAX_NUM_CATEGORIZATION_CONTROL_POSSIBILITIES-1] Description: Computes a series of categorizations WMOPS: 7kHz | 24kbit | 32kbit -------|--------------|---------------- AVG | 0.14 | 0.14 -------|--------------|---------------- MAX | 0.15 | 0.15 -------|--------------|---------------- 14kHz | 24kbit | 32kbit | 48kbit -------|--------------|----------------|---------------- AVG | 0.42 | 0.45 | 0.48 -------|--------------|----------------|---------------- MAX | 0.47 | 0.52 | 0.52 -------|--------------|----------------|---------------- ****************************************************************************************/ void categorize(Word16 number_of_available_bits, Word16 number_of_regions, Word16 num_categorization_control_possibilities, Word16 *rms_index, Word16 *power_categories, Word16 *category_balances) { Word16 offset; Word16 temp; Word16 frame_size; /* At higher bit rates, there is an increase for most categories in average bit consumption per region. We compensate for this by pretending we have fewer available bits. */ test(); if (number_of_regions == NUMBER_OF_REGIONS) { frame_size = DCT_LENGTH; } else { frame_size = MAX_DCT_LENGTH; } temp = sub(number_of_available_bits,frame_size); test(); if (temp > 0) { number_of_available_bits = sub(number_of_available_bits,frame_size); number_of_available_bits = extract_l(L_mult0(number_of_available_bits,5)); number_of_available_bits = shr(number_of_available_bits,3); number_of_available_bits = add(number_of_available_bits,frame_size); } /* calculate the offset using the original category assignments */ offset = calc_offset(rms_index,number_of_regions,number_of_available_bits); /* compute the power categories based on the uniform offset */ compute_raw_pow_categories(power_categories,rms_index,number_of_regions,offset); /* adjust the category assignments */ /* compute the new power categories and category balances */ comp_powercat_and_catbalance(power_categories,category_balances,rms_index,number_of_available_bits,number_of_regions,num_categorization_control_possibilities,offset); }
/*************************************************************************** Function: adjust_abs_region_power_index Syntax: adjust_abs_region_power_index(Word16 *absolute_region_power_index, Word16 *mlt_coefs, Word16 number_of_regions) inputs: *mlt_coefs *absolute_region_power_index number_of_regions outputs: *absolute_region_power_index Description: Adjusts the absolute power index WMOPS: 7kHz | 24kbit | 32kbit -------|--------------|---------------- AVG | 0.03 | 0.03 -------|--------------|---------------- MAX | 0.12 | 0.12 -------|--------------|---------------- 14kHz | 24kbit | 32kbit | 48kbit -------|--------------|----------------|---------------- AVG | 0.03 | 0.03 | 0.03 -------|--------------|----------------|---------------- MAX | 0.14 | 0.14 | 0.14 -------|--------------|----------------|---------------- ***************************************************************************/ void adjust_abs_region_power_index(Word16 *absolute_region_power_index,Word16 *mlt_coefs,Word16 number_of_regions) { Word16 n,i; Word16 region; Word16 *raw_mlt_ptr; Word32 acca; Word16 temp; for (region=0; region<number_of_regions; region++) { n = sub(absolute_region_power_index[region],39); n = shr_nocheck(n,1); test(); if (n > 0) { temp = extract_l(L_mult0(region,REGION_SIZE)); raw_mlt_ptr = &mlt_coefs[temp]; for (i=0; i<REGION_SIZE; i++) { acca = L_shl_nocheck(*raw_mlt_ptr,16); acca = L_add(acca,32768L); acca = L_shr_nocheck(acca,n); acca = L_shr_nocheck(acca,16); *raw_mlt_ptr++ = extract_l(acca); } temp = shl_nocheck(n,1); temp = sub(absolute_region_power_index[region],temp); absolute_region_power_index[region] = temp; move16(); } } }
/* Standard Long-Term Postfilter */ void postfilter( Word16 *s, /* input : quantized speech signal */ Word16 pp, /* input : pitch period */ Word16 *ma_a, Word16 *b_prv, Word16 *pp_prv, Word16 *e) /* output: enhanced speech signal */ { int n; Word16 len, t0, t1, t2, t3, shift, aa, R0norm, R0_exp; Word32 a0, a1, R0, R1, R01, R01max, Rx; Word16 *fp1; Word16 ppt, pptmin, pptmax, ppnew; Word16 bb[2]; Word16 R1max_exp, R1max, R01Sqmax_exp, R01Sqmax, R01Sq_exp, R01Sq, R1_exp, R1n; Word16 gainn, Rx_exp; Word16 buf[MAXPP+FRSZ]; Word16 *ps, ww1, ww2; Word32 step, delta; Word16 bi0, bi1c, bi1p; ps = s+XQOFF; /********************************************************************/ /* pitch search around decoded pitch */ /********************************************************************/ pptmin = sub(pp, DPPQNS); pptmax = add(pp, DPPQNS); if (pptmin<MINPP) { pptmin = MINPP; pptmax = add(pptmin, 2*DPPQNS); } else if (pptmax>MAXPP) { pptmax = MAXPP; pptmin = sub(pptmax, 2*DPPQNS); } fp1 = &s[XQOFF-pptmax]; len = add(FRSZ, pptmax); a0 = 0; for (n=0;n<len;n++) { t1 = shr(*fp1++, 3); a0 = L_mac0(a0,t1,t1); } shift = norm_l(a0); if (a0==0) shift=31; shift = sub(6, shift); if (shift > 0) { ps = buf+pptmax; fp1 = &s[XQOFF-pptmax]; shift = shr(add(shift, 1), 1); for (n=0;n<len;n++) { buf[n] = shr(fp1[n], shift); } } else shift=0; R0 = 0; R1 = 0; R01 = 0; for(n=0; n<FRSZ; n++) { R0 = L_mac0(R0, ps[n], ps[n]); R1 = L_mac0(R1, ps[n-pptmin], ps[n-pptmin]); R01 = L_mac0(R01,ps[n], ps[n-pptmin]); } R0_exp = norm_l(R0); R0norm = extract_h(L_shl(R0, R0_exp)); R0_exp = R0_exp-16; ppnew = pptmin; R1max_exp = norm_l(R1); R1max = extract_h(L_shl(R1, R1max_exp)); R01Sqmax_exp = norm_l(R01); t1 = extract_h(L_shl(R01, R01Sqmax_exp)); R01Sqmax_exp = shl(R01Sqmax_exp, 1); R01Sqmax = extract_h(L_mult(t1, t1)); R01max = R01; for(ppt=pptmin+1; ppt<=pptmax; ppt++) { R1 = L_msu0(R1,ps[FRSZ-ppt], ps[FRSZ-ppt]); R1 = L_mac0(R1,ps[-ppt], ps[-ppt]); R01= 0; for(n=0; n<FRSZ; n++) { R01 = L_mac0(R01, ps[n], ps[n-ppt]); } R01Sq_exp = norm_l(R01); t1 = extract_h(L_shl(R01, R01Sq_exp)); R01Sq_exp = shl(R01Sq_exp, 1); R01Sq = extract_h(L_mult(t1, t1)); R1_exp = norm_l(R1); R1n = extract_h(L_shl(R1, R1_exp)); a0 = L_mult(R01Sq, R1max); a1 = L_mult(R01Sqmax, R1n); t1 = add(R01Sq_exp, R1max_exp); t2 = add(R01Sqmax_exp, R1_exp); t2 = sub(t1, t2); if (t2>=0) a0 = L_shr(a0, t2); if (t2<0) a1 = L_shl(a1, t2); if (L_sub(a0, a1)>0) { R01Sqmax = R01Sq; R01Sqmax_exp = R01Sq_exp; R1max = R1n; R1max_exp = R1_exp; ppnew = ppt; R01max = R01; } } /******************************************************************/ /* calculate all-zero pitch postfilter */ /******************************************************************/ if (R1max==0 || R0==0 || R01max <= 0) { aa = 0; } else { a0 = R1max_exp-16; t1 = mult(R1max, R0norm); a0 = a0+R0_exp-15; sqrt_i(t1, (Word16)a0, &t1, &t2); t0 = norm_l(R01max); t3 = extract_h(L_shl(R01max, t0)); t0 = t0-16; aa = mult(t3, t1); t0 = t0+t2-15; t0 = t0-15; if (t0<0) aa = shl(aa, sub(0,t0)); else aa = shr(aa, t0); } a0 = L_mult(8192, aa); a0 = L_mac(a0, 24576, *ma_a); *ma_a = intround(a0); if((*ma_a < ATHLD1) && (aa < (ATHLD2))) aa = 0; bb[1] = mult(ScLTPF, aa); /******************************************************************/ /* calculate normalization energies */ /******************************************************************/ Rx = 0; R0 = 0; for(n=0; n<FRSZ; n++) { a0 = L_shl(s[XQOFF+n], 15); a0 = L_add(a0, L_mult0(bb[1], s[XQOFF+n-ppnew])); e[n] = intround(a0); t1 = shr(e[n], shift); t2 = shr(s[XQOFF+n], shift); Rx = L_mac0(Rx, t1, t1); R0 = L_mac0(R0, t2, t2); } R0 = L_shr(R0, 2); if(R0 == 0 || Rx == 0) gainn = 32767; else { Rx_exp = norm_l(Rx); t1 = extract_h(L_shl(Rx, Rx_exp)); t2 = extract_h(L_shl(R0, Rx_exp)); if (t2>= t1) gainn = 32767; else { t1 = div_s(t2, t1); gainn = sqrts(t1); } } /******************************************************************/ /* interpolate from the previous postfilter to the current */ /******************************************************************/ bb[0] = gainn; bb[1] = mult(gainn, bb[1]); step = (Word32)((1.0/(NINT+1))*(2147483648.0)); delta = 0; for(n=0; n<NINT; n++) { delta = L_add(delta, step); ww1 = intround(delta); ww2 = add(sub(32767, ww1), 1); /* interpolate between two filters */ bi0 = intround(L_mac(L_mult(ww1, bb[0]), ww2, b_prv[0])); bi1c= mult(ww1, bb[1]); bi1p= mult(ww2, b_prv[1]); e[n] = intround(L_mac(L_mac(L_mult(bi1c, s[XQOFF+n-ppnew]), bi1p, s[XQOFF+n-(*pp_prv)]), bi0, s[XQOFF+n])); } for(n=NINT; n<FRSZ; n++) { e[n] = intround(L_shl(L_mult(gainn, e[n]),1)); } /******************************************************************/ /* save state memory */ /******************************************************************/ *pp_prv = ppnew; b_prv[0] = bb[0]; b_prv[1] = bb[1]; return; }
void vector_quantize_mlts(Word16 number_of_available_bits, Word16 number_of_regions, Word16 num_categorization_control_possibilities, Word16 *mlt_coefs, Word16 *absolute_region_power_index, Word16 *power_categories, Word16 *category_balances, Word16 *p_categorization_control, Word16 *region_mlt_bit_counts, UWord32 *region_mlt_bits) { Word16 *raw_mlt_ptr; Word16 region; Word16 category; Word16 total_mlt_bits = 0; Word16 temp; Word16 temp1; Word16 temp2; /* Start in the middle of the categorization control range. */ temp = shr_nocheck(num_categorization_control_possibilities,1); temp = sub(temp,1); for (*p_categorization_control = 0; *p_categorization_control < temp; (*p_categorization_control)++) { region = category_balances[*p_categorization_control]; move16(); power_categories[region] = add(power_categories[region],1); move16(); } for (region=0; region<number_of_regions; region++) { category = power_categories[region]; move16(); temp = extract_l(L_mult0(region,REGION_SIZE)); raw_mlt_ptr = &mlt_coefs[temp]; move16(); temp = sub(category,(NUM_CATEGORIES-1)); test(); if (temp < 0) { region_mlt_bit_counts[region] = vector_huffman(category, absolute_region_power_index[region],raw_mlt_ptr, ®ion_mlt_bits[shl_nocheck(region,2)]); } else { region_mlt_bit_counts[region] = 0; move16(); } total_mlt_bits = add(total_mlt_bits,region_mlt_bit_counts[region]); } /* If too few bits... */ temp = sub(total_mlt_bits,number_of_available_bits); test(); test(); logic16(); while ((temp < 0) && (*p_categorization_control > 0)) { test(); test(); logic16(); (*p_categorization_control)--; region = category_balances[*p_categorization_control]; move16(); power_categories[region] = sub(power_categories[region],1); move16(); total_mlt_bits = sub(total_mlt_bits,region_mlt_bit_counts[region]); category = power_categories[region]; move16(); raw_mlt_ptr = &mlt_coefs[region*REGION_SIZE]; move16(); temp = sub(category,(NUM_CATEGORIES-1)); test(); if (temp < 0) { region_mlt_bit_counts[region] = vector_huffman(category, absolute_region_power_index[region],raw_mlt_ptr, ®ion_mlt_bits[shl_nocheck(region,2)]); } else { region_mlt_bit_counts[region] = 0; move16(); } total_mlt_bits = add(total_mlt_bits,region_mlt_bit_counts[region]); temp = sub(total_mlt_bits,number_of_available_bits); } /* If too many bits... */ /* Set up for while loop test */ temp1 = sub(total_mlt_bits,number_of_available_bits); temp2 = sub(*p_categorization_control,sub(num_categorization_control_possibilities,1)); test(); test(); logic16(); while ((temp1 > 0) && (temp2 < 0)) { /* operations for while contitions */ test(); test(); logic16(); region = category_balances[*p_categorization_control]; move16(); power_categories[region] = add(power_categories[region],1); move16(); total_mlt_bits = sub(total_mlt_bits,region_mlt_bit_counts[region]); category = power_categories[region]; move16(); temp = extract_l(L_mult0(region,REGION_SIZE)); raw_mlt_ptr = &mlt_coefs[temp]; move16(); temp = sub(category,(NUM_CATEGORIES-1)); test(); if (temp < 0) { region_mlt_bit_counts[region] = vector_huffman(category, absolute_region_power_index[region],raw_mlt_ptr, ®ion_mlt_bits[shl_nocheck(region,2)]); } else { region_mlt_bit_counts[region] = 0; move16(); } total_mlt_bits = add(total_mlt_bits,region_mlt_bit_counts[region]); (*p_categorization_control)++; temp1 = sub(total_mlt_bits,number_of_available_bits); temp2 = sub(*p_categorization_control,sub(num_categorization_control_possibilities,1)); } }
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; }
Word16 refinepitch( Word16 *x, /* (i) Q1 */ Word16 cpp, Word16 *ppt) /* (o) Q9 */ { Word32 a0, a1; Word32 cor, energy, cormax, enermax32; /* Q3 */ Word16 energymax, energymax_exp, ener, ener_exp; Word16 cor2, cor2_exp, cor2max, cor2max_exp; Word16 *sp0, *sp1, *sp2, *sp3; Word16 *xt; Word16 s, t; Word16 lb, ub; int pp, i, j; if (cpp >= MAXPP) cpp = MAXPP-1; if (cpp < MINPP) cpp = MINPP; lb = sub((Word16)cpp,DEV); if (lb < MINPP) lb = MINPP; /* lower bound of pitch period search range */ ub = add((Word16)cpp,DEV); /* to avoid selecting HMAXPP as the refined pitch period */ if (ub >= MAXPP) ub = MAXPP-1;/* lower bound of pitch period search range */ i = lb; /* start the search from lower bound */ xt = x+XOFF; sp0 = xt; sp1 = xt-i; cor = energy = 0; for (j=0;j<FRSZ; j++) { s = *sp1++; t = *sp0++; energy = L_mac0(energy, s, s); cor = L_mac0(cor, s, t); } pp = i; cormax = cor; enermax32 = energy; energymax_exp = norm_l(enermax32); energymax = extract_h(L_shl(enermax32, energymax_exp)); a0 = cor; cor2max_exp = norm_l(a0); s = extract_h(L_shl(a0, cor2max_exp)); cor2max_exp = shl(cor2max_exp, 1); cor2max = extract_h(L_mult0(s, s)); sp0 = xt+FRSZ-lb-1; sp1 = xt-lb-1; for (i=lb+1;i<=ub;i++) { sp2 = xt; sp3 = xt-i; cor = 0; for (j=0;j<FRSZ;j++) cor = L_mac0(cor, *sp2++, *sp3++); a0 = cor; cor2_exp = norm_l(a0); s = extract_h(L_shl(a0, cor2_exp)); cor2_exp = shl(cor2_exp, 1); cor2 = extract_h(L_mult0(s, s)); s = *sp0--; t = *sp1--; energy = L_msu0(energy, s, s); energy = L_mac0(energy, t, t); a0 = energy; ener_exp = norm_l(a0); ener = extract_h(L_shl(a0, ener_exp)); if (ener>0) { a0 = L_mult0(cor2, energymax); a1 = L_mult0(cor2max, ener); s = add(cor2_exp, energymax_exp); t = add(cor2max_exp, ener_exp); if (s>=t) a0 = L_shr(a0, sub(s,t)); else a1 = L_shr(a1, sub(t,s)); if (a0 > a1) { pp = i; cormax = cor; enermax32 = energy; cor2max = cor2; cor2max_exp = cor2_exp; energymax = ener; energymax_exp = ener_exp; } } } if ((enermax32 == 0) || (cormax<=0)) *ppt = 0; else { ub = sub(norm_l(cormax),1); lb = norm_l(enermax32); s = extract_h(L_shl(cormax,ub)); t = extract_h(L_shl(enermax32,lb)); s = div_s(s, t); lb = sub(sub(lb,ub),6); *ppt = shl(s, lb); } return pp; }