/*-------------- Telecommunications & Signal Processing Lab --------------- Routine: AFILE *AFgetESpar (FILE *fp, const char Fname[], long int *Nsamp, long int *Nchan, float *Sfreq, FILE *fpout) Purpose: Get file format information from an ESPS sampled data feature file Description: This routine reads the header for an ESPS sampled data feature file. The header information is used to set the file data format information in the audio file pointer structure and to set the returned argument values. A banner identifying the audio file and its parameters is printed. ESPS sampled data feature file header: Offset Length Type Contents 8 4 -- Header size (bytes) 12 4 int Sampled data record size 16 4 int File identifier 40 26 char File creation date 124 4 int Number of samples (may indicate zero) 132 4 int Number of doubles in a data record 136 4 int Number of floats in a data record 140 4 int Number of longs in a data record 144 4 int Number of shorts in a data record 148 4 int Number of chars in a data record 160 8 char User name 333 ... -- Generic header items, including "record_freq" - ... -- Audio data 16-bit integer and 32-bit floating-point data formats are supported. Parameters: <- AFILE *AFgetESpar Audio file pointer for the audio file -> FILE *fp File pointer for the file -> const char Fname[] File name <- long int *Nsamp Total number of samples in the file (all channels) <- long int *Nchan Number of channels <- float *Sfreq Sampling frequency from the file header -> FILE *fpout File pointer for printing the audio file identification information. If fpout is NULL, no information is printed. Author / revision: P. Kabal Copyright (C) 1996 $Revision: 1.41 $ $Date: 1996/08/14 17:55:55 $ -------------------------------------------------------------------------*/ static char rcsid [] = "$Id: AFgetESpar.c 1.41 1996/08/14 AFsp-V2R1 $"; #include #include #include #include #include #include #include #define MINV(a, b) (((a) < (b)) ? (a) : (b)) #define RHEAD_SN(fp,offs,string,N) \ AFreadHead (fp, (long int) (offs), (void *) (string), \ 1, N, DS_NATIVE) #define RHEAD_S(fp,offs,string) \ AFreadHead (fp, (long int) (offs), (void *) (string), \ 1, sizeof (string), DS_NATIVE) #define RHEAD_V(fp,offs,value,swap) \ AFreadHead (fp, (long int) (offs), (void *) &(value), \ sizeof (value), 1, swap) #define SAME_CSTR(str,ref) (memcmp (str, ref, sizeof (str)) == 0) AFILE * AFgetESpar (fp, Fname, Nsamp, Nchan, Sfreq, fpout) FILE *fp; const char Fname[]; long int *Nsamp; long int *Nchan; float *Sfreq; FILE *fpout; { struct ES_preamb Fpreamb; struct ES_head Fhead; AFILE *AFp; int Lw, Format, Fbo; long int Nbytes, Nsampx, offs, Nchanx, Ldata; int Ninfo; char Cinfo[ES_MAXINFO+1]; char *p; double8_t FSfreq; /* Get the size of the file */ Nbytes = FLfileSize (fp); if (Nbytes < ES_LHMIN) UThalt ("AFgetESpar: ESPS file header too short"); /* Check the preamble file magic */ RHEAD_S (fp, 16L, Fpreamb.Magic); if (SAME_CSTR (Fpreamb.Magic, FM_ESPS)) Fbo = DS_EB; else if (SAME_CSTR (Fpreamb.Magic, FM_ESPS_SWAPPED)) Fbo = DS_EL; else UThalt ("AFgetESpar: Invalid ESPS file identifier"); /* Read selected preamble values */ offs = 8L; offs += RHEAD_V (fp, offs, Fpreamb.Data_offset, Fbo); RHEAD_V (fp, offs, Fpreamb.Record_size, Fbo); /* Read selected header values */ offs = 32L; offs += RHEAD_V (fp, offs, Fhead.Type, Fbo); offs += 2; offs += RHEAD_S (fp, offs, Fhead.Magic); offs += RHEAD_S (fp, offs, Fhead.Datetime); offs += 58; offs += RHEAD_V (fp, offs, Fhead.Ndrec, Fbo); offs += 8; offs += RHEAD_V (fp, offs, Fhead.Nfloat, Fbo); offs += 4; offs += RHEAD_V (fp, offs, Fhead.Nshort, Fbo); offs += RHEAD_V (fp, offs, Fhead.Nchar, Fbo); if (Fhead.Type != ES_FTYPE) UThalt ("AFgetESpar: Unsupported ESPS file type"); if (! SAME_CSTR (Fhead.Magic, Fpreamb.Magic)) UThalt ("AFgetESpar: ESPS file identifier values do not match"); /* Get the data format */ if (Fhead.Nshort != 0) { Lw = FDL_INT16; Nchanx = Fhead.Nshort; Format = FD_INT16; } else if (Fhead.Nfloat != 0) { Lw = FDL_FLOAT32; Nchanx = Fhead.Nfloat; Format = FD_FLOAT32; } else UThalt ("AFgetESpar: Unsupported ESPS file data format"); if (Fpreamb.Record_size != Lw * Nchanx) UThalt ("AFgetESpar: Unsupported ESPS file data encoding"); /* Warnings, error checks */ if (Fpreamb.Data_offset < ES_LHMIN || Fpreamb.Data_offset > Nbytes) UThalt ("AFgetESpar: Invalid data offset value"); if (Fhead.Ndrec > 0) Ldata = Fhead.Ndrec * Lw * Nchanx; else Ldata = Nbytes - Fpreamb.Data_offset; if (Ldata > Nbytes - Fpreamb.Data_offset) UThalt ("AFgetESpar: Invalid header data length field"); if (Ldata != Nbytes - Fpreamb.Data_offset) UTwarn ("AFgetESpar - Invalid header data length field"); /* Get the sampling frequency from the "record_freq" record */ Ninfo = MINV (ES_MAXINFO, Fpreamb.Data_offset - ES_LHMIN); RHEAD_SN (fp, ES_LHMIN, Cinfo, Ninfo); p = STstrstrNM (Cinfo, "record_freq", Ninfo, 12); if (p != NULL) { offs = ES_LHMIN + (p - Cinfo) - 4; /* Beginning of record */ RHEAD_V (fp, offs + 22L, FSfreq, Fbo); } else { UThalt ("AFgetESpar: Unable to determine sampling frequency"); } /* Set the parameters for file access */ Nsampx = Ldata / Lw; AFp = AFsetAFp (fp, FO_RO, FT_ESPS, Format, Fbo, 1.0, Nchanx, (long int) Fpreamb.Data_offset, Ldata, Nsampx); /* Check and print the header information */ AFprintAFh (AFp, Fname, Fhead.Datetime, FSfreq, fpout); /* Set the return parameters */ *Nsamp = Nsampx; *Nchan = Nchanx; *Sfreq = FSfreq; return AFp; }