📄 adapters.c
字号:
/*************************************************************************//* *//* LD-CELP G.728 *//* *//* Low-Delay Code Excitation Linear Prediction speech compression. *//* *//* Code edited by Michael Concannon. *//* Based on code written by Alex Zatsman, Analog Devices 1993 *//* *//*************************************************************************/#include "common.h"#include "fast.h"#include "parm.h"#include "data.h"#include "prototyp.h"static int sf_levdur (real[], real[]);static int levdur (real[], real[], int);static void hybwin(int lpsize, int framesize, int nrsize, real old_input[], real new_input[], real output[], real window[], real rec[], real decay);static void bw_expand2(real input[], real z_out[], real p_out[], int order, real z_vec[], real p_vec[]);static void bw_expand1(real input[], real p_out[], int order, real p_vec[]);/********************************** Adapter for Perceptual Weighting Filter */static real pwf_z_vec[LPCW+1], /* Arrays for band widening: zeros and*/ pwf_p_vec[LPCW+1], /* poles */ pwf_old_input[LPCW+NFRSZ+NONRW], pwf_rec[LPCW+1]; /* Recursive Part */ voidpwf_adapter (real input[], real z_out[], /* zero coefficients */ real p_out[]) /* pole coefficients */{ static real acorr[LPCW+1], /* autocorrelation coefficients */ lpcoeff[LPCW+1]; static real LPC_MEM temp[LPCW+1]; hybwin(LPCW, /* lpsize */ NFRSZ, /* framesize */ NONRW, /* nrsize -- nonrecursive size */ pwf_old_input, input, acorr, hw_percw, pwf_rec, 0.5); if (levdur(acorr, temp, LPCW)) { RCOPY(temp, lpcoeff, LPCW+1); bw_expand2 (lpcoeff, z_out, p_out, LPCW, pwf_z_vec, pwf_p_vec); }}voidinit_pwf_adapter (real z_co[], real p_co[]){ real zv = 1.0, pv = 1.0; int i; for (i=0; i<=LPCW; i++) { pwf_z_vec[i] = zv; pwf_p_vec[i] = pv; zv *= WZCF; pv *= WPCF; z_co[i] = 0.0; p_co[i] = 0.0; } p_co[0] = 1.0; z_co[0] = 1.0; ZARR(pwf_old_input); ZARR(pwf_rec);}/*************************************** Backward Synthesis Filter Adapter */static real facv[LPC+1];static real bsf_old_input[LPC+NFRSZ+NONR], bsf_rec[LPC+1]; voidbsf_adapter (real input[], real p_out[]){ static real old_input[LPC + NFRSZ + NONR], acorr[LPC+1], /* autocorrelation coefficients */ lpcoeff[LPC+1]; static real temp[LPC+1]; hybwin(LPC, /* lpsize */ NFRSZ, /* framesize */ NONR, /* nrsize -- nonrecursive size */ old_input, input, acorr, hw_synth, bsf_rec, 0.75); if (sf_levdur(acorr, temp)) { k10 = -acorr[1]/acorr[0]; RCOPY(temp, lpcoeff, LPC+1); bw_expand1(lpcoeff, p_out, LPC, facv); }}/******************************************************* Gain Adapter **/static real gain_p_vec[LPCLG+1]= /* Array for band widening */{1.0, 0.90625, 0.8212890625, 0.74432373046875, 0.67449951171875, 0.61126708984375, 0.553955078125, 0.50201416015625, 0.4549560546875, 0.41229248046875, 0.3736572265625};static real g_rec[LPCLG+1]; /* Recursive part for Hybrid Window */static real g_old_input[LPCLG + NUPDATE + NONRLG];/*** recompute lpc_coeff **/void gain_adapter (real log_gain[], real coeff[]){ static real acorr[LPCLG+1], /* autocorrelation coefficients */ lpcoeff[LPCLG+1]; static real temp[LPCLG+1]; hybwin(LPCLG, /* lpsize */ NUPDATE, /* framesize */ NONRLG, /* nrsize -- nonrecursive size */ g_old_input, log_gain, acorr, hw_gain, g_rec, 0.75); if (levdur(acorr, temp, LPCLG)) { int i; for(i=1; i<=LPCLG; i++) lpcoeff[i] = temp[i]; bw_expand1 (lpcoeff, coeff, LPCLG, gain_p_vec); }}/******************************************** Initializations **/voidinit_bsf_adapter(real co[]){ int i; real v = 1.0; for(i=0; i<=LPC; i++) { facv[i] = v; v *= FAC; co[i] = 0; } co[0] = 1.0; ZARR(bsf_old_input); ZARR(bsf_rec); }void init_gain_adapter (real coeff[]){ int i; gain_p_vec[0] = 1.0; coeff[0] = 1.0; coeff[1] = -1.0; for(i=0; i<LPCLG+NUPDATE+NONRLG; i++) g_old_input[i] = -GOFF; ZARR(g_rec); ZARR(g_old_input);}/******************************************** Hybrid Window Module **//* Hybrid Window LPSIZE - size of OUTPUT (autocorrelation vector) FRAMESIZE - size of NEW_INPUT NRSIZE - size of non-recursive part. OLD_INPUT - buffer for holding old input (size LPSIZE+FRAMESIZE+NRSIZE) NEW_INPUT - new input, or frame (size FRAMESIZE) OUTPUT - autocorrelation vector (size LPSIZE) WINDOW - window coefficients (size LPSIZE+FRAMESIZE+NRSIZE) REC - - recursive part (size LPSIZE) DECAY - - scaling for the old recursive part. */static voidhybwin(int lpsize, int framesize, int nrsize, real old_input[], real new_input[], real output[],real WIN_MEM window[], real rec[], /* Recursive Part */ real decay){ static void autocorr(); int N1 = lpsize + framesize; /* M+L */ int N2 = lpsize + nrsize; /* M+N */ int N3 = lpsize + framesize + nrsize; int i; real ws[N3]; real tmp1[lpsize+1], tmp2[lpsize+1]; /* shift in INPUT into OLD_INPUT and window it*/ for(i=0; i<N2; i++) old_input[i] = old_input[i+framesize]; for(i=0; i<framesize; i++) old_input[N2+i] = new_input[i]; VPROD(old_input,window,ws,N3); autocorr(ws, tmp1, lpsize, lpsize, N1); for(i=0; i<=lpsize; i++) rec[i] = decay * rec[i] + tmp1[i]; autocorr(ws, tmp2, lpsize, N1, N3); for(i=0; i<=lpsize; i++) output[i] = rec[i] + tmp2[i]; output[0] *= WNCF;}/********************************************* Levinson-Durbin Routines *//* Levinson-Durbin algorithm *//* return 1 if ok, otherwise 0 */static int levdur(real acorr[], real coeff[], int order){ /* Local variables */ static int minc, minc2; static float s; static int ib, mh; static float at; static int ip; static float rc[20]; static float alpha; static float tmp; /* Parameter adjustments */ --acorr; --coeff;/* .......CHECK FOR ZERO SIGNAL OR ILLEGAL ZERO-LAG AUTOCORRELATION */ if ((acorr[1] <= (float)0.)||(acorr[order+1] == 0)) return 0;/* .......START DURBIN's RECURSION */ rc[1] = -acorr[2] / acorr[1]; coeff[1] = (float)1.; coeff[2] = rc[1]; alpha = acorr[1] + acorr[2] * rc[1]; if (alpha <= (float)0.) return 0; for (minc = 2; minc <= order; ++minc) { minc2 = minc + 2; s = acorr[minc + 1]; for (ip = 2; ip <= minc; ++ip) { s += acorr[minc2 - ip] * coeff[ip]; } rc[minc] = -s / alpha; mh = minc / 2 + 1; for (ip = 2; ip <= mh; ++ip) { ib = minc2 - ip; at = rc[minc] * coeff[ib]; at += coeff[ip]; tmp = rc[minc] * coeff[ip]; coeff[ib] += tmp; coeff[ip] = at; } coeff[minc + 1] = rc[minc]; alpha += rc[minc] * s;/* ...........IF RESIDUAL ENERGY LESS THAN ZERO (DUE TO ILL-CONDITIONING), *//* ...........RETURN WITHOUT UPDATING FILTER COEFFICIENTS (USE OLD ONES). */ if (alpha <= (float)0.) return 0; } return 1;}/* Levinson-Durbin algorithm for Synthesis Filter. Its main difference from the above is the fact that it saves 10-th order coefficients for Postfilter, plus some speedup since this is one of the longest routines in the algorithm. */ real a10[11];real k10;static int sf_levdur(real acorr[], real coeff[]){ real E; register real K REG(r9), c1 REG(r0), tmp REG(r12); int m, j, halfm; if (acorr[LPC] == 0) return 0; E = acorr[0]; if (E<=0) return 0; coeff[0] = 1.0; for(m=1; m<=LPC; m++) { K = -acorr[m]; if (m>1) { real a1 REG(r4)=acorr[m-1]; c1=coeff[1]; tmp = c1*a1; if (m>2) { c1 = coeff[2]; a1 = acorr[m-2]; for(j=3; j<=m-1; j++) { K -= tmp; tmp = c1 * a1; c1 = coeff[j]; a1 = acorr[m-j]; } K -= tmp; tmp = c1*a1; } K -= tmp; } K = K/E; coeff[m] = K; halfm = m>>1; /** this is pipilened version of parallel assignment: **/ /* coeff[j] = coeff[j] + K * coeff[m-j] */ /* coeff[m-j] = K * coeff[j] + coeff[m-j] */ { if (halfm>=1) { register real x REG(r1), y REG(r5), t1 REG(r10), t2 REG(r14), t3 REG(r2), t4 REG(r6); register real *p REG(i10); register real *pp REG(i11); register real *q REG(i12); register real *qq REG(i13); p = coeff+1; pp = p; q = coeff+m-1; qq = q; x=*p++; y=*q--; t1 = K * x; t2 = K * y; for(j=2; j<=halfm; j++) { t4 = t2 + x; x=*p++; t3 = t1 + y; y=*q--; t1 = K * x; *pp++ = t4; t2 = K * y; *qq-- = t3; } t3 = t1 + y; t4 = t2 + x; *pp = t4; *qq = t3; } } if (m==10) { int jj; for(jj=0; jj<=10; jj++) a10[jj] = coeff[jj]; } E = (1 - K * K) * E; if (E<0) return 0; } return 1;}/******************************************** Band Width Expanders **//* Don't have to worry about i=0 -- z_vec[0] and p_vec[0] should stay 1.0. */static voidbw_expand2(real input[], real z_out[], real p_out[], int order, real z_vec[], real p_vec[]){ int i; for(i=1; i<=order; i++) z_out[i] = z_vec[i] * input[i]; for(i=1; i<=order; i++) p_out[i] = p_vec[i]*input[i];}/* Poles only */static voidbw_expand1(real input[], real p_out[], int order, real p_vec[]){ int i; for(i=1; i<=order; i++) p_out[i] = p_vec[i]*input[i];}static voidautocorr(real X[], real R[], int K, int M, int N){ int ii,jj; float tmp; for(ii=0; ii<=K; ii++) { R[ii] = 0; for(jj=M; jj<N; jj++) { tmp = X[jj] * X[jj-ii]; R[ii] += tmp; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -