[MusicXML] Support breaks in secondary beams (import and export)
Currently MuseScore's MusicXML engine ignores breaks in secondary beams -- both when importing MusicXML and when exporting to MusicXML.
Here's example data for you. I created the following notation in Finale:
The attached MusicXML file musicxml_broken_secbeams.xml was generated by Finale with the latest Dolet plugin. When I import this in MuseScore 2.0.2, the beam breaks are ignored:
The attached MuseScore file musicxml_broken_secbeams.mscz has broken secondary beams. When I export it to MusicXML using MuseScore, the secondary beams are no longer broken in the resulting MusicXML file (musicxml_broken_secbeams_musescore.xml).
Attachment | Size |
---|---|
musicxml_broken_secbeams.xml | 9.29 KB |
finale_broken_beams.png | 56.9 KB |
musescore_broken_beams.png | 12.71 KB |
musicxml_broken_secbeams.mscz | 5.14 KB |
musicxml_broken_secbeams_musescore.xml | 7.98 KB |
Comments
I would be happy to put together a test for the MuseScore test suite, but it's not immediately obvious to me how I can do that. Let me know, and I'll get to work! :-)
Hi Adrian, Thank you for the report.
A more involved MusicXML file made with Finale involving 32nd beam too would be very helpful.
Something like this
Sure, here is a MusicXML file, generated by Finale, of the exact notation you requested (with 32nd beams).
Indeed, MusicXML secondary beams have never been supported by either importer or exporter.
I had a quick look and coded the import https://github.com/musescore/MuseScore/pull/2190.
@Leon any feedback?
Export is more involved and I couldn't make it work yet. The current code is here https://github.com/musescore/MuseScore/blob/b1d4272623779725693ba16a016…
Indeed export is more complex, especially when "auto" beams are involved.
I tried this inside the writeBeam function:
{syntaxhighlighter brush:c++;collapse:true;}
// find beam level previous chord
for (int i = idx - 1; blp == -1 && i >= 0; --i) {
ChordRest* crst = elements[i];
if (crst->type() == Element::Type::CHORD) {
if ((static_cast<Chord*>(cr))->beamMode() == Beam::Mode::BEGIN32) // hack: using cr instead of crst
blp = 1;
else if ((static_cast<Chord*>(cr))->beamMode() == Beam::Mode::BEGIN64) // hack: using cr instead of crst
blp = 2;
else
blp = (static_cast<Chord*>(crst))->beams();
}
}
// find beam level current chord
blc = (static_cast<Chord*>(cr))->beams();
// find beam level next chord
for (int i = idx + 1; bln == -1 && i < elements.size(); ++i) {
ChordRest* crst = elements[i];
if (crst->type() == Element::Type::CHORD) {
if ((static_cast<Chord*>(crst))->beamMode() == Beam::Mode::BEGIN32)
bln = 1;
else if ((static_cast<Chord*>(crst))->beamMode() == Beam::Mode::BEGIN64)
bln = 2;
else
bln = (static_cast<Chord*>(crst))->beams();
}
}{/syntaxhighlighter}
and it works for beams set with the beam options (the score in the issue report, for example). However, beams set with "auto" options are more complex: where the "auto" options is internally considered as "begin32" or "begin64"?
Try for example to input 8 consecutive 32nd notes inside My_First_score. They are divided in two group of 4 notes with a single beam linking the two groups, but they give all "auto" as beamMode.
EDIT:
Moreover, the handling of the direction of a hook (forward or backward) of a broken beam is probably not easy.
Was off-line for a short vacation, could not reply sooner.
Code looks OK to me, but I am not very familiar with MuseScores beam handling details, so I may misunderstand some things.
Does it also handle forward and backward hooks correctly ? Such as when one of the 16th around the split in the first example is a dotted 16th paired with a 32nd ?
relates to #270643: [EPIC] MusicXML import/export issues