ftp.nice.ch/pub/next/unix/audio/cmix.s.tar.gz#/cmix/track/ptrack.c

This is ptrack.c in view mode; [Download] [Up]

#define SFIRCAM
/*  Main program for pitch analysis
 *  This is a very BIG program and in order to run on the 34 it has
 *  to be broken down.  It requires
 *  1) A pipe using ccss' soundout with -O F option to force floating
 *     point output. The following command line would work, for example: 
 *
 * 			soundout -O F -d 1 sound | ptrack
 *
NB: now takes shortsams (INTs) only  -dll@ems
 *     The file should be mono.
NB: the following all happens on the commandline now  -dll@ems
 *  2) A regular ascii file called 'pchdata' and containing, on one or
 *     lines, the following information IN THIS ORDER
 *    -Name of file to contain analysis data--can be an old or null file.
 *    -Sampling rate.
 *    -LSLICE.  The total size of the frame to be analyzed, in samples.
 *     Maximum is 350, which has been good working number.  Frame should
 *     be able to contain at least one expected pitch period of signal.
 *    -JSLIDE.  The number of new samples to add per frame.  This number 
 *     should normally be less than half of LSLICE.  125 is good for 15k
 *     and 250 is good for 30k sampling rate.
 *     This number reflects the real time period of the frame, i.e. how
 *     far you creep up for each frame in the signal.
 *    -pchlow and pchigh-- expected lower and upper bounds of analysis.
 *     the better you guess at this, the better the quantization will
 *     be in the analysis.
 *     At the present time the highest fundamental analyzable is about SR/20
 *     cps, due to the settings of the lowpass filter.  This can be fixed
 *     by using interpolation, as in the fortran version of this program, 
 *     or, more sensibly, different filters.
 *    -inskip, amount of time to skip on input file before beginning analysis.
 *     The program is now written to write data sequentially beginning at the
 *     start of the data file, but this can be changed by simple adding an
 *     lseek.  
 *     (inskip should match the -s value in soundout).
 *    -dur,   amount of time to analyze. This should equal, but not
 *     exceed the -d value from soundout. 
 *  The following data file, is good for a 15k signal, for example:
 *
 *
 *      pitches 14000 350 125
 *	200 300
 *	0 .5
 *    
 */
 
#include "sysdep.h"
#include <stdio.h>
#ifdef SYS5
#include <fcntl.h>
#endif
#include <sys/file.h>
#ifdef SFIRCAM
#include "/musr/H/sfheader.h"
#endif SFIRCAM
#include <pwd.h>
#include "crack.h"
#include "ptrack.h"

#include "lpsf.h"		/* INT and FLOAT #defined here */
typedef short SIGTYPE;
#define SAMPTYPE INT		/* shortsam-only */
#define NAMESIZE 1024		/* commandline string size limit */
#define FRAMAX 350

int LSLICE;
int JSLIDE;
float SR;
float NYQ; 
int JMAX;
int MM;
char * buildsfname();
extern	int	remotein;
int debug = 0, verbose=0;

float gtphi[50][5][18],gtpsi[50][6][18];	/* had to change to globals */
float gtgamph[50][5],gtgamps[50][6]; 		/* hence the 'g' in front of the names */

