#include <stdio.h>
#include <stdlib.h>

#define SERIAL_SIZE 82    /* bits in stream = 80 + sync + size */
#define RATE_8000   80    /* 80 bits in frame */
#define PRM_SIZE    11    /* 11 parameters to extract */
#define RATE_SID    15
#define RATE_SID_OCTET 16
#define NC0_B          7
#define NC1_B          5
#define BIT_1          0x0081
#define OCTET_TX_MODE
#define MODE_PAUSE     0
#define MODE_ERASE     1

#define Word16  short

Word16 bitsno[PRM_SIZE] = {1+NC0_B, /* MA + 1st stage */
                                 NC1_B*2, /* 2nd stage */
                                 8,1,  13,4, 7, /* first subframe  */
                                 5,    13,4, 7}; /* second subframe */


Word16 bitsno2[4] = {1, /* SID Lsp : MA  */
                     5, /* SID Lsp : 1st stage */
                     4, /* SID Lsp : 2nd stage */
                     5 };  /* SID gain */



/***********************************************

FILE: erase.c
PURPOSE: This program reads a g.729 bitstream, erases certain
   frames, and writes the resulting bitstream back to another file
USAGE: erase instream outstream [-bs size] [-pause pause] [-o patternfile] [-i pfile]

NOTE: The procedures read_frame, bin2int,  and bit22prm_ld8k were
   taken from the ITU g.729 implementation.

*************************************************/

void Usage() {
  fprintf(stderr,"Usage:\n");
  fprintf(stderr,"erase instream outstream [-bs size] [-pause pause] [-o patternfile] [-i pfile]\n");
}

void main(int argc, char *argv[]) {
  int i;
  FILE *fin, *fout;
  int burstsize, pausesize;
  FILE *pin, *pout;
  short serial[SERIAL_SIZE];          /* Serial stream               */
  Word16 size;
  int pausesofar, erasesofar, numframes, numerasures;
  int mode,erasehere;



  /* Parse command line args */

  pin = pout = NULL;
  burstsize = 1;
  pausesize = 20;

  if(argc < 3) {
    Usage();
    exit(-1);
  }

  if((fin = fopen(argv[1],"r")) == NULL) {
    fprintf(stderr,"Error opening file %s for read\n",argv[1]);
    exit(-1);
  }
  if((fout = fopen(argv[2],"w")) == NULL) {
    fprintf(stderr,"Error opening file %s for write\n",argv[1]);
    exit(-1);
  }

  printf("Running erase:\n");
  printf(" Infile: %s\n",argv[1]);
  printf(" Outfile:%s\n",argv[2]);
  
  argc -= 3;
  argv += 3;
  while(argc != 0) {
    if(strcmp(*argv,"-bs") == 0) {
      argv++;
      burstsize = atoi(*argv);
      argv++;
      argc -= 2;
    }
    else if(strcmp(*argv,"-pause") == 0) {
      argv++;
      pausesize = atoi(*argv);
      argv++;
      argc -=2;
    }
    else if(strcmp(*argv, "-o") == 0) {
      argv++;
      pout = fopen(*argv,"w");
      argv++;
      argc -= 2;
    }
    else if(strcmp(*argv, "-i") == 0) {
      argv++;
      pin = fopen(*argv,"r");
      argv++;
      argv -= 2;
    }
    else {
      fprintf(stderr,"Unrecognized option %s\n",argv);
      exit(-1);
    }
  }
  
  printf("burstsize: %d\n",burstsize);
  printf("pausesize: %d\n",pausesize);
  printf("pattern out: %s\n",((pout == NULL)?("NO"):("YES")));
  printf("pattern in: %s\n",((pin == NULL)?("NO"):("YES")));

  /* Now, begin reading frames */

  pausesofar = 1;
  erasesofar = 1;
  mode = MODE_PAUSE;

  numerasures = 0;
  numframes = 0;

  while(1) {

    erasehere = 0;

    if(fread(serial, sizeof(short), 2, fin) != 2) {
      break;
    }


    if(fread(&serial[2], sizeof(Word16), (size_t)serial[1], fin)
       != (size_t)serial[1]) {
      break;
    }

    size = serial[1];
    
    /* Apply state machine only if this is a speech frame */

    if(size == RATE_8000) {

      /* Update state */
      if((mode == MODE_ERASE) && (erasesofar == burstsize)) {
	mode = MODE_PAUSE;
	erasesofar = 1;
	pausesofar = 1;
      }
      else if((mode == MODE_PAUSE) && (pausesofar == pausesize)) {
	mode = MODE_ERASE;
	erasesofar = 1;
	pausesofar = 1;
      }
      else if(mode == MODE_PAUSE) {
	pausesofar++;
      }
      else if(mode == MODE_ERASE) {
	erasesofar++;
      }

      /* Decide on erase */

      if(mode == MODE_ERASE) {
	erasehere = 1;
	numerasures++;
      }
      numframes++;

    }
    
    /* This decision is overridden by input erase file */
    if(pin != NULL) {
      fscanf(pin,"%d\n",&erasehere);
    }

    /* To erase, just set the next word to all zeroes */

    if(erasehere == 1)
      serial[2] = 0;

    /* Now write frame back */


    if(fwrite(serial, sizeof(short), 2, fout) != 2) {
      fprintf(stderr,"Error writing to file\n");
      exit(-1);
    }


    if(fwrite(&serial[2], sizeof(Word16), (size_t)serial[1], fout)
       != (size_t)serial[1]) {
      fprintf(stderr,"Error writing to file\n");
      exit(-1);
    }

    /* Write to pattern file */

    if(pout != NULL) {
      fprintf(pout,"%d\n",erasehere);
    }
     
  }

  /* Now we are done; close open files */

  fclose(fin);
  fclose(fout);
  if(pin != NULL) fclose(pin);
  if(pout != NULL) fclose(pout);

  /* Write statistics */
  
  printf("Out of %d frames of speech, deleted %d\n",numframes,numerasures);
  exit(0);
      

}


