/*-------------- Telecommunications & Signal Processing Lab --------------- McGill University Routine: int AFfileType (FILE *fp) Purpose: Identify the format of an audio file Description: This routine determines the format for an audio file. This routine checks the header of the file to identify the type of file. This check for most file types consists of a check for a file magic value in a known location in the header of the file. If the file has a header which is recognized, the file is declared to be a file of the corresponding type. The routine AFsetNH can be used to control the behaviour of this routine for audio files which do not have a header (raw audio files) or which have non-standard headers. AFsetNH allows for three ways of handling such files. 1: Files can be unconditionally accepted without checking the header 2: Files are accepted as "headerless", but only after checking the header against the standard file formats 3: Unrecognized files are not accepted Parameters: <- int AFfileType Integer code specifying the type of file, FT_UNKNOWN = 0, unknown audio file format FT_NH = 1, headerless (non-standard or no header) audio file FT_AFSP = 2, AFsp audio file FT_SUN = 3, Sun audio file FT_WAVE = 4, RIFF WAVE file FT_AIFF_C = 5, AIFF-C audio file FT_SPHERE = 6, NIST SPHERE audio file FT_ESPS = 7, ESPS sampled data feature file FT_SF = 8, IRCAM soundfile FT_SPPACK = 9, SPPACK file FT_INRS = 10, INRS-Telecom audio file FT_AIFF = 11, AIFF audio file FT_TXAUD = 12, Text audio file -> FILE *fp File pointer associated with the audio file Author / revision: P. Kabal Copyright (C) 1996 $Revision: 1.43 $ $Date: 1996/08/19 13:38:07 $ -------------------------------------------------------------------------*/ static char rcsid[] = "$Id: AFfileType.c 1.43 1996/08/19 AFsp-V2R1 $"; #include #include #include #include /* File magic values in file byte order */ #define FM_SUN "\056\163\156\144" /* ".snd" */ # define FM_AFSP "\101\106\163\160" /* "AFsp" */ #define FM_RIFF "\122\111\106\106" /* "RIFF" */ # define FM_WAVE "\127\101\126\105" /* "WAVE" */ #define FM_IFF "\106\117\122\115" /* "FORM" */ # define FM_AIFF "\101\111\106\106" /* "AIFF" */ # define FM_AIFF_C "\101\111\106\103" /* "AIFC" */ #define FM_SPHERE "\116\111\123\124\137\061\101\012" /* "NIST_1A\n" */ #define FM_ESPS "\0\0\152\32" #define FM_ESPS_SWAPPED "\32\152\0\0" #define FM_SF_VAX_L "\144\243\001\0" /* VAX - native */ #define FM_SF_VAX_B "\0\001\243\144" /* VAX - byte reversed */ #define FM_SF_SUN "\144\243\002\0" /* big-endian */ #define FM_SF_MIPS_L "\144\243\003\0" /* big-endian */ #define FM_SF_MIPS_B "\0\003\243\144" /* little-endian */ #define FM_SF_NEXT "\144\243\004\0" /* big-endian */ #define FM_SPPACK "\100\303" #define FM_TXAUD "\045\057\057" /* "%//" */ /* Common sampling frequencies (VAX floating-point values) in file byte order. The sampling frequencies recognized are 6500, 20000/3, 8000, 10000, 12000, 16000, and 20000 Hz. */ #define NINRS 7 static const char *FM_INRS[NINRS] = { "\313\106\0\040", "\320\106\125\125", "\372\106\0\0", "\034\107\0\100", "\073\107\0\200", "\172\107\0\0", "\234\107\0\100" }; /* Offset to the file magic */ #define MOFFS_SUN 0 # define MOFFS_AFSP 24 #define MOFFS_RIFF 0 # define MOFFS_WAVE 8 #define MOFFS_IFF 0 # define MOFFS_AIFF 8 # define MOFFS_AIFF_C MOFF_AIFF #define MOFFS_SPHERE 0 #define MOFFS_ESPS 16 #define MOFFS_SF 0 #define MOFFS_SPPACK 252 #define MOFFS_INRS 0 #define MOFFS_TXAUD 0 /* Size of the file magic */ #define MSIZE_SUN (sizeof (FM_SUN) - 1) # define MSIZE_AFSP (sizeof (FM_AFSP) - 1) #define MSIZE_RIFF (sizeof (FM_RIFF) - 1) # define MSIZE_WAVE (sizeof (FM_WAVE) - 1) #define MSIZE_SPHERE (sizeof (FM_SPHERE) - 1) #define MSIZE_SF (sizeof (FM_SF_SUN) - 1) #define MSIZE_ESPS (sizeof (FM_ESPS) - 1) #define MSIZE_SPPACK (sizeof (FM_SPPACK) - 1) #define MSIZE_INRS (sizeof (FM_INRS[0]) - 1) #define MSIZE_IFF (sizeof (FM_IFF) - 1) # define MSIZE_AIFF (sizeof (FM_AIFF) - 1) # define MSIZE_AIFF_C (sizeof (FM_AIFF_C) - 1) #define MSIZE_TXAUD (sizeof (FM_TXAUD) - 1) /* Minimum header lengths */ #define LHMIN_SUN 24 # define LHMIN_AFSP (LHMIN_SUN + 4) #define LHMIN_RIFF 16 # define LHMIN_WAVE 44 #define LHMIN_SPHERE 1024 #define LHMIN_SF 1024 #define LHMIN_ESPS 333 #define LHMIN_SPPACK 512 #define LHMIN_INRS 512 #define LHMIN_IFF 16 # define LHMIN_AIFF 54 # define LHMIN_AIFF_C 72 #define LHMIN_TXAUD 21 #define RHEAD_SN(fp,offs,string,N) \ AFreadHead (fp, (long int) (offs), (void *) string, \ 1, (int) (N), DS_NATIVE) #define ID_CSTR(str,ref,len) (memcmp (str, ref, (size_t) len) == 0) int AFfileType (fp) FILE *fp; { char Magic[8]; /* Longest Magic is 8 bytes */ long int Nbytes; int i; struct AF_NHpar *Fdef; /* Check for a forced headerless file */ Fdef = AFgetNH (); if (Fdef->Accept == NH_FORCE) return FT_NH; /* Get the file size */ Nbytes = FLfileSize (fp); /* Check for an AFsp or Sun audio file */ if (Nbytes >= LHMIN_SUN) { RHEAD_SN (fp, MOFFS_SUN, Magic, MSIZE_SUN); if (ID_CSTR (Magic, FM_SUN, MSIZE_SUN)) { if (Nbytes >= LHMIN_AFSP) { RHEAD_SN (fp, MOFFS_AFSP, Magic, MSIZE_AFSP); if (ID_CSTR (Magic, FM_AFSP, MSIZE_AFSP)) return FT_AFSP; } return FT_SUN; } } /* Check for a RIFF WAVE file */ if (Nbytes >= LHMIN_RIFF) { RHEAD_SN (fp, MOFFS_RIFF, Magic, MSIZE_RIFF); if (ID_CSTR (Magic, FM_RIFF, MSIZE_RIFF) && Nbytes > LHMIN_WAVE) { RHEAD_SN (fp, MOFFS_WAVE, Magic, MSIZE_WAVE); if (ID_CSTR (Magic, FM_WAVE, MSIZE_WAVE)) return FT_WAVE; } } /* Check for an AIFF or AIFF-C file */ if (Nbytes >= LHMIN_AIFF) { RHEAD_SN (fp, MOFFS_IFF, Magic, MSIZE_IFF); if (ID_CSTR (Magic, FM_IFF, MSIZE_IFF)) { RHEAD_SN (fp, MOFFS_AIFF, Magic, MSIZE_AIFF); if (ID_CSTR (Magic, FM_AIFF, MSIZE_AIFF)) return FT_AIFF; else if (ID_CSTR (Magic, FM_AIFF_C, MSIZE_AIFF_C)) return FT_AIFF_C; } } /* Check for an NIST SPHERE audio file */ if (Nbytes >= LHMIN_SPHERE) { RHEAD_SN (fp, MOFFS_SPHERE, Magic, MSIZE_SPHERE); if (ID_CSTR (Magic, FM_SPHERE, MSIZE_SPHERE)) return FT_SPHERE; } /* Check for an ESPS sampled data feature file */ /* ESPS files can be written in either byte order */ if (Nbytes >= LHMIN_ESPS) { RHEAD_SN (fp, MOFFS_ESPS, Magic, MSIZE_ESPS); if (ID_CSTR (Magic, FM_ESPS, MSIZE_ESPS) || ID_CSTR (Magic, FM_ESPS_SWAPPED, MSIZE_ESPS)) return FT_ESPS; } /* Check for an IRCAM soundfile */ if (Nbytes >= LHMIN_SF) { RHEAD_SN (fp, MOFFS_SF, Magic, MSIZE_SF); if (ID_CSTR (Magic, FM_SF_VAX_L, MSIZE_SF) || ID_CSTR (Magic, FM_SF_VAX_B, MSIZE_SF) || ID_CSTR (Magic, FM_SF_SUN, MSIZE_SF) || ID_CSTR (Magic, FM_SF_MIPS_L, MSIZE_SF) || ID_CSTR (Magic, FM_SF_MIPS_B, MSIZE_SF) || ID_CSTR (Magic, FM_SF_NEXT, MSIZE_SF)) return FT_SF; } /* Check for an SPPACK file */ if (Nbytes >= LHMIN_SPPACK) { RHEAD_SN (fp, MOFFS_SPPACK, Magic, MSIZE_SPPACK); if (ID_CSTR (Magic, FM_SPPACK, MSIZE_SPPACK)) return FT_SPPACK; } /* Check for an INRS-Telecommunications audio file */ if (Nbytes >= LHMIN_INRS) { RHEAD_SN (fp, MOFFS_INRS, Magic, MSIZE_INRS); for (i = 0; i < NINRS; i++) { if (ID_CSTR (Magic, FM_INRS[i], MSIZE_INRS)) return FT_INRS; } } /* Check for a text audio file */ if (Nbytes >= LHMIN_TXAUD) { RHEAD_SN (fp, MOFFS_TXAUD, Magic, MSIZE_TXAUD); if (ID_CSTR (Magic, FM_TXAUD, MSIZE_TXAUD)) return FT_TXAUD; } /* Check if a headerless (non-standard) file should be accepted */ if (Fdef->Accept == NH_ACCEPT) return FT_NH; /* No match, declare it an unknown file type */ return FT_UNKNOWN; }