comparison ffstools/tiaud/compile.c @ 240:2568a2a8a453

tiaud-compile program written
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 25 Aug 2017 23:36:07 +0000
parents
children 2abc086b13ed
comparison
equal deleted inserted replaced
239:d55368e45bfe 240:2568a2a8a453
1 /*
2 * This utility compiles a TI audio mode config file from our ASCII source
3 * format into the binary for uploading into Calypso device FFS.
4 */
5
6 #include <sys/types.h>
7 #include <sys/file.h>
8 #include <ctype.h>
9 #include <string.h>
10 #include <strings.h>
11 #include <stdio.h>
12 #include <stdint.h>
13 #include <endian.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include "binstruct.h"
17
18 struct audio_cfg_bin bin;
19
20 char *infname;
21 FILE *inf;
22 int lineno;
23
24 init_nonzero_defaults()
25 {
26 bin.mic_bytes[0] = 3;
27 bin.mic_fir[0] = 0x4000;
28 bin.speaker_fir[0] = 0x4000;
29 bin.sidetone_gain = -5;
30 }
31
32 static long
33 strtol_wrap(arg)
34 char *arg;
35 {
36 char *endptr;
37 long ret;
38
39 ret = strtol(arg, &endptr, 0);
40 if (*endptr) {
41 fprintf(stderr, "%s line %d: \"%s\" is not a valid number\n",
42 infname, lineno, arg);
43 exit(1);
44 }
45 return(ret);
46 }
47
48 static void
49 mic_gain_setting(args)
50 char *args;
51 {
52 char *cp, *np;
53
54 for (cp = args; isspace(*cp); cp++)
55 ;
56 if (*cp == '\0' || *cp == '#') {
57 fprintf(stderr,
58 "%s line %d: mic gain setting requires an argument\n",
59 infname, lineno);
60 exit(1);
61 }
62 for (np = cp; *cp && !isspace(*cp); cp++)
63 ;
64 if (*cp)
65 *cp++ = '\0';
66 while (isspace(*cp))
67 cp++;
68 if (*cp != '\0' && *cp != '#') {
69 fprintf(stderr,
70 "%s line %d: mic gain setting takes only one argument\n",
71 infname, lineno);
72 exit(1);
73 }
74 bin.mic_bytes[0] = strtol_wrap(np);
75 }
76
77 static void
78 mic_extra_gain_setting(args)
79 char *args;
80 {
81 char *cp, *np;
82
83 if (bin.mic_mode != AUDIO_MICROPHONE_HANDFREE) {
84 fprintf(stderr,
85 "%s line %d: mic extra-gain setting is only valid in aux mode\n",
86 infname, lineno);
87 exit(1);
88 }
89 for (cp = args; isspace(*cp); cp++)
90 ;
91 if (*cp == '\0' || *cp == '#') {
92 fprintf(stderr,
93 "%s line %d: mic extra-gain setting requires an argument\n",
94 infname, lineno);
95 exit(1);
96 }
97 for (np = cp; *cp && !isspace(*cp); cp++)
98 ;
99 if (*cp)
100 *cp++ = '\0';
101 while (isspace(*cp))
102 cp++;
103 if (*cp != '\0' && *cp != '#') {
104 fprintf(stderr,
105 "%s line %d: mic extra-gain setting takes only one argument\n",
106 infname, lineno);
107 exit(1);
108 }
109 bin.mic_bytes[1] = strtol_wrap(np);
110 }
111
112 static void
113 mic_output_bias_setting(args)
114 char *args;
115 {
116 char *cp, *np;
117 int idx;
118
119 for (cp = args; isspace(*cp); cp++)
120 ;
121 if (*cp == '\0' || *cp == '#') {
122 fprintf(stderr,
123 "%s line %d: mic output-bias setting requires an argument\n",
124 infname, lineno);
125 exit(1);
126 }
127 for (np = cp; *cp && !isspace(*cp); cp++)
128 ;
129 if (*cp)
130 *cp++ = '\0';
131 while (isspace(*cp))
132 cp++;
133 if (*cp != '\0' && *cp != '#') {
134 fprintf(stderr,
135 "%s line %d: mic output-bias setting takes only one argument\n",
136 infname, lineno);
137 exit(1);
138 }
139 if (bin.mic_mode != AUDIO_MICROPHONE_HANDFREE)
140 idx = 1;
141 else
142 idx = 2;
143 bin.mic_bytes[idx] = strtol_wrap(np);
144 }
145
146 static void
147 mic_fir_setting(args)
148 char *args;
149 {
150 char *cp, *np;
151 int idx, start_idx;
152
153 for (cp = args; isspace(*cp); cp++)
154 ;
155 if (*cp == '\0' || *cp == '#') {
156 missing_arg: fprintf(stderr,
157 "%s line %d: mic fir setting requires two or more arguments\n",
158 infname, lineno);
159 exit(1);
160 }
161 for (np = cp; *cp && !isspace(*cp); cp++)
162 ;
163 if (*cp)
164 *cp++ = '\0';
165 start_idx = strtol_wrap(np);
166 if (start_idx < 0 || start_idx > 31) {
167 fprintf(stderr,
168 "%s line %d: FIR coefficient number must be between 0 and 31\n",
169 infname, lineno);
170 exit(1);
171 }
172 for (idx = start_idx; ; idx++) {
173 while (isspace(*cp))
174 cp++;
175 if (*cp == '\0' || *cp == '#') {
176 if (idx == start_idx)
177 goto missing_arg;
178 break;
179 }
180 if (idx > 31) {
181 fprintf(stderr,
182 "%s line %d: spill past FIR coefficient 31\n",
183 infname, lineno);
184 exit(1);
185 }
186 for (np = cp; *cp && !isspace(*cp); cp++)
187 ;
188 if (*cp)
189 *cp++ = '\0';
190 bin.mic_fir[idx] = htole16(strtol_wrap(np));
191 }
192 }
193
194 static void
195 mic_head_line(args)
196 char *args;
197 {
198 char linebuf[512];
199 char *cp, *np;
200
201 for (cp = args; isspace(*cp); cp++)
202 ;
203 if (*cp == '\0' || *cp == '#') {
204 fprintf(stderr,
205 "%s line %d: mic setting requires a mode argument\n",
206 infname, lineno);
207 exit(1);
208 }
209 for (np = cp; *cp && !isspace(*cp); cp++)
210 ;
211 if (*cp)
212 *cp++ = '\0';
213 if (!strcmp(np, "default"))
214 bin.mic_mode = AUDIO_MICROPHONE_HANDHELD;
215 else if (!strcmp(np, "aux"))
216 bin.mic_mode = AUDIO_MICROPHONE_HANDFREE;
217 else if (!strcmp(np, "headset"))
218 bin.mic_mode = AUDIO_MICROPHONE_HEADSET;
219 else {
220 fprintf(stderr, "%s line %d: unknown mic mode \"%s\"\n",
221 infname, lineno, np);
222 exit(1);
223 }
224 while (isspace(*cp))
225 cp++;
226 if (*cp == '\0' || *cp == '#')
227 return;
228 if (*cp != '{') {
229 fprintf(stderr,
230 "%s line %d: invalid syntax on the mic head line\n",
231 infname, lineno);
232 exit(1);
233 }
234 for (;;) {
235 if (!fgets(linebuf, sizeof linebuf, inf)) {
236 fprintf(stderr, "%s: unexpected EOF in mic section\n",
237 infname);
238 exit(1);
239 }
240 lineno++;
241 for (cp = linebuf; isspace(*cp); cp++)
242 ;
243 if (*cp == '\0' || *cp == '#')
244 continue;
245 for (np = cp; *cp && !isspace(*cp); cp++)
246 ;
247 if (*cp)
248 *cp++ = '\0';
249 if (!strcmp(np, "gain"))
250 mic_gain_setting(cp);
251 else if (!strcmp(np, "extra-gain"))
252 mic_extra_gain_setting(cp);
253 else if (!strcmp(np, "output-bias"))
254 mic_output_bias_setting(cp);
255 else if (!strcmp(np, "fir"))
256 mic_fir_setting(cp);
257 else if (!strcmp(np, "}"))
258 break;
259 else {
260 fprintf(stderr,
261 "%s line %d: unknown mic setting \"%s\"\n",
262 infname, lineno, np);
263 exit(1);
264 }
265 }
266 }
267
268 static void
269 speaker_gain_setting(args)
270 char *args;
271 {
272 char *cp, *np;
273
274 if (bin.speaker_mode == AUDIO_SPEAKER_BUZZER) {
275 fprintf(stderr,
276 "%s line %d: speaker gain setting is not valid in buzzer mode\n",
277 infname, lineno);
278 exit(1);
279 }
280 for (cp = args; isspace(*cp); cp++)
281 ;
282 if (*cp == '\0' || *cp == '#') {
283 fprintf(stderr,
284 "%s line %d: speaker gain setting requires an argument\n",
285 infname, lineno);
286 exit(1);
287 }
288 for (np = cp; *cp && !isspace(*cp); cp++)
289 ;
290 if (*cp)
291 *cp++ = '\0';
292 while (isspace(*cp))
293 cp++;
294 if (*cp != '\0' && *cp != '#') {
295 fprintf(stderr,
296 "%s line %d: speaker gain setting takes only one argument\n",
297 infname, lineno);
298 exit(1);
299 }
300 bin.speaker_bytes[0] = strtol_wrap(np);
301 }
302
303 static void
304 speaker_audio_filter_setting(args)
305 char *args;
306 {
307 char *cp, *np;
308
309 if (bin.speaker_mode == AUDIO_SPEAKER_BUZZER) {
310 fprintf(stderr,
311 "%s line %d: speaker audio-filter setting is not valid in buzzer mode\n",
312 infname, lineno);
313 exit(1);
314 }
315 for (cp = args; isspace(*cp); cp++)
316 ;
317 if (*cp == '\0' || *cp == '#') {
318 fprintf(stderr,
319 "%s line %d: speaker audio-filter setting requires an argument\n",
320 infname, lineno);
321 exit(1);
322 }
323 for (np = cp; *cp && !isspace(*cp); cp++)
324 ;
325 if (*cp)
326 *cp++ = '\0';
327 while (isspace(*cp))
328 cp++;
329 if (*cp != '\0' && *cp != '#') {
330 fprintf(stderr,
331 "%s line %d: speaker audio-filter setting takes only one argument\n",
332 infname, lineno);
333 exit(1);
334 }
335 bin.speaker_bytes[1] = strtol_wrap(np);
336 }
337
338 static void
339 speaker_fir_setting(args)
340 char *args;
341 {
342 char *cp, *np;
343 int idx, start_idx;
344
345 if (bin.speaker_mode == AUDIO_SPEAKER_BUZZER) {
346 fprintf(stderr,
347 "%s line %d: speaker fir setting is not valid in buzzer mode\n",
348 infname, lineno);
349 exit(1);
350 }
351 for (cp = args; isspace(*cp); cp++)
352 ;
353 if (*cp == '\0' || *cp == '#') {
354 missing_arg: fprintf(stderr,
355 "%s line %d: speaker fir setting requires two or more arguments\n",
356 infname, lineno);
357 exit(1);
358 }
359 for (np = cp; *cp && !isspace(*cp); cp++)
360 ;
361 if (*cp)
362 *cp++ = '\0';
363 start_idx = strtol_wrap(np);
364 if (start_idx < 0 || start_idx > 31) {
365 fprintf(stderr,
366 "%s line %d: FIR coefficient number must be between 0 and 31\n",
367 infname, lineno);
368 exit(1);
369 }
370 for (idx = start_idx; ; idx++) {
371 while (isspace(*cp))
372 cp++;
373 if (*cp == '\0' || *cp == '#') {
374 if (idx == start_idx)
375 goto missing_arg;
376 break;
377 }
378 if (idx > 31) {
379 fprintf(stderr,
380 "%s line %d: spill past FIR coefficient 31\n",
381 infname, lineno);
382 exit(1);
383 }
384 for (np = cp; *cp && !isspace(*cp); cp++)
385 ;
386 if (*cp)
387 *cp++ = '\0';
388 bin.speaker_fir[idx] = htole16(strtol_wrap(np));
389 }
390 }
391
392 static void
393 speaker_activate_setting(args)
394 char *args;
395 {
396 char *cp, *np;
397
398 if (bin.speaker_mode != AUDIO_SPEAKER_BUZZER) {
399 fprintf(stderr,
400 "%s line %d: speaker activate setting is only valid in buzzer mode\n",
401 infname, lineno);
402 exit(1);
403 }
404 for (cp = args; isspace(*cp); cp++)
405 ;
406 if (*cp == '\0' || *cp == '#') {
407 fprintf(stderr,
408 "%s line %d: speaker activate setting requires an argument\n",
409 infname, lineno);
410 exit(1);
411 }
412 for (np = cp; *cp && !isspace(*cp); cp++)
413 ;
414 if (*cp)
415 *cp++ = '\0';
416 while (isspace(*cp))
417 cp++;
418 if (*cp != '\0' && *cp != '#') {
419 fprintf(stderr,
420 "%s line %d: speaker activate setting takes only one argument\n",
421 infname, lineno);
422 exit(1);
423 }
424 bin.speaker_bytes[0] = strtol_wrap(np);
425 }
426
427 static void
428 speaker_head_line(args)
429 char *args;
430 {
431 char linebuf[512];
432 char *cp, *np;
433
434 for (cp = args; isspace(*cp); cp++)
435 ;
436 if (*cp == '\0' || *cp == '#') {
437 fprintf(stderr,
438 "%s line %d: speaker setting requires a mode argument\n",
439 infname, lineno);
440 exit(1);
441 }
442 for (np = cp; *cp && !isspace(*cp); cp++)
443 ;
444 if (*cp)
445 *cp++ = '\0';
446 if (!strcmp(np, "ear"))
447 bin.speaker_mode = AUDIO_SPEAKER_HANDHELD;
448 else if (!strcmp(np, "aux"))
449 bin.speaker_mode = AUDIO_SPEAKER_HANDFREE;
450 else if (!strcmp(np, "headset"))
451 bin.speaker_mode = AUDIO_SPEAKER_HEADSET;
452 else if (!strcmp(np, "buzzer"))
453 bin.speaker_mode = AUDIO_SPEAKER_BUZZER;
454 else if (!strcmp(np, "ear+aux"))
455 bin.speaker_mode = AUDIO_SPEAKER_HANDHELD_HANDFREE;
456 else {
457 fprintf(stderr, "%s line %d: unknown speaker mode \"%s\"\n",
458 infname, lineno, np);
459 exit(1);
460 }
461 while (isspace(*cp))
462 cp++;
463 if (*cp == '\0' || *cp == '#')
464 return;
465 if (*cp != '{') {
466 fprintf(stderr,
467 "%s line %d: invalid syntax on the speaker head line\n",
468 infname, lineno);
469 exit(1);
470 }
471 for (;;) {
472 if (!fgets(linebuf, sizeof linebuf, inf)) {
473 fprintf(stderr,
474 "%s: unexpected EOF in speaker section\n",
475 infname);
476 exit(1);
477 }
478 lineno++;
479 for (cp = linebuf; isspace(*cp); cp++)
480 ;
481 if (*cp == '\0' || *cp == '#')
482 continue;
483 for (np = cp; *cp && !isspace(*cp); cp++)
484 ;
485 if (*cp)
486 *cp++ = '\0';
487 if (!strcmp(np, "gain"))
488 speaker_gain_setting(cp);
489 else if (!strcmp(np, "audio-filter"))
490 speaker_audio_filter_setting(cp);
491 else if (!strcmp(np, "fir"))
492 speaker_fir_setting(cp);
493 else if (!strcmp(np, "activate"))
494 speaker_activate_setting(cp);
495 else if (!strcmp(np, "}"))
496 break;
497 else {
498 fprintf(stderr,
499 "%s line %d: unknown speaker setting \"%s\"\n",
500 infname, lineno, np);
501 exit(1);
502 }
503 }
504 }
505
506 static void
507 voice_path_setting(args)
508 char *args;
509 {
510 char *cp, *np;
511
512 for (cp = args; isspace(*cp); cp++)
513 ;
514 if (*cp == '\0' || *cp == '#') {
515 fprintf(stderr,
516 "%s line %d: voice-path setting requires an argument\n",
517 infname, lineno);
518 exit(1);
519 }
520 for (np = cp; *cp && !isspace(*cp); cp++)
521 ;
522 if (*cp)
523 *cp++ = '\0';
524 while (isspace(*cp))
525 cp++;
526 if (*cp != '\0' && *cp != '#') {
527 fprintf(stderr,
528 "%s line %d: voice-path setting takes only one argument\n",
529 infname, lineno);
530 exit(1);
531 }
532 bin.voice_path = strtol_wrap(np);
533 }
534
535 static void
536 sidetone_setting(args)
537 char *args;
538 {
539 char *cp, *np;
540
541 for (cp = args; isspace(*cp); cp++)
542 ;
543 if (*cp == '\0' || *cp == '#') {
544 fprintf(stderr,
545 "%s line %d: sidetone setting requires an argument\n",
546 infname, lineno);
547 exit(1);
548 }
549 for (np = cp; *cp && !isspace(*cp); cp++)
550 ;
551 if (*cp)
552 *cp++ = '\0';
553 while (isspace(*cp))
554 cp++;
555 if (*cp != '\0' && *cp != '#') {
556 fprintf(stderr,
557 "%s line %d: sidetone setting takes only one argument\n",
558 infname, lineno);
559 exit(1);
560 }
561 bin.sidetone_gain = strtol_wrap(np);
562 }
563
564 static void
565 aec_setting(args)
566 char *args;
567 {
568 char *cp, *np;
569 int n;
570
571 cp = args;
572 for (n = 0; n < 5; n++) {
573 while (isspace(*cp))
574 cp++;
575 if (*cp == '\0' || *cp == '#') {
576 argcount_err: fprintf(stderr,
577 "%s line %d: aec setting takes 5 arguments\n",
578 infname, lineno);
579 exit(1);
580 }
581 for (np = cp; *cp && !isspace(*cp); cp++)
582 ;
583 if (*cp)
584 *cp++ = '\0';
585 bin.aec_words[n] = htole16(strtol_wrap(np));
586 }
587 while (isspace(*cp))
588 cp++;
589 if (*cp != '\0' && *cp != '#')
590 goto argcount_err;
591 }
592
593 read_input_main()
594 {
595 char linebuf[512];
596 char *cp, *np;
597
598 for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) {
599 for (cp = linebuf; isspace(*cp); cp++)
600 ;
601 if (*cp == '\0' || *cp == '#')
602 continue;
603 for (np = cp; *cp && !isspace(*cp); cp++)
604 ;
605 if (*cp)
606 *cp++ = '\0';
607 if (!strcmp(np, "voice-path"))
608 voice_path_setting(cp);
609 else if (!strcmp(np, "mic"))
610 mic_head_line(cp);
611 else if (!strcmp(np, "speaker"))
612 speaker_head_line(cp);
613 else if (!strcmp(np, "sidetone"))
614 sidetone_setting(cp);
615 else if (!strcmp(np, "aec"))
616 aec_setting(cp);
617 else {
618 fprintf(stderr,
619 "%s line %d: unknown top-level setting \"%s\"\n",
620 infname, lineno, np);
621 exit(1);
622 }
623 }
624 }
625
626 write_bin_output(filename)
627 char *filename;
628 {
629 int fd;
630
631 fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
632 if (fd < 0) {
633 perror(filename);
634 exit(1);
635 }
636 write(fd, &bin, sizeof bin);
637 close(fd);
638 }
639
640 main(argc, argv)
641 char **argv;
642 {
643 if (argc != 3) {
644 fprintf(stderr, "usage: %s infile outfile\n", argv[0]);
645 exit(1);
646 }
647 if (strcmp(argv[1], "-")) {
648 infname = argv[1];
649 inf = fopen(infname, "r");
650 if (!inf) {
651 perror(infname);
652 exit(1);
653 }
654 } else {
655 inf = stdin;
656 infname = "stdin";
657 }
658 init_nonzero_defaults();
659 read_input_main();
660 write_bin_output(argv[2]);
661 exit(0);
662 }