
/*
#    Sfront, a SAOL to C translator    
#    This file: Time synchronization routines for file playback.
#    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
#
#    Primary Author: John Lazzaro, lazzaro@cs.berkeley.edu
*/

/******************************************************************/
/*                                                                */
/* Playback synchronization routines act to estimate the cpuload  */
/* for each k-cycle. Two functions are must be defined:           */
/*                                                                */
/* void ksyncinit() { }                                           */
/*                                                                */
/*   called before first ipass begins, lets sync routines         */
/*   initialize state.                                            */
/*                                                                */
/* float ksync()  { }                                             */
/*                                                                */
/*   returns the current estimate of cpuload, the SA standard     */
/*   name.                                                        */
/*                                                                */
/* Rules for writing your own playback sync.c file:               */
/*                                                                */
/* (1) all globals and functions must begin with sync_, all defs  */
/*     must begin with SYNC_.                                     */
/* (2) Define both ksync() and ksyncinit().                       */
/*                                                                */
/* Note that:                                                     */
/*  KUTIME: a long,  defines k-cycle length in microseconds       */
/*  KMTIME: a float, defines k-cycle length in milliseconds       */
/*  KTIME:  a float, defines k-cycle length in seconds            */
/******************************************************************/


#include <sys/time.h>

#define SYNC_ONESECOND 1000000L
#define SYNC_SELDELAY 1000L
#define SYNC_NORM (1.0F/KUTIME)
struct timeval sync_last, sync_this;

/***********************************************************/
/*         synchronizes on k-rate boundaries               */
/***********************************************************/

float ksync()

{
  float ret = 1.0F;

  gettimeofday(&sync_this, NULL);

  if ((sync_last.tv_usec += KUTIME) < SYNC_ONESECOND) /* non-rollover case */
    {
      if ((sync_last.tv_usec >= sync_this.tv_usec) &&
	  (sync_last.tv_sec == sync_this.tv_sec))
	ret -= SYNC_NORM*(sync_last.tv_usec - sync_this.tv_usec);

      sync_last = sync_this;
      ret = (ret > 0.0F) ? ret : 0.0F;
      return ret;
    }

  sync_last.tv_sec++;
  sync_last.tv_usec %= SYNC_ONESECOND;

  if (sync_last.tv_sec >= sync_this.tv_sec)
    {
      if (sync_last.tv_sec > sync_this.tv_sec)
	{
	  ret -= SYNC_NORM*(sync_last.tv_usec + 
			    SYNC_ONESECOND - sync_this.tv_usec);
	}
      else
	{
	  if (sync_last.tv_usec > sync_this.tv_usec)
	    ret -= SYNC_NORM*(sync_last.tv_usec - sync_this.tv_usec);
	}
    }

  sync_last = sync_this;
  ret = (ret > 0.0F) ? ret : 0.0F;
  return ret;
}

/***********************************************************/
/*         initializes k-rate boundaries sync              */
/***********************************************************/

void ksyncinit()

{
  gettimeofday(&sync_last, NULL);
}


