#include "../../sysdep.h"
#include <stdio.h>
#include <fcntl.h>
#include "crack.h"
#include "../../lpc.h"

#define PFRAMSIZ  2                    /* words per frame (pitch&rms */
#define PCHSIZE   16                   /* record size in float words */
#define BPPFRAME  FLOAT*PFRAMSIZ       /* bytes per frame */
#define BPPREC    BPPFRAME*PCHSIZE     /* bytes per record */
#define FPPREC    PCHSIZE/PFRAMSIZ     /* frames per record */
float PFPS;                 	       /* pitch frames per second */

#define NAMESIZE 1024		/* commandline string size limit */
#define FLOAT 4
float sampspf;
int pitches;
int debug=0, verbose=0;

main(argc, argv)
     int argc;
     char **argv;
{
        int anal,j;
	int npoles,lpcframe,lpclast,pchframe,pchlast,nbpch;
	long nskiplpc,nskippch,nblpc;
	char  input[NAMESIZE],output[NAMESIZE];
	float pch[2],val,sr,time,getfreq();
	LPHEADER *lph;
	char lpbuf[LPBUFSIZ];
	char c;

	/* DEFAULTS... */
	*input = '\0';
	*output = '\0';
	PFPS = 20000.0 / 200.0;	/* this is ptrack.c default SR/JSLIDE */
	lpcframe = 0;
	lpclast = -1;		/* to EOF */

	if (debug) verbose++;
	if ( (c = crack(argc, argv, "q", 1)) == 'q' ) {	/* q flag present */
	  verbose++;
	  /* query for everything, ignore any other flags */
	  printf("Enter name of lpc analysis file :");
	  scanf("%s",output);
	  printf("Enter name of pitch analysis file :");
	  scanf("%s",input);
	  printf("Enter pitch frames per sec (floating point) :");
	  scanf("%f",&PFPS);
	  /* 	printf(" Enter number of poles in lpc analysis\t"); 
	   *	scanf("%d",&npoles);
	   */
	  printf("Enter starting frame in lpc analysis :");
	  scanf("%d",&lpcframe);
	  printf("Enter ending frame :");
	  scanf("%d",&lpclast);

	  /* 	printf(" Enter sr and samples per lpcframe\t");
	   *      scanf("%f %f",&sr,&sampspf); 
	   */
	} 
	else if ( c == EOF ) usage("-q flag doesn't take an option");
	else {			/* no q flag present */
	  /* set options from commandline */
	  arg_index = 0;	/* re-crack */
	  while ((c = crack(argc, argv, "p|b|e|", 0)) != NULL) {
	    if (c == EOF) usage("error cracking command line");
	    if (arg_option == NULL) usage("flag missing an option");
	    switch (c) {
	    case 'p':		/* pitchframerate */
	      sscanf(arg_option,"%f", &PFPS); break;
	    case 'b':		/* beg frame */
	      sscanf(arg_option,"%d", &lpcframe); break; 
	    case 'e':		/* end frame */
	      sscanf(arg_option,"%d", &lpclast); break;	
	    default: usage("unrecognized flag");
	    }
	  }
	  if ( arg_index >= (argc - 1) )
	    usage("missing anallpcfile and/or ptrackfile names");
	  if ( arg_index == (argc - 2) ) { /* ok */
	    if ( strlen(argv[arg_index]) >= NAMESIZE )
	      die("anallpcfile name too long!");
	    strcpy(output,argv[arg_index]);
	    arg_index++;	/* next! */
	    if ( strlen(argv[arg_index]) >= NAMESIZE )
	      die("ptrackfile name too long!");
	    strcpy(input,argv[arg_index]);
	  } else usage("extra arguments found");
	}
	if (verbose) {
	  fprintf(stderr,"Writing to lpfile ");
	  if (*output == '\0') fprintf(stderr,"<stdout>\n");
	  else fprintf(stderr,"%s\n",output);
	  fprintf(stderr,"Reading from ptrackfile ");
	  if (*input == '\0') fprintf(stderr,"<stdin>\n");
	  else fprintf(stderr,"%s\n",input);
	  fprintf(stderr,"pitchframerate = %f from frame %d to frame %d\n",
		  PFPS,lpcframe,lpclast);
	}

	if((anal = open(output,2)) < 0) {
		fprintf(stderr," Can't open lpc analysis file");
		exit(1);
		}
	if((pitches = open(input,0)) < 0) {
		fprintf(stderr," Can't open pitch analysis file");
		exit(1);
	}
	if ((j = read(anal, lpbuf, LPBUFSIZ)) <= 0)	{
		fprintf(stderr," Can't read header on lpc analysis file\n");
		exit(1);
	}
	lph = (LPHEADER *) lpbuf;
	npoles = lph->npoles;
	sr = lph->srate;
	sampspf = sr / lph->framrate;
	

	nblpc = (npoles+4)*FLOAT - FLOAT;/*to beginning of next pchloc*/
	nskiplpc = (long)(lpcframe)*(long)(nblpc+FLOAT) + (3*FLOAT);  
				 /* pch is 4th data value in fr*/
	if((lseek(anal,nskiplpc + lph->headersize,0)) < 0)  { /* add */
		printf("Bad lseek on analysis file\n");	/* headersize */
		exit(1);
		}
	for(j=lpcframe;;j++) {
	  if ( j > lpclast && lpclast != -1 ) break;
/*
*		if((read(pitches,(char *)pch,nbpch)) != nbpch) {
*			printf("Bad read on pitch analysis file\n");
*			exit(1);
*			}
*/
		time = (float)j*sampspf/sr;
		val = getfreq(time);
		if((write(anal,(char *)&val,FLOAT)) != FLOAT) {
			printf("Bad write on lpc analysis file\n");
			exit(1);
			}
		lseek(anal,nblpc,1);
	}
}

