1/*
2 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11// ReleaseTest-API.cpp : Defines the entry point for the console application.
12//
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <time.h>
18#include <ctype.h>
19#include <iostream>
20
21/* include API */
22#include "isac.h"
23#include "utility.h"
24#include "webrtc/base/format_macros.h"
25
26/* Defines */
27#define SEED_FILE "randseed.txt" /* Used when running decoder on garbage data */
28#define MAX_FRAMESAMPLES 960     /* max number of samples per frame
29                                    (= 60 ms frame & 16 kHz) or
30                                    (= 30 ms frame & 32 kHz) */
31#define FRAMESAMPLES_10ms 160 /* number of samples per 10ms frame */
32#define SWBFRAMESAMPLES_10ms 320
33//#define FS 16000 /* sampling frequency (Hz) */
34
35#ifdef WIN32
36#define CLOCKS_PER_SEC 1000 /* Runtime statistics */
37#endif
38
39using namespace std;
40
41int main(int argc, char* argv[]) {
42  char inname[100], outname[100], bottleneck_file[100], vadfile[100];
43  FILE* inp, *outp, * f_bn = NULL, * vadp = NULL, *bandwidthp;
44  int framecnt, endfile;
45
46  size_t i;
47  int errtype, VADusage = 0, packetLossPercent = 0;
48  int16_t CodingMode;
49  int32_t bottleneck = 0;
50  int framesize = 30; /* ms */
51  int cur_framesmpls, err;
52
53  /* Runtime statistics */
54  double starttime, runtime, length_file;
55
56  size_t stream_len = 0;
57  int declen = 0, declenTC = 0;
58  bool lostFrame = false;
59
60  int16_t shortdata[SWBFRAMESAMPLES_10ms];
61  int16_t vaddata[SWBFRAMESAMPLES_10ms * 3];
62  int16_t decoded[MAX_FRAMESAMPLES << 1];
63  int16_t decodedTC[MAX_FRAMESAMPLES << 1];
64  uint16_t streamdata[500];
65  int16_t speechType[1];
66  int16_t rateBPS = 0;
67  int16_t fixedFL = 0;
68  int16_t payloadSize = 0;
69  int32_t payloadRate = 0;
70  int setControlBWE = 0;
71  short FL, testNum;
72  char version_number[20];
73  FILE* plFile;
74  int32_t sendBN;
75
76#if !defined(NDEBUG)
77  FILE* fy;
78  double kbps;
79#endif
80  size_t totalbits = 0;
81  int totalsmpls = 0;
82
83  /* If use GNS file */
84  FILE* fp_gns = NULL;
85  char gns_file[100];
86  size_t maxStreamLen30 = 0;
87  size_t maxStreamLen60 = 0;
88  short sampFreqKHz = 32;
89  short samplesIn10Ms;
90  short useAssign = 0;
91  // FILE logFile;
92  bool doTransCoding = false;
93  int32_t rateTransCoding = 0;
94  uint8_t streamDataTransCoding[1200];
95  size_t streamLenTransCoding = 0;
96  FILE* transCodingFile = NULL;
97  FILE* transcodingBitstream = NULL;
98  size_t numTransCodingBytes = 0;
99
100  /* only one structure used for ISAC encoder */
101  ISACStruct* ISAC_main_inst = NULL;
102  ISACStruct* decoderTransCoding = NULL;
103
104  BottleNeckModel BN_data;
105
106#if !defined(NDEBUG)
107  fy = fopen("bit_rate.dat", "w");
108  fclose(fy);
109  fy = fopen("bytes_frames.dat", "w");
110  fclose(fy);
111#endif
112
113  /* Handling wrong input arguments in the command line */
114  if ((argc < 3) || (argc > 17)) {
115    printf("\n\nWrong number of arguments or flag values.\n\n");
116
117    printf("\n");
118    WebRtcIsac_version(version_number);
119    printf("iSAC-swb version %s \n\n", version_number);
120
121    printf("Usage:\n\n");
122    printf("./kenny.exe [-I] bottleneck_value infile outfile \n\n");
123    printf("with:\n");
124    printf("[-FS num]       : sampling frequency in kHz, valid values are\n");
125    printf("                  16 & 32, with 16 as default.\n");
126    printf("[-I]            : if -I option is specified, the coder will use\n");
127    printf("                  an instantaneous Bottleneck value. If not, it\n");
128    printf("                  will be an adaptive Bottleneck value.\n");
129    printf("[-assign]       : Use Assign API.\n");
130    printf("[-B num]        : the value of the bottleneck provided either\n");
131    printf("                  as a fixed value in bits/sec (e.g. 25000) or\n");
132    printf("                  read from a file (e.g. bottleneck.txt)\n");
133    printf("[-INITRATE num] : Set a new value for initial rate. Note! Only\n");
134    printf("                  used in adaptive mode.\n");
135    printf("[-FL num]       : Set (initial) frame length in msec. Valid\n");
136    printf("                  lengths are 30 and 60 msec.\n");
137    printf("[-FIXED_FL]     : Frame length will be fixed to initial value.\n");
138    printf("[-MAX num]      : Set the limit for the payload size of iSAC\n");
139    printf("                  in bytes. Minimum 100 maximum 400.\n");
140    printf("[-MAXRATE num]  : Set the maxrate for iSAC in bits per second.\n");
141    printf("                  Minimum 32000, maximum 53400.\n");
142    printf("[-F num]        : if -F option is specified, the test function\n");
143    printf("                  will run the iSAC API fault scenario\n");
144    printf("                  specified by the supplied number.\n");
145    printf("                  F 1 - Call encoder prior to init encoder call\n");
146    printf("                  F 2 - Call decoder prior to init decoder call\n");
147    printf("                  F 3 - Call decoder prior to encoder call\n");
148    printf("                  F 4 - Call decoder with a too short coded\n");
149    printf("                        sequence\n");
150    printf("                  F 5 - Call decoder with a too long coded\n");
151    printf("                        sequence\n");
152    printf("                  F 6 - Call decoder with random bit stream\n");
153    printf("                  F 7 - Call init encoder/decoder at random\n");
154    printf("                        during a call\n");
155    printf("                  F 8 - Call encoder/decoder without having\n");
156    printf("                        allocated memory for encoder/decoder\n");
157    printf("                        instance\n");
158    printf("                  F 9 - Call decodeB without calling decodeA\n");
159    printf("                  F 10 - Call decodeB with garbage data\n");
160    printf("[-PL num]       : if -PL option is specified \n");
161    printf("[-T rate file]  : test trans-coding with target bottleneck\n");
162    printf("                  'rate' bits/sec\n");
163    printf("                  the output file is written to 'file'\n");
164    printf("[-LOOP num]     : number of times to repeat coding the input\n");
165    printf("                  file for stress testing\n");
166    // printf("[-CE num]       : Test of APIs used by Conference Engine.\n");
167    // printf("                  CE 1 - getNewBitstream, getBWE \n");
168    // printf("                  (CE 2 - RESERVED for transcoding)\n");
169    // printf("                  CE 3 - getSendBWE, setSendBWE.  \n");
170    // printf("-L filename     : write the logging info into file
171    // (appending)\n");
172    printf("infile          :   Normal speech input file\n");
173    printf("outfile         :   Speech output file\n");
174    exit(0);
175  }
176
177  /* Print version number */
178  printf("-------------------------------------------------\n");
179  WebRtcIsac_version(version_number);
180  printf("iSAC version %s \n\n", version_number);
181
182  /* Loop over all command line arguments */
183  CodingMode = 0;
184  testNum = 0;
185  useAssign = 0;
186  // logFile = NULL;
187  char transCodingFileName[500];
188  int16_t totFileLoop = 0;
189  int16_t numFileLoop = 0;
190  for (i = 1; i + 2 < static_cast<size_t>(argc); i++) {
191    if (!strcmp("-LOOP", argv[i])) {
192      i++;
193      totFileLoop = (int16_t)atol(argv[i]);
194      if (totFileLoop <= 0) {
195        fprintf(stderr, "Invalid number of runs for the given input file, %d.",
196                totFileLoop);
197        exit(0);
198      }
199    }
200
201    if (!strcmp("-T", argv[i])) {
202      doTransCoding = true;
203      i++;
204      rateTransCoding = atoi(argv[i]);
205      i++;
206      strcpy(transCodingFileName, argv[i]);
207    }
208
209    /*Should we use assign API*/
210    if (!strcmp("-assign", argv[i])) {
211      useAssign = 1;
212    }
213
214    /* Set Sampling Rate */
215    if (!strcmp("-FS", argv[i])) {
216      i++;
217      sampFreqKHz = atoi(argv[i]);
218    }
219
220    /* Instantaneous mode */
221    if (!strcmp("-I", argv[i])) {
222      printf("Instantaneous BottleNeck\n");
223      CodingMode = 1;
224    }
225
226    /* Set (initial) bottleneck value */
227    if (!strcmp("-INITRATE", argv[i])) {
228      rateBPS = atoi(argv[i + 1]);
229      setControlBWE = 1;
230      if ((rateBPS < 10000) || (rateBPS > 32000)) {
231        printf("\n%d is not a initial rate. Valid values are in the range "
232               "10000 to 32000.\n", rateBPS);
233        exit(0);
234      }
235      printf("New initial rate: %d\n", rateBPS);
236      i++;
237    }
238
239    /* Set (initial) framelength */
240    if (!strcmp("-FL", argv[i])) {
241      framesize = atoi(argv[i + 1]);
242      if ((framesize != 30) && (framesize != 60)) {
243        printf("\n%d is not a valid frame length. Valid length are 30 and 60 "
244               "msec.\n", framesize);
245        exit(0);
246      }
247      setControlBWE = 1;
248      printf("Frame Length: %d\n", framesize);
249      i++;
250    }
251
252    /* Fixed frame length */
253    if (!strcmp("-FIXED_FL", argv[i])) {
254      fixedFL = 1;
255      setControlBWE = 1;
256      printf("Fixed Frame Length\n");
257    }
258
259    /* Set maximum allowed payload size in bytes */
260    if (!strcmp("-MAX", argv[i])) {
261      payloadSize = atoi(argv[i + 1]);
262      printf("Maximum Payload Size: %d\n", payloadSize);
263      i++;
264    }
265
266    /* Set maximum rate in bytes */
267    if (!strcmp("-MAXRATE", argv[i])) {
268      payloadRate = atoi(argv[i + 1]);
269      printf("Maximum Rate in kbps: %d\n", payloadRate);
270      i++;
271    }
272
273    /* Test of fault scenarious */
274    if (!strcmp("-F", argv[i])) {
275      testNum = atoi(argv[i + 1]);
276      printf("Fault test: %d\n", testNum);
277      if (testNum < 1 || testNum > 10) {
278        printf("\n%d is not a valid Fault Scenario number. Valid Fault "
279               "Scenarios are numbered 1-10.\n", testNum);
280        exit(0);
281      }
282      i++;
283    }
284
285    /* Packet loss test */
286    if (!strcmp("-PL", argv[i])) {
287      if (isdigit(*argv[i + 1])) {
288        packetLossPercent = atoi(argv[i + 1]);
289        if ((packetLossPercent < 0) | (packetLossPercent > 100)) {
290          printf("\nInvalid packet loss perentage \n");
291          exit(0);
292        }
293        if (packetLossPercent > 0) {
294          printf("Simulating %d %% of independent packet loss\n",
295                 packetLossPercent);
296        } else {
297          printf("\nNo Packet Loss Is Simulated \n");
298        }
299      } else {
300        plFile = fopen(argv[i + 1], "rb");
301        if (plFile == NULL) {
302          printf("\n couldn't open the frameloss file: %s\n", argv[i + 1]);
303          exit(0);
304        }
305        printf("Simulating packet loss through the given channel file: %s\n",
306               argv[i + 1]);
307      }
308      i++;
309    }
310
311    /* Random packetlosses */
312    if (!strcmp("-rnd", argv[i])) {
313      srand((unsigned int)time(NULL));
314      printf("Random pattern in lossed packets \n");
315    }
316
317    /* Use gns file */
318    if (!strcmp("-G", argv[i])) {
319      sscanf(argv[i + 1], "%s", gns_file);
320      fp_gns = fopen(gns_file, "rb");
321      if (fp_gns == NULL) {
322        printf("Cannot read file %s.\n", gns_file);
323        exit(0);
324      }
325      i++;
326    }
327
328    // make it with '-B'
329    /* Get Bottleneck value */
330    if (!strcmp("-B", argv[i])) {
331      i++;
332      bottleneck = atoi(argv[i]);
333      if (bottleneck == 0) {
334        sscanf(argv[i], "%s", bottleneck_file);
335        f_bn = fopen(bottleneck_file, "rb");
336        if (f_bn == NULL) {
337          printf("Error No value provided for BottleNeck and cannot read file "
338                 "%s.\n", bottleneck_file);
339          exit(0);
340        } else {
341          printf("reading bottleneck rates from file %s\n\n", bottleneck_file);
342          if (fscanf(f_bn, "%d", &bottleneck) == EOF) {
343            /* Set pointer to beginning of file */
344            fseek(f_bn, 0L, SEEK_SET);
345            if (fscanf(f_bn, "%d", &bottleneck) == EOF) {
346              exit(0);
347            }
348          }
349
350          /* Bottleneck is a cosine function
351           * Matlab code for writing the bottleneck file:
352           * BottleNeck_10ms = 20e3 + 10e3 * cos((0:5999)/5999*2*pi);
353           * fid = fopen('bottleneck.txt', 'wb');
354           * fprintf(fid, '%d\n', BottleNeck_10ms); fclose(fid);
355           */
356        }
357      } else {
358        printf("\nfixed bottleneck rate of %d bits/s\n\n", bottleneck);
359      }
360    }
361    /* Run Conference Engine APIs */
362    //     Do not test it in the first release
363    //
364    //     if(!strcmp ("-CE", argv[i]))
365    //     {
366    //         testCE = atoi(argv[i + 1]);
367    //         if(testCE==1)
368    //         {
369    //             i++;
370    //             scale = (float)atof( argv[i+1] );
371    //         }
372    //         else if(testCE == 2)
373    //         {
374    //             printf("\nCE-test 2 (transcoding) not implemented.\n");
375    //             exit(0);
376    //         }
377    //         else if(testCE < 1 || testCE > 3)
378    //         {
379    //             printf("\n%d is not a valid CE-test number. Valid CE tests
380    //             are 1-3.\n", testCE);
381    //             exit(0);
382    //         }
383    //         printf("CE-test number: %d\n", testCE);
384    //         i++;
385    //     }
386  }
387
388  if (CodingMode == 0) {
389    printf("\nAdaptive BottleNeck\n");
390  }
391
392  switch (sampFreqKHz) {
393    case 16: {
394      printf("iSAC Wideband.\n");
395      samplesIn10Ms = FRAMESAMPLES_10ms;
396      break;
397    }
398    case 32: {
399      printf("iSAC Supper-Wideband.\n");
400      samplesIn10Ms = SWBFRAMESAMPLES_10ms;
401      break;
402    }
403    default:
404      printf("Unsupported sampling frequency %d kHz", sampFreqKHz);
405      exit(0);
406  }
407
408  /* Get Input and Output files */
409  sscanf(argv[argc - 2], "%s", inname);
410  sscanf(argv[argc - 1], "%s", outname);
411  printf("\nInput file: %s\n", inname);
412  printf("Output file: %s\n\n", outname);
413  if ((inp = fopen(inname, "rb")) == NULL) {
414    printf("  Error iSAC Cannot read file %s.\n", inname);
415    cout << flush;
416    exit(1);
417  }
418
419  if ((outp = fopen(outname, "wb")) == NULL) {
420    printf("  Error iSAC Cannot write file %s.\n", outname);
421    cout << flush;
422    getc(stdin);
423    exit(1);
424  }
425  if (VADusage) {
426    if ((vadp = fopen(vadfile, "rb")) == NULL) {
427      printf("  Error iSAC Cannot read file %s.\n", vadfile);
428      cout << flush;
429      exit(1);
430    }
431  }
432
433  if ((bandwidthp = fopen("bwe.pcm", "wb")) == NULL) {
434    printf("  Error iSAC Cannot read file %s.\n", "bwe.pcm");
435    cout << flush;
436    exit(1);
437  }
438
439  starttime = clock() / (double)CLOCKS_PER_SEC; /* Runtime statistics */
440
441  /* Initialize the ISAC and BN structs */
442  if (testNum != 8) {
443    if (!useAssign) {
444      err = WebRtcIsac_Create(&ISAC_main_inst);
445      WebRtcIsac_SetEncSampRate(ISAC_main_inst, sampFreqKHz * 1000);
446      WebRtcIsac_SetDecSampRate(ISAC_main_inst,
447                                sampFreqKHz >= 32 ? 32000 : 16000);
448    } else {
449      /* Test the Assign functions */
450      int sss;
451      void* ppp;
452      err = WebRtcIsac_AssignSize(&sss);
453      ppp = malloc(sss);
454      err = WebRtcIsac_Assign(&ISAC_main_inst, ppp);
455      WebRtcIsac_SetEncSampRate(ISAC_main_inst, sampFreqKHz * 1000);
456      WebRtcIsac_SetDecSampRate(ISAC_main_inst,
457                                sampFreqKHz >= 32 ? 32000 : 16000);
458    }
459    /* Error check */
460    if (err < 0) {
461      printf("\n\n Error in create.\n\n");
462      cout << flush;
463      exit(EXIT_FAILURE);
464    }
465  }
466  BN_data.arrival_time = 0;
467  BN_data.sample_count = 0;
468  BN_data.rtp_number = 0;
469
470  /* Initialize encoder and decoder */
471  framecnt = 0;
472  endfile = 0;
473
474  if (doTransCoding) {
475    WebRtcIsac_Create(&decoderTransCoding);
476    WebRtcIsac_SetEncSampRate(decoderTransCoding, sampFreqKHz * 1000);
477    WebRtcIsac_SetDecSampRate(decoderTransCoding,
478                              sampFreqKHz >= 32 ? 32000 : 16000);
479    WebRtcIsac_DecoderInit(decoderTransCoding);
480    transCodingFile = fopen(transCodingFileName, "wb");
481    if (transCodingFile == NULL) {
482      printf("Could not open %s to output trans-coding.\n",
483             transCodingFileName);
484      exit(0);
485    }
486    strcat(transCodingFileName, ".bit");
487    transcodingBitstream = fopen(transCodingFileName, "wb");
488    if (transcodingBitstream == NULL) {
489      printf("Could not open %s to write the bit-stream of transcoder.\n",
490             transCodingFileName);
491      exit(0);
492    }
493  }
494
495  if (testNum != 1) {
496    if (WebRtcIsac_EncoderInit(ISAC_main_inst, CodingMode) < 0) {
497      printf("Error could not initialize the encoder \n");
498      cout << flush;
499      return 0;
500    }
501  }
502  if (testNum != 2)
503    WebRtcIsac_DecoderInit(ISAC_main_inst);
504  if (CodingMode == 1) {
505    err = WebRtcIsac_Control(ISAC_main_inst, bottleneck, framesize);
506    if (err < 0) {
507      /* exit if returned with error */
508      errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
509      printf("\n\n Error in initialization (control): %d.\n\n", errtype);
510      cout << flush;
511      if (testNum == 0) {
512        exit(EXIT_FAILURE);
513      }
514    }
515  }
516
517  if ((setControlBWE) && (CodingMode == 0)) {
518    err = WebRtcIsac_ControlBwe(ISAC_main_inst, rateBPS, framesize, fixedFL);
519    if (err < 0) {
520      /* exit if returned with error */
521      errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
522
523      printf("\n\n Error in Control BWE: %d.\n\n", errtype);
524      cout << flush;
525      exit(EXIT_FAILURE);
526    }
527  }
528
529  if (payloadSize != 0) {
530    err = WebRtcIsac_SetMaxPayloadSize(ISAC_main_inst, payloadSize);
531    if (err < 0) {
532      /* exit if returned with error */
533      errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
534      printf("\n\n Error in SetMaxPayloadSize: %d.\n\n", errtype);
535      cout << flush;
536      exit(EXIT_FAILURE);
537    }
538  }
539  if (payloadRate != 0) {
540    err = WebRtcIsac_SetMaxRate(ISAC_main_inst, payloadRate);
541    if (err < 0) {
542      /* exit if returned with error */
543      errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
544      printf("\n\n Error in SetMaxRateInBytes: %d.\n\n", errtype);
545      cout << flush;
546      exit(EXIT_FAILURE);
547    }
548  }
549
550  *speechType = 1;
551
552  cout << "\n" << flush;
553
554  length_file = 0;
555  int16_t bnIdxTC = 0;
556  int16_t jitterInfoTC = 0;
557  while (endfile == 0) {
558    /* Call init functions at random, fault test number 7 */
559    if (testNum == 7 && (rand() % 2 == 0)) {
560      err = WebRtcIsac_EncoderInit(ISAC_main_inst, CodingMode);
561      /* Error check */
562      if (err < 0) {
563        errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
564        printf("\n\n Error in encoderinit: %d.\n\n", errtype);
565        cout << flush;
566      }
567
568      WebRtcIsac_DecoderInit(ISAC_main_inst);
569    }
570
571    cur_framesmpls = 0;
572    while (1) {
573      int stream_len_int = 0;
574
575      /* Read 10 ms speech block */
576      endfile = readframe(shortdata, inp, samplesIn10Ms);
577
578      if (endfile) {
579        numFileLoop++;
580        if (numFileLoop < totFileLoop) {
581          rewind(inp);
582          framecnt = 0;
583          fprintf(stderr, "\n");
584          endfile = readframe(shortdata, inp, samplesIn10Ms);
585        }
586      }
587
588      if (testNum == 7) {
589        srand((unsigned int)time(NULL));
590      }
591
592      /* iSAC encoding */
593      if (!(testNum == 3 && framecnt == 0)) {
594        stream_len_int =
595            WebRtcIsac_Encode(ISAC_main_inst, shortdata, (uint8_t*)streamdata);
596        if ((payloadSize != 0) && (stream_len_int > payloadSize)) {
597          if (testNum == 0) {
598            printf("\n\n");
599          }
600
601          printf("\nError: Streamsize out of range %d\n",
602                 stream_len_int - payloadSize);
603          cout << flush;
604        }
605
606        WebRtcIsac_GetUplinkBw(ISAC_main_inst, &sendBN);
607
608        if (stream_len_int > 0) {
609          if (doTransCoding) {
610            int16_t indexStream;
611            uint8_t auxUW8;
612
613            /******************** Main Transcoding stream ********************/
614            WebRtcIsac_GetDownLinkBwIndex(ISAC_main_inst, &bnIdxTC,
615                                          &jitterInfoTC);
616            int streamLenTransCoding_int = WebRtcIsac_GetNewBitStream(
617                ISAC_main_inst, bnIdxTC, jitterInfoTC, rateTransCoding,
618                streamDataTransCoding, false);
619            if (streamLenTransCoding_int < 0) {
620              fprintf(stderr, "Error in trans-coding\n");
621              exit(0);
622            }
623            streamLenTransCoding =
624                static_cast<size_t>(streamLenTransCoding_int);
625            auxUW8 = (uint8_t)(((streamLenTransCoding & 0xFF00) >> 8) & 0x00FF);
626            if (fwrite(&auxUW8, sizeof(uint8_t), 1, transcodingBitstream) !=
627                1) {
628              return -1;
629            }
630
631            auxUW8 = (uint8_t)(streamLenTransCoding & 0x00FF);
632            if (fwrite(&auxUW8, sizeof(uint8_t), 1, transcodingBitstream) !=
633                1) {
634              return -1;
635            }
636
637            if (fwrite(streamDataTransCoding, sizeof(uint8_t),
638                       streamLenTransCoding, transcodingBitstream) !=
639                streamLenTransCoding) {
640              return -1;
641            }
642
643            WebRtcIsac_ReadBwIndex(streamDataTransCoding, &indexStream);
644            if (indexStream != bnIdxTC) {
645              fprintf(stderr,
646                      "Error in inserting Bandwidth index into transcoding "
647                      "stream.\n");
648              exit(0);
649            }
650            numTransCodingBytes += streamLenTransCoding;
651          }
652        }
653      } else {
654        break;
655      }
656
657      if (stream_len_int < 0) {
658        /* exit if returned with error */
659        errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
660        fprintf(stderr, "Error in encoder: %d.\n", errtype);
661        cout << flush;
662        exit(0);
663      }
664      stream_len = static_cast<size_t>(stream_len_int);
665
666      cur_framesmpls += samplesIn10Ms;
667      /* exit encoder loop if the encoder returned a bitstream */
668      if (stream_len != 0)
669        break;
670    }
671
672    /* read next bottleneck rate */
673    if (f_bn != NULL) {
674      if (fscanf(f_bn, "%d", &bottleneck) == EOF) {
675        /* Set pointer to beginning of file */
676        fseek(f_bn, 0L, SEEK_SET);
677        if (fscanf(f_bn, "%d", &bottleneck) == EOF) {
678          exit(0);
679        }
680      }
681      if (CodingMode == 1) {
682        WebRtcIsac_Control(ISAC_main_inst, bottleneck, framesize);
683      }
684    }
685
686    length_file += cur_framesmpls;
687    if (cur_framesmpls == (3 * samplesIn10Ms)) {
688      maxStreamLen30 =
689          (stream_len > maxStreamLen30) ? stream_len : maxStreamLen30;
690    } else {
691      maxStreamLen60 =
692          (stream_len > maxStreamLen60) ? stream_len : maxStreamLen60;
693    }
694
695    if (!lostFrame) {
696      lostFrame = ((rand() % 100) < packetLossPercent);
697    } else {
698      lostFrame = false;
699    }
700
701    // RED.
702    if (lostFrame) {
703      int stream_len_int = WebRtcIsac_GetRedPayload(
704          ISAC_main_inst, reinterpret_cast<uint8_t*>(streamdata));
705      if (stream_len_int < 0) {
706        fprintf(stderr, "Error getting RED payload\n");
707        exit(0);
708      }
709      stream_len = static_cast<size_t>(stream_len_int);
710
711      if (doTransCoding) {
712        int streamLenTransCoding_int = WebRtcIsac_GetNewBitStream(
713            ISAC_main_inst, bnIdxTC, jitterInfoTC, rateTransCoding,
714            streamDataTransCoding, true);
715        if (streamLenTransCoding_int < 0) {
716          fprintf(stderr, "Error in RED trans-coding\n");
717          exit(0);
718        }
719        streamLenTransCoding =
720            static_cast<size_t>(streamLenTransCoding_int);
721      }
722    }
723
724    /* make coded sequence to short be inreasing */
725    /* the length the decoder expects */
726    if (testNum == 4) {
727      stream_len += 10;
728    }
729
730    /* make coded sequence to long be decreasing */
731    /* the length the decoder expects */
732    if (testNum == 5) {
733      stream_len -= 10;
734    }
735
736    if (testNum == 6) {
737      srand((unsigned int)time(NULL));
738      for (i = 0; i < stream_len; i++) {
739        streamdata[i] = rand();
740      }
741    }
742
743    if (VADusage) {
744      readframe(vaddata, vadp, samplesIn10Ms * 3);
745    }
746
747    /* simulate packet handling through NetEq and the modem */
748    if (!(testNum == 3 && framecnt == 0)) {
749      get_arrival_time(cur_framesmpls, stream_len, bottleneck, &BN_data,
750                       sampFreqKHz * 1000, sampFreqKHz * 1000);
751    }
752
753    if (VADusage && (framecnt > 10 && vaddata[0] == 0)) {
754      BN_data.rtp_number--;
755    } else {
756      /* Error test number 10, garbage data */
757      if (testNum == 10) {
758        /* Test to run decoder with garbage data */
759        for (i = 0; i < stream_len; i++) {
760          streamdata[i] = (short)(streamdata[i]) + (short)rand();
761        }
762      }
763
764      if (testNum != 9) {
765        err = WebRtcIsac_UpdateBwEstimate(
766            ISAC_main_inst, reinterpret_cast<const uint8_t*>(streamdata),
767            stream_len, BN_data.rtp_number, BN_data.sample_count,
768            BN_data.arrival_time);
769
770        if (err < 0) {
771          /* exit if returned with error */
772          errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
773          if (testNum == 0) {
774            printf("\n\n");
775          }
776
777          printf("Error: in decoder: %d.", errtype);
778          cout << flush;
779          if (testNum == 0) {
780            printf("\n\n");
781          }
782        }
783      }
784
785      /* Call getFramelen, only used here for function test */
786      err = WebRtcIsac_ReadFrameLen(
787          ISAC_main_inst, reinterpret_cast<const uint8_t*>(streamdata), &FL);
788      if (err < 0) {
789        /* exit if returned with error */
790        errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
791        if (testNum == 0) {
792          printf("\n\n");
793        }
794        printf("    Error: in getFrameLen %d.", errtype);
795        cout << flush;
796        if (testNum == 0) {
797          printf("\n\n");
798        }
799      }
800
801      // iSAC decoding
802
803      if (lostFrame) {
804        declen = WebRtcIsac_DecodeRcu(
805            ISAC_main_inst, reinterpret_cast<const uint8_t*>(streamdata),
806            stream_len, decoded, speechType);
807
808        if (doTransCoding) {
809          declenTC =
810              WebRtcIsac_DecodeRcu(decoderTransCoding, streamDataTransCoding,
811                                   streamLenTransCoding, decodedTC, speechType);
812        }
813      } else {
814        declen = WebRtcIsac_Decode(ISAC_main_inst,
815                                   reinterpret_cast<const uint8_t*>(streamdata),
816                                   stream_len, decoded, speechType);
817        if (doTransCoding) {
818          declenTC =
819              WebRtcIsac_Decode(decoderTransCoding, streamDataTransCoding,
820                                streamLenTransCoding, decodedTC, speechType);
821        }
822      }
823
824      if (declen < 0) {
825        /* exit if returned with error */
826        errtype = WebRtcIsac_GetErrorCode(ISAC_main_inst);
827        if (testNum == 0) {
828          printf("\n\n");
829        }
830        printf("    Error: in decoder %d.", errtype);
831        cout << flush;
832        if (testNum == 0) {
833          printf("\n\n");
834        }
835      }
836
837      if (declenTC < 0) {
838        if (testNum == 0) {
839          printf("\n\n");
840        }
841        printf("    Error: in decoding the transcoded stream");
842        cout << flush;
843        if (testNum == 0) {
844          printf("\n\n");
845        }
846      }
847    }
848    /* Write decoded speech frame to file */
849    if ((declen > 0) && (numFileLoop == 0)) {
850      if (fwrite(decoded, sizeof(int16_t), declen, outp) !=
851          static_cast<size_t>(declen)) {
852        return -1;
853      }
854    }
855
856    if ((declenTC > 0) && (numFileLoop == 0)) {
857      if (fwrite(decodedTC, sizeof(int16_t), declen, transCodingFile) !=
858          static_cast<size_t>(declen)) {
859        return -1;
860      }
861    }
862
863    fprintf(stderr, "\rframe = %5d  ", framecnt);
864    fflush(stderr);
865    framecnt++;
866
867    /* Error test number 10, garbage data */
868    // if (testNum == 10)
869    // {
870    //   /* Test to run decoder with garbage data */
871    //   if ((seedfile = fopen(SEED_FILE, "a+t")) == NULL) {
872    //     fprintf(stderr, "Error: Could not open file %s\n", SEED_FILE);
873    //   } else {
874    //     fprintf(seedfile, "ok\n\n");
875    //     fclose(seedfile);
876    //   }
877    // }
878    /* Error test number 10, garbage data */
879    // if (testNum == 10) {
880    //   /* Test to run decoder with garbage data */
881    //   for (i = 0; i < stream_len; i++) {
882    //     streamdata[i] = (short) (streamdata[i] + (short) rand());
883    //   }
884    // }
885
886    totalsmpls += declen;
887    totalbits += 8 * stream_len;
888#if !defined(NDEBUG)
889    kbps = ((double)sampFreqKHz * 1000.) / ((double)cur_framesmpls) * 8.0 *
890           stream_len / 1000.0;  // kbits/s
891    fy = fopen("bit_rate.dat", "a");
892    fprintf(fy, "Frame %i = %0.14f\n", framecnt, kbps);
893    fclose(fy);
894
895#endif
896  }
897  printf("\n");
898  printf("total bits               = %" PRIuS " bits\n", totalbits);
899  printf("measured average bitrate = %0.3f kbits/s\n",
900         (double)totalbits * (sampFreqKHz) / totalsmpls);
901  if (doTransCoding) {
902    printf("Transcoding average bit-rate = %0.3f kbps\n",
903           (double)numTransCodingBytes * 8.0 * (sampFreqKHz) / totalsmpls);
904    fclose(transCodingFile);
905  }
906  printf("\n");
907
908  /* Runtime statistics */
909  runtime = (double)(clock() / (double)CLOCKS_PER_SEC - starttime);
910  length_file = length_file / (sampFreqKHz * 1000.);
911
912  printf("\n\nLength of speech file: %.1f s\n", length_file);
913  printf("Time to run iSAC:      %.2f s (%.2f %% of realtime)\n\n", runtime,
914         (100 * runtime / length_file));
915
916  if (maxStreamLen30 != 0) {
917    printf("Maximum payload size 30ms Frames %" PRIuS " bytes (%0.3f kbps)\n",
918           maxStreamLen30, maxStreamLen30 * 8 / 30.);
919  }
920  if (maxStreamLen60 != 0) {
921    printf("Maximum payload size 60ms Frames %" PRIuS " bytes (%0.3f kbps)\n",
922           maxStreamLen60, maxStreamLen60 * 8 / 60.);
923  }
924  // fprintf(stderr, "\n");
925
926  fprintf(stderr, "   %.1f s", length_file);
927  fprintf(stderr, "   %0.1f kbps",
928          (double)totalbits * (sampFreqKHz) / totalsmpls);
929  if (maxStreamLen30 != 0) {
930    fprintf(stderr, "   plmax-30ms %" PRIuS " bytes (%0.0f kbps)",
931            maxStreamLen30, maxStreamLen30 * 8 / 30.);
932  }
933  if (maxStreamLen60 != 0) {
934    fprintf(stderr, "   plmax-60ms %" PRIuS " bytes (%0.0f kbps)",
935            maxStreamLen60, maxStreamLen60 * 8 / 60.);
936  }
937  if (doTransCoding) {
938    fprintf(stderr, "  transcoding rate %.0f kbps",
939            (double)numTransCodingBytes * 8.0 * (sampFreqKHz) / totalsmpls);
940  }
941
942  fclose(inp);
943  fclose(outp);
944  WebRtcIsac_Free(ISAC_main_inst);
945
946  exit(0);
947}
948