source: SH_SHM/trunk/source/seed_io/seed_lib.c @ 352

Revision 352, 114.3 KB checked in by marcus, 11 years ago (diff)

r189 | klaus | 2011-03-25 18:54:37 +0100 (Fr, 25 Mär 2011) | 1 line

find blockette 1000 within multipleblockettes

Line 
1
2/* file seed_lib.c
3 *      ==========
4 *
5 * $Revision: 189 $, $Date: 2011-03-25 18:54:37 +0100 (Fr, 25 MÀr 2011) $
6 *
7 * SEED library
8 * K. Stammler, 29-Dec-93
9 * v 16, 22-Nov-94, K. Stammler, added headers for VAX-GCC
10 * v 18, 23-Nov-94, K. Stammler, automatic detection of necessary byte swaps
11 * v 43,  7-Dec-97, K. Stammler, fixed calib-bug when reading starts in a gap
12 * v 44,  9-Dec-97, K. Stammler, fixed bug in ReadNextRecord (appeared in Linux)
13 * v 46,  2-Mar-98, K. Stammler, fixed bug on records with too many samples
14 * v 47, 24-Mar-98, K. Stammler, was still a bug in records with too many smples
15 * v 48, 24-Apr-98, K. Stammler, replaced some printf's by fprintf's
16 * v 49,  1-Jun-98, K. Stammler, still another bug at records with bad samples
17 * v 50, 11-Aug-98, K. Stammler, implemented offset positions in SEED files
18 * v 51, 16-Mar-99, K. Stammler, use time correction field in SEED records
19 * v 52, 11-Jan-00, K. Stammler, variable SEED record length
20 * v 53, 14-Jun-00, K. Stammler, SeedSwapNecessary until 2030
21 * v 54, 11-Jul-00, K. Stammler, handle seed->databegin other than 64er numbers
22 * v 56,  6-Dec-01, K. Stammler, implementation of Steim2 input
23 * v 57, 11-Jan-02, K. Stammler, increased max samples/rec to 14000
24 * v 58,  8-Jul-02, K. Stammler, implement VAX word order
25 * v 59, 26-Aug-02, K. Stammler, only output printable chars on SeedLibWarning
26 * v 60,  9-Sep-02, K. Stammler, check for illegal 'first' entry (bus error)
27 * v 61, 17-Oct-02, K. Stammler, in SeedReadStreamReal, set fdat=NULL, first
28 * v 62, 17-Nov-02, K. Stammler, SeedStoreRec: swap 'first' entry on swapped rec
29 * v 63, 14-Apr-05, K. Stammler, insert blockette 1000 when writing miniSeed
30 * v 64, 18-Nov-05, K. Stammler, compiler error on Suse10, empty default switch
31 * v 65, 21-Nov-05, K. Stammler, change long to int32
32 * v 66, 25-Nov-05, K. Stammler, possibility to insert time quality in data recs
33 * v 67,  7-Mar-06, K. Stammler, netcode+locid used for reading
34 * v 68, 28-Apr-06, K. Stammler, fixed bug in SeedGetReclth (was no test for swap)
35 * v 70, 20-May-06, K. Stammler, new file format for calibration info
36 * v 71, 22-May-06, K. Stammler, new flag-parameter in SeedReadStream for qc
37 * v 72, 14-Jun-06, K. Stammler, missing fclose fixed on new sensitivities file
38 * v 73, 22-Oct-06, K. Stammler, string lists on sensitivity file
39 * v 74,  4-Nov-06, K. Stammler, add sfdb interface
40 * v 75, 12-Nov-06, K. Stammler, add routine to remove temp file of sfdb request
41 * v 76, 15-Dec-06, K. Stammler, date and time in INT and DOUBLE format
42 * v 77, 18-Dec-06, K. Stammler, added some debug printout
43 * v 78, 21-Dec-06, K. Stammler, restructered sfdb interface (sqliface.c)
44 * v 79, 28-Dec-06, K. Stammler, 'default' sensitivity replaced by $SH_INPUTS/sensitivities.txt
45 * v 80, 29-Dec-06, K. Stammler, implementation of data lock flag
46 * v 81,  3-Jan-07, K. Stammler, set default of seedv_use_timecorr to TRUE, TIMECORRUNIT to 10000
47 * v 82, 13-Feb-07, K. Stammler, swap blockette 1000 in SwapHeader
48 * v 83, 28-Nov-07, K. Stammler, accept also Q and R as data record identifier
49 * v 84, 19-Feb-08, M. Walther, removed VAX support
50 */
51
52
53#include <stdio.h>
54#include <string.h>
55#include <math.h>
56#include "basecnst.h"
57
58#ifdef BC_INC_UNISTD
59#include BC_INC_UNISTD
60#endif
61
62#ifdef BC_INC_STDLIB
63#include BC_INC_STDLIB
64#endif
65
66#include <fcntl.h>
67#include <sys/types.h>
68#include "sysbase.h"
69#include "tcusrdef.h"
70#include "erusrdef.h"
71#include "utusrdef.h"
72#include "globalparams.h"
73#include "seedcfg.h"
74#include "seed_lib.h"
75
76#define ANSI_EXTENSIONS
77#include "steim1.h"
78#undef ANSI_EXTENSIONS
79
80
81/*
82 * constants
83 * ---------
84 */
85
86#define PREV_XN_INVALID 0x7fffffffL
87#define ROOTDIR "$ROOT"
88#define ROOTDIRLTH 5
89#define MAX_SMP_PER_REC 14000
90#define TIMECORRUNIT 10000.0
91#define DEFAULT_RECLTH 4096
92
93
94
95
96/*
97 * global variables
98 * ----------------
99 */
100
101static SeedSetupParT   seedv_setup;                 /* setup parameters */
102static SeedFileDescrT  seedv_fd[Seed_C_MAXCHAN];    /* file descriptors */
103static SeedDataHeaderT seedv_rec[Seed_C_MAX_RECLTH/sizeof(SeedDataHeaderT)];
104                                                    /* SEED record */
105static int             seedv_out_reclth=DEFAULT_RECLTH;
106                                            /* record length of output files */
107static BOOLEAN         seedv_logrec;                /* log records */
108static BOOLEAN         seedv_warnings=TRUE;         /* print warnings */
109static BOOLEAN         seedv_invert_swap_hdr=FALSE; /* invert swap hdr flag */
110static BOOLEAN         seedv_capfiles=FALSE;        /* capitalized filenames */
111static BOOLEAN         seedv_decerr_abort=TRUE;     /* abort on decode errors */
112static BOOLEAN         seedv_use_timecorr=TRUE;     /* use time corrections */
113static char            seedv_last_fname[cBcFileLth+1]; /* last file read */
114static int             seedv_timequal= -1;          /* time quality */
115
116static SeedDataHeaderT seedv_hdr_proto = {        /* SEED header prototype */
117        "",                     /* seqno, sequence number string */
118        'D',                    /* indicator */
119        '\0',                   /* Reserved_bytes_A */
120        {'X','X','X',' ',' '},  /* statcode, station name */
121        {' ',' '},              /* locid, location identifier */
122        {'X','X','X'},          /* channel */
123        {'\0','\0'},            /* Reserved_bytes_B */
124        {0,0,0,0,0,0,0},        /* starttime */
125        0,                      /* no_of_samples */
126        1,                      /* smprate_fact */
127        1,                      /* smprate_mult */
128        0,                      /* activity */
129        0,                      /* ioflags */
130        0,                      /* quality */
131        0,                      /* no_of_blockettes */
132        0,                      /* timecorr */
133        0,                      /* databegin */
134        0                       /* first */
135}; /* end of SEED header prototype */
136
137/*
138 * prototypes of local routines
139 * ----------------------------
140 */
141
142static void SeedDecodeSteim1Frame( SeedSbyteT frame[], BOOLEAN swap,
143        BOOLEAN wo, INT32 diff[], int *lth );
144static void SeedDecodeSteim2Frame( SeedSbyteT frame[], BOOLEAN swap,
145        BOOLEAN wo, INT32 diff[], int *lth );
146static void SeedAdjustFilename( SeedFileDescrT *dsc, STATUS *status );
147static void SeedLibWarning( char text[] );
148static void SeedSwapLinuxRecord( SeedSbyteT *rec, int reclth );
149static void SeedSplitStreamName( char inpname[], char outname[],
150        char station[], char addinf[] );
151static void SeedFindFileInDatabase( char stream_str[], char start[],
152        char dbfile[], SeedFileDescrT *fdescr, STATUS *status );
153
154/* #define SeedLibWarning(t) fprintf( stderr, "%s", t ); */
155
156
157
158/*---------------------------------------------------------------------*/
159
160
161
162void SeedLibInitialize( STATUS *status )
163
164/* Initializes SEED library routines
165 *
166 * parameters of routine
167 * STATUS     *status;      output; return status
168 */
169{
170        /* local variables */
171        int      i;            /* counter */
172
173        /* executable code */
174
175        SeedGetSetup( &seedv_setup );
176        for  (i=0; i<Seed_C_MAXCHAN; seedv_fd[i++].ufd = Seed_C_ILLEGAL ) {}
177
178} /* end of SeedLibInitialize */
179
180
181
182/*---------------------------------------------------------------------*/
183
184
185
186void SeedDecodeSteim1( SeedSbyteT rec[], BOOLEAN swap, INT32 maxsmplth,
187        INT32 smp[], INT32 *smplth )
188
189/* Decodes Steim1-compressed data record of length specified within record.
190 * Data are returned in array 'smp', its length in 'smplth'.  No more than
191 * maxsmplth samples are copied to the output array.  If more samples would
192 * be available an error message is printed.
193 * A NULL pointer for 'rec' resets internal variables to initial state.
194 *
195 * Can now also read Steim2 compression, 10-Dec-2001, K. Stammler
196 *
197 * parameters of routine
198 * SeedSbyteT rec[];          input; SEED record
199 * BOOLEAN    swap;           input; swap bytes
200 * INT32      maxsmplth;      input; maximum length of output array
201 * INT32      smp[];          output; decoded samples
202 * INT32      *smplth;        output; number of output samples
203 */
204{
205        /* local variables */
206        static INT32 prev_xn=PREV_XN_INVALID;      /* previous xn */
207        static int err_cnt=0;          /* error count for diff[0]==x0 */
208        SeedSbyteT *frame;             /* byte pointer */
209        int        frames_per_rec;     /* number of frames/record (incl. header) */
210        int        framecnt;           /* frame counter */
211        int        framecnt_start;     /* frame count start value */
212        INT32      x0, xn;             /* integration constants */
213        INT32      diffs[Seed_C_MAXFRAMESMP];  /* differences of one frame */
214        int        declth;             /* number of differences in a frame */
215        char       str[BC_LINELTH+1];  /* scratch string */
216        INT32      cursmp;             /* current sample */
217        INT32      fsampleno;          /* number of samples in frame */
218        SeedDataHeaderT *rec_h;        /* data header structure */
219        INT32      rsampleno;          /* number of samples in record */
220        int        reclth;             /* record length */
221        int        comprs;             /* compression ID */
222        int        worder;             /* word order 0=VAX,8086 1=Sparc,68000 */
223
224        /* executable code */
225
226        if  (rec == NULL)  {
227                prev_xn = PREV_XN_INVALID;
228                return;
229        } /*endif*/
230
231        rec_h = (SeedDataHeaderT *)rec;
232        rsampleno = (INT32)(rec_h->no_of_samples);
233        if  (maxsmplth < rsampleno)  {
234                sprintf( str,
235                        "SeedDecodeSteim1: passed array is too short by %ld samples\n",
236                        rsampleno-maxsmplth );
237                SeedLibWarning( str );
238                rsampleno = maxsmplth;
239        } /*endif*/
240        /* printf( "--> databegin: %d\n", (int)rec_h->databegin ); */
241
242        reclth = SeedGetReclth( rec_h, FALSE );
243        frames_per_rec = reclth / Seed_C_FRAMELTH;
244        *smplth = 0;
245        frame = rec;
246        if  (rsampleno <= 0)  return;
247
248        comprs = SeedGetCompression( rec_h );
249        /* assume Steim1 compression if no blockette 1000 */
250        if  (comprs == 0)  {
251                comprs = Seed_C_DcmpSteim1;
252                /*
253                SeedLibWarning( "no blockette 1000 found, assume Steim1 compression\n" );
254                */
255        } /*endif*/
256        if  (comprs != Seed_C_DcmpSteim1 && comprs != Seed_C_DcmpSteim2)  {
257                sprintf( str, "unimplemented Compression %d\n", comprs );
258                SeedLibWarning( str );
259                return;
260        } /*endif*/
261        worder = SeedGetWordOrder( rec_h );
262
263        /* skip all frames wich are not data frames (minus one which is */
264        /* incremented inside the following loop)                       */
265        if  ((int)(rec_h->databegin) % Seed_C_FRAMELTH != 0)  {
266                /* illegal value of databegin, print warning and assume it as 64 */
267                sprintf( str, "SeedDecodeSteim1: illegal databegin %d\n",
268                        (int)(rec_h->databegin) );
269                SeedLibWarning( str );
270                /* increase databegin over the next 64er border, will be rounded off */
271                rec_h->databegin += Seed_C_FRAMELTH;
272        } /*endif*/
273        framecnt_start = 1;
274        /* a value of 0 is corrected to 64 */
275        /* values of 128 and more cause a increment of data start frame */
276        if  (rec_h->databegin > Seed_C_FRAMELTH)  {
277                /*printf( "--> found databegin of %d\n", (int)(rec_h->databegin) );*/
278                framecnt_start = (int)(rec_h->databegin) / Seed_C_FRAMELTH;
279                frame += (framecnt_start-1)*Seed_C_FRAMELTH;
280        } /*endif*/
281
282        /* loop over all frames in record (first frame is header) */
283        for  (framecnt=framecnt_start; framecnt<frames_per_rec; framecnt++)  {
284
285                frame += Seed_C_FRAMELTH;
286
287                /* get integration constants */
288                if  (framecnt == framecnt_start)  {
289                        x0 = SeedGet4Bytes( frame+4, swap );
290                        xn = SeedGet4Bytes( frame+8, swap );
291                } /*endif*/
292
293                /* get all differences of this frame */
294                if  (comprs == Seed_C_DcmpSteim1)  {
295                        SeedDecodeSteim1Frame( frame, swap, worder, diffs, &declth );
296                } else {
297                        /* printf( "--> decompressing Steim2\n" ); */
298                        SeedDecodeSteim2Frame( frame, swap, worder, diffs, &declth );
299                } /*endif*/
300                if  (declth > Seed_C_MAXFRAMESMP)  {printf("*****1*****\n"); exit(111);}
301
302                /* check difference to last record */
303                if  (framecnt == framecnt_start)  {
304                        if  (prev_xn+diffs[0] != x0 && prev_xn != PREV_XN_INVALID)  {
305                                if  (diffs[0] == x0)  {
306                                        /* this is probably a common error in compression */
307                                        if  (err_cnt++ % 100 == 0)  {
308                                                sprintf( str,
309                                                        "\n--- Steim1: diff[0] is always equal to x0\n" );
310                                                SeedLibWarning( str );
311                                        } /*endif*/
312                                } else {
313                                        sprintf( str, "\n--- first sample in record: wrong diff\n" );
314                                        SeedLibWarning( str );
315                                        sprintf( str,
316                                        "    should be (x[-1]+diff[0]) %d, x[0] is %d, diff[0] is %ld\n",
317                                                prev_xn+diffs[0], x0, diffs[0] );
318                                        SeedLibWarning( str );
319                                        /* grn_printhdr( &hdr ); */
320                                } /*endif*/
321                        } /*endif*/
322                        cursmp = x0 - diffs[0];  /* is undone in following loop */
323                } /*endif*/
324
325                /* integrate samples and copy to output array */
326                for  (fsampleno=0; fsampleno<declth; fsampleno++)  {
327                        cursmp += diffs[fsampleno];
328                        *smp++ = cursmp;
329                        if  (++(*smplth) == rsampleno)  break;
330                } /*endfor*/
331
332                if  (*smplth == rsampleno)  break;
333
334        } /*endfor*/
335
336        if  (cursmp != xn)  {
337                sprintf( str, "*** checksum not ok in record\n" );
338                SeedLibWarning( str );
339        } /*endif*/
340
341        prev_xn = xn;
342
343} /* end of SeedDecodeSteim1 */
344
345
346
347/*----------------------------------------------------------------------------*/
348
349
350
351static void SeedDecodeSteim1Frame( SeedSbyteT frame[], BOOLEAN swap,
352        BOOLEAN wo, INT32 diff[], int *lth )
353
354/* Decodes differences of a single frame.
355 *
356 * parameters of routine
357 * SeedSbyteT *frame;     input; byte stream
358 * BOOLEAN    swap;       input; swap bytes
359 * BOOLEAN    wo;         input; word order
360 * INT32      diff[];     output; decoded differences
361 * int        *lth;       output; number of differences
362 */
363{
364        /* local variables */
365        unsigned INT32  nibbles;    /* 2-bit nibbles */
366        int             diffcnt;    /* difference counter */
367        int             shift;      /* bit shift length */
368        int             diff_id;    /* difference 2-bit ID (0,1,2,3) */
369        short int       si;         /* scratch */
370        unsigned INT32  ultmp;      /* scratch */
371        SeedSbyteT      sbyte;      /* scratch */
372
373        /* executable code */
374
375        nibbles = SeedGet4Bytes( frame, swap );
376        *lth = 0;
377        for  (diffcnt=0; diffcnt<Seed_C_FRAMEDIFFS; diffcnt++)  {
378                shift = 30 - diffcnt*2;
379                diff_id = (int)((nibbles >> shift) & 3);
380                switch  (diff_id)  {
381                case 1:
382                        ultmp = SeedGet4Bytes( frame, swap );
383                        frame += 4;
384                        if  (wo == 0)  {
385                                sbyte = (SeedSbyteT)(ultmp & 0x000000ffL);
386                                diff[(*lth)++] = sbyte;
387                                sbyte = (SeedSbyteT)((ultmp & 0x0000ff00L) >>  8);
388                                diff[(*lth)++] = sbyte;
389                                sbyte = (SeedSbyteT)((ultmp & 0x00ff0000L) >> 16);
390                                diff[(*lth)++] = sbyte;
391                                sbyte = (SeedSbyteT)((ultmp & 0xff000000L) >> 24);
392                                diff[(*lth)++] = sbyte;
393                        } else {
394                                sbyte = (SeedSbyteT)((ultmp & 0xff000000L) >> 24);
395                                diff[(*lth)++] = sbyte;
396                                sbyte = (SeedSbyteT)((ultmp & 0x00ff0000L) >> 16);
397                                diff[(*lth)++] = sbyte;
398                                sbyte = (SeedSbyteT)((ultmp & 0x0000ff00L) >>  8);
399                                diff[(*lth)++] = sbyte;
400                                sbyte = (SeedSbyteT)(ultmp & 0x000000ffL);
401                                diff[(*lth)++] = sbyte;
402                        } /*endif*/
403                        break;
404                case 2:
405                        ultmp = SeedGet4Bytes( frame, swap );
406                        frame += 4;
407                        if  (wo == 0)  {
408                                si = (short int)(ultmp & 0x0000ffffL);
409                                diff[(*lth)++] = si;
410                                si = (short int)((ultmp & 0xffff0000L) >> 16);
411                                diff[(*lth)++] = si;
412                        } else {
413                                si = (short int)((ultmp & 0xffff0000L) >> 16);
414                                diff[(*lth)++] = si;
415                                si = (short int)(ultmp & 0x0000ffffL);
416                                diff[(*lth)++] = si;
417                        } /*endif*/
418                        break;
419                case 3:
420                        diff[(*lth)++] = (INT32)SeedGet4Bytes( frame, swap );
421                        frame += 4;
422                        break;
423                default:
424                        frame += 4;  /* no data */
425                } /*endswitch*/
426        } /*endfor*/
427
428} /* end of SeedDecodeSteim1Frame */
429
430
431
432/*----------------------------------------------------------------------------*/
433
434
435
436static void SeedDecodeSteim2Frame( SeedSbyteT frame[], BOOLEAN swap,
437        int wo, INT32 diff[], int *lth )
438
439/* Decodes differences of a single frame, Steim2.
440 *
441 * parameters of routine
442 * SeedSbyteT *frame;     input; byte stream
443 * BOOLEAN    swap;       input; swap bytes
444 * int        wo;         input; word order
445 * INT32      diff[];     output; decoded differences
446 * int        *lth;       output; number of differences
447 */
448{
449        /* local variables */
450        unsigned INT32  nibbles;    /* 2-bit nibbles */
451        int             diffcnt;    /* difference counter */
452        int             shift;      /* bit shift length */
453        int             diff_id;    /* difference 2-bit ID (0,1,2,3) */
454        unsigned int    dnib;       /* decode nibble in decoded longword */
455        unsigned int    udiff[8];   /* difference decoded */
456        short int       si;         /* scratch */
457        unsigned INT32  ultmp;      /* scratch */
458        SeedSbyteT      sbyte;      /* scratch */
459        int             i;          /* counter */
460
461        /* executable code */
462
463        if  (wo == 0)  {
464                fprintf( stderr,
465                        "  Steim2: word order 0 (80x86) not implemented, check data\n" );
466        } /*endif*/
467
468        nibbles = SeedGet4Bytes( frame, swap );
469        *lth = 0;
470        for  (diffcnt=0; diffcnt<Seed_C_FRAMEDIFFS; diffcnt++)  {
471                shift = 30 - diffcnt*2;
472                diff_id = (int)((nibbles >> shift) & 3);
473                switch  (diff_id)  {
474                case 1:  /* 01 */
475                        /* this is four 8-bit differences */
476                        ultmp = SeedGet4Bytes( frame, swap );
477                        frame += 4;
478                        sbyte = (SeedSbyteT)((ultmp & 0xff000000L) >> 24);
479                        diff[(*lth)++] = sbyte;
480                        sbyte = (SeedSbyteT)((ultmp & 0x00ff0000L) >> 16);
481                        diff[(*lth)++] = sbyte;
482                        sbyte = (SeedSbyteT)((ultmp & 0x0000ff00L) >>  8);
483                        diff[(*lth)++] = sbyte;
484                        sbyte = (SeedSbyteT)(ultmp & 0x000000ffL);
485                        diff[(*lth)++] = sbyte;
486                        break;
487                case 2:  /* 10 */
488                        /* ask high order two bits of decoded longword */
489                        ultmp = SeedGet4Bytes( frame, swap );
490                        frame += 4;
491                        dnib = (ultmp >> 30) & 3;
492                        switch  (dnib)  {
493                        case 1:  /* 01 */
494                                /* one 30-bit difference, set high oder bits acc. bit number 30 */
495                                if  (ultmp & 0x20000000L)
496                                        diff[(*lth)++] = (int)(ultmp | 0xc0000000L);
497                                else
498                                        diff[(*lth)++] = (int)(ultmp & 0x3fffffffL);
499                                break;
500                        case 2:  /* 10 */
501                                /* two 15 bit differences */
502                                udiff[0] = (ultmp >> 15) & 0x00007fffL;
503                                udiff[1] =  ultmp        & 0x00007fffL;
504                                for  (i=0; i<2; i++)
505                                        if  (udiff[i] & 0x00004000L)
506                                                diff[(*lth)++] = (int)(udiff[i] | 0xffff8000L);
507                                        else
508                                                diff[(*lth)++] = udiff[i];
509                                break;
510                        case 3:  /* 11 */
511                                udiff[0] = (ultmp >> 20) & 0x000003ffL;
512                                udiff[1] = (ultmp >> 10) & 0x000003ffL;
513                                udiff[2] =  ultmp        & 0x000003ffL;
514                                for  (i=0; i<3; i++)
515                                        if  (udiff[i] & 0x00000200L)
516                                                diff[(*lth)++] = (int)(udiff[i] | 0xfffffc00L);
517                                        else
518                                                diff[(*lth)++] = udiff[i];
519                                break;
520                        default:
521                                /* no data, ignore */;
522                        } /*endswitch*/
523                        break;
524                case 3:  /* 11 */
525                        /* ask high order two bits of decoded longword */
526                        ultmp = SeedGet4Bytes( frame, swap );
527                        frame += 4;
528                        dnib = (ultmp >> 30) & 3;
529                        switch  (dnib)  {
530                        case 0:  /* 00 */
531                                udiff[0] = (ultmp >> 24) & 0x0000003fL;
532                                udiff[1] = (ultmp >> 18) & 0x0000003fL;
533                                udiff[2] = (ultmp >> 12) & 0x0000003fL;
534                                udiff[3] = (ultmp >>  6) & 0x0000003fL;
535                                udiff[4] =  ultmp        & 0x0000003fL;
536                                for  (i=0; i<5; i++)
537                                        if  (udiff[i] & 0x00000020L)
538                                                diff[(*lth)++] = (int)(udiff[i] | 0xffffffc0L);
539                                        else
540                                                diff[(*lth)++] = udiff[i];
541                                break;
542                        case 1:  /* 01 */
543                                udiff[0] = (ultmp >> 25) & 0x0000001fL;
544                                udiff[1] = (ultmp >> 20) & 0x0000001fL;
545                                udiff[2] = (ultmp >> 15) & 0x0000001fL;
546                                udiff[3] = (ultmp >> 10) & 0x0000001fL;
547                                udiff[4] = (ultmp >>  5) & 0x0000001fL;
548                                udiff[5] =  ultmp        & 0x0000001fL;
549                                for  (i=0; i<6; i++)
550                                        if  (udiff[i] & 0x00000010L)
551                                                diff[(*lth)++] = (int)(udiff[i] | 0xffffffe0L);
552                                        else
553                                                diff[(*lth)++] = udiff[i];
554                                break;
555                        case 2:  /* 10 */
556                                udiff[0] = (ultmp >> 24) & 0x0000000fL;
557                                udiff[1] = (ultmp >> 20) & 0x0000000fL;
558                                udiff[2] = (ultmp >> 16) & 0x0000000fL;
559                                udiff[3] = (ultmp >> 12) & 0x0000000fL;
560                                udiff[4] = (ultmp >>  8) & 0x0000000fL;
561                                udiff[5] = (ultmp >>  4) & 0x0000000fL;
562                                udiff[6] =  ultmp        & 0x0000000fL;
563                                for  (i=0; i<7; i++)
564                                        if  (udiff[i] & 0x00000008L)
565                                                diff[(*lth)++] = (int)(udiff[i] | 0xfffffff0L);
566                                        else
567                                                diff[(*lth)++] = udiff[i];
568                                break;
569                        default:
570                                /* no data, ignore */;
571                        } /*endswitch*/
572                        break;
573                default: /* 00 */
574                        frame += 4;  /* no data */
575                } /*endswitch*/
576        } /*endfor*/
577
578} /* end of SeedDecodeSteim2Frame */
579
580
581
582/*----------------------------------------------------------------------------*/
583
584
585
586unsigned short int SeedGet2Bytes( SeedSbyteT b[], BOOLEAN swap )
587
588/* returns word from byte stream
589 *
590 * parameters of routine
591 * SeedSbyteT b[];     input;   byte stream
592 * BOOLEAN    swap;    input;   swap bytes
593 */
594{
595        /* local variables */
596        unsigned short int   word;
597
598        /* executable code */
599
600        if  (swap)  {
601                word = ((unsigned short)(b[0]) & 0xff) * 0x100;
602                word += (unsigned short)(b[1]) & 0xff;
603        } else {
604                word = ((unsigned short)(b[1]) & 0xff) * 0x100;
605                word += (unsigned short)(b[0]) & 0xff;
606        } /*endif*/
607        return word;
608
609} /* end of SeedGet2Bytes */
610
611
612
613/*----------------------------------------------------------------------------*/
614
615
616
617unsigned INT32 SeedGet4Bytes( SeedSbyteT b[], BOOLEAN swap )
618
619/* returns word from byte stream
620 *
621 * parameters of routine
622 * SeedSbyteT b[];     input;   byte stream
623 * BOOLEAN    swap;    input;   swap bytes
624 */
625{
626        /* local variables */
627        unsigned INT32   lword;
628
629        /* executable code */
630
631        if  (swap)  {
632                lword = ((unsigned INT32)(b[0]) & 0xffL) * 0x1000000L;
633                lword += ((unsigned INT32)(b[1]) & 0xffL) * 0x10000L;
634                lword += ((unsigned INT32)(b[2]) & 0xffL) * 0x100;
635                lword += (unsigned INT32)b[3] & 0xffL;
636        } else {
637                lword = ((unsigned INT32)(b[3]) & 0xffL) * 0x1000000L;
638                lword += ((unsigned INT32)(b[2]) & 0xffL) * 0x10000L;
639                lword += ((unsigned INT32)(b[1]) & 0xffL) * 0x100;
640                lword += (unsigned INT32)b[0] & 0xffL;
641        } /*endif*/
642        return lword;
643
644} /* end of SeedGet4Bytes */
645
646
647
648/*---------------------------------------------------------------------*/
649
650
651
652void SeedFindFileInSfd( char stream_str[], char start[], char sfdfile[],
653        SeedFileDescrT *fdescr, STATUS *status )
654
655/* Finds SEED file in sfd-file of given stream and containing given
656 * start time.  If no file is found the file with the next possible
657 * time is returned
658 *
659 * parameters of routine
660 * char       stream_str[];      input; stream string like "bfo-vbb-z"
661 * char       start[];           input; start time
662 * char       sfdfile[];         input; SEED file directory
663 * SeedFileDescrT *fdescr;       output; SEED file descriptor
664 * STATUS     *status;           output; return status
665 */
666{
667        /* local variables */
668        FILE     *sfd;                          /* pointer to sfd-file */
669        char     line[Seed_C_SFDLINELTH+1];     /* current line */
670        float    tdiff;                         /* time difference */
671        float    min_tdiff;                     /* minimum tdiff */
672        SeedFileDescrT next;                    /* file with next time */
673        SeedFileDescrT curr;                    /* current line */
674        char     lstream_str[BC_SHORTSTRLTH+1]; /* local lowercase stream string */
675        char     station[cBcShortStrLth+1];     /* station name */
676        char     xaddinf[Seed_C_AddinfLth+1];   /* netcode+locid searched */
677        TSyBoolean from_db;                     /* DB file instead of sfdfile */
678        TSyBoolean is_ingres;                   /* we have here wordy ingres output */
679        TSyBoolean firstline;                   /* first line of sfdfile */
680
681        /* executable code */
682
683        if  (strlen(stream_str) > BC_SHORTSTRLTH)  {
684                *status = SeedERR_STROVFL;
685                err_setcontext( " ## stream " );
686                err_setcontext( stream_str );
687                return;
688        } /*endif*/
689
690        SeedSplitStreamName( stream_str, lstream_str, station, xaddinf );
691
692        /* make stream string lowercase */
693        ut_uncap( lstream_str );
694
695        if  (GpGetInt(cGpI_debug_level) > 5)
696                printf( "SEED-dbg6: bench: in SeedFindFileInSfd, conventional sfdfile\n" );
697
698        /* initialize local descriptors */
699        strcpy( next.stream, lstream_str );
700        strcpy( curr.stream, lstream_str );
701        next.t_start[0] = curr.t_start[0] = '\0';
702        next.t_end[0] = curr.t_end[0] = '\0';
703        next.name[0] = curr.name[0] = '\0';
704        strcpy( next.sfdfile, sfdfile );
705        strcpy( curr.sfdfile, sfdfile );
706        next.recno = curr.recno = 0;
707        next.ufd = curr.ufd = Seed_C_ILLEGAL;
708        next.pos = curr.pos = 0;
709        next.sample = curr.sample = 0;
710        next.calib = curr.calib = 0.0;
711        next.dataflags = curr.dataflags = 0;
712        next.reclth = curr.reclth = DEFAULT_RECLTH;
713        next.byteoff = curr.byteoff = 0;
714        next.pri = curr.pri = 0;
715        next.dataformat = curr.dataformat = Seed_C_FORMAT_MSEED;
716        strcpy( next.addinf, Seed_C_EmptyAddinfStr );
717        strcpy( curr.addinf, Seed_C_EmptyAddinfStr );
718
719        sfd = sy_fopen( sfdfile, "r" );
720        if  (sfd == NULL)  {
721                *status = SeedERR_OPENINPUT;
722                err_setcontext( " ## file " );
723                err_setcontext( sfdfile );
724                return;
725        } /*endif*/
726
727        /* find requested stream and time in sfd-file*/
728        from_db = FALSE;  /* assume 'standard' sfdfile */
729        firstline = TRUE;
730        next.name[0] = '\0';
731        min_tdiff = 1.0e10;
732        fdescr->t_start[0] = '\0';
733        is_ingres = FALSE;
734        while  (fgets(line,Seed_C_SFDLINELTH,sfd) != NULL)  {
735                if  (*line == '!')  continue;
736                /* if ingres writes something like (223 rows) then stop */
737                if  (is_ingres && strstr(line," rows)\n"))  break;
738                if  (firstline)  {
739                        firstline = FALSE;
740                        is_ingres = FALSE;
741                        if  (strncmp(line,"station",7) == 0)  {
742                                from_db = TRUE;
743                                is_ingres = FALSE;
744                                continue; /* first line in db file contains no data */
745                        } else if  (strncmp(line,"INGRES TERMINAL",15) == 0)  {
746                                from_db = TRUE;
747                                is_ingres = TRUE;
748                                /* this is ingres output; skip this stupid header */
749                                fgets(line,Seed_C_SFDLINELTH,sfd);  /* this is: Ingres 2006 Linux ... */
750                                fgets(line,Seed_C_SFDLINELTH,sfd);  /* this is: date */
751                                fgets(line,Seed_C_SFDLINELTH,sfd);  /* this is: blank line */
752                                fgets(line,Seed_C_SFDLINELTH,sfd);  /* this is: continue */
753                                fgets(line,Seed_C_SFDLINELTH,sfd);  /* this is: * Executing ... */
754                                fgets(line,Seed_C_SFDLINELTH,sfd);  /* this is: blank line */
755                                fgets(line,Seed_C_SFDLINELTH,sfd);  /* this is: blank line */
756                                fgets(line,Seed_C_SFDLINELTH,sfd);  /* this is: header */
757                                continue;
758                        } /*endif*/
759                } /*endif*/
760                if  (from_db)  {
761                        SqlParseSftabLine( line, station, &curr, status );
762                        if  (seedv_invert_swap_hdr)  curr.swap_hdr = ! curr.swap_hdr;
763                } else {
764                        SeedParseSfdLine( line, &curr, status );
765                } /*endif*/
766                if  (Severe(status))  {fclose(sfd); return;}
767                if  (strcmp(curr.stream,lstream_str) != 0)  continue;
768                if  (strcmp(xaddinf,Seed_C_EmptyAddinfStr) != 0
769                        && strcmp(xaddinf,curr.addinf) != 0)  continue;
770                tdiff = tc_tdiff( start, curr.t_start, status );
771                if  (Severe(status))  {fclose(sfd); return;}
772                if  (!GpGetBoolean(cGpB_ignore_data_lock)
773                        && (curr.dataflags & Seed_F_QUAL_DATA_LOCKED))  continue;
774                if  (tdiff >= 0.0 && tc_tdiff(start,curr.t_end,status) < 0.0)  {
775                        /* found matching entry */
776                        if  (fdescr->t_start[0] != '\0')  {
777                                /* already found a previous matching entry */
778                                if  (fdescr->pri >= curr.pri)  continue; /* this has lower priority */
779                        } /*endif*/
780                        *fdescr = curr;
781                        if  (fdescr->calib == 0.0)  {
782                                fdescr->calib =
783                                        SeedFindStreamCalibration( fdescr->stream, start, status );
784                                if  (*status == SeedERR_NOCALIB)  {
785                                        *status = cBcNoError;
786                                        fdescr->dataflags |= Seed_F_QUAL_NOCALIB;
787                                } /*endif*/
788                        } /*endif*/
789                        if  (strncmp(fdescr->name,ROOTDIR,ROOTDIRLTH) == 0)
790                                SeedAdjustFilename( fdescr, status );
791                        if  (GpGetInt(cGpI_debug_level) > 5)
792                                printf( "SEED-dbg6: bench: returning from SeedFindFileInSfd, conventional sfdfile (1)\n" );
793                        if  (!from_db)  {
794                                /* take first matching entry only in sfdfile */
795                                fclose( sfd );
796                                return;
797                        } /*endif*/
798                } else if  (tdiff < 0.0)  {
799                        /* entries ordered by time, return if a matching entry previously found */
800                        if  (fdescr->t_start[0] != '\0')  {
801                                fclose( sfd );
802                                return;
803                        } /*endif*/
804                        /* store file with time next to requested */
805                        if  (Severe(status))  {fclose(sfd); return;}
806                        if  (next.name[0] == '\0' || tdiff > min_tdiff)  {
807                                min_tdiff = tdiff;
808                                next = curr;
809                        } /*endif*/
810                        if  (next.calib == 0.0)  {
811                                next.calib =
812                                        SeedFindStreamCalibration( next.stream, start, status );
813                                if  (*status == SeedERR_NOCALIB)  {
814                                        *status = cBcNoError;
815                                        next.dataflags |= Seed_F_QUAL_NOCALIB;
816                                } /*endif*/
817                        } /*endif*/
818                } /*endif*/
819                if  (Severe(status))  {fclose(sfd); return;}
820        } /*endwhile*/
821
822        /* if a matching entry has been found, return here */
823        if  (fdescr->t_start[0] != '\0')  {
824                fclose( sfd );
825                return;
826        } /*endif*/
827
828        *status = (next.name[0] == '\0') ? SeedERR_SFD_NOTFOUND : SeedERR_SFD_NEXT;
829        if  (*status == SeedERR_SFD_NOTFOUND)  {
830                err_setcontext( " ## stream " );
831                err_setcontext( lstream_str );
832                err_setcontext( ", addinf " );
833                err_setcontext( xaddinf );
834                err_setcontext( ", time " );
835                err_setcontext( start );
836        } /*endif*/
837        fclose( sfd );
838        *fdescr = next;
839        if  (strncmp(fdescr->name,ROOTDIR,ROOTDIRLTH) == 0)
840                SeedAdjustFilename( fdescr, status );
841        if  (GpGetInt(cGpI_debug_level) > 5)
842                printf( "SEED-dbg6: bench: returning from SeedFindFileInSfd, conventional sfdfile (2)\n" );
843        return;
844
845} /* end of SeedFindFileInSfd */
846
847
848
849/*---------------------------------------------------------------------*/
850
851
852void SeedSearchPosition( int chan, char sfdfile[], char stream_str[],
853        char req_start[], char act_start[], STATUS *status )
854
855/* Searches for given time position in a stream file.  The corresponding
856 * SEED file is opened and positioned, its file descriptor stored
857 * in an internal variable.  'chan' must range from 0..Seed_C_MAXCHAN-1.
858 * If the channel is already used the previously opened file is closed.
859 *
860 * parameters of routine
861 * int        chan;             input; channel number
862 * char       sfdfile[];        input; sfd-file
863 * char       stream_str[];     input; stream string
864 * char       req_start[];      input; requested start time
865 * char       act_start[];      output; actual start time
866 * STATUS     *status;          output; return status
867 */
868{
869        /* local variables */
870        BOOLEAN  next_time;      /* only next time possible */
871        float    tdiff_tot;      /* total time window of file */
872        float    tdiff_start;    /* difference to request time */
873        SeedFileDescrT *fd;      /* pointer to file descriptor */
874        INT32    seek_pos;       /* seek position */
875        NTIME    req_ntime;      /* requested time in NTIME format */
876        NTIME    cur_ntime;      /* start time of current SEED record */
877        float    cur_span;       /* time span (sec) of current SEED record */
878        float    dt;             /* sample distance in sec */
879        int      jump_rec;       /* number of records to jump */
880        int      new_pos;        /* new record position */
881        int      jump_cnt;       /* jump counter */
882
883        /* executable code */
884
885        if  (chan < 0 || chan >= Seed_C_MAXCHAN)  {
886                *status = SeedERR_CHAN_OOR;
887                return;
888        } /*endif*/
889        fd = seedv_fd + chan;
890
891        if  (fd->ufd != Seed_C_ILLEGAL)  {
892                close( fd->ufd );
893                fd->ufd = Seed_C_ILLEGAL;
894        } /*endif*/
895
896        SeedFindFileInSfd( stream_str, req_start, sfdfile, fd, status );
897        next_time =  (*status == SeedERR_SFD_NEXT);
898        if  (next_time)  *status = BC_NOERROR;
899        if  (Severe(status))  return;
900
901        if  (GpGetInt(cGpI_debug_level) > 4)
902                printf( "Seed-dbg5: opening file %s\n", fd->name );
903        fd->ufd = open( fd->name, O_RDONLY );
904        if  (fd->ufd < 0)  {
905                *status = SeedERR_OPENINPUT;
906                err_setcontext( " ## file " );
907                err_setcontext( fd->name );
908                fd->ufd = Seed_C_ILLEGAL;
909                return;
910        } /*endif*/
911
912        /* opened new file, jump to offset position if any */
913        if  (fd->byteoff > 0)  {
914                if  (lseek(fd->ufd,fd->byteoff,SEEK_SET) != fd->byteoff)  {
915                        *status = SeedERR_SEEDSEEK;
916                        err_setcontext( " ## file " );
917                        err_setcontext( fd->name );
918                        return;
919                } /*endif*/
920        } /*endif*/
921
922        if  (next_time)  {
923                strcpy( act_start, fd->t_start );
924                *status = SeedERR_NEXTTIMEPOS;
925                return;
926        } /*endif*/
927        tc_t2n( req_start, &req_ntime, status );
928        if  (Severe(status))  return;
929
930        /* compute approximate record position */
931        tdiff_tot = tc_tdiff( fd->t_end, fd->t_start, status );
932        if  (Severe(status))  return;
933        tdiff_start = tc_tdiff( req_start, fd->t_start, status );
934        if  (Severe(status))  return;
935        new_pos = Nint( (float)((fd->recno)-1)/tdiff_tot * tdiff_start );
936
937        for  (jump_cnt=0; jump_cnt<4; jump_cnt++)  {
938
939                /* position SEED file */
940                if  (new_pos != fd->pos)  {
941                        if  (new_pos >= fd->recno)  new_pos = fd->recno-1;
942                        if  (new_pos < 0)  new_pos = 0;
943                        fd->pos = new_pos;
944                        seek_pos = (INT32)(fd->pos) * (INT32)(fd->reclth) + (INT32)(fd->byteoff);
945                        if  (seedv_logrec)  printf( "-" );
946                        if  (lseek(fd->ufd,seek_pos,SEEK_SET) != seek_pos)  {
947                                *status = SeedERR_SEEDSEEK;
948                                err_setcontext( " ## file " );
949                                err_setcontext( fd->name );
950                                return;
951                        } /*endif*/
952                } /*endif*/
953
954                /* read current SEED record */
955                if  (seedv_logrec)  printf( "[%d]", fd->pos );  /* log */
956                if  (read(fd->ufd,(char *)seedv_rec,fd->reclth) != fd->reclth)  {
957                        *status = SeedERR_SEEDREAD;
958                        err_setcontext( " ## file " );
959                        err_setcontext( fd->name );
960                        return;
961                } /*endif*/
962                (fd->pos)++;
963                SeedStoreReclth( seedv_rec, fd->reclth );
964                if  (fd->swap_hdr)  SeedSwapHeader( seedv_rec );
965                dt = SeedGetSampleDist( seedv_rec );
966
967                /* check time found (return if time found) */
968                SeedBtimeToNtime( &(seedv_rec->starttime), &cur_ntime, status );
969                if  (Severe(status))  return;
970                /* check for time correction, K.S. 16-Mar-99 */
971                /* In old sfdfiles where the time correction is not applied */
972                /* this may cause problems, since the specified time windows are */
973                /* not exact.  This case is handled later. */
974                if  (seedv_use_timecorr && (seedv_rec->timecorr != 0)
975                        && (((int)(seedv_rec->activity) & Seed_F_ACT_TIMECORRAPP) == 0))  {
976                        tc_nadd( &cur_ntime, (float)(seedv_rec->timecorr)/TIMECORRUNIT,
977                                &cur_ntime, status );
978                        if  (Severe(status))  return;
979                } /*endif*/
980                tdiff_start = tc_ndiff( &req_ntime, &cur_ntime, status );
981                if  (Severe(status))  return;
982                cur_span = (float)(seedv_rec->no_of_samples) * dt;
983                if  (tdiff_start >= 0.0)  {
984                        if  (cur_span > tdiff_start)  {
985                                /* found it ! */
986                                seek_pos = (INT32)(--(fd->pos)) * (INT32)(fd->reclth)
987                                        + (INT32)(fd->byteoff);
988                                lseek( fd->ufd, seek_pos, SEEK_SET );
989                                fd->sample = Nint( tdiff_start/dt );
990                                if  (fd->sample >/*=*/ (int)(seedv_rec->no_of_samples))  {
991                                        printf( "! SeedSearchPosition: sample position adjusted (1)\n" );
992                                        fd->sample = seedv_rec->no_of_samples /*- 1*/;
993                                } /*endif*/
994                                tc_nadd( &cur_ntime, (fd->sample)*dt, &req_ntime, status );
995                                if  (Severe(status))  return;
996                                tc_n2t( &req_ntime, act_start, status );
997                                return;
998                        } /*endif*/
999                } /*endif*/
1000
1001                /* estimate next jump */
1002                if  (tdiff_start > 0.0)  tdiff_start -= cur_span;
1003                jump_rec = Nint( floor(tdiff_start/cur_span) );
1004                if  (jump_rec >= 0)  jump_rec++;  else  jump_rec--;
1005                new_pos = fd->pos - 1 + jump_rec;
1006
1007        } /*endfor*/
1008
1009        /* if still not found then read record by record */
1010        if  (seedv_logrec)  printf( "|" );
1011
1012        /* go back to time before */
1013        tdiff_start = tc_ndiff( &req_ntime, &cur_ntime, status );
1014        while  (tdiff_start < 0.0)  {
1015                fd->pos -= 2;
1016                if  (fd->pos < 0)  {
1017                        if  ((tdiff_start > ((-1.5)*(float)(seedv_rec->timecorr)/TIMECORRUNIT))
1018                                && seedv_use_timecorr)  {
1019                                /* This may happen if the sfdfile does not contain possible time  */
1020                                /* corrections of the data.  Try to fix this by positioning to    */
1021                                /* a time shifted by the correction.  The samples before this time*/
1022                                /* are not read.  Call this routine recursively.                  */
1023                                {
1024                                        char  newtime[cBcTimeLth+1];    /* new time position */
1025                                        tc_tadd( req_start, (float)(seedv_rec->timecorr)/TIMECORRUNIT,
1026                                                newtime, status );
1027                                        if  (SySevere(status))  {
1028                                                fprintf( stderr,
1029                                                        "*** SeedSearchPosition: error in time calc\n");
1030                                                *status = SeedERR_BUG;
1031                                                return;
1032                                        } /*endif*/
1033                                        fprintf( stderr,
1034                                                "SeedSearchPosition: try to fix time correction bug\n" );
1035                                        SeedSearchPosition( chan, sfdfile, stream_str, newtime,
1036                                                act_start, status );
1037                                        return;
1038                                }
1039                        } else {
1040                                fprintf( stderr, "*** SeedSearchPosition: check sfdfile\n" );
1041                                *status = SeedERR_BUG;
1042                                return;
1043                        } /*endif*/
1044                } /*endif*/
1045                seek_pos = (INT32)(fd->pos) * (INT32)(fd->reclth) + (INT32)(fd->byteoff);
1046                if  (seedv_logrec)  printf( "-" );
1047                if  (lseek(fd->ufd,seek_pos,SEEK_SET) != seek_pos)  {
1048                        *status = SeedERR_SEEDSEEK;
1049                        err_setcontext( " ## file " );
1050                        err_setcontext( fd->name );
1051                        return;
1052                } /*endif*/
1053                if  (seedv_logrec)  printf( "[%d]", fd->pos );  /* log */
1054                if  (read(fd->ufd,(char *)seedv_rec,fd->reclth) != fd->reclth)  {
1055                        *status = SeedERR_SEEDREAD;
1056                        err_setcontext( " ## file " );
1057                        err_setcontext( fd->name );
1058                        return;
1059                } /*endif*/
1060                (fd->pos)++;
1061                SeedStoreReclth( seedv_rec, fd->reclth );
1062                if  (fd->swap_hdr)  SeedSwapHeader( seedv_rec );
1063                dt = SeedGetSampleDist( seedv_rec );
1064                SeedBtimeToNtime( &(seedv_rec->starttime), &cur_ntime, status );
1065                if  (Severe(status))  return;
1066                /* check for time correction, K.S. 16-Mar-99 */
1067                if  (seedv_use_timecorr && (seedv_rec->timecorr != 0)
1068                        && (((int)(seedv_rec->activity) & Seed_F_ACT_TIMECORRAPP) == 0))  {
1069                        tc_nadd( &cur_ntime, (float)(seedv_rec->timecorr)/TIMECORRUNIT,
1070                                &cur_ntime, status );
1071                        if  (Severe(status))  return;
1072                } /*endif*/
1073                tdiff_start = tc_ndiff( &req_ntime, &cur_ntime, status );
1074                if  (Severe(status))  return;
1075                cur_span = (float)(seedv_rec->no_of_samples) * dt;
1076        } /*endwhile*/
1077
1078        /* now find forward */
1079        while  (tdiff_start >= cur_span)  {
1080                if  (seedv_logrec)  printf( "[%d]", fd->pos );  /* log */
1081                if  (read(fd->ufd,(char *)seedv_rec,fd->reclth) != fd->reclth)  {
1082                        *status = SeedERR_SEEDREAD;
1083                        err_setcontext( " ## file " );
1084                        err_setcontext( fd->name );
1085                        return;
1086                } /*endif*/
1087                (fd->pos)++;
1088                SeedStoreReclth( seedv_rec, fd->reclth );
1089                if  (fd->swap_hdr)  SeedSwapHeader( seedv_rec );
1090                dt = SeedGetSampleDist( seedv_rec );
1091                SeedBtimeToNtime( &(seedv_rec->starttime), &cur_ntime, status );
1092                if  (Severe(status))  return;
1093                /* check for time correction, K.S. 16-Mar-99 */
1094                if  (seedv_use_timecorr && (seedv_rec->timecorr != 0)
1095                        && (((int)(seedv_rec->activity) & Seed_F_ACT_TIMECORRAPP) == 0))  {
1096                        tc_nadd( &cur_ntime, (float)(seedv_rec->timecorr)/TIMECORRUNIT,
1097                                &cur_ntime, status );
1098                        if  (Severe(status))  return;
1099                } /*endif*/
1100                tdiff_start = tc_ndiff( &req_ntime, &cur_ntime, status );
1101                if  (Severe(status))  return;
1102                cur_span = (float)(seedv_rec->no_of_samples) * dt;
1103        } /*endwhile*/
1104
1105        /* step one record back to get it again on next read command */
1106        seek_pos = (INT32)(--(fd->pos)) * (INT32)(fd->reclth) + (INT32)(fd->byteoff);
1107        lseek( fd->ufd, seek_pos, SEEK_SET );
1108
1109        if  (tdiff_start >= 0.0)  {
1110                /* now found it */
1111                fd->sample = Nint( tdiff_start/dt );
1112                if  (fd->sample >/*=*/ (int)(seedv_rec->no_of_samples))  {
1113                        printf( "! SeedSearchPosition: sample position adjusted (2)\n" );
1114                        fd->sample = seedv_rec->no_of_samples /*- 1*/;
1115                } /*endif*/
1116                tc_nadd( &cur_ntime, (fd->sample)*dt, &req_ntime, status );
1117                if  (Severe(status))  return;
1118                tc_n2t( &req_ntime, act_start, status );
1119        } else {
1120                /* time gap */
1121                /* printf( "*** time gap: next possible time positioned ***\n" ); */
1122                tc_n2t( &cur_ntime, act_start, status );
1123                *status = SeedERR_NEXTTIMEPOS;
1124        } /*endif*/
1125
1126} /* end of SeedSearchPosition */
1127
1128
1129
1130/*----------------------------------------------------------------------------*/
1131
1132
1133
1134void SeedBtimeToNtime( SeedBtimeT *btime, NTIME *ntime, STATUS *status )
1135
1136/* converts SeedBtimeT to NTIME
1137 *
1138 * parameters of routine
1139 * SeedBtimeT *bt;      input; SEED binary time
1140 * NTIME      *nt;      output; KS numeric time
1141 * STATUS     *status;  output; return status
1142 */
1143{
1144        /* executable code */
1145
1146        ntime->year = btime->year;
1147        tc_dayofmn( btime->year, btime->day, &(ntime->month),
1148                &(ntime->day), status );
1149        if  (Severe(status))  return;
1150        ntime->hour = btime->hours;
1151        ntime->min = btime->minutes;
1152        ntime->sec = btime->seconds;
1153        ntime->ms = btime->frac_secs/10;
1154
1155} /* end of SeedBtimeToNtime */
1156
1157
1158
1159/*----------------------------------------------------------------------------*/
1160
1161
1162
1163void SeedNtimeToBtime( NTIME *ntime, SeedBtimeT *btime, STATUS *status )
1164
1165/* converts NTIME to BTIME
1166 *
1167 * parameters of routine
1168 * NTIME      *nt;      input; KS numeric time
1169 * BTIME      *bt;      output; SEED binary time
1170 * STATUS     *status;  output; return status
1171 */
1172{
1173        /* executable code */
1174
1175        btime->year = ntime->year;
1176        btime->day = tc_julian( ntime->year, ntime->month,
1177                ntime->day, status );
1178        if  (Severe(status))  return;
1179        btime->hours = ntime->hour;
1180        btime->minutes = ntime->min;
1181        btime->seconds = ntime->sec;
1182        btime->frac_secs = ntime->ms*10;
1183
1184} /* end of SeedNtimeToBtime */
1185
1186
1187
1188/*---------------------------------------------------------------------*/
1189
1190
1191
1192float SeedGetSampleDist( SeedDataHeaderT *hdr )
1193
1194/* Returns sample distance in sec.
1195 *
1196 * parameters of routine
1197 * SeedDataHeaderT  *hdr;        input; SEED data header
1198 *                               returns sample distance in sec
1199 */
1200{
1201        /* executable code */
1202
1203        if  (hdr->smprate_fact > 0 && hdr->smprate_mult > 0)  {
1204                return (1.0/((float)(hdr->smprate_fact) * (float)(hdr->smprate_mult)));
1205        } else if  (hdr->smprate_fact > 0 && hdr->smprate_mult < 0)  {
1206                return (-1.0/((float)(hdr->smprate_fact)/(float)(hdr->smprate_mult)));
1207        } else if  (hdr->smprate_fact < 0 && hdr->smprate_mult > 0)  {
1208                return (-1.0/((float)(hdr->smprate_mult)/(float)(hdr->smprate_fact)));
1209        } else if  (hdr->smprate_fact < 0 && hdr->smprate_mult < 0)  {
1210                return (1.0/((float)(hdr->smprate_fact)/(float)(hdr->smprate_mult)));
1211        } else {
1212                fprintf( stderr, "*** illegal sample rate, set dt=1.0\n" );
1213                return 1.0;
1214        } /*endif*/
1215
1216} /* end of SeedGetSampleDist */
1217
1218
1219
1220/*---------------------------------------------------------------------*/
1221
1222
1223
1224void SeedReadNextRecord( int chan, SeedSbyteT *rec, BOOLEAN *hdr_swapped,
1225        STATUS *status )
1226
1227/* Reads next available record from SEED file.  If the header must be
1228 * swapped this is done and indicated in '*hdr_swapped'.
1229 *
1230 * parameters of routine
1231 * int        chan;               input; channel number
1232 * SeedSbyteT *rec;               output; SEED record
1233 * BOOLEAN    *hdr_swapped;       output; tells whether header was swapped
1234 * STATUS     *status;            output; return status
1235 */
1236{
1237        /* local variables */
1238        SeedFileDescrT *fd;                  /* SEED file descriptor */
1239        char     l_sfdfile[BC_FILELTH+1];    /* local sfdfile */
1240        char     l_stream[BC_SHORTSTRLTH+1]; /* local stream string */
1241        char     l_t_end[BC_TIMELTH+1];      /* end of file time */
1242        char     act_time[BC_TIMELTH+1];     /* positioned time */
1243        BOOLEAN  time_gap;                   /* time gap found */
1244
1245        /* executable code */
1246
1247        /* check channel number */
1248        if  (chan < 0 || chan >= Seed_C_MAXCHAN)  {
1249                *status = SeedERR_CHAN_OOR;
1250                return;
1251        } /*endif*/
1252        fd = seedv_fd + chan;
1253
1254        if  (fd->ufd == Seed_C_ILLEGAL)  {
1255                *status = SeedERR_NOT_OPEN;
1256                return;
1257        } /*endif*/
1258
1259        /* store filename for last used file request */
1260        strcpy( seedv_last_fname, fd->name );
1261
1262        time_gap = FALSE;
1263        if  (fd->pos >= fd->recno)  {
1264                /* is at end of file */
1265                strcpy( l_sfdfile, fd->sfdfile );
1266                strcpy( l_stream, fd->stream );
1267                strcpy( l_t_end, fd->t_end );
1268                SeedSearchPosition( chan, l_sfdfile, l_stream, l_t_end,
1269                        act_time, status );
1270                time_gap = (*status == SeedERR_NEXTTIMEPOS);
1271                if  (time_gap)  *status = BC_NOERROR;
1272                if  (Severe(status))  return;
1273        } /*endif*/
1274
1275        if  (seedv_logrec)  printf( "[%d]", fd->pos );  /* log */
1276        if  (read(fd->ufd,(char *)rec,fd->reclth) != fd->reclth)  {
1277                *status = SeedERR_SEEDREAD;
1278                err_setcontext( " ## file " );
1279                err_setcontext( fd->name );
1280                return;
1281        } /*endif*/
1282        (fd->pos)++;
1283        SeedStoreReclth( (SeedDataHeaderT *)rec, fd->reclth );
1284        if  (fd->swap_hdr)  SeedSwapHeader( (SeedDataHeaderT *)rec );
1285        *hdr_swapped = fd->swap_hdr;
1286
1287        if  (time_gap)  *status = SeedERR_NEXTTIMEPOS;
1288
1289} /* end of SeedReadNextRecord */
1290
1291
1292
1293/*---------------------------------------------------------------------*/
1294
1295
1296
1297void SeedEncodeSteim1( int fd, INT32 smp[], INT32 *prev_smp, INT32 *idx,
1298        NTIME *ctime, SeedSbyteT *wrk, int wrklth, BOOLEAN complete, STATUS *status )
1299
1300/* Encodes sample array smp to SEED output file fd (UNIX file descriptor).
1301 * If complete is set to TRUE the last (probably not completely used)
1302 * record is written to the file, otherwise the samples of the
1303 * last record remain in the sample array.
1304 *
1305 * parameters of routine
1306 * int        fd;            input; UNIX file descr of output file
1307 * INT32      smp[];         modify; sample array to encode
1308 * INT32      *prev_smp;     modify; last sample before smp[0]
1309 * INT32      *idx;          modify; length of sample array
1310 * NTIME      *ctime;        modify; input: start time, output: new start time
1311 * SeedSbyteT *wrk;          scratch; work space for encoding
1312 * int        wrklth;        input; length of work space in records
1313 * BOOLEAN    complete;      input; finish up all records (-> *idx == 0)
1314 * STATUS     *status;       output; return status
1315 */
1316{
1317        /* local variables */
1318        static int rec_cnt=1;            /* record counter */
1319        int      recs_used;              /* number of records used */
1320        SeedDataHeaderT *hdr;            /* SEED data header */
1321        int      i;                      /* counter */
1322        char     str[BC_SHORTSTRLTH+1];  /* scratch string */
1323        int      write_ret;              /* write return value */
1324        int      smp_written;            /* total number of samples written to file*/
1325        float    dt;                     /* sample distance */
1326        int      rlexp;                  /* record length exponent */
1327        SeedBlockette1000T *b1000;       /* blockette 1000 */
1328        SeedBlockette1001T *b1001;       /* blockette 1001 */
1329
1330        /* executable code */
1331
1332        /* put start time to header prototype */
1333        SeedNtimeToBtime( ctime, &seedv_hdr_proto.starttime, status );
1334        if  (Severe(status))  return;
1335
1336        if  (*idx <= 0)  return;
1337
1338        /* compute record length exponent, needed for blockette 1000 */
1339        i = 1;
1340        rlexp = 0;
1341        while  (i < seedv_out_reclth)  {
1342                i *= 2;
1343                rlexp++;
1344        } /*endif*/
1345
1346        /* encode data */
1347        recs_used = (int)Steim_comp( smp, (DATA_HEADER *)&seedv_hdr_proto,
1348                (UINT32)(*idx), (WORD)(seedv_out_reclth), (INT32 *)wrk, *prev_smp);
1349        if  (recs_used > wrklth)  {
1350                fprintf( stderr,
1351                        "***!!! SeedEncodeSteim1: record array exceeded -> abort !!!***\n" );
1352                exit( 1 );
1353        } /*endif*/
1354
1355        /* if last record not to be written, keep it in smp-buffer */
1356        if  (complete)  {
1357                *prev_smp = (*idx > 0) ? smp[(*idx)-1] : 0;
1358                *idx = 0;
1359        } else {
1360                if  (recs_used == 1)  {
1361                        /* printf( "*** SeedEncodeSteim1: only 1 record, no flush\n" ); */
1362                        return;
1363                } /*endif*/
1364                hdr = (SeedDataHeaderT *)(wrk + (recs_used-1)*seedv_out_reclth);
1365                *prev_smp = smp[(*idx)-hdr->no_of_samples-1];
1366                memcpy( (char *)smp, (char *)(smp+(*idx)-(int)(hdr->no_of_samples)),
1367                        (int)(hdr->no_of_samples)*sizeof(INT32) );
1368                *idx = hdr->no_of_samples;
1369                recs_used--;
1370        } /*endif*/
1371
1372        /* write records to file */
1373        smp_written = 0;
1374        for  (i=0; i<recs_used; i++)  {
1375                hdr = (SeedDataHeaderT *)(wrk+i*seedv_out_reclth);
1376                sprintf( str, "%06d", rec_cnt++ );
1377                strncpy( (char *)hdr, str, 6 );
1378                hdr->Reserved_bytes_A = ' ';
1379                /* insert blockette 1000, 14-Apr-2005 */
1380                hdr->no_of_blockettes = 1;
1381                hdr->first = 48;
1382                b1000 = (SeedBlockette1000T *)((char *)hdr + (unsigned)(hdr->first));
1383                b1000->type = 1000;
1384                b1000->nextblock = 0;
1385                b1000->format = (UBYTE)Seed_C_DcmpSteim1;
1386                b1000->wordorder = (UBYTE)1;
1387                b1000->reclthexp = (UBYTE)rlexp;
1388                b1000->reserved = (UBYTE)0;
1389                /* end of blockette 1000 code */
1390                /* insert blockette 1001 if time quality >= 0 */
1391                if  (seedv_timequal >= 0)  {
1392                        hdr->no_of_blockettes = 2;
1393                        b1000->nextblock = 56;
1394                        b1001 = (SeedBlockette1001T *)((char *)hdr + (unsigned)(b1000->nextblock));
1395                        b1001->type = 1001;
1396                        b1001->nextblock = 0;
1397                        b1001->timequal = (UBYTE)seedv_timequal;
1398                        b1001->reserved = (UBYTE)0;
1399                        /* reset timequal to -1 */
1400                        seedv_timequal = -1;
1401                } /*endif*/
1402                /* end of blockette 1001 code */
1403#               ifdef cBc_OS_LINUX
1404                SeedStoreReclth( hdr, seedv_out_reclth );
1405                SeedSwapHeader( hdr );
1406                SeedSwapLinuxRecord( (SeedSbyteT *)hdr, seedv_out_reclth );
1407#               endif
1408                write_ret = (int)write( fd, (char *)hdr, seedv_out_reclth );
1409#               ifdef cBc_OS_LINUX
1410                /* swap it back otherwise not readable any more */
1411                SeedSwapHeader( hdr );
1412                SeedSwapLinuxRecord( (SeedSbyteT *)hdr, seedv_out_reclth );
1413#               endif
1414                if  (write_ret != seedv_out_reclth)  {
1415                        *status = SeedERR_SEEDWRITE;
1416                        return;
1417                } /*endif*/
1418                smp_written += hdr->no_of_samples;
1419        } /*endfor*/
1420
1421        /* update start time */
1422        dt = SeedGetSampleDist( hdr );
1423        tc_nadd( ctime, (float)smp_written*dt, ctime, status );
1424
1425} /* end of SeedEncodeSteim1 */
1426
1427
1428
1429/*---------------------------------------------------------------------*/
1430
1431
1432
1433void SeedEncodeSteim1Chan( int fd, INT32 smp[], INT32 *prev_smp, INT32 *idx,
1434        NTIME *ctime, int *reccnt, SeedDataHeaderT *seedhdr, SeedSbyteT *wrk,
1435        int wrklth, BOOLEAN complete, STATUS *status )
1436
1437/* Encodes sample array smp to SEED output file fd (UNIX file descriptor).
1438 * If complete is set to TRUE the last (probably not completely used)
1439 * record is written to the file, otherwise the samples of the
1440 * last record remain in the sample array.
1441 *
1442 * This is the same routine as SeedEncodeSteim1Chan except two additional
1443 * parameters reccnt and seedhdr.
1444 *
1445 * parameters of routine
1446 * int        fd;            input; UNIX file descr of output file
1447 * INT32      smp[];         modify; sample array to encode
1448 * INT32      *prev_smp;     modify; last sample before smp[0]
1449 * INT32      *idx;          modify; length of sample array
1450 * NTIME      *ctime;        modify; input: start time, output: new start time
1451 * int        *reccnt;       modify; record counter
1452 * SeedDataHeaderT *seedhdr; modify; SEED data header
1453 * SeedSbyteT *wrk;          scratch; work space for encoding
1454 * int        wrklth;        input; length of work space in records
1455 * BOOLEAN    complete;      input; finish up all records (-> *idx == 0)
1456 * STATUS     *status;       output; return status
1457 */
1458{
1459        /* local variables */
1460        int      recs_used;              /* number of records used */
1461        SeedDataHeaderT *hdr;            /* SEED data header */
1462        int      i;                      /* counter */
1463        char     str[BC_SHORTSTRLTH+1];  /* scratch string */
1464        int      write_ret;              /* write return value */
1465        int      smp_written;            /* total number of samples written to file*/
1466        float    dt;                     /* sample distance */
1467
1468        /* executable code */
1469
1470        /* put start time to header prototype */
1471        SeedNtimeToBtime( ctime, &(seedhdr->starttime), status );
1472        if  (Severe(status))  return;
1473
1474        if  (*idx <= 0)  return;
1475
1476        /* encode data */
1477        recs_used = (int)Steim_comp( smp, (DATA_HEADER *)seedhdr,
1478                (UINT32)(*idx), (WORD)(seedv_out_reclth), (INT32 *)wrk, *prev_smp );
1479        if  (recs_used > wrklth)  {
1480                fprintf( stderr,
1481                        "***!!! SeedEncodeSteim1: record array exceeded -> abort !!!***\n" );
1482                exit( 1 );
1483        } /*endif*/
1484
1485        /* if last record not to be written, keep it in smp-buffer */
1486        if  (complete)  {
1487                *prev_smp = (*idx > 0) ? smp[(*idx)-1] : 0;
1488                *idx = 0;
1489        } else {
1490                if  (recs_used == 1)  {
1491                        /* printf( "*** SeedEncodeSteim1: only 1 record, no flush\n" ); */
1492                        return;
1493                } /*endif*/
1494                hdr = (SeedDataHeaderT *)(wrk + (recs_used-1)*seedv_out_reclth);
1495                *prev_smp = smp[(*idx)-hdr->no_of_samples-1];
1496                memcpy( (char *)smp, (char *)(smp+(*idx)-(int)(hdr->no_of_samples)),
1497                        (int)(hdr->no_of_samples)*sizeof(INT32) );
1498                *idx = hdr->no_of_samples;
1499                recs_used--;
1500        } /*endif*/
1501
1502        /* write records to file */
1503        smp_written = 0;
1504        for  (i=0; i<recs_used; i++)  {
1505                hdr = (SeedDataHeaderT *)(wrk+i*seedv_out_reclth);
1506                sprintf( str, "%06d", *(reccnt)++ );
1507                strncpy( (char *)hdr, str, 6 );
1508                hdr->Reserved_bytes_A = ' ';
1509#               ifdef cBc_OS_LINUX
1510                SeedStoreReclth( hdr, seedv_out_reclth );
1511                SeedSwapHeader( hdr );
1512                SeedSwapLinuxRecord( (SeedSbyteT *)hdr, seedv_out_reclth );
1513#               endif
1514                write_ret = (int)write( fd, (char *)hdr, seedv_out_reclth );
1515#               ifdef cBc_OS_LINUX
1516                /* swap it back otherwise not readable any more */
1517                SeedSwapHeader( hdr );
1518                SeedSwapLinuxRecord( (SeedSbyteT *)hdr, seedv_out_reclth );
1519#               endif
1520                if  (write_ret != seedv_out_reclth)  {
1521                        *status = SeedERR_SEEDWRITE;
1522                        return;
1523                } /*endif*/
1524                smp_written += hdr->no_of_samples;
1525        } /*endfor*/
1526
1527        /* update start time */
1528        dt = SeedGetSampleDist( hdr );
1529        tc_nadd( ctime, (float)smp_written*dt, ctime, status );
1530
1531} /* end of SeedEncodeSteim1Chan */
1532
1533
1534
1535/*---------------------------------------------------------------------*/
1536
1537
1538
1539void SeedSetHeaderPrototype( SeedDataHeaderT *hdr )
1540
1541/* copies data header to global variables
1542 *
1543 * parameters of routine
1544 * SeedDataHeaderT *hdr;        input; data header prototype
1545 */
1546{
1547        /* executable code */
1548
1549        seedv_hdr_proto = *hdr;
1550
1551} /* end of SeedSetHeaderPrototype */
1552
1553
1554
1555/*---------------------------------------------------------------------*/
1556
1557
1558
1559void SeedRecordTime( SeedSbyteT *rec, NTIME *start, NTIME *end,
1560        STATUS *status )
1561
1562/* Returns start and end time of SEED record
1563 *
1564 * parameters of routine
1565 * SeedSbyteT *rec;           input; SEED record
1566 * NTIME      *start;         output; start time of record
1567 * NTIME      *end;           output; end time of record
1568 * STATUS     *status;        output; return status
1569 */
1570{
1571        /* local variables */
1572        SeedDataHeaderT *hdr;    /* pointer to data header */
1573        float    dt;            /* sample distance in sec */
1574
1575        /* executable code */
1576
1577        hdr = (SeedDataHeaderT *)rec;
1578
1579        SeedBtimeToNtime( &(hdr->starttime), start, status );
1580        if  (Severe(status))  return;
1581        dt = SeedGetSampleDist( hdr );
1582        tc_nadd( start, dt*(float)(hdr->no_of_samples), end, status );
1583        if  (Severe(status))  return;
1584
1585        if  (seedv_use_timecorr && (hdr->timecorr != 0)
1586                && (((int)(hdr->activity) & Seed_F_ACT_TIMECORRAPP) == 0))  {
1587                tc_nadd( start, (float)(hdr->timecorr)/TIMECORRUNIT, start, status );
1588                tc_nadd( end, (float)(hdr->timecorr)/TIMECORRUNIT, end, status );
1589        } /*endif*/
1590
1591} /* end of SeedRecordTime */
1592
1593
1594
1595/*---------------------------------------------------------------------*/
1596
1597
1598
1599#define BUFLTH 4096
1600/* should be enough for decoding one record */
1601
1602#define FREE_AND_RETURN         sy_deallocmem( smp ); \
1603                                                                        sy_deallocmem( buf ); \
1604                                                                        sy_deallocmem( encode ); \
1605                                                                        close( out ); \
1606                                                                        return
1607/* on failure free all memory */
1608
1609
1610
1611
1612void SeedCopy( int chan, char sfdfile[], char fname[], char stream[],
1613        char req_begin[], char req_end[], char act_begin[], char act_end[],
1614        STATUS *status )
1615
1616/* Copies SEED stream to SEED file
1617 *
1618 * parameters of routine
1619 * int        chan;           input; channel to be used
1620 * char       sfdfile[];      input; name of sfd-file for input data
1621 * char       fname[];        input; name of output file
1622 * char       stream[];       input; stream string
1623 * char       req_begin[];    input; requested start time
1624 * char       req_end[];      input; requested end time
1625 * char       act_begin[];    output; actual start time
1626 * char       act_end[];      output; actual end time
1627 * char       *status;        output; return status
1628 */
1629{
1630        /* local variables */
1631        NTIME    rec_start;        /* record start time */
1632        NTIME    rec_end;          /* record end time */
1633        NTIME    n_end;            /* request end time */
1634        INT32    *smp;             /* pointer to sample array */
1635        INT32    idx;              /* sample index */
1636        INT32    *buf;             /* one record buffer */
1637        INT32    buflth;           /* length of buffer */
1638        SeedSbyteT *encode;        /* encode buffer */
1639        int      encode_lth;       /* length of encode buffer in records */
1640        float    tdiff;            /* time difference */
1641        float    dt;               /* sample distance in sec */
1642        int      out;              /* UNIX file descriptor of output file */
1643        float    rec_span;         /* time span of record */
1644        int      i;                /* counter */
1645        BOOLEAN  quit;             /* quit loop */
1646        INT32    smp_written;      /* number of samples written */
1647        NTIME    ntime;            /* scratch time */
1648        BOOLEAN  hdr_swapped;      /* header was swapped */
1649
1650        /* executable code */
1651
1652        /* allocate memory */
1653        smp = (INT32 *)sy_allocmem( seedv_setup.copy_buf_lth, (int)sizeof(INT32),
1654                status );
1655        if  (Severe(status))  return;
1656        buf = (INT32 *)sy_allocmem( BUFLTH, (int)sizeof(INT32), status );
1657        if  (Severe(status))  {
1658                sy_deallocmem( smp );
1659                return;
1660        } /*endif*/
1661        /* encode buffer approximately of equal size as sample buffer 'smp'. */
1662        /* In the worst case this is not enough, but it is very unlikely.    */
1663        encode_lth = (int)(seedv_setup.copy_buf_lth*(int)sizeof(INT32)
1664                / seedv_out_reclth + 1);
1665        encode = (SeedSbyteT *)sy_allocmem( encode_lth, seedv_out_reclth,
1666                status );
1667        if  (Severe(status))  {
1668                sy_deallocmem( smp );
1669                sy_deallocmem( buf );
1670                return;
1671        } /*endif*/
1672
1673        /* open output file */
1674        out = open( fname, O_WRONLY|O_CREAT|O_TRUNC, 0x1ff );
1675        if  (out < 0)  {
1676                *status = SeedERR_OPENOUTPUT;
1677                err_setcontext( " ## file " );
1678                err_setcontext( fname );
1679                sy_deallocmem( smp );
1680                sy_deallocmem( buf );
1681                sy_deallocmem( encode );
1682        } /*endif*/
1683
1684        /* position input file to requested time */
1685        SeedSearchPosition( chan, sfdfile, stream, req_begin, act_begin, status );
1686        if  (Severe(status))  {FREE_AND_RETURN;}
1687        /* check if there are any data in this time window */
1688        if  (tc_tdiff(act_begin,req_end,status) >= 0.0)  {
1689                *status = SeedERR_TIMEGAP;
1690                err_setcontext( " ## no data in requested time window" );
1691                FREE_AND_RETURN;
1692        } /*endif*/
1693        /* initialize values for loop */
1694        tc_t2n( act_begin, &rec_end, status );
1695        if  (Severe(status))  {FREE_AND_RETURN;}
1696        tc_t2n( req_end, &n_end, status );
1697        if  (Severe(status))  {FREE_AND_RETURN;}
1698        SeedNtimeToBtime( &rec_end, &seedv_hdr_proto.starttime, status );
1699        if  (Severe(status))  {FREE_AND_RETURN;}
1700        /* !!! set record number !!! */
1701        /* !!! apply time correction !!! */
1702
1703        idx = 0;
1704        quit = FALSE;
1705
1706        do  {
1707
1708                /* decode next record */
1709                SeedReadNextRecord( chan, (SeedSbyteT *)seedv_rec, &hdr_swapped, status );
1710                if  (Severe(status))  {FREE_AND_RETURN;}
1711                SeedBtimeToNtime( &(seedv_rec->starttime), &rec_start, status );
1712                if  (Severe(status))  {FREE_AND_RETURN;}
1713                SeedDecodeSteim1( (SeedSbyteT *)seedv_rec, !hdr_swapped,
1714                        BUFLTH, buf, &buflth );
1715                if  (buflth != (INT32)(seedv_rec->no_of_samples))  {
1716                        fprintf( stderr, "*** inconsistency in sample length: should be %ld, is %ld\n",
1717                                (INT32)(seedv_rec->no_of_samples), buflth );
1718                } /*endif*/
1719                dt = SeedGetSampleDist( seedv_rec );
1720                /* if decoded values do not fit into smp-array, write it out */
1721                if  (idx+buflth > seedv_setup.copy_buf_lth)  {
1722                        SeedBtimeToNtime( &seedv_hdr_proto.starttime, &ntime, status );
1723                        if  (Severe(status))  {FREE_AND_RETURN;}
1724                        smp_written = idx;
1725                        SeedEncodeSteim1( out, smp, 0, &idx, &ntime, encode, encode_lth,
1726                                FALSE, status );
1727                        if  (Severe(status))  {FREE_AND_RETURN;}
1728                        smp_written -= idx;
1729                        /* tc_nadd( &ntime, (float)smp_written*dt, &ntime, status ); */
1730                        /* if  (Severe(status))  {FREE_AND_RETURN;} */
1731                        /* SeedNtimeToBtime( &ntime, &seedv_hdr_proto.starttime, status ); */
1732                        /* if  (Severe(status))  {FREE_AND_RETURN;} */
1733                } /*endif*/
1734                /* now check for time gap */
1735                rec_span = dt * (float)(seedv_rec->no_of_samples);
1736                tdiff = tc_ndiff( &rec_start, &rec_end, status );
1737                if  (Severe(status))  {FREE_AND_RETURN;}
1738                /* if there is a time gap, flush smp-buffer and start new record */
1739                if  (Abs(tdiff) > dt)  {
1740                        printf( "! time gap\n" );
1741                        SeedEncodeSteim1( out, smp, 0, &idx, &ntime, encode, encode_lth, TRUE,
1742                                status );
1743                        if  (Severe(status))  {FREE_AND_RETURN;}
1744                        seedv_hdr_proto.starttime = seedv_rec->starttime;
1745                } /*endif*/
1746                /* compute end time for this record, used in next loop */
1747                tc_nadd( &rec_start, rec_span, &rec_end, status );
1748                if  (Severe(status))  {FREE_AND_RETURN;}
1749                /* check whether requested end time is reached */
1750                tdiff = tc_ndiff( &rec_end, &n_end, status );
1751                if  (tdiff >= 0.0)  {
1752                        /* if end time reached decrease buflth ... */
1753                        tdiff = tc_ndiff( &n_end, &rec_start, status );
1754                        if  (Severe(status))  {FREE_AND_RETURN;}
1755                        buflth = Nint( tdiff / dt );
1756                        /* ... and compute actual end time */
1757                        tc_nadd( &rec_start, dt*(float)buflth, &n_end, status );
1758                        if  (Severe(status))  {FREE_AND_RETURN;}
1759                        tc_n2t( &n_end, act_end, status );
1760                        if  (Severe(status))  {FREE_AND_RETURN;}
1761                        quit = TRUE;
1762                } /*endif*/
1763                /* now add decoded values to smp-array */
1764                for  (i=0; i<buflth; i++)
1765                        smp[idx++] = buf[i];
1766                /* if end time found, flush buffer and exit loop */
1767                if  (quit)
1768                        SeedEncodeSteim1( out, smp, 0, &idx, &ntime, encode, encode_lth, TRUE,
1769                                status );
1770
1771        }  while (!quit);
1772
1773        FREE_AND_RETURN;
1774
1775} /* end of SeedCopy */
1776
1777
1778#undef FREE_AND_RETURN
1779
1780
1781/*---------------------------------------------------------------------*/
1782
1783
1784
1785#define DO_ABORT \
1786        *status = SeedERR_SFD_READ; \
1787        err_setcontext( " ## string " ); err_setcontext( line-1 ); \
1788        return;
1789
1790
1791
1792
1793void SeedParseSfdLine( char line[], SeedFileDescrT *fd, STATUS *status )
1794
1795/* parses line of SFD file.  Returns structure elements 'stream',
1796 * 't_start', 't_end', 'name', 'recno' and 'calib'.
1797 *
1798 * parameters of routine
1799 * char       line[];       input; SFD line
1800 * SeedFileDescrT *fd;      output; SEED file descriptor
1801 * STATUS     *status;      output; return status
1802 */
1803{
1804        /* local variables */
1805
1806        /* executable code */
1807
1808        fd->t_start[0] = '\0';
1809        fd->t_end[0] = '\0';
1810        fd->name[0] = '\0';
1811        fd->stream[0] = '\0';
1812        fd->recno = 0;
1813        fd->reclth = DEFAULT_RECLTH;
1814        fd->byteoff = 0;
1815        fd->calib = 0.0;
1816        fd->dataflags = 0;
1817        fd->swap_hdr = FALSE;
1818        fd->pri = 0;
1819        fd->dataformat = Seed_C_FORMAT_MSEED;
1820        strcpy( fd->addinf, Seed_C_EmptyAddinfStr );
1821
1822        FOREVER  {
1823
1824                if  (*line == '>')  line++;
1825                line = strchr( line, '>' );
1826                if  (line == NULL)  break;
1827                switch  (*(line-1))  {
1828                case Seed_C_SfdTStart:
1829                        if  (sscanf(line+1,"%s",fd->t_start) != 1)  { DO_ABORT }
1830                        break;
1831                case Seed_C_SfdTEnd:
1832                        if  (sscanf(line+1,"%s",fd->t_end) != 1)  { DO_ABORT }
1833                        break;
1834                case Seed_C_SfdName:
1835                        if  (sscanf(line+1,"%s",fd->name) != 1)  { DO_ABORT }
1836                        break;
1837                case Seed_C_SfdStream:
1838                        if  (sscanf(line+1,"%s",fd->stream) != 1)  { DO_ABORT }
1839                        break;
1840                case Seed_C_SfdRecno:
1841                        if  (sscanf(line+1,"%d",&(fd->recno)) != 1)  { DO_ABORT }
1842                        break;
1843                case Seed_C_SfdReclth:
1844                        if  (sscanf(line+1,"%d",&(fd->reclth)) != 1)  { DO_ABORT }
1845                        break;
1846                case Seed_C_SfdOffset:
1847                        if  (sscanf(line+1,"%d",&(fd->byteoff)) != 1)  { DO_ABORT }
1848                        break;
1849                case Seed_C_SfdCalib:
1850                        if  (sscanf(line+1,"%f",&(fd->calib)) != 1)  { DO_ABORT }
1851                        break;
1852                case Seed_C_SfdSwapH:
1853                        if  (sscanf(line+1,"%d",&(fd->swap_hdr)) != 1)  { DO_ABORT }
1854                        if  (seedv_invert_swap_hdr)  fd->swap_hdr = ! fd->swap_hdr;
1855                        break;
1856                case Seed_C_SfdAddinf:
1857                        strncpy( fd->addinf, line+1, Seed_C_AddinfLth);
1858                        fd->addinf[Seed_C_AddinfLth] = '\0';
1859                        ut_uncap( fd->addinf );
1860                        break;
1861                } /*endswitch*/
1862
1863        } /*endfor*/
1864
1865} /* end of SeedParseSfdLine */
1866
1867
1868
1869#undef DO_ABORT
1870
1871
1872
1873/*---------------------------------------------------------------------*/
1874
1875
1876
1877void SeedReadStream( int chan, char sfdfile[], char stream_str[],
1878        BOOLEAN swap, char req_start[], float seclth, INT32 **ldat,
1879        INT32 *smplth, char act_start[], float *dt, float *calib,
1880        int *flags, STATUS *status )
1881
1882/* Reads sample data from SEED stream.  The memory for the sample
1883 * data is allocated by the routine.  The channel number is chosen
1884 * by the caller of the routine.  It is legal to use always channel
1885 * number 0 but it is faster to use a separate channel number for
1886 * each stream used if the streams are read repeatedly.
1887 *
1888 * parameters of routine
1889 * int        chan;         input; channel number (0..Seed_C_MAXCHAN-1)
1890 * char       sfdfile[];    input; name of sfd file to use
1891 * char       stream_str[]; input; stream string (like "bfo-vbb-z")
1892 * BOOLEAN    swap;         input; swap bytes on file
1893 * char       req_start[];  input; requested start time
1894 * float      seclth;       input; number of seconds to be read
1895 * INT32      **ldat;       output; sample array read
1896 * INT32      *smplth;      output; number of samples read
1897 * char       act_start[];  output; actual start time
1898 * float      *dt;          output; sample distance in sec
1899 * float      *calib;       output; calibration constant
1900 * int        *flags;       output; data flags found
1901 * STATUS     *status;      output; return status
1902 */
1903{
1904        /* local variables */
1905        SeedFileDescrT *fd;   /* pointer to SEED file descriptor */
1906        INT32    getlth;      /* number of samples to read */
1907        INT32    maxrecsmp;   /* maximum number of samples per record */
1908        INT32    actrecsmp;   /* actual number of samples in record */
1909        INT32    *recsmp;     /* pointer to samples of record */
1910        INT32    *lsrc, *ldst;/* moving pointers */
1911        NTIME    recstart;    /* record start time */
1912        NTIME    recend;      /* record end time */
1913        NTIME    expectime;   /* expected time */
1914        float    tdiff;       /* time gap in sec */
1915        INT32    padcnt;      /* counter for zero padding */
1916        char     str[BC_TIMELTH+1];  /* scratch string for time output */
1917        BOOLEAN  swap_data;   /* swap data */
1918        int      i;           /* counter */
1919        char     recmsg[cBcLineLth+1];  /* output string */
1920        int      eloop_cnt;   /* endless loop preventer: counter */
1921        float    eloop_ratio; /* endless loop preventer; samples gained per loop */
1922
1923        /* executable code */
1924
1925        /* check channel number */
1926        if  (chan < 0 || chan >= Seed_C_MAXCHAN)  {
1927                *status = SeedERR_CHAN_OOR;
1928                return;
1929        } /*endif*/
1930        fd = seedv_fd + chan;
1931
1932        /* find requested position */
1933        tdiff = 0.0;
1934        SeedSearchPosition( chan, sfdfile, stream_str, req_start,
1935                act_start, status );
1936        if  (*status == SeedERR_NEXTTIMEPOS)  {
1937                *status = BC_NOERROR;
1938                tdiff = tc_tdiff( act_start, req_start, status );
1939                if  (Severe(status))  return;
1940                if  (tdiff >= seclth)  {*status = SeedERR_DATA_UNAVAIL; return;}
1941                fprintf( stderr,
1942                        "SeedReadStream: time %s not found, start at %s\n",
1943                        req_start, act_start );
1944        } /*endif*/
1945        if  (Severe(status))  return;
1946
1947        maxrecsmp = MAX_SMP_PER_REC;
1948        *smplth = 0;
1949        *ldat = NULL;
1950        recsmp = NULL;
1951        *dt = 0.0;
1952        expectime.year = 0;
1953        eloop_cnt = 0;
1954        /* reset decode routine */
1955        SeedDecodeSteim1( NULL, swap, 0, NULL, NULL );
1956
1957        FOREVER  {
1958
1959                /* read next record */
1960                SeedReadNextRecord( chan, (SeedSbyteT *)seedv_rec, &swap_data, status );
1961                if  (swap)  swap_data = !swap_data;
1962                if  (*status == SeedERR_NEXTTIMEPOS)  *status = BC_NOERROR;
1963                if  (*status == SeedERR_SFD_NOTFOUND && *smplth > 0)  {
1964                        /* last part of trace not available, truncate data */
1965                        *status = BC_NOERROR;
1966            fprintf( stderr, "*Seed: data truncated to %d samples\n", *smplth );
1967                        break;
1968                } /*endif*/
1969                if  (Severe(status))  return;
1970
1971                /* decode SEED record and select samples */
1972                /* ------------------------------------- */
1973                if  (*ldat == NULL)  {
1974
1975                        /* this is for first loop only */
1976                        /* --------------------------- */
1977                        *calib = fd->calib;
1978                        *flags = fd->dataflags;
1979                        if  (seedv_rec->quality != 0)  {
1980                                if  (GpGetInt(cGpI_debug_level > 0))
1981                                        printf( "SHM-dbg1: SEED quality flags: 0x%x\n",
1982                                                (int)seedv_rec->quality );
1983                                (*flags) |= seedv_rec->quality;
1984                        } /*endif*/
1985                        *dt = SeedGetSampleDist( seedv_rec );
1986                        getlth = Nint32( seclth / *dt );
1987                        if  (getlth <= 0)  {*status = SeedERR_ZEROLTH; return;}
1988                        *ldat = (INT32 *)sy_allocmem( getlth, (int)sizeof(INT32), status );
1989                        if  (Severe(status))  return;
1990                        ldst = *ldat;
1991                        recsmp = (INT32 *)sy_allocmem( maxrecsmp, (int)sizeof(INT32), status );
1992                        if  (Severe(status))  {sy_deallocmem(*ldat); return;}
1993                        /* if time gap at beginning, pad zeroes */
1994                        if  (tdiff > 0.0)  {
1995                                /* pad with zeroes and adjust start time */
1996                                padcnt = Nint32( tdiff / (*dt) );
1997                                fprintf( stderr, "SeedReadStream: record %6s, time %s\n",
1998                                        seedv_rec->seqno, act_start );
1999                                fprintf( stderr, "   gap %5.3f sec, start with %ld zeroes\n",
2000                                        tdiff, padcnt );
2001                                tc_tadd( act_start, -(*dt)*(float)padcnt, act_start, status );
2002                                if  (Severe(status))  *status = BC_NOERROR; /* ok, not elegant */
2003                                while  (padcnt-- > 0)  {
2004                                        ldst[(*smplth)++] = 0;
2005                                        if  (*smplth == getlth)  {
2006                                                sy_deallocmem( recsmp );
2007                                                fprintf( stderr,
2008                                                        "   padding aborted, %ld zeroes remaining\n", padcnt );
2009                                                strcpy( act_start, req_start );
2010                                                return;
2011                                        } /*endif*/
2012                                } /*endwhile*/
2013                        } /*endif*/
2014                        SeedDecodeSteim1( (SeedSbyteT *)seedv_rec, swap_data,
2015                                maxrecsmp, recsmp, &actrecsmp );
2016                        if  (actrecsmp != seedv_rec->no_of_samples)  {
2017                                fprintf( stderr,
2018                                        "*** seed record samples: expected %d, actual: %d\n",
2019                                        seedv_rec->no_of_samples, actrecsmp );
2020                                if  (seedv_decerr_abort)  {
2021                                        sy_deallocmem( *ldat );
2022                                        *ldat = NULL;
2023                                        sy_deallocmem( recsmp );
2024                                        *status = SeedERR_DECODE_ERR;
2025                                        return;
2026                                } else {
2027                                        INT32    zeronum;       /* number of sample to zero */
2028                                        zeronum = seedv_rec->no_of_samples;
2029                                        if  (zeronum > maxrecsmp)  zeronum = maxrecsmp;
2030                                        fprintf( stderr, "   zero %d samples and continue\n", zeronum );
2031                                        for  (i=0; i<zeronum; i++)
2032                                                recsmp[i] = 0;
2033                                } /*endif*/
2034                                actrecsmp = seedv_rec->no_of_samples;
2035                        } /*endif*/
2036                        lsrc = recsmp + fd->sample;
2037                        actrecsmp -= fd->sample;
2038                        if  (actrecsmp < 0)  {
2039                                sy_deallocmem( *ldat );
2040                                *ldat = NULL;
2041                                sy_deallocmem( recsmp );
2042                                *status = SeedERR_BUG;
2043                                fprintf( stderr, "*** SeedReadStream: bug (1) [sample: %d] ***\n",
2044                                        fd->sample );
2045                                return;
2046                        } /*endif*/
2047                        SeedRecordTime( (SeedSbyteT *)seedv_rec, &recstart, &expectime,
2048                                status );
2049                        if  (Severe(status))  return;
2050
2051                } else {
2052
2053                        /* this is for all other loops */
2054                        /* --------------------------- */
2055
2056                        /* collect data quality flags */
2057                        if  (seedv_rec->quality != 0)  {
2058                                if  (GpGetInt(cGpI_debug_level > 0))
2059                                        printf( "SHM-dbg1: SEED quality flags: %x\n",
2060                                                (int)seedv_rec->quality );
2061                                (*flags) |= seedv_rec->quality;
2062                        } /*endif*/
2063
2064                        /* decode record */
2065                        SeedDecodeSteim1( (SeedSbyteT *)seedv_rec, swap_data,
2066                                maxrecsmp, recsmp, &actrecsmp );
2067                        if  (actrecsmp != seedv_rec->no_of_samples)  {
2068                                fprintf( stderr,
2069                                        "*** seed record samples: expected %d, actual: %d\n",
2070                                        seedv_rec->no_of_samples, actrecsmp );
2071                                if  (seedv_decerr_abort)  {
2072                                        sy_deallocmem( *ldat );
2073                                        *ldat = NULL;
2074                                        sy_deallocmem( recsmp );
2075                                        *status = SeedERR_DECODE_ERR;
2076                                        return;
2077                                } else {
2078                                        INT32    zeronum;       /* number of sample to zero */
2079                                        zeronum = seedv_rec->no_of_samples;
2080                                        if  (zeronum > maxrecsmp)  zeronum = maxrecsmp;
2081                                        fprintf( stderr, "   zero %d samples and continue\n", zeronum );
2082                                        for  (i=0; i<zeronum; i++)
2083                                                recsmp[i] = 0;
2084                                } /*endif*/
2085                                actrecsmp = seedv_rec->no_of_samples;
2086                        } /*endif*/
2087                        lsrc = recsmp;
2088
2089                        /* check for time gaps, pad with zeroes */
2090                        SeedRecordTime( (SeedSbyteT *)seedv_rec, &recstart, &recend, status );
2091                        if  (Severe(status))  return;
2092                        tdiff = tc_ndiff( &recstart, &expectime, status );
2093                        if  (Severe(status))  return;
2094                        if  (tdiff <= -(*dt))  {
2095                                /* double data */
2096                                padcnt = Nint32( -tdiff / (*dt) );
2097                                tc_n2t( &recstart, str, status );
2098                                strncpy( recmsg, seedv_rec->seqno, 6 );
2099                                recmsg[6] = '\0';
2100                                fprintf( stderr, "SeedReadStream: record %6s, time %s\n",
2101                                        recmsg, str );
2102                                fprintf( stderr, "   double data, %ld samples skipped\n",
2103                                        padcnt );
2104                                if  (padcnt > (INT32)(seedv_rec->no_of_samples))  {
2105                                        /*
2106                                        *status = SeedERR_DOUBLEDATA;
2107                                        sy_deallocmem( recsmp );
2108                                        return;
2109                                        */
2110                                        fprintf( stderr, "double data; complete record skipped\n" );
2111                                        continue;
2112                                } /*endif*/
2113                                /* skip samples */
2114                                lsrc += padcnt;
2115                                actrecsmp -= padcnt;
2116                        } else if  (tdiff >= (*dt))  {
2117                                /* time gap */
2118                                padcnt = Nint32( tdiff / (*dt) );
2119                                tc_n2t( &recstart, str, status );
2120                                strncpy( recmsg, seedv_rec->seqno, 6 );
2121                                recmsg[6] = '\0';
2122                                fprintf( stderr, "ecord %6s, time %s\n",
2123                                        recmsg, str );
2124                                fprintf( stderr,
2125                                        "   gap %5.3f sec, padding %ld zeroes at sample %ld\n",
2126                                        tdiff, padcnt, *smplth );
2127                                /* pad zeroes */
2128                                while  (padcnt-- > 0)  {
2129                                        ldst[(*smplth)++] = 0;
2130                                        if  (*smplth == getlth)  {
2131                                                sy_deallocmem( recsmp );
2132                                                fprintf( stderr,
2133                                                        "   padding aborted, %ld zeroes remaining\n", padcnt );
2134                                                return;
2135                                        } /*endif*/
2136                                } /*endwhile*/
2137                        } /*endif*/
2138                        expectime = recend;
2139
2140                } /*endif*/
2141
2142                /* copy samples to output array */
2143                while  (actrecsmp-- > 0)  {
2144                        ldst[(*smplth)++] = *lsrc++;
2145                        if  (*smplth == getlth)  {  /* finished ! */
2146                                sy_deallocmem( recsmp );
2147                                return;
2148                        } /*endif*/
2149                } /*endwhile*/
2150
2151                /* endless loop preventer */
2152                eloop_cnt++;
2153                eloop_ratio = (float)(*smplth) / (float)eloop_cnt;
2154                /*printf( "********* dbg: eloop_ratio %g\n", eloop_ratio );*/
2155                if  (eloop_cnt > 100 && eloop_ratio < 10.0)  {
2156                    fprintf( stderr,
2157                                "SeedReadStream: endless loop preventer aborted after %d loops\n",
2158                                eloop_cnt );
2159                        break;
2160                } /*endif*/
2161
2162        } /*endfor*/
2163
2164} /* end of SeedReadStream */
2165
2166
2167
2168/*---------------------------------------------------------------------*/
2169
2170
2171
2172void SeedReadStreamReal( int chan, char sfdfile[], char stream_str[],
2173        BOOLEAN swap, char req_start[], float seclth, float **fdat,
2174        INT32 *smplth, char act_start[], float *dt, float *calib,
2175        int *flags, STATUS *status )
2176
2177/* Same as SeedReadStream except that a float array is returned
2178 *
2179 * parameters of routine
2180 * see SeedReadStream above
2181 */
2182{
2183        /* local variables */
2184        INT32    *lptr;         /* INT32 pointer to data array */
2185        INT32    *lp;           /* moving pointer */
2186        float    *fp;           /* moving pointer */
2187        INT32    i;             /* counter */
2188
2189        /* executable code */
2190
2191        *fdat = NULL;
2192
2193        SeedReadStream( chan, sfdfile, stream_str, swap, req_start,
2194                seclth, &lptr, smplth, act_start, dt, calib, flags, status );
2195        if  (Severe(status))  return;
2196
2197        if  (sizeof(INT32) != sizeof(float))  {
2198                printf( "--> sizeof(float) != sizeof(INT32)\n" );
2199                *status = 1;
2200                sy_deallocmem( lptr );
2201                return;
2202        } /*endif*/
2203
2204        lp = lptr;
2205        fp = *fdat = (float *)lptr;
2206        for  (i=0; i<(*smplth); i++)
2207                *fp++ = (float)(*lp++) * (*calib);
2208
2209} /* end of SeedReadStreamReal */
2210
2211
2212
2213/*---------------------------------------------------------------------*/
2214
2215
2216
2217float SeedFindStreamCalibration( char stream[], char stime[], STATUS *status )
2218
2219/* returns calibration value for counts for given stream 'stream' at time
2220 * 'stime'.
2221 *
2222 * parameters of routine
2223 * char           stream[];     input; stream string
2224 * char           stime[];      input; time
2225 * STATUS         *status;      output; return status
2226 *                              returns calibration or 0.0
2227 */
2228{
2229        /* local variables */
2230        char     calfile[BC_FILELTH+1];    /* name of calibration file */
2231        char     *eptr;                    /* pointer to environment variable */
2232        FILE     *fp;                      /* pointer to input file */
2233        char     line[BC_LINELTH+1];       /* current line of input file */
2234        char     v_start[BC_LINELTH+1];    /* start of valid time */
2235        char     v_end[BC_LINELTH+1];      /* end of valid time */
2236        float    lcalib;                   /* current value of calibration */
2237        int      cmpidx;                   /* position of component */
2238        int      filecnt;                  /* file counter */
2239        char     *sf;                      /* pointer to sensitivity file name */
2240
2241        /* executable code */
2242
2243        if  (strcmp(GpGetStringElem(cGpL_sensitivity_file,0),"old-style") == 0)  {
2244
2245                /* this is the old-style part, dealing with many, many
2246                 * seedcalib_... files in $SEED_INPUTS
2247                 */
2248
2249                /* build filename */
2250                *calfile = '\0';
2251                eptr = getenv( "SEED_INPUTS" );
2252                if  (eptr != NULL)  {
2253                        if  (strlen(eptr)+strlen(stream)+11 > BC_FILELTH)  {
2254                                *status = SeedERR_STROVFL;
2255                                return 0.0;
2256                        } /*endif*/
2257                        strcpy( calfile, eptr );
2258                        strcat( calfile, "/" );
2259                } /*endif*/
2260                strcat( calfile, "seedcalib_" );
2261                strcat( calfile, stream );
2262
2263                /* open file */
2264                fp = sy_fopen( calfile, "r" );
2265                if  (fp == NULL)  {
2266                        *status = SeedERR_NOCALIB;
2267                        fprintf( stderr, "*Seed: no calibration for %s, set to 1.0\n", stream );
2268                        return 1.0;
2269                } /*endif*/
2270
2271                while  (fgets(line,BC_LINELTH,fp) != NULL)  {
2272                        if  (*line == '!' || *line == '\n')  continue;
2273                        if  (sscanf(line,"%s %s %f",v_start,v_end,&lcalib) != 3)  {
2274                                fprintf( stderr, "*Seed: format error in calibration file %s\n", stream );
2275                                continue;
2276                        } /*endif*/
2277                        if  (tc_tdiff(stime,v_start,status) < 0.0)  continue;
2278                        if  (Severe(status))  return 0.0;
2279                        if  (tc_tdiff(stime,v_end,status) > 0.0)  continue;
2280                        if  (Severe(status))  return 0.0;
2281                        sy_fclose( fp );
2282                        return lcalib;
2283                } /*endwhile*/
2284
2285                sy_fclose( fp );
2286                *status = SeedERR_NOCALIB;
2287                fprintf( stderr, "*Seed: no valid calibration for %s %s, set to 1.0\n",
2288                        stream, stime );
2289                return 1.0;
2290
2291        } else {
2292
2293                /* this is the new version introduced 20-May-2006, all information
2294                 * is in a single file, by default in $SH_INPUTS/sensitivities.txt
2295                 */
2296
2297                /* loop all sensitivity files given */
2298                for  (filecnt=0;;filecnt++)  {
2299
2300                        /* get next sensitivity file name */
2301                        sf = GpGetStringElem( cGpL_sensitivity_file, filecnt );
2302                        if  (sf == NULL)  break;
2303
2304                        /* check for 'default' value, happens if GpReadParfile is not called */
2305                        if  (strcmp(sf,"default") == 0)  {
2306                                *calfile = '\0';
2307                                eptr = getenv( "SH_INPUTS" );
2308                                if  (eptr != NULL)  {
2309                                        if  (strlen(eptr)+18 > BC_FILELTH)  {
2310                                                *status = SeedERR_STROVFL;
2311                                                return 0.0;
2312                                        } /*endif*/
2313                                        strcpy( calfile, eptr );
2314                                        strcat( calfile, "/" );
2315                                } /*endif*/
2316                                strcat( calfile, "sensitivities.txt" );
2317                                sf = calfile;
2318                        } /*endif*/
2319
2320                        /* open it */
2321                        if  (GpGetInt(cGpI_debug_level) > 5)
2322                                printf( "SH-dbg6: open sensitivity file %s\n", sf );
2323                        fp = sy_fopen( sf, "r" );
2324                        if  (fp == NULL)  {
2325                                fprintf( stderr, "*Seed: sensitivity file %s not found\n", sf );
2326                                *status = SeedERR_NOCALIB;
2327                                return 1.0;
2328                        } /*endif*/
2329
2330                        /* wildcard takes stream with '?' as component */
2331                        cmpidx = strlen( stream ) - 1;
2332
2333                        /* read through file */
2334                        while  (fgets(line,cBcLineLth,fp) != NULL)  {
2335                                if  (*line == '!' || *line == '#' || *line == '\n')  continue;
2336                                if  (strncasecmp(line,stream,cmpidx) == 0)  {
2337                                        if  (line[cmpidx] == '?' || line[cmpidx] == stream[cmpidx])  {
2338                                                if  (sscanf(line+cmpidx+2,"%s %s %f",v_start,v_end,&lcalib) != 3)  {
2339                                                        fprintf( stderr, "*Seed: format error in calibration file at %s\n",
2340                                                                stream );
2341                                                        continue;
2342                                                } /*endif*/
2343                                                if  (strcmp(v_start,"...") != 0)
2344                                                        if  (tc_tdiff(stime,v_start,status) < 0.0)  continue;
2345                                                if  (Severe(status))  {
2346                                                        sy_fclose( fp );
2347                                                        return 0.0;
2348                                                } /*endif*/
2349                                                if  (strcmp(v_end,"...") != 0)
2350                                                        if  (tc_tdiff(stime,v_end,status) > 0.0)  continue;
2351                                                if  (Severe(status))  {
2352                                                        sy_fclose( fp );
2353                                                        return 0.0;
2354                                                } /*endif*/
2355                                                sy_fclose( fp );
2356                                                return lcalib;
2357                                        } /*endif*/
2358                                } /*endif*/
2359                        } /*endif*/
2360
2361                        sy_fclose( fp );
2362
2363                } /*endfor*/
2364
2365                *status = SeedERR_NOCALIB;
2366                fprintf( stderr, "*Seed: no valid calibration for %s %s, set to 1.0\n",
2367                        stream, stime );
2368                return 1.0;
2369
2370        } /*endif*/
2371
2372} /* end of SeedFindStreamCalibration */
2373
2374
2375
2376/*---------------------------------------------------------------------*/
2377
2378
2379
2380void SeedGetTimeSpan( char sfdfile[], char stream[], char start[],
2381        char end[], STATUS *status )
2382
2383/* Returns first and last time of channel 'stream' in sfd-file
2384 *
2385 * parameters of routine
2386 * char       sfdfile[];        input; name of sfd-file
2387 * char       stream[];         input; stream string to be checked
2388 * char       start[];          output; first start time
2389 * char       end[];            output; last end time
2390 * STATUS     *status;          output; return status
2391 */
2392{
2393        /* local variables */
2394        FILE     *sfd;                      /* pointer to sfd-file */
2395        char     line[Seed_C_SFDLINELTH+1]; /* current sfd-line */
2396        SeedFileDescrT dsc;                 /* sfd descriptor */
2397        char     lstream[BC_SHORTSTRLTH+1]; /* lowercase stream name */
2398
2399        /* executable code */
2400
2401        sfd = sy_fopen( sfdfile, "r" );
2402        if  (sfd == NULL)  {
2403                *status = SeedERR_OPENINPUT;
2404                err_setcontext( " ## file " );
2405                err_setcontext( sfdfile );
2406                return;
2407        } /*endif*/
2408
2409        strcpy( lstream, stream );
2410        ut_uncap( lstream );
2411
2412        /* find requested stream */
2413        *start = *end = '\0';
2414        while  (fgets(line,Seed_C_SFDLINELTH,sfd) != NULL)  {
2415                if  (*line == '!')  continue;
2416                SeedParseSfdLine( line, &dsc, status );
2417                if  (strcmp(dsc.stream,lstream) != 0)  continue;
2418                if  (*start == '\0')  {
2419                        strcpy( start, dsc.t_start );
2420                } else {
2421                        if  (tc_tdiff(dsc.t_start,start,status) < 0.0)
2422                                strcpy( start, dsc.t_start );
2423                } /*endif*/
2424                if  (Severe(status))  return;
2425                if  (*end == '\0')  {
2426                        strcpy( end, dsc.t_end );
2427                } else {
2428                        if  (tc_tdiff(dsc.t_end,end,status) > 0.0)
2429                                strcpy( end, dsc.t_end );
2430                } /*endif*/
2431                if  (Severe(status))  return;
2432        } /*endwhile*/
2433
2434        sy_fclose( sfd );
2435
2436} /* end of SeedGetTimeSpan */
2437
2438
2439
2440/*---------------------------------------------------------------------*/
2441
2442
2443
2444BOOLEAN SeedInquireTime( char sfdfile[], char stream[], char start[],
2445        char end[], STATUS *status )
2446
2447/* Checks whether the specified time span from 'start' to 'end' is
2448 * available for channel 'stream' in sfd-file 'sfdfile'
2449 *
2450 * parameters of routine
2451 * char       sfdfile[];        input; name of sfd-file
2452 * char       stream[];         input; stream string
2453 * char       start[];          input; start time
2454 * char       end[];            input; end time
2455 * STATUS     *status;          output; return status
2456 *                              returns TRUE if data are available
2457 */
2458{
2459        /* local variables */
2460        FILE     *sfd;                      /* pointer to sfd-file */
2461        char     line[Seed_C_SFDLINELTH+1]; /* current sfd-line */
2462        SeedFileDescrT dsc;                 /* sfd descriptor */
2463        char     lstream[BC_SHORTSTRLTH+1]; /* lowercase stream name */
2464        TIME     a_start, a_end;            /* absolute times of inquied span */
2465        TIME     a1, a2;                    /* absolute times of SEED file */
2466
2467        /* executable code */
2468
2469        sfd = sy_fopen( sfdfile, "r" );
2470        if  (sfd == NULL)  {
2471                *status = SeedERR_OPENINPUT;
2472                err_setcontext( " ## file " );
2473                err_setcontext( sfdfile );
2474                return FALSE;
2475        } /*endif*/
2476
2477        strcpy( lstream, stream );
2478        ut_uncap( lstream );
2479
2480        tc_t2a( start, &a_start, status );
2481        if  (Severe(status))  {sy_fclose(sfd); return FALSE;}
2482        tc_t2a( end, &a_end, status );
2483        if  (Severe(status))  {sy_fclose(sfd); return FALSE;}
2484        if  (tc_adiff(&a_end,&a_start) < 0.0)  {sy_fclose(sfd); return FALSE;}
2485
2486        while  (fgets(line,Seed_C_SFDLINELTH,sfd) != NULL)  {
2487                if  (*line == '!')  continue;
2488                SeedParseSfdLine( line, &dsc, status );
2489                if  (strcmp(dsc.stream,lstream) != 0)  continue;
2490                tc_t2a( dsc.t_start, &a1, status );
2491                if  (Severe(status))  {sy_fclose(sfd); return FALSE;}
2492                tc_t2a( dsc.t_end, &a2, status );
2493                if  (Severe(status))  {sy_fclose(sfd); return FALSE;}
2494                if  (tc_adiff(&a_start,&a1) < 0.0)  continue;
2495                if  (tc_adiff(&a2,&a_end) < 0.0)  continue;
2496                sy_fclose( sfd );
2497                return TRUE;
2498        } /*endwhile*/
2499
2500        sy_fclose( sfd );
2501
2502        return FALSE;
2503
2504} /* end of SeedInquireTime */
2505
2506
2507
2508/*---------------------------------------------------------------------*/
2509
2510
2511
2512void SeedInquireTimeList( char sfdfile[], char stations[], int itemlth,
2513        int listlth, char chan[], char comp, char start[], char end[],
2514        INT32 *avail, STATUS *status )
2515
2516/* Checks whether the specified time span from 'start' to 'end' is
2517 * available for all stations (stream 'station-chan-comp') in sfd-file
2518 * 'sfdfile'.  'station' is a char string with 'listlth' equidistant
2519 * strings of length 'itemlth'.
2520 *
2521 * parameters of routine
2522 * char       sfdfile[];        input; name of sfd-file
2523 * char       stations[];       input; list of stations
2524 * int        itemlth;          input; chars used for a station name
2525 * int        listlth;          input; length of list (# of stations) (<= 32)
2526 * char       chan[];           input; 2-char channel string
2527 * char       comp;             input; component
2528 * char       start[];          input; start time
2529 * char       end[];            input; end time
2530 * INT32      *avail;           output; station bits
2531 * STATUS     *status;          output; return status
2532 */
2533{
2534        /* local variables */
2535        FILE     *sfd;                      /* pointer to sfd-file */
2536        char     line[Seed_C_SFDLINELTH+1]; /* current sfd-line */
2537        SeedFileDescrT dsc;                 /* sfd descriptor */
2538        char     lstream[BC_SHORTSTRLTH+1]; /* lowercase stream name */
2539        TIME     a_start, a_end;            /* absolute times of inquied span */
2540        TIME     a1, a2;                    /* absolute times of SEED file */
2541        char     *sptr;                     /* current station name */
2542        int      scnt;                      /* station counter */
2543        char     cmpstr[2];                 /* component */
2544
2545        /* executable code */
2546
2547        sfd = sy_fopen( sfdfile, "r" );
2548        if  (sfd == NULL)  {
2549                *status = SeedERR_OPENINPUT;
2550                err_setcontext( " ## file " );
2551                err_setcontext( sfdfile );
2552                return;
2553        } /*endif*/
2554
2555        tc_t2a( start, &a_start, status );
2556        if  (Severe(status))  {sy_fclose(sfd); return;}
2557        tc_t2a( end, &a_end, status );
2558        if  (Severe(status))  {sy_fclose(sfd); return;}
2559        if  (tc_adiff(&a_end,&a_start) < 0.0)  {sy_fclose(sfd); return;}
2560
2561        cmpstr[0] = comp;
2562        cmpstr[1] = '\0';
2563
2564        *avail = 0;
2565
2566        while  (fgets(line,Seed_C_SFDLINELTH,sfd) != NULL)  {
2567
2568                /* get & parse next sfd line */
2569                if  (*line == '!')  continue;
2570                SeedParseSfdLine( line, &dsc, status );
2571
2572                /* check time */
2573                tc_t2a( dsc.t_start, &a1, status );
2574                if  (Severe(status))  {sy_fclose(sfd); return;}
2575                tc_t2a( dsc.t_end, &a2, status );
2576                if  (Severe(status))  {sy_fclose(sfd); return;}
2577                if  (tc_adiff(&a_start,&a1) < 0.0)  continue;
2578                if  (tc_adiff(&a2,&a_end) < 0.0)  continue;
2579
2580                /* now loop all stations */
2581                sptr = stations;
2582                for  (scnt=0; scnt<listlth; scnt++)  {
2583                        if  (*sptr != '-')  {
2584                                /* build stream name */
2585                                strcpy( lstream, sptr );
2586                                        strcat( lstream, "-" );
2587                                strcat( lstream, chan );
2588                                strcat( lstream, "-" );
2589                                strcat( lstream, cmpstr );
2590                                ut_uncap( lstream );
2591                                if  (strcmp(dsc.stream,lstream) == 0)
2592                                        *avail |= (1<<scnt);
2593                        } /*endif*/
2594                        /* increment station pointer */
2595                        sptr += itemlth;
2596                } /*endfor*/
2597
2598        } /*endwhile*/
2599
2600        sy_fclose( sfd );
2601
2602} /* end of SeedInquireTimeList */
2603
2604
2605
2606/*---------------------------------------------------------------------*/
2607
2608
2609
2610BOOLEAN SeedSwapNecessary( SeedDataHeaderT *hdr )
2611
2612/* Checks whether a swap is necessary on data header
2613 *
2614 * parameters of routine
2615 * SeedDataHeaderT *hdr;     input; header to check
2616 *                           returns TRUE if swap must be performed
2617 */
2618{
2619        /* executable code */
2620
2621        return  (hdr->starttime.year < 1950 || hdr->starttime.year > 2030);
2622
2623} /* end of SeedSwapNecessary */
2624
2625
2626
2627/*---------------------------------------------------------------------*/
2628
2629
2630
2631void SeedSwapHeader( SeedDataHeaderT *hdr )
2632
2633/* Swaps words and longwords in header
2634 *
2635 * parameters of routine
2636 * SeedDataHeaderT *hdr;          modify; data header to be swapped
2637 */
2638{
2639        /* local variables */
2640        WORD     v_word;      /* scratch */
2641        UWORD    v_uword;     /* scratch */
2642        INT32    v_long;      /* scratch */
2643        SeedBlockette1000T *b1000;  /* pointer to Blockette 1000 */
2644        UWORD    next_block;   /* next blockette pointer */
2645
2646        /* executable code */
2647
2648        v_uword = hdr->starttime.year;
2649        hdr->starttime.year = (v_uword & 0xff) * 0x100;
2650        hdr->starttime.year += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
2651
2652        v_uword = hdr->starttime.day;
2653        hdr->starttime.day = (v_uword & 0xff) * 0x100;
2654        hdr->starttime.day += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
2655
2656        v_uword = hdr->starttime.frac_secs;
2657        hdr->starttime.frac_secs = (v_uword & 0xff) * 0x100;
2658        hdr->starttime.frac_secs += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
2659
2660        v_uword = hdr->no_of_samples;
2661        hdr->no_of_samples = (v_uword & 0xff) * 0x100;
2662        hdr->no_of_samples += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
2663
2664        v_uword = (UWORD)(hdr->smprate_fact);
2665        hdr->smprate_fact = (int)( ((v_uword << 8) & 0xff00) |
2666                ((v_uword >> 8) & 0x00ff) );
2667
2668        v_uword = (UWORD)(hdr->smprate_mult);
2669        hdr->smprate_mult = (int)( ((v_uword << 8) & 0xff00) |
2670                ((v_uword >> 8) & 0x00ff) );
2671
2672        v_long = hdr->timecorr;
2673        hdr->timecorr =  (INT32)(((UINT32)v_long & 0x000000ffL) * (UINT32)0x1000000L);
2674        hdr->timecorr += (INT32)(((UINT32)v_long & 0x0000ff00L) * (UINT32)0x100L);
2675        hdr->timecorr += (INT32)(((UINT32)v_long & 0x00ff0000L) >> (UINT32)8L);
2676        hdr->timecorr += (INT32)(((UINT32)v_long & 0xff000000L) >> (UINT32)24L);
2677
2678        v_uword = hdr->databegin;
2679        hdr->databegin = (v_uword & 0xff) * 0x100;
2680        hdr->databegin += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
2681
2682        /* swap pointer to first blockette and store unswapped value */
2683        next_block = 0;
2684        v_uword = hdr->first;
2685        if  (v_uword >= 48 && v_uword < 64)  next_block = v_uword;
2686        hdr->first = (v_uword & 0xff) * 0x100;
2687        hdr->first += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
2688        if  (hdr->first >= 48 && hdr->first < 64)  next_block = hdr->first;
2689
2690        /* if a pointer > 0 was found swap type and nextblock entry of this blockette */
2691        while  (next_block > 0)  {
2692                b1000 = (SeedBlockette1000T *)((char *)hdr + (unsigned)(next_block));
2693                next_block = 0;
2694                /* check for blockette 1000 and 1001 */
2695                if  (b1000->type == 1000)  b1000->type = 0xe803;
2696                else if  (b1000->type == 1001)  b1000->type = 0xe903;
2697                else if  (b1000->type == 0xe803)  b1000->type = 1000;
2698                else if  (b1000->type == 0xe903)  b1000->type = 1001;
2699                /* swap pointer to next blockette and store pointer value */
2700                v_uword = b1000->nextblock;
2701                if  (v_uword >= 48 && v_uword < 64)  next_block = v_uword;
2702                b1000->nextblock = (v_uword & 0xff) * 0x100;
2703                b1000->nextblock += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
2704                if  ((b1000->nextblock) >= 48 && (b1000->nextblock) < 64)
2705                        next_block = b1000->nextblock;
2706        } /*endif*/
2707
2708} /* end of SeedSwapHeader */
2709
2710
2711
2712/*---------------------------------------------------------------------*/
2713
2714
2715
2716void SeedCloseFiles( void )
2717
2718/* closes all open SEED files
2719 *
2720 * no parameters
2721 */
2722{
2723        /* local variables */
2724        int      i;         /* counter */
2725
2726        /* executable code */
2727
2728        for  (i=0; i<Seed_C_MAXCHAN; i++)
2729                if  (seedv_fd[i].ufd != Seed_C_ILLEGAL)  {
2730                        close( seedv_fd[i].ufd );
2731                        seedv_fd[i].ufd = Seed_C_ILLEGAL;
2732                } /*endif*/
2733
2734} /* end of SeedCloseFiles */
2735
2736
2737
2738/*---------------------------------------------------------------------*/
2739
2740
2741
2742static void SeedAdjustFilename( SeedFileDescrT *dsc, STATUS *status )
2743
2744/* copies directory of sfd-file to data filename
2745 *
2746 * parameters of routine
2747 * SeedFileDescrT  *dsc;        modify; SEED file descriptor
2748 * STATUS          *status;     output; return status
2749 */
2750{
2751        /* local variables */
2752        int      i;                      /* counter */
2753        int      strlth;                 /* string length */
2754        char     path[BC_FILELTH+1];     /* path name */
2755        BOOLEAN  iscolon;                /* is there a colon ? */
2756        char     upname[cBcFileLth+1];   /* uppercase filename */
2757
2758        /* executable code */
2759
2760        /* find path in sfdfile */
2761        i = strlen( dsc->sfdfile ) - 1;
2762        while  (i >= 0 && dsc->sfdfile[i] != '/' && dsc->sfdfile[i] != ':'
2763                && dsc->sfdfile[i] != '\\')  i--;
2764        if  (i > 0)  {
2765                strncpy( path, dsc->sfdfile, i );
2766                path[i] = '\0';
2767                iscolon = (dsc->sfdfile[i] == ':');
2768        } else {
2769                *path = '\0';
2770                iscolon = FALSE;
2771        } /*endif*/
2772
2773        if  (strlen(dsc->name)-ROOTDIRLTH+strlen(path) > BC_FILELTH)  {
2774                *status = SeedERR_STROVFL;
2775                return;
2776        } /*endif*/
2777
2778        if  (*path != '\0')  {
2779                strlth = strlen( path );
2780                for  (i=0; i<strlth; i++)
2781                        if  (path[i] == '\\')  path[i] = '/';
2782                if  (iscolon)  {
2783                        strcat( path, ":" );
2784                        if  (seedv_capfiles)  {
2785                                strcpy( upname, dsc->name+ROOTDIRLTH+1 );
2786                                ut_cap( upname );
2787                                strcat( path, upname );
2788                        } else {
2789                                strcat( path, dsc->name+ROOTDIRLTH+1 );
2790                        } /*endif*/
2791                } else {
2792                        if  (seedv_capfiles)  {
2793                                strcpy( upname, dsc->name+ROOTDIRLTH );
2794                                ut_cap( upname );
2795                                strcat( path, upname );
2796                        } else {
2797                                strcat( path, dsc->name+ROOTDIRLTH );
2798                        } /*endif*/
2799                } /*endif*/
2800        } else {
2801                strcpy( path, dsc->name+ROOTDIRLTH+1 );
2802        } /*endif*/
2803        strcpy( dsc->name, path );
2804
2805} /* end of SeedAdjustFilename */
2806
2807
2808
2809/*---------------------------------------------------------------------*/
2810
2811
2812static void SeedLibWarning( char text[] )
2813
2814/* prints warning messages
2815 *
2816 * parameters of routine
2817 * char       text[];      input; output text
2818 */
2819{
2820        /* local variables */
2821        char     str[cBcLineLth+1];    /* output string */
2822        int      i;                    /* counter */
2823
2824        /* executable code */
2825
2826        if  (!seedv_warnings)  return;
2827
2828        fprintf( stderr, "%s", text );
2829
2830} /* end of SeedLibWarning */
2831
2832
2833
2834/*---------------------------------------------------------------------*/
2835
2836
2837
2838void SeedPrintWarnings( BOOLEAN on_off )
2839
2840/* switches warning messages on or off
2841 *
2842 * parameters of routine
2843 * BOOLEAN    on_off;       input; switch
2844 */
2845{
2846        /* executable code */
2847
2848        seedv_warnings = on_off;
2849
2850} /* end of SeedPrintWarnings */
2851
2852
2853
2854/*---------------------------------------------------------------------*/
2855
2856
2857
2858void SeedAcceptCapfiles( BOOLEAN on_off )
2859
2860/* switches on/off whether capitalized filenames on $ROOT-paths are accepted
2861 *
2862 * parameters of routine
2863 * BOOLEAN    on_off;       input; switch
2864 */
2865{
2866        /* executable code */
2867
2868        seedv_capfiles = on_off;
2869
2870} /* end of SeedPrintWarnings */
2871
2872
2873
2874/*---------------------------------------------------------------------*/
2875
2876
2877
2878BOOLEAN SeedSetInvertSwapHeader( BOOLEAN on_off )
2879
2880/* Sets the global variable seedv_invert_swap_hdr to invert header swap
2881 * info in sfd-file.  Returns old value.
2882 *
2883 * parameters of routine
2884 * BOOLEAN    on_off;    input; switch value
2885 */
2886{
2887        /* local variables */
2888        BOOLEAN  old;
2889
2890        /* executable code */
2891
2892        old = seedv_invert_swap_hdr;
2893        seedv_invert_swap_hdr = on_off;
2894        return old;
2895
2896} /* end of SeedSetInvertSwapHeader */
2897
2898
2899
2900/*---------------------------------------------------------------------*/
2901
2902
2903
2904BOOLEAN SeedSetDecodeErrorAbort( BOOLEAN on_off )
2905
2906/* Sets the global value seedv_decerr_abort (abort on occurrence of
2907 * SEED decoding errors.  Returns old value.
2908 *
2909 * parameters of routine
2910 * BOOLEAN    on_off;        input; switch value
2911 */
2912{
2913        /* local variables */
2914        BOOLEAN  old;        /* old value */
2915
2916        /* executable code */
2917
2918        old = seedv_decerr_abort;
2919        seedv_decerr_abort = on_off;
2920        return old;
2921
2922} /* end of SeedSetDecodeErrorAbort */
2923
2924
2925
2926/*---------------------------------------------------------------------*/
2927
2928
2929
2930BOOLEAN SeedUseTimeCorrection( BOOLEAN on_off )
2931
2932/* Sets the global value seedv_use_timecorr (use timec orrection field
2933 * within SEED data records).  Returns old value.
2934 *
2935 * parameters of routine
2936 * BOOLEAN    on_off;        input; switch value
2937 */
2938{
2939        /* local variables */
2940        BOOLEAN  old;        /* old value */
2941
2942        /* executable code */
2943
2944        old = seedv_use_timecorr;
2945        seedv_use_timecorr = on_off;
2946        return old;
2947
2948} /* end of SeedUseTimeCorrection */
2949
2950
2951
2952/*---------------------------------------------------------------------*/
2953
2954
2955
2956void SeedCutStartRecord( SeedSbyteT *seedrec, char extime[], BOOLEAN swap,
2957        STATUS *status )
2958
2959/* Throws away the first samples in record until given time
2960 *
2961 * parameters of routine
2962 * char       *seedrec;         modify; SEED record to cut
2963 * char       extime[];         input; exact time
2964 * BOOLEAN    swap;             input; swap bytes ?
2965 * STATUS     *status;          output; return status
2966 */
2967{
2968        /* local variables */
2969        SeedDataHeaderT *hdrptr;   /* pointer to data header */
2970        SeedDataHeaderT *outrec;   /* output records */
2971        SeedDataHeaderT tmphdr;    /* temp store */
2972        float    dt;               /* sample rate */
2973        NTIME    rstart, rend;     /* record start and end times */
2974        NTIME    ntime;            /* numeric exact time */
2975        float    tdiff;            /* time difference in sec */
2976        int      cutlth;           /* number of samples to cut */
2977        INT32    smp[MAX_SMP_PER_REC]; /* space for decoded samples */
2978        INT32    smplth;           /* number of sample decoded */
2979        int      i;                /* counter */
2980        int      recs_used;        /* records used for encoding (should be 1) */
2981        int      reclth;           /* record length */
2982
2983        /* executable code */
2984
2985        /* retrieve header information needed here */
2986        hdrptr = (SeedDataHeaderT *)seedrec;
2987        dt = SeedGetSampleDist( hdrptr );
2988        reclth = SeedGetReclth( hdrptr, FALSE );
2989        SeedRecordTime( seedrec, &rstart, &rend, status );
2990        if  (SySevere(status))  return;
2991        tc_t2n( extime, &ntime, status );
2992        if  (SySevere(status))  return;
2993        tdiff = tc_ndiff( &ntime, &rstart, status );
2994        if  (SySevere(status))  return;
2995        cutlth = Nint( tdiff / dt );
2996        if  (cutlth > (int)(hdrptr->no_of_samples))  {
2997                *status = SeedERR_ILLCUT;
2998                return;
2999        } else if  (cutlth == (int)(hdrptr->no_of_samples))  {
3000                hdrptr->no_of_samples = 0;
3001                return;
3002        } else if  (cutlth <= 0)  {
3003                /* nothing to be done */
3004                return;
3005        } /*endif*/
3006
3007        /* decode record */
3008        SeedDecodeSteim1( NULL, swap, 0, NULL, NULL );
3009        SeedDecodeSteim1( seedrec, swap, MAX_SMP_PER_REC, smp, &smplth );
3010        if  (smplth != (INT32)(hdrptr->no_of_samples))  {
3011                *status = SeedERR_DECODE_ERR;
3012                return;
3013        } /*endif*/
3014
3015        /* throw away cutlth samples from the beginning */
3016        for  (i=cutlth; i<(int)smplth; i++)
3017                smp[i-cutlth] = smp[i];
3018        smplth -= (INT32)cutlth;
3019        tdiff = (float)cutlth * dt;
3020        tc_nadd( &rstart, tdiff, &rstart, status );
3021        if  (SySevere(status))  return;
3022
3023        /* prepare changed record */
3024        outrec = (SeedDataHeaderT *)sy_allocmem( 2, reclth, status );
3025        /* get two records; need only one but who knows ... */
3026        hdrptr->no_of_samples = (UWORD)smplth;
3027        SeedNtimeToBtime( &rstart, &(hdrptr->starttime), status );
3028        if  (SySevere(status))  {
3029                sy_deallocmem( outrec );
3030                return;
3031        } /*endif*/
3032        recs_used = (int)Steim_comp( smp, (DATA_HEADER *)hdrptr, (UINT32)smplth,
3033                (WORD)(reclth), (INT32 *)outrec, 0 /*prev.smp*/ );
3034        if  (recs_used != 1)  {
3035                *status = SeedERR_BUG;
3036                sy_deallocmem( outrec );
3037                return;
3038        } /*endif*/
3039        /* copy result to output record and keep header */
3040        tmphdr = *hdrptr;
3041        memcpy( (char *)seedrec, (char *)outrec, reclth );
3042        SeedStoreReclth( (SeedDataHeaderT *)seedrec, reclth );
3043        *hdrptr = tmphdr;
3044        sy_deallocmem( outrec );
3045
3046} /* end of SeedCutStartRecord */
3047
3048
3049
3050/*---------------------------------------------------------------------*/
3051
3052
3053
3054void SeedCutEndRecord( SeedSbyteT *seedrec, char extime[], BOOLEAN swap,
3055        STATUS *status )
3056
3057/* Throws away the first samples in record until given time
3058 *
3059 * parameters of routine
3060 * char       *seedrec;         modify; SEED record to cut
3061 * char       extime[];         input; exact time
3062 * BOOLEAN    swap;             input; swap bytes ?
3063 * STATUS     *status;          output; return status
3064 */
3065{
3066        /* local variables */
3067        SeedDataHeaderT *hdrptr;   /* pointer to data header */
3068        SeedDataHeaderT *outrec;   /* output records */
3069        SeedDataHeaderT tmphdr;    /* temp store */
3070        float    dt;               /* sample rate */
3071        NTIME    rstart, rend;     /* record start and end times */
3072        NTIME    ntime;            /* numeric exact time */
3073        float    tdiff;            /* time difference in sec */
3074        int      cutlth;           /* number of samples to cut */
3075        INT32    smp[MAX_SMP_PER_REC]; /* space for decoded samples */
3076        INT32    smplth;           /* number of sample decoded */
3077        int      i;                /* counter */
3078        int      recs_used;        /* records used for encoding (should be 1) */
3079        int      reclth;           /* record length */
3080
3081        /* executable code */
3082
3083        /* retrieve header information needed here */
3084        hdrptr = (SeedDataHeaderT *)seedrec;
3085        dt = SeedGetSampleDist( hdrptr );
3086        reclth = SeedGetReclth( hdrptr, FALSE );
3087        SeedRecordTime( seedrec, &rstart, &rend, status );
3088        if  (SySevere(status))  return;
3089        tc_t2n( extime, &ntime, status );
3090        if  (SySevere(status))  return;
3091        tdiff = tc_ndiff( &rend, &ntime, status );
3092        if  (SySevere(status))  return;
3093        cutlth = Nint( tdiff / dt );
3094        if  (cutlth > (int)(hdrptr->no_of_samples))  {
3095                *status = SeedERR_ILLCUT;
3096                return;
3097        } else if  (cutlth == (int)(hdrptr->no_of_samples))  {
3098                hdrptr->no_of_samples = 0;
3099                return;
3100        } else if  (cutlth <= 0)  {
3101                /* nothing to be done */
3102                return;
3103        } /*endif*/
3104
3105        /* decode record */
3106        SeedDecodeSteim1( NULL, swap, 0, NULL, NULL );
3107        SeedDecodeSteim1( seedrec, swap, MAX_SMP_PER_REC, smp, &smplth );
3108        if  (smplth != (INT32)(hdrptr->no_of_samples))  {
3109                *status = SeedERR_DECODE_ERR;
3110                return;
3111        } /*endif*/
3112
3113        /* throw away cutlth samples at the end */
3114        smplth -= (INT32)cutlth;
3115
3116        /* prepare changed record */
3117        outrec = (SeedDataHeaderT *)sy_allocmem( 2, reclth, status );
3118        /* get two records; need only one but who knows ... */
3119        hdrptr->no_of_samples = (UWORD)smplth;
3120        recs_used = (int)Steim_comp( smp, (DATA_HEADER *)hdrptr, (UINT32)smplth,
3121                (WORD)(reclth), (INT32 *)outrec, 0 /*prev.smp*/ );
3122        if  (recs_used != 1)  {
3123                *status = SeedERR_BUG;
3124                sy_deallocmem( outrec );
3125                return;
3126        } /*endif*/
3127        /* copy result to output record and keep header */
3128        tmphdr = *hdrptr;
3129        memcpy( (char *)seedrec, (char *)outrec, reclth );
3130        SeedStoreReclth( (SeedDataHeaderT *)seedrec, reclth );
3131        *hdrptr = tmphdr;
3132        sy_deallocmem( outrec );
3133
3134} /* end of SeedCutEndRecord */
3135
3136
3137
3138/*---------------------------------------------------------------------*/
3139
3140
3141
3142char *SeedGetFilename( int chan )
3143
3144/* returns name of currently opened file on channel 'chan'.  If no filename
3145 * is found, a pointer to an empty string is returned.
3146 *
3147 * parameters of routine
3148 * int        chan;        input; channel number
3149 *                         returns name of file
3150 */
3151{
3152        /* local variables */
3153        static char nullstr[2] = "";  /* null string */
3154        SeedFileDescrT *fd;   /* pointer to SEED file descriptor */
3155
3156        /* executable code */
3157
3158        /* check channel number */
3159        if  (chan < 0 || chan >= Seed_C_MAXCHAN)  return nullstr;
3160        fd = seedv_fd + chan;
3161        return ((fd->name[0] == '\0') ? seedv_last_fname : fd->name);
3162
3163} /* end of SeedGetFilename */
3164
3165
3166
3167/*---------------------------------------------------------------------*/
3168
3169
3170
3171void SeedStoreReclth( SeedDataHeaderT *rec, int reclth )
3172
3173/* Stores record length in SEED record. Uses Reserved_bytes_A for this purpose
3174 * if no blockette 1000 is available.
3175 *
3176 * parameters of routine
3177 * SeedDataHeaderT   *rec;   modify;  SEED record
3178 */
3179{
3180        /* local variables */
3181        int      num, i;        /* value and exp counter */
3182        TSyBoolean b1000;       /* blockette 1000 found */
3183        UWORD    *uw;           /* pointer to UWORD */
3184        char     *cp;           /* pointer to char */
3185        UWORD    recfirst;      /* offset to first blockette */
3186        UWORD    tmp;           /* scratch */
3187
3188        /* executable code */
3189
3190        /* determine which power of 2 */
3191        num = 1;
3192        i = 0;
3193        while  (num < reclth)  {
3194                i++;
3195                num *= 2;
3196        } /*endwhile*/
3197
3198        /* if a blockette 1000 is there use it */
3199        b1000 = TRUE;
3200        if  (rec->no_of_blockettes == 0)  b1000 = FALSE;
3201        if  (b1000 && rec->first == 0)  b1000 = FALSE;
3202
3203        if  (b1000)  {
3204                if  (rec->first > reclth)  {
3205                        tmp = rec->first;
3206                        recfirst = (tmp & 0xff) * 0x100;
3207                        recfirst += (UWORD)(tmp & 0xff00) / (UWORD)0x100;
3208                } else {
3209                        recfirst = rec->first;
3210                } /*endif*/
3211                if  (recfirst % 2 == 1)  {
3212                        SeedLibWarning(
3213                                "*** illegal 'first' entry in record (StoreReclth) ***\n" );
3214                        b1000 = FALSE;
3215                } /*endif*/
3216        } /*endif*/
3217
3218        if  (b1000)  {
3219                uw = (UWORD *)((char *)rec + (int)recfirst);
3220                if  (*uw != 1000 && *uw != 59395)  b1000 = FALSE;
3221        } /*endif*/
3222
3223        if  (b1000)  {
3224                cp = (char *)rec + (int)recfirst + 6;
3225                *cp = (char)i;
3226        } else {
3227                rec->Reserved_bytes_A = (char)i;
3228        } /*endif*/
3229
3230} /* end of SeedStoreReclth */
3231
3232
3233
3234/*---------------------------------------------------------------------*/
3235
3236
3237
3238int SeedGetReclth( SeedDataHeaderT *rec, TSyBoolean clean )
3239
3240/* Returns SEED record length stored in record (by SeedStoreReclth)
3241 * If 'clean' is TRUE, the record length info is deleted from the record.
3242 *
3243 * parameters of routine
3244 * SeedDataHeaderT  *rec;      modify; SEED record
3245 * TSyBoolean       clean;     input; if TRUE, record length info is deleted
3246 */
3247{
3248        /* local variables */
3249        int      reclth;        /* record length */
3250        TSyBoolean b1000;       /* blockette 1000 found */
3251        UWORD    *uw;           /* pointer to UWORD */
3252        UWORD    recfirst;      /* offset to first blockette */
3253        char     *cp;           /* pointer to char */
3254        UWORD    tmp;           /* scratch */
3255
3256        /* executable code */
3257
3258        /* if a blockette 1000 is there use it */
3259        b1000 = TRUE;
3260        if  (rec->no_of_blockettes == 0)  b1000 = FALSE;
3261        if  (b1000 && rec->first == 0)  b1000 = FALSE;
3262        if  (b1000)  {
3263                if  (rec->first > (UWORD)sizeof(SeedDataHeaderT))  {
3264                        tmp = rec->first;
3265                        recfirst = (tmp & 0xff) * 0x100;
3266                        recfirst += (UWORD)(tmp & 0xff00) / (UWORD)0x100;
3267                } else {
3268                        recfirst = rec->first;
3269                } /*endif*/
3270                if  (recfirst % 2 == 1)  {
3271                        SeedLibWarning(
3272                                "*** illegal 'first' entry in record (StoreReclth) ***\n" );
3273                        b1000 = FALSE;
3274                } /*endif*/
3275        } /*endif*/
3276        if  (b1000)  {
3277                uw = (UWORD *)((char *)rec + (int)(recfirst));
3278                if  (*uw != 1000 && *uw != 59395)  b1000 = FALSE;
3279        } /*endif*/
3280
3281        if  (b1000)  {
3282                cp = (char *)rec + (int)(recfirst) + 6;
3283                reclth = (*cp);
3284                reclth = (1 << reclth);
3285        } else {
3286                if  (rec->Reserved_bytes_A == '\0' || rec->Reserved_bytes_A == ' ')  {
3287                        fprintf( stderr,
3288                                "SeedGetReclth: no record length found in record. Abort.\n" );
3289                        exit( 1 );
3290                } /*endif*/
3291                reclth = (1 << (int)(rec->Reserved_bytes_A));
3292                if (clean)  rec->Reserved_bytes_A = ' ';
3293        } /*endif*/
3294
3295        return reclth;
3296
3297} /* end of SeedGetReclth */
3298
3299
3300
3301/*---------------------------------------------------------------------*/
3302
3303
3304
3305int SeedGetCompression( SeedDataHeaderT *rec )
3306
3307/* Returns compression algorithm ID if blockette 1000 is found,
3308 * otherwise 0.
3309 *
3310 * parameters of routine
3311 * SeedDataHeaderT  *rec;      input; SEED record
3312 */
3313{
3314        /* local variables */
3315        TSyBoolean b1000;       /* blockette 1000 found */
3316        UWORD    *uw;           /* pointer to UWORD */
3317        char     *cp;           /* pointer to char */
3318    int      offset;        /* offset from record start */
3319    WORD     *next;         /* next blockette */
3320    int      blkcnt;        /* blockette counter */
3321
3322        /* executable code */
3323
3324        /* if a blockette 1000 is there use it */
3325        b1000 = TRUE;
3326        if  (rec->no_of_blockettes == 0)  b1000 = FALSE;
3327        if  (b1000 && rec->first == 0)  b1000 = FALSE;
3328        if  (rec->first % 2 == 1)  {
3329                SeedLibWarning(
3330                        "*** illegal 'first' entry in record (GetCompression) ***\n" );
3331                return 0;
3332        } /*endif*/
3333        if  (!b1000)  return 0;
3334    b1000 = FALSE;
3335    offset = (int)(rec->first);
3336    blkcnt = 0;
3337        while  (!b1000)  {
3338                uw = (UWORD *)((char *)rec + offset);
3339                if  (*uw == 1000 || *uw == 59395)  {
3340            b1000 = TRUE;
3341            break;
3342        } /*endif*/
3343        next = (WORD *)((char *)rec + offset + 2);
3344        if  ((int)(*next) <= offset || (int)(*next) > 4096)  break;
3345        offset = (int)(*next);
3346        blkcnt++;
3347        if  (blkcnt >= rec->no_of_blockettes)  break;
3348        } /*endwhile*/
3349        if  (!b1000)  return 0;
3350
3351        cp = (char *)rec + offset + 4;
3352        return (int)(*cp);
3353
3354} /* end of SeedGetCompression */
3355
3356
3357
3358/*---------------------------------------------------------------------*/
3359
3360
3361
3362int SeedGetTimequal( SeedDataHeaderT *rec )
3363
3364/* Returns time quality or -1
3365 *
3366 * parameters of routine
3367 * SeedDataHeaderT   *rec;
3368 */
3369{
3370        /* local variables */
3371        SeedBlockette1001T *b1001;       /* blockette 1001 */
3372
3373        /* executable code */
3374
3375        if  (rec->no_of_blockettes <= 0)  return (-1);
3376
3377        b1001 = (SeedBlockette1001T *)((char *)rec + (unsigned)(rec->first));
3378        if  (b1001->type == 1001)  return (int)(b1001->timequal);
3379        if  (rec->no_of_blockettes == 1)  return (-1);
3380        b1001 = (SeedBlockette1001T *)((char *)rec + (unsigned)(b1001->nextblock));
3381        if  (b1001->type == 1001)  return (int)(b1001->timequal);
3382        return (-1);
3383        /* not more than 2 blockettes checked, should implement loop */
3384
3385} /* end of SeedGetTimequal */
3386
3387
3388
3389/*---------------------------------------------------------------------*/
3390
3391
3392
3393int SeedGetWordOrder( SeedDataHeaderT *rec )
3394
3395/* Returns word order ID if blockette 1000 is found,
3396 * otherwise 1 (=Sparc).
3397 *
3398 * parameters of routine
3399 * SeedDataHeaderT  *rec;      input; SEED record
3400 */
3401{
3402        /* local variables */
3403        TSyBoolean b1000;       /* blockette 1000 found */
3404        UWORD    *uw;           /* pointer to UWORD */
3405        char     *cp;           /* pointer to char */
3406
3407        /* executable code */
3408
3409        /* if a blockette 1000 is there use it */
3410        b1000 = TRUE;
3411        if  (rec->no_of_blockettes == 0)  b1000 = FALSE;
3412        if  (b1000 && rec->first == 0)  b1000 = FALSE;
3413        if  (rec->first % 2 == 1)  {
3414                SeedLibWarning( "*** illegal 'first' entry in record ***\n" );
3415                return 1;
3416        } /*endif*/
3417        if  (b1000)  {
3418                uw = (UWORD *)((char *)rec + (int)(rec->first));
3419                if  (*uw != 1000 && *uw != 59395)  b1000 = FALSE;
3420        } /*endif*/
3421        if  (!b1000)  return 1;  /* Sparc word order is default */
3422
3423        cp = (char *)rec + (int)(rec->first) + 5;
3424        return (int)(*cp);
3425
3426} /* end of SeedGetWordOrder */
3427
3428
3429
3430/*---------------------------------------------------------------------*/
3431
3432
3433
3434void SeedSetOutputReclth( int reclth )
3435
3436/* Sets size of SEED output records (default is 4096, if not called)
3437 *
3438 * parameters of routine
3439 * int        reclth;       input; size of output records in bytes
3440 */
3441{
3442        /* executable code */
3443
3444        seedv_out_reclth = reclth;
3445
3446} /* end of SeedSetOutputReclth */
3447
3448
3449
3450/*----------------------------------------------------------------------------*/
3451
3452
3453
3454void SeedSetNextTimequal( int tq )
3455
3456/* Sets time quality for next Steim output record
3457 *
3458 * parameters of routine
3459 * int        tq;         input; time quality
3460 */
3461{
3462        /* executable code */
3463
3464        seedv_timequal = tq;
3465
3466} /* end of SeedSetNextTimequal */
3467
3468
3469
3470/*----------------------------------------------------------------------------*/
3471
3472
3473#define IDOFFSET 6
3474
3475
3476void SeedQuickFindReclth( FILE *fp, int *recsize, int *byteoff )
3477
3478/* Returns record size in bytes or 0 and the byte offset where data records
3479 * start.
3480 *
3481 * parameters of routine
3482 * FILE          *fp;          input; input file already opened
3483 * int           *recsize;     output; record size found
3484 * int           *byteoff;     output; byte offset found
3485 */
3486{
3487        /* local variables */
3488        char     id1, id2;  /* ID chars */
3489        TSyBoolean isdigit1, isdigit2; /* is number string */
3490        int      i;         /* counter */
3491
3492        /* executable code */
3493
3494        *recsize = 0;
3495        *byteoff = 0;
3496        isdigit1 = isdigit2 = TRUE;
3497
3498        /* position file and read number string and ID */
3499        fseek( fp, 0, 0 );
3500        for  (i=0; i<IDOFFSET; i++)  {
3501                id1 = getc( fp );
3502                if  (id1 < '0' || id1 > '9')  isdigit1 = FALSE;
3503        } /*endfor*/
3504        id1 = getc( fp );
3505        fseek( fp, 512, 0 );
3506        for  (i=0; i<IDOFFSET; i++)  {
3507                id2 = getc( fp );
3508                if  (id2 < '0' || id2 > '9')  isdigit2 = FALSE;
3509        } /*endfor*/
3510        id2 = getc( fp );
3511        if  (id1 == EOF || isdigit1 == FALSE)  {
3512                /* no SEED file, leave recsize zero */
3513        } else if  (strchr(Seed_C_DATCHARS,id1) != NULL && strchr(Seed_C_DATCHARS,id2) == NULL)  {
3514                /* definitely not 512 */
3515                *recsize = 4096;
3516                *byteoff = 0;
3517        } else if  (id1 == 'V' && strchr(Seed_C_DATCHARS,id2) != NULL && isdigit2 == TRUE)  {
3518                /* very likely 512 */
3519                *recsize = 512;
3520                *byteoff = 512;
3521        } else if  (isdigit2 == FALSE)  {
3522                *recsize = 4096;
3523                *byteoff = 0;  /* this is a guess */
3524        } else if  (strchr(Seed_C_DATCHARS,id1) != NULL && strchr(Seed_C_DATCHARS,id2) != NULL)  {
3525                *byteoff = 0;
3526                fseek( fp, 1024+IDOFFSET, 0 );
3527                id1 = getc( fp );
3528                fseek( fp, 1024+512+IDOFFSET, 0 );
3529                id2 = getc( fp );
3530                if  (strchr(Seed_C_DATCHARS,id1) != NULL && strchr(Seed_C_DATCHARS,id2) != NULL)  {
3531                        *recsize = 512;
3532                } else if  (strchr(Seed_C_DATCHARS,id1) != NULL && id2 == EOF)  {
3533                        *recsize = 512;
3534                } else if  (id1 == EOF)  {
3535                        *recsize = 512;
3536                } else {
3537                        *recsize = 4096;
3538                } /*endfif*/
3539        } else {
3540                /* cannot determine */
3541                *recsize = -1;
3542        } /*endif*/
3543
3544        /* rewind file */
3545        fseek( fp, 0, 0 );
3546
3547} /* end of SeedQuickFindReclth */
3548
3549
3550
3551/*---------------------------------------------------------------------*/
3552
3553
3554
3555static void SeedSwapLinuxRecord( SeedSbyteT *rec, int reclth )
3556
3557
3558/* Modifies record for writing on Linux system
3559 *
3560 * parameters of routine
3561 * SeedSbyteT *rec;                modify; SEED record
3562 * int        reclth;              input; record length, if 0 found by SeedGetReclth
3563 */
3564{
3565        /* local variables */
3566        SeedSbyteT     *ptr;                /* moving pointer */
3567        SeedSbyteT     tmp;                 /* scratch */
3568
3569        /* executable code */
3570
3571        if  (reclth == 0)
3572                reclth = SeedGetReclth( (SeedDataHeaderT *)rec, FALSE );
3573
3574        for  (ptr = rec+Seed_C_FRAMELTH; ptr < rec+reclth;
3575                ptr += 4)  {
3576                /* flip 0 and 3 */
3577                tmp = ptr[0];  ptr[0] = ptr[3];  ptr[3] = tmp;
3578                /* flip 1 and 2 */
3579                tmp = ptr[1];  ptr[1] = ptr[2];  ptr[2] = tmp;
3580        } /*endfor*/
3581
3582} /* end of SeedSwapLinuxRecord */
3583
3584
3585
3586/*---------------------------------------------------------------------*/
3587
3588
3589
3590static void SeedSplitStreamName( char inpname[], char outname[],
3591        char station[], char addinf[] )
3592
3593/* Splits extended stream name (e.g. anmo.iu00-bh-z) into standard stream
3594 * name (e.g. anmo-bh-z) and addinfo string (iu00).  Minimum output length
3595 * of addinf is Seed_C_AddinfLth+1.
3596 *
3597 * parameters of routine
3598 * char       inpname[];     input; extended stream name
3599 * char       outname[];     output; standard stream name
3600 * char       station[];     output; station name
3601 * char       addinf[];      output; addinfo string
3602 */
3603{
3604        /* local variables */
3605        int      i, j, k;         /* counter */
3606        int      slen;            /* length of stream string */
3607        TSyBoolean add;           /* addinfo string */
3608        TSyBoolean first;         /* first point */
3609        TSyBoolean isstat;        /* station part */
3610
3611        /* executable code */
3612
3613        /* default addinf */
3614        strcpy( addinf, Seed_C_EmptyAddinfStr );
3615        *station = '\0';
3616
3617        first = TRUE;
3618        slen = strlen( inpname );
3619        j = k = 0;
3620        add = FALSE;
3621        isstat = TRUE;
3622        for  (i=0; i<slen; i++)  {
3623                if  (inpname[i] == '.' && first)  {
3624                        add = TRUE;
3625                        first = FALSE;
3626                        if  (isstat)  {
3627                                station[i] = '\0';
3628                                isstat = FALSE;
3629                        } /*endif*/
3630                } else if  (inpname[i] == '-')  {
3631                        add = FALSE;
3632                        outname[k++] = inpname[i];
3633                        if  (isstat)  {
3634                                station[i] = '\0';
3635                                isstat = FALSE;
3636                        } /*endif*/
3637                } else {
3638                        if  (isstat)  station[i] = Uncap( inpname[i] );
3639                        if  (add && j < Seed_C_AddinfLth)  {
3640                                addinf[j++] = Uncap( inpname[i] );
3641                        } else {
3642                                outname[k++] = inpname[i];
3643                        } /*endif*/
3644                } /*endif*/
3645        } /*endfor*/
3646
3647        outname[k] = '\0';
3648
3649        /*printf( "--> %s -> %s,%s\n", inpname, outname, addinf );*/
3650
3651} /* end of SeedSplitStreamName */
3652
3653
3654/*---------------------------------------------------------------------*/
3655
3656
3657
3658void SeedTranslateChan( char station[], char inchan[], char outchan[] )
3659
3660/* Translates channel name, e.g. '++' depending on station name
3661 *
3662 * parameters of routine
3663 * char       station[];    input; station name, e.g. 'bfo'
3664 * char       inchan[];     input; channel name (length 2+term), e.g. '++'
3665 * char       outchan[];    output; translated name (length 2 + term)
3666 */
3667{
3668        /* local variables */
3669        int      pathcnt;                      /* path counter (to transl. files) */
3670        char     *transpath;                   /* name of translation file */
3671        FILE     *fp;                          /* pointer to file */
3672        char     fstr[cBcLineLth+1];           /* station+chan name */
3673        int      fstrlen;                      /* length of fstr */
3674        char     dstr[cBcLineLth+1];           /* default station+chan name */
3675        int      dstrlen;                      /* length of dstr */
3676        char     line[cBcLineLth+1];           /* current line of file */
3677        char     *cptr;                        /* moving pointer */
3678        char     defchan[cBcShortStrLth+1];    /* default channel */
3679        TSyBoolean default_found;              /* default string found */
3680
3681        /* executable code */
3682
3683        strcpy( outchan, inchan );
3684        default_found = FALSE;
3685
3686        /* skip this of no special channel given */
3687        if  (strcmp(inchan,"++") != 0)
3688                return;
3689
3690        /* prepare search strings */
3691        if  (strlen(station)+3 > cBcLineLth)  {
3692                printf( "*Seed: station name too long.  Cannot translate chan\n" );
3693                return;
3694        } /*endif*/
3695        /* get string to search in file (station-inchan) */
3696        sprintf( fstr, "%s-%s", station, inchan );
3697        ut_uncap( fstr );
3698        fstrlen = strlen( fstr );
3699        /* default setting is also needed (*-inchan) */
3700        sprintf( dstr, "*-%s", inchan );
3701        ut_uncap( dstr );
3702        dstrlen = strlen( dstr );
3703
3704        for  (pathcnt=0;;pathcnt++)  {
3705                transpath = GpGetStringElem( cGpL_channel_translation, pathcnt );
3706                if  (transpath == NULL)  break;
3707                fp = fopen( transpath, "r" );
3708                if  (fp == NULL)
3709                        continue;
3710                while (fgets(line,cBcLineLth,fp) != NULL)  {
3711                        if  (strncmp(line,fstr,fstrlen) == 0)  {
3712                                /* found entry for this station, read it and return */
3713                                cptr = line+fstrlen;
3714                                while  (*cptr == ' ' || *cptr == ':')
3715                                        cptr++;
3716                                outchan[0] = (cptr[0] > ' ') ? cptr[0] : '\0';
3717                                outchan[1] = (cptr[1] > ' ') ? cptr[1] : '\0';
3718                                outchan[2] = '\0';
3719                                fclose( fp );
3720                                return;
3721                        }  else if  (strncmp(line,dstr,dstrlen) == 0)  {
3722                                /* found at least a default entry, save this */
3723                                cptr = line+dstrlen;
3724                                while  (*cptr == ' ' || *cptr == ':')
3725                                        cptr++;
3726                                defchan[0] = (cptr[0] > ' ') ? cptr[0] : '\0';
3727                                defchan[1] = (cptr[1] > ' ') ? cptr[1] : '\0';
3728                                defchan[2] = '\0';
3729                                default_found = TRUE;
3730                        } /*endif*/
3731                } /*endwhile*/
3732                fclose( fp );
3733        } /*endif*/
3734
3735        if  (default_found)
3736                strcpy( outchan, defchan );
3737
3738} /* end of SeedTranslateChan */
3739
3740
3741
3742/*---------------------------------------------------------------------*/
3743
3744
3745
3746/* FORTRAN interface routine */
3747
3748
3749void SeedReadStreamReal_( int chan, char sfdfile[], char stream_str[],
3750        BOOLEAN swap, char req_start[], float seclth, float **fdat,
3751        INT32 *smplth, char act_start[], float *dt, float *calib,
3752        int *flags, STATUS *status )
3753{
3754
3755        SeedReadStreamReal( chan, sfdfile, stream_str, swap, req_start,
3756                seclth, fdat, smplth, act_start, dt, calib, flags, status );
3757
3758} /* end of SeedReadStreamReal_ */
3759
3760
3761void SeedLibInitialize_( STATUS *status )
3762{
3763
3764        SeedLibInitialize( status );
3765
3766} /* end of SeedLibInitialize_ */
3767
3768
3769void SeedSetup_( STATUS *status )
3770{
3771        static SeedSetupParT setup;
3772
3773        SeedSetup( &setup, status );
3774
3775} /* end of SeedSetup_ */
3776
3777
3778/*---------------------------------------------------------------------*/
Note: See TracBrowser for help on using the repository browser.