INT_TIME decode_time_sdr (SDR_TIME st, /* SDR_TIME structure to decode. */ int wordorder) /* wordorder of time contents. */ { SDR_TIME ct = st; EXT_TIME et; if (my_wordorder < 0) get_my_wordorder(); if (my_wordorder != wordorder) { swab2 ((short int *)&ct.year); swab2 ((short int *)&ct.day); swab2 ((short int *)&ct.ticks); } #ifdef QLIB_DEBUG if (debug_option & 128) fprintf (info, "time = %02d.%02d %02d:%02d:%02d:%04d\n", ct.year, ct.day, ct.hour, ct.minute, ct.second, ct.ticks); #endif et.year = ct.year; et.doy = ct.day; et.hour = ct.hour; et.minute = ct.minute; et.second = ct.second; et.usec = ct.ticks * USECS_PER_TICK; dy_to_mdy (et.doy, et.year, &et.month, &et.day); return (normalize_time(ext_to_int(et))); }
DATA_HDR *new_data_hdr () { DATA_HDR *hdr; if (my_wordorder < 0) get_my_wordorder(); hdr = (DATA_HDR *) malloc (sizeof(DATA_HDR)); if (hdr == NULL) { fprintf (stderr, "Error: unable to allocate data_hdr for output\n"); fflush (stderr); if (QLIB2_CLASSIC) exit (1); return (NULL); } init_data_hdr (hdr); return (hdr); }
char *asc_sdr_time (char *str, /* string to encode time into. */ SDR_TIME st, /* SDR_TIME structure to decode. */ int wordorder) /* wordorder for encoded time contents. */ { if (my_wordorder < 0) get_my_wordorder(); if (my_wordorder != wordorder) { swab2 ((short int *)&st.year); swab2 ((short int *)&st.day); swab2 ((short int *)&st.ticks); } sprintf(str,"%04d,%03d,%02d:%02d:%02d.%04d", st.year, st.day, st.hour, st.minute, st.second, st.ticks); return (str); }
int wordorder_from_time (unsigned char *p) /* ptr to fixed data time field. */ { int wordorder; unsigned char *cyear = p; /* This check ONLY works for dates in the range [1800, ..., 2054]. */ if (my_wordorder < 0) get_my_wordorder(); if ((cyear[0] == 0x07 && cyear[1] >= 0x08) || (cyear[0] == 0x08 && cyear[1] < 0x07)) wordorder = SEED_BIG_ENDIAN; else if ((cyear[1] == 0x07 && cyear[0] >= 0x08) || (cyear[1] == 0x08 && cyear[0] < 0x07)) wordorder = SEED_LITTLE_ENDIAN; else { fprintf (stderr, "Error: Unable to determine wordorder from time\n"); fflush (stderr); if (QLIB2_CLASSIC) exit(1); return (MS_ERROR); } return (wordorder); }
int blockettecmp (BS *bs1, /* BS* of first blockette to compare. */ BS *bs2) /* BS* of first blockette to compare. */ { int swapflag; SEED_UWORD l1, l2, type1, type2; int status; char *pbc1, *pbc2; char *p = NULL; if (my_wordorder < 0) get_my_wordorder(); if (bs1 == NULL && bs2 == NULL) return (0); if (bs1 == NULL) return (-1); if (bs2 == NULL) return (1); swapflag = (bs1->wordorder != bs2->wordorder); type1 = bs1->type; type2 = bs2->type; if (swapflag && bs1->wordorder != my_wordorder) swab2 ((short int *)&type1); if (swapflag && bs2->wordorder != my_wordorder) swab2 ((short int *)&type2); if (type1-type2) return (type1-type2); l1 = bs1->len; l2 = bs2->len; if (l1-l2) return (l1-l2); pbc1 = (char *)bs1->pb; pbc2 = (char *)bs2->pb; if (swapflag) { /* Reorder the wordorder of one of the blockettes for compare. */ p = (char *)malloc(l1-4); if (bs1->wordorder != my_wordorder) { memcpy (p, pbc1, l1); swab_blockette (type1, pbc1, l1); pbc1 = p; } else { memcpy (p, pbc2, l2); swab_blockette (type2, pbc2, l2); pbc2 = p; } } status = memcmp(pbc1+4, pbc2+4, l1-4); if (swapflag && p) free (p); return (status); }
int write_blockettes (DATA_HDR *hdr, /* ptr to data_hdr */ char *str) /* ptr to output SDR. */ { BS *bs = hdr->pblockettes; int offset = hdr->first_blockette; SEED_UWORD next; int alen; int swapflag; if (my_wordorder < 0) get_my_wordorder(); /* Ensure initial offset is a multiple of 4. */ if (offset%4) { memset (str+offset, 0, 4-(offset%4)); offset += 4-(offset%4); ((SDR_HDR *)str)->first_blockette = offset; } while (bs != (BS *)NULL) { /* Ensure offset to next blockette is correct. */ alen = bs->len; if (bs->len%4) alen += 4-(bs->len%4); next = (bs->next == NULL) ? 0 : offset + alen; if (my_wordorder != bs->wordorder) swab2((short int *)&next); ((BLOCKETTE_HDR *)(bs->pb))->next = next; memcpy (str+offset,bs->pb,bs->len); if (alen != bs->len) memset(str+offset+bs->len, 0, alen-bs->len); /* Ensure blockette wordorder is the same as hdr wordorder. */ swapflag = (hdr->hdr_wordorder != bs->wordorder); if (swapflag) { swab_blockette (bs->type, str+offset, bs->len); } offset += alen; bs = bs->next; } if (hdr->first_data > 0 && offset > hdr->first_data) { fprintf (stderr, "Error: blockettes won't fit between hdr and data.\n"); fflush (stderr); if (QLIB2_CLASSIC) exit(1); return (MS_ERROR); } return (0); }
int update_sdr_hdr (SDR_HDR *sh, /* ptr to space for SDR data hdr. */ DATA_HDR *hdr) /* initial DATA_HDR for SDR record. */ { int swapflag; /* flag to indicate byteswapping. */ short int stmp; if (my_wordorder < 0) get_my_wordorder(); swapflag = (my_wordorder != hdr->hdr_wordorder); if (swapflag) { stmp = hdr->num_samples; swab2 (&stmp); sh->num_samples = stmp; } else { sh->num_samples = hdr->num_samples; } if (hdr->num_samples == 0) sh->first_data = 0; return (0); }
int add_required_miniseed_blockettes (DATA_HDR *hdr) /* ptr to DATA_HDR. */ { int status = 0; /* Currently only blockette 1000 is required for miniSEED. */ if (my_wordorder < 0) get_my_wordorder(); if (find_blockette(hdr, 1000) == NULL) { BLOCKETTE_1000 b1000; int ok; b1000.hdr.type = 1000; b1000.hdr.next = 0; b1000.format = hdr->data_type; b1000.word_order = SEED_BIG_ENDIAN; b1000.data_rec_len = roundoff(log2((double)hdr->blksize)); b1000.reserved = 0; ok = add_blockette (hdr, (char *)&b1000, 1000, sizeof(BLOCKETTE_1000), my_wordorder, 0); if (! ok) status = MS_ERROR; } return (status); }
time_t unix_time_from_sdr_time (SDR_TIME st, /* SDR_TIME structure to convert. */ int wordorder) /* wordorder for encoded time contents. */ { EXT_TIME et; if (my_wordorder < 0) get_my_wordorder(); if (my_wordorder != wordorder) { swab2 ((short int *)&st.year); swab2 ((short int *)&st.day); swab2 ((short int *)&st.ticks); } et.year = st.year; et.doy = st.day; et.hour = st.hour; et.minute = st.minute; et.second = st.second; et.usec = st.ticks * USECS_PER_TICK; dy_to_mdy (et.doy, et.year, &et.month, &et.day); return (unix_time_from_ext_time(et)); }
SDR_TIME encode_time_sdr (INT_TIME it, /* IN_TIME structure to decode. */ int wordorder) /* wordorder for encoded time contents. */ { SDR_TIME st; EXT_TIME et = int_to_ext(it); if (my_wordorder < 0) get_my_wordorder(); st.year = et.year; st.day = et.doy; st.hour = et.hour; st.minute = et.minute; st.second = et.second; st.pad = 0; st.ticks = et.usec / USECS_PER_TICK; if (my_wordorder != wordorder) { swab2 ((short int *)&st.year); swab2 ((short int *)&st.day); swab2 ((short int *)&st.ticks); } return (st); }
int delete_blockette (DATA_HDR *hdr, /* ptr to DATA_HDR. */ int n) /* blockette # to delete. -1 -> ALL. */ { BS *bs = hdr->pblockettes; BS *pbs = (BS *)NULL; BS *dbs; int num_deleted = 0; SEED_UWORD type; /* Don't worry about updating the offset within the blockette */ /* headers, since we will do that on output. */ if (my_wordorder < 0) get_my_wordorder(); while (bs != (BS *)NULL) { type = bs->type; if ( n < 0 || n == type) { if (pbs == NULL) hdr->pblockettes = bs->next; else pbs->next = bs->next; --(hdr->num_blockettes); if (hdr->num_blockettes <= 0) hdr->first_blockette = 0; dbs = bs; bs = bs->next; free (dbs->pb); free ((char *)dbs); ++num_deleted; } else { pbs = bs; bs = bs->next; } } return (num_deleted); }
int pack_steim2 (SDF *p_sdf, /* ptr to SDR structure. */ int data[], /* unpacked data array. */ int diff[], /* unpacked diff array. */ int ns, /* num_samples. */ int nf, /* total number of data frames. */ int pad, /* flag to specify padding to nf. */ int data_wordorder, /* wordorder of data (NOT USED). */ int *pnframes, /* number of frames actually packed. */ int *pnsamples) /* number of samples actually packed. */ { int points_remaining = ns; int *minbits; /* min bits for difference. */ int i, j; int mask; int ipt = 0; /* index of initial data to pack. */ int fn = 0; /* index of initial frame to pack. */ int wn = 2; /* index of initial word to pack. */ int itmp; short int stmp; int swapflag; int nb; /* number of minbits to compute. */ int max_samples_per_frame; if (my_wordorder < 0) get_my_wordorder(); swapflag = (my_wordorder != data_wordorder); max_samples_per_frame = 8 * VALS_PER_FRAME; /* steim2 compression. */ nb = max_samples_per_frame * nf; if (nb > points_remaining) nb = points_remaining; minbits = NULL; minbits = (int *)malloc(nb * sizeof(int)); if (minbits == NULL) { fprintf (stderr, "Error: mallocing minbits in pack_steim1\n"); fflush (stderr); if (QLIB2_CLASSIC) exit(1); return (MS_ERROR); } for (i=0; i<nb; i++) MINBITS(diff[i],minbits[i]); p_sdf->f[fn].ctrl = 0; /* Set new X0 value in first frame. */ X0 = data[0]; if (swapflag) swab4((int *)&X0); p_sdf->f[fn].ctrl = (p_sdf->f[fn].ctrl<<2) | STEIM2_SPECIAL_MASK; XN = data[ns-1]; if (swapflag) swab4((int *)&XN); p_sdf->f[fn].ctrl = (p_sdf->f[fn].ctrl<<2) | STEIM2_SPECIAL_MASK; while (points_remaining > 0) { /* Pack the next available datapoints into the most compact form. */ if (BIT4PACK(ipt,points_remaining)) { PACK(4,7,0x0000000f,02) if (swapflag) swab4 ((int *)&p_sdf->f[fn].w[wn].fw); mask = STEIM2_567_MASK; points_remaining -= 7; } else if (BIT5PACK(ipt,points_remaining)) { PACK(5,6,0x0000001f,01) if (swapflag) swab4 ((int *)&p_sdf->f[fn].w[wn].fw); mask = STEIM2_567_MASK; points_remaining -= 6; } else if (BIT6PACK(ipt,points_remaining)) {
DATA_HDR *decode_hdr_sdr (SDR_HDR *ihdr, /* input SDR header. */ int maxbytes) /* max # bytes in buffer. */ { char tmp[80]; DATA_HDR *ohdr; BS *bs; /* ptr to blockette structure. */ char *p; char *pc; int i, next_seq; int seconds, usecs; int swapflag; int itmp[2]; short int stmp[2]; unsigned short int ustmp[2]; int wo; qlib2_errno = 0; if (my_wordorder < 0) get_my_wordorder(); /* Perform data integrity check, and pick out pertinent header info.*/ if (! (is_data_hdr_ind (ihdr->data_hdr_ind) || is_vol_hdr_ind (ihdr->data_hdr_ind))) { /* Don't have a data header. See if the entire header is */ /* composed of NULLS. If so, print warning and return NULL. */ /* Some early Quanterras output a spurious block with null */ /* header info every 16 blocks. That block should be ignored. */ if (allnull((char *)ihdr, sizeof(SDR_HDR))) { return ((DATA_HDR *)NULL); } else { qlib2_errno = 1; return ((DATA_HDR *)NULL); } } if ((ohdr = new_data_hdr()) == NULL) return (NULL); ohdr->record_type = ihdr->data_hdr_ind; ohdr->seq_no = atoi (charncpy (tmp, ihdr->seq_no, 6) ); /* Handle volume header. */ /* Return a pointer to a DATA_HDR structure containing blksize. */ /* Save actual blockette for later use. */ if (is_vol_hdr_ind(ihdr->data_hdr_ind)) { /* Get blksize from volume header. */ p = (char *)ihdr+8; ohdr->blksize = 4096; /* default tape blksize. */ /* Put volume blockette number in data_type field. */ ohdr->data_type = atoi (charncpy (tmp, p, 3)); switch (ohdr->data_type) { int ok; case 5: case 8: case 10: ohdr->blksize = (int)pow(2.0,atoi(charncpy(tmp,p+11,2))); ok = add_blockette (ohdr, p, ohdr->data_type, atoi(charncpy(tmp,p+3,4)), my_wordorder, 0); if (! ok) { qlib2_errno = 2; free_data_hdr(ohdr); return ((DATA_HDR *)NULL); } break; default: break; } return (ohdr); } /* Determine word order of the fixed record header. */ if ((wo = wordorder_from_time((unsigned char *)&(ihdr->time))) < 0) { qlib2_errno = 3; free_data_hdr (ohdr); return ((DATA_HDR *)NULL); } ohdr->hdr_wordorder = wo; ohdr->data_wordorder = ohdr->hdr_wordorder; swapflag = (ohdr->hdr_wordorder != my_wordorder); charncpy (ohdr->station_id, ihdr->station_id, 5); charncpy (ohdr->location_id, ihdr->location_id, 2); charncpy (ohdr->channel_id, ihdr->channel_id, 3); charncpy (ohdr->network_id, ihdr->network_id, 2); trim (ohdr->station_id); trim (ohdr->location_id); trim (ohdr->channel_id); trim (ohdr->network_id); ohdr->hdrtime = decode_time_sdr(ihdr->time, ohdr->hdr_wordorder); if (swapflag) { /* num_samples. */ ustmp[0] = ihdr->num_samples; swab2 ((short int *)&ustmp[0]); ohdr->num_samples = ustmp[0]; /* data_rate */ stmp[0] = ihdr->sample_rate_factor; stmp[1] = ihdr->sample_rate_mult; swab2 ((short int *)&stmp[0]); swab2 ((short int *)&stmp[1]); ohdr->sample_rate = stmp[0]; ohdr->sample_rate_mult = stmp[1]; /* num_ticks_correction. */ itmp[0] = ihdr->num_ticks_correction; swab4 (&itmp[0]); ohdr->num_ticks_correction = itmp[0]; /* first_data */ ustmp[0] = ihdr->first_data; swab2 ((short int *)&ustmp[0]); ohdr->first_data = ustmp[0]; /* first_blockette */ ustmp[1] = ihdr->first_blockette; swab2 ((short int *)&ustmp[1]); ohdr->first_blockette = ustmp[1]; } else { ohdr->num_samples = ihdr->num_samples; ohdr->sample_rate = ihdr->sample_rate_factor; ohdr->sample_rate_mult = ihdr->sample_rate_mult; ohdr->num_ticks_correction = ihdr->num_ticks_correction; ohdr->first_data = ihdr->first_data; ohdr->first_blockette = ihdr->first_blockette; } /* WARNING - may need to convert flags to independent format */ /* if we ever choose a different flag format for the DATA_HDR. */ ohdr->activity_flags = ihdr->activity_flags; ohdr->io_flags = ihdr->io_flags; ohdr->data_quality_flags = ihdr->data_quality_flags; ohdr->num_blockettes = ihdr->num_blockettes; ohdr->data_type = 0; /* assume unknown datatype. */ ohdr->pblockettes = (BS *)NULL; /* Do not parse blockettes here.*/ if (ohdr->num_blockettes == 0) ohdr->pblockettes = (BS *)NULL; else { if (read_blockettes (ohdr, (char *)ihdr) != 1) { free ((char *)ohdr); return ((DATA_HDR *)NULL); } } /* Process any blockettes that follow the fixed data header. */ /* If a blockette 1000 exists, fill in the datatype. */ /* Otherwise, leave the datatype as unknown. */ ohdr->data_type = UNKNOWN_DATATYPE; ohdr->num_data_frames = -1; if ((bs=find_blockette(ohdr, 1000))) { /* Ensure we have proper output blocksize in the blockette. */ BLOCKETTE_1000 *b1000 = (BLOCKETTE_1000 *) bs->pb; ohdr->data_type = b1000->format; ohdr->blksize = (int)pow(2.0,b1000->data_rec_len); ohdr->data_wordorder = b1000->word_order; } if ((bs=find_blockette(ohdr, 1001))) { /* Add in the usec99 field to the hdrtime. */ BLOCKETTE_1001 *b1001 = (BLOCKETTE_1001 *) bs->pb; ohdr->hdrtime = add_time (ohdr->hdrtime, 0, b1001->usec99); ohdr->num_data_frames = b1001->frame_count; } /* If the time correction has not already been added, we should */ /* add it to the begtime. Do NOT change the ACTIVITY flag, since */ /* it refers to the hdrtime, NOT the begtime/endtime. */ ohdr->begtime = ohdr->hdrtime; if ( ohdr->num_ticks_correction != 0 && ((ohdr->activity_flags & ACTIVITY_TIME_CORR_APPLIED) == 0) ) { ohdr->begtime = add_dtime (ohdr->begtime, (double)ohdr->num_ticks_correction * USECS_PER_TICK); } /* Compute endtime. Use precise sample interval in blockette 100. */ /* For client convenience convert it to my_wordorder if not already.*/ if ((bs=find_blockette(ohdr, 100))) { double actual_rate, dusecs; BLOCKETTE_100 *b = (BLOCKETTE_100 *) bs->pb; if (bs->wordorder != my_wordorder) { swab_blockette (bs->type, bs->pb, bs->len); bs->wordorder = my_wordorder; } actual_rate = b->actual_rate; dusecs = ((double)((ohdr->num_samples-1)/actual_rate))*USECS_PER_SEC; ohdr->endtime = add_dtime (ohdr->begtime, dusecs); ohdr->rate_spsec = actual_rate; } else { time_interval2(ohdr->num_samples - 1, ohdr->sample_rate, ohdr->sample_rate_mult, &seconds, &usecs); ohdr->endtime = add_time(ohdr->begtime, seconds, usecs); } /* Attempt to determine blocksize if current setting is 0. */ /* We can detect files of either 512 byte or 4K byte blocks. */ if (ohdr->blksize == 0) { for (i=1; i< 4; i++) { pc = ((char *)(ihdr)) + (i*512); if (pc - (char *)(ihdr) >= maxbytes) break; if ( allnull ( pc,sizeof(SDR_HDR)) ) continue; next_seq = atoi (charncpy (tmp, ((SDR_HDR *)pc)->seq_no, 6) ); if (next_seq == ohdr->seq_no + i) { ohdr->blksize = 512; break; } } /* Can't determine the blocksize. Assume default. */ /* Assume all non-MiniSEED SDR data is in STEIM1 format. */ /* Assume data_wordorder == hdr_wordorder. */ if (ohdr->blksize == 0) ohdr->blksize = (maxbytes >= 1024) ? 4096 : 512; if (ohdr->num_samples > 0 && ohdr->sample_rate != 0) { ohdr->data_type = STEIM1; ohdr->num_data_frames = (ohdr->blksize-ohdr->first_data)/sizeof(FRAME); ohdr->data_wordorder = ohdr->hdr_wordorder; } } /* Fill in num_data_frames, since there may not be a blockette 1001.*/ if (IS_STEIM_COMP(ohdr->data_type) && ohdr->num_samples > 0 && ohdr->sample_rate != 0 && ohdr->num_data_frames < 0) { ohdr->num_data_frames = (ohdr->blksize-ohdr->first_data)/sizeof(FRAME); } return (ohdr); }
int init_sdr_hdr (SDR_HDR *sh, /* ptr to space for sdr data hdr. */ DATA_HDR *hdr, /* initial DATA_HDR for sdr record. */ BS *extra_bs) /* ptr to block-specific blockettes. */ { int status = 0; int blockette_space; /* # of bytes required for blockettes. */ int n_extra_bs; /* # of extra blockettes. */ BS *bs; /* ptr to blockette structure. */ BS *last_bs; /* ptr to last permanent blockette. */ int align; /* alignment in bytes required for data.*/ int swapflag; /* flag to indicate byteswapping. */ MS_ATTR attr; int blksize = hdr->blksize; if (my_wordorder < 0) get_my_wordorder(); swapflag = (my_wordorder != hdr->hdr_wordorder); /* Determine the space required for all of the blockettes. */ for (bs=hdr->pblockettes, blockette_space=0, last_bs=NULL; bs!=NULL; last_bs=bs, bs=bs->next) { blockette_space += bs->len + ((bs->len%4) ? 4-(bs->len%4) : 0); } for (bs=extra_bs, n_extra_bs=0; bs!=NULL; bs=bs->next, n_extra_bs++) { blockette_space += bs->len + ((bs->len%4) ? 4-(bs->len%4) : 0); } /* Temporarily add the list of extra blockettes to the list of */ /* permanent blockettes. */ if (extra_bs) { if (last_bs) last_bs->next = extra_bs; else hdr->pblockettes = extra_bs; hdr->num_blockettes += n_extra_bs; } /* Ensure that first_data points to appropriate offset for data. */ /* Some data formats (eg the STEIM compressed formats) require */ /* first_data to be on a frame boundary. */ attr = get_ms_attr(hdr); if (attr.alignment == 0) return (MS_ERROR); align = attr.alignment; hdr->first_data = ((sizeof(SDR_HDR)+blockette_space+align-1)/align)*align; /* Update any blockettes that have block-specific info. */ if ((bs=find_blockette(hdr, 1000))) { /* Ensure we have proper data in the blockette. */ BLOCKETTE_1000 *b1000 = (BLOCKETTE_1000 *) bs->pb; /* These are all byte values, so I can ignore wordorder. */ b1000->data_rec_len = roundoff(log2((double)blksize)); b1000->format = hdr->data_type; b1000->word_order = hdr->data_wordorder; } if ((bs=find_blockette(hdr, 1001))) { /* Ensure we have proper data in the blockette. */ /* Mark all frames as being in use. */ BLOCKETTE_1001 *b1001 = (BLOCKETTE_1001 *) bs->pb; /* These are all byte values, so I can ignore wordorder. */ b1001->frame_count = hdr->num_data_frames; b1001->usec99 = hdr->hdrtime.usec % 100; } /* Create the SDR fixed data header and data blockettes. */ /* Parts of the header that do not change from block to block. */ sh->space_1 = ' '; capnstr(sh->station_id,hdr->station_id,5); capnstr(sh->channel_id,hdr->channel_id,3); capnstr(sh->network_id,hdr->network_id,2); capnstr(sh->location_id,hdr->location_id,2); sh->sample_rate_factor = hdr->sample_rate; sh->sample_rate_mult = (hdr->sample_rate) ? hdr->sample_rate_mult : 0; /* Parts of the header that change with each block. */ sh->data_hdr_ind = hdr->record_type; capnint(sh->seq_no,hdr->seq_no,6); sh->time = encode_time_sdr(hdr->hdrtime, hdr->hdr_wordorder); sh->activity_flags = hdr->activity_flags; sh->io_flags = hdr->io_flags; sh->data_quality_flags = hdr->data_quality_flags; sh->num_samples = 0; sh->num_ticks_correction = hdr->num_ticks_correction; /* Parts of the header that depend on the blockettes. */ sh->first_data = hdr->first_data; sh->num_blockettes = hdr->num_blockettes; sh->first_blockette = hdr->first_blockette; /* Output any data blockettes. */ if (hdr->num_blockettes > 0) { write_blockettes(hdr, (char *)sh); } /* Unlink the extra blockettes from the data_hdr. */ if (extra_bs) { if (last_bs) last_bs->next = NULL; else hdr->pblockettes = NULL; hdr->num_blockettes -= n_extra_bs; } if (swapflag) { swab2 ((short int *)&sh->num_samples); swab2 ((short int *)&sh->sample_rate_factor); swab2 ((short int *)&sh->sample_rate_mult); swab2 ((short int *)&sh->first_data); swab2 ((short int *)&sh->first_blockette); swab4 ((int *)&sh->num_ticks_correction); } /* Zero any space between the end of the blockettes and first_data. */ memset ((char*)sh + (sizeof(SDR_HDR)+blockette_space), 0, hdr->first_data - (sizeof(SDR_HDR)+blockette_space)); /* Return status our SDR header creation. */ return (status); }
int read_ms_bkt (DATA_HDR *hdr, /* data_header structure. */ char *buf, /* ptr to fixed data header. */ FILE *fp) /* FILE pointer for input file. */ { BS *bs, *pbs; int offset, i, bl_limit; SEED_UWORD bl_len, bl_next, bl_type; int bh_len = sizeof(BLOCKETTE_HDR); int blksize = 0; int preread = 0; /* # bytes of blockette data preread. */ if (my_wordorder < 0) get_my_wordorder(); bs = pbs = (BS *)NULL; offset = hdr->first_blockette; hdr->pblockettes = (BS *)NULL; bl_next = 0; /* Run through each blockette, allocate a linked list structure */ /* for it, and verify that the blockette structures are OK. */ /* There is a LOT of checking to ensure proper structure. */ for (i=0; i<hdr->num_blockettes; i++) { if (i > 0 && bl_next == 0) { fprintf (stderr, "Error: zero offset to next blockette\n"); fflush (stderr); if (QLIB2_CLASSIC) exit(1); return (MS_ERROR); } if ( (bs=(BS *)malloc(sizeof(BS))) == NULL ) { fprintf (stderr, "Error: unable to malloc BS\n"); if (QLIB2_CLASSIC) exit(1); return (QLIB2_MALLOC_ERROR); } bs->next = (BS *)NULL; if (i == 0) hdr->pblockettes = bs; else pbs->next = bs; pbs = bs; /* Read blockette header. */ if (fread (buf+offset, bh_len, 1, fp) != 1) return (EOF); preread = 0; /* Decide how much space the blockette takes up. If we know */ /* blockette type, then allocate the appropriate space. */ /* Otherwise, determine the required space by the offset to */ /* the next blockette, or by the offset to the first data if */ /* this is the last blockette. */ /* If there is not data, then ensure that we know the length */ /* of the blockette. If not, consider it to be a fatal error, */ /* since we have no idea how long it should be. */ /* */ /* We cannot allow it to extend to the blksize, since we use */ /* this routine to process blockettes from packed miniSEED */ /* files. Packed miniSEED files contain records that are a */ /* multiple of the packsize (currently 128 bytes) with a block */ /* whose size is specified in the b1000 blksize field. */ bl_type = ((BLOCKETTE_HDR *)(buf+offset))->type; bl_next = ((BLOCKETTE_HDR *)(buf+offset))->next; if (hdr->hdr_wordorder != my_wordorder) { swab2 ((short int *)&bl_type); swab2 ((short int *)&bl_next); } bl_limit = (bl_next) ? bl_next : (hdr->first_data) ? hdr->first_data : 0; switch (bl_type) { case 100: bl_len = sizeof (BLOCKETTE_100); break; case 200: bl_len = sizeof (BLOCKETTE_200); break; case 201: bl_len = sizeof (BLOCKETTE_201); break; case 300: bl_len = sizeof (BLOCKETTE_300); break; case 310: bl_len = sizeof (BLOCKETTE_310); break; case 320: bl_len = sizeof (BLOCKETTE_320); break; case 390: bl_len = sizeof (BLOCKETTE_390); break; case 395: bl_len = sizeof (BLOCKETTE_395); break; case 400: bl_len = sizeof (BLOCKETTE_400); break; case 405: bl_len = sizeof (BLOCKETTE_405); break; case 500: bl_len = sizeof (BLOCKETTE_500); break; case 1000: bl_len = sizeof (BLOCKETTE_1000); break; case 1001: bl_len = sizeof (BLOCKETTE_1001); break; /* Variable length blockettes. Preserve original length, */ /* even though it may not is divisible by 4. */ /* It is up to the user to ensure that that blockettes */ /* have 4 byte alignment in a SEED data record. */ case 2000: /* Length of blockette 2000 is stored in first word of blockette. */ preread = 2; if (fread (buf+offset+bh_len, preread, 1, fp) != 1) return (EOF); bl_len = ((BLOCKETTE_2000 *)(buf+offset))->blockette_len; if (hdr->hdr_wordorder != my_wordorder) { swab2 ((short int *)&bl_len); } break; default: fprintf (stderr, "Warning: unknown blockette %d\n",bl_type); bl_len = 0; break; } /* Perform integrity checks on blockette. */ if (bl_len != 0) { /* Known blockettes: */ /* Check that the presumed blockette length is correct. */ if (bl_limit > 0 && (int)bl_len > bl_limit-offset) { /* Warning only if blockette is too short. */ /* Allow padding between blockettes. */ fprintf (stderr, "Warning: short blockette %d len=%d, expected len=%d\n", bl_type, bl_limit-offset, bl_len); } /* Be safe and extend the effective length of the blockette */ /* to the limit (next blockette or first data) if there is */ /* a limit. */ bl_len = (bl_limit) ? bl_limit - offset : bl_len; /* Check that we do not run into the data portion of record.*/ if (hdr->first_data != 0 && (int)bl_len+offset > hdr->first_data) { fprintf (stderr, "Warning: blockette %d at offset=%d len=%d first_data=%d\n", bl_type, bl_limit-offset, bl_len, hdr->first_data); bl_len = bl_limit - offset; } } else { /* Unknown blockettes: */ if (bl_limit == 0) { fprintf (stderr, "Warning: unknown blockette and no length limit\n"); return (-1); } /* For unknown blockettes ensure that we have a max len. */ bl_len = bl_limit - offset; } if ((bs->pb = (char *)malloc(bl_len))==NULL) { fprintf (stderr, "unable to malloc blockettd\n"); return (-1); } /* Read the body of the blockette, and copy entire blockette. */ if (fread(buf+offset+bh_len+preread, bl_len-bh_len-preread, 1, fp) != 1) return(-1); memcpy (bs->pb,buf+offset,bl_len); bs->len = bl_len; bs->type = bl_type; bs->wordorder = hdr->hdr_wordorder; if (bl_type == 1000) { blksize = (int)pow(2., (double)((BLOCKETTE_1000 *)(buf+offset))->data_rec_len); } offset += bl_len; preread = 0; } /* Ensure there are no more blockettes. */ if (bl_next != 0) { fprintf (stderr, "extra blockette found\n"); return(-1); } return (offset); }
DATA_HDR *decode_fixed_data_hdr (SDR_HDR *ihdr) /* MiniSEED header. */ { char tmp[80]; DATA_HDR *ohdr; int seconds, usecs; char *p; int swapflag; int itmp[2]; short int stmp[2]; unsigned short int ustmp[2]; int wo; if (my_wordorder < 0) get_my_wordorder(); /* Perform data integrity check, and pick out pertinent header info.*/ if (! (is_data_hdr_ind (ihdr->data_hdr_ind) || is_vol_hdr_ind (ihdr->data_hdr_ind))) { return ((DATA_HDR *)NULL); } if ((ohdr = new_data_hdr()) == NULL) return (NULL); ohdr->record_type = ihdr->data_hdr_ind; ohdr->seq_no = atoi (charncpy (tmp, ihdr->seq_no, 6) ); /* Handle volume header. */ /* Return a pointer to a DATA_HDR structure containing blksize. */ /* Save actual blockette for later use. */ if (is_vol_hdr_ind(ihdr->data_hdr_ind)) { if ((ohdr = new_data_hdr()) == NULL) return (NULL); ohdr->record_type = ihdr->data_hdr_ind; ohdr->seq_no = atoi (charncpy (tmp, ihdr->seq_no, 6) ); ohdr->blksize = 4096; /* default tape blksize. */ p = (char *)ihdr+8; /* point to start of blockette. */ ohdr->data_type = atoi(charncpy(tmp,p,3)); switch (ohdr->data_type) { case 5: case 8: case 10: ohdr->blksize = (int)pow(2.0,atoi(charncpy(tmp,p+11,2))); /* Do not add the blockette here, since we are not */ /* assured that the entire blockette is in this buffer. */ break; default: break; } return (ohdr); } /* Determine word order of the fixed record header. */ if ((wo = wordorder_from_time((unsigned char *)&(ihdr->time)))< 0) { free_data_hdr (ohdr); return ((DATA_HDR *)NULL); } ohdr->hdr_wordorder = wo; ohdr->data_wordorder = ohdr->hdr_wordorder; swapflag = (ohdr->hdr_wordorder != my_wordorder); charncpy (ohdr->station_id, ihdr->station_id, 5); charncpy (ohdr->location_id, ihdr->location_id, 2); charncpy (ohdr->channel_id, ihdr->channel_id, 3); charncpy (ohdr->network_id, ihdr->network_id, 2); trim (ohdr->station_id); trim (ohdr->location_id); trim (ohdr->channel_id); trim (ohdr->network_id); ohdr->hdrtime = ohdr->begtime = decode_time_sdr(ihdr->time, ohdr->hdr_wordorder); if (swapflag) { /* num_samples. */ ustmp[0] = ihdr->num_samples; swab2 ((short int *)&ustmp[0]); ohdr->num_samples = ustmp[0]; /* data_rate */ stmp[0] = ihdr->sample_rate_factor; stmp[1] = ihdr->sample_rate_mult; swab2 (&stmp[0]); swab2 (&stmp[1]); ohdr->sample_rate = stmp[0]; ohdr->sample_rate_mult = stmp[1]; /* num_ticks_correction. */ itmp[0] = ihdr->num_ticks_correction; swab4 (&itmp[0]); ohdr->num_ticks_correction = itmp[0]; /* first_data */ ustmp[0] = ihdr->first_data; swab2 ((short int *)&ustmp[0]); ohdr->first_data = ustmp[0]; /* first_blockette */ ustmp[1] = ihdr->first_blockette; swab2 ((short int *)&ustmp[1]); ohdr->first_blockette = ustmp[1]; } else { ohdr->num_samples = ihdr->num_samples; ohdr->sample_rate = ihdr->sample_rate_factor; ohdr->sample_rate_mult = ihdr->sample_rate_mult; ohdr->num_ticks_correction = ihdr->num_ticks_correction; ohdr->first_data = ihdr->first_data; ohdr->first_blockette = ihdr->first_blockette; } /* WARNING - may need to convert flags to independent format */ /* if we ever choose a different flag format for the DATA_HDR. */ ohdr->activity_flags = ihdr->activity_flags; ohdr->io_flags = ihdr->io_flags; ohdr->data_quality_flags = ihdr->data_quality_flags; ohdr->num_blockettes = ihdr->num_blockettes; ohdr->data_type = 0; /* assume unknown datatype. */ ohdr->pblockettes = (BS *)NULL; /* Do not parse blockettes here.*/ /* If the time correction has not already been added, we should */ /* add it to the begtime. Do NOT change the ACTIVITY flag, since */ /* it refers to the hdrtime, NOT the begtime/endtime. */ if ( ohdr->num_ticks_correction != 0 && ((ohdr->activity_flags & ACTIVITY_TIME_CORR_APPLIED) == 0) ) { ohdr->begtime = add_dtime (ohdr->begtime, (double)ohdr->num_ticks_correction * USECS_PER_TICK); } time_interval2(ohdr->num_samples - 1, ohdr->sample_rate, ohdr->sample_rate_mult, &seconds, &usecs); ohdr->endtime = add_time(ohdr->begtime, seconds, usecs); return(ohdr); }
int read_blockettes (DATA_HDR *hdr, /* data_header structure. */ char *str) /* ptr to fixed data header. */ { BS *bs, *pbs; int offset, i; SEED_UWORD bl_len, bl_next, bl_type; if (my_wordorder < 0) get_my_wordorder(); bs = pbs = (BS *)NULL; offset = hdr->first_blockette; hdr->pblockettes = (BS *)NULL; bl_next = 0; /* Run through each blockette, allocate a linked list structure */ /* for it, and verify that the blockette structures are OK. */ /* There is a LOT of checking to ensure proper structure. */ for (i=0; i<hdr->num_blockettes; i++) { if (i > 0 && bl_next == 0) { fprintf (stderr, "Error: zero offset to next blockette\n"); fflush (stderr); if (QLIB2_CLASSIC) exit(1); return (MS_ERROR); } if ( (bs=(BS *)malloc(sizeof(BS))) == NULL ) { fprintf (stderr, "Error: unable to malloc BS\n"); fflush (stderr); if (QLIB2_CLASSIC) exit(1); return (QLIB2_MALLOC_ERROR); } bs->next = (BS *)NULL; /* Decide how much space the blockette takes up. */ /* In order to allow for variable blockette size for either */ /* newer SEED version or vendor-specific additions, */ /* attempt to determine the required space by the offset to */ /* the next blockette. If this is the last blockette, */ /* then just use the length of the blockette as it is defined. */ bl_type = ((BLOCKETTE_HDR *)(str+offset))->type; bl_next = ((BLOCKETTE_HDR *)(str+offset))->next; if (hdr->hdr_wordorder != my_wordorder) { swab2 ((short int *)&bl_type); swab2 ((short int *)&bl_next); } if (bl_next > 0) { bl_len = (bl_next-offset); } else { /* No further blockettes. Assume length of blockette structure.*/ switch (bl_type) { /* Fixed length blockettes. */ case 100: bl_len = sizeof (BLOCKETTE_100); break; case 200: bl_len = sizeof (BLOCKETTE_200); break; case 201: bl_len = sizeof (BLOCKETTE_201); break; case 300: bl_len = sizeof (BLOCKETTE_300); break; case 310: bl_len = sizeof (BLOCKETTE_310); break; case 320: bl_len = sizeof (BLOCKETTE_320); break; case 390: bl_len = sizeof (BLOCKETTE_390); break; case 395: bl_len = sizeof (BLOCKETTE_395); break; case 400: bl_len = sizeof (BLOCKETTE_400); break; case 405: bl_len = sizeof (BLOCKETTE_405); break; case 500: bl_len = sizeof (BLOCKETTE_500); break; case 1000: bl_len = sizeof (BLOCKETTE_1000); break; case 1001: bl_len = sizeof (BLOCKETTE_1001); break; /* Variable length blockettes. Preserve original length, */ /* even though it may not is divisible by 4. */ /* It is up to the user to ensure that that blockettes */ /* have 4 byte alignment in a SEED data record. */ case 2000: bl_len = ((BLOCKETTE_2000 *)(str+offset))->blockette_len; if (hdr->hdr_wordorder != my_wordorder) { swab2 ((short int *)&bl_len); } break; default: bl_type = 0; bl_len = 0; break; } /* Ensure that the blockette length does not exceed space */ /* available for it after the header and before first_data. */ if (hdr->first_data > 0 && hdr->first_data - offset > 0 && (int)bl_len > hdr->first_data - offset) bl_len = hdr->first_data - offset; } if (bl_next != 0 && bl_len != 0) { /* Verify length for known blockettes when possible. */ /*:: if (bl_len != bl_next-offset) { fprintf (stderr, "Error: blockette %d apparent size %d does not match known length %d\n", bl_type, bl_next-offset, bl_len); fflush (stderr); if (QLIB2_CLASSIC) exit(1); return (MS_ERROR); } ::*/ } else if (bl_len == 0 && bl_type == 0) { /* Assume the blockette reaches to first data. */ /* If first data == 0, then abort -- we don't know this blockette. */ if (hdr->first_data <= offset) { fprintf (stderr, "Unknown blockette type %d - unable to determine size\n", ((BLOCKETTE_HDR *)(str+offset))->type); fflush (stderr); free ((char *)bs); continue; } else bl_len = hdr->first_data - offset; } if ((bs->pb = (char *)malloc(bl_len))==NULL) { fprintf (stderr, "Error: unable to malloc blockette\n"); fflush (stderr); if (QLIB2_CLASSIC) exit(1); return (MS_ERROR); } memcpy (bs->pb,str+offset,bl_len); bs->len = bl_len; bs->type = bl_type; bs->wordorder = hdr->hdr_wordorder; offset += bl_len; if (i == 0) hdr->pblockettes = bs; else pbs->next = bs; pbs = bs; } /* Ensure there are no more blockettes. */ if (bl_next != 0) { fprintf (stderr, "extra blockette found\n"); fflush (stderr); return (QLIB2_CLASSIC ? 0 : MS_ERROR); } return (1); }
int f_get_my_wordorder (void) #endif { return (get_my_wordorder()); }
int pack_steim1 (SDF *p_sdf, /* ptr to SDR structure. */ int data[], /* unpacked data array. */ int diff[], /* unpacked diff array. */ int ns, /* num_samples. */ int nf, /* total number of data frames. */ int pad, /* flag to specify padding to nf. */ int data_wordorder, /* wordorder of data (NOT USED). */ int *pnframes, /* number of frames actually packed. */ int *pnsamples) /* number of samples actually packed. */ { int points_remaining = ns; int *minbits; /* min bytes for difference. */ int i, j; int mask; int ipt = 0; /* index of initial data to pack. */ int fn = 0; /* index of initial frame to pack. */ int wn = 2; /* index of initial word to pack. */ int itmp; short int stmp; int swapflag; int nb; /* number of minbits to compute. */ int max_samples_per_frame; if (my_wordorder < 0) get_my_wordorder(); swapflag = (my_wordorder != data_wordorder); max_samples_per_frame = 4 * VALS_PER_FRAME; /* steim1 compression. */ nb = max_samples_per_frame * nf; if (nb > points_remaining) nb = points_remaining; minbits = NULL; minbits = (int *)malloc(nb * sizeof(int)); if (minbits == NULL) { fprintf (stderr, "Error: mallocing minbits in pack_steim1\n"); fflush (stderr); if (QLIB2_CLASSIC) exit(1); return (MS_ERROR); } for (i=0; i<nb; i++) MINBITS(diff[i],minbits[i]); p_sdf->f[fn].ctrl = 0; /* Set new X0 value in first frame. */ X0 = data[0]; if (swapflag) swab4((int *)&X0); p_sdf->f[fn].ctrl = (p_sdf->f[fn].ctrl<<2) | STEIM1_SPECIAL_MASK; XN = data[ns-1]; if (swapflag) swab4((int *)&XN); p_sdf->f[fn].ctrl = (p_sdf->f[fn].ctrl<<2) | STEIM1_SPECIAL_MASK; while (points_remaining > 0) { /* Pack the next available data into the most compact form. */ if (BYTEPACK(ipt,points_remaining)) { mask = STEIM1_BYTE_MASK; for (j=0; j<4; j++) p_sdf->f[fn].w[wn].byte[j] = diff[ipt++]; points_remaining -= 4; } else if (HALFPACK(ipt,points_remaining)) { mask = STEIM1_HALFWORD_MASK; for (j=0; j<2; j++) { stmp = diff[ipt++]; if (swapflag) swab2 (&stmp); p_sdf->f[fn].w[wn].hw[j] = stmp; } points_remaining -= 2; } else { mask = STEIM1_FULLWORD_MASK; itmp = diff[ipt++]; if (swapflag) swab4 (&itmp); p_sdf->f[fn].w[wn].fw = itmp; points_remaining -= 1; } /* Append mask for this word to current mask. */ p_sdf->f[fn].ctrl = (p_sdf->f[fn].ctrl<<2) | mask; /* Check for full frame or full block. */ if (++wn >= VALS_PER_FRAME) { if (swapflag) swab4 ((int *)&p_sdf->f[fn].ctrl); /* Reset output index to beginning of frame. */ wn = 0; /* If block is full, output block and reinitialize. */ if (++fn >= nf) break; p_sdf->f[fn].ctrl = 0; } } /* Set new XN value in first frame. */ XN = data[(ns-1)-points_remaining]; if (swapflag) swab4((int *)&XN); /* End of data. Pad current frame and optionally rest of block. */ /* Do not pad and output a completely empty block. */ if (! EMPTY_BLOCK(fn,wn)) { *pnframes = pad_steim_frame(p_sdf,fn,wn,nf,swapflag,pad); } else { *pnframes = 0; } *pnsamples = ns - points_remaining; free ((char *)minbits); return(0); }