Home | History | Annotate | Download | only in test
      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 
     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
    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