/*-------------- Telecommunications & Signal Processing Lab ---------------
                             McGill University

Routine:
  int AFupdWVhead (AFILE *AFp)

Purpose:
  Update header information in a RIFF WAVE file

Description:
  This routine updates the data length fields of a RIFF WAVE file.  The file is
  assumed to have been opened with routine AFopenWrite.

Parameters:
  <-  int AFupdWVhead
      Error code, zero for no error
   -> AFILE *AFp
      Audio file pointer for an audio file opened by AFopenWrite

Author / revision:
  P. Kabal  Copyright (C) 1998
  $Revision: 1.22 $  $Date: 1998/06/26 20:55:25 $

-------------------------------------------------------------------------*/

static char rcsid [] = "$Id: AFupdWVhead.c 1.22 1998/06/26 libtsp-v3r0 $";

#include <setjmp.h>

#include <libtsp.h>
#include <libtsp/AFdataio.h>
#include <libtsp/AFheader.h>
#define AF_DATA_LENGTHS
#include <libtsp/AFpar.h>
#include <libtsp/WVpar.h>

#define ICEILV(n,m)	(((n) + ((m) - 1)) / (m))	/* int n,m >= 0 */
#define RNDUPV(n,m)	((m) * ICEILV (n, m))		/* Round up */

#define WRPAD(fp,size,align) \
     AFwriteHead (fp, NULL, 1, (int) (RNDUPV(size, align) - (size)), \
		  DS_NATIVE);

#define ALIGN		2	/* Chunks padded out to a multiple of ALIGN */

/* setjmp / longjmp environment */
extern jmp_buf AFW_JMPENV;


int
AFupdWVhead (AFp)

     AFILE *AFp;

{
  long int Nbytes, Ldata;
  uint4_t val;

/* Set the long jump environment; on error return a 1 */
  if (setjmp (AFW_JMPENV))
    return 1;		/* Return from a header write error */

/* This routine assumes that the header has the following layout
   offset  contents
      4     RIFF chunk
    ...     other chunks
    D-4     data chunk
      D     data
*/

/* Add a padding byte to the sound data; this padding byte is not included
   in the data chunk cksize field, but is included in the RIFF chunk
   cksize field
*/
  Ldata = AF_DL[AFp->Format] * AFp->Nsamp;
  Nbytes = AFp->Start + Ldata;
  Nbytes += WRPAD (AFp->fp, Nbytes, ALIGN);	/* Update Nbytes */

/* Update the RIFF chunk cksize field */
  val = (uint4_t) (Nbytes - 8);
  if (AFseek (AFp->fp, 4L, NULL))
    return 1;
  WHEAD_V (AFp->fp, val, DS_EL);

/* Update the data chunk cksize field */
  val = (uint4_t) Ldata;
  if (AFseek (AFp->fp, AFp->Start - 4, NULL))
    return 1;
  WHEAD_V (AFp->fp, val, DS_EL);

  return 0;
}
