00001 /**********************************************************/ 00002 /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ 00003 /* 00004 Copyright: 1994 - Grupo de Voz (DAET) ETSII/IT-Bilbao 00005 00006 Nombre fuente................ XFFT3.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 00012 00013 Codificacion................. Borja Etxebarria 00014 00015 Version dd/mm/aa Autor Proposito de la edicion 00016 ------- -------- -------- ----------------------- 00017 1.3.2 30/07/95 Borja scope funciones explicito 00018 1.3.1 30/03/95 Borja llamada invalida en cefm_cepfm_f32() 00019 1.3.0 08/12/94 Borja revision general (tipos,idx,nel,tnel...) 00020 1.2.1 14/03/94 Borja bug: cepfm_getceps() --> cepfm_getcepfm() 00021 1.2.0 28/10/93 Borja Soporte de diferentes tipos de enventanado. 00022 1.1.0 01/02/93 Borja Calculo de cepstrum fft-modulo ('clase' cepfm). 00023 1.0.0 16/03/92 Borja Codificacion inicial. 00024 00025 ======================== Contenido ======================== 00026 Funciones para el calculo eficiente y reiterado de 00027 cepstrum-FFT-modulo. 00028 00029 Ver XFFT1.C para informacion general sobre los modulos XFFT?.C. 00030 =========================================================== 00031 */ 00032 /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ 00033 /**********************************************************/ 00034 00035 #include "_xfft.h" 00036 00037 /**********************************************************/ 00038 /* Cepstrum FFT-modulo. Funcion constructora de la estructura. 00039 00040 Recibe como parametros: 00041 - SPL_INT {np} : Numero de puntos de los vectores de datos (reales) 00042 . de los que queremos calcular los cepstrum FFT-modulo. 00043 . {np}>0, y no tiene por que ser una potencia de 2 (relleno 00044 . automatico con ceros). 00045 . La fft directa utiliza la menor potencia de dos superior 00046 . o igual a {np}. 00047 00048 - SPL_INT {ifftnp} : Numero de puntos de la FFT inversa. 00049 . Si este parametro es cero, se utiliza la menor potencia 00050 . de dos superior o igual a {np}. 00051 . Si este valor no es cero, se utiliza la menor potencia 00052 . de dos superior o igual a {ifftnp}. En caso de que {np} 00053 . sea menor que {ifftnp} (realmente las potencias de dos 00054 . mas proximas), se introducen ceros al rededor 00055 . de la muestra correspondiente a PI. Asi, la fft inversa 00056 . da como resultado cepstrum con valores 'interpolados'. 00057 . {ifftnp}>=0, y no tiene porque ser potencia de 2. 00058 00059 - SPL_FLOAT {ufactor} : factor de escalado. Multiplica al resultado 00060 . de los cepstrum. Por lo general este 00061 . factor es 1 (sin escalado). 00062 00063 - XFFT_WIN {win} : Codigo que identifica el tipo de ventana a 00064 . utilizar. Son los codigos XFFT_WIN_??? definidos 00065 . en xfft.h. Ver rfft_setwin() para mas informacion. 00066 . Si se utilizar una ventana, sera de {np} puntos, 00067 . aunque si el numero de puntos de la fft es menor, 00068 . se utiliza este otro valor. 00069 00070 - XFFT_WIN_FUNC {winfunc} : Puntero a una funcion que sigue el 00071 . prototipo indicado (xfft.h) que suministra 00072 . el usuario. Esta funcion se utiliza para 00073 . obtener la ventana a utilizar cuando 00074 . en {win} se envia XFFT_WIN_USER. Si este 00075 . puntero es NULL y se envia XFFT_WIN_USER 00076 . en {win}, no se utiliza ningun enventanado. 00077 00078 La funcion {devuelve} un puntero a una estructura, que debera utilizarse 00079 como primer parametro para el resto de las funciones cepfm_???(). 00080 Si no es posible crear la estructura, la funcion {devuelve} NULL. */ 00081 00082 PUBLIC pCEPFM XAPI cepfm_construct( SPL_INT np, SPL_INT ifftnp, 00083 SPL_FLOAT ufactor, XFFT_WIN win, XFFT_WIN_FUNC winfunc ) 00084 { 00085 pCEPFM c; 00086 SPL_INT n, i; 00087 assert(np>0); 00088 assert(ifftnp>=0); 00089 00090 c = (pCEPFM)xfft_malloc(sizeof(CEPFM)); 00091 00092 if (c!=NULL) { 00093 00094 if (!ifftnp) 00095 ifftnp = np; 00096 00097 c->_r1 = rfft_construct(np,0,FFT_DIRECT,1,win,winfunc); 00098 n = ((SPL_INT)1 << fft_n_bits(ifftnp)); 00099 00100 /* fft inversa: divide entre ufactor */ 00101 /* log(XAPI^2)=2*log(XAPI), por tanto, escala 00102 a 1/2 --> ifft divide entre 2 */ 00103 c->_r2 = rfft_construct(n,0,FFT_INVERSE, 00104 2.0/ufactor,XFFT_WIN_NONE,NULL); 00105 00106 c->_tmp = (SPL_pFLOAT)xfft_malloc(sizeof(SPL_FLOAT)*n); 00107 00108 if ((c->_r1!=NULL)&&(c->_r2!=NULL)&&(c->_tmp!=NULL)) { 00109 for (i=0; i<n; i++) 00110 c->_tmp[i]=0.0; 00111 } 00112 else { 00113 cepfm_destruct(c); 00114 c=NULL; 00115 } 00116 } 00117 00118 return c; 00119 } 00120 00121 /**********************************************************/ 00122 /* destructor para una estructura CEPFM */ 00123 00124 PUBLIC SPL_VOID XAPI cepfm_destruct( pCEPFM c ) 00125 { 00126 assert(c!=NULL); 00127 00128 if (c->_r1) 00129 rfft_destruct(c->_r1); 00130 if (c->_r2) 00131 rfft_destruct(c->_r2); 00132 if (c->_tmp) 00133 xfft_free(c->_tmp); 00134 xfft_free(c); 00135 } 00136 00137 /**********************************************************/ 00138 /* modifica el uso de la ventana en la fft directa. 00139 Enviar {win}==XFFT_WIN_??? para utilizar la ventana del tipo 00140 deseado. En xfft.h se definen constantes XFFT_WIN_??? para 00141 diversos tipos de ventanas (??? = HAMM, HANN, BART, BLACK, 00142 KAIS5, ... KAIS10, USER, NONE). Si {win} es XFFT_WIN_NONE o 00143 XFFT_WIN_RECT no se utiliza ninguna ventana. Si {win} es 00144 XFFT_WIN_USER, entonces se utilizara la ventana obtenida 00145 a traves de la funcion que el usuario suministra en el puntero 00146 {winfunc} (siempre y cuando sea distinto de NULL, ya que si es 00147 NULL no se utiliza ninguna ventana). En xfft.h se explica el 00148 prototipo que debe seguir esta funcion. 00149 00150 Puesto que el proceso realizado puede implicar la creacion 00151 de vectores de datos utilizando memoria dinamica, la 00152 funcion {devuelve} SPL_TRUE si todo va bien, o SPL_FALSE si se produce 00153 algun error. En caso de error, la ventana se desconecta (se 00154 utiliza ventana rectangular) */ 00155 00156 PUBLIC SPL_BOOL XAPI cepfm_setwin( pCEPFM c, XFFT_WIN win, 00157 XFFT_WIN_FUNC winfunc ) 00158 { 00159 assert(c!=NULL); 00160 00161 return rfft_setwin(c->_r1,win,winfunc); 00162 } 00163 00164 /**********************************************************/ 00165 /* modifica el numero de puntos de los vectores de los que se 00166 quiere calcular los cepstrum, indicando que los vectores 00167 tendran {np} puntos. Si {np} es mayor que el numero de puntos de la 00168 FFT directa configurada al crear la estructura cepfm, {np} se trunca 00169 al valor del numero de puntos de esta FFT. 00170 00171 Puesto que esto puede implicar la creacion de vectores de datos 00172 utilizando memoria dinamica, la funcion {devuelve} SPL_TRUE si todo 00173 va bien, o SPL_FALSE si se produce algun error. En caso de error, 00174 significa que la ventana de hamming se desconecta (se utiliza 00175 ventana rectangular) */ 00176 00177 PUBLIC SPL_BOOL XAPI cepfm_setnp( pCEPFM c, SPL_INT np ) 00178 { 00179 assert(c!=NULL); 00180 00181 return rfft_setnp(c->_r1,np); 00182 } 00183 00184 /**********************************************************/ 00185 /* modifica simultaneamente el numero de puntos de los vectores 00186 de datos y el uso del enventanado (ver cepfm_setwin()). 00187 El valor SPL_BOOL que {devuelve} la funcion es similar al indicado 00188 en cepfm_setwin() */ 00189 00190 PUBLIC SPL_BOOL XAPI cepfm_setnpwin( pCEPFM c, SPL_INT np, 00191 XFFT_WIN win, XFFT_WIN_FUNC winfunc ) 00192 { 00193 assert(c!=NULL); 00194 00195 return rfft_setnpwin(c->_r1,np,win,winfunc); 00196 } 00197 00198 /**********************************************************/ 00199 /* modifica el factor de usuario que multiplica a los cepstrum */ 00200 00201 PUBLIC SPL_VOID XAPI cepfm_setufactor( pCEPFM c, SPL_FLOAT ufactor ) 00202 { 00203 assert(c!=NULL); 00204 00205 rfft_setufactor(c->_r2,2/ufactor); 00206 } 00207 00208 /**********************************************************/ 00209 /* {devuelve} el numero de puntos que deben tener los vectores 00210 de datos de los que se quiere calcular los cepstrum */ 00211 00212 PUBLIC SPL_INT XAPI cepfm_getnp( pCEPFM c ) 00213 { 00214 assert(c!=NULL); 00215 00216 return rfft_getnp(c->_r1); 00217 } 00218 00219 /**********************************************************/ 00220 /* {devuelve} el numero de puntos del vector resultado que contiene 00221 los cepstrum FFT-modulo */ 00222 00223 PUBLIC SPL_INT XAPI cepfm_getcepnp( pCEPFM c ) 00224 { 00225 assert(c!=NULL); 00226 00227 return rfft_getvecnp(c->_r2); 00228 } 00229 00230 /**********************************************************/ 00231 /* {devuelve} el tipo de enventanado que se esta utilizando 00232 (XFFT_WIN_???, con ??? = NONE (o RECT), HAMM, HANN, .... 00233 consultar xfft.h ) */ 00234 00235 PUBLIC XFFT_WIN XAPI cepfm_getwin( pCEPFM c ) 00236 { 00237 assert(c!=NULL); 00238 00239 return rfft_getwin(c->_r1); 00240 } 00241 00242 /**********************************************************/ 00243 /* {devuelve} el puntero a la funcion de enventanado que 00244 ha suministrado el usuario */ 00245 00246 PUBLIC XFFT_WIN_FUNC XAPI cepfm_getwinfunc( pCEPFM c ) 00247 { 00248 assert(c!=NULL); 00249 00250 return rfft_getwinfunc(c->_r1); 00251 } 00252 00253 /**********************************************************/ 00254 /* {devuelve} el factor de usuario */ 00255 00256 PUBLIC SPL_FLOAT XAPI cepfm_getufactor( pCEPFM c ) 00257 { 00258 assert(c!=NULL); 00259 00260 /* fft inversa, 'divide' entre 2 */ 00261 return 2.0 / rfft_getufactor(c->_r2); 00262 } 00263 00264 /**********************************************************/ 00265 /* {devuelve} un puntero al vector que contiene los cepstrum. 00266 El usuario previamente habra tenido que calcular los cepstrum. 00267 Este vector es interno y el usuario no debe borrarlo, aunque 00268 si puede modificarlo. 00269 Este vector tiene cepfm_getcepnp() puntos. */ 00270 00271 PUBLIC SPL_pFLOAT XAPI cepfm_getcepfm( pCEPFM c ) 00272 { 00273 assert(c!=NULL); 00274 00275 return rfft_getrevec(c->_r2); 00276 } 00277 00278 /**********************************************************/ 00279 /* uso interno: 2*log(modulo(r,i)) */ 00280 00281 PRIVATE SPL_FLOAT cepfm_logmod2( SPL_FLOAT * r, SPL_FLOAT * i ) 00282 { 00283 SPL_FLOAT tmp; 00284 00285 tmp = __fft_cx_norm(*r,*i); 00286 00287 if (tmp<(FFT_ZERO*FFT_ZERO)) 00288 return log((FFT_ZERO*FFT_ZERO)); 00289 else 00290 return log(tmp); 00291 } 00292 00293 /**********************************************************/ 00294 /* uso interno */ 00295 00296 PRIVATE SPL_VOID cepfm_docepfm( pCEPFM c ) 00297 { 00298 SPL_INT i, n1, n2; 00299 SPL_pFLOAT qr,qi, pi,pf; 00300 assert(c!=NULL); 00301 00302 n2 = rfft_getnp(c->_r2); 00303 pi = (c->_tmp); 00304 pf = (c->_tmp)+n2-1; 00305 n2 >>= 1; 00306 n1 = rfft_getvecnp(c->_r1)-1; 00307 if (n1>n2) 00308 n1 = n2; 00309 qr = rfft_getrevec(c->_r1); 00310 qi = rfft_getimvec(c->_r1); 00311 00312 /* log(XAPI**2)==2*log(XAPI), por tanto hay que dividir 00313 entre 2 en la fft inversa */ 00314 (*(pi++)) = cepfm_logmod2(qr++,qi++); 00315 for (i=1; i<n1; i++) 00316 (*(pi++)) = (*(pf--)) = cepfm_logmod2(qr++,qi++); 00317 if (n1) 00318 (*pf) = cepfm_logmod2(qr,qi); 00319 00320 rfft_rfft(c->_r2,c->_tmp); 00321 } 00322 00323 /**********************************************************/ 00324 /* calcula los cepstrum FFT-modulo de un vector {invec} de cepfm_getnp() 00325 elementos de tipo SPL_FLOAT */ 00326 00327 PUBLIC SPL_VOID XAPI cepfm_cepfm( pCEPFM c, SPL_pFLOAT invec ) 00328 { 00329 assert(c!=NULL); 00330 00331 rfft_rfft(c->_r1,invec); 00332 cepfm_docepfm(c); 00333 } 00334 00335 /**********************************************************/ 00336 /* calcula los cepstrum FFT-modulo de un vector {invec} de cepfm_getnp() 00337 elementos de tipo SPL_INT */ 00338 00339 PUBLIC SPL_VOID XAPI cepfm_cepfm_i( pCEPFM c, SPL_pINT invec ) 00340 { 00341 assert(c!=NULL); 00342 00343 rfft_rfft_i(c->_r1,invec); 00344 cepfm_docepfm(c); 00345 } 00346 00347 /**********************************************************/ 00348 /* calcula los cepstrum FFT-modulo de un vector {invec} de cepfm_getnp() 00349 elementos de tipo INT16 */ 00350 00351 PUBLIC SPL_VOID XAPI cepfm_cepfm_i16( pCEPFM c, pINT16 invec ) 00352 { 00353 assert(c!=NULL); 00354 00355 rfft_rfft_i16(c->_r1,invec); 00356 cepfm_docepfm(c); 00357 } 00358 00359 /**********************************************************/ 00360 /* calcula los cepstrum FFT-modulo de un vector {invec} de cepfm_getnp() 00361 elementos de tipo FLOAT32 */ 00362 00363 PUBLIC SPL_VOID XAPI cepfm_cepfm_f32( pCEPFM c, pFLOAT32 invec ) 00364 { 00365 assert(c!=NULL); 00366 00367 rfft_rfft_f32(c->_r1,invec); 00368 cepfm_docepfm(c); 00369 } 00370 00371 /**********************************************************/ 00372