/*-------------- Telecommunications & Signal Processing Lab --------------- McGill University Routine: AFILE *AFsetAUpar (const char Fname[], int Format, long int Nchan, double Sfreq, FILE *fpout) Purpose: Write header information to an AFsp (Sun) audio file Description: This routine writes header information to an AFsp (Sun) format audio file. The file is assumed to have been opened with routine AFopenWrite. Optionally, the file header information is printed. The dditional header information returned by AFgenHinfo is written as part of the file header. AFsp (Sun) audio file header: Bytes Type Contents 0 -> 3 int File identifier 4 -> 7 int Header size H (bytes) 8 -> 11 int Audio data length (bytes) 12 -> 15 int Data encoding format 16 -> 19 int Sample rate (samples per second) 20 -> 23 int Number of interleaved channels 24 -> 27 int AFsp identifier ("AFsp)") 28 -> H-1 -- Additional header information 8-bit mu-law, 8-bit A-law, 8-bit integer, 16-bit integer, and 32-bit IEEE floating-point data formats are supported. Parameters: <- AFILE AFsetAUpar Audio file pointer for the audio file -> const char Fname[] File name -> int Format Audio file data format code, FD_MULAW8 = 1, mu-law 8-bit data FD_ALAW8 = 2, A-law 8-bit data FD_INT8 = 4, two's-complement 8-bit integer data FD_INT16 = 5, two's-complement 16-bit integer data FD_FLOAT32 = 6, 32-bit IEEE floating-point data -> long int Nchan Number of channels -> double Sfreq Sampling frequency -> FILE *fpout File pointer for printing audio file information. If fpout is not NULL, information about the audio file is printed on the stream selected by fpout. Author / revision: P. Kabal Copyright (C) 1996 $Revision: 1.41 $ $Date: 1996/08/14 18:06:23 $ -------------------------------------------------------------------------*/ static char rcsid [] = "$Id: AFsetAUpar.c 1.41 1996/08/14 AFsp-V2R1 $"; #include #include #include #include #include #include #define ICEILV(n, m) (((n) + ((m) - 1)) / (m)) /* int n,m >= 0 */ #define WHEAD_SN(fp,offs,string,N) \ AFwriteHead (fp, (long int) (offs), \ (void *) (string), \ 1, (int) (N), DS_NATIVE) #define WHEAD_S(fp,offs,string) \ AFwriteHead (fp, (long int) (offs), \ (void *) (string), \ 1, sizeof (string), DS_NATIVE) #define WHEAD_V(fp,offs,value,swap) \ AFwriteHead (fp, (long int) (offs), \ (void *) &(value), \ sizeof (value), 1, swap) #define MCOPY(src,dest) memcpy ((void *) (dest), (void *) (src), \ sizeof (dest)) #define ALIGN 4 /* Header length is a multiple of ALIGN */ static const char Nullpad[ALIGN-1] = {'\0'}; /* ALIGN-1 nulls */ AFILE * AFsetAUpar (Fname, Format, Nchan, Sfreq, fpout) const char Fname[]; int Format; long int Nchan; double Sfreq; FILE *fpout; { struct AU_head Fhead; FILE *fp; AFILE *AFp; int Lhead, Dencod, Ninfo; long int offs; double ScaleF; char *h; /* Set up the encoding parameters */ switch (Format) { case FD_MULAW8: Dencod = AU_MULAW8; ScaleF = 1.; break; case FD_ALAW8: Dencod = AU_ALAW8; ScaleF = 1.; break; case FD_INT8: Dencod = AU_LIN8; ScaleF = 1./128.; break; case FD_INT16: Dencod = AU_LIN16; ScaleF = 1.; break; case FD_FLOAT32: if (! UTcheckIEEE ()) UThalt ("AFsetAUpar: Host does not use IEEE float format"); Dencod = AU_FLOAT32; ScaleF = 1./32768.; break; default: UThalt ("AFsetAUpar: Unsupported data encoding"); break; } /* Create the header information */ /* Get the header information string */ h = AFgenHinfo (Sfreq, &Ninfo); Lhead = ALIGN * ICEILV (AFsp_LHMIN + Ninfo, ALIGN); /* Round up */ /* Set up the fixed header parameters */ MCOPY (FM_SUN, Fhead.Magic); Fhead.Lhead = Lhead; Fhead.Ldata = AU_NOSIZE; Fhead.Dencod = Dencod; Fhead.Srate = (uint4_t) (Sfreq + 0.5); /* Rounding */ Fhead.Nchan = (uint4_t) Nchan; MCOPY (FM_AFSP, Fhead.AFspID); /* Open the file for writing */ fp = fopen (Fname, "wb"); if (fp == NULL) UTerror ("AFsetAUpar: Cannot open file \"%s\"", Fname); /* Write out the header */ offs = 0L; offs += WHEAD_S (fp, offs, Fhead.Magic); offs += WHEAD_V (fp, offs, Fhead.Lhead, DS_EB); offs += WHEAD_V (fp, offs, Fhead.Ldata, DS_EB); offs += WHEAD_V (fp, offs, Fhead.Dencod, DS_EB); offs += WHEAD_V (fp, offs, Fhead.Srate, DS_EB); offs += WHEAD_V (fp, offs, Fhead.Nchan, DS_EB); offs += WHEAD_S (fp, offs, Fhead.AFspID); offs += WHEAD_SN (fp, offs, h, Ninfo); if (offs < Lhead) WHEAD_SN (fp, offs, Nullpad, Lhead - offs); /* null padding */ /* Set the parameters for file access */ AFp = AFsetAFp (fp, FO_WO, FT_AFSP, Format, DS_EB, ScaleF, Nchan, (long int) Lhead, 0L, 0L); /* Print the header information */ AFprintAFh (AFp, Fname, "", Sfreq, fpout); return AFp; }