00001 /**********************************************************/ 00002 /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ 00003 /* 00004 Copyright: 1994 - Grupo de Voz (DAET) ETSII/IT-Bilbao 00005 00006 Nombre fuente................ SPL5c.C 00007 Nombre paquete............... SPL 00008 Lenguaje fuente.............. C (Borland C/C++ 3.1) 00009 Estado....................... Completado 00010 Dependencia Hard/OS.......... - 00011 Codigo condicional........... NDEBUG, LP_NEGSUM 00012 00013 Codificacion................. Borja Etxebarria 00014 00015 Version dd/mm/aa Autor Proposito de la edicion 00016 ------- -------- -------- ----------------------- 00017 1.1.1 30/07/95 Borja scope funciones explicito 00018 1.1.0 08/12/94 Borja revision general (tipos,idx,nel,tnel...) 00019 1.0.2 07/12/93 Borja soporte LP_NEGSUM_NEG() y LP_POSSUM_NEG() 00020 1.0.1 05/12/93 Borja funciones para LSFs. 00021 1.0.0 16/09/93 Borja Codificacion inicial. 00022 00023 ======================== Contenido ======================== 00024 Algoritmos de prediccion lineal (LP). Ver SPL5A.C para mas detalles. 00025 00026 Definir NDEBUG para desconectar la validacion de parametros 00027 con assert(). No definir este simbolo mientras se depuren 00028 aplicaciones, ya que aunque las funciones son algo mas lentas, 00029 el chequeo de validacion de parametros resuelve muchos problemas. 00030 =========================================================== 00031 */ 00032 /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ 00033 /**********************************************************/ 00034 00035 #include "spli.h" 00036 00037 /**********************************************************/ 00038 /* a partir de los coeficientes lpc de orden {p} enviados en el vector 00039 {vai} ({p} coeficientes, desde a(1) hasta a(p)) calcula los 00040 polinomios singulares simetrico y antisimetrico (p(x) y q(x)) 00041 en los que se ha hecho un cambio de variable z por x (Furui). 00042 Los vectores resultado se devuelven en {vpi} y {vqi} respectivamente. 00043 El vector {vtmp} es un vector temporal de tnel_lp_a2pq(p) elementos. 00044 Solo se ha implementado el proceso para orden {p} par (si alguien 00045 tiene ganas...). Para orden {p} impar simplemente se calculan 00046 los polinomios para el siguiente orden (par) {p}+1, asumiendo 00047 que el coeficiente a(p+1)=0. 00048 Los polinomios p(x) y q(x) son de orden {p}/2, y por tanto cada uno 00049 de los vectores {vpi} y {vqi} debe tene (({p}/2)+1) elementos, 00050 pero si el orden {p} es impar, como se calculan los polinomios del 00051 siguiente orden, estos vectores seran de ({p}/2+2) elementos. 00052 En cualquier caso, tanto para {p} par como impar, se cumple que 00053 estos vectores son de ({p}+3)/2 elementos (operacion con enteros). 00054 00055 Los ceros xi de estos polomios p(xi)=0 y q(xi)=0 dan directamente 00056 las frecuencias espectrales de linea wi mediante el calculo 00057 00058 . xi=cos(wi) -----> wi=(+-)acos(xi) (radianes) 00059 00060 Los polinomios se devuelve empezando por el termino independiente: 00061 00062 . p(x) = vpi[0] + vpi[1]*x + vpi[2]*(x**2) +...+ vpi[p/2]*(x**(p/2)) 00063 . q(x) = vqi[0] + vqi[1]*x + vqi[2]*(x**2) +...+ vqi[p/2]*(x**(p/2)) 00064 00065 siempre con {p} par (si es impar, se usa {p}={p}+1). 00066 Los ceros xi de p(x) y q(x) cumplen -1<xi<1 y ademas los ceros 00067 de p(x) estan entrelazados con los de q(x) (Furui). 00068 00069 Enviar siempre p>=1. */ 00070 00071 PUBLIC SPL_VOID XAPI lp_a2pq( SPL_pFLOAT vai, SPL_INT p, SPL_pFLOAT vpi, 00072 SPL_pFLOAT vqi, SPL_pFLOAT vtmp ) 00073 { 00074 SPL_INT i,j,k, p2; 00075 #define pp vtmp 00076 SPL_pFLOAT qq,nc,oc,t; 00077 assert(p>0); 00078 00079 p2=(p+1)/2; /* +1 para tener en cuenta si p es impar */ 00080 /*pp=vtmp, en el define*/ 00081 qq=pp+p2; 00082 nc=qq+p2; 00083 oc=nc+(p2/2)+1; 00084 00085 if (p&1) { /* si p es impar */ 00086 p++; 00087 pp[0]=LP_NEGSUM_NEG(vai[0])-1.0; 00088 qq[0]=LP_NEGSUM_NEG(vai[0])+1.0; 00089 } 00090 else { 00091 pp[0]=LP_NEGSUM_NEG(vai[0]+vai[p-1])-1.0; 00092 qq[0]=LP_NEGSUM_NEG(vai[0]-vai[p-1])+1.0; 00093 } 00094 for (i=1; i<p2; i++) { 00095 pp[i]= (-pp[i-1])+LP_NEGSUM_NEG(vai[i]+vai[p-1-i]); 00096 qq[i]= (qq[i-1])+LP_NEGSUM_NEG(vai[i]-vai[p-1-i]); 00097 } 00098 00099 for (i=1; i<=p2; i++) 00100 vpi[i]=vqi[i]=0.0; 00101 vpi[0]=pp[p2-1]/2.0; 00102 vqi[0]=qq[p2-1]/2.0; 00103 00104 /*ciclo de cosenos, para desarrollar todos los cos(x**n) en cos(x) */ 00105 oc[0]=nc[0]=1.0; 00106 for (i=1; i<p2; ) { 00107 k=0; 00108 for (j=i; j>=0; j-=2) { 00109 vpi[j]+=nc[k]*pp[p2-1-i]; 00110 vqi[j]+=nc[k]*qq[p2-1-i]; 00111 k++; 00112 } 00113 00114 __swap(nc,oc,t); 00115 j=(++i)/2; 00116 if (!(i&1)) { 00117 nc[j]=-nc[j-1]; 00118 j--; 00119 } 00120 for ( ; j>=1; j--) 00121 nc[j]=oc[j]*2-nc[j-1]; 00122 nc[0]=oc[0]*2.0; 00123 } 00124 k=0; 00125 for (j=p2; j>=0; j-=2) { 00126 vpi[j]+=nc[k]; 00127 vqi[j]+=nc[k]; 00128 k++; 00129 } 00130 #undef pp 00131 } 00132 00133 /**********************************************************/ 00134 00135 PUBLIC SPL_INT XAPI tnel_lp_a2pq( SPL_INT p ) 00136 { 00137 assert(p>0); 00138 00139 if (p&1) /* si el orden es impar */ 00140 p++; 00141 return p+p/2+2; 00142 } 00143 00144 /**********************************************************/ 00145 /* Metodo Split-Levinson simetrico para las correlaciones. Fast! 00146 El mas rapido para el metodo de las correlaciones. 00147 A partir de las {p}+1 primeras autocorrelaciones {vac} la 00148 funcion devuelve unos coeficientes (alfa-sub-i) {vxs} ({p} coeficientes) 00149 que definen el polinomio predictor singular. La funcion, {devuelve} 00150 la potencia del error de prediccion para analisis de orden {p}. La 00151 funcion lpa_cor_sls_b_ne() hace lo mismo que esta pero no devuelve 00152 el error. 00153 00154 En la referencia The Split Levinson Algorithm (PUBLIC. Delsarte, Y. V. Genin) 00155 se definen estos coeficientes, y como derivar otros coeficientes beta 00156 a partir de ellos, con los cuales se forma un determinante (Jacobiano) 00157 del que se extraen los LSFs (autovalores...) */ 00158 00159 PUBLIC SPL_FLOAT XAPI lpa_cor_sls_xa( SPL_pFLOAT vac, SPL_pFLOAT vxs, 00160 SPL_INT p, SPL_pFLOAT vtmp ) 00161 { 00162 SPL_INT i,k,t; 00163 #define po vtmp 00164 SPL_pFLOAT pa, pn, px; /* tres vectores, old,actual,new, y uno auxiliar */ 00165 SPL_FLOAT sum,tk,ak,lk; 00166 assert(p>0); 00167 00168 t = (p+1)/2; 00169 /* po=vtmp en el define */ 00170 pa=po+t; 00171 pn=pa+t; 00172 00173 pa[0]=2.0-2.0*(vxs[0]=(tk=vac[0]+vac[1])/vac[0]); 00174 t=0; 00175 00176 for (k=1; k<p; k++) { 00177 __xsum(i,0,t,(vac[i+1]+vac[k-i])*pa[i],sum,vac[0]+vac[k+1]); 00178 if (k&1) { 00179 sum+=vac[t+1]*pa[t]; 00180 vxs[k]=ak=sum/tk; 00181 tk=sum; 00182 pn[0]=pa[0]+1.0-ak; 00183 for (i=1; i<=t; i++) 00184 pn[i]=pa[i]+pa[i-1]-ak*po[i-1]; 00185 t++; 00186 } 00187 else { 00188 vxs[k]=ak=sum/tk; 00189 tk=sum; 00190 pn[0]=pa[0]+1.0-ak; 00191 for (i=1; i<t; i++) 00192 pn[i]=pa[i]+pa[i-1]-ak*po[i-1]; 00193 pn[t]=pa[t-1]+pa[t-1]-ak*po[t-1]; 00194 } 00195 px=po; 00196 po=pa; 00197 pa=pn; 00198 pn=px; 00199 } 00200 00201 lk=sum=1.0; 00202 if (p&1) { /* impar */ 00203 for (i=0; i<t; i++) { 00204 sum+=po[i]; 00205 lk+=pa[i]; 00206 } 00207 lk=(lk+lk+pa[i])/(sum+sum); 00208 } 00209 else { 00210 for (i=0; i<t-1; i++) { 00211 sum+=po[i]; 00212 lk+=pa[i]; 00213 } 00214 lk=(2.0*(lk+pa[i]))/(sum+sum+po[i]); 00215 } 00216 return lk*tk; 00217 #undef po 00218 } 00219 00220 /**********************************************************/ 00221 /* Metodo Split-Levinson simetrico para las correlaciones. Fast! 00222 El mas rapido para el metodo de las correlaciones. 00223 A partir de las {p}+1 primeras autocorrelaciones {vac} la 00224 funcion devuelve unos coeficientes (alfa-sub-i) {vxs} ({p} coeficientes) 00225 que definen el polinomio predictor singular. La funcion NO {devuelve} 00226 la potencia del error de prediccion, para ahorrar operaciones. La funcion 00227 lpa_cor_sls_xa() hace lo mismo que esta pero devuelve el error. 00228 00229 En la referencia The Split Levinson Algorithm (PUBLIC. Delsarte, Y. V. Genin) 00230 se definen estos coeficientes, y como derivar otros coeficientes beta 00231 a partir de ellos, con los cuales se forma un determinante (Jacobiano) 00232 del que se extraen los LSFs (autovalores...) */ 00233 00234 PUBLIC SPL_VOID XAPI lpa_cor_sls_xa_ne( SPL_pFLOAT vac, SPL_pFLOAT vxs, 00235 SPL_INT p, SPL_pFLOAT vtmp ) 00236 { 00237 SPL_INT i,k,t; 00238 #define po vtmp 00239 SPL_pFLOAT pa, pn, px; /* tres vectores, old,actual,new, y uno auxiliar */ 00240 SPL_FLOAT sum,tk,ak; 00241 assert(p>0); 00242 00243 t = (p+1)/2; 00244 /* po=vtmp en el define */ 00245 pa=po+t; 00246 pn=pa+t; 00247 00248 pa[0]=2.0-2.0*(vxs[0]=(tk=vac[0]+vac[1])/vac[0]); 00249 t=0; 00250 00251 for (k=1; k<p; k++) { 00252 __xsum(i,0,t,(vac[i+1]+vac[k-i])*pa[i],sum,vac[0]+vac[k+1]); 00253 if (k&1) { 00254 sum+=vac[t+1]*pa[t]; 00255 vxs[k]=ak=sum/tk; 00256 tk=sum; 00257 pn[0]=pa[0]+1.0-ak; 00258 for (i=1; i<=t; i++) 00259 pn[i]=pa[i]+pa[i-1]-ak*po[i-1]; 00260 t++; 00261 } 00262 else { 00263 vxs[k]=ak=sum/tk; 00264 tk=sum; 00265 pn[0]=pa[0]+1.0-ak; 00266 for (i=1; i<t; i++) 00267 pn[i]=pa[i]+pa[i-1]-ak*po[i-1]; 00268 pn[t]=pa[t-1]+pa[t-1]-ak*po[t-1]; 00269 } 00270 px=po; 00271 po=pa; 00272 pa=pn; 00273 pn=px; 00274 } 00275 00276 #undef po 00277 } 00278 00279 /**********************************************************/ 00280 /* Metodo Split-Levinson antisimetrico para las correlaciones. Fast! 00281 El tan rapido como el simetrico. 00282 A partir de las {p}+1 primeras autocorrelaciones {vac} la 00283 funcion devuelve unos coeficientes (alfa-sub-i) {vxa} ({p} coeficientes) 00284 que definen el polinomio predictor singular antisimetrico. La funcion, 00285 {devuelve} la potencia del error de prediccion para analisis de orden {p} 00286 (coincide con el valor que devuelve lpa_cor_sls_xa(). La funcion 00287 lpa_cor_sla_xa_ne() hace lo mismo que esta pero no devuelve el error. 00288 00289 En la referencia The Split Levinson Algorithm (PUBLIC. Delsarte, Y. V. Genin) 00290 se definen estos coeficientes, y como derivar otros coeficientes beta 00291 a partir de ellos, con los cuales se forma un determinante (Jacobiano) 00292 del que se extraen los LSFs (autovalores...) */ 00293 00294 PUBLIC SPL_FLOAT XAPI lpa_cor_sla_xa( SPL_pFLOAT vac, SPL_pFLOAT vxa, 00295 SPL_INT p, SPL_pFLOAT vtmp ) 00296 { 00297 SPL_INT i,k,t; 00298 #define po vtmp 00299 SPL_pFLOAT pa, pn, px; /* tres vectores, old,actual,new, y uno auxiliar */ 00300 SPL_FLOAT sum,tk,ak,lk; 00301 assert(p>0); 00302 00303 t = p/2; 00304 /* po=vtmp en el define */ 00305 pa=po+t; 00306 pn=pa+t; 00307 00308 lk=2.0-(vxa[0]=ak=(tk=vac[0]-vac[1])/vac[0]); 00309 pa[0]=0.0; 00310 t=0; 00311 00312 for (k=1; k<p; k++) { 00313 if (k&1) { 00314 __xsum(i,0,t,(vac[i+1]-vac[k-i])*pa[i],sum,vac[0]-vac[k+1]); 00315 vxa[k]=ak=sum/tk; 00316 tk=sum; 00317 pn[0]=pa[0]+1.0-ak; 00318 for (i=1; i<t; i++) 00319 pn[i]=pa[i]+pa[i-1]-ak*po[i-1]; 00320 if (t) 00321 pn[t]=pa[t-1]-ak*po[t-1]; 00322 } 00323 else { 00324 __sum(i,0,t,(vac[i+1]-vac[k-i])*pa[i],sum,vac[0]-vac[k+1]); 00325 vxa[k]=ak=sum/tk; 00326 tk=sum; 00327 pn[0]=pa[0]+1.0-ak; 00328 for (i=1; i<=t; i++) 00329 pn[i]=pa[i]+pa[i-1]-ak*po[i-1]; 00330 t++; 00331 } 00332 lk=2.0-ak/lk; 00333 00334 px=po; 00335 po=pa; 00336 pa=pn; 00337 pn=px; 00338 } 00339 00340 return lk*tk; 00341 #undef po 00342 } 00343 00344 /**********************************************************/ 00345 /* Metodo Split-Levinson antisimetrico para las correlaciones. Fast! 00346 El tan rapido como el simetrico. 00347 A partir de las {p}+1 primeras autocorrelaciones {vac} la 00348 funcion devuelve unos coeficientes (alfa-sub-i) {vxa} ({p} coeficientes) 00349 que definen el polinomio predictor singular antisimetrico. La 00350 funcion NO {devuelve} la potencia del error de prediccion, para 00351 ahorrar operaciones. La funcion lpa_cor_sla_xa() hace lo mismo que 00352 esta pero devuelve el error. 00353 00354 En la referencia The Split Levinson Algorithm (PUBLIC. Delsarte, Y. V. Genin) 00355 se definen estos coeficientes, y como derivar otros coeficientes beta 00356 a partir de ellos, con los cuales se forma un determinante (Jacobiano) 00357 del que se extraen los LSFs (autovalores...) */ 00358 00359 PUBLIC SPL_VOID XAPI lpa_cor_sla_xa_ne( SPL_pFLOAT vac, SPL_pFLOAT vxa, 00360 SPL_INT p, SPL_pFLOAT vtmp ) 00361 { 00362 SPL_INT i,k,t; 00363 #define po vtmp 00364 SPL_pFLOAT pa, pn, px; /* tres vectores, old,actual,new, y uno auxiliar */ 00365 SPL_FLOAT sum,tk,ak; 00366 assert(p>0); 00367 00368 t = p/2; 00369 /* po=vtmp en el define */ 00370 pa=po+t; 00371 pn=pa+t; 00372 00373 vxa[0]=ak=(tk=vac[0]-vac[1])/vac[0]; 00374 pa[0]=0.0; 00375 t=0; 00376 00377 for (k=1; k<p; k++) { 00378 if (k&1) { 00379 __xsum(i,0,t,(vac[i+1]-vac[k-i])*pa[i],sum,vac[0]-vac[k+1]); 00380 vxa[k]=ak=sum/tk; 00381 tk=sum; 00382 pn[0]=pa[0]+1.0-ak; 00383 for (i=1; i<t; i++) 00384 pn[i]=pa[i]+pa[i-1]-ak*po[i-1]; 00385 if (t) 00386 pn[t]=pa[t-1]-ak*po[t-1]; 00387 } 00388 else { 00389 __sum(i,0,t,(vac[i+1]-vac[k-i])*pa[i],sum,vac[0]-vac[k+1]); 00390 vxa[k]=ak=sum/tk; 00391 tk=sum; 00392 pn[0]=pa[0]+1.0-ak; 00393 for (i=1; i<=t; i++) 00394 pn[i]=pa[i]+pa[i-1]-ak*po[i-1]; 00395 t++; 00396 } 00397 px=po; 00398 po=pa; 00399 pa=pn; 00400 pn=px; 00401 } 00402 00403 #undef po 00404 } 00405 00406 /**********************************************************/ 00407 /* Calculo de los coeficientes espectrales de linea LSF o LSP 00408 (line spectrum pairs). 00409 Utiliza el metodo de las correlaciones (Split Levinson). 00410 A partir de las {p}+1 primeras autocorrelaciones {vac} la 00411 funcion devuelve los coeficientes LSFs en {vlx} ({p} coeficientes) 00412 que definen el polinomio predictor optimo de orden {p}. 00413 Si en {E} se envia un puntero a un SPL_FLOAT, se almacena en el el 00414 valor de la potencia del error de prediccion, pero si en {E} se 00415 envia NULL, la funcion no calcula este valor, reduciendo el 00416 numero de operaciones. {vtmp} es un vector temporal de trabajo que 00417 debe enviar el usuario, y debe tener sitio para tnel_lpa_cor_slv_lx(p) 00418 valores SPL_FLOAT. 00419 Puesto que la funcion debe calcular autovalores de un Jacobiano, 00420 puede suceder que se sobrepase el numero maximo de iteraciones 00421 permitidas (ver eigen_tdg()), en cuyo caso el resultado queda 00422 indefinido, y la funcion {devuelve} TRUE. En caso de que todo 00423 se desarrolle correctamente, la funcion {devuelve} FALSE. 00424 00425 Los valores de los LSF devueltos estan en el rango {1,-1}, y corresponden 00426 realmente con el valor del coseno de la frecuencia LSF correspondiente. 00427 Ver lp_lx2lw() y lp_lw2lx() para conversion entre frecuencias y cosenos. 00428 00429 Los LSF son los ceros de los polinomios singulares sim‚trico P(z) 00430 y antisimetrico Q(z). Para un analisis de orden {p}, P(z) tiene 00431 {p}+1 raices y Q(z) otras {p}+1, siempre por pares simetricos conjugados. 00432 En caso de que {p} sea par, la raiz que sobra es un valor trivial, siendo 00433 un cero en z=-1 para P(z) y uno en z=1 para Q(z). Si {p} es impar, entonces 00434 P(z) tiene ({p}+1)/2 pares conjugados (un total de {p}+1 raices, ninguna 00435 trivial) mientras que Q(z) tiene solo ({p}-1)/2 pares conjugados y dos 00436 raices triviales, una en z=-1 y otra en z=1. 00437 Ademas, las raices de P(z) y Q(z) van entrelazadas entre si, (y siempre 00438 estan en el circulo de radio unidad). Puesto que z=1 es siempre raiz 00439 singular de Q(z), siempre sucede que la primera raiz no singular 00440 pertenece a P(z), la siguiente a Q(z), etc. 00441 00442 Esta funcion, en lugar de devolver las raices como frecuencias w(i), 00443 devuelve las raices como x(i), con el cambio de variable x=cos(w). 00444 Ver lp_lx2lw() y lp_lw2lx() para conversion entre frecuencias y cosenos. 00445 La funcion no devuelve las raices singulares, ni las que estan en 00446 el semiplano inferior (conjugadas). Tan solo se devuelven las raices 00447 entre w=0 y w=Pi, y por eso los valores devueltos (x=cos(x)) varian entre 00448 1 para w=0 y -1 para w=Pi. Ademas las raices se devuelven ordenadas, y 00449 entrelazadas, es decir vlx[0] es la primera raiz (no singular) de P(x), 00450 vlx[1] la primera de Q(x), vlx[2] la segunda de P(x) y asi sucesivamente 00451 hasta {p} raices. 00452 Ademas, mientras se conserve este orden de entrelazado, y se cumpla 00453 w(i-1)<w(i)<w(i+1) se asegura la estabilidad del predictor. 00454 p>0. 00455 00456 Ref: 00457 . PUBLIC. Delsarte, Y. V. Genin 00458 . The Split Levinson Algorithm 00459 . IEEE trans. ASSP, vol 34, n. 3, Jun. 1986 00460 00461 . Furui 00462 . ???? 00463 00464 . K.K Paliwal, B.S. Atal 00465 . Efficient Vector Quantization of LPC Parameters at 24 Bits/Frame 00466 . IEEE. Trans. Speech, and Audio Processing, Vol 1, N.1 Jan 93 00467 00468 . F.K. Soong B.H. Juang 00469 . Optimal Quantization of LSP Parameters 00470 . IEEE. Trans. Speech, and Audio Processing, Vol 1, N.1 Jan 93 */ 00471 00472 PUBLIC SPL_BOOL XAPI lpa_cor_slv_lx( SPL_pFLOAT vac, SPL_pFLOAT vlx, 00473 SPL_INT p, SPL_FLOAT * E, SPL_pFLOAT vtmp ) 00474 { 00475 #define SORT_LSFS /* si se quita este define, las raices no se ordenan. 00476 Asi que no quitarlo!!. Tan solo esta por si algun 00477 dia hace falta una funcion mas rapida que no ordene*/ 00478 00479 SPL_INT i, j, n; 00480 #ifdef SORT_LSFS 00481 SPL_INT m; 00482 #endif 00483 00484 #define vx vtmp 00485 SPL_pFLOAT vd, ve; 00486 assert(p>0); 00487 00488 n = (p+1)/2; 00489 /*vx=vtmp en el define */ 00490 vd = vx+p; 00491 ve = vd+n; 00492 00493 if (E==NULL) /* no devolver ni calcular E */ 00494 lpa_cor_sls_xa_ne(vac,vx,p,vd); 00495 else 00496 (*E)=lpa_cor_sls_xa(vac,vx,p,vd); 00497 00498 vx[0]*=0.5; 00499 for (i=1; i<p; i++) 00500 vx[i] *= 0.25; 00501 if (p&1) { /* p+1 par */ 00502 vd[0]=vx[0]; 00503 j=0; 00504 } 00505 else { 00506 vd[0]=vx[0]+vx[1]; 00507 j=1; 00508 } 00509 for (i=1; i<n; i++) { 00510 ve[i-1]=sqrt(vx[j]*vx[j+1]); 00511 vd[i]=vx[j+1]+vx[j+2]; 00512 j+=2; 00513 } 00514 if (eigen_tdg(vd,ve,n,NULL)!=SPL_FALSE) /* calcula autovalores...*/ 00515 return SPL_TRUE; /* y fin en caso de error */ 00516 #ifdef SORT_LSFS 00517 for (i=0; i<n; i++) { 00518 for (j=m=0; j<n; j++) /* busca el mayor */ 00519 if (vd[j]>vd[m]) 00520 m=j; 00521 vlx[i*2]= 2.0*vd[m]-1.0; 00522 vd[m]=0.0; 00523 } 00524 #else 00525 for (i=0; i<n; i++) /* guardar sin ordenar */ 00526 vlx[i] = 2.0*vd[i]-1.0; 00527 #endif 00528 00529 lpa_cor_sla_xa_ne(vac,vx,p,vd); 00530 for (i=1; i<p; i++) 00531 vx[i] *= 0.25; 00532 if (p&1) { /* p impar */ 00533 vd[0]=vx[1]+vx[2]; 00534 j=2; 00535 } 00536 else { 00537 vd[0]=vx[1]; 00538 j=1; 00539 } 00540 p-=n; 00541 for (i=1; i<p; i++) { 00542 ve[i-1]=sqrt(vx[j]*vx[j+1]); 00543 vd[i]=vx[j+1]+vx[j+2]; 00544 j+=2; 00545 } 00546 if (eigen_tdg(vd,ve,p,NULL)!=SPL_FALSE) /* calcula autovalores...*/ 00547 return SPL_TRUE; /* y fin en caso de error */ 00548 00549 #ifdef SORT_LSFS 00550 for (i=0; i<p; i++) { 00551 for (j=m=0; j<p; j++) /* busca el mayor */ 00552 if (vd[j]>vd[m]) 00553 m=j; 00554 vlx[i*2+1]= 2.0*vd[m]-1.0; 00555 vd[m]=0.0; 00556 } 00557 #else 00558 for (i=0; i<p; i++) /* guardar sin orden */ 00559 vlx[n+i] = 2.0*vd[i]-1.0; 00560 #endif 00561 00562 return SPL_FALSE; 00563 00564 #undef vx 00565 #undef SORT_LSFS 00566 } 00567 00568 /**********************************************************/ 00569 00570 PUBLIC SPL_INT XAPI tnel_lpa_cor_slv_lx( SPL_INT p ) 00571 { 00572 SPL_INT i1, i2; 00573 assert(p>0); 00574 00575 i1 = tnel_lpa_cor_sls_xa(p); 00576 00577 i2 = tnel_lpa_cor_sls_xa_ne(p); 00578 if (i1<i2) 00579 i1=i2; 00580 00581 i2 = tnel_lpa_cor_sla_xa_ne(p); 00582 if (i1<i2) 00583 i1=i2; 00584 00585 if (i1<=p) 00586 i1=p+1; 00587 00588 return p+2+i1; 00589 } 00590 00591 /**********************************************************/ 00592 /* A partir de los {p} coeficientes enviados en el vector {vlx} 00593 y que representan los cosenos de las LSFs (rango 1, -1), devuelve en 00594 el vector {vlw} (tambien de {p} elementos) las LSFs correspondientes 00595 (rango 0, Pi). 00596 Es decir, calcula vlw[i]=arccos(vlx[i]). 00597 La funcion {devuelve} el vector {vlw}. Ademas {vlw} puede coincidir 00598 con {vlx}. 00599 p>=0. */ 00600 00601 PUBLIC SPL_pFLOAT XAPI lp_lx2lw( SPL_pFLOAT vlx, SPL_pFLOAT vlw, SPL_INT p ) 00602 { 00603 SPL_INT i; 00604 assert(p>=0); 00605 00606 for (i=0; i<p; i++) 00607 vlw[i]=acos(vlx[i]); 00608 00609 return vlw; 00610 } 00611 00612 /**********************************************************/ 00613 /* A partir de los {p} coeficientes enviados en el vector {vlw} 00614 y que representan las LSFs (rango 0, Pi), devuelve en el 00615 vector {vlx} (tambien de {p} elementos) los cosenos de las LSFs 00616 correspondientes (rango 1, -1). 00617 Es decir, calcula vlx[i]=cos(vlw[i]). 00618 La funcion {devuelve} el vector {vlx}. Ademas {vlx} puede coincidir 00619 con {vlw}. 00620 p>=0. */ 00621 00622 PUBLIC SPL_pFLOAT XAPI lp_lw2lx( SPL_pFLOAT vlw, SPL_pFLOAT vlx, SPL_INT p ) 00623 { 00624 SPL_INT i; 00625 assert(p>=0); 00626 00627 for (i=0; i<p; i++) 00628 vlx[i]=cos(vlw[i]); 00629 00630 return vlx; 00631 } 00632 00633 /**********************************************************/ 00634 /* a partir del vector de coeficientes LPC {vai} de {p} 00635 elementos (analisis predictivo de orden {p}, calcula los 00636 cosenos de las LSFs, y los devuelve en el vector {vlx} de {p} 00637 elementos. Ver lpa_cor_slv_lx() para mas informacion sobre {vlx}. 00638 Si se obtiene el resultado, la funcion {devuelve} FALSE, pero si 00639 se supera el numero maximo de iteraciones al obtener los autovalores, 00640 la funcion {devuelve} TRUE y el resultado es indefinido. 00641 {vtmp} es un vector temporal de tnel_lp_a2lx(p) elementos. 00642 p>0. */ 00643 00644 PUBLIC SPL_BOOL XAPI lp_a2lx( SPL_pFLOAT vai, SPL_pFLOAT vlx, SPL_INT p, 00645 SPL_pFLOAT vtmp ) 00646 { 00647 assert(p>0); 00648 00649 lp_a2rh(vai,vtmp+1,p,vtmp+p+1); /* calcula autocorrelaciones */ 00650 vtmp[0]=1.0; /* estan normalizadas a la del origen */ 00651 00652 return lpa_cor_slv_lx(vtmp,vlx,p,NULL,vtmp+p+1); 00653 } 00654 00655 /**********************************************************/ 00656 00657 PUBLIC SPL_INT XAPI tnel_lp_a2lx( SPL_INT p ) 00658 { 00659 SPL_INT i1, i2; 00660 assert(p>0); 00661 00662 i1 = tnel_lp_a2rh(p); 00663 00664 i2=tnel_lpa_cor_slv_lx(p); 00665 if (i1<i2) 00666 i1=i2; 00667 00668 return i1+p+1; 00669 } 00670 00671 /**********************************************************/ 00672 /* a partir de los {p} cosenos de las LSFs enviados en {vlx} para un 00673 analisis predictivo de orden {p}, calcula los coeficientes LPC 00674 correspondientes en {vai} (tambien de {p} elementos. 00675 {vtmp} es un vector temporal de tnel_lp_lx2a(p) elementos. 00676 La funcion {devuelve} el puntero {vai}. 00677 El vector {vlx} debe cumplir la condicion de que todas las LSFs esten 00678 ordenadas de forma ascendente, (y raices de P(z) y Q(z) entrelazadas, 00679 comenzando por la menor raiz no trivial de P(z). Este es precisamente 00680 el formato que utiliza lpa_cor_slv_lx() al calcular {vlx}. Ver esta 00681 funcion para mas informacion. 00682 p>0. */ 00683 00684 PUBLIC SPL_pFLOAT XAPI lp_lx2a( SPL_pFLOAT vlx, SPL_pFLOAT vai, 00685 SPL_INT p, SPL_pFLOAT vtmp ) 00686 { 00687 #define pp vtmp 00688 SPL_pFLOAT qq, ac; 00689 SPL_FLOAT lx2; 00690 SPL_INT i, j, np, nq; 00691 assert(p>0); 00692 00693 np=(p+1)/2; 00694 nq=p/2; 00695 /* pp=vtmp en el define */ 00696 qq = pp+np; 00697 ac = qq+nq; 00698 00699 for (i=0; i<np; i++) 00700 pp[i]=0.0; 00701 for (i=0; i<nq; i++) 00702 qq[i]=0.0; 00703 /* inicializar con ceros triviales */ 00704 if (p&1) /* p impar, PUBLIC sin ceros, Q con ceros en z=1 y z=-1 */ 00705 qq[1]=-1.0; 00706 else { /* p par, PUBLIC con cero en z=-1, Q con cero en z=1 */ 00707 pp[0]=1.0; 00708 qq[0]=-1.0; 00709 } 00710 00711 for (i=0; i<np; i++) { /* ceros de PUBLIC */ 00712 lx2 = 2.0*vlx[i*2]; 00713 ac[0]=-lx2; 00714 ac[1]=1.0; 00715 for (j=2; j<np; j++) 00716 ac[j] = pp[j-2]; /* z**2 */ 00717 for (j=1; j<np; j++) 00718 ac[j] -= lx2*pp[j-1]; /* 2*lx*z */ 00719 for (j=0; j<np; j++) 00720 pp[j]+=ac[j]; 00721 } 00722 00723 for (i=0; i<nq; i++) { /* ceros de Q */ 00724 lx2 = 2.0*vlx[i*2+1]; 00725 ac[0]=-lx2; 00726 ac[1]=1.0; 00727 for (j=2; j<nq; j++) 00728 ac[j] = qq[j-2]; /* z**2 */ 00729 for (j=1; j<nq; j++) 00730 ac[j] -= lx2*qq[j-1]; /* 2*lx*z */ 00731 for (j=0; j<nq; j++) 00732 qq[j]+=ac[j]; 00733 } 00734 00735 for (i=0; i<nq; i++) { /* reconstruye coeficientes LPC */ 00736 vai[i] = LP_NEGSUM_NEG(0.5)*(pp[i]+qq[i]); 00737 vai[p-i-1] = LP_NEGSUM_NEG(0.5)*(pp[i]-qq[i]); 00738 } 00739 if (p&1) /* si p impar */ 00740 vai[nq] = LP_NEGSUM_NEG(0.5)*pp[nq]; 00741 00742 return vai; 00743 #undef pp 00744 } 00745 00746 /**********************************************************/ 00747 00748 PUBLIC SPL_INT XAPI tnel_lp_lx2a( SPL_INT p ) 00749 { 00750 return p+(p+5)/2; 00751 } 00752 00753 /**********************************************************/ 00754