FreeCalypso > hg > gsm-net-reveng
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 } |