cemfi / meico

A converter framework with support for MEI, MSM, MPM, MIDI, WAV, MP3, chroma, and XSLT
GNU General Public License v3.0
67 stars 12 forks source link

Recognition of the instruments #23

Closed o-sapov closed 3 years ago

o-sapov commented 3 years ago

Hi Axel, we have the following issues regarding the recognition of the instruments.

Case 1: Symphony

The french horn is mapped to soprano saxophone because we use German and Italian terms in the \<label>:

<mei meiversion="3.0.0" xmlns="http://www.music-encoding.org/ns/mei">
    <meiHead>
        <fileDesc>
            <titleStmt>
                <title label="NMA digital" type="unit">an example</title>
            </titleStmt>
            <pubStmt/>
        </fileDesc>
        <workDesc>
            <work>
                <perfMedium>
                    <perfResList analog="marc:048" authURI="https://www.loc.gov/standards/valuelist/marcmusperf.html" authority="marcmusperf">
                        <perfRes codedval="ba" label="horn" n="8" xml:id="instrVoice_1">horn</perfRes>
                    </perfResList>
                </perfMedium>
            </work>
        </workDesc>
    </meiHead>
    <music>
        <body>
            <mdiv n="1" xml:id="mdiv_72">
                <score xml:id="score_78">
                    <scoreDef meter.count="4" meter.sym="common" meter.unit="4" xml:id="scoreDef_01">
                        <staffGrp symbol="bracket" xml:id="staffGrp_01">
                            <staffDef clef.line="2" clef.shape="G" decls="#instrVoice_1" key.sig="0" lines="5" n="1" trans.diat="-1" trans.semi="-2" xml:id="staffDef_P1">
                                <label xml:id="label_P1">Corno<lb xml:id="lb_P1"/> in Si♭ alto/B hoch</label>
                            </staffDef>
                        </staffGrp>
                    </scoreDef>
                    <section xml:id="section_A_m1-1">
                        <measure n="1" xml:id="m1">
                            <staff n="1" xml:id="staff_144">
                                <layer n="1" xml:id="layer_150">
                                    <note dur="4" oct="4" pname="c" xml:id="note_156"/>
                                    <note dur="4" oct="4" pname="c" xml:id="note_162"/>
                                    <note dur="4" oct="4" pname="c" xml:id="note_168"/>
                                    <note dur="4" oct="4" pname="c" xml:id="note_174"/>
                                </layer>
                            </staff>
                        </measure>
                    </section>
                </score>
            </mdiv>
        </body>
    </music>
</mei>

Full example

Case 2: Canons

Soprano voices are mapped to piva and scifi because the \<label> contains Roman numerals:

