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