float getfreq(time) 
float time;
{


	int i,j,frame;
	float fframe,fraction,cps,error;
	static int oldframe = 0;
	static int endframe = 0;
	static float parray[PCHSIZE*2];

	fframe = time * PFPS;
	frame = (int)fframe;
	fraction = fframe - (float)frame;
	if(!((frame >= oldframe) && (frame < endframe))) {
		if(lseek(pitches,((long)frame*(long)BPPFRAME),0) < 0) {
			printf("Bad lseek on pitch file\n");
			exit(1);
		} 
		if(read(pitches,(char *)parray,BPPREC) != BPPREC) {
			printf("Bad read on pitch file\n");
		}
		oldframe = frame;
		endframe = oldframe + FPPREC - 1;
	}
	cps = (1.-fraction) * *(parray+(frame-oldframe)*PFRAMSIZ) +
	    fraction  * *((parray+(frame-oldframe)*PFRAMSIZ)+2);
	error = (1.-fraction) * *(parray+(frame-oldframe)*PFRAMSIZ+1) +
	    fraction  * *((parray+(frame-oldframe)*PFRAMSIZ)+3);
	return(cps);
}

usage(msg)
     char *msg;
{
fprintf(stderr,"%s%s%s%s%s%s%s%s%s%s",
"   Usage:  lpconcat [flag][option] anallpcfile ptrackfile\n",
"[flag][option] from among:\n",
"-pPFRAMERATE  ptrack framerate: SRATE/INTERFRAMEOFFSET (default 20000/150)\n",
"-bBEGINFRAME  first frame to insert pitch data into (default 0)\n",
"-eENDFRAME    last frame to insert pitch data into (default -1 (to end))\n",
"anallpcfile   lpc data file to insert pitch data into\n",
"ptrackfile    pitch data file to read\n",
"\n",
"      or:  lpconcat -q   (queries the user for commandline options)\n",
"see also:  man lpconcat\n\n"
);
die(msg);
}