main(argc, argv)
     int argc;
     char **argv;
{
	SIGTYPE sig[FRAMAX];
	int MIDPOINT,needed,howmuch;
	float freq[50];
	float getpch(),getrms(),lowpass(), ptable();
	float pchlow,pchigh,input[4];
	FILE *pdata;
	int i,n,jj,anal,framesize;
	long nsamps;
	float data[2],inskip,dur;
	char name[NAMESIZE], *fullsfname;
	char *sigp,*sigtemp;
	double rmsm,freqm,rmsx,freqx;
#ifdef SFIRCAM
	SFHEADER *sfh;
	char sfbuf[SIZEOF_HEADER], sfname[NAMESIZE];
	int sfd, sfn;
	int Hflag = 0;
#endif SFIRCAM
	char c;
	int rflag = 0;

	/* DEFAULTS... */
	*sfname = '\0';		/* '\0' => stdin */
	*name = '\0';		/* '\0' => stdout */
	LSLICE = 350;		/* 350 is max! */
	JSLIDE = 200;
	pchlow = 100.0;
	pchigh = 1000.0;
	inskip = 0.0;
	dur = 1.0;		/* should implement an EOF dur! */
	SR = 20000.0;

	if (debug) verbose++;
	if ( (c = crack(argc, argv, "q", 1)) == 'q' ) {	/* q flag present */
	  verbose++;
	  /* query for everything, ignore any other flags */
	  fprintf(stderr,"Enter soundfile name : ");
	  scanf("%s", sfname);
#ifdef SFIRCAM
	  fprintf(stderr,"Is soundfile headerless? (y or n) ");
	  scanf("%s",name); 
	  if ( *name == 'y' || *name == 'Y' ) {
	    Hflag++; fprintf(stderr,"Enter sampling rate : ");
	    scanf("%d",&SR); rflag++;
	  }
#endif SFIRCAM
	  fprintf(stderr,"Enter output file name : ");
	  scanf("%s",name); 
	  fprintf(stderr,"Enter framesize (samples per analyzed segment) : ");
	  scanf("%d",&LSLICE);
	  fprintf(stderr,"Enter interframe offset (new samples per segment) : ");
	  scanf("%d",&JSLIDE); 
	  fprintf(stderr,"Enter low pitch estimate (cps) : ");
	  scanf("%f",&pchlow); 
	  fprintf(stderr,"Enter high pitch estimate : ");
	  scanf("%f",&pchigh); 
	  fprintf(stderr,"Enter initial skip (seconds) : ");
	  scanf("%f",&inskip); 
	  fprintf(stderr,"Enter duration of analysis (seconds) : ");
	  scanf("%f",&dur);
	  /* 	and that's all	 */
	} 
	else if ( c == EOF ) usage("-q flag takes no option");
	else {			/* no q flag present */
	  /* set options from commandline */
	  arg_index = 0;	/* re-crack */
	  while ((c = crack(argc, argv,
#ifdef SFIRCAM
			    "r|h|l|f|i|s|d|o|H", 
#else SFIRCAM
			    "r|h|l|f|i|s|d|o|", 
#endif SFIRCAM
			    0)) != NULL) {
	    if (c == EOF) usage("error cracking commandline");
	    switch (c) {	/* cases w/o options */
#ifdef SFIRCAM
	    case 'H': Hflag++; break; /* no soundfile header */
#endif SFIRCAM	
	    default:		/* cases w/ options */
	      if (arg_option == NULL) usage("flag missing an option");
	      switch (c) {
		/* sound flags... */
	      case 'r':		/* sampling rate */
		sscanf(arg_option,"%d", &SR); rflag++; break;
		/* analysis and i/o flags... */
	      case 'h':		/* high cps */
		sscanf(arg_option,"%f", &pchigh); break; 
	      case 'l':		/* low cps */
		sscanf(arg_option,"%f", &pchlow); break; 
	      case 'f':		/* framesize */
		sscanf(arg_option,"%d", &LSLICE); break; 
	      case 'i':		/* framesize */
		sscanf(arg_option,"%d", &JSLIDE); break; 
	      case 's':		/* skiptime */
		sscanf(arg_option,"%f", &inskip); break;	
	      case 'd':		/* duration */
		sscanf(arg_option,"%f", &dur); break; 
	      case 'o':		/* output filename */
		if ( strlen(arg_option) >= NAMESIZE )
		  die("outputfile name too long!");
		strcpy(name,arg_option); break; 
	      default: usage("unrecognized flag");
	      }
	    }
	  }
	  if ( arg_index != argc ) { /* soundfile name here */
	    if ( strlen(argv[arg_index]) >= NAMESIZE )
	      die("soundfile name too long!");
	    strcpy(sfname,argv[arg_index]);
	  }			/* else all done */
	}
	if ( *name == '\0' ) anal = fileno(stdout); /* write stdout */
	else {
	  if ((anal = creat(name,0644)) < 0) /* create if not exists */
	    dies("ptrack: can't open output data file %s", name);
	}
	if ( *sfname == '\0' ) sfd = fileno(stdin); /* read stdin*/
	else {
	  fullsfname = buildsfname(sfname);
#ifdef SFREMOTE
	  if (index(fullsfname,':') != NULL)
	    sfd = rsfopen(fullsfname,'<');
	  else 
#endif SFREMOTE
	    if ((sfd = open(fullsfname,O_RDONLY)) < 0)
	      dies("Ptrack: can't open soundfile %s",fullsfname);
	}
#ifdef SFIRCAM
	if ( Hflag == 0 ) {	/* use sfheader */
	  if ((sfn = readin(sfd,sfbuf,SIZEOF_HEADER)) < SIZEOF_HEADER)
	    die("Ptrack: error reading soundfile header");
	  sfh = (SFHEADER *) sfbuf;
	  if (!ismagic(sfh))
	    dies("Ptrack: %s is not a soundfile",sfname);
	  if ( rflag == 0 ) SR = sfsrate(sfh);
	}
#endif SFIRCAM
	if (verbose) {
	  if (*name == '\0') fprintf(stderr,"Writing to <stdout>\n");
	  else fprintf(stderr,"Writing to %s\n",name);
	  if (*sfname == '\0') fprintf(stderr,"Reading from <stdin>\n");
	  else fprintf(stderr,"Reading from %s\n",sfname);
	  fprintf(stderr,"Sampling rate = %f\n",SR);
	  fprintf(stderr, "Pitch boundary estimates = %f (low) %f (high) \n",
		  pchlow,pchigh);
	  fprintf(stderr,"Framesize = %d\n",LSLICE);
	  fprintf(stderr,"Interframe offset = %d\n",JSLIDE);
	  fprintf(stderr,"rflag: %d Hflag: %d\n",rflag,Hflag);
	}
	{			/* do input skipping */
	  long skipbytes;
	  int nread;
	  skipbytes = (long)(inskip * SR * SAMPTYPE);
	  if (remotein || *sfname == '\0') {
	    while (skipbytes > FRAMAX) { /* remote: spinread for lseek */
	      if ((nread = readin(sfd,(char *)sig,FRAMAX)) < FRAMAX)
		die("sound skip error");
	      skipbytes -= nread;
	    }
	    if ((nread = readin(sfd, (char *)sig, skipbytes)) < skipbytes)
	      die("sound skip error");
	  }
	  else if (lseek(sfd,skipbytes,L_INCR) < 0)
	    die("bad sflseek on skip");
	}

	NYQ = SR/2.;
	JMAX = LSLICE/10;
	MM = ((LSLICE/10+1)/2);
	MIDPOINT = LSLICE - JSLIDE;
	sigp = (char *)(sig+MIDPOINT);
	ptable(pchlow,pchigh,gtphi,gtpsi,gtgamph,gtgamps,freq,n); 
	if (debug) fprintf(stderr,"returned\n");

	if ((jj = readin(sfd,(char *)sig,LSLICE*SAMPTYPE)) != LSLICE*SAMPTYPE)
	  die("Ptrack: couldn't fill first frame");
	for(i=0; i<LSLICE; i++) sig[i]=lowpass(sig[i]);
	nsamps = SR * dur;
	while(nsamps) {
	  if (debug) printf("Main loop : Nsamps = %d\n",nsamps);
	  data[0] = getpch(sig,gtphi,gtpsi,gtgamph,gtgamps,freq,n);
	  data[1] = getrms(sig);
	  write(anal,(char *)data,8);  
	  if (debug) fprintf(stderr,"pitch= %f rmsamp= %f\n ",data[0],data[1]);
	  sigp = (char *)(sig+MIDPOINT);
	  for(i=0; i<MIDPOINT; i++)  sig[i] = sig[i+JSLIDE];
	  howmuch=0;
	  needed=JSLIDE*SAMPTYPE;

	  if ((howmuch=readin(sfd,sigp,needed)) != needed)
	    break;		/* ran up against eof */

	  for(i=MIDPOINT; i<LSLICE; i++) sig[i] = lowpass(sig[i]);
	  nsamps -= JSLIDE; 
	}
}

