music-encoding / sibmei

Sibelius MEI Plugin
MIT License
40 stars 16 forks source link

Export of @trans.diat/@trans.semi not correct? #194

Open wergo opened 2 years ago

wergo commented 2 years ago

When exporting a little orchestral score from Sibelius (2019 on Mac) with SibMEI (4.0.0), the pitches of the transposing instruments are kept original (i.e., sounding), but the @trans.diat, @trans.semi attributes are in staffDef as if the instruments were notated as transposed.

However, when exporting to MusicXML, it works as expected.

Test Sibelius file (testorchester.sib): https://drive.google.com/file/d/1zXBOo-tY3s2jVD28olrt4KQX658gt9_c/view?usp=sharing

With SibMEI (Sibelius set to show transposing score):

grafik
MEI export through SibMEI: ```xml <respStmt xml:id="m-15"> <persName xml:id="m-16"/> </respStmt> </titleStmt> <pubStmt xml:id="m-17"> <availability xml:id="m-18"> <useRestrict xml:id="m-19">Copyright © </useRestrict> </availability> </pubStmt> </fileDesc> <encodingDesc xml:id="m-5"> <appInfo xml:id="m-6"> <application xml:id="sibelius" isodate="2022-3-21T17:22:27Z" version="19100"> <name xml:id="m-8" type="operating-system">Mac OS X Mountain Lion</name> </application> <application xml:id="sibmei" type="plugin" version="4.0.0"> <name xml:id="m-10">Sibelius to MEI 4 Exporter (4.0.0)</name> </application> </appInfo> </encodingDesc> <workList xml:id="m-11"> <work xml:id="m-12"> <title xml:id="m-13"/> </work> </workList> </meiHead> <music xml:id="m-21"> <body xml:id="m-22"> <mdiv xml:id="m-23"> <score xml:id="m-25"> <scoreDef xml:id="m-26" lyric.name="Times New Roman" meter.count="4" meter.unit="4" music.name="Opus Std" page.botmar="15mm" page.height="297mm" page.leftmar="15mm" page.rightmar="15mm" page.topmar="15mm" page.width="210mm" ppq="256" spacing.staff="11" spacing.system="18.5" text.name="Times New Roman" vu.height="0.525mm"> <staffGrp xml:id="m-27"> <staffGrp xml:id="m-53" n="1" symbol="bracket"> <staffDef xml:id="m-28" clef.line="2" clef.shape="G" key.mode="major" key.sig="2s" lines="5" n="1"> <label xml:id="m-29">Flöte</label> <labelAbbr xml:id="m-30">Fl.</labelAbbr> <!-- wind.flutes.flute --> <instrDef xml:id="m-32" midi.channel="1" midi.pan="68" midi.volume="95"/> </staffDef> <staffDef xml:id="m-33" clef.line="2" clef.shape="G" key.mode="major" key.sig="2s" lines="5" n="2" trans.diat="-1" trans.semi="-2"> <label xml:id="m-34">Klarinette in B</label> <labelAbbr xml:id="m-35">Kl.</labelAbbr> <!-- wind.clarinets.clarinet --> <instrDef xml:id="m-37" midi.channel="1" midi.pan="61" midi.volume="95"/> </staffDef> <staffDef xml:id="m-38" clef.line="2" clef.shape="G" key.mode="major" key.sig="2s" lines="5" n="3" trans.diat="-5" trans.semi="-9"> <label xml:id="m-39">Altsaxophon</label> <labelAbbr xml:id="m-40">Asax.</labelAbbr> <!-- wind.saxophones.alto --> <instrDef xml:id="m-42" midi.channel="1" midi.pan="53" midi.volume="95"/> </staffDef> </staffGrp> <staffDef xml:id="m-43" clef.line="2" clef.shape="G" key.mode="major" key.sig="2s" lines="5" n="4" trans.diat="-1" trans.semi="-2"> <label xml:id="m-44">Trompete in B</label> <labelAbbr xml:id="m-45">Trp.</labelAbbr> <!-- brass.trumpets.trumpet --> <instrDef xml:id="m-47" midi.channel="1" midi.pan="77" midi.volume="105"/> </staffDef> <staffDef xml:id="m-48" clef.line="2" clef.shape="G" key.mode="major" key.sig="2s" lines="5" n="5" trans.diat="14" trans.semi="24"> <label xml:id="m-49">Glockenspiel</label> <labelAbbr xml:id="m-50">Glsp.</labelAbbr> <!-- pitched percussion.metal.glockenspiel --> <instrDef xml:id="m-52" midi.channel="1" midi.pan="53" midi.volume="100"/> </staffDef> </staffGrp> </scoreDef> <section xml:id="m-54"> <pb xml:id="m-20"/> <sb xml:id="m-56"/> <measure xml:id="m-55" n="1"> <staff xml:id="m-57" n="1"> <layer xml:id="m-58" n="1"> <note xml:id="m-59" dur="4" dur.ppq="256" oct="5" pname="d" pnum="74" stem.dir="down" tstamp.real="00:00:00" vel="0"/> <note xml:id="m-60" dur="4" dur.ppq="256" oct="4" pname="a" pnum="69" stem.dir="up" tstamp.real="00:00:00.6" vel="0"/> <note xml:id="m-61" dur="4" dur.ppq="256" oct="5" pname="d" pnum="74" stem.dir="down" tstamp.real="00:00:01.2" vel="0"/> <note xml:id="m-62" dur="4" dur.ppq="256" oct="5" pname="f" pnum="78" stem.dir="down" tstamp.real="00:00:01.8" vel="0"> <accid xml:id="m-63" accid.ges="s"/> </note> </layer> </staff> <staff xml:id="m-64" n="2"> <layer xml:id="m-65" n="1"> <note xml:id="m-66" dur="4" dur.ppq="256" oct="5" pname="d" pnum="74" stem.dir="down" tstamp.real="00:00:00" vel="0"/> <note xml:id="m-67" dur="4" dur.ppq="256" oct="4" pname="a" pnum="69" stem.dir="down" tstamp.real="00:00:00.6" vel="0"/> <note xml:id="m-68" dur="4" dur.ppq="256" oct="5" pname="d" pnum="74" stem.dir="down" tstamp.real="00:00:01.2" vel="0"/> <note xml:id="m-69" dur="4" dur.ppq="256" oct="5" pname="f" pnum="78" stem.dir="down" tstamp.real="00:00:01.8" vel="0"> <accid xml:id="m-70" accid.ges="s"/> </note> </layer> </staff> <staff xml:id="m-71" n="3"> <layer xml:id="m-72" n="1"> <note xml:id="m-73" dur="4" dur.ppq="256" oct="5" pname="d" pnum="74" stem.dir="down" tstamp.real="00:00:00" vel="0"/> <note xml:id="m-74" dur="4" dur.ppq="256" oct="4" pname="a" pnum="69" stem.dir="down" tstamp.real="00:00:00.6" vel="0"/> <note xml:id="m-75" dur="4" dur.ppq="256" oct="5" pname="d" pnum="74" stem.dir="down" tstamp.real="00:00:01.2" vel="0"/> <note xml:id="m-76" dur="4" dur.ppq="256" oct="5" pname="f" pnum="78" stem.dir="down" tstamp.real="00:00:01.8" vel="0"> <accid xml:id="m-77" accid.ges="s"/> </note> </layer> </staff> <staff xml:id="m-78" n="4"> <layer xml:id="m-79" n="1"> <note xml:id="m-80" dur="4" dur.ppq="256" oct="5" pname="d" pnum="74" stem.dir="down" tstamp.real="00:00:00" vel="0"/> <note xml:id="m-81" dur="4" dur.ppq="256" oct="4" pname="a" pnum="69" stem.dir="down" tstamp.real="00:00:00.6" vel="0"/> <note xml:id="m-82" dur="4" dur.ppq="256" oct="5" pname="d" pnum="74" stem.dir="down" tstamp.real="00:00:01.2" vel="0"/> <note xml:id="m-83" dur="4" dur.ppq="256" oct="5" pname="f" pnum="78" stem.dir="down" tstamp.real="00:00:01.8" vel="0"> <accid xml:id="m-84" accid.ges="s"/> </note> </layer> </staff> <staff xml:id="m-85" n="5"> <layer xml:id="m-86" n="1"> <note xml:id="m-87" dur="4" dur.ppq="256" oct="7" pname="d" pnum="98" stem.dir="down" tstamp.real="00:00:00" vel="0"/> <note xml:id="m-88" dur="4" dur.ppq="256" oct="6" pname="a" pnum="93" stem.dir="up" tstamp.real="00:00:00.6" vel="0"/> <note xml:id="m-89" dur="4" dur.ppq="256" oct="7" pname="d" pnum="98" stem.dir="down" tstamp.real="00:00:01.2" vel="0"/> <note xml:id="m-90" dur="4" dur.ppq="256" oct="7" pname="f" pnum="102" stem.dir="down" tstamp.real="00:00:01.8" vel="0"> <accid xml:id="m-91" accid.ges="s"/> </note> </layer> </staff> </measure> <measure xml:id="m-92" n="2" right="end"> <staff xml:id="m-93" n="1"> <layer xml:id="m-94" n="1"> <note xml:id="m-95" dur="4" dur.ppq="256" oct="5" pname="a" pnum="81" stem.dir="down" tstamp.real="00:00:02.4" vel="0"/> <rest xml:id="m-96" dur="4" dur.ppq="256" tstamp.real="00:00:03"/> <rest xml:id="m-97" dur="2" dur.ppq="512" tstamp.real="00:00:03.6"/> </layer> </staff> <staff xml:id="m-98" n="2"> <layer xml:id="m-99" n="1"> <note xml:id="m-100" dur="4" dur.ppq="256" oct="5" pname="a" pnum="81" stem.dir="down" tstamp.real="00:00:02.4" vel="0"/> <rest xml:id="m-101" dur="4" dur.ppq="256" tstamp.real="00:00:03"/> <rest xml:id="m-102" dur="2" dur.ppq="512" tstamp.real="00:00:03.6"/> </layer> </staff> <staff xml:id="m-103" n="3"> <layer xml:id="m-104" n="1"> <note xml:id="m-105" dur="4" dur.ppq="256" oct="5" pname="a" pnum="81" stem.dir="down" tstamp.real="00:00:02.4" vel="0"/> <rest xml:id="m-106" dur="4" dur.ppq="256" tstamp.real="00:00:03"/> <rest xml:id="m-107" dur="2" dur.ppq="512" tstamp.real="00:00:03.6"/> </layer> </staff> <staff xml:id="m-108" n="4"> <layer xml:id="m-109" n="1"> <note xml:id="m-110" dur="4" dur.ppq="256" oct="5" pname="a" pnum="81" stem.dir="down" tstamp.real="00:00:02.4" vel="0"/> <rest xml:id="m-111" dur="4" dur.ppq="256" tstamp.real="00:00:03"/> <rest xml:id="m-112" dur="2" dur.ppq="512" tstamp.real="00:00:03.6"/> </layer> </staff> <staff xml:id="m-113" n="5"> <layer xml:id="m-114" n="1"> <note xml:id="m-115" dur="4" dur.ppq="256" oct="7" pname="a" pnum="105" stem.dir="down" tstamp.real="00:00:02.4" vel="0"/> <rest xml:id="m-116" dur="4" dur.ppq="256" tstamp.real="00:00:03"/> <rest xml:id="m-117" dur="2" dur.ppq="512" tstamp.real="00:00:03.6"/> </layer> </staff> </measure> </section> <annot xml:id="m-24" type="duration">00:00:04.8</annot> </score> </mdiv> </body> </music> </mei> ``` </details> <p>When exporting to MusicXML, it looks great: </p> <img width="898" alt="grafik" src="https://user-images.githubusercontent.com/45632600/159308281-e5e4ee11-f124-44b1-8d97-f135078e85f5.png"> <details> <summary>Imported MEI via MusicXML:</summary> ```xml <?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> Copyright © 2022-03-21 Verovio

Transcoded from MusicXML

Fl. Kl. Asax. Trp. Glsp.
```
rettinghaus commented 2 years ago

