2
|
1 /* 21/Mar/2000 V1.2
|
|
2 ============================================================================
|
|
3
|
|
4 G726DEMO.C
|
|
5 ~~~~~~~~~~
|
|
6
|
|
7 Description:
|
|
8 ~~~~~~~~~~~~
|
|
9
|
|
10 Demonstration program for UGST/ITU-T G.726 module (the same as the Blue
|
|
11 Book G.726). Takes the input file and processes by the G.726 codec,
|
|
12 depending on user's option: for encoding, input must be in either A
|
|
13 or mu law (G711), for decoding, in ADPCM format. The modules called have
|
|
14 been originally written in Fortran, and were translated into C by the
|
|
15 converter f2c, version of October 15, 1990 at 19:58:17.
|
|
16
|
|
17 Input data is supposed to be aligned at word boundaries, i.e.,
|
|
18 organized in 16-bit words, following the operating system normal
|
|
19 organization (low-byte first for VMS and DOS; high byte first
|
|
20 for most Unix systems). G711 compressed data is supposed to be
|
|
21 in the 8 LEAST significant bits of the word and the ADPCM data
|
|
22 is in the LEAST 5 bits. Both are without sign extension.
|
|
23
|
|
24 Output data will be generated in the same format as decribed
|
|
25 above for the input data.
|
|
26
|
|
27 Usage:
|
|
28 ~~~~~~
|
|
29 $ G726demo [-options] Law Transf Rate InpFile OutFile
|
|
30 [BlockSize [1stBlock [NoOfBlocks [Reset]]]]
|
|
31 where:
|
|
32 Law is the law desired (either A or u)
|
|
33 Transf is the desired conversion on the input file:
|
|
34 [lolo], (A/u)log -> ADPCM -> (A/u) log
|
|
35 [load], (A/u)log -> ADPCM
|
|
36 [adlo], ADPCM -> (A/u) log
|
|
37 Rate is the number of ADPCM bits per sample:
|
|
38 [5],[40] -> 5 bits per sample (40 kbit/s)
|
|
39 [4],[32] -> 4 bits per sample (32 kbit/s)
|
|
40 [3],[24] -> 3 bits per sample (24 kbit/s)
|
|
41 [2],[16] -> 2 bits per sample (16 kbit/s)
|
|
42 InpFile is the name of the file to be processed;
|
|
43 OutFile is the name with the processed data;
|
|
44 BlockSize is the block size, in number of samples
|
|
45 1stBlock is the number of the first block of the input file
|
|
46 to be processed;
|
|
47 NoOfBlocks is the number of blocks to be processed, starting on
|
|
48 block "1stBlock"
|
|
49 Reset is the optional reset. If specified as 1, the
|
|
50 coder and decoder will be reset at the very beginning of
|
|
51 the processings. If 0, the processing will start with
|
|
52 the variables at a unknown state. It defaults to 1
|
|
53 (reset ON).
|
|
54 Options:
|
|
55 -noreset don't apply reset to the encoder/decoder
|
|
56 -?/-help print help message
|
|
57
|
|
58
|
|
59 Example:
|
|
60 $ G726demo u lolo 4 voice.ref voice.rel 256 3 45 *OR*
|
|
61 $ G726demo u lolo 32 voice.ref voice.rel 256 3 45
|
|
62
|
|
63 The command above takes the samples in file "voice.ref", already
|
|
64 in mu law format, processes the data through the G726 encoder
|
|
65 and decoder at a rate of 32 bkit/s, saving them into the file
|
|
66 "voice.rel". The processing starts at block 3 for 45 blocks,
|
|
67 each block being 256 samples wide.
|
|
68
|
|
69 Original authors:
|
|
70 ~~~~~~~~~~~~~~~~~
|
|
71 Simao Ferraz de Campos Neto EMail : simao@cpqd.ansp.br (32k)
|
|
72 Fernando Tofolli Queiroz EMail : tdfernan@cpqd.ansp.br (extension)
|
|
73
|
|
74 CPqD/Telebras Rd. Mogi Mirim-Campinas Km.118
|
|
75 DDS/Pr.11 13.088-061 - Campinas - SP (Brazil)
|
|
76
|
|
77 History:
|
|
78 ~~~~~~~~
|
|
79 28/Feb/1994 v1.0 Release of 1st version of this demo program
|
|
80 based on the g721demo of the STL92. G.726
|
|
81 functionality added by Fernando Toffoli Queiroz
|
|
82 <tdfernan@cpqd.ansp.br>; usage routine and
|
|
83 portability tests by Simao.
|
|
84 22/Feb/1996 v1.1 Removed compilation warnings, included headers as
|
|
85 suggested by Kirchherr (FI/DBP Telekom) to run under
|
|
86 OpenVMS/AXP <simao@ctd.comsat.com>
|
|
87 21/Mar/2000 v1.2 Changed memory allocation of floating point buffers
|
|
88 tmp_buf[], inp_buf[] and out_buf[] from static to
|
|
89 dynamic, to prevent memory invasion
|
|
90 when block sizes larger than 256 are specified.
|
|
91 Corrected bug that made incorrect calculation on
|
|
92 total number of blocks to process when the block
|
|
93 size is not a multiple of the file
|
|
94 size. <simao.campos@labs.comsat.com>
|
|
95
|
|
96 ============================================================================
|
|
97 */
|
|
98
|
|
99
|
|
100 /* ..... General definitions for UGST demo programs ..... */
|
|
101 #include "ugstdemo.h"
|
|
102
|
|
103 /* ..... General include ..... */
|
|
104 #include <stdio.h>
|
|
105 #include <string.h>
|
|
106 #include <stdlib.h>
|
|
107 #include <ctype.h>
|
|
108 #include <math.h>
|
|
109
|
|
110 #if defined(VMS)
|
|
111 #include <stat.h>
|
|
112 #else /* Unix/DOS */
|
|
113 #include <sys/stat.h>
|
|
114 #endif
|
|
115
|
|
116 /* ..... G.726 module as include functions ..... */
|
|
117 #include "g726.h"
|
|
118
|
|
119 /*
|
|
120 -------------------------------------------------------------------------
|
|
121 void display_usage(void);
|
|
122 ~~~~~~~~~~~~~~~~~~
|
|
123 Display proper usage for the demo program. Generated automatically from
|
|
124 program documentation.
|
|
125
|
|
126 History:
|
|
127 ~~~~~~~~
|
|
128 8.Mar.94 v1.0 Created.
|
|
129 -------------------------------------------------------------------------
|
|
130 */
|
|
131 #define P(x) printf x
|
|
132 void display_usage()
|
|
133 {
|
|
134 P(("G726DEMO - Version 1.2 of 21/Mar/2000 \n\n"));
|
|
135
|
|
136 P(("> Description:\n"));
|
|
137 P((" Demonstration program for UGST/ITU-T G.726 module. Takes the\n"));
|
|
138 P((" input file and processes by the G.726 codec,\n"));
|
|
139 P((" depending on user's option: for encoding, input must be in\n"));
|
|
140 P((" either A or mu law (G711), for decoding, in ADPCM format. The\n"));
|
|
141 P((" modules called have been originally written in Fortran, and were\n"));
|
|
142 P((" translated into C by the converter f2c, version of October 15,1990\n"));
|
|
143 P(("\n"));
|
|
144 P((" Input data is supposed to be aligned at word boundaries, i.e.,\n"));
|
|
145 P((" organized in 16-bit words, following the operating system normal\n"));
|
|
146 P((" organization (low-byte first for VMS and DOS; high byte first\n"));
|
|
147 P((" for most Unix systems). G711 compressed data is supposed to be\n"));
|
|
148 P((" in the 8 LEAST significant bits of the word and the ADPCM data\n"));
|
|
149 P((" is in the LEAST 5 bits. Both are without sign extension.\n"));
|
|
150 P(("\n"));
|
|
151 P((" Output data will be generated in the same format as decribed\n"));
|
|
152 P((" above for the input data.\n"));
|
|
153 P(("\n"));
|
|
154
|
|
155 P(("> Usage:\n"));
|
|
156 P(("$ G726demo [-options] Law Transf Rate InpFile OutFile \n"));
|
|
157 P((" [BlockSize [1stBlock [NoOfBlocks [Reset]]]]\n"));
|
|
158 P((" where:\n"));
|
|
159 P((" Law is the law desired (either A or u)\n"));
|
|
160 P((" Transf is the desired conversion on the input file:\n"));
|
|
161 P((" [lolo], (A/u)log -> ADPCM -> (A/u) log\n"));
|
|
162 P((" [load], (A/u)log -> ADPCM \n"));
|
|
163 P((" [adlo], ADPCM -> (A/u) log\n"));
|
|
164 P((" Rate is the number of ADPCM bits per sample:\n"));
|
|
165 P((" [5],[40] -> 5 bits per sample (40 kbit/s)\n"));
|
|
166 P((" [4],[32] -> 4 bits per sample (32 kbit/s)\n"));
|
|
167 P((" [3],[24] -> 3 bits per sample (24 kbit/s)\n"));
|
|
168 P((" [2],[16] -> 2 bits per sample (16 kbit/s)\n"));
|
|
169 P((" InpFile is the name of the file to be processed;\n"));
|
|
170 P((" OutFile is the name with the processed data;\n"));
|
|
171 P((" BlockSize is the block size, in number of samples\n"));
|
|
172 P((" 1stBlock is the number of the first block of the input file\n"));
|
|
173 P((" to be processed;\n"));
|
|
174 P((" NoOfBlocks is the number of blocks to be processed, starting on\n"));
|
|
175 P((" block \"1stBlock\"\n"));
|
|
176 P((" Reset is the optional reset. If specified as 1, the\n"));
|
|
177 P((" coder and decoder will be reset at the very\n"));
|
|
178 P((" beginning of the processings. If 0, the\n"));
|
|
179 P((" processing will start with the variables at a\n"));
|
|
180 P((" unknown state. It defaults to 1 (reset ON). \n"));
|
|
181 P((" Options: \n"));
|
|
182 P((" -noreset don't apply reset to the encoder/decoder\n"));
|
|
183 P((" -? or -help print this help message\n"));
|
|
184 P(("\n"));
|
|
185
|
|
186 /* Quit program */
|
|
187 exit(-128);
|
|
188 }
|
|
189
|
|
190 #undef P
|
|
191 /* .................... End of display_usage() ........................... */
|
|
192
|
|
193
|
|
194 /*
|
|
195 **************************************************************************
|
|
196 *** ***
|
|
197 *** Demo-Program for testing the correct implementation ***
|
|
198 *** and to show how to use the programs ***
|
|
199 *** ***
|
|
200 **************************************************************************
|
|
201 */
|
|
202 int main(argc, argv)
|
|
203 int argc;
|
|
204 char *argv[];
|
|
205 {
|
|
206 G726_state encoder_state, decoder_state;
|
|
207 long N = 256, N1 = 1, N2 = 0, cur_blk, smpno;
|
|
208 short *tmp_buf, *inp_buf, *out_buf, reset = 1;
|
|
209 short inp_type, out_type, rate;
|
|
210
|
|
211 /* Progress indication */
|
|
212 static char quiet = 0, funny[9] = "|/-\\|/-\\";
|
|
213
|
|
214 /* File variables */
|
|
215 char FileIn[80], FileOut[80], law[4], lilo[8];
|
|
216 FILE *Fi, *Fo;
|
|
217 int inp, out;
|
|
218 long start_byte;
|
|
219 #ifdef VMS
|
|
220 char mrs[15];
|
|
221 #endif
|
|
222
|
|
223 /*
|
|
224 * ......... PARAMETERS FOR PROCESSING .........
|
|
225 */
|
|
226
|
|
227 /* GETTING OPTIONS */
|
|
228
|
|
229 if (argc < 2)
|
|
230 display_usage();
|
|
231 else {
|
|
232 while (argc > 1 && argv[1][0] == '-')
|
|
233 if (strcmp(argv[1], "-noreset") == 0) {
|
|
234 /* No reset */
|
|
235 reset = 0;
|
|
236
|
|
237 /* Update argc/argv to next valid option/argument */
|
|
238 argv++;
|
|
239 argc--;
|
|
240 } else if (strcmp(argv[1], "-q") == 0) {
|
|
241 /* Don't print progress indicator */
|
|
242 quiet = 1;
|
|
243
|
|
244 /* Move argv over the option to the next argument */
|
|
245 argv++;
|
|
246 argc--;
|
|
247 } else if (strcmp(argv[1], "-?") == 0
|
|
248 || strcmp(argv[1], "-help") == 0) {
|
|
249 /* Print help */
|
|
250 display_usage();
|
|
251 } else {
|
|
252 fprintf(stderr,
|
|
253 "ERROR! Invalid option \"%s\" in command line\n\n", argv[1]);
|
|
254 display_usage();
|
|
255 }
|
|
256 }
|
|
257
|
|
258 /* Now get regular parameters */
|
|
259 GET_PAR_S(1, "_Law (A,u): ................... ", law);
|
|
260 GET_PAR_S(2, "_Operation (lolo,load,adlo): .. ", lilo);
|
|
261 GET_PAR_I(3, "_Rate or bits/ADPCM sample: ... ", rate);
|
|
262 GET_PAR_S(4, "_Input File: .................. ", FileIn);
|
|
263 GET_PAR_S(5, "_Output File: ................. ", FileOut);
|
|
264 FIND_PAR_L(6, "_Block Size: .................. ", N, 256);
|
|
265 FIND_PAR_L(7, "_Starting Block: .............. ", N1, 1);
|
|
266 FIND_PAR_L(8, "_No. of Blocks: ............... ", N2, 0);
|
|
267 FIND_PAR_I(9, "_Reset (YES=1, NO=0): ......... ", reset, 1);
|
|
268
|
|
269 /* Find starting byte in file */
|
|
270 start_byte = sizeof(short) * (long) (--N1) * (long) N;
|
|
271
|
|
272 /* Check if is to process the whole file */
|
|
273 if (N2 == 0) {
|
|
274 struct stat st;
|
|
275
|
|
276 /* ... find the input file size ... */
|
|
277 stat(FileIn, &st);
|
|
278 N2 = ceil((st.st_size - start_byte) / (double) (N * sizeof(short)));
|
|
279 }
|
|
280
|
|
281 /* Classification of the conversion desired */
|
|
282 inp_type = toupper(lilo[1]) == 'O' ? IS_LOG : IS_ADPCM;
|
|
283 out_type = toupper(lilo[3]) == 'O' ? IS_LOG : IS_ADPCM;
|
|
284 if ((out_type == IS_ADPCM) && (inp_type == IS_ADPCM))
|
|
285 HARAKIRI("Bad conversion chosen (lolo,load,adlo)! Aborted...\n", 8);
|
|
286
|
|
287 /* Classification of law */
|
|
288 if (toupper(law[0]) == (char) 'A')
|
|
289 law[0] = '1';
|
|
290 else if (toupper(law[0]) == (char) 'U')
|
|
291 law[0] = '0';
|
|
292 else
|
|
293 HARAKIRI(" Invalid law (A or u)! Aborted...\n", 7);
|
|
294
|
|
295 /* Classification of rate */
|
|
296 if (rate > 5) {
|
|
297 if (rate == 40)
|
|
298 rate = 5;
|
|
299 else if (rate == 32)
|
|
300 rate = 4;
|
|
301 else if (rate == 24)
|
|
302 rate = 3;
|
|
303 else if (rate == 16)
|
|
304 rate = 2;
|
|
305 else {
|
|
306 HARAKIRI(" Invalid rate (5/4/3/2) or (40/32/24/16)! Aborted...\n",
|
|
307 9);
|
|
308 }
|
|
309 }
|
|
310
|
|
311 /*
|
|
312 * ...... MEMORY ALLOCATION .........
|
|
313 */
|
|
314
|
|
315 if ((inp_buf = (short *) calloc(N, sizeof(short))) == NULL)
|
|
316 HARAKIRI("Error in memory allocation!\n", 1);
|
|
317 if ((out_buf = (short *) calloc(N, sizeof(short))) == NULL)
|
|
318 HARAKIRI("Error in memory allocation!\n", 1);
|
|
319 if ((tmp_buf = (short *) calloc(N, sizeof(short))) == NULL)
|
|
320 HARAKIRI("Error in memory allocation!\n", 1);
|
|
321
|
|
322 /*
|
|
323 * ......... FILE PREPARATION .........
|
|
324 */
|
|
325
|
|
326 /* Opening input file; abort if there's any problem */
|
|
327 if ((Fi = fopen(FileIn, "rb")) == NULL)
|
|
328 KILL(FileIn, 2);
|
|
329 inp = fileno(Fi);
|
|
330
|
|
331 /* Creates output file */
|
|
332 #ifdef VMS
|
|
333 sprintf(mrs, "mrs=%d", 512);
|
|
334 #endif
|
|
335 if ((Fo = fopen(FileOut, WB)) == NULL)
|
|
336 KILL(FileOut, 3);
|
|
337 out = fileno(Fo);
|
|
338
|
|
339 /* Move pointer to 1st block of interest */
|
|
340 if (fseek(Fi, start_byte, 0) < 0l)
|
|
341 KILL(FileIn, 4);
|
|
342
|
|
343 /*
|
|
344 * ......... PROCESSING ACCORDING TO ITU-T G.726 .........
|
|
345 */
|
|
346
|
|
347 for (cur_blk = 0; cur_blk < N2; cur_blk++) {
|
|
348 /* Print progress flag */
|
|
349 if (!quiet)
|
|
350 fprintf(stderr, "%c\r", funny[cur_blk % 8]);
|
|
351
|
|
352 /* Read a block of samples */
|
|
353 if ((smpno = fread(inp_buf, sizeof(short), N, Fi)) < 0)
|
|
354 KILL(FileIn, 5);
|
|
355
|
|
356 /* Check if reset is needed */
|
|
357 reset = (reset == 1 && cur_blk == 0) ? 1 : 0;
|
|
358
|
|
359 /* Carry out the desired operation */
|
|
360 if (inp_type == IS_LOG && out_type == IS_ADPCM) {
|
|
361 G726_encode(inp_buf, out_buf, smpno, law, rate, reset,
|
|
362 &encoder_state);
|
|
363 } else if (inp_type == IS_ADPCM && out_type == IS_LOG) {
|
|
364 G726_decode(inp_buf, out_buf, smpno, law, rate, reset,
|
|
365 &decoder_state);
|
|
366 } else if (inp_type == IS_LOG && out_type == IS_LOG) {
|
|
367 G726_encode(inp_buf, tmp_buf, smpno, law, rate, reset,
|
|
368 &encoder_state);
|
|
369 G726_decode(tmp_buf, out_buf, smpno, law, rate, reset,
|
|
370 &decoder_state);
|
|
371 }
|
|
372
|
|
373 /* Write ADPCM output word */
|
|
374 if ((smpno = fwrite(out_buf, sizeof(short), smpno, Fo)) < 0)
|
|
375 KILL(FileOut, 6);
|
|
376 }
|
|
377
|
|
378 /*
|
|
379 * ......... FINALIZATIONS .........
|
|
380 */
|
|
381
|
|
382 /* Close input and output files */
|
|
383 fclose(Fi);
|
|
384 fclose(Fo);
|
|
385
|
|
386 /* Exit with success for non-vms systems */
|
|
387 #ifndef VMS
|
|
388 return (0);
|
|
389 #endif
|
|
390 }
|
|
391
|
|
392 /* ............................. end of main() ............................. */
|