• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /* kenny.c  - Main function for the iSAC coder */
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <time.h>
17 
18 #ifdef WIN32
19 #include "windows.h"
20 #define CLOCKS_PER_SEC 1000
21 #endif
22 
23 #include <ctype.h>
24 #include <math.h>
25 
26 /* include API */
27 #include "isac.h"
28 #include "utility.h"
29 #include "webrtc/base/format_macros.h"
30 //#include "commonDefs.h"
31 
32 /* max number of samples per frame (= 60 ms frame) */
33 #define MAX_FRAMESAMPLES_SWB 1920
34 /* number of samples per 10ms frame */
35 #define FRAMESAMPLES_SWB_10ms 320
36 #define FRAMESAMPLES_WB_10ms 160
37 
38 /* sampling frequency (Hz) */
39 #define FS_SWB 32000
40 #define FS_WB 16000
41 
42 //#define CHANGE_OUTPUT_NAME
43 
44 #ifdef HAVE_DEBUG_INFO
45 #include "debugUtility.h"
46 debugStruct debugInfo;
47 #endif
48 
49 unsigned long framecnt = 0;
50 
main(int argc,char * argv[])51 int main(int argc, char* argv[]) {
52   //--- File IO ----
53   FILE* inp;
54   FILE* outp;
55   char inname[500];
56   char outname[500];
57 
58   /* Runtime statistics */
59   double rate;
60   double rateRCU;
61   size_t totalbits = 0;
62   unsigned long totalBitsRCU = 0;
63   unsigned long totalsmpls = 0;
64 
65   int32_t bottleneck = 39;
66   int frameSize = 30; /* ms */
67   int16_t codingMode = 1;
68   int16_t shortdata[FRAMESAMPLES_SWB_10ms];
69   int16_t decoded[MAX_FRAMESAMPLES_SWB];
70   // uint16_t  streamdata[1000];
71   int16_t speechType[1];
72   int16_t payloadLimit;
73   int32_t rateLimit;
74   ISACStruct* ISAC_main_inst;
75 
76   size_t stream_len = 0;
77   int declen = 0;
78   int16_t err;
79   int cur_framesmpls;
80   int endfile;
81 #ifdef WIN32
82   double length_file;
83   double runtime;
84   char outDrive[10];
85   char outPath[500];
86   char outPrefix[500];
87   char outSuffix[500];
88   char bitrateFileName[500];
89   FILE* bitrateFile;
90   double starttime;
91   double rateLB = 0;
92   double rateUB = 0;
93 #endif
94   FILE* histFile;
95   FILE* averageFile;
96   int sampFreqKHz;
97   int samplesIn10Ms;
98   size_t maxStreamLen = 0;
99   char histFileName[500];
100   char averageFileName[500];
101   unsigned int hist[600];
102   double tmpSumStreamLen = 0;
103   unsigned int packetCntr = 0;
104   unsigned int lostPacketCntr = 0;
105   uint8_t payload[1200];
106   uint8_t payloadRCU[1200];
107   uint16_t packetLossPercent = 0;
108   int16_t rcuStreamLen = 0;
109   int onlyEncode;
110   int onlyDecode;
111 
112   BottleNeckModel packetData;
113   packetData.arrival_time = 0;
114   packetData.sample_count = 0;
115   packetData.rtp_number = 0;
116   memset(hist, 0, sizeof(hist));
117 
118   /* handling wrong input arguments in the command line */
119   if (argc < 5) {
120     int size;
121     WebRtcIsac_AssignSize(&size);
122 
123     printf("\n\nWrong number of arguments or flag values.\n\n");
124 
125     printf("Usage:\n\n");
126     printf("%s infile outfile -bn bottleneck [options]\n\n", argv[0]);
127     printf("with:\n");
128     printf("-I.............. indicates encoding in instantaneous mode.\n");
129     printf("-bn bottleneck.. the value of the bottleneck in bit/sec, e.g.\n");
130     printf("                 39742, in instantaneous (channel-independent)\n");
131     printf("                 mode.\n\n");
132     printf("infile.......... Normal speech input file\n\n");
133     printf("outfile......... Speech output file\n\n");
134     printf("OPTIONS\n");
135     printf("-------\n");
136     printf("-fs sampFreq.... sampling frequency of codec 16 or 32 (default)\n");
137     printf("                 kHz.\n");
138     printf("-plim payloadLim payload limit in bytes, default is the maximum\n");
139     printf("                 possible.\n");
140     printf("-rlim rateLim... rate limit in bits/sec, default is the maximum\n");
141     printf("                 possible.\n");
142     printf("-h file......... record histogram and *append* to 'file'.\n");
143     printf("-ave file....... record average rate of 3 sec intervales and\n");
144     printf("                 *append* to 'file'.\n");
145     printf("-ploss.......... packet-loss percentage.\n");
146     printf("-enc............ do only encoding and store the bit-stream\n");
147     printf("-dec............ the input file is a bit-stream, decode it.\n\n");
148     printf("Example usage:\n\n");
149     printf("%s speechIn.pcm speechOut.pcm -B 40000 -fs 32\n\n", argv[0]);
150     printf("structure size %d bytes\n", size);
151 
152     exit(0);
153   }
154 
155   /* Get Bottleneck value */
156   bottleneck = readParamInt(argc, argv, "-bn", 50000);
157   fprintf(stderr, "\nfixed bottleneck rate of %d bits/s\n\n", bottleneck);
158 
159   /* Get Input and Output files */
160   sscanf(argv[1], "%s", inname);
161   sscanf(argv[2], "%s", outname);
162   codingMode = readSwitch(argc, argv, "-I");
163   sampFreqKHz = (int16_t)readParamInt(argc, argv, "-fs", 32);
164   if (readParamString(argc, argv, "-h", histFileName, 500) > 0) {
165     histFile = fopen(histFileName, "a");
166     if (histFile == NULL) {
167       printf("cannot open hist file %s", histFileName);
168       exit(0);
169     }
170   } else {
171     // NO recording of hitstogram
172     histFile = NULL;
173   }
174 
175   packetLossPercent = readParamInt(argc, argv, "-ploss", 0);
176 
177   if (readParamString(argc, argv, "-ave", averageFileName, 500) > 0) {
178     averageFile = fopen(averageFileName, "a");
179     if (averageFile == NULL) {
180       printf("cannot open file to write rate %s", averageFileName);
181       exit(0);
182     }
183   } else {
184     averageFile = NULL;
185   }
186 
187   onlyEncode = readSwitch(argc, argv, "-enc");
188   onlyDecode = readSwitch(argc, argv, "-dec");
189 
190   switch (sampFreqKHz) {
191     case 16: {
192       samplesIn10Ms = 160;
193       break;
194     }
195     case 32: {
196       samplesIn10Ms = 320;
197       break;
198     }
199     default:
200       printf("A sampling frequency of %d kHz is not supported, valid values are"
201              " 8 and 16.\n", sampFreqKHz);
202       exit(-1);
203   }
204   payloadLimit = (int16_t)readParamInt(argc, argv, "-plim", 400);
205   rateLimit = readParamInt(argc, argv, "-rlim", 106800);
206 
207   if ((inp = fopen(inname, "rb")) == NULL) {
208     printf("  iSAC: Cannot read file %s.\n", inname);
209     exit(1);
210   }
211   if ((outp = fopen(outname, "wb")) == NULL) {
212     printf("  iSAC: Cannot write file %s.\n", outname);
213     exit(1);
214   }
215 
216 #ifdef WIN32
217   _splitpath(outname, outDrive, outPath, outPrefix, outSuffix);
218   _makepath(bitrateFileName, outDrive, outPath, "bitrate", ".txt");
219 
220   bitrateFile = fopen(bitrateFileName, "a");
221   fprintf(bitrateFile, "%  %%s  \n", inname);
222 #endif
223 
224   printf("\n");
225   printf("Input.................... %s\n", inname);
226   printf("Output................... %s\n", outname);
227   printf("Encoding Mode............ %s\n",
228          (codingMode == 1) ? "Channel-Independent" : "Channel-Adaptive");
229   printf("Bottleneck............... %d bits/sec\n", bottleneck);
230   printf("Packet-loss Percentage... %d\n", packetLossPercent);
231   printf("\n");
232 
233 #ifdef WIN32
234   starttime = clock() / (double)CLOCKS_PER_SEC; /* Runtime statistics */
235 #endif
236 
237   /* Initialize the ISAC and BN structs */
238   err = WebRtcIsac_Create(&ISAC_main_inst);
239 
240   WebRtcIsac_SetEncSampRate(ISAC_main_inst, sampFreqKHz * 1000);
241   WebRtcIsac_SetDecSampRate(ISAC_main_inst, sampFreqKHz >= 32 ? 32000 : 16000);
242   /* Error check */
243   if (err < 0) {
244     fprintf(stderr, "\n\n Error in create.\n\n");
245     exit(EXIT_FAILURE);
246   }
247 
248   framecnt = 0;
249   endfile = 0;
250 
251   /* Initialize encoder and decoder */
252   if (WebRtcIsac_EncoderInit(ISAC_main_inst, codingMode) < 0) {
253     printf("cannot initialize encoder\n");
254     return -1;
255   }
256   WebRtcIsac_DecoderInit(ISAC_main_inst);
257 
258   // {
259   //   int32_t b1, b2;
260   //   FILE* fileID = fopen("GetBNTest.txt", "w");
261   //   b2 = 32100;
262   //   while (b2 <= 52000) {
263   //     WebRtcIsac_Control(ISAC_main_inst, b2, frameSize);
264   //     WebRtcIsac_GetUplinkBw(ISAC_main_inst, &b1);
265   //     fprintf(fileID, "%5d %5d\n", b2, b1);
266   //     b2 += 10;
267   //   }
268   // }
269 
270   if (codingMode == 1) {
271     if (WebRtcIsac_Control(ISAC_main_inst, bottleneck, frameSize) < 0) {
272       printf("cannot set bottleneck\n");
273       return -1;
274     }
275   } else {
276     if (WebRtcIsac_ControlBwe(ISAC_main_inst, 15000, 30, 1) < 0) {
277       printf("cannot configure BWE\n");
278       return -1;
279     }
280   }
281 
282   if (WebRtcIsac_SetMaxPayloadSize(ISAC_main_inst, payloadLimit) < 0) {
283     printf("cannot set maximum payload size %d.\n", payloadLimit);
284     return -1;
285   }
286 
287   if (rateLimit < 106800) {
288     if (WebRtcIsac_SetMaxRate(ISAC_main_inst, rateLimit) < 0) {
289       printf("cannot set the maximum rate %d.\n", rateLimit);
290       return -1;
291     }
292   }
293 
294   //=====================================
295   //#ifdef HAVE_DEBUG_INFO
296   //    if(setupDebugStruct(&debugInfo) < 0)
297   //    {
298   //        exit(1);
299   //    }
300   //#endif
301 
302   while (endfile == 0) {
303     fprintf(stderr, "  \rframe = %7li", framecnt);
304 
305     //============== Readind from the file and encoding =================
306     cur_framesmpls = 0;
307     stream_len = 0;
308 
309     if (onlyDecode) {
310       uint8_t auxUW8;
311       if (fread(&auxUW8, sizeof(uint8_t), 1, inp) < 1) {
312         break;
313       }
314       stream_len = auxUW8 << 8;
315       if (fread(&auxUW8, sizeof(uint8_t), 1, inp) < 1) {
316         break;
317       }
318       stream_len |= auxUW8;
319       if (fread(payload, 1, stream_len, inp) < stream_len) {
320         printf("last payload is corrupted\n");
321         break;
322       }
323     } else {
324       while (stream_len == 0) {
325         int stream_len_int;
326 
327         // Read 10 ms speech block
328         endfile = readframe(shortdata, inp, samplesIn10Ms);
329         if (endfile) {
330           break;
331         }
332         cur_framesmpls += samplesIn10Ms;
333 
334         //-------- iSAC encoding ---------
335         stream_len_int = WebRtcIsac_Encode(ISAC_main_inst, shortdata, payload);
336 
337         if (stream_len_int < 0) {
338           // exit if returned with error
339           // errType=WebRtcIsac_GetErrorCode(ISAC_main_inst);
340           fprintf(stderr, "\nError in encoder\n");
341           getc(stdin);
342           exit(EXIT_FAILURE);
343         }
344         stream_len = (size_t)stream_len_int;
345       }
346       //===================================================================
347       if (endfile) {
348         break;
349       }
350 
351       rcuStreamLen = WebRtcIsac_GetRedPayload(ISAC_main_inst, payloadRCU);
352       if (rcuStreamLen < 0) {
353         fprintf(stderr, "\nError getting RED payload\n");
354         getc(stdin);
355         exit(EXIT_FAILURE);
356       }
357 
358       get_arrival_time(cur_framesmpls, stream_len, bottleneck, &packetData,
359                        sampFreqKHz * 1000, sampFreqKHz * 1000);
360       if (WebRtcIsac_UpdateBwEstimate(
361               ISAC_main_inst, payload, stream_len, packetData.rtp_number,
362               packetData.sample_count, packetData.arrival_time) < 0) {
363         printf(" BWE Error at client\n");
364         return -1;
365       }
366     }
367 
368     if (endfile) {
369       break;
370     }
371 
372     maxStreamLen = (stream_len > maxStreamLen) ? stream_len : maxStreamLen;
373     packetCntr++;
374 
375     hist[stream_len]++;
376     if (averageFile != NULL) {
377       tmpSumStreamLen += stream_len;
378       if (packetCntr == 100) {
379         // kbps
380         fprintf(averageFile, "%8.3f ",
381                 tmpSumStreamLen * 8.0 / (30.0 * packetCntr));
382         packetCntr = 0;
383         tmpSumStreamLen = 0;
384       }
385     }
386 
387     if (onlyEncode) {
388       uint8_t auxUW8;
389       auxUW8 = (uint8_t)(((stream_len & 0x7F00) >> 8) & 0xFF);
390       if (fwrite(&auxUW8, sizeof(uint8_t), 1, outp) != 1) {
391         return -1;
392       }
393 
394       auxUW8 = (uint8_t)(stream_len & 0xFF);
395       if (fwrite(&auxUW8, sizeof(uint8_t), 1, outp) != 1) {
396         return -1;
397       }
398       if (fwrite(payload, 1, stream_len, outp) != stream_len) {
399         return -1;
400       }
401     } else {
402       //======================= iSAC decoding ===========================
403 
404       if ((rand() % 100) < packetLossPercent) {
405         declen = WebRtcIsac_DecodeRcu(ISAC_main_inst, payloadRCU,
406                                       (size_t)rcuStreamLen, decoded,
407                                       speechType);
408         lostPacketCntr++;
409       } else {
410         declen = WebRtcIsac_Decode(ISAC_main_inst, payload, stream_len, decoded,
411                                    speechType);
412       }
413       if (declen <= 0) {
414         // errType=WebRtcIsac_GetErrorCode(ISAC_main_inst);
415         fprintf(stderr, "\nError in decoder.\n");
416         getc(stdin);
417         exit(1);
418       }
419 
420       // Write decoded speech frame to file
421       if (fwrite(decoded, sizeof(int16_t), declen, outp) != (size_t)declen) {
422         return -1;
423       }
424       cur_framesmpls = declen;
425     }
426     // Update Statistics
427     framecnt++;
428     totalsmpls += cur_framesmpls;
429     if (stream_len > 0) {
430       totalbits += 8 * stream_len;
431     }
432     if (rcuStreamLen > 0) {
433       totalBitsRCU += 8 * rcuStreamLen;
434     }
435   }
436 
437   rate = ((double)totalbits * (sampFreqKHz)) / (double)totalsmpls;
438   rateRCU = ((double)totalBitsRCU * (sampFreqKHz)) / (double)totalsmpls;
439 
440   printf("\n\n");
441   printf("Sampling Rate............... %d kHz\n", sampFreqKHz);
442   printf("Payload Limit............... %d bytes \n", payloadLimit);
443   printf("Rate Limit.................. %d bits/sec \n", rateLimit);
444 
445 #ifdef WIN32
446 #ifdef HAVE_DEBUG_INFO
447   rateLB =
448       ((double)debugInfo.lbBytes * 8. * (sampFreqKHz)) / (double)totalsmpls;
449   rateUB =
450       ((double)debugInfo.ubBytes * 8. * (sampFreqKHz)) / (double)totalsmpls;
451 #endif
452 
453   fprintf(bitrateFile, "%d  %10u     %d     %6.3f  %6.3f    %6.3f\n",
454           sampFreqKHz, framecnt, bottleneck, rateLB, rateUB, rate);
455   fclose(bitrateFile);
456 #endif  // WIN32
457 
458   printf("\n");
459   printf("Measured bit-rate........... %0.3f kbps\n", rate);
460   printf("Measured RCU bit-ratre...... %0.3f kbps\n", rateRCU);
461   printf("Maximum bit-rate/payloadsize %0.3f / %" PRIuS "\n",
462          maxStreamLen * 8 / 0.03, maxStreamLen);
463   printf("Measured packet-loss........ %0.1f%% \n",
464          100.0f * (float)lostPacketCntr / (float)packetCntr);
465 
466   // #ifdef HAVE_DEBUG_INFO
467   // printf("Measured lower-band bit-rate %0.3f kbps (%.0f%%)\n",
468   //        rateLB, (double)(rateLB) * 100. /(double)(rate));
469   // printf("Measured upper-band bit-rate %0.3f kbps (%.0f%%)\n",
470   //        rateUB, (double)(rateUB) * 100. /(double)(rate));
471   //
472   // printf("Maximum payload lower-band.. %d bytes (%0.3f kbps)\n",
473   //        debugInfo.maxPayloadLB, debugInfo.maxPayloadLB * 8.0 / 0.03);
474   // printf("Maximum payload upper-band.. %d bytes (%0.3f kbps)\n",
475   //        debugInfo.maxPayloadUB, debugInfo.maxPayloadUB * 8.0 / 0.03);
476   // #endif
477 
478   printf("\n");
479 
480 /* Runtime statistics */
481 #ifdef WIN32
482   runtime = (double)(clock() / (double)CLOCKS_PER_SEC - starttime);
483   length_file = ((double)framecnt * (double)declen / (sampFreqKHz * 1000));
484   printf("Length of speech file....... %.1f s\n", length_file);
485   printf("Time to run iSAC............ %.2f s (%.2f %% of realtime)\n\n",
486          runtime, (100 * runtime / length_file));
487 #endif
488   printf("\n\n_______________________________________________\n");
489 
490   if (histFile != NULL) {
491     int n;
492     for (n = 0; n < 600; n++) {
493       fprintf(histFile, "%6d ", hist[n]);
494     }
495     fprintf(histFile, "\n");
496     fclose(histFile);
497   }
498   if (averageFile != NULL) {
499     if (packetCntr > 0) {
500       fprintf(averageFile, "%8.3f ",
501               tmpSumStreamLen * 8.0 / (30.0 * packetCntr));
502     }
503     fprintf(averageFile, "\n");
504     fclose(averageFile);
505   }
506 
507   fclose(inp);
508   fclose(outp);
509 
510   WebRtcIsac_Free(ISAC_main_inst);
511 
512 #ifdef CHANGE_OUTPUT_NAME
513   {
514     char* p;
515     char myExt[50];
516     char bitRateStr[10];
517     char newOutName[500];
518     strcpy(newOutName, outname);
519 
520     myExt[0] = '\0';
521     p = strchr(newOutName, '.');
522     if (p != NULL) {
523       strcpy(myExt, p);
524       *p = '_';
525       p++;
526       *p = '\0';
527     } else {
528       strcat(newOutName, "_");
529     }
530     sprintf(bitRateStr, "%0.0fkbps", rate);
531     strcat(newOutName, bitRateStr);
532     strcat(newOutName, myExt);
533     rename(outname, newOutName);
534   }
535 #endif
536   exit(0);
537 }
538 
539 #ifdef HAVE_DEBUG_INFO
setupDebugStruct(debugStruct * str)540 int setupDebugStruct(debugStruct* str) {
541   str->prevPacketLost = 0;
542   str->currPacketLost = 0;
543 
544   OPEN_FILE_WB(str->res0to4FilePtr, "Res0to4.dat");
545   OPEN_FILE_WB(str->res4to8FilePtr, "Res4to8.dat");
546   OPEN_FILE_WB(str->res8to12FilePtr, "Res8to12.dat");
547   OPEN_FILE_WB(str->res8to16FilePtr, "Res8to16.dat");
548 
549   OPEN_FILE_WB(str->res0to4DecFilePtr, "Res0to4Dec.dat");
550   OPEN_FILE_WB(str->res4to8DecFilePtr, "Res4to8Dec.dat");
551   OPEN_FILE_WB(str->res8to12DecFilePtr, "Res8to12Dec.dat");
552   OPEN_FILE_WB(str->res8to16DecFilePtr, "Res8to16Dec.dat");
553 
554   OPEN_FILE_WB(str->in0to4FilePtr, "in0to4.dat");
555   OPEN_FILE_WB(str->in4to8FilePtr, "in4to8.dat");
556   OPEN_FILE_WB(str->in8to12FilePtr, "in8to12.dat");
557   OPEN_FILE_WB(str->in8to16FilePtr, "in8to16.dat");
558 
559   OPEN_FILE_WB(str->out0to4FilePtr, "out0to4.dat");
560   OPEN_FILE_WB(str->out4to8FilePtr, "out4to8.dat");
561   OPEN_FILE_WB(str->out8to12FilePtr, "out8to12.dat");
562   OPEN_FILE_WB(str->out8to16FilePtr, "out8to16.dat");
563   OPEN_FILE_WB(str->fftFilePtr, "riFFT.dat");
564   OPEN_FILE_WB(str->fftDecFilePtr, "riFFTDec.dat");
565 
566   OPEN_FILE_WB(str->arrivalTime, NULL /*"ArivalTime.dat"*/);
567   str->lastArrivalTime = 0;
568 
569   str->maxPayloadLB = 0;
570   str->maxPayloadUB = 0;
571   str->lbBytes = 0;
572   str->ubBytes = 0;
573 
574   return 0;
575 };
576 #endif
577