X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=score.c;h=ecfc2352662194790ec40b39577146fca64c08ee;hb=aae6b7f55870ab7f9cd41f95e22231e66a673aea;hp=e587c2799ed93a6396456b8d929388d56f482a30;hpb=41e993a65ab55db1f3297003fe65dd556a15f85f;p=scherzo diff --git a/score.c b/score.c index e587c27..ecfc235 100644 --- a/score.c +++ b/score.c @@ -21,9 +21,23 @@ #include #include +#include #include "score.h" +typedef struct score_note +{ + score_staff_t *staff; + pitch_t pitch; + score_duration_t duration; + + struct { + double r; + double g; + double b; + } color; +} score_note_t; + struct score_staff { score_clef_t clef; @@ -174,13 +188,25 @@ _score_clef_c_line (score_clef_t clef) } } +/* On which line would 'pitch' appear on 'staff'. + * + * Lines are numbered with line 0 as the top full line of the staff + * and increasing downward. So line values less than 0 will appear as + * ledger lines above the staff while line values greater than 4 will + * appear on ledger lines below the staff. + * + * A line value of 2 will be centered verticall on the staff. + * + * For notes appearing on a space, the line value will be half-way + * between two integers. */ static double -_score_note_to_line (score_staff_t *staff, score_note_t *note) +_score_staff_pitch_to_line (score_staff_t *staff, pitch_t pitch) { - pitch_name_t name = PITCH_NAME (note->pitch); + pitch_name_t name = PITCH_NAME (pitch); + int octave = PITCH_OCTAVE (pitch); int c_line = _score_clef_c_line (staff->clef); - return c_line - (name - PITCH_NAME_C) / 2.0 - 3.5 * (note->octave - 4); + return c_line - (name - PITCH_NAME_C) / 2.0 - 3.5 * (octave - 4); } /* chord->width is updated as a side effect */ @@ -258,7 +284,7 @@ _draw_note (score_t *score, cairo_t *cr, * note on a ledger line above the staff). Values half way between * integers indicate notes appearing on a space between two staff * lines (or ledger lines). */ - line = _score_note_to_line (staff, note); + line = _score_staff_pitch_to_line (staff, note->pitch); cairo_select_font_face (cr, "Gonville-26", 0, 0); cairo_set_font_size (cr, score->staff_height); @@ -570,33 +596,27 @@ score_add_chord (score_staff_t *staff, } void -score_remove_chord (score_chord_t *chord) +score_staff_remove_chords (score_staff_t *staff) { - score_staff_t *staff = chord->staff; - int i; - - for (i = 0; i < staff->num_chords; i++) - if (staff->chords[i] == chord) - break; + talloc_free (staff->chords); + staff->chords = NULL; - if (i == staff->num_chords) - return; + staff->num_chords = 0; +} - if (i < staff->num_chords - 1) - { - memmove (staff->chords + i, - staff->chords + i + 1, - (staff->num_chords - 1 - i) * sizeof (score_chord_t *)); - } +void +score_remove_chords (score_t *score) +{ + int i; - staff->num_chords -= 1; + for (i = 0; i < score->num_staves; i++) + score_staff_remove_chords (score->staves[i]); } -score_note_t * -score_add_note (score_staff_t *staff, - pitch_t pitch, - int octave, - score_duration_t duration) +void +score_staff_add_note (score_staff_t *staff, + pitch_t pitch, + score_duration_t duration) { score_note_t *note; double line; @@ -606,27 +626,25 @@ score_add_note (score_staff_t *staff, for (i = 0; i < staff->num_notes; i++) { note = staff->notes[i]; if (note->pitch == pitch && - note->octave == octave && note->duration == duration) { - return note; + return; } } note = talloc (staff, score_note_t); if (note == NULL) - return NULL; + return; note->staff = staff; note->pitch = pitch; - note->octave = octave; note->duration = duration; note->color.r = 0.0; note->color.g = 0.0; note->color.b = 0.0; - line = _score_note_to_line (staff, note); + line = _score_staff_pitch_to_line (staff, note->pitch); if (line < 0) { int lines = (int) (- line); if (lines > staff->upper_ledger_lines) @@ -644,71 +662,53 @@ score_add_note (score_staff_t *staff, staff->num_notes); if (staff->notes == NULL) { staff->num_notes = 0; - return NULL; + return; } staff->notes[staff->num_notes - 1] = note; - - return note; } void -score_remove_note (score_note_t *note) +score_add_note (score_t *score, pitch_t pitch, score_duration_t duration) { - score_staff_t *staff = note->staff; + score_staff_t *staff, *nearest_staff = NULL; + double distance, nearest_distance = 0.0; int i; - for (i = 0; i < staff->num_notes; i++) - if (staff->notes[i] == note) - break; - - if (i == staff->num_notes) + /* Nothing to do if we have no staff, (there's no place to add a note) . */ + if (score->num_staves == 0) return; - if (i < staff->num_notes - 1) - { - memmove (staff->notes + i, - staff->notes + i + 1, - (staff->num_notes - 1 - i) * sizeof (score_note_t *)); + /* Find the staff where the note will be closest to the center of + * the staff. */ + for (i = 0; i < score->num_staves; i++) { + staff = score->staves[i]; + distance = fabs (_score_staff_pitch_to_line (staff, pitch) - 2.0); + if (nearest_staff == NULL || distance < nearest_distance) { + nearest_staff = staff; + nearest_distance = distance; + } } - staff->num_notes -= 1; - - if (staff->num_notes == 0) { - staff->upper_ledger_lines = 0; - staff->lower_ledger_lines = 0; - } + score_staff_add_note (nearest_staff, pitch, duration); } void -score_set_note_color_rgb (score_note_t *note, - double r, - double g, - double b) +score_staff_remove_notes (score_staff_t *staff) { - note->color.r = r; - note->color.g = g; - note->color.b = b; + talloc_free (staff->notes); + staff->notes = NULL; + staff->num_notes = 0; + + staff->upper_ledger_lines = 0; + staff->lower_ledger_lines = 0; } -score_note_t * -score_staff_find_note (score_staff_t *staff, - pitch_t pitch, - int octave, - score_duration_t duration) +void +score_remove_notes (score_t *score) { int i; - score_note_t *note; - - for (i = 0; i < staff->num_notes; i++) { - note = staff->notes[i]; - if (note->pitch == pitch && - note->octave == octave && - note->duration == duration) - { - return note; - } - } - return NULL; + for (i = 0; i < score->num_staves; i++) + score_staff_remove_notes (score->staves[i]); }