1 /***************************************************************************
4 * Generic routines to unpack Mini-SEED records.
6 * Appropriate values from the record header will be byte-swapped to
7 * the host order. The purpose of this code is to provide a portable
8 * way of accessing common SEED data record header information. All
9 * data structures in SEED 2.4 data records are supported. The data
10 * samples are optionally decompressed/unpacked.
12 * Written by Chad Trabant,
13 * ORFEUS/EC-Project MEREDIAN
14 * IRIS Data Management Center
17 ***************************************************************************/
25 #include "unpackdata.h"
27 /* Function(s) internal to this file */
28 static int check_environment (int verbose
);
30 /* Header and data byte order flags controlled by environment variables */
31 /* -2 = not checked, -1 = checked but not set, or 0 = LE and 1 = BE */
32 flag unpackheaderbyteorder
= -2;
33 flag unpackdatabyteorder
= -2;
35 /* Data encoding format/fallback controlled by environment variable */
36 /* -2 = not checked, -1 = checked but not set, or = encoding */
37 int unpackencodingformat
= -2;
38 int unpackencodingfallback
= -2;
40 /* A pointer to the srcname of the record being unpacked */
41 char *UNPACK_SRCNAME
= NULL
;
44 /***************************************************************************
47 * Unpack a SEED data record header/blockettes and populate a MSRecord
48 * struct. All approriate fields are byteswapped, if needed, and
49 * pointers to structured data are setup in addition to setting the
50 * common header fields.
52 * If 'dataflag' is true the data samples are unpacked/decompressed
53 * and the MSRecord->datasamples pointer is set appropriately. The
54 * data samples will be either 32-bit integers, 32-bit floats or
55 * 64-bit floats (doubles) with the same byte order as the host
56 * machine. The MSRecord->numsamples will be set to the actual number
57 * of samples unpacked/decompressed and MSRecord->sampletype will
58 * indicated the sample type.
60 * All appropriate values will be byte-swapped to the host order,
61 * including the data samples.
63 * All header values, blockette values and data samples will be
64 * overwritten by subsequent calls to this function.
66 * If the msr struct is NULL it will be allocated.
68 * Returns MS_NOERROR and populates the MSRecord struct at *ppmsr on
69 * success, otherwise returns a libmseed error code (listed in
71 ***************************************************************************/
73 msr_unpack ( char *record
, int reclen
, MSRecord
**ppmsr
,
74 flag dataflag
, flag verbose
)
76 flag headerswapflag
= 0;
77 flag dataswapflag
= 0;
81 char sequence_number
[7];
84 /* For blockette parsing */
85 BlktLink
*blkt_link
= 0;
94 ms_log (2, "msr_unpack(): ppmsr argument cannot be NULL\n");
98 /* Verify that record includes a valid header */
99 if ( ! MS_ISVALIDHEADER(record
) )
101 ms_recsrcname (record
, srcname
, 1);
102 ms_log (2, "msr_unpack(%s) Record header & quality indicator unrecognized: '%c'\n", srcname
);
103 ms_log (2, "msr_unpack(%s) This is not a valid Mini-SEED record\n", srcname
);
108 /* Verify that passed record length is within supported range */
109 if ( reclen
< MINRECLEN
|| reclen
> MAXRECLEN
)
111 ms_recsrcname (record
, srcname
, 1);
112 ms_log (2, "msr_unpack(%s): Record length is out of range: %d\n", srcname
, reclen
);
113 return MS_OUTOFRANGE
;
116 /* Initialize the MSRecord */
117 if ( ! (*ppmsr
= msr_init (*ppmsr
)) )
120 /* Shortcut pointer, historical and help readability */
123 /* Set raw record pointer and record length */
124 msr
->record
= record
;
125 msr
->reclen
= reclen
;
127 /* Check environment variables if necessary */
128 if ( unpackheaderbyteorder
== -2 ||
129 unpackdatabyteorder
== -2 ||
130 unpackencodingformat
== -2 ||
131 unpackencodingfallback
== -2 )
132 if ( check_environment(verbose
) )
135 /* Allocate and copy fixed section of data header */
136 msr
->fsdh
= realloc (msr
->fsdh
, sizeof (struct fsdh_s
));
138 if ( msr
->fsdh
== NULL
)
140 ms_log (2, "msr_unpack(): Cannot allocate memory\n");
144 memcpy (msr
->fsdh
, record
, sizeof (struct fsdh_s
));
146 /* Check to see if byte swapping is needed by testing the year and day */
147 if ( ! MS_ISVALIDYEARDAY (msr
->fsdh
->start_time
.year
, msr
->fsdh
->start_time
.day
) )
148 headerswapflag
= dataswapflag
= 1;
150 /* Check if byte order is forced */
151 if ( unpackheaderbyteorder
>= 0 )
153 headerswapflag
= ( ms_bigendianhost() != unpackheaderbyteorder
) ? 1 : 0;
156 if ( unpackdatabyteorder
>= 0 )
158 dataswapflag
= ( ms_bigendianhost() != unpackdatabyteorder
) ? 1 : 0;
161 /* Swap byte order? */
162 if ( headerswapflag
)
164 MS_SWAPBTIME (&msr
->fsdh
->start_time
);
165 ms_gswap2a (&msr
->fsdh
->numsamples
);
166 ms_gswap2a (&msr
->fsdh
->samprate_fact
);
167 ms_gswap2a (&msr
->fsdh
->samprate_mult
);
168 ms_gswap4a (&msr
->fsdh
->time_correct
);
169 ms_gswap2a (&msr
->fsdh
->data_offset
);
170 ms_gswap2a (&msr
->fsdh
->blockette_offset
);
173 /* Populate some of the common header fields */
174 strncpy (sequence_number
, msr
->fsdh
->sequence_number
, 6);
175 sequence_number
[6] = '\0';
176 msr
->sequence_number
= (int32_t) strtol (sequence_number
, NULL
, 10);
177 msr
->dataquality
= msr
->fsdh
->dataquality
;
178 ms_strncpcleantail (msr
->network
, msr
->fsdh
->network
, 2);
179 ms_strncpcleantail (msr
->station
, msr
->fsdh
->station
, 5);
180 ms_strncpcleantail (msr
->location
, msr
->fsdh
->location
, 2);
181 ms_strncpcleantail (msr
->channel
, msr
->fsdh
->channel
, 3);
182 msr
->samplecnt
= msr
->fsdh
->numsamples
;
184 /* Generate source name for MSRecord */
185 if ( msr_srcname (msr
, srcname
, 1) == NULL
)
187 ms_log (2, "msr_unpack(): Cannot generate srcname\n");
191 /* Set shared srcname pointer to source name */
192 UNPACK_SRCNAME
= &srcname
[0];
194 /* Report byte swapping status */
197 if ( headerswapflag
)
198 ms_log (1, "%s: Byte swapping needed for unpacking of header\n",
201 ms_log (1, "%s: Byte swapping NOT needed for unpacking of header\n",
205 /* Traverse the blockettes */
206 blkt_offset
= msr
->fsdh
->blockette_offset
;
208 while ((blkt_offset
!= 0) &&
209 ((int)blkt_offset
< reclen
) &&
210 (blkt_offset
< MAXRECLEN
))
212 /* Every blockette has a similar 4 byte header: type and next */
213 memcpy (&blkt_type
, record
+ blkt_offset
, 2);
215 memcpy (&next_blkt
, record
+ blkt_offset
, 2);
218 if ( headerswapflag
)
220 ms_gswap2 (&blkt_type
);
221 ms_gswap2 (&next_blkt
);
224 /* Get blockette length */
225 blkt_length
= ms_blktlen (blkt_type
,
226 record
+ blkt_offset
- 4,
229 if ( blkt_length
== 0 )
231 ms_log (2, "msr_unpack(%s): Unknown blockette length for type %d\n",
232 UNPACK_SRCNAME
, blkt_type
);
236 /* Make sure blockette is contained within the msrecord buffer */
237 if ( (int)(blkt_offset
- 4 + blkt_length
) > reclen
)
239 ms_log (2, "msr_unpack(%s): Blockette %d extends beyond record size, truncated?\n",
240 UNPACK_SRCNAME
, blkt_type
);
244 if ( blkt_type
== 100 )
245 { /* Found a Blockette 100 */
246 struct blkt_100_s
*blkt_100
;
248 blkt_link
= msr_addblockette (msr
, record
+ blkt_offset
,
249 sizeof (struct blkt_100_s
),
254 blkt_link
->blktoffset
= blkt_offset
- 4;
255 blkt_link
->next_blkt
= next_blkt
;
257 blkt_100
= (struct blkt_100_s
*) blkt_link
->blktdata
;
259 if ( headerswapflag
)
261 ms_gswap4 (&blkt_100
->samprate
);
264 msr
->samprate
= msr
->Blkt100
->samprate
;
267 else if ( blkt_type
== 200 )
268 { /* Found a Blockette 200 */
269 struct blkt_200_s
*blkt_200
;
271 blkt_link
= msr_addblockette (msr
, record
+ blkt_offset
,
272 sizeof (struct blkt_200_s
),
277 blkt_link
->blktoffset
= blkt_offset
- 4;
278 blkt_link
->next_blkt
= next_blkt
;
280 blkt_200
= (struct blkt_200_s
*) blkt_link
->blktdata
;
282 if ( headerswapflag
)
284 ms_gswap4 (&blkt_200
->amplitude
);
285 ms_gswap4 (&blkt_200
->period
);
286 ms_gswap4 (&blkt_200
->background_estimate
);
287 MS_SWAPBTIME (&blkt_200
->time
);
291 else if ( blkt_type
== 201 )
292 { /* Found a Blockette 201 */
293 struct blkt_201_s
*blkt_201
;
295 blkt_link
= msr_addblockette (msr
, record
+ blkt_offset
,
296 sizeof (struct blkt_201_s
),
301 blkt_link
->blktoffset
= blkt_offset
- 4;
302 blkt_link
->next_blkt
= next_blkt
;
304 blkt_201
= (struct blkt_201_s
*) blkt_link
->blktdata
;
306 if ( headerswapflag
)
308 ms_gswap4 (&blkt_201
->amplitude
);
309 ms_gswap4 (&blkt_201
->period
);
310 ms_gswap4 (&blkt_201
->background_estimate
);
311 MS_SWAPBTIME (&blkt_201
->time
);
315 else if ( blkt_type
== 300 )
316 { /* Found a Blockette 300 */
317 struct blkt_300_s
*blkt_300
;
319 blkt_link
= msr_addblockette (msr
, record
+ blkt_offset
,
320 sizeof (struct blkt_300_s
),
325 blkt_link
->blktoffset
= blkt_offset
- 4;
326 blkt_link
->next_blkt
= next_blkt
;
328 blkt_300
= (struct blkt_300_s
*) blkt_link
->blktdata
;
330 if ( headerswapflag
)
332 MS_SWAPBTIME (&blkt_300
->time
);
333 ms_gswap4 (&blkt_300
->step_duration
);
334 ms_gswap4 (&blkt_300
->interval_duration
);
335 ms_gswap4 (&blkt_300
->amplitude
);
336 ms_gswap4 (&blkt_300
->reference_amplitude
);
340 else if ( blkt_type
== 310 )
341 { /* Found a Blockette 310 */
342 struct blkt_310_s
*blkt_310
;
344 blkt_link
= msr_addblockette (msr
, record
+ blkt_offset
,
345 sizeof (struct blkt_310_s
),
350 blkt_link
->blktoffset
= blkt_offset
- 4;
351 blkt_link
->next_blkt
= next_blkt
;
353 blkt_310
= (struct blkt_310_s
*) blkt_link
->blktdata
;
355 if ( headerswapflag
)
357 MS_SWAPBTIME (&blkt_310
->time
);
358 ms_gswap4 (&blkt_310
->duration
);
359 ms_gswap4 (&blkt_310
->period
);
360 ms_gswap4 (&blkt_310
->amplitude
);
361 ms_gswap4 (&blkt_310
->reference_amplitude
);
365 else if ( blkt_type
== 320 )
366 { /* Found a Blockette 320 */
367 struct blkt_320_s
*blkt_320
;
369 blkt_link
= msr_addblockette (msr
, record
+ blkt_offset
,
370 sizeof (struct blkt_320_s
),
375 blkt_link
->blktoffset
= blkt_offset
- 4;
376 blkt_link
->next_blkt
= next_blkt
;
378 blkt_320
= (struct blkt_320_s
*) blkt_link
->blktdata
;
380 if ( headerswapflag
)
382 MS_SWAPBTIME (&blkt_320
->time
);
383 ms_gswap4 (&blkt_320
->duration
);
384 ms_gswap4 (&blkt_320
->ptp_amplitude
);
385 ms_gswap4 (&blkt_320
->reference_amplitude
);
389 else if ( blkt_type
== 390 )
390 { /* Found a Blockette 390 */
391 struct blkt_390_s
*blkt_390
;
393 blkt_link
= msr_addblockette (msr
, record
+ blkt_offset
,
394 sizeof (struct blkt_390_s
),
399 blkt_link
->blktoffset
= blkt_offset
- 4;
400 blkt_link
->next_blkt
= next_blkt
;
402 blkt_390
= (struct blkt_390_s
*) blkt_link
->blktdata
;
404 if ( headerswapflag
)
406 MS_SWAPBTIME (&blkt_390
->time
);
407 ms_gswap4 (&blkt_390
->duration
);
408 ms_gswap4 (&blkt_390
->amplitude
);
412 else if ( blkt_type
== 395 )
413 { /* Found a Blockette 395 */
414 struct blkt_395_s
*blkt_395
;
416 blkt_link
= msr_addblockette (msr
, record
+ blkt_offset
,
417 sizeof (struct blkt_395_s
),
422 blkt_link
->blktoffset
= blkt_offset
- 4;
423 blkt_link
->next_blkt
= next_blkt
;
425 blkt_395
= (struct blkt_395_s
*) blkt_link
->blktdata
;
427 if ( headerswapflag
)
429 MS_SWAPBTIME (&blkt_395
->time
);
433 else if ( blkt_type
== 400 )
434 { /* Found a Blockette 400 */
435 struct blkt_400_s
*blkt_400
;
437 blkt_link
= msr_addblockette (msr
, record
+ blkt_offset
,
438 sizeof (struct blkt_400_s
),
443 blkt_link
->blktoffset
= blkt_offset
- 4;
444 blkt_link
->next_blkt
= next_blkt
;
446 blkt_400
= (struct blkt_400_s
*) blkt_link
->blktdata
;
448 if ( headerswapflag
)
450 ms_gswap4 (&blkt_400
->azimuth
);
451 ms_gswap4 (&blkt_400
->slowness
);
452 ms_gswap2 (&blkt_400
->configuration
);
456 else if ( blkt_type
== 405 )
457 { /* Found a Blockette 405 */
458 struct blkt_405_s
*blkt_405
;
460 blkt_link
= msr_addblockette (msr
, record
+ blkt_offset
,
461 sizeof (struct blkt_405_s
),
466 blkt_link
->blktoffset
= blkt_offset
- 4;
467 blkt_link
->next_blkt
= next_blkt
;
469 blkt_405
= (struct blkt_405_s
*) blkt_link
->blktdata
;
471 if ( headerswapflag
)
473 ms_gswap2 (&blkt_405
->delay_values
);
478 ms_log (1, "msr_unpack(%s): WARNING Blockette 405 cannot be fully supported\n",
483 else if ( blkt_type
== 500 )
484 { /* Found a Blockette 500 */
485 struct blkt_500_s
*blkt_500
;
487 blkt_link
= msr_addblockette (msr
, record
+ blkt_offset
,
488 sizeof (struct blkt_500_s
),
493 blkt_link
->blktoffset
= blkt_offset
- 4;
494 blkt_link
->next_blkt
= next_blkt
;
496 blkt_500
= (struct blkt_500_s
*) blkt_link
->blktdata
;
498 if ( headerswapflag
)
500 ms_gswap4 (&blkt_500
->vco_correction
);
501 MS_SWAPBTIME (&blkt_500
->time
);
502 ms_gswap4 (&blkt_500
->exception_count
);
506 else if ( blkt_type
== 1000 )
507 { /* Found a Blockette 1000 */
508 struct blkt_1000_s
*blkt_1000
;
510 blkt_link
= msr_addblockette (msr
, record
+ blkt_offset
,
511 sizeof (struct blkt_1000_s
),
516 blkt_link
->blktoffset
= blkt_offset
- 4;
517 blkt_link
->next_blkt
= next_blkt
;
519 blkt_1000
= (struct blkt_1000_s
*) blkt_link
->blktdata
;
521 /* Calculate record length in bytes as 2^(blkt_1000->reclen) */
522 msr
->reclen
= (uint32_t) 1 << blkt_1000
->reclen
;
524 /* Compare against the specified length */
525 if ( msr
->reclen
!= reclen
&& verbose
)
527 ms_log (2, "msr_unpack(%s): Record length in Blockette 1000 (%d) != specified length (%d)\n",
528 UNPACK_SRCNAME
, msr
->reclen
, reclen
);
531 msr
->encoding
= blkt_1000
->encoding
;
532 msr
->byteorder
= blkt_1000
->byteorder
;
535 else if ( blkt_type
== 1001 )
536 { /* Found a Blockette 1001 */
537 blkt_link
= msr_addblockette (msr
, record
+ blkt_offset
,
538 sizeof (struct blkt_1001_s
),
543 blkt_link
->blktoffset
= blkt_offset
- 4;
544 blkt_link
->next_blkt
= next_blkt
;
547 else if ( blkt_type
== 2000 )
548 { /* Found a Blockette 2000 */
549 struct blkt_2000_s
*blkt_2000
;
552 /* Read the blockette length from blockette */
553 memcpy (&b2klen
, record
+ blkt_offset
, 2);
554 if ( headerswapflag
) ms_gswap2 (&b2klen
);
556 /* Minus four bytes for the blockette type and next fields */
559 blkt_link
= msr_addblockette (msr
, record
+ blkt_offset
,
560 b2klen
, blkt_type
, 0);
564 blkt_link
->blktoffset
= blkt_offset
- 4;
565 blkt_link
->next_blkt
= next_blkt
;
567 blkt_2000
= (struct blkt_2000_s
*) blkt_link
->blktdata
;
569 if ( headerswapflag
)
571 ms_gswap2 (&blkt_2000
->length
);
572 ms_gswap2 (&blkt_2000
->data_offset
);
573 ms_gswap4 (&blkt_2000
->recnum
);
578 { /* Unknown blockette type */
579 if ( blkt_length
>= 4 )
581 blkt_link
= msr_addblockette (msr
, record
+ blkt_offset
,
588 blkt_link
->blktoffset
= blkt_offset
- 4;
589 blkt_link
->next_blkt
= next_blkt
;
593 /* Check that the next blockette offset is beyond the current blockette */
594 if ( next_blkt
&& next_blkt
< (blkt_offset
+ blkt_length
- 4) )
596 ms_log (2, "msr_unpack(%s): Offset to next blockette (%d) is within current blockette ending at byte %d\n",
597 UNPACK_SRCNAME
, next_blkt
, (blkt_offset
+ blkt_length
- 4));
601 /* Check that the offset is within record length */
602 else if ( next_blkt
&& next_blkt
> reclen
)
604 ms_log (2, "msr_unpack(%s): Offset to next blockette (%d) from type %d is beyond record length\n",
605 UNPACK_SRCNAME
, next_blkt
, blkt_type
);
611 blkt_offset
= next_blkt
;
615 } /* End of while looping through blockettes */
617 /* Check for a Blockette 1000 */
618 if ( msr
->Blkt1000
== 0 )
622 ms_log (1, "%s: Warning: No Blockette 1000 found\n", UNPACK_SRCNAME
);
626 /* Check that the data offset is after the blockette chain */
627 if ( blkt_link
&& msr
->fsdh
->numsamples
&& msr
->fsdh
->data_offset
< (blkt_link
->blktoffset
+ blkt_link
->blktdatalen
+ 4) )
629 ms_log (1, "%s: Warning: Data offset in fixed header (%d) is within the blockette chain ending at %d\n",
630 UNPACK_SRCNAME
, msr
->fsdh
->data_offset
, (blkt_link
->blktoffset
+ blkt_link
->blktdatalen
+ 4));
633 /* Check that the blockette count matches the number parsed */
634 if ( msr
->fsdh
->numblockettes
!= blkt_count
)
636 ms_log (1, "%s: Warning: Number of blockettes in fixed header (%d) does not match the number parsed (%d)\n",
637 UNPACK_SRCNAME
, msr
->fsdh
->numblockettes
, blkt_count
);
640 /* Populate remaining common header fields */
641 msr
->starttime
= msr_starttime (msr
);
642 msr
->samprate
= msr_samprate (msr
);
644 /* Set MSRecord->byteorder if data byte order is forced */
645 if ( unpackdatabyteorder
>= 0 )
647 msr
->byteorder
= unpackdatabyteorder
;
650 /* Check if encoding format is forced */
651 if ( unpackencodingformat
>= 0 )
653 msr
->encoding
= unpackencodingformat
;
656 /* Use encoding format fallback if defined and no encoding is set,
657 * also make sure the byteorder is set by default to big endian */
658 if ( unpackencodingfallback
>= 0 && msr
->encoding
== -1 )
660 msr
->encoding
= unpackencodingfallback
;
662 if ( msr
->byteorder
== -1 )
668 /* Unpack the data samples if requested */
669 if ( dataflag
&& msr
->samplecnt
> 0 )
671 flag dswapflag
= headerswapflag
;
672 flag bigendianhost
= ms_bigendianhost();
674 /* Determine byte order of the data and set the dswapflag as
675 needed; if no Blkt1000 or UNPACK_DATA_BYTEORDER environment
676 variable setting assume the order is the same as the header */
677 if ( msr
->Blkt1000
!= 0 && unpackdatabyteorder
< 0 )
681 /* If BE host and LE data need swapping */
682 if ( bigendianhost
&& msr
->byteorder
== 0 )
684 /* If LE host and BE data (or bad byte order value) need swapping */
685 else if ( !bigendianhost
&& msr
->byteorder
> 0 )
688 else if ( unpackdatabyteorder
>= 0 )
690 dswapflag
= dataswapflag
;
693 if ( verbose
> 2 && dswapflag
)
694 ms_log (1, "%s: Byte swapping needed for unpacking of data samples\n",
696 else if ( verbose
> 2 )
697 ms_log (1, "%s: Byte swapping NOT needed for unpacking of data samples \n",
700 retval
= msr_unpack_data (msr
, dswapflag
, verbose
);
705 msr
->numsamples
= retval
;
709 if ( msr
->datasamples
)
710 free (msr
->datasamples
);
712 msr
->datasamples
= 0;
716 /* Unset shared pointer to source name */
717 UNPACK_SRCNAME
= NULL
;
720 } /* End of msr_unpack() */
723 /************************************************************************
726 * Unpack Mini-SEED data samples for a given MSRecord. The packed
727 * data is accessed in the record indicated by MSRecord->record and
728 * the unpacked samples are placed in MSRecord->datasamples. The
729 * resulting data samples are either 32-bit integers, 32-bit floats
730 * or 64-bit floats in host byte order.
732 * Return number of samples unpacked or negative libmseed error code.
733 ************************************************************************/
735 msr_unpack_data ( MSRecord
*msr
, int swapflag
, flag verbose
)
737 int datasize
; /* byte size of data samples in record */
738 int nsamples
; /* number of samples unpacked */
739 int unpacksize
; /* byte size of unpacked samples */
740 int samplesize
= 0; /* size of the data samples in bytes */
745 /* Sanity record length */
746 if ( msr
->reclen
== -1 )
748 ms_log (2, "msr_unpack_data(%s): Record size unknown\n",
752 else if ( msr
->reclen
< MINRECLEN
|| msr
->reclen
> MAXRECLEN
)
754 ms_log (2, "msr_unpack_data(%s): Unsupported record length: %d\n",
755 UNPACK_SRCNAME
, msr
->reclen
);
756 return MS_OUTOFRANGE
;
759 /* Sanity check data offset before creating a pointer based on the value */
760 if ( msr
->fsdh
->data_offset
< 48 || msr
->fsdh
->data_offset
>= msr
->reclen
)
762 ms_log (2, "msr_unpack_data(%s): data offset value is not valid: %d\n",
763 UNPACK_SRCNAME
, msr
->fsdh
->data_offset
);
767 datasize
= msr
->reclen
- msr
->fsdh
->data_offset
;
768 dbuf
= msr
->record
+ msr
->fsdh
->data_offset
;
770 switch (msr
->encoding
)
773 samplesize
= 1; break;
785 samplesize
= 4; break;
787 samplesize
= 8; break;
789 samplesize
= 0; break;
792 /* Calculate buffer size needed for unpacked samples */
793 unpacksize
= (int) msr
->samplecnt
* samplesize
;
795 /* (Re)Allocate space for the unpacked data */
796 if ( unpacksize
> 0 )
798 msr
->datasamples
= realloc (msr
->datasamples
, unpacksize
);
800 if ( msr
->datasamples
== NULL
)
802 ms_log (2, "msr_unpack_data(%s): Cannot (re)allocate memory\n",
809 if ( msr
->datasamples
)
810 free (msr
->datasamples
);
811 msr
->datasamples
= 0;
816 ms_log (1, "%s: Unpacking %"PRId64
" samples\n",
817 UNPACK_SRCNAME
, msr
->samplecnt
);
819 /* Decide if this is a encoding that we can decode */
820 switch (msr
->encoding
)
825 ms_log (1, "%s: Found ASCII data\n", UNPACK_SRCNAME
);
827 nsamples
= (int)msr
->samplecnt
;
828 memcpy (msr
->datasamples
, dbuf
, nsamples
);
829 msr
->sampletype
= 'a';
834 ms_log (1, "%s: Unpacking INT-16 data samples\n", UNPACK_SRCNAME
);
836 nsamples
= msr_unpack_int_16 ((int16_t *)dbuf
, (int)msr
->samplecnt
,
837 (int)msr
->samplecnt
, msr
->datasamples
,
839 msr
->sampletype
= 'i';
844 ms_log (1, "%s: Unpacking INT-32 data samples\n", UNPACK_SRCNAME
);
846 nsamples
= msr_unpack_int_32 ((int32_t *)dbuf
, (int)msr
->samplecnt
,
847 (int)msr
->samplecnt
, msr
->datasamples
,
849 msr
->sampletype
= 'i';
854 ms_log (1, "%s: Unpacking FLOAT-32 data samples\n", UNPACK_SRCNAME
);
856 nsamples
= msr_unpack_float_32 ((float *)dbuf
, (int)msr
->samplecnt
,
857 (int)msr
->samplecnt
, msr
->datasamples
,
859 msr
->sampletype
= 'f';
864 ms_log (1, "%s: Unpacking FLOAT-64 data samples\n", UNPACK_SRCNAME
);
866 nsamples
= msr_unpack_float_64 ((double *)dbuf
, (int)msr
->samplecnt
,
867 (int)msr
->samplecnt
, msr
->datasamples
,
869 msr
->sampletype
= 'd';
873 diffbuff
= (int32_t *) malloc(unpacksize
);
874 if ( diffbuff
== NULL
)
876 ms_log (2, "msr_unpack_data(%s): Cannot allocate diff buffer\n",
882 ms_log (1, "%s: Unpacking Steim-1 data frames\n", UNPACK_SRCNAME
);
884 nsamples
= msr_unpack_steim1 ((FRAME
*)dbuf
, datasize
, (int)msr
->samplecnt
,
885 (int)msr
->samplecnt
, msr
->datasamples
, diffbuff
,
886 &x0
, &xn
, swapflag
, verbose
);
887 msr
->sampletype
= 'i';
892 diffbuff
= (int32_t *) malloc(unpacksize
);
893 if ( diffbuff
== NULL
)
895 ms_log (2, "msr_unpack_data(%s): Cannot allocate diff buffer\n",
901 ms_log (1, "%s: Unpacking Steim-2 data frames\n", UNPACK_SRCNAME
);
903 nsamples
= msr_unpack_steim2 ((FRAME
*)dbuf
, datasize
, (int)msr
->samplecnt
,
904 (int)msr
->samplecnt
, msr
->datasamples
, diffbuff
,
905 &x0
, &xn
, swapflag
, verbose
);
906 msr
->sampletype
= 'i';
915 if ( msr
->encoding
== DE_GEOSCOPE24
)
916 ms_log (1, "%s: Unpacking GEOSCOPE 24bit integer data samples\n",
918 if ( msr
->encoding
== DE_GEOSCOPE163
)
919 ms_log (1, "%s: Unpacking GEOSCOPE 16bit gain ranged/3bit exponent data samples\n",
921 if ( msr
->encoding
== DE_GEOSCOPE164
)
922 ms_log (1, "%s: Unpacking GEOSCOPE 16bit gain ranged/4bit exponent data samples\n",
926 nsamples
= msr_unpack_geoscope (dbuf
, (int)msr
->samplecnt
, (int)msr
->samplecnt
,
927 msr
->datasamples
, msr
->encoding
, swapflag
);
928 msr
->sampletype
= 'f';
933 ms_log (1, "%s: Unpacking CDSN encoded data samples\n", UNPACK_SRCNAME
);
935 nsamples
= msr_unpack_cdsn ((int16_t *)dbuf
, (int)msr
->samplecnt
, (int)msr
->samplecnt
,
936 msr
->datasamples
, swapflag
);
937 msr
->sampletype
= 'i';
942 ms_log (1, "%s: Unpacking SRO encoded data samples\n", UNPACK_SRCNAME
);
944 nsamples
= msr_unpack_sro ((int16_t *)dbuf
, (int)msr
->samplecnt
, (int)msr
->samplecnt
,
945 msr
->datasamples
, swapflag
);
946 msr
->sampletype
= 'i';
951 ms_log (1, "%s: Unpacking DWWSSN encoded data samples\n", UNPACK_SRCNAME
);
953 nsamples
= msr_unpack_dwwssn ((int16_t *)dbuf
, (int)msr
->samplecnt
, (int)msr
->samplecnt
,
954 msr
->datasamples
, swapflag
);
955 msr
->sampletype
= 'i';
959 ms_log (2, "%s: Unsupported encoding format %d (%s)\n",
960 UNPACK_SRCNAME
, msr
->encoding
, (char *) ms_encodingstr(msr
->encoding
));
962 return MS_UNKNOWNFORMAT
;
966 } /* End of msr_unpack_data() */
969 /************************************************************************
972 * Check environment variables and set global variables appropriately.
974 * Return 0 on success and -1 on error.
975 ************************************************************************/
977 check_environment (int verbose
)
981 /* Read possible environmental variables that force byteorder */
982 if ( unpackheaderbyteorder
== -2 )
984 if ( (envvariable
= getenv("UNPACK_HEADER_BYTEORDER")) )
986 if ( *envvariable
!= '0' && *envvariable
!= '1' )
988 ms_log (2, "Environment variable UNPACK_HEADER_BYTEORDER must be set to '0' or '1'\n");
991 else if ( *envvariable
== '0' )
993 unpackheaderbyteorder
= 0;
995 ms_log (1, "UNPACK_HEADER_BYTEORDER=0, unpacking little-endian header\n");
999 unpackheaderbyteorder
= 1;
1001 ms_log (1, "UNPACK_HEADER_BYTEORDER=1, unpacking big-endian header\n");
1006 unpackheaderbyteorder
= -1;
1010 if ( unpackdatabyteorder
== -2 )
1012 if ( (envvariable
= getenv("UNPACK_DATA_BYTEORDER")) )
1014 if ( *envvariable
!= '0' && *envvariable
!= '1' )
1016 ms_log (2, "Environment variable UNPACK_DATA_BYTEORDER must be set to '0' or '1'\n");
1019 else if ( *envvariable
== '0' )
1021 unpackdatabyteorder
= 0;
1023 ms_log (1, "UNPACK_DATA_BYTEORDER=0, unpacking little-endian data samples\n");
1027 unpackdatabyteorder
= 1;
1029 ms_log (1, "UNPACK_DATA_BYTEORDER=1, unpacking big-endian data samples\n");
1034 unpackdatabyteorder
= -1;
1038 /* Read possible environmental variable that forces encoding format */
1039 if ( unpackencodingformat
== -2 )
1041 if ( (envvariable
= getenv("UNPACK_DATA_FORMAT")) )
1043 unpackencodingformat
= (int) strtol (envvariable
, NULL
, 10);
1045 if ( unpackencodingformat
< 0 || unpackencodingformat
> 33 )
1047 ms_log (2, "Environment variable UNPACK_DATA_FORMAT set to invalid value: '%d'\n", unpackencodingformat
);
1050 else if ( verbose
> 2 )
1051 ms_log (1, "UNPACK_DATA_FORMAT, unpacking data in encoding format %d\n", unpackencodingformat
);
1055 unpackencodingformat
= -1;
1059 /* Read possible environmental variable to be used as a fallback encoding format */
1060 if ( unpackencodingfallback
== -2 )
1062 if ( (envvariable
= getenv("UNPACK_DATA_FORMAT_FALLBACK")) )
1064 unpackencodingfallback
= (int) strtol (envvariable
, NULL
, 10);
1066 if ( unpackencodingfallback
< 0 || unpackencodingfallback
> 33 )
1068 ms_log (2, "Environment variable UNPACK_DATA_FORMAT_FALLBACK set to invalid value: '%d'\n",
1069 unpackencodingfallback
);
1072 else if ( verbose
> 2 )
1073 ms_log (1, "UNPACK_DATA_FORMAT_FALLBACK, fallback data unpacking encoding format %d\n",
1074 unpackencodingfallback
);
1078 unpackencodingfallback
= 10; /* Default fallback is Steim-1 encoding */
1083 } /* End of check_environment() */