This is interesting. It looks like the actual values for @trans.diat and @trans.semi are correct, but everything visual is wrong, i.e. written as it would sound.

wergo commented 2 years ago

Yes, exactly, only the Glockenspiel converts a little more strangely.

craigsapp commented 2 years ago

Glockenspiel has a two octave transposition down for the written score. Often the transposition is wrong in Sibelius unless the person explicitly added a glockenspiel instrument, since octave transpositions are easy to overlook.

I suspect that there is a separate attribute in Sibelius for transposing by octave, or there is an additional octave adjustment for the transposition. For example, a B-flat bass clarinet should be written up a major 9th (octave + a major 2nd), so that would be a good test instrument to see which of the two cases is happening.

ahankinson commented 2 years ago

Related:

ahankinson commented 2 years ago

I'm trying to remember this -- I think what happens is that you have to choose between the encoding being correct (e.g., the notes are encoded in the correct octave) but visually incorrect (leger lines) OR the visual appearance as correct, but without the correct octave.

Your MusicXML export may look correct, but it's incorrect in its encoding -- As @craigsapp says, the glockenspiel plays in the 7th octave, not the 5th. It also loses any indication that it's a transposing instrument in the staffdef of the MusicXML file.

How are you rendering the MEI file? Is it possible that Verovio doesn't understand the trans.diat and trans.semi attributes? If it did, it could automatically adjust the rendering of the notes to have the correct visual display while still keeping the correct encoding.

