Mercurial > hg > audiostuff
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() ............................. */ |