Skip to content

Commit

Permalink
Impelment *stem and *Xstem for Humdrum-to-MEI converter.
Browse files Browse the repository at this point in the history
  • Loading branch information
craigsapp committed Jan 3, 2023
1 parent 62227b4 commit eeb05ca
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 15 deletions.
9 changes: 7 additions & 2 deletions include/vrv/iohumdrum.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,15 @@ namespace humaux {
// add to a note/chord. The states are:
// '\' == down stem
// '/' == up stem
// 'x' == no stem
// 'X' == no automatic assignments (assignment will be done automatically by verovio).
// 'x' == no stem (better to use *Xstem instead)
// 'X' == no automatic assignments (assignment will be done automatically by verovio) (better to use *stem
// instead to cancel *Xstem)
std::vector<char> stem_type;

// stem_visible == keeps track of whether the stem should be made
// invisible or not for a staff.
std::vector<bool> stem_visible;

// ligature_recta == true if in a recta ligature
bool ligature_recta = false;
// ligature_obliqua == true if in a obliqua ligature
Expand Down
63 changes: 50 additions & 13 deletions src/iohumdrum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ namespace humaux {
{
cue_size.resize(100);
stem_type.resize(100);
stem_visible.resize(100);
clear();
}

Expand Down Expand Up @@ -481,6 +482,7 @@ namespace humaux {

std::fill(cue_size.begin(), cue_size.end(), false);
std::fill(stem_type.begin(), stem_type.end(), 'X');
std::fill(stem_visible.begin(), stem_visible.end(), true);

mensuration_type = 0;

Expand All @@ -498,6 +500,7 @@ namespace humaux {
out << prefix << "tremolo = " << tremolo << endl;
// std::vector<bool> cue_size;
// std::vector<char> stem_type;
// std::vector<char> stem_visible;
out << prefix << "ligature_recta = " << ligature_recta << endl;
out << prefix << "ligature_obliqua = " << ligature_obliqua << endl;
out << prefix << "last_clef = " << last_clef << endl;
Expand Down Expand Up @@ -5127,7 +5130,10 @@ void HumdrumInput::fillStaffInfo(hum::HTp staffstart, int staffnumber, int staff
storeAcclev(*part, staffindex);
}
else if (part->compare(0, 5, "*stem") == 0) {
storeStemInterpretation(*part, staffindex, 1);
storeStemInterpretation(*part, staffindex, part->getSubtrack());
}
else if (part->compare(0, 6, "*Xstem") == 0) {
storeStemInterpretation(*part, staffindex, part->getSubtrack());
}

hum::HumdrumFile *hf = part->getOwner()->getOwner();
Expand Down Expand Up @@ -12228,7 +12234,9 @@ void HumdrumInput::handleColoration(hum::HTp token)

template <class ELEMENT> void HumdrumInput::assignAutomaticStem(ELEMENT element, hum::HTp tok, int staffindex)
{
char value = m_staffstates.at(staffindex).stem_type.at(m_currentlayer);
std::vector<humaux::StaffStateVariables> &ss = m_staffstates;

char value = ss.at(staffindex).stem_type.at(m_currentlayer);
if (value != 'X') {
char hasstem = tok->hasStemDirection();
if (!hasstem) {
Expand All @@ -12239,6 +12247,10 @@ template <class ELEMENT> void HumdrumInput::assignAutomaticStem(ELEMENT element,
}
}
}
bool visible = ss.at(staffindex).stem_visible.at(m_currentlayer);
if (!visible) {
element->SetStemVisible(BOOLEAN_false);
}
}

//////////////////////////////
Expand Down Expand Up @@ -20467,7 +20479,10 @@ void HumdrumInput::handleStaffStateVariables(hum::HTp token)
}

else if (value.substr(0, 5) == "*stem") {
storeStemInterpretation(value, staffindex, m_currentlayer);
storeStemInterpretation(value, staffindex, token->getSubtrack());
}
else if (value.substr(0, 6) == "*Xstem") {
storeStemInterpretation(value, staffindex, token->getSubtrack());
}

else if (value.find("acclev") != std::string::npos) {
Expand Down Expand Up @@ -20518,18 +20533,40 @@ void HumdrumInput::storeStemInterpretation(const std::string &value, int staffin

std::vector<humaux::StaffStateVariables> &ss = m_staffstates;

std::string ending = value.substr(6);
if (ending == "x") {
ss[staffindex].stem_type.at(layernumber) = 'x';
}
else if (ending == "/") {
ss[staffindex].stem_type.at(layernumber) = '/';
if ((value.size() >= 7) && (value.compare(0, 6, "*stem:") == 0)) {
std::string ending = value.substr(6);
if (ending == "x") {
ss[staffindex].stem_type.at(layernumber) = 'x';
}
else if (ending == "/") {
// force notes to have stem up starting here
ss[staffindex].stem_type.at(layernumber) = '/';
}
else if (ending == "\\") {
// force notes to have stem down starting here
ss[staffindex].stem_type.at(layernumber) = '\\';
}
else {
ss[staffindex].stem_type.at(layernumber) = 'X';
}
}
else if (ending == "\\") {
ss[staffindex].stem_type.at(layernumber) = '\\';
else if (value == "*stem") {
// show stems (default behavior)
if (layernumber == 0) {
std::fill(ss[staffindex].stem_visible.begin(), ss[staffindex].stem_visible.end(), true);
}
else {
ss[staffindex].stem_visible.at(layernumber) = true;
}
}
else {
ss[staffindex].stem_type.at(layernumber) = 'X';
else if (value == "*Xstem") {
// hide stems
if (layernumber == 0) {
std::fill(ss[staffindex].stem_visible.begin(), ss[staffindex].stem_visible.end(), false);
}
else {
ss[staffindex].stem_visible.at(layernumber) = false;
}
}
}

Expand Down

1 comment on commit eeb05ca

@craigsapp
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit implements *Xstem in the Humdrum-to-MEI converter for **kern spines, which is used to hide stems. It maps to note@stem.visible="false". *stem is used to make the stems visible again.

Example:

Screenshot 2023-01-02 at 10 22 53 PM

Humdrum data:

**kern
*clefG2
!!LO:TX:a:t=show stems (default)
4c
4d
4e
8aL
16bL
16ccJJ
=2
*Xstem
!!LO:TX:a:t=hide stems
4c
4d
4e
8aL
16bL
16ccJJ
=3
*stem
*^
!!LO:TX:a:t=show stems again
4a	4e
4b	4f
4cc	4e
4dd	4d
*v	*v
=4
*Xstem
*^
!!LO:TX:a:t=hide stems (all layers)
4a	4e
4b	4f
4cc	4e
4dd	4d
*v	*v
=
*stem
*^
*Xstem	*
!!LO:TX:b:t=hide only top notes
4a	4e
4b	4f
4cc	4e
4dd	4d
*v	*v
=
*stem
*^
*	*Xstem
!!LO:TX:b:t=hide only bottom notes
4a	4e
4b	4f
4cc	4e
4dd	4d
*v	*v
=
=
*stem
!!LO:TX:a:t=show stems
4c
4d
4e
4f
=
*-
Click to view MEI conversion of above Humdrum data
<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="https://music-encoding.org/schema/dev/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="https://music-encoding.org/schema/dev/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="5.0.0-dev">
 <meiHead>
  <fileDesc>
   <titleStmt>
    <title />
   </titleStmt>
   <pubStmt />
  </fileDesc>
  <encodingDesc>
   <appInfo>
    <application isodate="2023-01-02T22:25:03" version="3.15.0-dev-4dae4a8">
     <name>Verovio</name>
     <p>Transcoded from Humdrum</p>
    </application>
   </appInfo>
  </encodingDesc>
  <workList>
   <work>
    <title />
   </work>
  </workList>
 </meiHead>
 <music>
  <body>
   <mdiv xml:id="mhdfhbo">
    <score xml:id="sr02dxu">
     <scoreDef xml:id="s1sgbf90">
      <staffGrp xml:id="sq516yp">
       <staffDef xml:id="staffdef-L1F1" n="1" lines="5">
        <clef xml:id="clef-L2F1" shape="G" line="2" />
       </staffDef>
      </staffGrp>
     </scoreDef>
     <section xml:id="section-L1F1">
      <measure xml:id="measure-L1">
       <staff xml:id="staff-L1F1" n="1">
        <layer xml:id="layer-L1F1N1" n="1">
         <note xml:id="note-L4F1" dur="4" oct="4" pname="c" accid.ges="n" />
         <note xml:id="note-L5F1" dur="4" oct="4" pname="d" accid.ges="n" />
         <note xml:id="note-L6F1" dur="4" oct="4" pname="e" accid.ges="n" />
         <beam xml:id="beam-L7F1-L9F1">
          <note xml:id="note-L7F1" dur="8" oct="4" pname="a" accid.ges="n" />
          <note xml:id="note-L8F1" dur="16" oct="4" pname="b" accid.ges="n" />
          <note xml:id="note-L9F1" dur="16" oct="5" pname="c" accid.ges="n" />
         </beam>
        </layer>
       </staff>
       <dir xml:id="dir-L3F1" place="above" staff="1" tstamp="1.000000">
        <rend xml:id="rrwnlea" fontstyle="normal">show stems (default)</rend>
       </dir>
      </measure>
      <measure xml:id="measure-L10" n="2">
       <staff xml:id="staff-L10F1N1" n="1">
        <layer xml:id="layer-L10F1N1" n="1">
         <note xml:id="note-L13F1" dur="4" oct="4" pname="c" stem.visible="false" accid.ges="n" />
         <note xml:id="note-L14F1" dur="4" oct="4" pname="d" stem.visible="false" accid.ges="n" />
         <note xml:id="note-L15F1" dur="4" oct="4" pname="e" stem.visible="false" accid.ges="n" />
         <beam xml:id="beam-L16F1-L18F1">
          <note xml:id="note-L16F1" dur="8" oct="4" pname="a" stem.visible="false" accid.ges="n" />
          <note xml:id="note-L17F1" dur="16" oct="4" pname="b" stem.visible="false" accid.ges="n" />
          <note xml:id="note-L18F1" dur="16" oct="5" pname="c" stem.visible="false" accid.ges="n" />
         </beam>
        </layer>
       </staff>
       <dir xml:id="dir-L12F1" place="above" staff="1" tstamp="1.000000">
        <rend xml:id="rxe2b3t" fontstyle="normal">hide stems</rend>
       </dir>
      </measure>
      <measure xml:id="measure-L19" n="3">
       <staff xml:id="staff-L19F1N1" n="1">
        <layer xml:id="layer-L19F1N1" n="1">
         <note xml:id="note-L23F1" dur="4" oct="4" pname="a" accid.ges="n" />
         <note xml:id="note-L24F1" dur="4" oct="4" pname="b" accid.ges="n" />
         <note xml:id="note-L25F1" dur="4" oct="5" pname="c" accid.ges="n" />
         <note xml:id="note-L26F1" dur="4" oct="5" pname="d" accid.ges="n" />
        </layer>
        <layer xml:id="layer-L19F2N2" n="2">
         <note xml:id="note-L23F2" dur="4" oct="4" pname="e" accid.ges="n" />
         <note xml:id="note-L24F2" dur="4" oct="4" pname="f" accid.ges="n" />
         <note xml:id="note-L25F2" dur="4" oct="4" pname="e" accid.ges="n" />
         <note xml:id="note-L26F2" dur="4" oct="4" pname="d" accid.ges="n" />
        </layer>
       </staff>
       <dir xml:id="dir-L22F1" place="above" staff="1" tstamp="1.000000">
        <rend xml:id="r1v2eo1w" fontstyle="normal">show stems again</rend>
       </dir>
      </measure>
      <measure xml:id="measure-L28" n="4">
       <staff xml:id="staff-L28F1N1" n="1">
        <layer xml:id="layer-L28F1N1" n="1">
         <note xml:id="note-L32F1" dur="4" oct="4" pname="a" stem.visible="false" accid.ges="n" />
         <note xml:id="note-L33F1" dur="4" oct="4" pname="b" stem.visible="false" accid.ges="n" />
         <note xml:id="note-L34F1" dur="4" oct="5" pname="c" stem.visible="false" accid.ges="n" />
         <note xml:id="note-L35F1" dur="4" oct="5" pname="d" stem.visible="false" accid.ges="n" />
        </layer>
        <layer xml:id="layer-L28F2N2" n="2">
         <note xml:id="note-L32F2" dur="4" oct="4" pname="e" stem.visible="false" accid.ges="n" />
         <note xml:id="note-L33F2" dur="4" oct="4" pname="f" stem.visible="false" accid.ges="n" />
         <note xml:id="note-L34F2" dur="4" oct="4" pname="e" stem.visible="false" accid.ges="n" />
         <note xml:id="note-L35F2" dur="4" oct="4" pname="d" stem.visible="false" accid.ges="n" />
        </layer>
       </staff>
       <dir xml:id="dir-L31F1" place="above" staff="1" tstamp="1.000000">
        <rend xml:id="r1octpew" fontstyle="normal">hide stems (all layers)</rend>
       </dir>
      </measure>
      <measure xml:id="measure-L37">
       <staff xml:id="staff-L37F1N1" n="1">
        <layer xml:id="layer-L37F1N1" n="1">
         <note xml:id="note-L42F1" dur="4" oct="4" pname="a" stem.visible="false" accid.ges="n" />
         <note xml:id="note-L43F1" dur="4" oct="4" pname="b" stem.visible="false" accid.ges="n" />
         <note xml:id="note-L44F1" dur="4" oct="5" pname="c" stem.visible="false" accid.ges="n" />
         <note xml:id="note-L45F1" dur="4" oct="5" pname="d" stem.visible="false" accid.ges="n" />
        </layer>
        <layer xml:id="layer-L37F2N2" n="2">
         <note xml:id="note-L42F2" dur="4" oct="4" pname="e" accid.ges="n" />
         <note xml:id="note-L43F2" dur="4" oct="4" pname="f" accid.ges="n" />
         <note xml:id="note-L44F2" dur="4" oct="4" pname="e" accid.ges="n" />
         <note xml:id="note-L45F2" dur="4" oct="4" pname="d" accid.ges="n" />
        </layer>
       </staff>
       <dir xml:id="dir-L41F1" place="below" staff="1" tstamp="1.000000">
        <rend xml:id="rz4v267" fontstyle="normal">hide only top notes</rend>
       </dir>
      </measure>
      <measure xml:id="measure-L47">
       <staff xml:id="staff-L47F1N1" n="1">
        <layer xml:id="layer-L47F1N1" n="1">
         <note xml:id="note-L52F1" dur="4" oct="4" pname="a" accid.ges="n" />
         <note xml:id="note-L53F1" dur="4" oct="4" pname="b" accid.ges="n" />
         <note xml:id="note-L54F1" dur="4" oct="5" pname="c" accid.ges="n" />
         <note xml:id="note-L55F1" dur="4" oct="5" pname="d" accid.ges="n" />
        </layer>
        <layer xml:id="layer-L47F2N2" n="2">
         <note xml:id="note-L52F2" dur="4" oct="4" pname="e" stem.visible="false" accid.ges="n" />
         <note xml:id="note-L53F2" dur="4" oct="4" pname="f" stem.visible="false" accid.ges="n" />
         <note xml:id="note-L54F2" dur="4" oct="4" pname="e" stem.visible="false" accid.ges="n" />
         <note xml:id="note-L55F2" dur="4" oct="4" pname="d" stem.visible="false" accid.ges="n" />
        </layer>
       </staff>
       <dir xml:id="dir-L51F1" place="below" staff="1" tstamp="1.000000">
        <rend xml:id="r171t0eo" fontstyle="normal">hide only bottom notes</rend>
       </dir>
      </measure>
      <measure xml:id="measure-L58">
       <staff xml:id="staff-L58F1N1" n="1">
        <layer xml:id="layer-L58F1N1" n="1">
         <note xml:id="note-L61F1" dur="4" oct="4" pname="c" accid.ges="n" />
         <note xml:id="note-L62F1" dur="4" oct="4" pname="d" accid.ges="n" />
         <note xml:id="note-L63F1" dur="4" oct="4" pname="e" accid.ges="n" />
         <note xml:id="note-L64F1" dur="4" oct="4" pname="f" accid.ges="n" />
        </layer>
       </staff>
       <dir xml:id="dir-L60F1" place="above" staff="1" tstamp="1.000000">
        <rend xml:id="ri4soiy" fontstyle="normal">show stems</rend>
       </dir>
      </measure>
     </section>
    </score>
   </mdiv>
  </body>
 </music>
</mei>

Please sign in to comment.