/*-------------- Telecommunications & Signal Processing Lab --------------- McGill University Routine: AFILE *AFsetWVpar (const char Fname[], int Format, long int Nchan, double Sfreq, FILE *fpout) Purpose: Write header information to a RIFF WAVE file Description: This routine writes header information to a RIFF WAVE format audio file. The file is assumed to have been opened with routine AFopenWrite. Optionally, the file header information is printed. RIFF WAVE file: Offset Length Type Contents 0 4 char File identifier ("RIFF") 4 4 int RIFF chunk length (initially set to 36) 8 4 char File identifier ("WAVE") 12 4 char Format chunk identifier ("fmt ") 16 4 int Format chunk length (16) 20 2 int Audio data type 22 2 int Number of interleaved channels 24 4 int Sample rate 28 4 int Average bytes/sec 32 2 int Block align 34 2 int Data word length (bits) 36 4 char Data chunk identifier ("data") 40 4 int Data chunk length (initially set to 0) 44 ... ... Audio data 8-bit mu-law, 8-bit A-law, 8-bit integer, 16-bit integer data formats are supported. Parameters: <- AFILE AFsetWVpar 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_UINT8 = 3, offset-binary 8-bit integer data FD_INT16 = 5, two's-complement 16-bit integer 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.11 $ $Date: 1996/08/14 18:08:35 $ -------------------------------------------------------------------------*/ static char rcsid [] = "$Id: AFsetWVpar.c 1.11 1996/08/14 AFsp-V2R1 $"; #include #include #include #include #include #include #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)) AFILE * AFsetWVpar (Fname, Format, Nchan, Sfreq, fpout) const char Fname[]; int Format; long int Nchan; double Sfreq; FILE *fpout; { FILE *fp; AFILE *AFp; int Lenb, Dencod; long int offs, Ldata; double ScaleF; struct { struct WV_CkPreamb riff_p; char waveid[4]; struct WV_CkPreamb fmt_p; struct WV_PCMformat fmt; struct WV_CkPreamb data_p; } Fhead; /* Set up the encoding parameters */ switch (Format) { case FD_INT16: Dencod = WAVE_FORMAT_PCM; Lenb = FDL_INT16; ScaleF = 1.; break; case FD_UINT8: Dencod = WAVE_FORMAT_PCM; Lenb = FDL_INT8; ScaleF = 1./128.; break; case FD_MULAW8: Dencod = WAVE_FORMAT_MULAW; Lenb = FDL_MULAW8; ScaleF = 1.; break; case FD_ALAW8: Dencod = WAVE_FORMAT_ALAW; Lenb = FDL_ALAW8; ScaleF = 1.; break; default: UThalt ("AFsetWVpar: Unsupported data encoding"); break; } /* Set up the fixed header parameters */ Ldata = 0; MCOPY (FM_RIFF, Fhead.riff_p.ckid); Fhead.riff_p.cksize = (uint4_t) (4 + 8 + WV_FMT_CKSIZE + 8 + Ldata); MCOPY (FM_WAVE, Fhead.waveid); MCOPY ("fmt ", Fhead.fmt_p.ckid); Fhead.fmt_p.cksize = WV_FMT_CKSIZE; Fhead.fmt.FormatTag = Dencod; Fhead.fmt.Channels = (uint2_t) Nchan; Fhead.fmt.SamplesPerSec = (uint4_t) (Sfreq + 0.5); /* Rounding */ Fhead.fmt.AvgBytesPerSec = Fhead.fmt.SamplesPerSec * Lenb; Fhead.fmt.BlockAlign = (uint2_t) (Lenb * Nchan); Fhead.fmt.BitsPerSample = 8 * Lenb; MCOPY ("data", Fhead.data_p.ckid); Fhead.data_p.cksize = (uint4_t) Ldata; /* Open the file for writing */ fp = fopen (Fname, "wb"); if (fp == NULL) UTerror ("AFsetWVpar: Cannot open file \"%s\"", Fname); /* Write out the header */ offs = 0L; offs += WHEAD_S (fp, offs, Fhead.riff_p.ckid); offs += WHEAD_V (fp, offs, Fhead.riff_p.cksize, DS_EL); offs += WHEAD_S (fp, offs, Fhead.waveid); offs += WHEAD_S (fp, offs, Fhead.fmt_p.ckid); offs += WHEAD_V (fp, offs, Fhead.fmt_p.cksize, DS_EL); offs += WHEAD_V (fp, offs, Fhead.fmt.FormatTag, DS_EL); offs += WHEAD_V (fp, offs, Fhead.fmt.Channels, DS_EL); offs += WHEAD_V (fp, offs, Fhead.fmt.SamplesPerSec, DS_EL); offs += WHEAD_V (fp, offs, Fhead.fmt.AvgBytesPerSec, DS_EL); offs += WHEAD_V (fp, offs, Fhead.fmt.BlockAlign, DS_EL); offs += WHEAD_V (fp, offs, Fhead.fmt.BitsPerSample, DS_EL); offs += WHEAD_S (fp, offs, Fhead.data_p.ckid); offs += WHEAD_V (fp, offs, Fhead.data_p.cksize, DS_EL); /* Set the parameters for file access */ AFp = AFsetAFp (fp, FO_WO, FT_WAVE, Format, DS_EL, ScaleF, Nchan, offs, 0L, 0L); /* Print the header information */ AFprintAFh (AFp, Fname, "", (double) Fhead.fmt.SamplesPerSec, fpout); return AFp; }