
/*
#    Sfront, a SAOL to C translator    
#    This file: raw audio driver for sfront
#    Copyright (C) 1999  Regents of the University of California
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License (Version 2) as
#    published by the Free Software Foundation.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#    Maintainer: John Lazzaro, lazzaro@cs.berkeley.edu
*/


/****************************************************************/
/****************************************************************/
/*             raw file audio driver for sfront                 */ 
/*       reads/writes 16-bit signed shorts in native format     */
/****************************************************************/
        
#include <stdio.h>
#include <string.h>

#if defined(ASYS_HASOUTPUT)

/* default name for output audio file */
#define ASYSO_DEFAULTNAME "output"

/* global variables, must start with asyso_ */

FILE * asyso_fd[ASYS_OCHAN]; /* output file pointer */
long asyso_srate;            /* sampling rate */
float asyso_stime;           /* sample period */
long asyso_channels;         /* number of channels */
long asyso_size;             /* number of samples in a buffer */
long asyso_nsamp;            /* total number of samples written */
ASYS_OTYPE * asyso_buf;      /* location for output buffer */ 
#endif

#if defined(ASYS_HASINPUT)

/* default name for output audio file */
#define ASYSI_DEFAULTNAME "input"

/* global variables, must start with asysi_ */

FILE * asysi_fd;     /* input file pointer */
char * asysi_name;   /* name of file  */        
long asysi_srate;    /* sampling rate */
long asysi_channels; /* number of channels */
long asysi_size;    /* number of samples in a buffer */
long asysi_nsamp;    /* total number of samples written */
ASYS_ITYPE * asysi_buf;   /* location for input buffer */ 

#endif

#if defined(ASYS_HASOUTPUT)

/****************************************************************/
/*        core routine for audio output setup                   */
/****************************************************************/

int asyso_setup(long srate, long ochannels, long osample, 
		long osize, char * name)


{
  int i;
  char * cname;
  char * nname;

  /* note: ASYS_OCHAN holds same value as ochannels */

  if (name == NULL)
    return ASYS_ERROR;
  else
    {
      if (ASYS_OCHAN == 1)
	{
	  asyso_fd[0] = fopen(name,"w");
	  if (asyso_fd[0] == NULL)
	    return ASYS_ERROR;
	}
      else
	{
	  cname = strcpy((char *)calloc((strlen(name)+1),sizeof(char)), name);
	  cname[((int)strlen(cname))-4]='\0';
	  nname = (char *) malloc((int)strlen(cname)+8);
	  for(i=0;i < ASYS_OCHAN;i++)
	    {
	      sprintf(nname,"%s%i.dat",cname,i+1);
	      asyso_fd[i] = fopen(nname,"w");
	      if (asyso_fd[i] == NULL)
		return ASYS_ERROR;
	    }
	}
    }

  for(i=0;i<ASYS_OCHAN;i++)
    {
      fprintf(asyso_fd[i],"1\n");
      fprintf(asyso_fd[i],"# Sa.c channel %i: sample rate %i\n\n",i+1,srate);
      fprintf(asyso_fd[i],"pairs\n");
      fprintf(asyso_fd[i],"ch%i\n",i+1);
      fprintf(asyso_fd[i],"*\n");
      fprintf(asyso_fd[i],"*\n");
    }

  asyso_srate = srate;
  asyso_stime = 1.0F/srate;
  asyso_channels = ochannels;
  asyso_size = osize;
  asyso_nsamp = 0;
  asyso_buf = (ASYS_OTYPE *)calloc(osize, sizeof(ASYS_OTYPE));
  return ASYS_DONE;
}

#endif

#if defined(ASYS_HASINPUT)

/****************************************************************/
/*        core routine for audio input setup                   */
/****************************************************************/

int asysi_setup(long srate, long ichannels, long isample, 
		long isize, char * name)


{
  char strbuf[128];
  char * ret;
  char * val;

  if (name == NULL)
    val = ASYSI_DEFAULTNAME;
  else
    val = name;
  asysi_name = strcpy((char *) calloc((strlen(val)+1),sizeof(char)), val);
  asysi_fd = fopen(asysi_name,"r");
  if (asysi_fd == NULL)
    return ASYS_ERROR;

  ret = fgets(strbuf, 128, asysi_fd);
  while ((strstr(strbuf,"pairs") == NULL)||(strbuf[0]=='#'))
    {
      if (ret == NULL)
	return ASYS_ERROR;
      ret = fgets(strbuf, 128, asysi_fd);
    }

  if (fgets(strbuf, 128, asysi_fd) == NULL)
    return ASYS_ERROR;
  if (fgets(strbuf, 128, asysi_fd) == NULL)
    return ASYS_ERROR;
  if (fgets(strbuf, 128, asysi_fd) == NULL)
    return ASYS_ERROR;
  
  asysi_srate = srate;
  asysi_channels = ichannels;
  asysi_size = isize;
  asysi_nsamp = 0;
  asysi_buf = (ASYS_ITYPE *)malloc(sizeof(ASYS_ITYPE)*isize);
  return ASYS_DONE;

}

