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