/* * maestropond.c * * Convert Acorn Maestro files to LilyPond files * * (c) 2011 Thomas White * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include static const int bpm[] = { 40, 50, 60, 65, 70, 80, 90, 100, 115, 130, 145, 160, 175, 190, 210 }; static void show_syntax(const char *s) { printf("Syntax: %s [options]\n", s); } static void show_help(const char *s) { show_syntax(s); printf( "\nConvert Acorn Maestro files to LilyPond files.\n" "\n" " -h, --help Display this help message.\n" "\n" ); } static unsigned int get_basic_int(unsigned char *f, size_t *pptr) { unsigned int v; size_t ptr = *pptr; int sig; v = 0; sig = f[ptr++]; if ( sig != 0x40 ) { fprintf(stderr, "Not a BASIC integer (sig %i, val %i)\n", sig, v); goto out; } v += f[ptr++] << 24; v += f[ptr++] << 16; v += f[ptr++] << 8; v += f[ptr++]; out: *pptr = ptr; return v; } static void music_attribute(unsigned char ma, FILE *ofh) { if ( (ma & 0x7f) == 0x40 ) { printf("Warning: reserved gate type.\n"); } else if ( (ma & 0x3f) == 0x20 ) { fprintf(ofh, "|\n ");; } else if ( (ma & 0x1f) == 0x10 ) { printf("Octave shift\n"); } else if ( (ma & 0xf) == 0x8 ) { int st; st = 1 + ((ma & 0xc0) >> 6); if ( ma & 0x10 ) { printf("Slur on (stave %i)\n", st); } else { printf("Slur off (stave %i)\n", st); } } else if ( (ma & 0x7) == 0x4 ) { int ct, st; ct = (ma & 0x18) >> 3; switch ( ct ) { case 0 : fprintf(ofh, "\\clef \"treble\"\n"); break; case 1 : fprintf(ofh, "\\clef \"treble\"\n"); break; case 2 : fprintf(ofh, "\\clef \"treble\"\n"); break; case 3 : fprintf(ofh, "\\clef \"treble\"\n"); break; } st = (ma & 0x60) >> 5; printf(" stave %i\n", st); } else if ( (ma & 0x3) == 0x2 ) { } else if ( (ma & 0x1) == 0x1 ) { int tn, td; tn = 1 + ((ma & 0x1e) >> 1); td = 1 + ((ma & 0xe0) >> 5); fprintf(ofh, "\\time %i/%i\n", tn, td); } } static const char *note_letter(int pos, int acc) { switch ( pos ) { case 0 : return "a"; case 1 : return "b"; case 2 : return "c"; case 4 : return "d"; case 5 : return "e"; case 6 : return "f"; case 7 : return "g"; case 8 : return "a'"; case 9 : return "b'"; case 10 : return "c'"; case 11 : return "d'"; case 12 : return "e'"; case 13 : return "f'"; case 14 : return "g'"; case 15 : return "a''"; case 16 : return "b''"; case 17 : return "c''"; case 18 : return "d''"; case 19 : return "e''"; case 20 : return "f''"; case 21 : return "g''"; case 22 : return "a'''"; case 23 : return "b'''"; case 24 : return "c'''"; case 25 : return "d'''"; case 26 : return "e'''"; case 27 : return "f'''"; case 28 : return "g'''"; case 29 : return "a''''"; case 30 : return "b''''"; case 31 : return "c''''"; } return "?"; } static void get_note(unsigned char **notes, int *nptrs, int ch, FILE *ofh) { unsigned char n1, n2; int rest = 0; n1 = notes[ch][nptrs[ch]++]; if ( n1 & 0xf8 ) { n2 = notes[ch][nptrs[ch]++]; } else { rest = 1; } if ( rest ) { printf(" %i", n1); } else { int pos, acc, len; pos = (n1 & 0xf8) >> 3; acc = n2 & 0x07; len = (n2 & 0xe0) >> 5; fprintf(ofh, "%s%i ", note_letter(pos, acc), (int)pow(2, len)); } } static void interpret_gates(unsigned char *gates, unsigned char **notes, int n_gates, FILE *ofh) { int i; int ma = 0; int nptrs[8]; for ( i=0; i<8; i++ ) nptrs[i] = 0; fprintf(ofh, "{\n "); for ( i=0; i "); } } fprintf(ofh, "\n}\n"); } static size_t process_music_data(unsigned char *f, size_t ptr, FILE *ofh, size_t len, int staff) { unsigned int n_gates; unsigned int i; unsigned int lengths[8]; unsigned char *gates; unsigned char *notes[8]; n_gates = get_basic_int(f, &ptr); printf("%i gates\n", n_gates); for ( i=0; i<8; i++ ) { lengths[i] = get_basic_int(f, &ptr); printf("Channel %i, length %i\n", i+1, lengths[i]); } gates = malloc(n_gates); if ( gates == NULL ) { fprintf(stderr, "Failed to allocate gates\n"); } for ( i=0; i= argc ) { show_syntax(argv[0]); return 1; } infile = argv[optind++]; printf("Input: '%s'\n", infile); convert_file(infile); return 0; }