Skip to content

Commit

Permalink
ENG-35: Fix small chords on MusicXML import.
Browse files Browse the repository at this point in the history
Since MusicXML only stores note-level information about smallness
(<type size='cue'> and <cue>), chords that should be small were being
read as normal-sized chords of small notes. This caused issues with
the sizes of flags, ledger lines, and articulations.

This commit adds handleSmallness to ensure that a chord with all small
notes is imported as a small chord with all non-small notes, as well
as a test for this particular case.
  • Loading branch information
iveshenry18 committed May 26, 2021
1 parent e298be2 commit e9e2288
Show file tree
Hide file tree
Showing 4 changed files with 797 additions and 3 deletions.
41 changes: 38 additions & 3 deletions importexport/musicxml/importmxmlpass2.cpp
Expand Up @@ -3999,7 +3999,7 @@ static TDuration determineDuration(const bool rest, const QString& type, const i
static Chord* findOrCreateChord(Score* score, Measure* m,
const Fraction& tick, const int track, const int move,
const TDuration duration, const Fraction dura,
Beam::Mode bm)
Beam::Mode bm, bool small)
{
//qDebug("findOrCreateChord tick %d track %d dur ticks %d ticks %s bm %hhd",
// tick, track, duration.ticks(), qPrintable(dura.print()), bm);
Expand All @@ -4013,6 +4013,9 @@ static Chord* findOrCreateChord(Score* score, Measure* m,
else
c->setBeamMode(bm);
c->setTrack(track);
// Chord is initialized with the smallness of its first note.
// If a non-small note is added later, this is handled in handleSmallness.
c->setSmall(small);

setChordRestDuration(c, duration, dura);
Segment* s = m->getSegment(SegmentType::ChordRest, tick);
Expand Down Expand Up @@ -4087,6 +4090,38 @@ static void handleDisplayStep(ChordRest* cr, int step, int octave, const Fractio
}
}

//---------------------------------------------------------
// handleSmallness
//---------------------------------------------------------

/**
* Handle the distinction between small notes and a small
* chord, to ensure a chord with all small notes is small.
* This also handles the fact that a small note being added
* to a small chord should not itself be small.
* I.e. a chord is "small until proven otherwise".
*/

static void handleSmallness(bool cueOrSmall, Note* note, Chord* c)
{
if (cueOrSmall) {
note->setSmall(!c->small()); // Avoid redundant smallness
}
else {
note->setSmall(false);
if (c->small()) {
// What was a small chord becomes small notes in a non-small chord
c->setSmall(false);
for (Note* otherNote : c->notes()) {
if (note != otherNote)
otherNote->setSmall(true);
}
}
}
}



//---------------------------------------------------------
// setNoteHead
//---------------------------------------------------------
Expand Down Expand Up @@ -4500,7 +4535,7 @@ Note* MusicXMLParserPass2::note(const QString& partId,
c = findOrCreateChord(_score, measure,
noteStartTime,
msTrack + msVoice, msMove,
duration, dura, bm);
duration, dura, bm, small || cue);
}
else {
// grace note
Expand Down Expand Up @@ -4572,7 +4607,7 @@ Note* MusicXMLParserPass2::note(const QString& partId,
addGraceChordsBefore(c, gcl);
}

note->setSmall(cue || small); // cue notes are always small, normal notes only if size=cue
handleSmallness(cue || small, note, c);
note->setPlay(!cue); // cue notes don't play
note->setHeadGroup(headGroup);
if (noteColor != QColor::Invalid)
Expand Down

0 comments on commit e9e2288

Please sign in to comment.