wergo commented 2 years ago

@ahankinson thanks for clarifying.

So, the Glockenspiel in the sib-->musicXml-->MEI file lacks trans.diat="0" trans.semi="24" in staffDef. However, the exported musicXml file contains information about the transposition through an octave-change element:

  <transpose>
     <diatonic>0</diatonic>
     <chromatic>0</chromatic>
     <octave-change>2</octave-change>
    </transpose>

This should be imported by Verovio. I will raise an issue there.

Is it possible that Verovio doesn't understand the trans.diat and trans.semi attributes?

No, it does understand them. When exporting the MEI to MIDI, the sounded pitches are adapted using the @trans attributes. The visible pitches should be the notated ones, not the sounding ones (https://music-encoding.org/guidelines/v4/content/cmn.html#cmnDefs).

ahankinson commented 2 years ago

I'm still not sure how you are rendering the first example (the one with the Glockenspiel on the ledger lines). Sibelius doesn't do MEI import, so it must be Verovio? Or am I missing something?

annplaksin commented 2 years ago

@wergo At least according to the Reference Book, att.transposition within <staffDef> should be available in Verovio

wergo commented 2 years ago

I'm still not sure how you are rendering the first example (the one with the Glockenspiel on the ledger lines). Sibelius doesn't do MEI import, so it must be Verovio? Or am I missing something?

Yes, I am using Verovio for both renderings. The first one from sibMEI export; the second one through musicXML.

wergo commented 2 years ago

@wergo At least according to the Reference Book, att.transposition within <staffDef> should be available in Verovio

Yes, Verovio correctly imports <transpose><diatonic> and <transpose><chromatic> from musicXML; we would have to add <ocatve-change> there, but this is not related to sibMEI.

rettinghaus commented 2 years ago

We have nothing directly comparable in MEI for <octave-change>. From the MusicXML description I think this would basically be something that applies to the clef (see also https://github.com/music-encoding/music-encoding/issues/440). But we also can change the MusicXML import in Verovio to translate this to @trans.diat and @trans.semi.

rettinghaus commented 2 years ago

But the main issue here is with SibMEI, isn't it?

wergo commented 2 years ago

But the main issue here is with SibMEI, isn't it?

Yes, absolutely.

ahankinson commented 2 years ago

So what should the value of @oct be for the glockenspiel?

th-we commented 2 years ago

Sibmei exports sounding pitch(*). Sibelius is distinguishing between "sounding (concert) pitch" and "transposed pitch".

grafik

But "sounding pitch" or "non-transposing" is not fitting terminology here because both modes are in fact transposing – as is the case for the default Glockenspiel:

grafik

Written middle C would have to sound as C4 to be truly non-transposing. In lack of a better term, let me use the slightly less non-fitting term "concert pitch".

What would be the right things to do IMO:

(*)At least mostly. When there are <octave> lines, the encoded pitch is not the actual sounding pitch.

wergo commented 2 years ago

So what should the value of @oct be for the glockenspiel?

oct="5" to reflect the written pitch, and adding @trans.semi="24" to define the sounding pitch.

ahankinson commented 2 years ago

... or oct="7" for the logical encoding, and subtracting @trans.semi="24" to get the written rendering?

ahankinson commented 2 years ago

The argument being that the note is, independent of sounding or written, functionally in the 7th octave (as in, any other note written in the 6th octave in another voice, the note sounds in the octave above, rather than in the octave below).

th-we commented 2 years ago

... or oct="7" for the logical encoding, and subtracting @trans.semi="24" to get the written rendering?

That's not how I read the specification of @trans.*.

Also, @pname/@oct are specified to encode written pitch. We could additionally write @pname.ges and @oct.ges for sounding pitch, though that would be redundant with @trans.*.

craigsapp commented 2 years ago

Yes, what @th-we said. MEI usually encodes written pitch (for transposing scores) and then transposes the data when creating MIDI (or to create a sounding score). Humdrum usually encodes the sounding pitch, and then transposition is applied to get the written pitch.

Here is an example where there are four instruments that have the same written pitch, but different sounding pitches:

Screen Shot 2022-03-22 at 8 05 51 AM

Notation generated with verovio:

Screen Shot 2022-03-22 at 8 05 56 AM
Click to view MEI translation of the Humdrum score ```xml </titleStmt> <pubStmt /> </fileDesc> <encodingDesc> <appInfo> <application isodate="2022-03-22T08:08:39" version="3.10.0-dev-fe12a79-dirty"> <name>Verovio</name> <p>Transcoded from Humdrum</p> </application> </appInfo> </encodingDesc> <workList> <work> <title /> </work> </workList> </meiHead> <music> <body> <mdiv xml:id="mstyh00"> <score xml:id="s2joi6o"> <scoreDef xml:id="spxm7rt" midi.bpm="400.000000"> <staffGrp xml:id="sthqxdc" symbol="bracket"> <staffDef xml:id="sfnmos5" n="1" lines="5" trans.diat="14.000000" trans.semi="24.000000"> <label xml:id="label-L2F4">Glockenspiel</label> <clef xml:id="ccx9j9c" shape="G" line="2" /> </staffDef> <staffDef xml:id="sboimly" n="2" lines="5" trans.diat="7.000000" trans.semi="12.000000"> <label xml:id="label-L2F3">Piccolo</label> <clef xml:id="czfolgn" shape="G" line="2" /> </staffDef> <staffDef xml:id="s4yvymz" n="3" lines="5"> <label xml:id="label-L2F2">Cello</label> <clef xml:id="c2wzprk" shape="G" line="2" /> </staffDef> <staffDef xml:id="sah313b" n="4" lines="5" trans.diat="-7.000000" trans.semi="-12.000000"> <label xml:id="label-L2F1">Contrabass</label> <clef xml:id="cx6n2x8" shape="F" line="4" /> </staffDef> </staffGrp> </scoreDef> <section xml:id="section-L1F1"> <measure xml:id="measure-L1"> <staff xml:id="sq32bxj" n="1"> <layer xml:id="layer-L1F4N1" n="1"> <note xml:id="note-L5F4" dur="1" oct="4" pname="c" accid.ges="n" /> </layer> </staff> <staff xml:id="sdfoorw" n="2"> <layer xml:id="layer-L1F3N1" n="1"> <note xml:id="note-L5F3" dur="1" oct="4" pname="c" accid.ges="n" /> </layer> </staff> <staff xml:id="sl7qv9r" n="3"> <layer xml:id="layer-L1F2N1" n="1"> <note xml:id="note-L5F2" dur="1" oct="4" pname="c" accid.ges="n" /> </layer> </staff> <staff xml:id="s9hkwy2" n="4"> <layer xml:id="layer-L1F1N1" n="1"> <note xml:id="note-L5F1" dur="1" oct="4" pname="c" accid.ges="n" /> </layer> </staff> </measure> </section> </score> </mdiv> </body> </music> </mei> ``` </details> <p>Preferably MEI would not implement a separate attribute for <code><octave-change></code>, since it is better to incorporate the octave transpositions into the <code>@trans.semi</code> and <code>@trans.diat</code> system (by adding 12 for each octave in <code>semi</code> and 7 for each octave in <code>diat</code>).</p> <p>But one thing in favor of preserving <code><octave-change></code> is that it would allow you to convert back and forth to/from a sounding score: When creating a sounding score, the octave transposition instruments maintain their transpositions. For example, the glockenspiel notation will look exactly the same in both sounding and transposing scores (and will always have a two octave transposition to sounding pitch). Incorporating <code><octave-change></code> into <code>@trans.semi</code> and <code>@trans.diat</code> would make conversion between sounding and transposing scores much more difficult to implement.</p> </div> </div> <div class="comment"> <div class="user"> <a rel="noreferrer nofollow" target="_blank" href="https://github.com/rettinghaus"><img src="https://avatars.githubusercontent.com/u/7693447?v=4" />rettinghaus</a> commented <strong> 11 months ago</strong> </div> <div class="markdown-body"> <p>NB: The Dolet plugin does a lot for calculating the written pitch. We could use their code as a guide: <a href="https://github.com/MakeMusicInc/DoletSibelius/blob/main/Dolet8.plg">https://github.com/MakeMusicInc/DoletSibelius/blob/main/Dolet8.plg</a></p> </div> </div> <div class="page-bar-simple"> </div> <div class="footer"> <ul class="body"> <li>© <script> document.write(new Date().getFullYear()) </script> Githubissues.</li> <li>Githubissues is a development platform for aggregating issues.</li> </ul> </div> <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"></script> <script src="/githubissues/assets/js.js"></script> <script src="/githubissues/assets/markdown.js"></script> <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.4.0/build/highlight.min.js"></script> <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.4.0/build/languages/go.min.js"></script> <script> hljs.highlightAll(); </script> </body> </html>