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

Routine:
  int AFrdTA (AFILE *AFp, float Fbuff[], int Nreq)

Purpose:
  Read samples (text data) from an audio file (return float values)

Description:
  This routine reads a specified number of samples from an audio file.  The
  data in the file is converted to float format on output. The file must have
  been opened using subroutine AFopenRead.

  The data is expected to be one value to a line.

Parameters:
  <-  int AFrdTA
      Number of data values transferred from the file.  On reaching the end of
      the file, this value may be less than Nreq.
   -> AFILE *AFp
      Audio file pointer for an audio file opened by AFopenRead
  <-  float Fbuff[]
      Array of floats to receive the samples
   -> int Nreq
      Number of samples requested.  Nreq may be zero.

Author / revision:
  P. Kabal  Copyright (C) 1998
  $Revision: 1.14 $  $Date: 1998/04/24 22:05:39 $

-------------------------------------------------------------------------*/

static char rcsid [] = "$Id: AFrdTA.c 1.14 1998/04/24 libtsp-v3r0 $";

#include <ctype.h>

#include <libtsp.h>
#include <libtsp/AFdataio.h>
#include <libtsp/Xstdlib.h>
#include <libtsp/AFmsg.h>
#include <libtsp/AFpar.h>

#define MINV(a, b)	(((a) < (b)) ? (a) : (b))


int
AFrdTA (AFp, Fbuff, Nreq)

     AFILE *AFp;
     float Fbuff[];
     int Nreq;

{
  char *line;
  int n, ErrCode;
  double Dv;
  char *endstr;

/*
   This routine spends most of its time in strtod (sscanf is even slower)
   Tests:  24 Mb file with 4.7M samples
   - read data, copy to another file, 43 sec CPU
   - read data (strtod commented out), copy to another file, 16 sec CPU
*/

/* Read the data */
  ErrCode = 0;
  for (n = 0; n < Nreq; ++n) {
    line = AFgetLine (AFp->fp, &ErrCode);	/* prints error messages */
    if (line == NULL || ErrCode)
      break;
    Dv = strtod (line, &endstr);
    for (; isspace ((int)(*endstr)); ++endstr)
      ;
    if (endstr[0] != '\0') {
      UTwarn ("AFrdTA - %s", AFM_DataErr);
      ErrCode = AF_DECERR;
      break;
    }
    Fbuff[n] = AFp->ScaleF * Dv;
  }

/* Check for errors */
  if (ErrCode)
    AFp->Error = ErrCode;

  return n;
}
