00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "time_frequency.h"
00022 #include "linalg.h"
00023
00038 Spectrogram* spectrogram( const Array *sig, Spectrogram *spectgram,
00039 OptArgList *optargs ){
00040 double x;
00041 void *ptr;
00042 double sample_frequency;
00043 WindowFunction winfct;
00044 int winlength;
00045 double winparam;
00046 int N_freq;
00047 int N_time;
00048 double corner_freqs[2];
00049 int *timepoints;
00050
00051
00052 bool isvec;
00053 vector_CHECK( isvec, sig );
00054 if( !isvec ) return NULL;
00055
00056 int n=sig->size[0];
00057
00058 sample_frequency = 500.0;
00059 winfct = window_hanning;
00060 winlength = MAX( SQR( sqrt(next_pow2( n ))-3 ), 5 );
00061 winparam=0.0;
00062 N_freq = winlength*4;
00063 N_time = n;
00064 corner_freqs[0] = 0.0;
00065 corner_freqs[1] = 250.0;
00066 timepoints = NULL;
00067 bool N_time_set=FALSE;
00068
00069
00070 optarg_PARSE_SCALAR( optargs, "sample_frequency", sample_frequency, double, x );
00071 optarg_PARSE_PTR( optargs, "winfct", winfct, WindowFunction, ptr );
00072 optarg_PARSE_SCALAR( optargs, "winlength", winlength, int, x );
00073 optarg_PARSE_SCALAR( optargs, "winparam", winparam, double, x );
00074 optarg_PARSE_SCALAR( optargs, "N_freq", N_freq, int, x );
00075 if( optarglist_has_key( optargs, "N_time" ) ){
00076 x = optarglist_scalar_by_key( optargs, "N_time" );
00077 if( !isnan( x ) ){
00078 N_time=(int)x;
00079 N_time_set=TRUE;
00080 }
00081 }
00082 if( optarglist_has_key( optargs, "corner_freqs" ) ){
00083 ptr = optarglist_ptr_by_key( optargs, "corner_freqs" );
00084 if( ptr ){
00085 corner_freqs[0] = ((double*)ptr)[0];
00086 corner_freqs[1] = ((double*)ptr)[1];
00087 }
00088 }
00089 if( optarglist_has_key( optargs, "timepoints" ) ){
00090 ptr = optarglist_ptr_by_key( optargs, "timepoints" );
00091 if( ptr && N_time_set ){
00092 timepoints = (int*)ptr;
00093 }
00094 }
00095
00096 dprintf("got sfreq=%f, winfct=%p, winlength=%i, winparam=%f, N_f=%i,"
00097 "N_t=%i, cf=(%f,%f), timepoints=%p\n",
00098 sample_frequency, winfct, winlength, winparam, N_freq, N_time,
00099 corner_freqs[0], corner_freqs[1], timepoints );
00100
00101 Array *window=winfct( winlength, winparam );
00102
00103 spectgram = spectrogram_stft( sig, sample_frequency,
00104 window, N_freq, N_time, corner_freqs,
00105 timepoints, spectgram );
00106 return spectgram;
00107 }
00108
00109
00144 Spectrogram* spectrogram_stft(const Array* sig, double sampling_rate,
00145 const Array *Window, int N_freq, int N_time,
00146 double corner_freqs[2],
00147 int *timepoints, Spectrogram *spectgram){
00148
00149 int Nfft, timepoint, frequency, time;
00150 int taumin, taumax, tau;
00151 int half_Window_Length;
00152 double *wind_sig_complex;
00153 double normh;
00154 double inter;
00155 int corner_freqs_idx[2];
00156 int N_freq_spect;
00157 int Window_Length;
00158
00159
00160 bool isvec;
00161 vector_CHECK( isvec, sig );
00162 if( !isvec ) return NULL;
00163 vector_CHECK( isvec, Window );
00164 if( !isvec ) return NULL;
00165
00166 int n=sig->size[0];
00167 Window_Length=Window->size[0];
00168
00169
00170 half_Window_Length = (Window_Length - 1) / 2;
00171 inter = 0.0;
00172 for (frequency = 0; frequency <Window_Length; frequency++){
00173 inter += SQR (vec_IDX(Window,frequency));
00174 }
00175 normh = sqrt (inter);
00176
00177
00178 Nfft = pow( 2, next_pow2( N_freq ));
00179 if( corner_freqs[1]<=corner_freqs[0] ||
00180 corner_freqs[0]<0 || corner_freqs[1]>sampling_rate/2.0 ){
00181 errprintf("corner_freqs funny: (%f,%f)\n",
00182 corner_freqs[0], corner_freqs[1] );
00183 return NULL;
00184 }
00185 corner_freqs_idx[0] = (int)round( (corner_freqs[0]/(sampling_rate/2.0)) * (N_freq-1) );
00186 corner_freqs_idx[1] = (int)round( (corner_freqs[1]/(sampling_rate/2.0)) * (N_freq-1) );
00187 dprintf(" Corner-freqs=(%.2f,%.2f) in idx=(%i,%i)\n", corner_freqs[0], corner_freqs[1],
00188 corner_freqs_idx[0], corner_freqs_idx[1] );
00189 dprintf(" Returning actual frequencies: (%.3f, %.3f)\n",
00190 (corner_freqs_idx[0]/(double)N_freq)*sampling_rate/2.0,
00191 (corner_freqs_idx[1]/(double)N_freq)*sampling_rate/2.0 );
00192 N_freq_spect = corner_freqs_idx[1]-corner_freqs_idx[0];
00193
00194
00195
00196 wind_sig_complex = (double *) calloc (2*Nfft, sizeof (double));
00197
00198 if( spectgram==NULL ){
00199 spectgram = spectrogram_init( N_freq_spect, N_time );
00200 }
00201 spectgram->low_corner_freq = corner_freqs[0];
00202 spectgram->up_corner_freq = corner_freqs[1];
00203
00204
00205 for (timepoint = 0; timepoint < N_time; timepoint++) {
00206
00207 for (frequency = 0; frequency < 2*Nfft; frequency++){
00208 wind_sig_complex[frequency] = 0.0;
00209 }
00210
00211
00212 if( timepoints ){
00213 time = timepoints[timepoint];
00214 } else {
00215 time = timepoint*(int)(n/N_time);
00216 }
00217
00218
00219
00220
00221
00222
00223 taumin = MIN (N_freq / 2, half_Window_Length);
00224 taumin = MIN (taumin, time);
00225
00226 taumax = MIN ((N_freq / 2 - 1), half_Window_Length);
00227 taumax = MIN (taumax, (n - time - 1));
00228
00229
00230
00231 frequency=0;
00232 for (tau = -taumin; tau <= taumax; tau++){
00233 wind_sig_complex[2*frequency ] = vec_IDX(sig,time + tau) *
00234 vec_IDX( Window, half_Window_Length + tau ) / normh;
00235 wind_sig_complex[2*frequency+1] = 0.0;
00236 frequency++;
00237 }
00238
00239 fft( wind_sig_complex, Nfft, 1 );
00240
00241
00242
00243 for (frequency = corner_freqs_idx[0]; frequency < corner_freqs_idx[1]; frequency++){
00244 spectgram->sgram[timepoint][frequency].re = wind_sig_complex[2*frequency ];
00245 spectgram->sgram[timepoint][frequency].im = wind_sig_complex[2*frequency+1];
00246 }
00247 }
00248
00249
00250 free (wind_sig_complex);
00251
00252 return spectgram;
00253 }
00254
00255
00264 Array* spectrogram_powerspectrum( const Spectrogram *s ){
00265 int i,j;
00266 Array *p = array_new2( DOUBLE, 2, s->N_time, s->N_freq );
00267
00268 for( i=0; i<s->N_time; i++ ){
00269 for( j=0; j<s->N_freq; j++ ){
00270 mat_IDX( p, i,j) = SQR( complex_abs( s->sgram[i][j] ) );
00271 }
00272 }
00273 return p;
00274 }
00275
00282 Spectrogram* spectrogram_init( int N_freq, int N_time ){
00283 Spectrogram *s;
00284 int i;
00285
00286 dprintf("N_freq=%i, N_time=%i\n", N_freq, N_time );
00287 s = (Spectrogram*) malloc( sizeof(Spectrogram) );
00288 s->samplingrate = 500.0;
00289 s->N_freq = N_freq;
00290 s->N_time = N_time;
00291 s->low_corner_freq=0;
00292 s->up_corner_freq=0;
00293 s->sgram = (Complex**) malloc( N_time*sizeof(Complex*) );
00294 for( i=0; i<N_time; i++ ){
00295 s->sgram[i] = (Complex*) malloc( N_freq*sizeof(Complex) );
00296 }
00297 return s;
00298 }
00299
00302 void spectrogram_free( Spectrogram *s ){
00303 int i;
00304
00305 for( i=0; i<s->N_time; i++ ){
00306 free( s->sgram[i] );
00307 }
00308 free( s->sgram );
00309 free( s );
00310 }
00311
00312
00313
00323 Array* window_dirichlet( int n, double noparam ){
00324 int i;
00325
00326 if( !ISODD( n ) ){
00327 errprintf("window size must be ODD! Adding 1, n=%i!\n", n+1);
00328 n++;
00329 }
00330 Array *window = array_new2( DOUBLE, 1, n );
00331 for( i=0; i<n; i++ ){
00332 vec_IDX( window,i ) = 1.0;
00333 }
00334
00335 return window;
00336 }
00337
00349 Array* window_gaussian( int n, double sigma ){
00350 int i;
00351
00352 if( !ISODD( n ) ){
00353 errprintf("window size must be ODD! Adding 1, n=%i!\n", n+1);
00354 n++;
00355 }
00356
00357 Array *window = array_new2( DOUBLE, 1, n );
00358 for( i=0; i<n; i++ ){
00359 vec_IDX(window,i) = exp(-0.5*SQR( (i-(n-1)/2.0)/(double)(sigma*(n-1)/2.0)) );
00360 }
00361
00362 return window;
00363 }
00364
00374 Array* window_hamming( int n, double noparam ){
00375 int i;
00376
00377 if( !ISODD( n ) ){
00378 errprintf("window size must be ODD! Adding 1, n=%i!\n", n+1);
00379 n++;
00380 }
00381
00382 Array *window = array_new2( DOUBLE, 1, n );
00383 for( i=0; i<n; i++ ){
00384 vec_IDX(window,i) = 0.53836 - 0.46164*cos( (2* PI *i)/(double)(n-1) );
00385 }
00386
00387 return window;
00388 }
00399 Array* window_hanning( int n, double noparam ){
00400 int i;
00401
00402 if( !ISODD( n ) ){
00403 errprintf("window size must be ODD! Adding 1, n=%i!\n", n+1);
00404 n++;
00405 }
00406 Array *window = array_new2( DOUBLE, 1, n );
00407 for( i=0; i<n; i++ ){
00408 vec_IDX( window,i) = 0.5*(1 - cos( (2* PI *i)/(double)(n-1) ));
00409 }
00410
00411 return window;
00412 }
00413
00414
00423 Array* window_kaiser( int n, double alpha ){
00424 int i;
00425 double bessel_alpha;
00426
00427 Array *window = array_new2( DOUBLE, 1, n );
00428
00429 bessel_alpha=gsl_sf_bessel_I0( alpha );
00430 for( i=0; i<n-1; i++ ){
00431 vec_IDX(window,i) = gsl_sf_bessel_I0( alpha*sqrt(1 - SQR( (2*i)/(double)(n-1) - 1 ) ) ) / bessel_alpha;
00432 }
00433 vec_IDX(window,n-1)=0;
00434
00435 return window;
00436 }
00437