FreeCalypso > hg > freecalypso-tools
view ringtools/imy/convert.c @ 882:fd4c9bc7835d
fc-imy2pwt program written, compiles
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 03 Apr 2022 03:30:27 +0000 |
parents | |
children | 3e398f9c31a0 |
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 process_octave_cmd(octchar) { if (!isdigit(octchar)) { fprintf(stderr, "melody error: '*' octave prefix not followed by digit\n"); exit(1); } cur_octave = octchar - '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: fprintf(stderr, "melody error: note letter expected after '&' or '#'\n"); exit(1); } switch (type) { case 1: if (note == 0 || note == 5) { fprintf(stderr, "melody error: invalid flat note\n"); exit(1); } note--; break; case 2: if (note == 4 || note == 11) { fprintf(stderr, "melody error: invalid sharp note\n"); exit(1); } note++; break; } if (str[1] < '0' || str[1] > '5') { fprintf(stderr, "melody error: missing expected note duration digit\n"); exit(1); } 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') { fprintf(stderr, "melody error: missing expected rest duration digit\n"); exit(1); } 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[1]); 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)) { fprintf(stderr, "melody error: invalid character after 'V'\n"); exit(1); } if (*cp == '1' && cp[1] >= '0' && cp[1] <= '5') cp += 2; else cp++; continue; case '(': if (repeat_start_ptr) { fprintf(stderr, "melody error: nested repeat\n"); exit(1); } cp++; repeat_start_ptr = cp; repeat_start_octave = cur_octave; repeat_count = 0; continue; case '@': if (!repeat_start_ptr) { fprintf(stderr, "melody error: '@' not in repeat block\n"); exit(1); } cp++; if (!isdigit(*cp)) { fprintf(stderr, "melody error: '@' not followed by digit\n"); exit(1); } rpt_set = *cp - '0'; if (!rpt_set) { fprintf(stderr, "melody error: infinite repeat not supported\n"); exit(1); } cp++; if (!repeat_count) repeat_count = rpt_set; continue; case ')': if (!repeat_start_ptr) { fprintf(stderr, "melody error: ')' without opening '('\n"); exit(1); } if (!repeat_count) { fprintf(stderr, "melody error: repeat block without count\n"); exit(1); } repeat_count--; if (repeat_count) { cp = repeat_start_ptr; cur_octave = repeat_start_octave; } else { cp++; repeat_start_ptr = 0; } continue; default: fprintf(stderr, "melody error: non-understood character\n"); exit(1); } } }