Skip to content

Commit

Permalink
Merge pull request #25790 from rettinghaus/mei/trill-line
Browse files Browse the repository at this point in the history
[MEI] Add support for trill spanners
  • Loading branch information
cbjeukendrup authored Dec 10, 2024
2 parents 64b0bb4 + b2a2a2a commit 9eca3b4
Show file tree
Hide file tree
Showing 7 changed files with 760 additions and 3 deletions.
6 changes: 6 additions & 0 deletions src/importexport/mei/internal/meiconverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3160,6 +3160,9 @@ Convert::OrnamStruct Convert::trillFromMEI(engraving::Ornament* ornament, const

ornament->setSymId(symId);

// @color
Convert::colorFromMEI(ornament, meiTrill);

// Other attributes
return Convert::ornamFromMEI(ornament, meiTrill, warning);
}
Expand All @@ -3177,6 +3180,9 @@ libmei::Trill Convert::trillToMEI(const engraving::Ornament* ornament)
meiTrill.SetGlyphAuth(SMUFL_AUTH);
}

// @color
Convert::colorToMEI(ornament, meiTrill);

return meiTrill;
}

Expand Down
29 changes: 28 additions & 1 deletion src/importexport/mei/internal/meiexporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
#include "engraving/dom/text.h"
#include "engraving/dom/tie.h"
#include "engraving/dom/timesig.h"
#include "engraving/dom/trill.h"
#include "engraving/dom/tuplet.h"
#include "engraving/dom/volta.h"

Expand Down Expand Up @@ -837,6 +838,8 @@ bool MeiExporter::writeMeasure(const Measure* measure, int& measureN, bool& isFi
success = success && this->writeTempo(dynamic_cast<const TempoText*>(controlEvent.first), controlEvent.second);
} else if (controlEvent.first->isTie()) {
success = success && this->writeTie(dynamic_cast<const Tie*>(controlEvent.first), controlEvent.second);
} else if (controlEvent.first->isTrill()) {
success = success && this->writeTrill(dynamic_cast<const Trill*>(controlEvent.first), controlEvent.second);
}
}
m_startingControlEventList.clear();
Expand Down Expand Up @@ -2032,6 +2035,30 @@ bool MeiExporter::writeTie(const Tie* tie, const std::string& startid)
return true;
}

/**
* Write a trill.
*/

bool MeiExporter::writeTrill(const Trill* trill, const std::string& startid)
{
IF_ASSERT_FAILED(trill) {
return false;
}

pugi::xml_node trillNode = m_currentNode.append_child();
libmei::Trill meiTrill = Convert::trillToMEI(trill->ornament());
Convert::colorlineToMEI(trill, meiTrill);
meiTrill.SetExtender(libmei::BOOLEAN_true);
meiTrill.SetStartid(startid);

meiTrill.Write(trillNode, this->getXmlIdFor(trill, 't'));

// Add the node to the map of open control events
this->addNodeToOpenControlEvents(trillNode, trill, startid);

return true;
}

