summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.org.uk>2011-11-20 17:52:30 +0100
committerThomas White <taw@bitwiz.org.uk>2011-11-20 17:52:30 +0100
commit91cd3b6586021d867d0265c0a2283d4d8e447e40 (patch)
treed579d0af2ec3f5eea686710b8d70087bd1b665c8
parent49ce677d26d938db08a7c6994d3cf0ae92a3d1c2 (diff)
New parser
-rw-r--r--maestropond.c200
1 files 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 <sys/types.h>
#include <sys/stat.h>
#include <math.h>
+#include <assert.h>
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; j<mus->n_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<<k)) ) continue;
+
+ if ( check_note(mus->notes[k], &nptrs[k], n, l,
+ &mus->staves[j]) )
+ {
+ mus->gates[i] = mus->gates[i] ^ (1<<k);
+ }
+
+ }
+
+ }
+
+ }
}
@@ -275,22 +402,7 @@ static void interpret_gates(struct music *mus)
ma = 1;
continue;
} else {
-
- int l, j;
- struct chord c;
-
- l = find_max_length(mus->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<<j)) ) continue;
- find_note_with_length(mus->notes[j],
- &nptrs[j], &c, l);
- }
-
-
+ process_gate(mus, i, nptrs);
}
}
}