comparison intercom/g726/vbr-g726.c @ 2:13be24d74cd2

import intercom-0.4.1
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 09:57:52 +0200
parents
children
comparison
equal deleted inserted replaced
1:9cadc470e3da 2:13be24d74cd2
1 /* 21.Mar.2000 V1.3
2 ============================================================================
3
4 VBR-G726.C
5 ~~~~~~~~~~
6
7 Description:
8 ~~~~~~~~~~~~
9
10 Demonstration program for UGST/ITU-T G.726 module using the variable
11 bit rate feature. This version accepts either linear or G.711 A/u-law
12 input. Since this implementation of the G.726 requires G.711 compressed
13 samples, linear samples are converted to G.711 format before being
14 processed. Therefore, the same ammount of quantization distortion should
15 be expect either way.
16
17 The modules called have been originally written in Fortran, and were
18 translated into C by the converter f2c, version of October 15, 1990
19 at 19:58:17.
20
21 Input data is supposed to be aligned at word boundaries, i.e.,
22 organized in 16-bit words, following the operating system normal
23 organization (low-byte first for VMS and DOS; high byte first for most
24 Unix systems). Linear samples are supposed to be 16-bit right-adjusted.
25 G711 compressed data is supposed to be in the 8 LEAST
26 significant bits of the word and the ADPCM data is in the LEAST 5
27 bits. Both are without sign extension.
28
29 Output data will be generated in the same format as decribed above for
30 the input data.
31
32 Usage:
33 ~~~~~~
34 $ VBR-G726 [-options] InpFile OutFile
35 [FrameSize [1stBlock [NoOfBlocks [Reset]]]]
36 where:
37 InpFile is the name of the file to be processed;
38 OutFile is the name with the processed data;
39 FrameSize is the frame size, in number of samples; the bitrate
40 will only change in the boundaries of a frame
41 [default: 16 samples]
42 1stBlock is the number of the first block of the input file
43 to be processed [default: 1st block]
44 NoOfBlocks is the number of blocks to be processed, starting on
45 block "1stBlock" [default: all blocks]
46
47 Options:
48 -law # the letters A or a for G.711 A-law, letter u for
49 G.711 u-law, or letter l for linear. If linear is
50 chosen, A-law is used to compress/expand samples to/from
51 the G.726 routines. Default is A-law.
52 -rate # is the bit-rate (in kbit/s): 40, 32, 24 or 16 (in kbit/s);
53 or a combination of them using dashes (e.g. 32-24 or
54 16-24-32). Default is 32 kbit/s.
55 -frame # Number of samples per frame for switching bit rates.
56 Default is 16 samples (or 2ms)
57 -enc run only the G.726 encoder on the samples
58 [default: run encoder and decoder]
59 -dec run only the G.726 decoder on the samples
60 [default: run encoder and decoder]
61 -noreset don't apply reset to the encoder/decoder
62 -?/-help print help message
63
64 Example:
65 $ vbr-G726 -law u -enc -rate 32 voice.ref voice.adp 256 3 45
66
67 The command above takes the samples in file "voice.ref", already
68 in mu law format, processes the data through the G726 encoder
69 only at a rate of 32 bkit/s, saving them into the file
70 "voice.rel". The processing starts at block 3 for 45 blocks,
71 each block being 256 samples wide.
72
73 Variables:
74 ~~~~~~~~~~
75 law law to use (either A or u)
76 conv desired processing
77 rate desired rate
78 inpfil input file name;
79 outfil output file name;
80 N block size;
81 N1 first block to process;
82 N2 no. of blocks to process;
83
84 Exit values:
85 ~~~~~~~~~~~~
86 0 success (all but VMS);
87 1 success (only in VMS);
88 2 error opening input file;
89 3 error creating output file;
90 4 error moving pointer to desired start of conversion;
91 5 error reading input file;
92 6 error writing to file;
93 7 invalid law
94 8 invalid conversion
95 9 invalid rate
96
97 Original author:
98 ~~~~~~~~~~~~~~~~
99 Simao Ferraz de Campos Neto
100 Comsat Laboratories Tel: +1-301-428-4516
101 22300 Comsat Drive Fax: +1-301-428-9287
102 Clarksburg MD 20871 - USA E-mail: simao@ctd.comsat.com
103
104 History:
105 ~~~~~~~~
106 10/Mar/1995 v1.0 Created based on vbr-g726.c
107 22/Feb/1996 v1.1 Removed compilation warnings, included headers as
108 suggested by Kirchherr (FI/DBP Telekom) to run under
109 OpenVMS/AXP <simao@ctd.comsat.com>
110 22/Jul/1997 v1.2 Changed static allocation for data arrays to allow longer
111 frame sizes. Fix based on modifications by R. Kirchherr
112 <kirchherr@tzd.telekom.de>
113 21.Mar.2000 v1.3 Corrected bug when the bitrate is not specified by
114 the user. Corrected bug that made incorrect
115 calculation on total number of blocks to process
116 when the block size is not a multiple of the file
117 size. <simao.campos@labs.comsat.com>
118 ============================================================================
119 */
120
121 /* ..... General definitions for UGST demo programs ..... */
122 #include "ugstdemo.h"
123
124 /* ..... General include ..... */
125 #include <stdio.h>
126 #include <stdlib.h>
127 #include <string.h>
128 #include <math.h>
129 #include <ctype.h>
130
131 #if defined(VMS)
132 #include <unixio.h>
133 #include <stat.h>
134 #else /* Unix/DOS */
135 #include <sys/stat.h>
136 #endif
137
138 /* ..... G.726 module as include functions ..... */
139 #include "g726.h"
140 #include "g711.h"
141
142 /*
143 -------------------------------------------------------------------------
144 void parse_rate(char *str, short *rate);
145 ~~~~~~~~~~~~~~~
146 Parses string str with a list of bitrates for the operation of the G726
147 algorithm and return a list of them in rate, and the number of rates read.
148
149 Parameters:
150 ~~~~~~~~~~~
151 str ..... string pointing to a list of dash-separated bitrates to be used.
152 Valid examples are: 16 (single rate), 32-24 (duo-rate), etc.
153 rate .... string of short numbers with each of the specified rates.
154
155 Return:
156 ~~~~~~~
157 Returns the number of bitrates for the ADPCM operation, 0 if str is
158 empty or improper, and -1 if there are too many rates requested.
159
160 History:
161 ~~~~~~~~
162 10.Mar.95 v1.0 Created <simao@ctd.comsat.com>
163 -------------------------------------------------------------------------
164 */
165 int parse_rate(str, rate)
166 char *str;
167 short **rate;
168 {
169 char *s = str;
170 int count = 1, i;
171
172 if (str == NULL)
173 return 0;
174
175 while ((s = strchr(s, '-')) != NULL) {
176 s++;
177 count++;
178 }
179
180 /* Allocates memory for the necessary number of rates */
181 *rate = (short *) calloc(sizeof(short), count);
182 if (*rate == NULL)
183 return (-1);
184
185 /* Save rates in the array */
186 for (s = strtok(str, "-"), i = 0; i < count; i++) {
187 /* Convert to short & save */
188 (*rate)[i] = atoi(s);
189
190 /* Classification of rate - return 0 if invalid rate was specified */
191 if ((*rate)[i] > 5) {
192 if ((*rate)[i] == 40)
193 (*rate)[i] = 5;
194 else if ((*rate)[i] == 32)
195 (*rate)[i] = 4;
196 else if ((*rate)[i] == 24)
197 (*rate)[i] = 3;
198 else if ((*rate)[i] == 16)
199 (*rate)[i] = 2;
200 else
201 return (0);
202 }
203
204 /* Update s to the next valid rate number */
205 s = strtok(NULL, "-");
206 }
207
208 /* Return the number of rates */
209 return (count);
210 }
211
212 /* .................... End of parse_rate() ........................... */
213
214
215 /*
216 -------------------------------------------------------------------------
217 void display_usage(void);
218 ~~~~~~~~~~~~~~~~~~
219 Display proper usage for the demo program. Generated automatically from
220 program documentation.
221
222 History:
223 ~~~~~~~~
224 10.Mar.95 v1.0 Created <simao>.
225 -------------------------------------------------------------------------
226 */
227 #define P(x) printf x
228 void display_usage()
229 {
230 P(("Version 1.3 of 21/Mar/2000 \n\n"));
231
232 P((" VBR-G726.C \n"));
233 P((" Demonstration program for UGST/ITU-T G.726 module using the variable\n"));
234 P((" bit rate feature. This version accepts either linear or G.711 A/u-law\n"));
235 P((" input. Since this implementation of the G.726 requires G.711 compressed\n"));
236 P((" samples, linear samples are converted to G.711 format before being\n"));
237 P((" processed. Therefore, the same ammount of quantization distortion should\n"));
238 P((" be expect either way.\n"));
239 P((" Input data is supposed to be aligned at word boundaries, i.e.,\n"));
240 P((" organized in 16-bit words, following the operating system normal\n"));
241 P((" organization (low-byte first for VMS and DOS; high byte first for most\n"));
242 P((" Unix systems). Linear samples are supposed to be 16-bit right-adjusted. \n"));
243 P((" G711 compressed data is supposed to be in the 8 LEAST\n"));
244 P((" significant bits of the word and the ADPCM data is in the LEAST 5\n"));
245 P((" bits. Both are without sign extension.\n"));
246 P((" \n"));
247 P((" Output data will be generated in the same format as decribed above for\n"));
248 P((" the input data.\n"));
249 P((" \n"));
250 P((" Usage:\n"));
251 P((" VBR-G726 [-options] InpFile OutFile \n"));
252 P((" [FrameSize [1stBlock [NoOfBlocks [Reset]]]]\n"));
253 P((" where:\n"));
254 P((" InpFile is the name of the file to be processed;\n"));
255 P((" OutFile is the name with the processed data;\n"));
256 P((" FrameSize is the frame size, in number of samples; the bitrate \n"));
257 P((" will only change in the boundaries of a frame \n"));
258 P((" [default: 16 samples]\n"));
259 P((" 1stBlock is the number of the first block of the input file\n"));
260 P((" to be processed [default: 1st block]\n"));
261 P((" NoOfBlocks is the number of blocks to be processed, starting on\n"));
262 P((" block \"1stBlock\" [default: all blocks]\n"));
263 P(("\n"));
264 P((" Options:\n"));
265 P((" -law # the letters A or a for G.711 A-law, letter u for \n"));
266 P((" G.711 u-law, or letter l for linear. If linear is\n"));
267 P((" chosen, A-law is used to compress/expand samples to/from\n"));
268 P((" the G.726 routines. Default is A-law.\n"));
269 P((" -rate # is the bit-rate (in kbit/s): 40, 32, 24 or 16 (in kbit/s); \n"));
270 P((" or a combination of them using dashes (e.g. 32-24 or\n"));
271 P((" 16-24-32). Default is 32 kbit/s.\n"));
272 P((" -frame # Number of samples per frame for switching bit rates.\n"));
273 P((" Default is 16 samples (or 2ms) \n"));
274 P((" -enc run only the G.726 encoder on the samples \n"));
275 P((" [default: run encoder and decoder]\n"));
276 P((" -dec run only the G.726 decoder on the samples \n"));
277 P((" [default: run encoder and decoder]\n"));
278 P((" -noreset don't apply reset to the encoder/decoder\n"));
279 P((" -?/-help print help message\n"));
280 P(("\n"));
281
282 /* Quit program */
283 exit(-128);
284 }
285
286 #undef P
287 /* .................... End of display_usage() ........................... */
288
289
290 void G726_initEncode(G726_state *encoder_state)
291 {
292 memset(encoder_state, 0, sizeof(G726_state));
293 }
294
295 void G726_initDecode(G726_state *decoder_state)
296 {
297 memset(decoder_state, 0, sizeof(G726_state));
298 }
299
300 void g726pack(Byte *packed, short *in, int cnt)
301 {
302 int i;
303 for (i = 0; i <= cnt; i += 2, ++packed, ++in) {
304 *packed = (*in & 0xF);
305 ++in;
306 *packed += (*in & 0xF) * 16;
307 }
308 }
309
310 void g726unpack(short *out, Byte *packed, int cnt)
311 {
312 int i;
313 for (i = 0; i <= cnt; i += 2, ++packed, ++out) {
314 *out = (*packed & 0xF);
315 ++out;
316 *out = (*packed & 0xF0) / 16;
317 }
318 }
319
320 /*
321 **************************************************************************
322 *** ***
323 *** Demo-Program for testing the correct implementation ***
324 *** and to show how to use the programs ***
325 *** ***
326 **************************************************************************
327 */
328 int main(argc, argv)
329 int argc;
330 char *argv[];
331 {
332 G726_state encoder_state, decoder_state;
333 long N = 16, N1 = 1, N2 = 0, cur_blk, smpno;
334 short *tmp_buf, *inp_buf, *out_buf, reset = 1;
335 Byte tmpb_buf[N], outb_buf[N];
336 short inp_type, out_type, *rate = 0;
337 char encode = 1, decode = 1, law[4] = "A", def_rate[] = "32";
338 int rateno = 1, rate_idx;
339
340 /* General-purpose, progress indication */
341 static char quiet = 0, funny[9] = "|/-\\|/-\\";
342
343 /* File variables */
344 char FileIn[80], FileOut[80];
345 FILE *Fi, *Fo;
346 int inp, out;
347 long start_byte;
348 #ifdef VMS
349 char mrs[15];
350 #endif
351
352 /*
353 * ......... PARAMETERS FOR PROCESSING .........
354 */
355
356 /* GETTING OPTIONS */
357
358 if (argc < 2)
359 display_usage();
360 else {
361 while (argc > 1 && argv[1][0] == '-')
362 if (strcmp(argv[1], "-noreset") == 0) {
363 /* No reset */
364 reset = 0;
365
366 /* Update argc/argv to next valid option/argument */
367 argv++;
368 argc--;
369 } else if (strcmp(argv[1], "-enc") == 0) {
370 /* Encoder-only operation */
371 encode = 1;
372 decode = 0;
373
374 /* Move argv over the option to the next argument */
375 argv++;
376 argc--;
377 } else if (strcmp(argv[1], "-dec") == 0) {
378 /*Decoder-only operation */
379 encode = 0;
380 decode = 1;
381
382 /* Move argv over the option to the next argument */
383 argv++;
384 argc--;
385 } else if (strcmp(argv[1], "-law") == 0) {
386 /* Define law for operation: A, u, or linear */
387 switch (toupper(argv[2][0])) {
388 case 'A':
389 law[0] = '1';
390 break;
391 case 'U':
392 law[0] = '0';
393 break;
394 case 'L':
395 law[0] = '2';
396 break;
397 default:
398 HARAKIRI(" Invalid law (A or u)! Aborted...\n", 7);
399 }
400
401 /* Move argv over the option to the next argument */
402 argv += 2;
403 argc -= 2;
404 } else if (strcmp(argv[1], "-frame") == 0) {
405 /* Define Frame size for rate change during operation */
406 N = atoi(argv[2]);
407
408 /* Move argv over the option to the next argument */
409 argv += 2;
410 argc -= 2;
411 } else if (strcmp(argv[1], "-rate") == 0) {
412 /*Define rate(s) for operation */
413 rateno = parse_rate(argv[2], &rate);
414 if (rateno == 0) {
415 fprintf(stderr, "Invalid bitrate list: %s\n", argv[2]);
416 exit(9);
417 }
418 /* Move argv over the option to the next argument */
419 argv += 2;
420 argc -= 2;
421 } else if (strcmp(argv[1], "-q") == 0) {
422 /* Don't print progress indicator */
423 quiet = 1;
424
425 /* Move argv over the option to the next argument */
426 argv++;
427 argc--;
428 } else if (strcmp(argv[1], "-?") == 0
429 || strcmp(argv[1], "-help") == 0) {
430 /* Print help */
431 display_usage();
432 } else {
433 fprintf(stderr,
434 "ERROR! Invalid option \"%s\" in command line\n\n", argv[1]);
435 display_usage();
436 }
437 }
438
439 /* Now get regular parameters */
440 GET_PAR_S(1, "_Input File: .................. ", FileIn);
441 GET_PAR_S(2, "_Output File: ................. ", FileOut);
442 FIND_PAR_L(3, "_Block Size: .................. ", N, N);
443 FIND_PAR_L(4, "_Starting Block: .............. ", N1, N1);
444 FIND_PAR_L(5, "_No. of Blocks: ............... ", N2, N2);
445
446 /* Uses default rate if none is given */
447 if (rate == 0)
448 rateno = parse_rate(def_rate, &rate);
449
450 /* Inform user of the compading law used: 0->u, 1->A, 2->linear */
451 fprintf(stderr, "Using %s\n",
452 law[0] == '1' ? "A-law" : (law[0] == '0' ? "u-law" : "linear PCM"));
453
454 /* Find starting byte in file */
455 start_byte = sizeof(short) * (long) (--N1) * (long) N;
456
457 /* Check if is to process the whole file */
458 if (N2 == 0) {
459 struct stat st;
460
461 /* ... find the input file size ... */
462 stat(FileIn, &st);
463 N2 = ceil((st.st_size - start_byte) / (double) (N * sizeof(short)));
464 }
465
466 /* Define correct data I/O types */
467 if (encode && decode) {
468 inp_type = out_type = (law[0] == '2' ? IS_LIN : IS_LOG);
469 } else if (encode) {
470 inp_type = law[0] == '2' ? IS_LIN : IS_LOG;
471 out_type = IS_ADPCM;
472 } else {
473 inp_type = IS_ADPCM;
474 out_type = law[0] == '2' ? IS_LIN : IS_LOG;
475 }
476
477 /* Force law to be used *by the ADPCM* to A-law, if input is linear */
478 if (law[0] == '2')
479 law[0] = '1';
480
481 /*
482 * ...... MEMORY ALLOCATION .........
483 */
484
485 if ((inp_buf = (short *) calloc(N, sizeof(short))) == NULL)
486 HARAKIRI("Error in memory allocation!\n", 1);
487 if ((out_buf = (short *) calloc(N, sizeof(short))) == NULL)
488 HARAKIRI("Error in memory allocation!\n", 1);
489 if ((tmp_buf = (short *) calloc(N, sizeof(short))) == NULL)
490 HARAKIRI("Error in memory allocation!\n", 1);
491
492 /*
493 * ......... FILE PREPARATION .........
494 */
495
496 /* Opening input file; abort if there's any problem */
497 if ((Fi = fopen(FileIn, "rb")) == NULL)
498 KILL(FileIn, 2);
499 inp = fileno(Fi);
500
501 /* Creates output file */
502 #ifdef VMS
503 sprintf(mrs, "mrs=%d", 512);
504 #endif
505 if ((Fo = fopen(FileOut, WB)) == NULL)
506 KILL(FileOut, 3);
507 out = fileno(Fo);
508
509 /* Move pointer to 1st block of interest */
510 if (fseek(Fi, start_byte, 0) < 0l)
511 KILL(FileIn, 4);
512
513 /*
514 * ......... PROCESSING ACCORDING TO ITU-T G.726 .........
515 */
516 /* Reset VBR counters */
517 rate_idx = 0;
518
519 for (cur_blk = 0; cur_blk < N2; cur_blk++) {
520 /* Set the proper rate index */
521 rate_idx = cur_blk % rateno;
522
523 /* Print progress flag */
524 if (!quiet)
525 #ifdef DISPLAY_CURRENT_RATE
526 fprintf(stderr, "%d-", 8 * rate[rate_idx]);
527 #else
528 fprintf(stderr, "%c\r", funny[cur_blk % 8]);
529 #endif
530
531 /* Read a block of samples */
532 if ((smpno = fread(inp_buf, sizeof(short), N, Fi)) < 0)
533 KILL(FileIn, 5);
534
535 /* Compress linear input samples */
536 if (inp_type == IS_LIN) {
537 /* Compress using A-law */
538 alaw_compress(smpno, inp_buf, tmpb_buf);
539
540 /* copy temporary buffer over input buffer */
541 // memcpy(inp_buf, tmp_buf, sizeof(short) * smpno);
542 }
543
544 /* Check if reset is needed */
545 reset = (reset == 1 && cur_blk == 0) ? 1 : 0;
546
547 /* Carry out the desired operation */
548 if (encode && !decode)
549 G726_encode(tmpb_buf, out_buf, smpno, law,
550 rate[rate_idx], reset, &encoder_state);
551 else if (decode && !encode)
552 G726_decode(inp_buf, outb_buf, smpno, law,
553 rate[rate_idx], reset, &decoder_state);
554 else if (encode && decode) {
555 Byte g726_buf[N/2];
556
557 G726_encode(tmpb_buf, tmp_buf, smpno, law,
558 rate[rate_idx], reset, &encoder_state);
559 // printf ("rate[rate_idx] = %d\n", rate[rate_idx]);
560 g726pack(g726_buf, tmp_buf, smpno);
561
562 g726unpack(tmp_buf, g726_buf, smpno);
563
564 G726_decode(tmp_buf, outb_buf, smpno, law,
565 rate[rate_idx], reset, &decoder_state);
566 }
567
568 /* Expand linear input samples */
569 if (out_type == IS_LIN) {
570 /* Compress using A-law */
571 alaw_expand(smpno, outb_buf, tmp_buf);
572
573 /* copy temporary buffer over input buffer */
574 memcpy(out_buf, tmp_buf, sizeof(short) * smpno);
575 }
576
577 /* Write ADPCM output word */
578 if ((smpno = fwrite(out_buf, sizeof(short), smpno, Fo)) < 0)
579 KILL(FileOut, 6);
580 }
581
582 /*
583 * ......... FINALIZATIONS .........
584 */
585
586 /* Free allocated memory */
587 free(tmp_buf);
588 free(out_buf);
589 free(inp_buf);
590 free(rate);
591
592 /* Close input and output files */
593 fclose(Fi);
594 fclose(Fo);
595
596 /* Exit with success for non-vms systems */
597 #ifndef VMS
598 return (0);
599 #endif
600 }
601
602 /* ............................. end of main() ............................. */

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.