source: SH_SHM/trunk/source/fftfiltr.c @ 344

Revision 341, 40.1 KB checked in by marcus, 13 years ago (diff)

r180 | walther | 2011-03-09 16:27:03 +0100 (Mi, 09 Mär 2011) | 3 lines

Merging most of the changes from marcus' branch. For full details please see
http://www.seismic-handler.org/portal/log/SH_SHM/branches/marcus?revs=101-106,123-171

Line 
1
2/* file FFTFILTR.C
3 *      ==========
4 *
5 * version 18, 1-Nov-2006
6 *
7 * fast fourier filter
8 * K. Stammler, 11-JUL-1990
9 */
10
11
12/*
13 *
14 *  SeismicHandler, seismic analysis software
15 *  Copyright (C) 1992,  Klaus Stammler, Federal Institute for Geosciences
16 *                                       and Natural Resources (BGR), Germany
17 *
18 *  This program is free software; you can redistribute it and/or modify
19 *  it under the terms of the GNU General Public License as published by
20 *  the Free Software Foundation; either version 2 of the License, or
21 *  (at your option) any later version.
22 *
23 *  This program is distributed in the hope that it will be useful,
24 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
25 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26 *  GNU General Public License for more details.
27 *
28 *  You should have received a copy of the GNU General Public License
29 *  along with this program; if not, write to the Free Software
30 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
31 *
32 */
33
34
35#include <stdio.h>
36#include <string.h>
37#include <math.h>
38#include "basecnst.h"
39#include BC_SYSBASE
40#include "shconst.h"
41#include "shvars.h"
42#include "erusrdef.h"
43#include "ffusrdef.h"
44#include "fctxmt.h"
45#include "flerrors.h"
46#include "numres.h"
47#include "globalparams.h"
48
49
50/* global constants */
51#define MAXFILTER 5
52        /* maximum number of filters */
53#define FILMAGIC 1357913578L
54        /* magic longword of filter files */
55#define FILTERMCH '@'
56        /* termination character between filters */
57#define FILCOMMENTCH '!'
58        /* comment character */
59#define FILID_TFRAT 1
60        /* store ID for FFT filters */
61#define FILID_FILFUNC 2
62        /* store ID for digital filter function */
63
64
65/* macros */
66#define re_mul(ar,ai,br,bi) ((ar)*(br)-(ai)*(bi))
67#define im_mul(ar,ai,br,bi) ((ai)*(br)+(ar)*(bi))
68
69
70/* global variables */
71FFT_RATFCT  fct_ffv[MAXFILTER]; /* transfer functions */
72int         no_of_fil_ffv;      /* number of transfer functions */
73FFT_FILFUNC ffv_filf;           /* digital filter */
74
75
76/* prototypes of local routines */
77void ff_read_filter( char file[], int pos, FFT_RATFCT *filter, STATUS *status );
78static void ff_readcoeff( FILE *f, int *no, COMPLEX coeff[], STATUS *status );
79static long ff_next2pow( long l );
80static void ff_frqmul( long lth, COMPLEX dat[], REAL d_omega, int no_of_fil,
81        FFT_RATFCT fil[] );
82static void ff_filfmul( long lth, COMPLEX dat[], REAL d_omega,
83        FFT_FILFUNC *filf, STATUS *status );
84static void ff_attmul( long lth, COMPLEX dat[], REAL d_omega, REAL t, REAL nf );
85static void ff_tfvalue( COMPLEX *res, FFT_RATFCT *fct, REAL x );
86static void ff_filfvalue( COMPLEX *x, FFT_FILFUNC *filf, REAL f,
87        STATUS *status );
88static BOOLEAN ff_freq0ok( FFT_RATFCT *fil );
89static void ff_lintaper( float taper, long lth, COMPLEX dat[] );
90static void ff_costaper( float taper, long lth, COMPLEX dat[] );
91
92
93/*-------------------------------------------------------------------------*/
94
95
96
97void ff_filter_input( int listlth, char *flt_list[], int poslist[],
98        STATUS *status )
99
100/* reads a list of filters into memory.  If "poslist[i]" is negative,
101 * the i-th filter is inverted, that means poles become zeroes and
102 * zeroes become poles.
103 *
104 * parameters of routine
105 * int        listlth;      input; length of filter list
106 * char       *flt_list[];  input; filter list
107 * int        poslist[];    input; position list
108 * STATUS     *status;      output; return status
109 */
110{
111        /* local variables */
112        int      i;        /* counter */
113        int      f;        /* filter counter */
114        int      pos;      /* position counter */
115
116        /* executable code */
117
118        if  (listlth > MAXFILTER)  {
119                *status = FLE_TOOMANY;
120                err_setcontext( " ## number " ); err_setcontext_l( listlth );
121                return;
122        } /*endif*/
123
124        f = 0;
125        for  (i=0;i<listlth;i++)  {
126                if  (poslist[i] == 0)  {   /* read all filters of file */
127                        pos = 1;
128                        *status = FLE_NOERROR;
129                        while  (*status == FLE_NOERROR)  {
130                                if  (f == MAXFILTER)  {
131                                        no_of_fil_ffv = MAXFILTER;
132                                        *status = FLE_TOOMANY;
133                                        err_setcontext( " ## number " ); err_setcontext_l( no_of_fil_ffv );
134                                        return;
135                                } /*endif*/
136                                ff_read_filter( flt_list[i], pos++, fct_ffv+f, status );
137                                if  (*status == FLE_NOERROR)  f++;
138                        } /*endwhile*/
139                        if  (*status == FLE_EOFF)  *status = FLE_NOERROR;
140                } else {
141                        ff_read_filter( flt_list[i], poslist[i], fct_ffv+f, status );
142                        if  (*status == FLE_NOERROR)  f++;
143                } /*endif*/
144                if  (*status != FLE_NOERROR)  return;
145        } /*endfor*/
146        no_of_fil_ffv = f;
147
148        /* shorten zeroes in numerator and denominator of all filters read in */
149        ff_shorten_zeroes( fct_ffv, no_of_fil_ffv );
150
151} /* end of ff_filter_input */
152
153
154
155/*-------------------------------------------------------------------------*/
156
157
158
159void ff_read_filter( char file[], int pos, FFT_RATFCT *filter, STATUS *status )
160
161/* reads filter from filter file "file" at position number "pos"
162 *
163 * parameters of routine
164 * char       file[];   input; name of filter file
165 * int        pos;      input; position; if negative filter is inverted
166 * FFT_RATFCT *filter;  output; filter read from file
167 * STATUS     *status;  output; return status
168 */
169{
170        /* local variables */
171        FILE     *ff;                   /* filter file */
172        char     *filpath;              /* filter path */
173        int      pathcnt;               /* path counter */
174        char     str[BC_LONGSTRLTH+1];  /* scratch */
175        int      i;                     /* counter */
176        long     magic;                 /* magic longword */
177        int      id;                    /* store ID */
178
179        /* executable code */
180
181        /* open filter file */
182        ff = NULL;
183        for  (pathcnt=0;;pathcnt++) {
184                filpath = GpGetStringElem( cGpL_defpath_filter, pathcnt );
185                if  (filpath == NULL)  break;
186                if  ((strlen(file)+strlen(filpath)+1) > BC_LONGSTRLTH)  {
187                        *status = FLE_STROVFL;
188                        return;
189                } /*endif*/
190                strcpy( str, filpath );
191                strcat( str, "/" );
192                strcat( str, file );
193                strcat( str, SHC_DE_FFILT );
194                ff = sy_fopen( str, "r" );
195                if  (ff != NULL)  break;
196        } /*endfor*/
197        if  (ff == NULL)  {
198                *status = FLE_OPNREAD;
199                err_setcontext( " ## file " ); err_setcontext( str );
200                return;
201        } /*endif*/
202
203        /* read off comments */
204        do  {
205                if  (fgets(str,BC_LONGSTRLTH,ff) == NULL)  {
206                        *status = FLE_EOFF; fclose( ff ); return;
207                } /*endif*/
208        } while (*str == FILCOMMENTCH);
209
210        /* read magic longword */
211        i = sscanf( str, "%ld\n", &magic );
212        if  ((i != 1) || (magic != FILMAGIC))  {
213                err_setcontext( " ## file " ); err_setcontext( file );
214                *status = FLE_NOMAGIC; fclose( ff ); return;
215        } /*endif*/
216
217        /* count position */
218        for  (i=2;i<=Abs(pos);i++)  {
219                do  {
220                        if  (fgets(str,BC_LONGSTRLTH,ff) == NULL)  {
221                                err_setcontext( " ## file " ); err_setcontext( file );
222                                *status = FLE_EOFF; fclose( ff ); return;
223                        } /*endif*/
224                } while (*str != FILTERMCH);
225        } /*endfor*/
226
227        /* check store ID */
228        i = fscanf( ff, "%d\n", &id );
229        if  ((i != 1) || (id != FILID_TFRAT))  {
230                err_setcontext( " ## file " ); err_setcontext( file );
231                *status = FLE_NORATFCT; fclose( ff ); return;
232        } /*endif*/
233
234        /* read normalisation */
235        if  (fscanf( ff, "%e\n", &(filter->norm) ) != 1)  {
236                err_setcontext( " ## file " ); err_setcontext( file );
237                *status = FLE_FREAD; fclose( ff ); return;
238        } /*endif*/
239        if  (pos < 0)  filter->norm = 1.0 / filter->norm;
240
241        if  (pos > 0)  {
242                ff_readcoeff( ff, &(filter->no_of_zeroes), filter->zero, status );
243                if  (*status != FLE_NOERROR)  return;
244                ff_readcoeff( ff, &(filter->no_of_poles), filter->pole, status );
245                if  (*status != FLE_NOERROR)  return;
246        } else {
247                ff_readcoeff( ff, &(filter->no_of_poles), filter->pole, status );
248                if  (*status != FLE_NOERROR)  return;
249                ff_readcoeff( ff, &(filter->no_of_zeroes), filter->zero, status );
250                if  (*status != FLE_NOERROR)  return;
251        } /*endif*/
252
253        fclose( ff );
254
255} /* end of ff_read_filter */
256
257
258
259/*------------------------------------------------------------------------*/
260
261
262
263static void ff_readcoeff( FILE *f, int *no, COMPLEX coeff[], STATUS *status )
264
265/* reads complex coefficients from file
266 *
267 * parameters of routine
268 * FILE       *f;       input; file pointer
269 * int        *no;      output; number of coefficients
270 * COMPLEX    coeff[];  output; coefficients read
271 * STATUS     *status;  output; return status
272 */
273{
274        /* local variables */
275        int      i;        /* counter */
276
277        /* executable code */
278
279        if  (fscanf( f, "%d\n", no ) != 1)  {
280                *status = FLE_FREAD; fclose( f ); return;
281        } /*endif*/
282        if  (*no > FFC_MAXDEGREE)  {
283                *status = FLE_DEGOVFL; fclose( f ); return;
284        } /*endif*/
285        for  ( i = 0; i < *no; i++ )  {
286                if  (fscanf( f, "(%e,%e)\n", &(coeff[i].re), &(coeff[i].im) ) != 2)  {
287                        *status = FLE_FREAD; fclose( f ); return;
288                } /*endif*/
289        } /*endfor*/
290
291} /* end of ff_readcoeff */
292
293
294
295/*-------------------------------------------------------------------------*/
296
297
298
299void ff_filfunc_input( char file[], FFT_FILFUNC *filf, STATUS *status )
300
301/* reads digital filter function to specified filter structure "filf" or
302 * into internal variable if "filf" is NULL
303 *
304 * parameters of routine
305 * char       file[];         input; name of filter file
306 * FFT_FILFUNC *filf;         output; output structure or NULL
307 * STATUS     *status;        output; return status
308 */
309{
310        /* local variables */
311        FFT_FILFUNC *lfilf;             /* pointer to filter structure */
312        FILE     *ff;                   /* pointer to filter file */
313        char     *filpath;              /* path to filter */
314        int      pathcnt;               /* path counter */
315        char     str[BC_LONGSTRLTH+1];  /* scratch string */
316        long     magic;                 /* magic number */
317        int      id;                    /* store ID */
318        long     i;                     /* counter */
319
320        /* executable code */
321
322        lfilf = (filf == NULL) ? &ffv_filf : filf;
323
324        /* open filter file */
325        ff = NULL;
326        for  (pathcnt=0;;pathcnt++)  {
327                filpath = GpGetStringElem( cGpL_defpath_filter, pathcnt );
328                if  (filpath == NULL)  break;
329                if  ((strlen(file)+strlen(filpath)+1) > BC_LONGSTRLTH)  {
330                        *status = FLE_STROVFL;
331                        return;
332                } /*endif*/
333                strcpy( str, filpath );
334                strcat( str, "/" );
335                strcat( str, file );
336                strcat( str, SHC_DE_DFILT );
337                ff = sy_fopen( str, "r" );
338                if  (ff != NULL)  break;
339        } /*endif*/
340        if  (ff == NULL)  {
341                *status = FLE_OPNREAD;
342                err_setcontext( " ## file " ); err_setcontext( str );
343                return;
344        } /*endif*/
345
346        /* read off comments */
347        do  {
348                if  (fgets(str,BC_LONGSTRLTH,ff) == NULL)  {
349                        err_setcontext( " ## file " ); err_setcontext( file );
350                        *status = FLE_EOFF; fclose( ff ); return;
351                } /*endif*/
352        } while (*str == FILCOMMENTCH);
353
354        /* read magic longword */
355        i = sscanf( str, "%ld\n", &magic );
356        if  ((i != 1) || (magic != FILMAGIC))  {
357                err_setcontext( " ## file " ); err_setcontext( file );
358                *status = FLE_NOMAGIC; fclose( ff ); return;
359        } /*endif*/
360
361        /* check store ID */
362        i = fscanf( ff, "%d\n", &id );
363        if  ((i != 1) || (id != FILID_FILFUNC))  {
364                err_setcontext( " ## file " ); err_setcontext( file );
365                *status = FLE_NOFILFUNC; fclose( ff ); return;
366        } /*endif*/
367
368        /* free previous filter */
369        if  (filf == NULL && ffv_filf.lth != 0)
370                sy_deallocmem( ffv_filf.frq );
371
372        i = fscanf( ff, "%ld\n", &(lfilf->lth) );
373        if  (i != 1)  {
374                err_setcontext( " ## file " ); err_setcontext( file );
375                *status = FLE_READERR;
376                fclose( ff );
377                lfilf->lth = 0;
378                return;
379        } /*endif*/
380
381        /* allocate memory */
382        lfilf->frq = (REAL *)sy_allocmem( (lfilf->lth)*3L,
383                (int)sizeof(REAL), status );
384        if  (Severe(status))  {
385                fclose( ff );
386                lfilf->lth = 0;
387                return;
388        } /*endif*/
389        lfilf->mod = lfilf->frq + lfilf->lth;
390        lfilf->phase = lfilf->mod + lfilf->lth;
391
392        for  (i=0; i<(lfilf->lth); i++)  {
393                fscanf( ff, "%f %f %f\n", (lfilf->frq)+i, (lfilf->mod)+i,
394                        (lfilf->phase)+i );
395                lfilf->frq[i] *= 2.0*BC_PI;   /* make omega from f */
396        } /*endfor*/
397
398        fclose( ff );
399
400} /* end of ff_filfunc_input */
401
402
403
404/*-------------------------------------------------------------------------*/
405
406
407
408void ff_filter( BOOLEAN filf, SAMPLE src[], long lth, REAL dt,
409        float taper, SAMPLE dst[], STATUS *status )
410
411/* filters array "src" with all filters read in.  The result is
412 * stored in "dst".
413 *
414 * parameters of routine
415 * BOOLEAN    filf;        input; digital filter (TRUE) or poles-zeroes
416 * SAMPLE     src[];       input; input trace
417 * long       lth;         input; length of traces
418 * REAL       dt;          input; sample distance in sec
419 * float      taper;       input; start of taper window [0..1]
420 * SAMPLE     dst[];       output; filtered trace
421 * STATUS     *status;     output; return status
422 */
423{
424        /* local variables */
425        long     serieslth;    /* length of FFT array */
426        REAL     *fftarr;      /* pointer to complex FFT array */
427        REAL     *c;           /* moving pointer */
428        REAL     *r;           /* moving pointer */
429        REAL     norm;         /* normalisation */
430
431        /* executable code */
432
433        if  (lth <= 0)  {
434                *status = FLE_ZEROLTH;
435                return;
436        } else if  (no_of_fil_ffv == 0 && !filf)  {
437                *status = FLE_NOFILTER;
438                return;
439        } else if  (ffv_filf.lth == 0 && filf)  {
440                *status = FLE_NOFILTER;
441                return;
442        } /*endif*/
443
444        /* allocate memory */
445        serieslth = ff_next2pow( lth );
446        fftarr = (REAL *)sy_allocmem( serieslth, (int)sizeof(REAL), status );
447        if  (*status != FLE_NOERROR)  return;
448
449        /* copy input data to FFT array */
450        for  ( r=src, c=fftarr; c<(fftarr+lth); *c++ = *r++ )  {}
451        for  ( c=fftarr+lth; c<(fftarr+serieslth); *c++ = 0.0 )  {}
452
453        /* perform FFT */
454        nr_realft( fftarr-1, serieslth/2, 1 );
455        for  ( c=fftarr+3; c<(fftarr+serieslth); c += 2 )
456                *c = -(*c);
457
458        /* apply filter(s) */
459        if  (filf)  {
460                ff_filfmul( serieslth/2, (COMPLEX *)fftarr,
461                        2.0*SHC_PI/((float)serieslth*dt), &ffv_filf, status );
462                if  (Severe(status))  {
463                        sy_deallocmem( fftarr );
464                        return;
465                } /*endif*/
466        } else {
467                ff_frqmul( serieslth/2, (COMPLEX *)fftarr,
468                        2.0*SHC_PI/((float)serieslth*dt), no_of_fil_ffv, fct_ffv );
469        } /*endif*/
470
471        if  (taper >= 0.0 && taper < 1.0)
472                ff_costaper( taper, serieslth/2, (COMPLEX *)fftarr );
473
474        /* back transformation */
475        for  ( c=fftarr+3; c<(fftarr+serieslth); c += 2 )
476                *c = -(*c);
477        nr_realft( fftarr-1, serieslth/2, -1 );
478
479        /* copy results to output array */
480        norm = 2.0 / (float)serieslth;
481        for  ( r=dst, c=fftarr; c<(fftarr+lth); *dst++ = *c++ * norm )  {}
482
483        /* free memory */
484        sy_deallocmem( fftarr );
485
486} /* end of ff_filter */
487
488
489
490/*-------------------------------------------------------------------------*/
491
492
493
494static void ff_frqmul( long lth, COMPLEX dat[], REAL d_omega,
495        int no_of_fil, FFT_RATFCT fil[] )
496
497/* applies filter(s) to "dat" array.  Multiplies the whole array
498 * by a filter function "fil".  The array is assumed to be the
499 * positive half of a FFT output.  The imaginary part of the zeroth
500 * complex number is assumed to be the (real) frequency value at
501 * the nyquist frequency.
502 *
503 * parameters of routine
504 * long       lth;        input; length of array to be filtered
505 * COMPLEX    dat[];      modify; array to be filtered
506 * REAL       d_omega;    input; angular frequency steps
507 * int        no_of_fil;  input; number of filters
508 * FFT_RATFCT fil[];      input; filters
509 */
510{
511        /* local variables */
512        int      f;           /* filter counter */
513        long     i;           /* counter */
514        long     start;       /* start value of counter */
515        COMPLEX  *c;          /* moving pointer */
516        COMPLEX  temp, tfval; /* scratch */
517        COMPLEX  nyquist;     /* value at nyquist frequency */
518
519        /* executable code */
520
521        nyquist.re = dat[0].im;
522        nyquist.im = 0.0;
523        dat[0].im = 0.0;
524
525        for  (f=0; f<no_of_fil; f++)  {
526                if  (ff_freq0ok(fil+f))  {
527                        start = 0;
528                        c = dat;
529                } else {
530                        start = 1;
531                        dat->re = 0.0;
532                        dat->im = 0.0;
533                        c = dat+1;
534                } /*endif*/
535                for  (i=start; i<lth; i++)  {
536                        ff_tfvalue( &tfval, fil+f, (float)i*d_omega );
537                        mt_mulcmplx( &temp, c, &tfval );
538                        c->re = temp.re;
539                        (c++)->im = temp.im;
540                } /*endfor*/
541                ff_tfvalue( &tfval, fil+f, (float)lth*d_omega );
542                mt_mulcmplx( &temp, &nyquist, &tfval );
543                nyquist = temp;
544        } /*endfor*/
545
546        dat[0].im = nyquist.re;
547
548} /* end of ff_frqmul */
549
550
551
552/*-------------------------------------------------------------------------*/
553
554
555
556static void ff_filfmul( long lth, COMPLEX dat[], REAL d_omega,
557        FFT_FILFUNC *filf, STATUS *status )
558
559/* applies digital filter to "dat" array.  Multiplies the whole array
560 * by a filter function "fil".  The array is assumed to be the
561 * positive half of a FFT output.  The imaginary part of the zeroth
562 * complex number is assumed to be the (real) frequency value at
563 * the nyquist frequency.
564 *
565 * parameters of routine
566 * long       lth;        input; length of array to be filtered
567 * COMPLEX    dat[];      modify; array to be filtered
568 * REAL       d_omega;    input; angular frequency steps
569 * FFT_FILFUNC *filf;     input; digital filter
570 * STATUS     *status;    output; return status
571 */
572{
573        /* local variables */
574        long     i;           /* counter */
575        COMPLEX  *c;          /* moving pointer */
576        COMPLEX  temp, tfval; /* scratch */
577        COMPLEX  nyquist;     /* value at nyquist frequency */
578
579        /* executable code */
580
581        nyquist.re = dat[0].im;
582        nyquist.im = 0.0;
583        dat[0].im = 0.0;
584
585        c = dat;
586        for  (i=0; i<lth; i++)  {
587                ff_filfvalue( &tfval, filf, (float)i*d_omega, status );
588                if  (Severe(status))  return;
589                mt_mulcmplx( &temp, c, &tfval );
590                c->re = temp.re;
591                (c++)->im = temp.im;
592        } /*endfor*/
593        ff_filfvalue( &tfval, filf, (float)lth*d_omega, status );
594        if  (Severe(status))  return;
595        mt_mulcmplx( &temp, &nyquist, &tfval );
596        nyquist = temp;
597
598        dat[0].im = nyquist.re;
599
600} /* end of ff_filfmul */
601
602
603
604/*-------------------------------------------------------------------------*/
605
606
607
608static void ff_filfvalue( COMPLEX *x, FFT_FILFUNC *filf, REAL f,
609        STATUS *status )
610
611/* computes value of digital filter "filf" at frequency "f" by
612 * linear interpolation
613 *
614 * parameters of routine
615 * COMPLEX    *x;        output; computed value
616 * FFT_FILFUNC *filf;    input; digital filter
617 * REAL       f;         input; frequency
618 * STATUS     *status;   output; return status
619 */
620{
621        /* local variables */
622        long     maxidx;    /* maximum index */
623        long     idx;       /* index of lower frequency */
624        REAL     m, p;      /* modulus and phase */
625        REAL     frac;      /* fraction for interpolation */
626        REAL     p1, p2;    /* phase values at grid points */
627
628        /* executable code */
629
630        maxidx = filf->lth-1;
631        if  (filf->frq[0] > f  ||  filf->frq[maxidx] < f)  {
632                *status = FLE_FILFRANGE;
633                return;
634        } /*endif*/
635
636        idx = 1;
637        while  (filf->frq[idx] < f)
638                idx++;
639        idx--;
640
641        /* interpolate modulus and phase */
642        frac = (filf->mod[idx+1] - filf->mod[idx])
643                / (filf->frq[idx+1] - filf->frq[idx]);
644        m = filf->mod[idx] + (f - filf->frq[idx])*frac;
645
646        /* phase may contain a 360 deg wrap */
647        p1 = filf->phase[idx];
648        p2 = filf->phase[idx+1];
649        if  (fabs(p1-p2) > 180.0)  {
650                if  (p1 < p2)  {
651                        p1 += 360.0;
652                } else {
653                        p2 += 360.0;
654                } /*endif*/
655        } /*endif*/
656        frac = (p2 - p1)
657                / (filf->frq[idx+1] - filf->frq[idx]);
658        p = p1 + (f - filf->frq[idx])*frac;
659        p /= SHC_RAD_TO_DEG;
660
661        x->re = m*cos(p);
662        x->im = m*sin(p);
663
664} /* end of ff_filfvalue */
665
666
667
668/*-------------------------------------------------------------------------*/
669
670
671
672void ff_attenuate( SAMPLE src[], long lth, REAL dt, REAL att,
673        SAMPLE dst[], STATUS *status )
674
675/* attenuates array "src" with t* of "att".  The result is
676 * stored in "dst".
677 *
678 * parameters of routine
679 * SAMPLE     src[];       input; input trace
680 * long       lth;         input; length of traces
681 * REAL       dt;          input; sample distance in sec
682 * REAL       att;         input; attenuation (t* in sec)
683 * SAMPLE     dst[];       output; filtered trace
684 * STATUS     *status;     output; return status
685 */
686{
687        /* local variables */
688        long     serieslth;    /* length of FFT array */
689        REAL     *fftarr;      /* pointer to complex FFT array */
690        REAL     *c;           /* moving pointer */
691        REAL     *r;           /* moving pointer */
692        REAL     norm;         /* normalisation */
693
694        /* executable code */
695
696        if  (lth <= 0)  {
697                *status = FLE_ZEROLTH;
698                return;
699        } /*endif*/
700
701        /* allocate memory */
702        serieslth = ff_next2pow( lth );
703        fftarr = (REAL *)sy_allocmem( serieslth, (int)sizeof(REAL), status );
704        if  (*status != FLE_NOERROR)  return;
705
706        /* copy input data to FFT array */
707        for  ( r=src, c=fftarr; c<(fftarr+lth); *c++ = *r++ )  {}
708        for  ( c=fftarr+lth; c<(fftarr+serieslth); *c++ = 0.0 )  {}
709
710        /* perform FFT */
711        nr_realft( fftarr-1, serieslth/2, 1 );
712        for  ( c=fftarr+3; c<(fftarr+serieslth); c += 2 )
713                *c = -(*c);
714
715        /* attenuate */
716        ff_attmul( serieslth/2, (COMPLEX *)fftarr,
717                2.0*SHC_PI/((float)serieslth*dt), att, SHC_PI/dt );
718
719        /* back transformation */
720        for  ( c=fftarr+3; c<(fftarr+serieslth); c += 2 )
721                *c = -(*c);
722        nr_realft( fftarr-1, serieslth/2, -1 );
723
724        /* copy results to output array */
725        norm = 2.0 / (float)serieslth;
726        for  ( c=fftarr; c<(fftarr+lth); *dst++ = *c++ * norm )  {}
727
728        /* free memory */
729        sy_deallocmem( fftarr );
730
731} /* end of ff_attenuate */
732
733
734
735/*-------------------------------------------------------------------------*/
736
737
738
739void ff_hilbert( SAMPLE src[], long lth, SAMPLE dst[], STATUS *status )
740
741/* computes Hilbert transformation of "src"
742 *
743 * parameters of routine
744 * SAMPLE     src[];       input; input trace
745 * long       lth;         input; length of traces
746 * SAMPLE     dst[];       output; filtered trace
747 * STATUS     *status;     output; return status
748 */
749{
750        /* local variables */
751        long     serieslth;    /* length of FFT array */
752        REAL     *fftarr;      /* pointer to complex FFT array */
753        REAL     *c;           /* moving pointer */
754        REAL     *r;           /* moving pointer */
755        REAL     tmp;          /* scratch */
756        REAL     norm;         /* normalisation of back transformation */
757
758        /* executable code */
759
760        if  (lth <= 0)  {
761                *status = FLE_ZEROLTH;
762                return;
763        } /*endif*/
764
765        /* allocate memory */
766        serieslth = ff_next2pow( lth );
767        fftarr = (REAL *)sy_allocmem( serieslth, (int)sizeof(REAL), status );
768        if  (*status != FLE_NOERROR)  return;
769
770        /* copy input data to FFT array */
771        for  ( r=src, c=fftarr; c<(fftarr+lth); *c++ = *r++ )  {}
772        for  ( c=fftarr+lth; c<(fftarr+serieslth); *c++ = 0.0 )  {}
773
774        /* perform FFT */
775        nr_realft( fftarr-1, serieslth/2, 1 );
776        /* for  ( c=fftarr+3; c<(fftarr+serieslth); c += 2 )
777                *c = -(*c); */
778
779        for  (c=fftarr+2; c<fftarr+serieslth; c += 2)  {
780                tmp = *c;
781                *c = *(c+1);
782                *(c+1) = -tmp;
783        } /*endfor*/
784        *fftarr = 0.;
785        *(fftarr+1) = 0.;
786
787        /* back transformation */
788        /* for  ( c=fftarr+3; c<(fftarr+serieslth); c += 2 )
789                *c = -(*c); */
790        nr_realft( fftarr-1, serieslth/2, -1 );
791
792        /* copy results to output array */
793        norm = 2.0 / (float)serieslth;
794        for  ( c=fftarr; c<(fftarr+lth); *dst++ = norm * (*c++) )  {}
795
796        /* free memory */
797        sy_deallocmem( fftarr );
798
799} /* end of ff_hilbert */
800
801
802
803/*-------------------------------------------------------------------------*/
804
805
806
807void ff_hilbphase( int mode, SAMPLE src[], long lth, SAMPLE dst[], STATUS *status )
808
809/* computes Hilbert transformation of "src", uses this as imaginary
810 * part of the input function and returns the phase in deg of this
811 * complex value.
812 *
813 * parameters of routine
814 * int        mode;        input; mode of computation
815 * SAMPLE     src[];       input; input trace
816 * long       lth;         input; length of traces
817 * SAMPLE     dst[];       output; filtered trace
818 * STATUS     *status;     output; return status
819 */
820{
821        /* local variables */
822        long     serieslth;    /* length of FFT array */
823        REAL     *fftarr;      /* pointer to complex FFT array */
824        REAL     *c;           /* moving pointer */
825        REAL     *r;           /* moving pointer */
826        REAL     tmp;          /* scratch */
827        REAL     norm;         /* normalisation of back transformation */
828
829        /* executable code */
830
831        if  (lth <= 0)  {
832                *status = FLE_ZEROLTH;
833                return;
834        } /*endif*/
835
836        /* allocate memory */
837        serieslth = ff_next2pow( lth );
838        fftarr = (REAL *)sy_allocmem( serieslth, (int)sizeof(REAL), status );
839        if  (*status != FLE_NOERROR)  return;
840
841        /* copy input data to FFT array */
842        for  ( r=src, c=fftarr; c<(fftarr+lth); *c++ = *r++ )  {}
843        for  ( c=fftarr+lth; c<(fftarr+serieslth); *c++ = 0.0 )  {}
844
845        /* perform FFT */
846        nr_realft( fftarr-1, serieslth/2, 1 );
847        /* for  ( c=fftarr+3; c<(fftarr+serieslth); c += 2 )
848                *c = -(*c); */
849
850        for  (c=fftarr+2; c<fftarr+serieslth; c += 2)  {
851                tmp = *c;
852                *c = *(c+1);
853                *(c+1) = -tmp;
854        } /*endfor*/
855        *fftarr = 0.;
856        *(fftarr+1) = 0.;
857
858        /* back transformation */
859        /* for  ( c=fftarr+3; c<(fftarr+serieslth); c += 2 )
860                *c = -(*c); */
861        nr_realft( fftarr-1, serieslth/2, -1 );
862
863        /* compute phase of complex number <src> + i*<fft> */
864        norm = 2.0 / (float)serieslth;
865        for  ( r=src, c=fftarr; c<(fftarr+lth); c++, r++)  {
866                if  (mode == FFC_GET_PHASE_I)  {
867                        *dst++ = sin( atan2( norm*(*c), *r ) );
868                } else if  (mode == FFC_GET_PHASE_R)  {
869                        *dst++ = cos( atan2( norm*(*c), *r ) );
870                } else {
871                        *dst++ = atan2( norm*(*c), *r ) / SHC_PI * 180.0;
872                } /*endif*/
873        } /*endfor*/
874
875        /* free memory */
876        sy_deallocmem( fftarr );
877
878} /* end of ff_hilbphase */
879
880
881
882/*-------------------------------------------------------------------------*/
883
884
885
886void ff_mindelay( SAMPLE src[], long lth, long offset, BOOLEAN ac,
887        SAMPLE dst[], STATUS *status )
888
889/* transforms "src" into a minimum delay wavelet
890 *
891 * parameters of routine
892 * SAMPLE     src[];       input; input trace
893 * long       lth;         input; length of traces
894 * long       offset;      input; number of offset samples
895 * BOOLEAN    ac;          input; input is autocorrelation
896 * SAMPLE     dst[];       output; minimum delay wavelet trace
897 * STATUS     *status;     output; return status
898 */
899{
900        /* local variables */
901        long     serieslth;    /* length of FFT array */
902        REAL     *fftarr;      /* pointer to complex FFT array */
903        REAL     *c;           /* moving pointer */
904        REAL     *r;           /* moving pointer */
905        REAL     *phase;       /* phase spectrum */
906        REAL     *lna;         /* logarithm of amplitude */
907        REAL     norm;         /* normalisation of back transformation */
908        REAL     shift;        /* shift phase */
909
910        /* executable code */
911
912        if  (lth <= 0)  {
913                *status = FLE_ZEROLTH;
914                return;
915        } /*endif*/
916
917        /* allocate memory */
918        serieslth = ff_next2pow( lth );
919        fftarr = (REAL *)sy_allocmem( serieslth, (int)sizeof(REAL), status );
920        if  (*status != FLE_NOERROR)  return;
921        lna = (REAL *)sy_allocmem( serieslth, (int)sizeof(REAL), status );
922        if  (*status != FLE_NOERROR)  {
923                sy_deallocmem( fftarr );
924                return;
925        } /*endif*/
926        phase = lna + (serieslth/2);
927
928        shift = -(REAL)offset * 2.0*SHC_PI/(REAL)serieslth;
929
930        /* copy input data to FFT array */
931        for  ( r=src, c=fftarr; c<(fftarr+lth); *c++ = *r++ )  {}
932        for  ( c=fftarr+lth; c<(fftarr+serieslth); *c++ = 0.0 )  {}
933
934        /* perform FFT */
935        nr_realft( fftarr-1, serieslth/2, 1 );
936        for  ( c=fftarr+3; c<(fftarr+serieslth); c += 2 )
937                *c = -(*c);
938
939        /* get amplitude spectrum and compute logarithm */
940        for  (r=fftarr,c=lna; r<fftarr+serieslth; r += 2,c++)  {
941                *r = sqrt( (*r)*(*r) + (*(r+1))*(*(r+1)) );
942                if  (ac)  *r = sqrt( *r );   /* autocorr. has squared amplitudes */
943                *c = (*r > 0.) ? log( *r ) : 0.;
944        } /*endif*/
945        /* phase spectrum is Hilbert transform of ln(A) */
946        ff_hilbert( lna, serieslth/2, phase, status );
947        if  (Severe(status))  {
948                sy_deallocmem( fftarr );
949                sy_deallocmem( lna );
950                return;
951        } /*endif*/
952        /* get minimum delay spectrum */
953        for  (r=fftarr,c=phase; r<fftarr+serieslth; r += 2,c++)  {
954                *c += (REAL)(c-phase)*shift;
955                *(r+1) = *r * sin(*c);  /* imaginary part */
956                *r *= cos(*c);          /* real part */
957        } /*endif*/
958
959        /* back transformation */
960        for  ( c=fftarr+3; c<(fftarr+serieslth); c += 2 )
961                *c = -(*c);
962        nr_realft( fftarr-1, serieslth/2, -1 );
963
964        /* copy results to output array */
965        norm = 2.0 / (float)serieslth;
966        for  ( c=fftarr; c<(fftarr+lth); *dst++ = norm * (*c++) )  {}
967
968        /* free memory */
969        sy_deallocmem( fftarr );
970        sy_deallocmem( lna );
971
972} /* end of ff_mindelay */
973
974
975
976/*-------------------------------------------------------------------------*/
977
978
979
980void ff_specdiv( SAMPLE f1[], SAMPLE f2[], long lth, REAL dt,
981        REAL wlevel, REAL alpha, REAL offset, SAMPLE res[], STATUS *status )
982
983/* divides spectrum of f1 by spectrum of f2 and stores the result
984 * in res.  The formula is:
985 *    res[i] = f1[i]*f2^[i]/phi[i] * G[i],  where
986 *    phi[i] = max{f2[i]*f2^[i], wlevel*max[f2[k]*f2^[k]]}
987 *    G[i] = exp( -w[i]*w[i]/(4*alpha*alpha) )
988 *    w[i]:   circular frequency
989 *    ^:      complex conjugate
990 *
991 * parameters of routine
992 * SAMPLE     f1[], f2[];     input; input wavelets
993 * long       lth;            input; length of traces
994 * REAL       wlevel;         input; water level
995 * REAL       alpha;          input; width of gauss peak
996 * REAL       offset;         input; time offset of output trace
997 * SAMPLE     res[];          output; results trace
998 * STATUS     *status;        output; return status
999 */
1000{
1001        /* local variables */
1002        long     serieslth;         /* length of FFT arrays */
1003        long     i;                 /* counter */
1004        REAL     *ff1, *ff2, *ff3;  /* pointers to output arrays */
1005        REAL     *p1, *p2, *p3;     /* moving pointers */
1006        REAL     norm;              /* normalization */
1007        REAL     d_omega;           /* frequency step */
1008        REAL     maxdiv;            /* maximum of trace f2 */
1009        REAL     shift;             /* time shift */
1010        REAL     tmp, tmp2, x1, x2; /* scratch */
1011        REAL     shiftphase;        /* shift phase */
1012
1013        /* executable code */
1014
1015        if  (lth <= 0)  {
1016                *status = FLE_ZEROLTH;
1017                return;
1018        } /*endif*/
1019
1020        /* allocate memory */
1021        serieslth = ff_next2pow( lth );
1022        ff1 = (REAL *)sy_allocmem( serieslth, (int)sizeof(REAL), status );
1023        if  (Severe(status))  return;
1024        ff2 = (REAL *)sy_allocmem( serieslth, (int)sizeof(REAL), status );
1025        if  (Severe(status))  {sy_deallocmem(ff1); return;}
1026        ff3 = (REAL *)sy_allocmem( serieslth, (int)sizeof(REAL), status );
1027        if  (Severe(status))  {sy_deallocmem(ff1); sy_deallocmem(ff2); return;}
1028
1029        d_omega = 2.0*SHC_PI/((float)serieslth*dt);
1030        alpha *= 4.0*alpha;
1031        shift = offset/dt * 2.0*SHC_PI/(REAL)serieslth;
1032
1033        /* copy input arrays */
1034        for  ( p3=f1, p1=ff1; p1<(ff1+lth); *p1++ = *p3++ )  {}
1035        for  ( p1=ff1+lth; p1<(ff1+serieslth); *p1++ = 0.0 )  {}
1036        for  ( p3=f2, p1=ff2; p1<(ff2+lth); *p1++ = *p3++ )  {}
1037        for  ( p1=ff2+lth; p1<(ff2+serieslth); *p1++ = 0.0 )  {}
1038
1039        /* perform FFT */
1040        nr_realft( ff1-1, serieslth/2, 1 );
1041        nr_realft( ff2-1, serieslth/2, 1 );
1042
1043        /* find maximum in divisor */
1044        p2 = ff2+2;
1045        maxdiv = (*ff2)*(*ff2);
1046        for  (i=1; i<(serieslth/2); i++)  {
1047                tmp = (*p2)*(*p2) + (*(p2+1))*(*(p2+1));
1048                if  (tmp > maxdiv)  maxdiv = tmp;
1049                p2 += 2;
1050        } /*endif*/
1051        maxdiv *= wlevel;
1052
1053        /* compute result */
1054        *ff3 = (*ff1)*(*ff2);
1055        tmp = (*ff2)*(*ff2);
1056        *ff3 /= (tmp < maxdiv) ? maxdiv : tmp;
1057        *(ff3+1) = (*(ff1+1))*(*(ff2+1));
1058        tmp = (*(ff2+1))*(*(ff2+1));
1059        *(ff3+1) /= (tmp < maxdiv) ? maxdiv : tmp;
1060        p1 = ff1+2;  p2 = ff2+2;  p3 = ff3+2;
1061        for  (i=1; i<(serieslth/2); i++)  {
1062                *p3 = re_mul(*p1,*(p1+1),*p2,-(*(p2+1)));
1063                *(p3+1) = im_mul(*p1,*(p1+1),*p2,-(*(p2+1)));
1064                if  (shift != 0.)  {
1065                        shiftphase = (REAL)i*shift;
1066                        tmp = cos( shiftphase );
1067                        tmp2 = sin( shiftphase );
1068                        x1 = re_mul(*p3,*(p3+1),tmp,tmp2);
1069                        x2 = im_mul(*p3,*(p3+1),tmp,tmp2);
1070                        *p3 = x1;
1071                        *(p3+1) = x2;
1072                } /*endif*/
1073                tmp = (*p2)*(*p2) + (*(p2+1))*(*(p2+1));
1074                if  (tmp < maxdiv)  tmp = maxdiv;
1075                *p3 /= tmp;
1076                *(p3+1) /= tmp;
1077                tmp = (float)i*d_omega;
1078                tmp = exp(-tmp*tmp/alpha);
1079                *p3 *= tmp;
1080                *(p3+1) *= tmp;
1081                p1 += 2;
1082                p2 += 2;
1083                p3 += 2;
1084        } /*endif*/
1085
1086        /* back transformation */
1087        nr_realft( ff3-1, serieslth/2, -1 );
1088
1089        /* copy results to output array */
1090        norm = 2.0 / (float)serieslth;
1091        for  ( p3=ff3; p3<(ff3+lth); *res++ = norm * (*p3++) )  {}
1092
1093        sy_deallocmem( ff1 );
1094        sy_deallocmem( ff2 );
1095        sy_deallocmem( ff3 );
1096
1097} /* end of ff_specdiv */
1098
1099
1100
1101/*-------------------------------------------------------------------------*/
1102
1103
1104
1105static long ff_next2pow( long l )
1106
1107/* returns next power of 2
1108 *
1109 * parameter of routine
1110 * long      l;      input; input number
1111 */
1112{
1113        /* local variables */
1114        long     next;     /* next power of 2 */
1115
1116        /* executable code */
1117
1118        next = 1;
1119        while  (next < l)
1120                next *= 2;
1121
1122        return next;
1123
1124} /* end of ff_next2pow */
1125
1126
1127
1128/*-------------------------------------------------------------------------*/
1129
1130
1131
1132static void ff_attmul( long lth, COMPLEX dat[], REAL d_omega, REAL t, REAL nf )
1133
1134/* attenuates "dat"-array with t* of "t" sec
1135 *
1136 * parameters of routine
1137 * long       lth;        input; length of array to be attenuated
1138 * COMPLEX    dat[];      modify; array to be attenuated
1139 * REAL       d_omega;    input; step size in omega
1140 * REAL       t;          input; t* in sec
1141 * REAL       nf;         input; nyquist frequency
1142 */
1143{
1144        /* local variables */
1145        REAL     omega;       /* current frequency */
1146        long     i;           /* counter */
1147        COMPLEX  *c;          /* moving pointer */
1148        COMPLEX  temp, eval;  /* scratch */
1149        COMPLEX  nyquist;     /* value at nyquist frequency */
1150
1151        /* executable code */
1152
1153        nyquist.re = dat[0].im;
1154        nyquist.im = 0.0;
1155        dat[0].im = 0.0;
1156
1157        c = dat + 1;
1158        for  (i=1; i<lth; i++)  {
1159                omega = (float)i * d_omega;
1160                mt_imexp( &temp, ((omega*t / SHC_PI) * log(omega/nf)) );
1161                mt_rmulcmplx( &eval, &temp, exp(-omega*t/2.0) );
1162                mt_mulcmplx( &temp, c, &eval );
1163                c->re = temp.re;
1164                (c++)->im = temp.im;
1165        } /*endfor*/
1166        omega = (float)lth * d_omega;
1167        mt_imexp( &temp, ((omega*t / SHC_PI) * log(omega/nf)) );
1168        mt_rmulcmplx( &eval, &temp, exp(-omega*t/2.0) );
1169        mt_mulcmplx( &temp, &nyquist, &eval );
1170        nyquist = temp;
1171
1172        dat[0].im = nyquist.re;
1173
1174} /* end of ff_attmul */
1175
1176
1177
1178/*-------------------------------------------------------------------------*/
1179
1180
1181
1182static void ff_tfvalue( COMPLEX *res, FFT_RATFCT *fct, REAL x )
1183
1184/* evaluates function at point "x"
1185 *
1186 * parameters of routine
1187 * COMPLEX    *res;        output; value of function at point "x"
1188 * FFT_RATFCT *fct;        input; function to be evaluated
1189 * REAL       x;           input; argument
1190 */
1191{
1192        /* local variables */
1193        int      degree;    /* max of no_of_poles & no_of_zeroes */
1194        int      i;           /* degree counter */
1195        COMPLEX  temp, tmp2;  /* scratch */
1196
1197        /* executable code */
1198
1199        degree = (fct->no_of_poles > fct->no_of_zeroes) ?
1200                fct->no_of_poles : fct->no_of_zeroes;
1201
1202        res->re = 1.0;
1203        res->im = 0.0;
1204
1205        for  (i=0; i<degree; i++)  {
1206                if  (i < fct->no_of_zeroes)  {
1207                        tmp2.re = - fct->zero[i].re;
1208                        tmp2.im = x - fct->zero[i].im;
1209                        mt_mulcmplx( &temp, res, &tmp2 );
1210                        *res = temp;
1211                } /*endif*/
1212                if  (i < fct->no_of_poles)  {
1213                        tmp2.re = - fct->pole[i].re;
1214                        tmp2.im = x - fct->pole[i].im;
1215                        mt_divcmplx( &temp, res, &tmp2 );
1216                        *res = temp;
1217                } /*endif*/
1218        } /*endfor*/
1219
1220        res->re *= fct->norm;
1221        res->im *= fct->norm;
1222
1223} /* end of ff_tfvalue */
1224
1225
1226
1227/*-------------------------------------------------------------------------*/
1228
1229
1230
1231static BOOLEAN ff_freq0ok( FFT_RATFCT *fil )
1232
1233/* checks whether or not filter "fil" exists at frequency zero
1234 *
1235 * parameter of routine
1236 * FFT_RATFCT  *fil;     input; filter to be checked
1237 *                       returns TRUE if filter exists at zero
1238 */
1239{
1240        /* local variables */
1241        int      p;        /* pole counter */
1242
1243        /* executable code */
1244
1245        for  (p=0; p < fil->no_of_poles; p++)  {
1246                if  (Abs(fil->pole[p].re) < SHC_EPSILON)  return FALSE;
1247                if  (Abs(fil->pole[p].im) < SHC_EPSILON)  return FALSE;
1248        } /*endfor*/
1249        return TRUE;
1250
1251} /* end of ff_freq0ok */
1252
1253
1254
1255/*-------------------------------------------------------------------------*/
1256
1257
1258
1259void ff_shorten_zeroes( FFT_RATFCT fct[], int no )
1260
1261/* shortens zeroes in all filter functions fct[0..no-1]
1262 *
1263 * parameters of routine
1264 * FFT_RATFCT fct[];      modify; filter functions to be shortened
1265 * int        no;         input; number of filter functions
1266 */
1267{
1268        /* local variables */
1269        FFT_RATFCT loc;     /* local function */
1270        int      f;         /* filter counter */
1271        int      i;         /* counter */
1272        int      z_poles;   /* number of poles at zero freq. */
1273        int      z_zeroes;  /* number of zeroes at zero freq. */
1274
1275        /* executable code */
1276
1277        /* count zeroes in numerator and denominator */
1278        z_poles = 0;
1279        z_zeroes = 0;
1280        for  (f=0; f<no; f++)  {
1281                for  (i=0; i < fct[f].no_of_zeroes; i++)
1282                        if  ((fct[f].zero[i].re == 0.0) && (fct[f].zero[i].im == 0.0))
1283                                z_zeroes++;
1284                for  (i=0; i < fct[f].no_of_poles; i++)
1285                        if  ((fct[f].pole[i].re == 0.0) && (fct[f].pole[i].im == 0.0))
1286                                z_poles++;
1287        } /*endfor*/
1288
1289        /* take smaller number */
1290        if  (z_poles < z_zeroes)  {
1291                z_zeroes = z_poles;
1292        } else {
1293                z_poles = z_zeroes;
1294        } /*endif*/
1295        if  (z_zeroes == 0)  return;
1296
1297        /* shorten */
1298        for  (f=0; f<no; f++)  {
1299                loc.norm = fct[f].norm;
1300                loc.no_of_zeroes = 0;
1301                for  (i=0; i < fct[f].no_of_zeroes; i++)  {
1302                        if  ((fct[f].zero[i].re == 0.0) &&
1303                                (fct[f].zero[i].im == 0.0) && (z_zeroes > 0))  {
1304                                z_zeroes--;
1305                        } else {
1306                                loc.zero[loc.no_of_zeroes].re = fct[f].zero[i].re;
1307                                loc.zero[(loc.no_of_zeroes)++].im = fct[f].zero[i].im;
1308                        } /*endif*/
1309                } /*endfor*/
1310                loc.no_of_poles = 0;
1311                for  (i=0; i < fct[f].no_of_poles; i++)  {
1312                        if  ((fct[f].pole[i].re == 0.0) &&
1313                                (fct[f].pole[i].im == 0.0) && (z_poles > 0))  {
1314                                z_poles--;
1315                        } else {
1316                                loc.pole[loc.no_of_poles].re = fct[f].pole[i].re;
1317                                loc.pole[(loc.no_of_poles)++].im = fct[f].pole[i].im;
1318                        } /*endif*/
1319                } /*endfor*/
1320                fct[f] = loc;
1321                if  ((z_zeroes == 0) && (z_poles == 0))  return;
1322        } /*endfor*/
1323
1324} /* end of ff_shorten_zeroes */
1325
1326
1327
1328/*-------------------------------------------------------------------------*/
1329
1330
1331
1332void ff_compress( STATUS *status )
1333
1334/* combines a cascade of filters read in to a single filter function
1335 *
1336 * parameters of routine
1337 * STATUS     *status;    output; return status
1338 */
1339{
1340        /* local variables */
1341        FFT_RATFCT loc;     /* local filter */
1342        int      f;         /* filter counter */
1343        int      i;         /* counter */
1344
1345        /* executable code */
1346
1347        if  (no_of_fil_ffv <= 1)  return;
1348
1349        loc.norm = 1.0;
1350        loc.no_of_zeroes = 0;
1351        loc.no_of_poles = 0;
1352        for  (f=0; f<no_of_fil_ffv; f++)  {
1353                loc.norm *= fct_ffv[f].norm;
1354                for  (i=0; i < fct_ffv[f].no_of_zeroes; i++)  {
1355                        if  (loc.no_of_zeroes >= FFC_MAXDEGREE)  {
1356                                *status = FLE_COMPRESS;
1357                                return;
1358                        } /*endif*/
1359                        loc.zero[loc.no_of_zeroes].re = fct_ffv[f].zero[i].re;
1360                        loc.zero[(loc.no_of_zeroes)++].im = fct_ffv[f].zero[i].im;
1361                } /*endfor*/
1362                for  (i=0; i < fct_ffv[f].no_of_poles; i++)  {
1363                        if  (loc.no_of_poles >= FFC_MAXDEGREE)  {
1364                                *status = FLE_COMPRESS;
1365                                return;
1366                        } /*endif*/
1367                        loc.pole[loc.no_of_poles].re = fct_ffv[f].pole[i].re;
1368                        loc.pole[(loc.no_of_poles)++].im = fct_ffv[f].pole[i].im;
1369                } /*endfor*/
1370        } /*endfor*/
1371
1372        fct_ffv[0] = loc;
1373        no_of_fil_ffv = 1;
1374
1375} /* end of ff_compress */
1376
1377
1378
1379/*-------------------------------------------------------------------------*/
1380
1381static void ff_costaper( float taper, long lth, COMPLEX dat[] )
1382
1383/* tapers the end of data array (cosine taper)
1384 *
1385 * parameters of routine
1386 * float      taper;       input; taper start [0..1]
1387 * long       lth;         input; length of data array
1388 * COMPLEX    dat[];       modify; data array to be tapered
1389 */
1390{
1391        /* local variables */
1392        long     start;    /* start index */
1393        long     i;        /* index counter */
1394        float    step;     /*  */
1395        float    r;        /* scratch */
1396
1397        /* executable code */
1398
1399        start = Nlong( (float)lth * taper );
1400        if  (start >= (lth-1))  return;
1401        step = 1.0 / (float)(lth-start-1) * BC_PI;
1402
1403        for  (i=start+1; i<lth-1; i++)  {
1404                r = 0.5 * (1.0 + cos( (float)(i-start) * step ));
1405                dat[i+1].re *= r;
1406                dat[i+1].im *= r;
1407        } /*endfor*/
1408        dat[0].im = 0.0;
1409
1410} /* end of ff_costaper */
1411
1412
1413
1414/*-------------------------------------------------------------------------*/
1415
1416
1417
1418REAL ff_filter_amplitude_old( char filter[], REAL frq, STATUS *status )
1419
1420/* returns amplitude of filter "filter" at frequency "frq"
1421 *
1422 * parameters of routine
1423 * char       filter[];      input; name of filter
1424 * REAL       frq;           input; frequency in Hz (no angular frequency)
1425 * STATUS     *status;       output; return status
1426 *                           returns amplitude of filter
1427 */
1428{
1429        /* local variables */
1430        FFT_FILFUNC  filf;       /* filter function */
1431        COMPLEX      val;        /* complex filter value */
1432
1433        /* executable code */
1434
1435        ff_filfunc_input( filter, &filf, status );
1436        if  (Severe(status))  return 0.0;
1437        frq *= 2.0*BC_PI;   /* make angular frequency */
1438        ff_filfvalue( &val, &filf, frq, status );
1439        ff_free_filfunc( &filf );
1440        if  (Severe(status))  return 0.0;
1441        return (sqrt(val.re*val.re + val.im*val.im));
1442
1443} /* end of ff_filter_amplitude_old */
1444
1445
1446
1447/*-------------------------------------------------------------------------*/
1448
1449
1450
1451REAL ff_filter_amplitude( char filter[], REAL frq, STATUS *status )
1452
1453/* returns amplitude of filter "filter" at frequency "frq"
1454 *
1455 * parameters of routine
1456 * char       filter[];      input; name of filter
1457 * REAL       frq;           input; frequency in Hz (no angular frequency)
1458 * STATUS     *status;       output; return status
1459 *                           returns amplitude of filter
1460 */
1461{
1462        /* local variables */
1463        FFT_RATFCT  filf;       /* filter function */
1464        COMPLEX      val;        /* complex filter value */
1465
1466        /* executable code */
1467
1468        ff_read_filter( filter, 1, &filf, status );
1469        if  (Severe(status))  return 0.0;
1470        frq *= 2.0*BC_PI;   /* make angular frequency */
1471        ff_tfvalue( &val, &filf, frq );
1472        if  (Severe(status))  return 0.0;
1473        return (sqrt(val.re*val.re + val.im*val.im));
1474
1475} /* end of ff_filter_amplitude */
1476
1477
1478
1479/*-------------------------------------------------------------------------*/
Note: See TracBrowser for help on using the repository browser.