FreeCalypso > hg > freecalypso-tools
view ffstools/tiaud/compile.c @ 1010:1d144553a5d0
CHANGES: fc-host-tools-r21 about to be released
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 12 Dec 2023 07:45:56 +0000 |
parents | f7e946389f8b |
children |
line wrap: on
line source
/* * This utility compiles a TI audio mode config file from our ASCII source * format into the binary for uploading into Calypso device FFS. */ #include <sys/types.h> #include <sys/file.h> #include <ctype.h> #include <string.h> #include <strings.h> #include <stdio.h> #include <stdint.h> #include <endian.h> #include <stdlib.h> #include <unistd.h> #include "binstruct.h" struct audio_cfg_bin bin; int is_new_aec; char *infname; FILE *inf; int lineno; init_nonzero_defaults() { bin.mic_bytes[0] = 3; bin.mic_fir[0] = 0x4000; bin.speaker_fir[0] = 0x4000; bin.sidetone_gain = -5; } static long strtol_wrap(arg) char *arg; { char *endptr; long ret; ret = strtol(arg, &endptr, 0); if (*endptr) { fprintf(stderr, "%s line %d: \"%s\" is not a valid number\n", infname, lineno, arg); exit(1); } return(ret); } static void mic_gain_setting(args) char *args; { char *cp, *np; for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: mic gain setting requires an argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') { fprintf(stderr, "%s line %d: mic gain setting takes only one argument\n", infname, lineno); exit(1); } bin.mic_bytes[0] = strtol_wrap(np); } static void mic_extra_gain_setting(args) char *args; { char *cp, *np; if (bin.mic_mode != AUDIO_MICROPHONE_HANDFREE) { fprintf(stderr, "%s line %d: mic extra-gain setting is only valid in aux mode\n", infname, lineno); exit(1); } for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: mic extra-gain setting requires an argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') { fprintf(stderr, "%s line %d: mic extra-gain setting takes only one argument\n", infname, lineno); exit(1); } bin.mic_bytes[1] = strtol_wrap(np); } static void mic_output_bias_setting(args) char *args; { char *cp, *np; int idx; for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: mic output-bias setting requires an argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') { fprintf(stderr, "%s line %d: mic output-bias setting takes only one argument\n", infname, lineno); exit(1); } if (bin.mic_mode != AUDIO_MICROPHONE_HANDFREE) idx = 1; else idx = 2; bin.mic_bytes[idx] = strtol_wrap(np); } static void mic_fir_setting(args) char *args; { char *cp, *np; int idx, start_idx; for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { missing_arg: fprintf(stderr, "%s line %d: mic fir setting requires two or more arguments\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; start_idx = strtol_wrap(np); if (start_idx < 0 || start_idx > 30) { fprintf(stderr, "%s line %d: FIR coefficient number must be between 0 and 30\n", infname, lineno); exit(1); } for (idx = start_idx; ; idx++) { while (isspace(*cp)) cp++; if (*cp == '\0' || *cp == '#') { if (idx == start_idx) goto missing_arg; break; } if (idx > 30) { fprintf(stderr, "%s line %d: spill past FIR coefficient 30\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; bin.mic_fir[idx] = htole16(strtol_wrap(np)); } } static void mic_head_line(args) char *args; { char linebuf[512]; char *cp, *np; for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: mic setting requires a mode argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; if (!strcmp(np, "default")) bin.mic_mode = AUDIO_MICROPHONE_HANDHELD; else if (!strcmp(np, "aux")) bin.mic_mode = AUDIO_MICROPHONE_HANDFREE; else if (!strcmp(np, "headset")) bin.mic_mode = AUDIO_MICROPHONE_HEADSET; else { fprintf(stderr, "%s line %d: unknown mic mode \"%s\"\n", infname, lineno, np); exit(1); } while (isspace(*cp)) cp++; if (*cp == '\0' || *cp == '#') return; if (*cp != '{') { fprintf(stderr, "%s line %d: invalid syntax on the mic head line\n", infname, lineno); exit(1); } for (;;) { if (!fgets(linebuf, sizeof linebuf, inf)) { fprintf(stderr, "%s: unexpected EOF in mic section\n", infname); exit(1); } lineno++; for (cp = linebuf; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') continue; for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; if (!strcmp(np, "gain")) mic_gain_setting(cp); else if (!strcmp(np, "extra-gain")) mic_extra_gain_setting(cp); else if (!strcmp(np, "output-bias")) mic_output_bias_setting(cp); else if (!strcmp(np, "fir")) mic_fir_setting(cp); else if (!strcmp(np, "}")) break; else { fprintf(stderr, "%s line %d: unknown mic setting \"%s\"\n", infname, lineno, np); exit(1); } } } static void speaker_gain_setting(args) char *args; { char *cp, *np; if (bin.speaker_mode == AUDIO_SPEAKER_BUZZER) { fprintf(stderr, "%s line %d: speaker gain setting is not valid in buzzer mode\n", infname, lineno); exit(1); } for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: speaker gain setting requires an argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') { fprintf(stderr, "%s line %d: speaker gain setting takes only one argument\n", infname, lineno); exit(1); } bin.speaker_bytes[0] = strtol_wrap(np); } static void speaker_audio_filter_setting(args) char *args; { char *cp, *np; if (bin.speaker_mode == AUDIO_SPEAKER_BUZZER) { fprintf(stderr, "%s line %d: speaker audio-filter setting is not valid in buzzer mode\n", infname, lineno); exit(1); } for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: speaker audio-filter setting requires an argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') { fprintf(stderr, "%s line %d: speaker audio-filter setting takes only one argument\n", infname, lineno); exit(1); } bin.speaker_bytes[1] = strtol_wrap(np); } static void speaker_fir_setting(args) char *args; { char *cp, *np; int idx, start_idx; if (bin.speaker_mode == AUDIO_SPEAKER_BUZZER) { fprintf(stderr, "%s line %d: speaker fir setting is not valid in buzzer mode\n", infname, lineno); exit(1); } for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { missing_arg: fprintf(stderr, "%s line %d: speaker fir setting requires two or more arguments\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; start_idx = strtol_wrap(np); if (start_idx < 0 || start_idx > 30) { fprintf(stderr, "%s line %d: FIR coefficient number must be between 0 and 30\n", infname, lineno); exit(1); } for (idx = start_idx; ; idx++) { while (isspace(*cp)) cp++; if (*cp == '\0' || *cp == '#') { if (idx == start_idx) goto missing_arg; break; } if (idx > 30) { fprintf(stderr, "%s line %d: spill past FIR coefficient 30\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; bin.speaker_fir[idx] = htole16(strtol_wrap(np)); } } static void speaker_activate_setting(args) char *args; { char *cp, *np; if (bin.speaker_mode != AUDIO_SPEAKER_BUZZER) { fprintf(stderr, "%s line %d: speaker activate setting is only valid in buzzer mode\n", infname, lineno); exit(1); } for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: speaker activate setting requires an argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') { fprintf(stderr, "%s line %d: speaker activate setting takes only one argument\n", infname, lineno); exit(1); } bin.speaker_bytes[0] = strtol_wrap(np); } static void speaker_head_line(args) char *args; { char linebuf[512]; char *cp, *np; for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: speaker setting requires a mode argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; if (!strcmp(np, "ear")) bin.speaker_mode = AUDIO_SPEAKER_HANDHELD; else if (!strcmp(np, "aux")) bin.speaker_mode = AUDIO_SPEAKER_HANDFREE; else if (!strcmp(np, "headset")) bin.speaker_mode = AUDIO_SPEAKER_HEADSET; else if (!strcmp(np, "buzzer")) bin.speaker_mode = AUDIO_SPEAKER_BUZZER; else if (!strcmp(np, "ear+aux")) bin.speaker_mode = AUDIO_SPEAKER_HANDHELD_HANDFREE; else { fprintf(stderr, "%s line %d: unknown speaker mode \"%s\"\n", infname, lineno, np); exit(1); } while (isspace(*cp)) cp++; if (*cp == '\0' || *cp == '#') return; if (*cp != '{') { fprintf(stderr, "%s line %d: invalid syntax on the speaker head line\n", infname, lineno); exit(1); } for (;;) { if (!fgets(linebuf, sizeof linebuf, inf)) { fprintf(stderr, "%s: unexpected EOF in speaker section\n", infname); exit(1); } lineno++; for (cp = linebuf; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') continue; for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; if (!strcmp(np, "gain")) speaker_gain_setting(cp); else if (!strcmp(np, "audio-filter")) speaker_audio_filter_setting(cp); else if (!strcmp(np, "fir")) speaker_fir_setting(cp); else if (!strcmp(np, "activate")) speaker_activate_setting(cp); else if (!strcmp(np, "}")) break; else { fprintf(stderr, "%s line %d: unknown speaker setting \"%s\"\n", infname, lineno, np); exit(1); } } } static void voice_path_setting(args) char *args; { char *cp, *np; for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: voice-path setting requires an argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') { fprintf(stderr, "%s line %d: voice-path setting takes only one argument\n", infname, lineno); exit(1); } bin.voice_path = strtol_wrap(np); } static void sidetone_setting(args) char *args; { char *cp, *np; for (cp = args; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') { fprintf(stderr, "%s line %d: sidetone setting requires an argument\n", infname, lineno); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') { fprintf(stderr, "%s line %d: sidetone setting takes only one argument\n", infname, lineno); exit(1); } bin.sidetone_gain = strtol_wrap(np); } static void aec_setting(name, nwords, args) char *name, *args; { char *cp, *np; int n; cp = args; for (n = 0; n < nwords; n++) { while (isspace(*cp)) cp++; if (*cp == '\0' || *cp == '#') { argcount_err: fprintf(stderr, "%s line %d: %s setting takes %d arguments\n", infname, lineno, name, nwords); exit(1); } for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; bin.aec_words[n] = htole16(strtol_wrap(np)); } while (isspace(*cp)) cp++; if (*cp != '\0' && *cp != '#') goto argcount_err; } read_input_main() { char linebuf[512]; char *cp, *np; for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) { for (cp = linebuf; isspace(*cp); cp++) ; if (*cp == '\0' || *cp == '#') continue; for (np = cp; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; if (!strcmp(np, "voice-path")) voice_path_setting(cp); else if (!strcmp(np, "mic")) mic_head_line(cp); else if (!strcmp(np, "speaker")) speaker_head_line(cp); else if (!strcmp(np, "sidetone")) sidetone_setting(cp); else if (!strcmp(np, "aec")) { is_new_aec = 0; aec_setting("aec", 5, cp); } else if (!strcmp(np, "aec-new")) { is_new_aec = 1; aec_setting("aec-new", 12, cp); } else { fprintf(stderr, "%s line %d: unknown top-level setting \"%s\"\n", infname, lineno, np); exit(1); } } } write_bin_output(filename) char *filename; { int fd; fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666); if (fd < 0) { perror(filename); exit(1); } write(fd, &bin, is_new_aec ? MODE_FILE_SIZE_NEWAEC : MODE_FILE_SIZE_OLDAEC); close(fd); } main(argc, argv) char **argv; { if (argc != 3) { fprintf(stderr, "usage: %s infile outfile\n", argv[0]); exit(1); } if (strcmp(argv[1], "-")) { infname = argv[1]; inf = fopen(infname, "r"); if (!inf) { perror(infname); exit(1); } } else { inf = stdin; infname = "stdin"; } init_nonzero_defaults(); read_input_main(); write_bin_output(argv[2]); exit(0); }