#include "grasp.h" void realft(float *, unsigned long, int); /* this file contains code for computing the various time frequency distributions */ void time_freq_map(float *htilde, struct_tfparam *tfs, int ind, float **tfgeneral,float **pic) { int i,j; for(i=0;i<(*tfs).ND;i+=(*tfs).TD){ for(j=0; j < (*tfs).TD/(*tfs).offset_step_size; j++){ /* branch depending on the type of the distribution */ switch((*tfs).transformtype){ case WIGNERTF: wigner((*tfs).ND, htilde + ind*(*tfs).ND + (*tfs).PRE, tfgeneral[j], \ i+(*tfs).offset_step_size*j); break; case WFFTWTF: windowfft((*tfs).ND, htilde + ind*(*tfs).ND + (*tfs).PRE, tfgeneral[j],\ i+(*tfs).offset_step_size*j,tfs); break; case CHOIWILLIAMS: choiwill((*tfs).ND, htilde + ind*(*tfs).ND + (*tfs).PRE,tfgeneral[j],\ i+(*tfs).offset_step_size*j,tfs); break; case WIGNERTF_NP: wigner_np((*tfs).ND, htilde + ind*(*tfs).ND + (*tfs).PRE, tfgeneral[j], \ i+(*tfs).offset_step_size*j); break; } } /* average the time frequency region to a raster of dimension (*tfs).PD*/ averageblock(tfgeneral,pic[i/(*tfs).TD],tfs); } } void wigner(unsigned long n, float *inp, float *out, int wig_offset) /* computes the wigner tranform of the array inp assuming it is the time representation Only alternate elements of array inp are used and so the array "out" contains only n/2 elements. Zeropadding is done. */ { int i,j,k; /* out(t,tau) = inp(t-tau/2) * inp(t+tau/2)*/ for(i=0;in)) out[i/2] =0.0; else out[i/2] = inp[j]*inp[k]; } realft(out-1,n/2,1); /* zero out the negative elements */ for(i=0;i<=n/2;i+=1) if(out[i]<0) out[i]=0.0; } void wigner_np(unsigned long n, float *inp, float *out, int wig_offset) /* computes the wigner tranform of the array inp assuming it is the time representation Only alternate elements of array inp are used and so the array "out" contains only n/2 elements. Zero padding is NOT done */ { int i,j,k; /* out(t,tau) = inp(t-tau/2) * inp(t+tau/2)*/ for(i=0;i-60.0) /* other wise the exp() term is too small */ sum += inp[k-l]*inp[k+l]*exp(temp); } out[l] = sum*tmp4*tmp1; } realft(out-1,n/2,1); /* zero out the negative elements */ for(j=2;j<=n/2;j++) if(out[j]<0) out[j]=0.0; } void averageblock(float **tfb, float *raster,struct_tfparam *tfs) { switch((*tfs).transformtype){ case WIGNERTF: { int i,j,k,l; double sum; for(i=0;i<(*tfs).PD;i++){ sum=0.0; for(j=0;j<(*tfs).TD/(*tfs).offset_step_size;j++){ for(k=0;k<(*tfs).FD;k++){ l = 2*(i*(*tfs).FD + k); sum += *(tfb[j] + l); } } raster[i] = (sum*(*tfs).offset_step_size)/((*tfs).FD*(*tfs).TD); } } break; case WIGNERTF_NP: { int i,j,k,l; double sum; for(i=0;i<(*tfs).PD;i++){ sum=0.0; for(j=0;j<(*tfs).TD/(*tfs).offset_step_size;j++){ for(k=0;k<(*tfs).FD;k++){ l = 2*(i*(*tfs).FD + k); sum += *(tfb[j] + l); } } raster[i] = (sum*(*tfs).offset_step_size)/((*tfs).FD*(*tfs).TD); } } break; case WFFTWTF: { int i,j,k,l,m; double sum,val; for(i=0;i<(*tfs).PD;i++){ sum=0.0; for(j=0;j<(*tfs).TD/(*tfs).offset_step_size;j++){ for(k=0;k<(*tfs).FD;k++){ l = 2*(i*(*tfs).FD + k); m=l+1; val=((*(tfb[j]+l))*(*(tfb[j]+l)) + (*(tfb[j]+m))*(*(tfb[j]+m))); sum += val; } } raster[i] = (sum*((*tfs).offset_step_size))/((*tfs).FD*(*tfs).TD); } } break; case CHOIWILLIAMS: { int i,j,k,l; double sum; for(i=0;i<(*tfs).PD;i++){ sum=0.0; for(j=0;j<(*tfs).TD/(*tfs).offset_step_size;j++){ for(k=0;k<(*tfs).FD;k++){ l = 2*(i*(*tfs).FD + k); sum += *(tfb[j] + l); } } raster[i] = (sum*(*tfs).offset_step_size)/((*tfs).FD*(*tfs).TD); } } break; } } void normalize_picture(float **pic,int PDIM) { float max,min; int i,j; /* uniformly scale the values in the tf picture to values between 0 and 1 */ max=min=*(pic[0]); for(i=0;imax) max = *(pic[i] + j); if(*(pic[i] + j)1.0) *(pic[i] + j) = 1.0; } float compute_scalefactor(float **pic,float rescale_factor, int pdim) { float max=0.0; int i,j; for (i=0;i=0;i--){ for(j=0;j=0;i--){ for(j=0;j