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

Routine:
  struct AF_info *AFgenHinfo (double Sfreq)

Purpose:
  Form an AFsp information structure

Description:
  This returns an AFsp information structure.  The information records in
  that structure are in a form suitable for writing directly to an audio file
  header.  The header string is formed from a combination of the standard
  header information and the user supplied information string.  There are three
  cases.
    - User header information not specified.  The standard header information
      records are generated.
    - User header information string starts with a newline.  The standard
      header information is generated and then the user header information
      string (containing information records) is appended.
    - User header information string does not start with a newline.  Only the
      user header information string is used.

  Standard Header Information:
    date: 1994/01/25 19:19:39 UTC  date
    sample_rate: 8012.5            sampling frequency (only if non-integer)
    user: kabal@aldebaran          user
    program: CopyAudio             program name (if set via routine UTsetProg)

Parameters:
  <-  struct AF_info *AFgenHinfo
      AFsp information structure.  The information records in the structure
      are in a form that can be directly written to the header, i.e. newline
      characters have been changed to null characters.  This string is
      allocated by this routine.
   -> double Sfreq
      Sampling frequency.  If this value is non-integer, a sample_rate record
      is put in the standard header information string.

Author / revision:
  P. Kabal  Copyright (C) 1998
  $Revision: 1.16 $  $Date: 1998/06/18 12:58:05 $

-------------------------------------------------------------------------*/

static char rcsid[] = "$Id: AFgenHinfo.c 1.16 1998/06/18 libtsp-v3r0 $";

#include <assert.h>
#include <math.h>	/* floor */
#include <string.h>

#include <libtsp.h>
#include <libtsp/AFheader.h>
#include <libtsp/AFpar.h>

#define MAX_SINFO	320

static int
AF_stdInfo p_((char *Sinfo, double Sfreq));
static int
AF_nlNull p_((char *Info));


struct AF_info *
AFgenHinfo (Sfreq)

     double Sfreq;

{
  char Sinfo[MAX_SINFO];
  char *Uinfo;
  int ns, nu;
  static struct AF_info Hinfo = {NULL, 0};

  Uinfo = AFgetHinfo ();
  if (Uinfo == NULL || Uinfo[0] == '\n')
    ns = AF_stdInfo (Sinfo, Sfreq);
  else {
    ns = 0;
    Sinfo[0] = '\0';
  }

 /* Add the user specified header information */
  if (Uinfo != NULL)
    nu = strlen (Uinfo);
  else
    nu = 0;

  UTfree ((void *) Hinfo.Info);
  Hinfo.Info = (char *) UTmalloc (nu + ns + 1);

  strcpy (Hinfo.Info, Sinfo);
  if (Uinfo != NULL)
    strcpy (&Hinfo.Info[ns], Uinfo);

/* Change newlines to nulls */
  Hinfo.N = AF_nlNull (Hinfo.Info);

/* Return a pointer to the header information */
  return &Hinfo;
}

/* Generate the standard header information */


static int
AF_stdInfo (Sinfo, Sfreq)

     char *Sinfo;
     double Sfreq;

{
  int N;
  char *p;

  sprintf (Sinfo, "date: %.40s\n", UTdate(3));
  N = strlen (Sinfo);	/* Some versions of sprintf return a pointer */
  if (Sfreq > 0.0 && Sfreq != floor (Sfreq)) {
    sprintf (&Sinfo[N], "sample_rate: %.7g\n", Sfreq);
    N += strlen (&Sinfo[N]);
  }
  p = UTuserName ();
  if (*p != '\0') {
    sprintf (&Sinfo[N], "user: %.40s\n", p);
    N += strlen (&Sinfo[N]);
  }
  p = UTgetProg ();
  if (*p != '\0') {
    sprintf (&Sinfo[N], "program: %.40s", p);
    N += strlen (&Sinfo[N]);
  }
  assert (N < MAX_SINFO);

  return N;
}

/* Change newlines to nulls (unless escaped) */


static int
AF_nlNull (Info)

     char *Info;

{
  int i, k;

  for (i = 0, k = 0; Info[i] != '\0'; ++i, ++k) {
    if (Info[i] == '\\' && Info[i+1] == '\n') {
      Info[k] = '\n';
      ++i;
    }
    else if (Info[i] == '\n')
      Info[k] = '\0';
    else if (k != i)
      Info[k] = Info[i];
  }
  Info[k] = '\0';

  return k;
}
