Beispiel #1
0
MS_PLUGIN_DECLARE ( void ) libmsisac_init() {
    char isac_version[64];
    isac_version[0] = 0;

    WebRtcSpl_Init();
    WebRtcIsacfix_version(isac_version);

    ms_filter_register ( &ms_isac_enc_desc );
    ms_filter_register ( &ms_isac_dec_desc );

    ms_message ( " libmsisac " VERSION " plugin loaded, iSAC codec version %s", isac_version );
}
Beispiel #2
0
MS_PLUGIN_DECLARE ( void ) libmswebrtc_init() {
#ifdef BUILD_ISAC
	char isac_version[64];
	isac_version[0] = 0;
#endif

	WebRtcSpl_Init();

#ifdef BUILD_ISAC
	WebRtcIsacfix_version(isac_version);
	ms_filter_register(&ms_isac_enc_desc);
	ms_filter_register(&ms_isac_dec_desc);
#endif
#ifdef BUILD_AEC
	ms_filter_register(&ms_webrtc_aec_desc);
#endif

	ms_message("libmswebrtc " VERSION " plugin loaded"
#ifdef BUILD_ISAC
	", iSAC codec version %s", isac_version
#endif
	);
}
Beispiel #3
0
int main(int argc, char* argv[])
{

  char inname[100], outname[100],  outbitsname[100], bottleneck_file[100];
  FILE *inp, *outp, *f_bn, *outbits;
  int endfile;

  int i, errtype, h = 0, k, packetLossPercent = 0;
  WebRtc_Word16 CodingMode;
  WebRtc_Word16 bottleneck;
  WebRtc_Word16 framesize = 30;           /* ms */
  int cur_framesmpls, err = 0, lostPackets = 0;

  /* Runtime statistics */
  double starttime, runtime, length_file;

  WebRtc_Word16 stream_len = 0;
  WebRtc_Word16 framecnt, declen = 0;
  WebRtc_Word16 shortdata[FRAMESAMPLES_10ms];
  WebRtc_Word16 decoded[MAX_FRAMESAMPLES];
  WebRtc_UWord16 streamdata[500];
  WebRtc_Word16 speechType[1];
  WebRtc_Word16 prevFrameSize = 1;
  WebRtc_Word16 rateBPS = 0;
  WebRtc_Word16 fixedFL = 0;
  WebRtc_Word16 payloadSize = 0;
  WebRtc_Word32 payloadRate = 0;
  int setControlBWE = 0;
  int readLoss;
  FILE  *plFile = NULL;

  char version_number[20];
  char tmpBit[5] = ".bit";

  double kbps;
  int totalbits =0;
  int totalsmpls =0;
#ifdef _DEBUG
  FILE *fy;
#endif
  WebRtc_Word16 testNum, testCE;

  FILE *fp_gns = NULL;
  int gns = 0;
  int cur_delay = 0;
  char gns_file[100];

  int nbTest = 0;
  WebRtc_Word16 lostFrame;
  float scale = (float)0.7;
  /* only one structure used for ISAC encoder */
  ISACFIX_MainStruct *ISAC_main_inst;

  /* For fault test 10, garbage data */
  FILE *seedfile;
  unsigned int random_seed = (unsigned int) time(NULL);//1196764538

  BottleNeckModel       BN_data;
  f_bn  = NULL;

#ifdef _DEBUG
  fy = fopen("bit_rate.dat", "w");
  fclose(fy);
  fy = fopen("bytes_frames.dat", "w");
  fclose(fy);
#endif

  readLoss = 0;
  packetLossPercent = 0;

  /* Handling wrong input arguments in the command line */
  if ((argc<3) || (argc>21))  {
    printf("\n\nWrong number of arguments or flag values.\n\n");

    printf("\n");
    WebRtcIsacfix_version(version_number);
    printf("iSAC version %s \n\n", version_number);

    printf("Usage:\n\n");
    printf("./kenny.exe [-F num][-I] bottleneck_value infile outfile \n\n");
    printf("with:\n");
    printf("[-I]             :if -I option is specified, the coder will use\n");
    printf("                  an instantaneous Bottleneck value. If not, it\n");
    printf("                  will be an adaptive Bottleneck value.\n\n");
    printf("bottleneck_value :the value of the bottleneck provided either\n");
    printf("                  as a fixed value (e.g. 25000) or\n");
    printf("                  read from a file (e.g. bottleneck.txt)\n\n");
    printf("[-INITRATE num]  :Set a new value for initial rate. Note! Only used"
           " in adaptive mode.\n\n");
    printf("[-FL num]        :Set (initial) frame length in msec. Valid length"
           " are 30 and 60 msec.\n\n");
    printf("[-FIXED_FL]      :Frame length will be fixed to initial value.\n\n");
    printf("[-MAX num]       :Set the limit for the payload size of iSAC"
           " in bytes. \n");
    printf("                  Minimum 100, maximum 400.\n\n");
    printf("[-MAXRATE num]   :Set the maxrate for iSAC in bits per second. \n");
    printf("                  Minimum 32000, maximum 53400.\n\n");
    printf("[-F num]         :if -F option is specified, the test function\n");
    printf("                  will run the iSAC API fault scenario specified"
           " by the\n");
    printf("                  supplied number.\n");
    printf("                  F 1 - Call encoder prior to init encoder call\n");
    printf("                  F 2 - Call decoder prior to init decoder call\n");
    printf("                  F 3 - Call decoder prior to encoder call\n");
    printf("                  F 4 - Call decoder with a too short coded"
           " sequence\n");
    printf("                  F 5 - Call decoder with a too long coded"
           " sequence\n");
    printf("                  F 6 - Call decoder with random bit stream\n");
    printf("                  F 7 - Call init encoder/decoder at random"
           " during a call\n");
    printf("                  F 8 - Call encoder/decoder without having"
           " allocated memory for \n");
    printf("                        encoder/decoder instance\n");
    printf("                  F 9 - Call decodeB without calling decodeA\n");
    printf("                  F 10 - Call decodeB with garbage data\n");
    printf("[-PL num]       : if -PL option is specified 0<num<100 will "
           "specify the\n");
    printf("                  percentage of packet loss\n\n");
    printf("[-G file]       : if -G option is specified the file given is"
           " a .gns file\n");
    printf("                  that represents a network profile\n\n");
    printf("[-NB num]       : if -NB option, use the narrowband interfaces\n");
    printf("                  num=1 => encode with narrowband encoder"
           " (infile is narrowband)\n");
    printf("                  num=2 => decode with narrowband decoder"
           " (outfile is narrowband)\n\n");
    printf("[-CE num]       : Test of APIs used by Conference Engine.\n");
    printf("                  CE 1 - createInternal, freeInternal,"
           " getNewBitstream \n");
    printf("                  CE 2 - transcode, getBWE \n");
    printf("                  CE 3 - getSendBWE, setSendBWE.  \n\n");
    printf("[-RTP_INIT num] : if -RTP_INIT option is specified num will be"
           " the initial\n");
    printf("                  value of the rtp sequence number.\n\n");
    printf("infile          : Normal speech input file\n\n");
    printf("outfile         : Speech output file\n\n");
    printf("Example usage   : \n\n");
    printf("./kenny.exe -I bottleneck.txt speechIn.pcm speechOut.pcm\n\n");
    exit(0);

  }

  /* Print version number */
  WebRtcIsacfix_version(version_number);
  printf("iSAC version %s \n\n", version_number);

  /* Loop over all command line arguments */
  CodingMode = 0;
  testNum = 0;
  testCE = 0;
  for (i = 1; i < argc-2;i++) {
    /* Instantaneous mode */
    if (!strcmp ("-I", argv[i])) {
      printf("\nInstantaneous BottleNeck\n");
      CodingMode = 1;
      i++;
    }

    /* Set (initial) bottleneck value */
    if (!strcmp ("-INITRATE", argv[i])) {
      rateBPS = atoi(argv[i + 1]);
      setControlBWE = 1;
      if ((rateBPS < 10000) || (rateBPS > 32000)) {
        printf("\n%d is not a initial rate. "
               "Valid values are in the range 10000 to 32000.\n", rateBPS);
        exit(0);
      }
      printf("\nNew initial rate: %d\n", rateBPS);
      i++;
    }

    /* Set (initial) framelength */
    if (!strcmp ("-FL", argv[i])) {
      framesize = atoi(argv[i + 1]);
      if ((framesize != 30) && (framesize != 60)) {
        printf("\n%d is not a valid frame length. "
               "Valid length are 30 and 60 msec.\n", framesize);
        exit(0);
      }
      printf("\nFrame Length: %d\n", framesize);
      i++;
    }

    /* Fixed frame length */
    if (!strcmp ("-FIXED_FL", argv[i])) {
      fixedFL = 1;
      setControlBWE = 1;
    }

    /* Set maximum allowed payload size in bytes */
    if (!strcmp ("-MAX", argv[i])) {
      payloadSize = atoi(argv[i + 1]);
      printf("Maximum Payload Size: %d\n", payloadSize);
      i++;
    }

    /* Set maximum rate in bytes */
    if (!strcmp ("-MAXRATE", argv[i])) {
      payloadRate = atoi(argv[i + 1]);
      printf("Maximum Rate in kbps: %d\n", payloadRate);
      i++;
    }

    /* Test of fault scenarious */
    if (!strcmp ("-F", argv[i])) {
      testNum = atoi(argv[i + 1]);
      printf("\nFault test: %d\n", testNum);
      if (testNum < 1 || testNum > 10) {
        printf("\n%d is not a valid Fault Scenario number."
               " Valid Fault Scenarios are numbered 1-10.\n", testNum);
        exit(0);
      }
      i++;
    }

    /* Packet loss test */
    if (!strcmp ("-PL", argv[i])) {
      if( isdigit( *argv[i+1] ) ) {
        packetLossPercent = atoi( argv[i+1] );
        if( (packetLossPercent < 0) | (packetLossPercent > 100) ) {
          printf( "\nInvalid packet loss perentage \n" );
          exit( 0 );
        }
        if( packetLossPercent > 0 ) {
          printf( "\nSimulating %d %% of independent packet loss\n",
                  packetLossPercent );
        } else {
          printf( "\nNo Packet Loss Is Simulated \n" );
        }
        readLoss = 0;
      } else {
        readLoss = 1;
        plFile = fopen( argv[i+1], "rb" );
        if( plFile == NULL ) {
          printf( "\n couldn't open the frameloss file: %s\n", argv[i+1] );
          exit( 0 );
        }
        printf( "\nSimulating packet loss through the given "
                "channel file: %s\n", argv[i+1] );
      }
      i++;
    }

    /* Random packetlosses */
    if (!strcmp ("-rnd", argv[i])) {
      srand(time(NULL) );
      printf( "\n Random pattern in lossed packets \n" );
    }

    /* Use gns file */
    if (!strcmp ("-G", argv[i])) {
      sscanf(argv[i + 1], "%s", gns_file);
      fp_gns = fopen(gns_file, "rb");
      if (fp_gns  == NULL) {
        printf("Cannot read file %s.\n", gns_file);
        exit(0);
      }
      gns = 1;
      i++;
    }

    /* Run Narrowband interfaces (either encoder or decoder) */
    if (!strcmp ("-NB", argv[i])) {
      nbTest = atoi(argv[i + 1]);
      i++;
    }

    /* Run Conference Engine APIs */
    if (!strcmp ("-CE", argv[i])) {
      testCE = atoi(argv[i + 1]);
      if (testCE==1 || testCE==2) {
        i++;
        scale = (float)atof( argv[i+1] );
      } else if (testCE < 1 || testCE > 3) {
        printf("\n%d is not a valid CE-test number, valid Fault "
               "Scenarios are numbered 1-3\n", testCE);
        exit(0);
      }
      i++;
    }

    /* Set initial RTP number */
    if (!strcmp ("-RTP_INIT", argv[i])) {
      i++;
    }
  }

  /* Get Bottleneck value                                                   */
  /* Gns files and bottleneck should not and can not be used simultaneously */
  bottleneck = atoi(argv[CodingMode+1]);
  if (bottleneck == 0 && gns == 0) {
    sscanf(argv[CodingMode+1], "%s", bottleneck_file);
    f_bn = fopen(bottleneck_file, "rb");
    if (f_bn  == NULL) {
      printf("No value provided for BottleNeck and cannot read file %s\n", bottleneck_file);
      exit(0);
    } else {
      int aux_var;
      printf("reading bottleneck rates from file %s\n\n",bottleneck_file);
      if (fscanf(f_bn, "%d", &aux_var) == EOF) {
        /* Set pointer to beginning of file */
        fseek(f_bn, 0L, SEEK_SET);
        if (fscanf(f_bn, "%d", &aux_var) == EOF) {
          exit(0);
        }
      }
      bottleneck = (WebRtc_Word16)aux_var;
      /* Bottleneck is a cosine function
       * Matlab code for writing the bottleneck file:
       * BottleNeck_10ms = 20e3 + 10e3 * cos((0:5999)/5999*2*pi);
       * fid = fopen('bottleneck.txt', 'wb');
       * fprintf(fid, '%d\n', BottleNeck_10ms); fclose(fid);
       */
    }
  } else {
    f_bn = NULL;
    printf("\nfixed bottleneck rate of %d bits/s\n\n", bottleneck);
  }

  if (CodingMode == 0) {
    printf("\nAdaptive BottleNeck\n");
  }

  /* Get Input and Output files */
  sscanf(argv[argc-2], "%s", inname);
  sscanf(argv[argc-1], "%s", outname);

  /* Add '.bit' to output bitstream file */
  while ((int)outname[h] != 0) {
    outbitsname[h] = outname[h];
    h++;
  }
  for (k=0; k<5; k++) {
    outbitsname[h] = tmpBit[k];
    h++;
  }
  if ((inp = fopen(inname,"rb")) == NULL) {
    printf("  iSAC: Cannot read file %s\n", inname);
    exit(1);
  }
  if ((outp = fopen(outname,"wb")) == NULL) {
    printf("  iSAC: Cannot write file %s\n", outname);
    exit(1);
  }

  if ((outbits = fopen(outbitsname,"wb")) == NULL) {
    printf("  iSAC: Cannot write file %s\n", outbitsname);
    exit(1);
  }
  printf("\nInput:%s\nOutput:%s\n\n", inname, outname);

  /* Error test number 10, garbage data */
  if (testNum == 10) {
    /* Test to run decoder with garbage data */
    srand(random_seed);

    if ( (seedfile = fopen(SEED_FILE, "a+t") ) == NULL ) {
      printf("Error: Could not open file %s\n", SEED_FILE);
    }
    else {
      fprintf(seedfile, "%u\n", random_seed);
      fclose(seedfile);
    }
  }

  /* Runtime statistics */
  starttime = clock()/(double)CLOCKS_PER_SEC;

  /* Initialize the ISAC and BN structs */
  if (testNum != 8)
  {
    if(1){
      err =WebRtcIsacfix_Create(&ISAC_main_inst);
    }else{
      /* Test the Assign functions */
      int sss;
      void *ppp;
      err =WebRtcIsacfix_AssignSize(&sss);
      ppp=malloc(sss);
      err =WebRtcIsacfix_Assign(&ISAC_main_inst,ppp);
    }
    /* Error check */
    if (err < 0) {
      printf("\n\n Error in create.\n\n");
    }
    if (testCE == 1) {
      err = WebRtcIsacfix_CreateInternal(ISAC_main_inst);
      /* Error check */
      if (err < 0) {
        printf("\n\n Error in createInternal.\n\n");
      }
    }
  }

  /* Init of bandwidth data */
  BN_data.send_time     = 0;
  BN_data.arrival_time  = 0;
  BN_data.sample_count  = 0;
  BN_data.rtp_number    = 0;

  /* Initialize encoder and decoder */
  framecnt= 0;
  endfile = 0;
  if (testNum != 1) {
    WebRtcIsacfix_EncoderInit(ISAC_main_inst, CodingMode);
  }
  if (testNum != 2) {
    WebRtcIsacfix_DecoderInit(ISAC_main_inst);
  }

  if (CodingMode == 1) {
    err = WebRtcIsacfix_Control(ISAC_main_inst, bottleneck, framesize);
    if (err < 0) {
      /* exit if returned with error */
      errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
      printf("\n\n Error in control: %d.\n\n", errtype);
    }
  } else if(setControlBWE == 1) {
    err = WebRtcIsacfix_ControlBwe(ISAC_main_inst, rateBPS, framesize, fixedFL);
  }

  if (payloadSize != 0) {
    err = WebRtcIsacfix_SetMaxPayloadSize(ISAC_main_inst, payloadSize);
    if (err < 0) {
      /* exit if returned with error */
      errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
      printf("\n\n Error in SetMaxPayloadSize: %d.\n\n", errtype);
      exit(EXIT_FAILURE);
    }
  }
  if (payloadRate != 0) {
    err = WebRtcIsacfix_SetMaxRate(ISAC_main_inst, payloadRate);
    if (err < 0) {
      /* exit if returned with error */
      errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
      printf("\n\n Error in SetMaxRateInBytes: %d.\n\n", errtype);
      exit(EXIT_FAILURE);
    }
  }

  *speechType = 1;


  while (endfile == 0) {

    if(testNum == 7 && (rand()%2 == 0)) {
      err = WebRtcIsacfix_EncoderInit(ISAC_main_inst, CodingMode);
      /* Error check */
      if (err < 0) {
        errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
        printf("\n\n Error in encoderinit: %d.\n\n", errtype);
      }

      err = WebRtcIsacfix_DecoderInit(ISAC_main_inst);
      /* Error check */
      if (err < 0) {
        errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
        printf("\n\n Error in decoderinit: %d.\n\n", errtype);
      }
    }


    cur_framesmpls = 0;
    while (1) {
      /* Read 10 ms speech block */
      if (nbTest != 1) {
        endfile = readframe(shortdata, inp, FRAMESAMPLES_10ms);
      } else {
        endfile = readframe(shortdata, inp, (FRAMESAMPLES_10ms/2));
      }

      if (testNum == 7) {
        srand(time(NULL));
      }

      /* iSAC encoding */
      if (!(testNum == 3 && framecnt == 0)) {
        if (nbTest != 1) {
          short bwe;

          /* Encode */
          stream_len = WebRtcIsacfix_Encode(ISAC_main_inst,
                                            shortdata,
                                            (WebRtc_Word16*)streamdata);

          /* If packet is ready, and CE testing, call the different API functions
             from the internal API.                       */
          if (stream_len>0) {
            if (testCE == 1) {
              err = WebRtcIsacfix_ReadBwIndex((WebRtc_Word16*)streamdata, &bwe);
              stream_len = WebRtcIsacfix_GetNewBitStream(
                  ISAC_main_inst,
                  bwe,
                  scale,
                  (WebRtc_Word16*)streamdata);
            } else if (testCE == 2) {
              /* transcode function not supported */
            } else if (testCE == 3) {
              /* Only for Function testing. The functions should normally
                 not be used in this way                                      */

              err = WebRtcIsacfix_GetDownLinkBwIndex(ISAC_main_inst, &bwe);
              /* Error Check */
              if (err < 0) {
                errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
                printf("\nError in getSendBWE: %d.\n", errtype);
              }

              err = WebRtcIsacfix_UpdateUplinkBw(ISAC_main_inst, bwe);
              /* Error Check */
              if (err < 0) {
                errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
                printf("\nError in setBWE: %d.\n", errtype);
              }

            }
          }
        } else {
#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
          stream_len = WebRtcIsacfix_EncodeNb(ISAC_main_inst,
                                              shortdata,
                                              streamdata);
#else
          stream_len = -1;
#endif
        }
      }
      else
      {
        break;
      }

      if (stream_len < 0 || err < 0) {
        /* exit if returned with error */
        errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
        printf("\nError in encoder: %d.\n", errtype);
      } else {
        if (fwrite(streamdata, sizeof(char),
                   stream_len, outbits) != (size_t)stream_len) {
          return -1;
        }
      }

      cur_framesmpls += FRAMESAMPLES_10ms;

      /* read next bottleneck rate */
      if (f_bn != NULL) {
        int aux_var;
        if (fscanf(f_bn, "%d", &aux_var) == EOF) {
          /* Set pointer to beginning of file */
          fseek(f_bn, 0L, SEEK_SET);
          if (fscanf(f_bn, "%d", &aux_var) == EOF) {
            exit(0);
          }
        }
        bottleneck = (WebRtc_Word16)aux_var;
        if (CodingMode == 1) {
          WebRtcIsacfix_Control(ISAC_main_inst, bottleneck, framesize);
        }
      }

      /* exit encoder loop if the encoder returned a bitstream */
      if (stream_len != 0) break;
    }

    /* make coded sequence to short be inreasing */
    /* the length the decoder expects */
    if (testNum == 4) {
      stream_len += 10;
    }

    /* make coded sequence to long be decreasing */
    /* the length the decoder expects */
    if (testNum == 5) {
      stream_len -= 10;
    }

    if (testNum == 6) {
      srand(time(NULL));
      for (i = 0; i < stream_len; i++ ) {
        streamdata[i] = rand();
      }
    }

    /* set pointer to beginning of file */
    if (fp_gns != NULL) {
      if (fscanf(fp_gns, "%d", &cur_delay) == EOF) {
        fseek(fp_gns, 0L, SEEK_SET);
        if (fscanf(fp_gns, "%d", &cur_delay) == EOF) {
          exit(0);
        }
      }
    }

    /* simulate packet handling through NetEq and the modem */
    if (!(testNum == 3 && framecnt == 0)) {
      if (gns == 0) {
        get_arrival_time(cur_framesmpls, stream_len, bottleneck,
                         &BN_data);
      } else {
        get_arrival_time2(cur_framesmpls, cur_delay, &BN_data);
      }
    }

    /* packet not dropped */
    if (cur_delay != -1) {

      /* Error test number 10, garbage data */
      if (testNum == 10) {
        for ( i = 0; i < stream_len; i++) {
          streamdata[i] = (short) (streamdata[i] + (short) rand());
        }
      }

      if (testNum != 9) {
        err = WebRtcIsacfix_UpdateBwEstimate(ISAC_main_inst,
                                             streamdata,
                                             stream_len,
                                             BN_data.rtp_number,
                                             BN_data.send_time,
                                             BN_data.arrival_time);

        if (err < 0) {
          /* exit if returned with error */
          errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
          printf("\nError in decoder: %d.\n", errtype);
        }
      }
#ifdef _DEBUG
      fprintf(stderr,"  \rframe = %7d", framecnt);
#endif

      if( readLoss == 1 ) {
        if( fread( &lostFrame, sizeof(WebRtc_Word16), 1, plFile ) != 1 ) {
          rewind( plFile );
        }
        lostFrame = !lostFrame;
      } else {
        lostFrame = (rand()%100 < packetLossPercent);
      }



      /* iSAC decoding */
      if( lostFrame && framecnt >  0) {
        if (nbTest !=2) {
          declen = WebRtcIsacfix_DecodePlc(ISAC_main_inst,
                                           decoded, prevFrameSize );
        } else {
#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
          declen = WebRtcIsacfix_DecodePlcNb(ISAC_main_inst, decoded,
                                             prevFrameSize );
#else
          declen = -1;
#endif
        }
        lostPackets++;
      } else {
        if (nbTest !=2 ) {
          short FL;
          /* Call getFramelen, only used here for function test */
          err = WebRtcIsacfix_ReadFrameLen((WebRtc_Word16*)streamdata, &FL);
          declen = WebRtcIsacfix_Decode( ISAC_main_inst, streamdata, stream_len,
                                         decoded, speechType );
          /* Error check */
          if (err<0 || declen<0 || FL!=declen) {
            errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
            printf("\nError in decode_B/or getFrameLen: %d.\n", errtype);
          }
          prevFrameSize = declen/480;

        } else {
#ifdef WEBRTC_ISAC_FIX_NB_CALLS_ENABLED
          declen = WebRtcIsacfix_DecodeNb( ISAC_main_inst, streamdata,
                                           stream_len, decoded, speechType );
#else
          declen = -1;
#endif
          prevFrameSize = declen/240;
        }
      }

      if (declen <= 0) {
        /* exit if returned with error */
        errtype=WebRtcIsacfix_GetErrorCode(ISAC_main_inst);
        printf("\nError in decoder: %d.\n", errtype);
      }

      /* Write decoded speech frame to file */
      if (fwrite(decoded, sizeof(WebRtc_Word16),
                 declen, outp) != (size_t)declen) {
        return -1;
      }
      //   fprintf( ratefile, "%f \n", stream_len / ( ((double)declen)/
      // ((double)FS) ) * 8 );
    } else {
      lostPackets++;
    }
    framecnt++;

    totalsmpls += declen;
    totalbits += 8 * stream_len;
    kbps = ((double) FS) / ((double) cur_framesmpls) * 8.0 *
        stream_len / 1000.0;// kbits/s

    /* Error test number 10, garbage data */
    if (testNum == 10) {
      if ( (seedfile = fopen(SEED_FILE, "a+t") ) == NULL ) {
        printf( "Error: Could not open file %s\n", SEED_FILE);
      }
      else {
        fprintf(seedfile, "ok\n\n");
        fclose(seedfile);
      }
    }

#ifdef _DEBUG

    fy = fopen("bit_rate.dat", "a");
    fprintf(fy, "Frame %i = %0.14f\n", framecnt, kbps);
    fclose(fy);

#endif /* _DEBUG */

  }
  printf("\nLost Frames %d ~ %4.1f%%\n", lostPackets,
         (double)lostPackets/(double)framecnt*100.0 );
  printf("\n\ntotal bits                          = %d bits", totalbits);
  printf("\nmeasured average bitrate              = %0.3f kbits/s",
         (double)totalbits *(FS/1000) / totalsmpls);
  printf("\n");

#ifdef _DEBUG
  /* fprintf(stderr,"\n\ntotal bits    = %d bits", totalbits);
     fprintf(stderr,"\nmeasured average bitrate  = %0.3f kbits/s",
     (double)totalbits *(FS/1000) / totalsmpls);
     fprintf(stderr,"\n");
  */
#endif /* _DEBUG */

  /* Runtime statistics */


  runtime = (double)(((double)clock()/(double)CLOCKS_PER_SEC)-starttime);
  length_file = ((double)framecnt*(double)declen/FS);
  printf("\n\nLength of speech file: %.1f s\n", length_file);
  printf("Time to run iSAC:      %.2f s (%.2f %% of realtime)\n\n",
         runtime, (100*runtime/length_file));
  printf("\n\n_______________________________________________\n");

  fclose(inp);
  fclose(outp);
  fclose(outbits);

  if ( testCE == 1) {
    WebRtcIsacfix_FreeInternal(ISAC_main_inst);
  }
  WebRtcIsacfix_Free(ISAC_main_inst);
  return 0;
}
int main(int argc, char* argv[]) {
    char inname[50], outname[50], bottleneck_file[50], bitfilename[60],
         bitending[10] = "_bits.pcm";
    FILE* inp, *outp, *f_bn, *bitsp;
    int framecnt, endfile;

    int i, j, errtype, plc = 0;
    int16_t CodingMode;
    int16_t bottleneck;

    int framesize = 30; /* ms */
    // int framesize = 60; /* To invoke cisco complexity case at frame 2252 */

    int cur_framesmpls, err;

    /* Runtime statistics */
    double starttime;
    double runtime;
    double length_file;

    size_t stream_len = 0;
    int declen;

    int16_t shortdata[FRAMESAMPLES_10ms];
    int16_t decoded[MAX_FRAMESAMPLES];
    uint16_t streamdata[600];
    int16_t speechType[1];

    // int16_t* iSACstruct;

    char version_number[20];
    int mode = -1, tmp, nbTest = 0; /*,sss;*/

#if !defined(NDEBUG)
    FILE* fy;
    double kbps;
    size_t totalbits = 0;
    int totalsmpls = 0;
#endif

    /* only one structure used for ISAC encoder */
    ISAC_MainStruct* ISAC_main_inst;
    ISACFIX_MainStruct* ISACFIX_main_inst;

    BottleNeckModel BN_data;
    f_bn = NULL;

#if !defined(NDEBUG)
    fy = fopen("bit_rate.dat", "w");
    fclose(fy);
    fy = fopen("bytes_frames.dat", "w");
    fclose(fy);
#endif

    // histfile = fopen("histo.dat", "ab");
    // ratefile = fopen("rates.dat", "ab");

    /* handling wrong input arguments in the command line */
    if ((argc < 6) || (argc > 10)) {
        printf("\n\nWrong number of arguments or flag values.\n\n");

        printf("\n");
        WebRtcIsacfix_version(version_number);
        printf("iSAC version %s \n\n", version_number);

        printf("Usage:\n\n");
        printf("./kenny.exe [-I] bottleneck_value infile outfile \n\n");
        printf("with:\n");

        printf("[-I]            : If -I option is specified, the coder will use\n");
        printf("                  an instantaneous Bottleneck value. If not, it\n");
        printf("                  will be an adaptive Bottleneck value.\n\n");
        printf("bottleneck_value: The value of the bottleneck provided either\n");
        printf("                  as a fixed value (e.g. 25000) or\n");
        printf("                  read from a file (e.g. bottleneck.txt)\n\n");
        printf("[-m] mode       : Mode (encoder - decoder):\n");
        printf("                    0 - float - float\n");
        printf("                    1 - float - fix\n");
        printf("                    2 - fix - float\n");
        printf("                    3 - fix - fix\n\n");
        printf("[-PLC]          : Test PLC packetlosses\n\n");
        printf("[-NB] num       : Test NB interfaces:\n");
        printf("                    1 - encNB\n");
        printf("                    2 - decNB\n\n");
        printf("infile          : Normal speech input file\n\n");
        printf("outfile         : Speech output file\n\n");
        printf("Example usage:\n\n");
        printf("./kenny.exe -I bottleneck.txt -m 1 speechIn.pcm speechOut.pcm\n\n");
        exit(0);
    }

    printf("--------------------START---------------------\n\n");
    WebRtcIsac_version(version_number);
    printf("iSAC FLOAT version %s \n", version_number);
    WebRtcIsacfix_version(version_number);
    printf("iSAC FIX version   %s \n\n", version_number);

    CodingMode = 0;
    tmp = 1;
    for (i = 1; i < argc; i++) {
        if (!strcmp("-I", argv[i])) {
            printf("\nInstantaneous BottleNeck\n");
            CodingMode = 1;
            i++;
            tmp = 0;
        }

        if (!strcmp("-m", argv[i])) {
            mode = atoi(argv[i + 1]);
            i++;
        }

        if (!strcmp("-PLC", argv[i])) {
            plc = 1;
        }

        if (!strcmp("-NB", argv[i])) {
            nbTest = atoi(argv[i + 1]);
            i++;
        }
    }

    if (mode < 0) {
        printf("\nError! Mode must be set: -m 0 \n");
        exit(0);
    }

    if (CodingMode == 0) {
        printf("\nAdaptive BottleNeck\n");
    }

    /* Get Bottleneck value */
    bottleneck = atoi(argv[2 - tmp]);
    if (bottleneck == 0) {
        sscanf(argv[2 - tmp], "%s", bottleneck_file);
        f_bn = fopen(bottleneck_file, "rb");
        if (f_bn == NULL) {
            printf("No value provided for BottleNeck and cannot read file %s.\n",
                   bottleneck_file);
            exit(0);
        } else {
            printf("reading bottleneck rates from file %s\n\n", bottleneck_file);
            if (fscanf(f_bn, "%d", &bottleneck) == EOF) {
                /* Set pointer to beginning of file */
                fseek(f_bn, 0L, SEEK_SET);
                fscanf(f_bn, "%d", &bottleneck);
            }

            /* Bottleneck is a cosine function
             * Matlab code for writing the bottleneck file:
             * BottleNeck_10ms = 20e3 + 10e3 * cos((0:5999)/5999*2*pi);
             * fid = fopen('bottleneck.txt', 'wb');
             * fprintf(fid, '%d\n', BottleNeck_10ms); fclose(fid);
             */
        }
    } else {
        printf("\nfixed bottleneck rate of %d bits/s\n\n", bottleneck);
    }

    /* Get Input and Output files */
    sscanf(argv[argc - 2], "%s", inname);
    sscanf(argv[argc - 1], "%s", outname);

    if ((inp = fopen(inname, "rb")) == NULL) {
        printf("  iSAC: Cannot read file %s.\n", inname);
        exit(1);
    }
    if ((outp = fopen(outname, "wb")) == NULL) {
        printf("  iSAC: Cannot write file %s.\n", outname);
        exit(1);
    }
    printf("\nInput:%s\nOutput:%s\n", inname, outname);

    i = 0;
    while (outname[i] != '\0') {
        bitfilename[i] = outname[i];
        i++;
    }
    i -= 4;
    for (j = 0; j < 9; j++, i++)
        bitfilename[i] = bitending[j];
    bitfilename[i] = '\0';
    if ((bitsp = fopen(bitfilename, "wb")) == NULL) {
        printf("  iSAC: Cannot read file %s.\n", bitfilename);
        exit(1);
    }
    printf("Bitstream:%s\n\n", bitfilename);

    starttime = clock() / (double)CLOCKS_PER_SEC; /* Runtime statistics */

    /* Initialize the ISAC and BN structs */
    WebRtcIsac_create(&ISAC_main_inst);
    WebRtcIsacfix_Create(&ISACFIX_main_inst);

    BN_data.send_time = 0;
    BN_data.arrival_time = 0;
    BN_data.sample_count = 0;
    BN_data.rtp_number = 0;

    /* Initialize encoder and decoder */
    framecnt = 0;
    endfile = 0;

    if (mode == 0) { /* Encode using FLOAT, decode using FLOAT */

        printf("Coding mode: Encode using FLOAT, decode using FLOAT \n\n");

        /* Init iSAC FLOAT */
        WebRtcIsac_EncoderInit(ISAC_main_inst, CodingMode);
        WebRtcIsac_DecoderInit(ISAC_main_inst);
        if (CodingMode == 1) {
            err = WebRtcIsac_Control(ISAC_main_inst, bottleneck, framesize);
            if (err < 0) {
                /* exit if returned with error */
                errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
                printf("\n\n Error in initialization: %d.\n\n", errtype);
                // exit(EXIT_FAILURE);
            }
        }

    } else if (mode == 1) { /* Encode using FLOAT, decode using FIX */

        printf("Coding mode: Encode using FLOAT, decode using FIX \n\n");

        /* Init iSAC FLOAT */
        WebRtcIsac_EncoderInit(ISAC_main_inst, CodingMode);
        WebRtcIsac_DecoderInit(ISAC_main_inst);
        if (CodingMode == 1) {
            err = WebRtcIsac_Control(ISAC_main_inst, bottleneck, framesize);
            if (err < 0) {
                /* exit if returned with error */
                errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
                printf("\n\n Error in initialization: %d.\n\n", errtype);
                // exit(EXIT_FAILURE);
            }
        }

        /* Init iSAC FIX */
        WebRtcIsacfix_EncoderInit(ISACFIX_main_inst, CodingMode);
        WebRtcIsacfix_DecoderInit(ISACFIX_main_inst);
        if (CodingMode == 1) {
            err = WebRtcIsacfix_Control(ISACFIX_main_inst, bottleneck, framesize);
            if (err < 0) {
                /* exit if returned with error */
                errtype = WebRtcIsacfix_GetErrorCode(ISACFIX_main_inst);
                printf("\n\n Error in initialization: %d.\n\n", errtype);
                // exit(EXIT_FAILURE);
            }
        }
    } else if (mode == 2) { /* Encode using FIX, decode using FLOAT */

        printf("Coding mode: Encode using FIX, decode using FLOAT \n\n");

        /* Init iSAC FLOAT */
        WebRtcIsac_EncoderInit(ISAC_main_inst, CodingMode);
        WebRtcIsac_DecoderInit(ISAC_main_inst);
        if (CodingMode == 1) {
            err = WebRtcIsac_Control(ISAC_main_inst, bottleneck, framesize);
            if (err < 0) {
                /* exit if returned with error */
                errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
                printf("\n\n Error in initialization: %d.\n\n", errtype);
                // exit(EXIT_FAILURE);
            }
        }

        /* Init iSAC FIX */
        WebRtcIsacfix_EncoderInit(ISACFIX_main_inst, CodingMode);
        WebRtcIsacfix_DecoderInit(ISACFIX_main_inst);
        if (CodingMode == 1) {
            err = WebRtcIsacfix_Control(ISACFIX_main_inst, bottleneck, framesize);
            if (err < 0) {
                /* exit if returned with error */
                errtype = WebRtcIsacfix_GetErrorCode(ISACFIX_main_inst);
                printf("\n\n Error in initialization: %d.\n\n", errtype);
                // exit(EXIT_FAILURE);
            }
        }
    } else if (mode == 3) {
        printf("Coding mode: Encode using FIX, decode using FIX \n\n");

        WebRtcIsacfix_EncoderInit(ISACFIX_main_inst, CodingMode);
        WebRtcIsacfix_DecoderInit(ISACFIX_main_inst);
        if (CodingMode == 1) {
            err = WebRtcIsacfix_Control(ISACFIX_main_inst, bottleneck, framesize);
            if (err < 0) {
                /* exit if returned with error */
                errtype = WebRtcIsacfix_GetErrorCode(ISACFIX_main_inst);
                printf("\n\n Error in initialization: %d.\n\n", errtype);
                // exit(EXIT_FAILURE);
            }
        }

    } else
        printf("Mode must be value between 0 and 3\n");
    *speechType = 1;

//#define BI_TEST 1
#ifdef BI_TEST
    err = WebRtcIsacfix_SetMaxPayloadSize(ISACFIX_main_inst, 300);
    if (err < 0) {
        /* exit if returned with error */
        errtype = WebRtcIsacfix_GetErrorCode(ISACFIX_main_inst);
        printf("\n\n Error in setMaxPayloadSize: %d.\n\n", errtype);
        fclose(inp);
        fclose(outp);
        fclose(bitsp);
        return (EXIT_FAILURE);
    }
#endif

    while (endfile == 0) {
        cur_framesmpls = 0;
        while (1) {
            int stream_len_int;

            /* Read 10 ms speech block */
            if (nbTest != 1)
                endfile = readframe(shortdata, inp, FRAMESAMPLES_10ms);
            else
                endfile = readframe(shortdata, inp, (FRAMESAMPLES_10ms / 2));

            /* iSAC encoding */

            if (mode == 0 || mode == 1) {
                stream_len_int =
                    WebRtcIsac_Encode(ISAC_main_inst, shortdata, (uint8_t*)streamdata);
                if (stream_len_int < 0) {
                    /* exit if returned with error */
                    errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
                    printf("\n\nError in encoder: %d.\n\n", errtype);
                    // exit(EXIT_FAILURE);
                }
            } else if (mode == 2 || mode == 3) {
                /* iSAC encoding */
                if (nbTest != 1) {
                    stream_len_int = WebRtcIsacfix_Encode(ISACFIX_main_inst, shortdata,
                                                          (uint8_t*)streamdata);
                } else {
                    stream_len_int =
                        WebRtcIsacfix_EncodeNb(ISACFIX_main_inst, shortdata, streamdata);
                }

                if (stream_len_int < 0) {
                    /* exit if returned with error */
                    errtype = WebRtcIsacfix_GetErrorCode(ISACFIX_main_inst);
                    printf("\n\nError in encoder: %d.\n\n", errtype);
                    // exit(EXIT_FAILURE);
                }
            }
            stream_len = (size_t)stream_len_int;

            cur_framesmpls += FRAMESAMPLES_10ms;

            /* read next bottleneck rate */
            if (f_bn != NULL) {
                if (fscanf(f_bn, "%d", &bottleneck) == EOF) {
                    /* Set pointer to beginning of file */
                    fseek(f_bn, 0L, SEEK_SET);
                    fscanf(f_bn, "%d", &bottleneck);
                }
                if (CodingMode == 1) {
                    if (mode == 0 || mode == 1)
                        WebRtcIsac_Control(ISAC_main_inst, bottleneck, framesize);
                    else if (mode == 2 || mode == 3)
                        WebRtcIsacfix_Control(ISACFIX_main_inst, bottleneck, framesize);
                }
            }

            /* exit encoder loop if the encoder returned a bitstream */
            if (stream_len != 0)
                break;
        }

        fwrite(streamdata, 1, stream_len, bitsp); /* NOTE! Writes bytes to file */

        /* simulate packet handling through NetEq and the modem */
        get_arrival_time(cur_framesmpls, stream_len, bottleneck, &BN_data);
        //*****************************
        if (1) {
            if (mode == 0) {
                err = WebRtcIsac_UpdateBwEstimate(ISAC_main_inst, streamdata,
                                                  stream_len, BN_data.rtp_number,
                                                  BN_data.arrival_time);

                if (err < 0) {
                    /* exit if returned with error */
                    errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
                    printf("\n\nError in decoder: %d.\n\n", errtype);
                    // exit(EXIT_FAILURE);
                }
                /* iSAC decoding */
                declen = WebRtcIsac_Decode(ISAC_main_inst, streamdata, stream_len,
                                           decoded, speechType);
                if (declen <= 0) {
                    /* exit if returned with error */
                    errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
                    printf("\n\nError in decoder: %d.\n\n", errtype);
                    // exit(EXIT_FAILURE);
                }
            } else if (mode == 1) {
                err = WebRtcIsac_UpdateBwEstimate(ISAC_main_inst, streamdata,
                                                  stream_len, BN_data.rtp_number,
                                                  BN_data.arrival_time);
                err = WebRtcIsacfix_UpdateBwEstimate1(ISACFIX_main_inst, streamdata,
                                                      stream_len, BN_data.rtp_number,
                                                      BN_data.arrival_time);
                if (err < 0) {
                    /* exit if returned with error */
                    errtype = WebRtcIsacfix_GetErrorCode(ISACFIX_main_inst);
                    printf("\n\nError in decoder: %d.\n\n", errtype);
                    // exit(EXIT_FAILURE);
                }

                declen = WebRtcIsac_Decode(ISAC_main_inst, streamdata, stream_len,
                                           decoded, speechType);

                /* iSAC decoding */
                if (plc && (framecnt + 1) % 10 == 0) {
                    if (nbTest != 2) {
                        declen =
                            (int)WebRtcIsacfix_DecodePlc(ISACFIX_main_inst, decoded, 1);
                    } else {
                        declen =
                            (int)WebRtcIsacfix_DecodePlcNb(ISACFIX_main_inst, decoded, 1);
                    }
                } else {
                    if (nbTest != 2)
                        declen = WebRtcIsacfix_Decode(ISACFIX_main_inst, streamdata,
                                                      stream_len, decoded, speechType);
                    else
                        declen = WebRtcIsacfix_DecodeNb(ISACFIX_main_inst, streamdata,
                                                        stream_len, decoded, speechType);
                }

                if (declen <= 0) {
                    /* exit if returned with error */
                    errtype = WebRtcIsacfix_GetErrorCode(ISACFIX_main_inst);
                    printf("\n\nError in decoder: %d.\n\n", errtype);
                    // exit(EXIT_FAILURE);
                }
            } else if (mode == 2) {
                err = WebRtcIsacfix_UpdateBwEstimate1(ISACFIX_main_inst, streamdata,
                                                      stream_len, BN_data.rtp_number,
                                                      BN_data.arrival_time);

                err = WebRtcIsac_UpdateBwEstimate(ISAC_main_inst, streamdata,
                                                  stream_len, BN_data.rtp_number,
                                                  BN_data.arrival_time);

                if (err < 0) {
                    /* exit if returned with error */
                    errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
                    printf("\n\nError in decoder: %d.\n\n", errtype);
                    // exit(EXIT_FAILURE);
                }
                /* iSAC decoding */
                declen = WebRtcIsac_Decode(ISAC_main_inst, streamdata, stream_len,
                                           decoded, speechType);
                if (declen <= 0) {
                    /* exit if returned with error */
                    errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
                    printf("\n\nError in decoder: %d.\n\n", errtype);
                    // exit(EXIT_FAILURE);
                }
            } else if (mode == 3) {
                err = WebRtcIsacfix_UpdateBwEstimate(
                          ISACFIX_main_inst, streamdata, stream_len, BN_data.rtp_number,
                          BN_data.send_time, BN_data.arrival_time);

                if (err < 0) {
                    /* exit if returned with error */
                    errtype = WebRtcIsacfix_GetErrorCode(ISACFIX_main_inst);
                    printf("\n\nError in decoder: %d.\n\n", errtype);
                    // exit(EXIT_FAILURE);
                }
                /* iSAC decoding */

                if (plc && (framecnt + 1) % 10 == 0) {
                    if (nbTest != 2) {
                        declen =
                            (int)WebRtcIsacfix_DecodePlc(ISACFIX_main_inst, decoded, 1);
                    } else {
                        declen =
                            (int)WebRtcIsacfix_DecodePlcNb(ISACFIX_main_inst, decoded, 1);
                    }
                } else {
                    if (nbTest != 2) {
                        declen = WebRtcIsacfix_Decode(ISACFIX_main_inst, streamdata,
                                                      stream_len, decoded, speechType);
                    } else {
                        declen = WebRtcIsacfix_DecodeNb(ISACFIX_main_inst, streamdata,
                                                        stream_len, decoded, speechType);
                    }
                }
                if (declen <= 0) {
                    /* exit if returned with error */
                    errtype = WebRtcIsacfix_GetErrorCode(ISACFIX_main_inst);
                    printf("\n\nError in decoder: %d.\n\n", errtype);
                    // exit(EXIT_FAILURE);
                }
            }

            /* Write decoded speech frame to file */
            fwrite(decoded, sizeof(int16_t), declen, outp);
        }

        fprintf(stderr, "  \rframe = %d", framecnt);
        framecnt++;

#if !defined(NDEBUG)

        totalsmpls += declen;
        totalbits += 8 * stream_len;
        kbps = (double)FS / (double)cur_framesmpls * 8.0 * stream_len / 1000.0;
        fy = fopen("bit_rate.dat", "a");
        fprintf(fy, "Frame %i = %0.14f\n", framecnt, kbps);
        fclose(fy);

#endif
    }

#if !defined(NDEBUG)
    printf("\n\ntotal bits               = %" PRIuS " bits", totalbits);
    printf("\nmeasured average bitrate = %0.3f kbits/s",
           (double)totalbits * (FS / 1000) / totalsmpls);
    printf("\n");
#endif

    /* Runtime statistics */
    runtime = (double)(clock() / (double)CLOCKS_PER_SEC - starttime);
    length_file = ((double)framecnt * (double)declen / FS);
    printf("\n\nLength of speech file: %.1f s\n", length_file);
    printf("Time to run iSAC:      %.2f s (%.2f %% of realtime)\n\n", runtime,
           (100 * runtime / length_file));
    printf("---------------------END----------------------\n");

    fclose(inp);
    fclose(outp);

    WebRtcIsac_Free(ISAC_main_inst);
    WebRtcIsacfix_Free(ISACFIX_main_inst);

    // fclose(histfile);
    // fclose(ratefile);

    return 0;
}