comparison trau-ul-compile/trau-ul-compile.c @ 24:8e9bbb83bd16

trau-ul-compile program written
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 24 Jun 2024 01:01:17 +0000
parents
children
comparison
equal deleted inserted replaced
23:bffbe80ffade 24:8e9bbb83bd16
1 /*
2 * This program compile *.tsrc source format into *.tul binary format,
3 * see ../doc/TRAU-UL-testing article.
4 */
5
6 #include <sys/types.h>
7 #include <ctype.h>
8 #include <stdio.h>
9 #include <stdint.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <strings.h>
13 #include <tw_gsmfr.h>
14 #include <gsm_efr.h>
15
16 #define MAX_FIELDS 18
17
18 static char *infname, *outfname;
19 static FILE *inf, *outf;
20
21 static int lineno;
22 static char linebuf[256];
23 static char *fields[MAX_FIELDS];
24 static unsigned nfields;
25
26 static int is_efr;
27 static int16_t speech_params[GSMFR_NUM_PARAMS];
28 static int global_params_set, subframe_count;
29 static int bfi, bfi_set, sid, sid_set;
30 static uint8_t crc_inv, crc_inv_set;
31
32 static int
33 get_line()
34 {
35 char *cp;
36
37 if (!fgets(linebuf, sizeof linebuf, inf))
38 return 1;
39 lineno++;
40 if (!index(linebuf, '\n')) {
41 fprintf(stderr, "%s line %d: too long or missing newline\n",
42 infname, lineno);
43 exit(1);
44 }
45 nfields = 0;
46 for (cp = linebuf; ; ) {
47 while (isspace(*cp))
48 cp++;
49 if (*cp == '\0' || *cp == '#')
50 break;
51 if (nfields >= MAX_FIELDS) {
52 fprintf(stderr, "%s line %d: too many fields\n",
53 infname, lineno);
54 exit(1);
55 }
56 fields[nfields++] = cp;
57 while (*cp && !isspace(*cp))
58 cp++;
59 if (*cp)
60 *cp++ = '\0';
61 }
62 return 0;
63 }
64
65 static int
66 get_line_nonempty()
67 {
68 int rc;
69
70 for (;;) {
71 rc = get_line();
72 if (rc)
73 return rc;
74 if (nfields)
75 return 0;
76 }
77 }
78
79 static void
80 start_new_frame()
81 {
82 if (nfields != 2 || strcmp(fields[1], "{")) {
83 fprintf(stderr, "%s line %d: invalid frame opening line\n",
84 infname, lineno);
85 exit(1);
86 }
87 global_params_set = 0;
88 subframe_count = 0;
89 bfi = 0;
90 bfi_set = 0;
91 sid_set = 0;
92 crc_inv = 0;
93 crc_inv_set = 0;
94 }
95
96 static void
97 set_speech_params(start_param)
98 unsigned start_param;
99 {
100 unsigned ni, no;
101 u_long val;
102 char *cp;
103
104 no = start_param;
105 for (ni = 1; ni < nfields; ni++) {
106 if (!isdigit(fields[ni][0])) {
107 inv_number: fprintf(stderr,
108 "%s line %d: field \"%s\" is not a valid number\n",
109 infname, lineno, fields[ni]);
110 exit(1);
111 }
112 val = strtoul(fields[ni], &cp, 0);
113 if (*cp)
114 goto inv_number;
115 if (val > 0x1FF) {
116 fprintf(stderr,
117 "%s line %d: number \"%s\" is too large for a speech parameter\n",
118 infname, lineno, fields[ni]);
119 exit(1);
120 }
121 speech_params[no++] = val;
122 }
123 }
124
125 static void
126 handle_larc()
127 {
128 if (is_efr) {
129 fprintf(stderr, "%s line %d: LARc not valid for EFR\n",
130 infname, lineno);
131 exit(1);
132 }
133 if (nfields != 9) {
134 fprintf(stderr,
135 "%s line %d: wrong number of arguments for LARc\n",
136 infname, lineno);
137 exit(1);
138 }
139 if (global_params_set) {
140 fprintf(stderr, "%s line %d: LARc already set\n",
141 infname, lineno);
142 exit(1);
143 }
144 set_speech_params(0);
145 global_params_set = 1;
146 }
147
148 static void
149 handle_lpc()
150 {
151 if (!is_efr) {
152 fprintf(stderr, "%s line %d: LPC not valid for FR\n",
153 infname, lineno);
154 exit(1);
155 }
156 if (nfields != 6) {
157 fprintf(stderr,
158 "%s line %d: wrong number of arguments for LPC\n",
159 infname, lineno);
160 exit(1);
161 }
162 if (global_params_set) {
163 fprintf(stderr, "%s line %d: LPC already set\n",
164 infname, lineno);
165 exit(1);
166 }
167 set_speech_params(0);
168 global_params_set = 1;
169 }
170
171 static void
172 handle_sf()
173 {
174 if (is_efr) {
175 if (nfields != 14) {
176 fprintf(stderr,
177 "%s line %d: wrong number of arguments for EFR sf\n",
178 infname, lineno);
179 exit(1);
180 }
181 } else {
182 if (nfields != 18) {
183 fprintf(stderr,
184 "%s line %d: wrong number of arguments for FR sf\n",
185 infname, lineno);
186 exit(1);
187 }
188 }
189 if (subframe_count >= 4) {
190 fprintf(stderr, "%s line %d: too many subframes\n",
191 infname, lineno);
192 exit(1);
193 }
194 if (is_efr)
195 set_speech_params(5 + subframe_count * 13);
196 else
197 set_speech_params(8 + subframe_count * 17);
198 subframe_count++;
199 }
200
201 static void
202 handle_bfi()
203 {
204 if (nfields != 2) {
205 fprintf(stderr, "%s line %d: BFI takes one argument\n",
206 infname, lineno);
207 exit(1);
208 }
209 if (bfi_set) {
210 fprintf(stderr, "%s line %d: BFI already set\n",
211 infname, lineno);
212 exit(1);
213 }
214 if (fields[1][0] < '0' || fields[1][0] > '1' || fields[1][1]) {
215 fprintf(stderr,
216 "%s line %d: invalid BFI argument \"%s\" (must be 0 or 1)\n",
217 infname, lineno, fields[1]);
218 exit(1);
219 }
220 bfi = fields[1][0] - '0';
221 bfi_set = 1;
222 }
223
224 static void
225 handle_sid()
226 {
227 if (nfields != 2) {
228 fprintf(stderr, "%s line %d: SID takes one argument\n",
229 infname, lineno);
230 exit(1);
231 }
232 if (sid_set) {
233 fprintf(stderr, "%s line %d: SID already set\n",
234 infname, lineno);
235 exit(1);
236 }
237 if (fields[1][0] < '0' || fields[1][0] > '2' || fields[1][1]) {
238 fprintf(stderr,
239 "%s line %d: invalid SID argument \"%s\" (must be 0, 1 or 2)\n",
240 infname, lineno, fields[1]);
241 exit(1);
242 }
243 sid = fields[1][0] - '0';
244 sid_set = 1;
245 }
246
247 static void
248 handle_crc_inv()
249 {
250 unsigned nf;
251
252 if (!is_efr) {
253 fprintf(stderr, "%s line %d: crc-inv not valid for FR\n",
254 infname, lineno);
255 exit(1);
256 }
257 if (nfields < 2) {
258 fprintf(stderr,
259 "%s line %d: crc-inv requires at least 1 argument\n",
260 infname, lineno);
261 exit(1);
262 }
263 if (crc_inv_set) {
264 fprintf(stderr, "%s line %d: crc-inv already set\n",
265 infname, lineno);
266 exit(1);
267 }
268 for (nf = 1; nf < nfields; nf++) {
269 if (!strcasecmp(fields[nf], "all"))
270 crc_inv = 0xF8;
271 else if (fields[nf][0] >= '0' && fields[nf][0] <= '4' &&
272 !fields[nf][1])
273 crc_inv |= 0x80 >> (fields[nf][0] - '0');
274 else {
275 fprintf(stderr,
276 "%s line %d: \"%s\" is not a valid argument to crc-inv\n",
277 infname, lineno, fields[nf]);
278 exit(1);
279 }
280 }
281 crc_inv_set = 1;
282 }
283
284 static void
285 process_frame_interior()
286 {
287 int rc;
288
289 for (;;) {
290 rc = get_line_nonempty();
291 if (rc) {
292 fprintf(stderr, "bad input: EOF inside frame block\n");
293 exit(1);
294 }
295 if (!strcasecmp(fields[0], "larc"))
296 handle_larc();
297 else if (!strcasecmp(fields[0], "lpc"))
298 handle_lpc();
299 else if (!strcasecmp(fields[0], "sf"))
300 handle_sf();
301 else if (!strcasecmp(fields[0], "bfi"))
302 handle_bfi();
303 else if (!strcasecmp(fields[0], "sid"))
304 handle_sid();
305 else if (!strcasecmp(fields[0], "crc-inv"))
306 handle_crc_inv();
307 else if (!strcmp(fields[0], "}")) {
308 if (nfields != 1) {
309 fprintf(stderr,
310 "%s line %d: stuff after } not permitted\n",
311 infname, lineno);
312 exit(1);
313 }
314 return;
315 } else {
316 fprintf(stderr,
317 "%s line %d: non-understood keyword \"%s\"\n",
318 infname, lineno, fields[0]);
319 exit(1);
320 }
321 }
322 }
323
324 static void
325 finish_frame()
326 {
327 uint8_t bin[34];
328
329 if (!global_params_set) {
330 fprintf(stderr, "%s line %d: LARc/LPC parameters not set\n",
331 infname, lineno);
332 exit(1);
333 }
334 if (subframe_count != 4) {
335 fprintf(stderr, "%s line %d: subframe parameters not set\n",
336 infname, lineno);
337 exit(1);
338 }
339 if (is_efr) {
340 EFR_params2frame(speech_params, bin);
341 if (!sid_set)
342 sid = EFR_sid_classify(bin);
343 bin[31] = crc_inv;
344 bin[32] = 0;
345 } else {
346 gsmfr_pack_from_array(speech_params, bin);
347 if (!sid_set)
348 sid = gsmfr_preproc_sid_classify(bin);
349 }
350 bin[33] = (bfi << 7) | sid;
351 fwrite(bin, 1, 34, outf);
352 }
353
354 main(argc, argv)
355 char **argv;
356 {
357 int rc;
358
359 if (argc != 3) {
360 fprintf(stderr, "usage: %s input.tsrc output.tul\n", argv[0]);
361 exit(1);
362 }
363 infname = argv[1];
364 outfname = argv[2];
365
366 inf = fopen(infname, "r");
367 if (!inf) {
368 perror(infname);
369 exit(1);
370 }
371 outf = fopen(outfname, "w");
372 if (!outf) {
373 perror(outfname);
374 exit(1);
375 }
376
377 for (;;) {
378 rc = get_line_nonempty();
379 if (rc)
380 break;
381 if (!strcasecmp(fields[0], "frame_fr")) {
382 is_efr = 0;
383 start_new_frame();
384 } else if (!strcasecmp(fields[0], "frame_efr")) {
385 is_efr = 1;
386 start_new_frame();
387 } else {
388 fprintf(stderr,
389 "%s line %d: expected frame opening line, got something else\n",
390 infname, lineno);
391 exit(1);
392 }
393 process_frame_interior();
394 finish_frame();
395 }
396 exit(0);
397 }