//---------------------------------------------------------
// write MEI attribute classes
//---------------------------------------------------------
Expand Down Expand Up @@ -2157,7 +2184,7 @@ void MeiExporter::fillControlEventMap(const std::string& xmlId, const ChordRest*
auto spanners = smap.findOverlapping(chordRest->tick().ticks(), chordRest->tick().ticks());
for (auto interval : spanners) {
Spanner* spanner = interval.value;
if (spanner && (spanner->isHairpin() || spanner->isOttava() || spanner->isPedal() || spanner->isSlur())) {
if (spanner && (spanner->isHairpin() || spanner->isOttava() || spanner->isPedal() || spanner->isSlur() || spanner->isTrill())) {
if (spanner->startCR() == chordRest) {
m_startingControlEventList.push_back(std::make_pair(spanner, "#" + xmlId));
} else if (spanner->endCR() == chordRest) {
Expand Down
2 changes: 2 additions & 0 deletions src/importexport/mei/internal/meiexporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class Rest;
class Score;
class Staff;
class TremoloSingleChord;
class Trill;
class Tuplet;
class VBox;
}
Expand Down Expand Up @@ -143,6 +144,7 @@ class MeiExporter
bool writeSlur(const engraving::Slur* slur, const std::string& startid);
bool writeTempo(const engraving::TempoText* tempoText, const std::string& startid);
bool writeTie(const engraving::Tie* tie, const std::string& startid);
bool writeTrill(const engraving::Trill* trill, const std::string& startid);

/**
* Methods for writing specific MEI attribute classes within elements
Expand Down
17 changes: 15 additions & 2 deletions src/importexport/mei/internal/meiimporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,8 @@ Spanner* MeiImporter::addSpanner(const libmei::Element& meiElement, Measure* mea
item = Factory::createPedal(chordRest->segment());
} else if (meiElement.m_name == "slur") {
item = Factory::createSlur(chordRest->segment());
} else if (meiElement.m_name == "trill") {
item = Factory::createTrill(chordRest->segment());
} else {
return nullptr;
}
Expand Down Expand Up @@ -2885,6 +2887,17 @@ bool MeiImporter::readTrill(pugi::xml_node trillNode, Measure* measure)
return true;
}

if (meiTrill.HasEndid()) {
Trill* trill = static_cast<Trill*>(this->addSpanner(meiTrill, measure, trillNode));
if (trill) {
// move ornament to spanner
ornament->parentItem()->remove(ornament);
trill->setOrnament(ornament);
// @color
Convert::colorlineFromMEI(trill, meiTrill);
}
}

Convert::OrnamStruct ornamSt = Convert::trillFromMEI(ornament, meiTrill, warning);
this->setOrnamentAccid(ornament, ornamSt);

Expand Down Expand Up @@ -3286,10 +3299,10 @@ void MeiImporter::addSpannerEnds()
spannerMapEntry.first->setTick2(chordRest->tick());
spannerMapEntry.first->setEndElement(chordRest);
spannerMapEntry.first->setTrack2(chordRest->track());
if (spannerMapEntry.first->isOttava()) {
if (spannerMapEntry.first->isOttava() || spannerMapEntry.first->isTrill()) {
// Set the tick2 to include the duration of the ChordRest
spannerMapEntry.first->setTick2(chordRest->tick() + chordRest->ticks());
// Special handling of ottava
// Special handling of ottavas
if (spannerMapEntry.first->isOttava()) {
Ottava* ottava = toOttava(spannerMapEntry.first);
// Make the staff fill the pitch offsets accordingly since we use Note::ppitch in export
Expand Down
170 changes: 170 additions & 0 deletions src/importexport/mei/tests/data/trill-01.mei
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="https://music-encoding.org/schema/5.0/mei-basic.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="https://music-encoding.org/schema/5.0/mei-basic.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="5.0+basic">
<meiHead>
<fileDesc>
<titleStmt>
<title type="main">The Art of Trill</title>
<respStmt>
<persName role="composer">Klaus Rettinghaus</persName>
</respStmt>
</titleStmt>
<pubStmt>
<date isodate="2024-12-09T15:18:31" />
</pubStmt>
</fileDesc>
</meiHead>
<music>
<body>
<mdiv>
<score>
<scoreDef>
<pgHead>
<rend halign="center" valign="top">
<rend type="title" fontsize="x-large">The Art of Trill</rend>
</rend>
</pgHead>
<staffGrp>
<staffDef n="1" lines="5" meter.count="2" meter.unit="4" trans.diat="7" trans.semi="12">
<label>Piccolo</label>
<labelAbbr>Picc.</labelAbbr>
<clef shape="G" line="2" />
</staffDef>
</staffGrp>
</scoreDef>
<section xml:id="s1">
<measure xml:id="msrr467" n="1">
<staff xml:id="m1s1" n="1">
<layer xml:id="m1s1l1" n="1">
<note xml:id="n17i18e9" dur="2" pname="b" oct="4" />
</layer>
</staff>
<trill xml:id="t1kauqmr" startid="#n17i18e9" extender="true" endid="#n1bf8c8b" />
<tie xml:id="t1kei3qd" startid="#n17i18e9" endid="#nrugdj0" />
</measure>
<measure xml:id="mb72cse" n="2">
<staff xml:id="m2s1" n="1">
<layer xml:id="m2s1l1" n="1">
<note xml:id="nrugdj0" dur="2" pname="b" oct="4" />
</layer>
</staff>
<tie xml:id="t1a0vvqz" startid="#nrugdj0" endid="#n1zovi6" />
</measure>
<measure xml:id="mir06ev" n="3">
<staff xml:id="m3s1" n="1">
<layer xml:id="m3s1l1" n="1">
<note xml:id="n1zovi6" dur="2" pname="b" oct="4" />
</layer>
</staff>
<tie xml:id="tkb1m8a" startid="#n1zovi6" endid="#n1bf8c8b" />
</measure>
<measure xml:id="mk49vq8" n="4">
<staff xml:id="m4s1" n="1">
<layer xml:id="m4s1l1" n="1">
<note xml:id="n1bf8c8b" dur="2" pname="b" oct="4" />
</layer>
</staff>
</measure>
<measure xml:id="m1hz5uj3" n="5">
<staff xml:id="m5s1" n="1">
<layer xml:id="m5s1l1" n="1">
<note xml:id="n7uxaq5" dur="2" pname="b" oct="4" />
</layer>
</staff>
<trill xml:id="t193bus8" type="mscore-above-second:major" accidupper="s" startid="#n7uxaq5" extender="true" endid="#n1rz933n" />
<tie xml:id="t1o6a0p8" startid="#n7uxaq5" endid="#naeqhp4" />
</measure>
<measure xml:id="mcwv6cu" n="6">
<staff xml:id="m6s1" n="1">
<layer xml:id="m6s1l1" n="1">
<note xml:id="naeqhp4" dur="2" pname="b" oct="4" />
</layer>
</staff>
<tie xml:id="ttrj1wl" startid="#naeqhp4" endid="#n1ekqfjo" />
</measure>
<measure xml:id="m1wmz5xo" n="7">
<staff xml:id="m7s1" n="1">
<layer xml:id="m7s1l1" n="1">
<note xml:id="n1ekqfjo" dur="2" pname="b" oct="4" />
</layer>
</staff>
<tie xml:id="tozvyfe" startid="#n1ekqfjo" endid="#n1rz933n" />
</measure>
<measure xml:id="m1cwbxwe" n="8">
<staff xml:id="m8s1" n="1">
<layer xml:id="m8s1l1" n="1">
<note xml:id="n1rz933n" dur="2" pname="b" oct="4" />
</layer>
</staff>
</measure>
<measure xml:id="m4jclcr" n="9">
<staff xml:id="m9s1" n="1">
<layer xml:id="m9s1l1" n="1">
<note xml:id="n4lgjur" dur="2" pname="c" oct="5" />
</layer>
</staff>
<trill xml:id="t1l4ocqa" type="mscore-above-second:minor" accidupper="f" startid="#n4lgjur" color="#FF2600" extender="true" place="below" endid="#n1g1qo7n" />
<tie xml:id="t1utpc8k" startid="#n4lgjur" endid="#n1t5d015" />
</measure>
<measure xml:id="m162jsy4" n="10">
<staff xml:id="m10s1" n="1">
<layer xml:id="m10s1l1" n="1">
<note xml:id="n1t5d015" dur="2" pname="c" oct="5" />
</layer>
</staff>
<tie xml:id="tg9si3f" startid="#n1t5d015" endid="#n1ijnalw" />
</measure>
<measure xml:id="m8i8pot" n="11">
<staff xml:id="m11s1" n="1">
<layer xml:id="m11s1l1" n="1">
<note xml:id="n1ijnalw" dur="2" pname="c" oct="5" />
</layer>
</staff>
<tie xml:id="t1kjvex7" startid="#n1ijnalw" endid="#n1g1qo7n" />
</measure>
<measure xml:id="m1vrswm4" n="12">
<staff xml:id="m12s1" n="1">
<layer xml:id="m12s1l1" n="1">
<note xml:id="n1g1qo7n" dur="2" pname="c" oct="5" />
</layer>
</staff>
</measure>
<measure xml:id="mzrv1i6" n="13">
<staff xml:id="m13s1" n="1">
<layer xml:id="m13s1l1" n="1">
<note xml:id="nf0myb" dur="2" pname="b" oct="4" />
</layer>
</staff>
<trill xml:id="t347uzv" type="mscore-above-second:minor" startid="#nf0myb" extender="true" place="above" endid="#ntdh2f7" />
<tie xml:id="t1w7cmo4" startid="#nf0myb" endid="#ncch6k6" />
</measure>
<measure xml:id="mejqda1" n="14">
<staff xml:id="m14s1" n="1">
<layer xml:id="m14s1l1" n="1">
<note xml:id="ncch6k6" dur="2" pname="b" oct="4" />
</layer>
</staff>
<tie xml:id="t1hb6lac" startid="#ncch6k6" endid="#n17an8bs" />
</measure>
<measure xml:id="m1fmomlt" n="15">
<staff xml:id="m15s1" n="1">
<layer xml:id="m15s1l1" n="1">
<note xml:id="n17an8bs" dur="2" pname="b" oct="4" />
</layer>
</staff>
<tie xml:id="td695gg" startid="#n17an8bs" endid="#ntdh2f7" />
</measure>
<measure xml:id="mv4ch4x" right="end" n="16">
<staff xml:id="m16s1" n="1">
<layer xml:id="m16s1l1" n="1">
<note xml:id="ntdh2f7" dur="2" pname="b" oct="4" />
</layer>
</staff>
</measure>
</section>
</score>
</mdiv>
</body>
</music>
</mei>
Loading

0 comments on commit 9eca3b4

Please sign in to comment.