craigsapp / humlib

Humdrum data parsing library in C++
http://humlib.humdrum.org
BSD 2-Clause "Simplified" License
31 stars 8 forks source link

mei2hum: partial mensural conversion to **kern (not **mens) #35

Open davidrizo opened 4 years ago

davidrizo commented 4 years ago

When converting from PAEC, Verovio can export mensural notation into files such as:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="https://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="https://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<mei xmlns="http://www.music-encoding.org/ns/mei" meiversion="4.0.0">
    <meiHead>
        <fileDesc>
            <titleStmt>
                <title />
            </titleStmt>
            <pubStmt>
                <date>2020-03-12 21:01:00</date>
            </pubStmt>
        </fileDesc>
        <encodingDesc>
            <projectDesc>
                <p>Encoded with Verovio version 2.7.0-dev-57a617f</p>
            </projectDesc>
        </encodingDesc>
    </meiHead>
    <music>
        <body>
            <mdiv xml:id="mdiv-0000001810695481">
                <score xml:id="score-0000000368187530">
                    <scoreDef xml:id="scoredef-0000000660298961" key.sig="1f" mensur.sign="C">
                        <staffGrp xml:id="staffgrp-0000000683105239">
                            <staffDef xml:id="staffdef-0000000502175011" n="1" notationtype="mensural" lines="5" clef.shape="C" clef.line="1" />
                        </staffGrp>
                    </scoreDef>
                    <section xml:id="section-0000001227429703">
                        <measure xml:id="measure-0000000157327193" right="invis">
                            <staff xml:id="staff-0000001419185946" n="1">
                                <layer xml:id="layer-0000001600440127" n="1">
                                    <note xml:id="note-0000001364535814" dur="brevis" oct="4" pname="f" />
                                    <note xml:id="note-0000000775559585" dur="semibrevis" oct="4" pname="g" />
                                    <note xml:id="note-0000001751691452" dur="brevis" oct="4" pname="f" />
                                    <note xml:id="note-0000000824917041" dur="semibrevis" oct="4" pname="g" />
                                    <note xml:id="note-0000000226283055" dur="minima" oct="4" pname="a" />
                                    <note xml:id="note-0000002093250195" dur="minima" oct="4" pname="a" />
                                    <note xml:id="note-0000001178922211" dur="minima" oct="4" pname="b">
                                        <accid xml:id="accid-0000001461473055" accid.ges="f" />
                                    </note>
                                    <note xml:id="note-0000000059680999" dur="minima" oct="4" pname="a" />
                                    <note xml:id="note-0000000183687044" dur="semibrevis" oct="5" pname="c" />
                                    <note xml:id="note-0000001294147769" dur="minima" oct="4" pname="a" />
                                    <note xml:id="note-0000001027176767" dur="minima" oct="5" pname="d" />
                                    <dot xml:id="dot-0000000138884736" />
                                    <note xml:id="note-0000002068517310" dur="semiminima" oct="5" pname="c" />
                                    <note xml:id="note-0000002105151534" dur="semiminima" oct="4" pname="a" />
                                    <note xml:id="note-0000001488747613" dur="semiminima" oct="4" pname="b">
                                        <accid xml:id="accid-0000001049160494" accid.ges="f" />
                                    </note>
                                    <note xml:id="note-0000000252197141" dur="semibrevis" oct="5" pname="c" />
                                    <dot xml:id="dot-0000001692113256" />
                                </layer>
                            </staff>
                        </measure>
                    </section>
                </score>
            </mdiv>
        </body>
    </music>
</mei>

If for any reason we want to translate into a modern notation **kern file (considering all notes as imperfect), unless you want to avoid this conversion and prepare a mei2mens conversion, the code below be used that converts the mensural figures and processed individual dots located just after the note or rests.

End of method Tool_mei2hum::parseLayer:

HumNum  starting = starttime;
    string dummy;

    // drizo - before processing convert mensural dots that appear after a note or rest as attributes
    // e.g. <note> .... </note> <dot...> 
    // is converted into
    // <note dots="1">  
    // end drizo

    int nchildren = (int)children.size(); // drizo
    bool skipNextDot = false; // drizo
    for (int i=0; i<nchildren; i++) {
        string nodename = children[i].name();

        if (nodename == "note" ||nodename == "rest") { // drizo
            skipNextDot = false;// drizo
            if (i<nchildren-1 &&  strcmp(children[i+1].name(), "dot")==0) {// drizo
                xml_attribute dotattr = children[i].append_attribute("dots");// drizo
                dotattr.set_value("1");// drizo
                skipNextDot = true;// drizo
            }// drizo
        } // drizo

        if (nodename == "note") {
            starttime = parseNote(children[i], xml_node(NULL), dummy, starttime, 0);
        } else if (nodename == "chord") {
            starttime = parseChord(children[i], starttime, 0);
        } else if (nodename == "rest") {
            starttime = parseRest(children[i], starttime);
        } else if (nodename == "space") {
            starttime = parseRest(children[i], starttime);
        } else if (nodename == "mRest") {
            starttime = parseMRest(children[i], starttime);
        //} else if (nodename == "multiRest") { // drizo
        //  parseMultiRest(children[i], starttime); // drizo
        } else if (nodename == "beam") {
            starttime = parseBeam(children[i], starttime);
        } else if (nodename == "tuplet") {
            starttime = parseTuplet(children[i], starttime);
        } else if (nodename == "clef") {
            parseClef(children[i], starttime);
        } else if (nodename == "meterSig") { // drizo
            parseMeterSig(children[i], starttime); // drizo
        } else if (nodename == "dot") { // drizo
            if (!skipNextDot) {// drizo
                cerr << "Dot found after an element other than note or rest" <<
                    layer.name() << "/" << nodename << CURRLOC << endl;// drizo
            }// drizo
            skipNextDot = false;// drizo
        } else {
            cerr << DKHTP << layer.name() << "/" << nodename << CURRLOC << endl;
        }
    }

And in HumNum Tool_mei2hum::getDuration:

HumNum output;
    if (dur == "breve") {
        output = 2;
    } else if (dur == "long") {
        output = 4;
    } else if (dur == "maxima") {
        output = 8;
    } 
    /* drizo from here - mensural figures */ 
    else if (dur == "longa") {
        output = 4;
    } else if (dur == "brevis") {
        output = 2;
    } else if (dur == "semibrevis") { 
        output = 1;
    } else if (dur == "minima") {
        output = 1;
        output /= 2;
    } else if (dur == "semiminima") {
        output = 1;
        output /= 4;
    } else if (dur == "fusa") {
        output = 1;
        output /= 8;
    } /* drizo - to here */
    else if (isdigit(dur[0])) {
        output = 1;
        output /= stoi(dur);
    } else {
        cerr << "Unknown " << element.name() << "@dur: " << dur << endl;
        return 0;
    }

I've added // drizo comments just to show the changed lines