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.