#endif

#if (defined(ASYS_HASOUTPUT) && !defined(ASYS_HASINPUT))

/****************************************************************/
/*        sets up audio output for a given srate/channels       */
/****************************************************************/

int asys_osetup(long srate, long ochannels, long osample, 
                char * oname, long toption)

{
  return asyso_setup(srate, ochannels, osample, ASYS_OCHAN*ACYCLE, oname);
}

#endif


#if (!defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT))

/****************************************************************/
/*        sets up audio input for a given srate/channels       */
/****************************************************************/

int asys_isetup(long srate, long ichannels, long isample, 
                char * iname, long toption)

{
  return asysi_setup(srate, ichannels, isample, ASYS_ICHAN*ACYCLE, iname);
}

#endif


#if (defined(ASYS_HASOUTPUT) && defined(ASYS_HASINPUT))

/****************************************************************/
/*   sets up audio input and output for a given srate/channels  */
/****************************************************************/

int asys_iosetup(long srate, long ichannels, long ochannels,
                 long isample, long osample, 
                 char * iname, char * oname, long toption)

{
  if (asysi_setup(srate, ichannels, isample, ASYS_ICHAN*ACYCLE,
		  iname) != ASYS_DONE)
    return ASYS_ERROR;
  return asyso_setup(srate, ochannels, osample, ASYS_OCHAN*ACYCLE, oname);
}

#endif

#if defined(ASYS_HASOUTPUT)

/****************************************************************/
/*             shuts down audio output system                   */
/****************************************************************/

void asyso_shutdown(void)

{
  int i;

  for (i=0;i<ASYS_OCHAN;i++)
    {
      fprintf(asyso_fd[i],"\n");
      fclose(asyso_fd[i]);
    }
}

#endif

#if defined(ASYS_HASINPUT)

/****************************************************************/
/*               shuts down audio input system                  */
/****************************************************************/

void asysi_shutdown(void)

{
  fclose(asysi_fd);
}

#endif


#if (defined(ASYS_HASOUTPUT)&&(!defined(ASYS_HASINPUT)))

/****************************************************************/
/*                    shuts down audio output                   */
/****************************************************************/

void asys_oshutdown(void)

{
  asyso_shutdown();
}

#endif

#if (!defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT)))

/****************************************************************/
/*              shuts down audio input device                   */
/****************************************************************/

void asys_ishutdown(void)

{
  asysi_shutdown();
}

#endif

#if (defined(ASYS_HASOUTPUT)&&(defined(ASYS_HASINPUT)))

/****************************************************************/
/*              shuts down audio input and output device        */
/****************************************************************/

void asys_ioshutdown(void)

{
  asysi_shutdown();
  asyso_shutdown();
}

#endif


#if defined(ASYS_HASOUTPUT)

  

/****************************************************************/
/*        creates buffer, and generates starting silence        */
/****************************************************************/

int asys_preamble(ASYS_OTYPE * asys_obuf[], long * osize)

{
  int i;

  *asys_obuf = asyso_buf;
  *osize = asyso_size;
  return ASYS_DONE;
}


/****************************************************************/
/*               sends one frame of audio to output             */
/****************************************************************/

int asys_putbuf(ASYS_OTYPE * asys_obuf[], long * osize)


{
  long i;

  for (i = 0; i < *osize; i++)
    {
      fprintf(asyso_fd[i % ASYS_OCHAN], "%f %f\n", asyso_nsamp*asyso_stime, 
	      (float)((*asys_obuf)[i]));
      if (!(i%ASYS_OCHAN))
	asyso_nsamp++;
    }

  return ASYS_DONE;
}

#endif

#if defined(ASYS_HASINPUT)

/****************************************************************/
/*               gets one frame of audio from input             */
/****************************************************************/

int asys_getbuf(ASYS_ITYPE * asys_ibuf[], long * isize)

{
  float x, y;
  int i;

  if (*asys_ibuf == NULL)
    *asys_ibuf = asysi_buf;
  *isize = 0;
  while (*isize < asysi_size)
    {
      if (fscanf(asysi_fd,"%f%f",&x, &y) != 2)
	break;
      for (i = 0; i < asysi_channels; i++)
	(*asys_ibuf)[(*isize)++] = (ASYS_ITYPE) y;
    }
  asysi_nsamp += *isize;
  return ASYS_DONE;
}

#endif

