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