00001 /**********************************************************/ 00002 /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ 00003 /* 00004 Copyright: 1994 - Grupo de Voz (DAET) ETSII/IT-Bilbao 00005 00006 Nombre fuente................ SPL8C.C 00007 Nombre paquete............... SPL 00008 Lenguaje fuente.............. C (Borland C/C++ 3.1) 00009 Estado....................... experimental 00010 Dependencia Hard/OS.......... - 00011 Codigo condicional........... NDEBUG 00012 00013 Codificacion................. Borja Etxebarria 00014 00015 Version dd/mm/aa Autor Proposito de la edicion 00016 ------- -------- -------- ----------------------- 00017 2.0.0 01/07/97 Borja spl8.c -> spl8?.c 00018 00019 ======================== Contenido ======================== 00020 Pruebas con la DST y DCT 00021 =========================================================== 00022 */ 00023 /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ 00024 /**********************************************************/ 00025 00026 #include "spli.h" 00027 00028 /**********************************************************/ 00029 00030 /**********************************************************/ 00031 /* PROVISIONAL PROVISIONAL PROVISIONAL PROVISIONAL PROVISION 00032 AL PROVISIONAL PROVISIONAL PROVISIONAL PROVISIONAL PROVIS */ 00033 /**********************************************************/ 00034 00035 /**********************************************************/ 00036 /*pruebas transformada seno/coseno segun Numerical Recipes*/ 00037 /**********************************************************/ 00038 /* Genera una media-tabla de senos(0 ---> -PI/2) en {vhts}, que 00039 es un vector de {tp} puntos. 00040 00041 . 0 -PI/2 00042 . vhts: ..--------x------ 00043 . ``--.... 00044 00045 La tabla termina en la muestra anterior a -PI/2, y no incluye el 00046 elemento vhts{tp}=sin(-PI/2) que queda ya fuera del vector. 00047 00048 Esta funcion es similar a fft_fill_half_tsin(), pero utiliza otra 00049 media-tabla de senos {vhts2} en vez de calcular montones de nuevos sin(x). 00050 {vhts2} es de {tp}*2 elementos (el doble que {vths}). 00051 Utilizar cuando {vhts2} tambien sea necesaria (transformadas seno y 00052 coseno). 00053 {tp} debe ser >= 0 */ 00054 00055 PUBLIC SPL_VOID XAPI htsin2_fill_htsin( SPL_pFLOAT vhts, SPL_pFLOAT vhts2, SPL_INT tp ) 00056 { 00057 SPL_INT i; 00058 assert(tp>=0); 00059 00060 for (i=0; i<tp; i++) 00061 vhts[i]=vhts2[(SPL_INT)i << 1]; 00062 } 00063 00064 /**********************************************************/ 00065 /* Prepara el vector real {vre} de {np} puntos para calcular la 00066 transformada seno rapida (fst). 00067 La funcion necesita el vector {vhst2}, media-tabla de senos 00068 de {np}/2 puntos. 00069 {np} debe ser un numero par >0 !!! */ 00070 00071 PUBLIC SPL_VOID XAPI fst_re_in( SPL_pFLOAT vre, SPL_pFLOAT vhst2, SPL_INT np ) 00072 { 00073 SPL_INT i,np2; 00074 SPL_FLOAT n1,n2; 00075 assert((np&1)==0); /* testea que np es par */ 00076 assert(np>0); 00077 00078 np2 = np >> 1; 00079 vre[0]=0.0; 00080 for (i=1; i<np2; i++) { 00081 n1 = -vhst2[i]*(vre[i]+vre[np-i]); 00082 n2 = 0.5*(vre[i]-vre[np-i]); 00083 vre[i] = n1+n2; 00084 vre[np-i] = n1-n2; 00085 } 00086 vre[np2] *= 2.0; 00087 } 00088 00089 /**********************************************************/ 00090 /* Prepara el vector real {vre} de {np} puntos para calcular la 00091 transformada coseno rapida (fst). 00092 La funcion necesita el vector {vhst2}, media-tabla de senos 00093 de {np}/2 puntos. 00094 Ademas la funcion {devuelve} un valor necesario para el calculo 00095 de la transformada coseno. 00096 {np} debe ser un numero par >0 !!! */ 00097 00098 PUBLIC SPL_FLOAT XAPI fct_re_in( SPL_pFLOAT vre, SPL_pFLOAT vhst2, SPL_INT np ) 00099 { 00100 SPL_INT i,np2; 00101 SPL_FLOAT n1,n2,n3,sum; 00102 assert((np&1)==0); /* testea que np es par */ 00103 assert(np>0); 00104 00105 np2 = np >> 1; 00106 sum=vre[0]; 00107 00108 for (i=1; i<np2; i++) { 00109 n1 = 0.5*(vre[i]+vre[np-i]); 00110 n2 = vhst2[i] * (n3 = vre[np-i]-vre[i]); 00111 vre[i] = n1-n2; 00112 vre[np-i] = n1+n2; 00113 sum+= (n3*vhst2[np2-i]); 00114 } 00115 return sum; 00116 } 00117 00118 /**********************************************************/ 00119 /* esta funcion es similar a fft_scramble_re_in() pero intercambiando 00120 las partes real e imaginaria (se recibe el vector real de {np} 00121 puntos en {vre_i}, y se crea el vector complejo {vim_r}+j*{vre_i} 00122 de {np}/2 puntos. Hecho asi por eficiencia para la transformada seno. 00123 A la hora de hacer la fft, tener en cuenta que la parte real va en 00124 {vim_r} y la imaginaria en {vre_i}. 00125 {np} debe ser un numero par!!! */ 00126 00127 PUBLIC SPL_VOID XAPI fst_scramble_re_in( SPL_pFLOAT vre_i, SPL_pFLOAT vim_r, SPL_INT np ) 00128 { 00129 SPL_INT i,j; 00130 assert((np&1)==0); /* testea que np es par */ 00131 00132 np >>= 1; 00133 for (i=j=0; i<np; i++) { 00134 vim_r[i] = vre_i[j++]; 00135 vre_i[i] = vre_i[j++]; 00136 }; 00137 } 00138 00139 /**********************************************************/ 00140 /* recupera la transformada seno rapida a partir de la fft efectuada 00141 sobre el vector modificado por frt_re_in(). La fft se ha tenido que 00142 realizar utilizando fst_scramble_re_in() como funcion de scrambling, 00143 por lo que {vre_i} y {vim_r} son la parte imaginaria y real 00144 respectivamente de la fft, una vez efectuado el fft_unscramble_cx_out(), 00145 y son de {np}/2 puntos cada uno (mitad de puntos de la fft). 00146 {np} es la longitud del vector original, y por tanto la del vector 00147 de la transformada seno. 00148 La transformada seno se devuelve en {vre_i} y sera de {np} puntos. Por 00149 tanto, aunque en {vre_i} solo se envian {np}/2 puntos, se devuelven {np}, 00150 y {vim_r} queda indefinido. 00151 {np} debe ser una potencia de 2 y >0.*/ 00152 00153 PUBLIC SPL_VOID XAPI fst_re_out( SPL_pFLOAT vre_i, SPL_pFLOAT vim_r, SPL_INT np ) 00154 { 00155 SPL_INT i, np2; 00156 SPL_FLOAT sum; 00157 assert((np&1)==0); /* testea que np es par */ 00158 assert(np>0); 00159 00160 np2 = np >> 1; 00161 00162 for (i=np2-1; i>0; i--) 00163 vre_i[(SPL_INT)i << 1] = vre_i[i]; 00164 vre_i[0] = 0.0; 00165 sum = (vre_i[1] = vim_r[0]*0.5); 00166 for (i=1; i<np2; i++) { 00167 sum += vim_r[i]; 00168 vre_i[((SPL_INT)i << 1)+1] = sum; 00169 } 00170 } 00171 00172 /**********************************************************/ 00173 /* calcula la transformada seno (fst) vector real {vre} de {np} puntos. 00174 La fst es simetrica (directa e inversa son iguales). 00175 {ufac} multiplica el vector resultado. 00176 {np} debe ser una potencia de 2, mayor o igual que 2 (2,4,8...). 00177 {vtmp} es un vector auxiliar que el usuario debe crear y destruir, 00178 y que debe tener sitio para un numero tnel_fst(np) de elementos 00179 de tipo SPL_FLOAT */ 00180 00181 PUBLIC SPL_VOID XAPI fst( SPL_pFLOAT vre, SPL_INT np, SPL_BOOL inv, SPL_FLOAT ufac, SPL_pFLOAT vtmp ) 00182 { 00183 SPL_pFLOAT vhts2,vhts,vts,vtc,vim; 00184 SPL_INT np_d2, npdiv4; 00185 assert(fft_test_2pow(np)); 00186 assert(np>=2); 00187 00188 npdiv4 = (np_d2 = np >> 1) >> 1; 00189 vim=vtmp; 00190 vhts2=vim+np_d2; 00191 fft_fill_half_tsin(vhts2,np_d2); /* genera media-tabla de senos dobles */ 00192 if (npdiv4) { /* tres tablas */ 00193 vhts = vhts2+np_d2; /* media-tabla de senos, np/4 puntos */ 00194 vts = vhts+npdiv4; /* tablas de senos y cosenos, np/4 puntos */ 00195 vtc = vts+npdiv4; 00196 00197 htsin2_fill_htsin(vhts,vhts2,npdiv4); /* genera media-tabla de senos */ 00198 fft_htsin_fill_tsin_tcos(vts,vtc,vhts,npdiv4); /* tablas de senos y cosenos */ 00199 } 00200 else 00201 vhts = vts = vtc = NULL; 00202 00203 /* preparar para fft compleja rapida, reduce np a np/2 en la fft compleja, 00204 y tener en cuenta que el vector imaginario esta realmente en vre. */ 00205 fst_scramble_re_in(vre,vim,np); 00206 00207 fft_inverse_vecs(vre,vim,np_d2); /* bit-inversion de elementos */ 00208 if (inv) /* factor de correccion por usar la mitad de puntos (FFT inversa)*/ 00209 ufac *= 2.0; 00210 /* calcula fft, con vre y vim intercambiados */ 00211 fft_fft(fft_n_bits(np_d2),inv,vim,vre,vts,vtc,ufac); 00212 00213 /* obtiene la fft final, en rango 0 a PI (np/2 puntos) */ 00214 fft_unscramble_cx_out(vre,vim,np_d2,vhts,inv); 00215 00216 /* extrae la fst a partir de la fft */ 00217 fst_re_out(vre,vim,np); 00218 } 00219 00220 /**********************************************************/ 00221 /* {devuelve} el numero de elementos de tipo SPL_FLOAT (no bytes!!) que 00222 debe enviar el usuario en el vector temporal {vtmp} a la funcion 00223 fst() para calcular una fst de {np} puntos */ 00224 00225 PUBLIC SPL_INT XAPI tnel_fst( SPL_INT np ) 00226 { 00227 return np+(np >> 2)*3; 00228 } 00229 00230 /**********************************************************/