From 91cd3b6586021d867d0265c0a2283d4d8e447e40 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Sun, 20 Nov 2011 17:52:30 +0100 Subject: New parser --- maestropond.c | 200 +++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 156 insertions(+), 44 deletions(-) diff --git a/maestropond.c b/maestropond.c index fe575bd..3a0ae4d 100644 --- a/maestropond.c +++ b/maestropond.c @@ -21,6 +21,7 @@ #include #include #include +#include enum note_tone { @@ -42,6 +43,20 @@ enum note_semitone SEMI_FLATFLAT }; +enum clef +{ + CLEF_TREBLE, + CLEF_ALTO, + CLEF_TENOR, + CLEF_BASS +}; + +enum chord_type +{ + CHORD_MUSIC, + CHORD_CLEF +}; + struct note { enum note_tone nt; @@ -51,9 +66,13 @@ struct note struct chord { + enum chord_type type; + int n_notes; struct note notes[8]; int length; + + enum clef clef; }; struct stave @@ -61,6 +80,7 @@ struct stave int n_chords; int max_chords; struct chord *chords; + enum clef last_clef; }; struct music @@ -124,6 +144,25 @@ out: } +static struct chord *add_chord(struct music *mus, int stave) +{ + struct stave *st = &mus->staves[stave]; + + if ( st->n_chords >= st->max_chords ) { + struct chord *n; + st->max_chords += 128; + n = realloc(st->chords, st->max_chords*sizeof(struct chord)); + if ( n == NULL ) { + fprintf(stderr, "Couldn't allocate chord.\n"); + abort(); + } + st->chords = n; + } + + return &st->chords[st->n_chords++]; +} + + static void music_attribute(unsigned char ma, struct music *mus) { if ( (ma & 0x7f) == 0x40 ) { @@ -153,29 +192,34 @@ static void music_attribute(unsigned char ma, struct music *mus) } else if ( (ma & 0x7) == 0x4 ) { int ct, st; + struct chord *n; + + st = (ma & 0x60) >> 5; + if ( st > 0 ) st--; /* Horrible fudge, seems to be necessary */ + n = add_chord(mus, st); + n->type = CHORD_CLEF; ct = (ma & 0x18) >> 3; switch ( ct ) { case 0 : - //fprintf(ofh, "\\clef \"treble\"\n"); + n->clef = CLEF_TREBLE; break; case 1 : - //fprintf(ofh, "\\clef \"treble\"\n"); + n->clef = CLEF_ALTO; break; case 2 : - //fprintf(ofh, "\\clef \"treble\"\n"); + n->clef = CLEF_TENOR; break; case 3 : - //fprintf(ofh, "\\clef \"treble\"\n"); + n->clef = CLEF_BASS; break; } - st = (ma & 0x60) >> 5; - printf(" stave %i\n", st); + mus->staves[st].last_clef = n->clef; } else if ( (ma & 0x3) == 0x2 ) { @@ -191,34 +235,54 @@ static void music_attribute(unsigned char ma, struct music *mus) } -static struct note get_note(unsigned char *notes, int *nptr) +static enum note_tone note_letter(int n) +{ + switch ( n ) { + case 0 : return NOTE_A; + case 1 : return NOTE_B; + case 2 : return NOTE_C; + case 3 : return NOTE_D; + case 4 : return NOTE_E; + case 5 : return NOTE_F; + case 6 : return NOTE_G; + } + + return NOTE_SILENCE; +} + + +static struct note pitch_to_note(int pos, int acc, enum clef cl) { - unsigned char n1, n2; - int rest = 0; struct note n; - n1 = notes[*nptr++]; + switch ( cl ) { - if ( n1 & 0xf8 ) { - n2 = notes[*nptr++]; - } else { - rest = 1; - } + case CLEF_BASS : + n.octave = (pos+1) / 8; + n.nt = note_letter((pos+1) % 8); + break; + + case CLEF_TREBLE : + n.octave = 2+ ((pos-1) / 8); + n.nt = note_letter((pos-1) % 8); + break; + + default: + abort(); - if ( rest ) { - printf(" %i", n1); - } else { - int pos, acc; - pos = (n1 & 0xf8) >> 3; - acc = n2 & 0x07; - n.nt = NOTE_A; - /* FIXME: Convert and store */ } return n; } +static int is_rest(unsigned char n1) +{ + if ( n1 & 0xf8 ) return 0; + return 1; +} + + static int find_max_length(unsigned char g, unsigned char **notes, int *nptrs) { int ch; @@ -243,15 +307,78 @@ static int find_max_length(unsigned char g, unsigned char **notes, int *nptrs) } -static void find_note_with_length(unsigned char *notes, int *nptr, - struct chord *c, int ls) +static int check_note(unsigned char *notes, int *nptr, struct chord *c, int ls, + struct stave *st) { - int len; + int len, pos, acc; + unsigned char n1, n2; + /* Is it the right length? If not, save it for the next chord */ len = (notes[*nptr] & 0xe0) >> 5; - if ( len != ls ) return; + if ( len != ls ) return 0; + + /* Is it a rest? */ + n1 = notes[*nptr]; + if ( is_rest(n1) ) return 0; + + (*nptr)++; + n2 = notes[*nptr++]; - c->notes[c->n_notes++] = get_note(notes, nptr); + pos = (n1 & 0xf8) >> 3; + acc = n2 & 0x07; + + c->notes[c->n_notes++] = pitch_to_note(pos, acc, st->last_clef); + + return 1; +} + + +static int channel_in_stave(int ch, int stave, int n_staves) +{ + assert(n_staves == 2); /* FIXME! */ + + if ( (ch < 4) && (stave == 0) ) return 1; + if ( (ch >= 4) && (stave == 1) ) return 1; + return 0; +} + + +static void process_gate(struct music *mus, int i, int *nptrs) +{ + unsigned int l, j; + + while ( mus->gates[i] != 0 ) { + + l = find_max_length(mus->gates[i], mus->notes, nptrs); + + for ( j=0; jn_staves; j++ ) { + + struct chord *n; + int k; + + n = add_chord(mus, j); + n->length = l; + n->type = CHORD_MUSIC; + + /* Find the notes of this length on this stave */ + for ( k=0; k<8; k++ ) { + + if ( !channel_in_stave(k, j, mus->n_staves) ) { + continue; + } + if ( !(mus->gates[i] & (1<notes[k], &nptrs[k], n, l, + &mus->staves[j]) ) + { + mus->gates[i] = mus->gates[i] ^ (1<gates[i], mus->notes, nptrs); - - /* Find the notes of this length on this stave */ - c.n_notes = 0; - c.length = l; - for ( j=0; j<4; j++ ) { - if ( !(mus->gates[i] & (1<notes[j], - &nptrs[j], &c, l); - } - - + process_gate(mus, i, nptrs); } } } -- cgit v1.2.3