<mei meiversion="3.0.0" xmlns="http://www.music-encoding.org/ns/mei">
    <meiHead>
        <fileDesc>
            <titleStmt>
                <title label="NMA digital" type="unit">"Bona nox! bist a rechta Ox". Canon for four voices in A, K. 561</title>
            </titleStmt>
            <pubStmt/>
        </fileDesc>
        <workDesc>
            <work>
                <perfMedium>
                    <perfResList analog="marc:048" authURI="https://www.loc.gov/standards/valuelist/marcmusperf.html" authority="marcmusperf">
                        <perfRes codedval="va" label="soprano" n="1" xml:id="vocalVoice_1">Soprano I</perfRes>
                        <perfRes codedval="va" label="soprano" n="2" xml:id="vocalVoice_2">Soprano II</perfRes>
                        <perfRes codedval="va" label="soprano" n="3" xml:id="vocalVoice_3">Soprano III</perfRes>
                        <perfRes codedval="va" label="soprano" n="4" xml:id="vocalVoice_4">Soprano IV</perfRes>
                    </perfResList>
                </perfMedium>
            </work>
        </workDesc>
    </meiHead>
    <music>
        <body>
            <mdiv n="1" xml:id="mdiv_144">
                <score xml:id="score_150">
                    <scoreDef key.mode="major" key.pname="a" key.sig="3s" meter.count="2" meter.sym="cut" meter.unit="2" xml:id="scoreDef_01">
                        <staffGrp barthru="false" symbol="bracket" xml:id="staffGrp_01">
                            <staffDef clef.line="2" clef.shape="G" decls="#vocalVoice_1" lines="5" n="1" xml:id="staffDef_P1">
                                <label xml:id="label_P1">I</label>
                            </staffDef>
                            <staffDef clef.line="2" clef.shape="G" decls="#vocalVoice_2" lines="5" n="2" xml:id="staffDef_P2">
                                <label xml:id="label_P2">II</label>
                            </staffDef>
                            <staffDef clef.line="2" clef.shape="G" decls="#vocalVoice_3" lines="5" n="3" xml:id="staffDef_P3">
                                <label xml:id="label_P3">III</label>
                            </staffDef>
                            <staffDef clef.line="2" clef.shape="G" decls="#vocalVoice_4" lines="5" n="4" xml:id="staffDef_P4">
                                <label xml:id="label_P4">IV</label>
                            </staffDef>
                        </staffGrp>
                    </scoreDef>
                    <section xml:id="section_A_m1-1">
                        <measure n="1" xml:id="m1">
                            <staff n="1" xml:id="staff_252">
                                <layer n="1" xml:id="layer_258">
                                    <note dur="2" oct="4" pname="a" tstamp="1" xml:id="note_264">
                                        <verse xml:id="verse_270">
                                            <syl con="d" wordpos="i" xml:id="syl_276">Bo</syl>
                                        </verse>
                                    </note>
                                    <note accid.ges="s" dur="2" oct="5" pname="c" tstamp="2" xml:id="note_288">
                                        <verse xml:id="verse_294">
                                            <syl wordpos="t" xml:id="syl_300">na</syl>
                                        </verse>
                                    </note>
                                </layer>
                            </staff>
                            <staff n="2" xml:id="staff_312">
                                <layer n="1" xml:id="layer_318">
                                    <mRest tstamp="1" xml:id="mRest_324"/>
                                </layer>
                            </staff>
                            <staff n="3" xml:id="staff_330">
                                <layer n="1" xml:id="layer_336">
                                    <mRest tstamp="1" xml:id="mRest_342"/>
                                </layer>
                            </staff>
                            <staff n="4" xml:id="staff_348">
                                <layer n="1" xml:id="layer_354">
                                    <mRest tstamp="1" xml:id="mRest_360"/>
                                </layer>
                            </staff>
                        </measure>
                    </section>
                </score>
            </mdiv>
        </body>
    </music>
</mei>

Possible solution

The both problems could be solved if MEICO would first check in the \<meiHead> if there is information about the instruments. In our case, there is a link via staffDef@decls to the MARC instruments vocabulary.

axelberndt commented 3 years ago

Hi Oleksii, hm, these labels do not make life easy for the string maching algorithms. ;)

A quick and dirty workaround is to export the MSM/MPS and adapt the names there to something like "Horn" and "Soprano". But that is, of course, no automatic solution.

I have to look deeper into the <perfMedium>, <perfResList> and <perfRes> definitions to see what they do, mean and allow. However, I will run into a conflict anyway as the general rule in meicos decision making for competing information is to prioritize local information. Regarding the <staffDef> it means, meico first looks for @label and then child <label>. Verovio seems to do the same here. Element <perfRes> is even less local ...

I have to think about this and get back to you. Give me some time.

axelberndt commented 3 years ago

I just commited a solution for this issue via release version 0.8.17. It does not follow your suggestion with element <perfRes>, though. This element is so vaguely specified and allows too much troublesome usecases. You may still use it, but meico keeps ignoring it. What you should do instead to specify the instrument in case of a nonexpressive or misleading label is the following.

Add to the <staffDef> an <instrDef> as described in the MEI Guidelines in the section on Recording General MIDI Instrumentation, just like this.

<staffDef clef.line="2" clef.shape="G" decls="#instrVoice_1" key.sig="0" lines="5" n="1" trans.diat="-1" trans.semi="-2" xml:id="staffDef_P1">
    <label xml:id="label_P1">Corno<lb xml:id="lb_P1"/> in Si♭ alto/B hoch</label>
    <instrDef midi.instrnum="60" midi.instrname="French Horn"/>
</staffDef>

You need only one of the attributes @midi.instrnum and @midi.instrname. The latter is subject to processing via the instruments dictionary, so it works also with instrument names that are not in the General MIDI list. Be aware that the instrument number must be in [0, 127]. Many GM instrument lists provide numbers from 1 to 128; those must be decreased by 1 to get the right instrument. This is also addressed in the MEI specification of this attribute.

So on your side of the data creation, instead of the relatively complicated <perfRes> approach you can, instead, just add an <instrDef> to the <staffDef> and you are done. Meico supports this now. Further information on this can be found here.