usage(msg)
     char *msg;
{
#ifdef SFIRCAM
  fprintf (stderr, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
#else SFIRCAM
  fprintf (stderr, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
#endif SFIRCAM
   "   Usage:  ptrack [flag][option] ... [soundfile]\n",
   "[flag][option] from among:\n",
#ifdef SFIRCAM
   "-rSRATE             sampling rate of sound input (default read from\n",
   "                       soundfile header; else 20000 if -H specified)\n",
#else
   "-rSRATE             sampling rate of sound input (default 20000)\n",
#endif
   "-fFRAMESIZE         analysis framesize in samples (default 350 (max))\n",
   "-iINTERFRAMEOFFSET  offset in samples between frames (default 200 (250 max))\n",
   "-hHIGHPITCH         high pitch estimate in cps (default 1000)\n",
   "-lLOWPITCH          low pitch estimate in cps (default 100)\n",
   "-sSKIPTIME          initial seconds of sound to skip over (default 0.0)\n",
   "-dDURATION          duration in seconds to analyze (default 1.0)\n",
   "-oOUTPUTFILE        analysis output file (stdout if absent, default)\n",
#ifdef SFIRCAM
   "-H                  no soundfile header, SRATE taken from -r flag\n",
   "                       (default reads SRATE from soundfile header)\n",
#endif
   "soundfile           monaural shortsam soundfile\n",
   "                       (reads shorts on stdin if absent, default)\n",
   "\n",
   "      or:  ptrack -q   (queries the user for commandline options)\n",
   "see also:  man ptrack\n\n"
   );
	   die(msg);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.