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