FreeCalypso > hg > freecalypso-tools
view ringtools/imy/convert.c @ 964:a96cb97b66a2
ringtools/imy: fix duplicate definition of tdma_durations[]
The bug was reported by Vadim Yanitskiy <fixeria@osmocom.org>,
although the present fix is slightly different from the contributed
patch: because main.c doesn't need this tdma_durations[] array
at all, let's simply remove the reference to this array from main.c
rather than turn it into an extern.
I no longer remember my original thought flow that resulted (by mistake)
in tdma_durations[] being multiply defined in main.c and durations.c.
My intent might have been to define all globals in main.c and have
the reference in durations.c be an extern - and I missed that extern -
but without clear memory, I have no certainty. In any case, having
this data array defined in the same module that fills it (durations.c)
is sensible, so let's make it the new way.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 31 Aug 2023 19:38:18 +0000 |
parents | 3e398f9c31a0 |
children |
line wrap: on
line source
/* * This module implements the second pass of fc-imy2pwt processing: * stepping through the captured melody and converting it to PWT. */ #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> extern char melody_str_buf[]; extern unsigned tdma_durations[6][4]; extern FILE *outF; static int cur_octave = 4; static char *pwt_note_names[12] = {"c", "cs", "d", "ds", "e", "f", "fs", "g", "gs", "a", "as", "b"}; static void melody_error(cp, msg) char *cp, *msg; { unsigned pos; pos = cp - melody_str_buf; fprintf(stderr, "melody error at offset %u: %s\n", pos, msg); exit(1); } static void process_octave_cmd(cp) char *cp; { if (!isdigit(cp[1])) melody_error(cp, "'*' octave prefix not followed by digit"); cur_octave = cp[1] - '0'; } static int process_note(str, type) char *str; { int note, dur_basic, dur_mod; switch (*str) { case 'c': note = 0; break; case 'd': note = 2; break; case 'e': note = 4; break; case 'f': note = 5; break; case 'g': note = 7; break; case 'a': note = 9; break; case 'b': note = 11; break; default: melody_error(str, "note letter expected after '&' or '#'"); } switch (type) { case 1: if (note == 0 || note == 5) melody_error(str, "invalid flat note"); note--; break; case 2: if (note == 4 || note == 11) melody_error(str, "invalid sharp note"); note++; break; } if (str[1] < '0' || str[1] > '5') melody_error(str, "missing expected note duration digit"); dur_basic = str[1] - '0'; switch (str[2]) { case '.': dur_mod = 1; break; case ':': dur_mod = 2; break; case ';': dur_mod = 3; break; default: dur_mod = 0; break; } fprintf(outF, "%s%d\t64\t%u\n", pwt_note_names[note], cur_octave + 1, tdma_durations[dur_basic][dur_mod]); if (dur_mod) return 3; else return 2; } static int process_rest(str) char *str; { int dur_basic, dur_mod; if (str[1] < '0' || str[1] > '5') melody_error(str, "missing expected rest duration digit"); dur_basic = str[1] - '0'; switch (str[2]) { case '.': dur_mod = 1; break; case ':': dur_mod = 2; break; case ';': dur_mod = 3; break; default: dur_mod = 0; break; } fprintf(outF, "rest\t\t%u\n", tdma_durations[dur_basic][dur_mod]); if (dur_mod) return 3; else return 2; } melody_convert_pass() { char *cp, *repeat_start_ptr; int repeat_start_octave, repeat_count, rpt_set; repeat_start_ptr = 0; for (cp = melody_str_buf; *cp; ) { /* skip junk first */ if (!strncmp(cp, "vibeon", 6)) { cp += 6; continue; } if (!strncmp(cp, "vibeoff", 7)) { cp += 7; continue; } if (!strncmp(cp, "ledon", 5)) { cp += 5; continue; } if (!strncmp(cp, "ledoff", 6)) { cp += 6; continue; } if (!strncmp(cp, "backon", 6)) { cp += 6; continue; } if (!strncmp(cp, "backoff", 7)) { cp += 7; continue; } /* real stuff */ switch (*cp) { case '*': process_octave_cmd(cp); cp += 2; continue; case 'c': case 'd': case 'e': case 'f': case 'g': case 'a': case 'b': cp += process_note(cp, 0); continue; case '&': cp++; cp += process_note(cp, 1); continue; case '#': cp++; cp += process_note(cp, 2); continue; case 'r': cp += process_rest(cp); continue; case 'V': /* skip unimplemented volume control */ cp++; if (*cp == '+' || *cp == '-') { cp++; continue; } if (!isdigit(*cp)) melody_error(cp, "invalid character after 'V'"); if (*cp == '1' && cp[1] >= '0' && cp[1] <= '5') cp += 2; else cp++; continue; case '(': if (repeat_start_ptr) melody_error(cp, "nested repeat"); cp++; repeat_start_ptr = cp; repeat_start_octave = cur_octave; repeat_count = 0; continue; case '@': if (!repeat_start_ptr) melody_error(cp, "'@' not in repeat block"); cp++; if (!isdigit(*cp)) melody_error(cp, "'@' not followed by digit"); rpt_set = *cp - '0'; if (!rpt_set) melody_error(cp, "infinite repeat not supported"); cp++; if (!repeat_count) repeat_count = rpt_set; continue; case ')': if (!repeat_start_ptr) melody_error(cp, "')' without opening '('"); if (!repeat_count) melody_error(cp, "repeat block without count"); repeat_count--; if (repeat_count) { cp = repeat_start_ptr; cur_octave = repeat_start_octave; } else { cp++; repeat_start_ptr = 0; } continue; default: melody_error(cp, "non-understood character"); } } }