Closed peterkorgaard closed 4 years ago
This is a problem that is much discussed and never seems to go away. Related to an issue from 2.5 years ago https://github.com/rism-ch/verovio/issues/190 and from 1.5 weeks ago https://github.com/rism-ch/verovio/issues/974.
The solution, as you point out, is that notes with an implicit sharp must also include the attribute accid.ges="s"
.
Here is a generalized test case:
@clef:G-2
@keysig:0
@timesig:4/4
@data:'4xGGGG+/GxGGG+/1G+/1G+/4GxG''2G//
All notes except for the last one are G-sharps. The last note is a G nautral.
Here are some things mixed up.
That is not really an encoding problem in MEI (so not really connected to #190 and #974). Instead it has something to do with Plaine & Easie code, that was never made for encoding sound, but what is written.
Plaine & Easie code is for "entering music incipits in modern or mensural notation" (https://www.iaml.info/plaine-easie-code). So the "generalized test case" isn't really one.
The first case could be solved relatively easy. But I'm not sure about a general solution.
There are still other problems in the PAE importer with preliminary (or ugly) fixes.
I know that PAE was never made in relation to generating MIDI, but I do not think this is the problem.
Within the PAE code is every information needed to convert it to correct MEI with accid.ges. The coversion just need to follow the rules for musical notation. At the moment the generated MEI is incorrect - not in visual apperance, but in terms of the attributes assigned.
Generally I think one of Verovios' strongest features is the possibility to use PAE or MEI - whatever fits the purpose best. If PAE is unable to convert correctly to MEI, and thereby creating propper MIDI, the value downgrades significant.
Here are some things mixed up.
OK, then that is not a bug, but should be classified as a feature request.
The primary use of Plaine & Easie is encoding for RISM A/II, which is music manuscripts after 1600. So if there are ambiguities, then the majority interpretation should be for CMN rather than mensuration. And since P&E is for opening measures of a piece of music, it is not common to find written accidentals at the start of mensural music.
Ideally the P&E importer should include an option for how to interpret accidentals.
It is critically related to those two issues: The MEI data in this case must therefore indicate that the accid.ges
state is undefined (which is not currently possible to do in an explicit manner). In #974, you say that no @accid.ges
means @accid.ges="n"
, but now you are saying that no @accid.ges
means @accid.ges="undefined"
. There is only 10 days between these two interpretations 😛 Having this ambiguous interpretation of a missing @accid.ges
in MEI is bad. This is also why I add @accid.ges
if there is no @accid
on every single note in the humdrum-to-mei importer.
One possibility is that I could add the Humdrum PAE importer to verovio, similar to the one for MusicXML which is already there.
https://github.com/craigsapp/humextra/blob/master/src-programs/pae2kern.cpp http://extras.humdrum.org/man/pae2kern
The converter does include interpretation of implicit accidentals:
!!!clef:G-2
!!!key:
!!!keysig:0
!!!timesig:4/4
!!!alttimesig:
!!!incipit:'4xGGGG//
**kern
*MM120
*clefG2
*k[]
*M4/4
4g#
4g#
4g#
4g#
=||
*-
Which then transforms into MEI with the Humdrum importer in verovio as:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="http://music-encoding.org/schema/4.0.0/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="http://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 />
</fileDesc>
<encodingDesc>
<appInfo>
<application isodate="2019-01-13T10:05:06" version="2.0.0-dev-5832f47-dirty">
<name>Verovio</name>
<p>Transcoded from Humdrum</p>
</application>
</appInfo>
</encodingDesc>
<workList>
<work>
<title />
</work>
</workList>
<extMeta>
<frames xmlns="http://www.humdrum.org/ns/humxml">
<metaFrame n="0" token="!!!clef:G-2" xml:id="L1">
<frameInfo>
<startTime float="0" />
<frameType>reference</frameType>
<referenceKey>clef</referenceKey>
<referenceValue>G-2</referenceValue>
</frameInfo>
</metaFrame>
<metaFrame n="1" token="!!!key:" xml:id="L2">
<frameInfo>
<startTime float="0" />
<frameType>reference</frameType>
<referenceKey>key</referenceKey>
<referenceValue />
</frameInfo>
</metaFrame>
<metaFrame n="2" token="!!!keysig:0" xml:id="L3">
<frameInfo>
<startTime float="0" />
<frameType>reference</frameType>
<referenceKey>keysig</referenceKey>
<referenceValue>0</referenceValue>
</frameInfo>
</metaFrame>
<metaFrame n="3" token="!!!timesig:4/4" xml:id="L4">
<frameInfo>
<startTime float="0" />
<frameType>reference</frameType>
<referenceKey>timesig</referenceKey>
<referenceValue>4/4</referenceValue>
</frameInfo>
</metaFrame>
<metaFrame n="4" token="!!!alttimesig:" xml:id="L5">
<frameInfo>
<startTime float="0" />
<frameType>reference</frameType>
<referenceKey>alttimesig</referenceKey>
<referenceValue />
</frameInfo>
</metaFrame>
<metaFrame n="5" token="!!!incipit:'4xGGGG// " xml:id="L6">
<frameInfo>
<startTime float="0" />
<frameType>reference</frameType>
<referenceKey>incipit</referenceKey>
<referenceValue>'4xGGGG//</referenceValue>
</frameInfo>
</metaFrame>
</frames>
</extMeta>
</meiHead>
<music>
<body>
<mdiv xml:id="mdiv-0000002047778210">
<score xml:id="score-0000001435448648">
<scoreDef xml:id="scoredef-0000001769908001" midi.bpm="120">
<staffGrp xml:id="staffgrp-0000000750382875">
<staffDef xml:id="staffdef-0000000324309572" clef.shape="G" clef.line="2" key.sig="0" meter.count="4" meter.unit="4" n="1" lines="5">
<label xml:id="label-0000001590776402" />
</staffDef>
</staffGrp>
</scoreDef>
<section xml:id="section-L7F1">
<measure xml:id="measure-L7" right="dbl" n="0">
<staff xml:id="staff-0000001069777701" n="1">
<layer xml:id="layer-L7F1N1" n="1">
<note xml:id="note-L12F1" dur="4" oct="4" pname="g" accid="s" />
<note xml:id="note-L13F1" dur="4" oct="4" pname="g" accid.ges="s" />
<note xml:id="note-L14F1" dur="4" oct="4" pname="g" accid.ges="s" />
<note xml:id="note-L15F1" dur="4" oct="4" pname="g" accid.ges="s" />
</layer>
</staff>
</measure>
</section>
</score>
</mdiv>
</body>
</music>
</mei>
Notice that it includes the desired accid.ges="s"
. And renders notation correctly:
And MIDI export from verovio now sounds correct.
The importer should probably include information about the explicit visual accidentals, which is currently being thrown away (all notes in the Humdrum data are g#
, but the first one could be encoded as g#X
to indicate that the sharp is written). But my Humdrum-to-MEI converter reconstructs this visual information.
The most precise conversion would be:
!!!clef:G-2
!!!key:
!!!keysig:0
!!!timesig:4/4
!!!alttimesig:
!!!incipit:'4xGGGG//
**kern
*MM120
*clefG2
*k[]
*M4/4
4g#X
4g#y
4g#y
4g#y
=||
*-
Where X
means the accidental is written, and y
means that it is interpreted (visually hidden, but sonically audible).
But pae2kern does not yet handle accidentals for tied notes across barlines and needs to treat octave accidentals separately, so its conversion would need adjustment. The current output for the generalized case:
!!!clef:G-2
!!!key:
!!!keysig:0
!!!timesig:4/4
!!!alttimesig:
!!!incipit:'4xGGGG+/GxGGG+/1G+/1G+/4GxG''2G//
**kern
*MM120
*clefG2
*k[]
*M4/4
4g#
4g#
4g#
[4g#
=
4g]
4g#
4g#
[4g#
=
[1g
=
[1g
=
4g]
4g#
2gg#
=||
*-
The ties are converted properly, but the humdrum-to-MEI converter is refusing to convert them since they are not tieing the same pitches together (g-sharp to g-natural).
If you import ABC notation, what would you do? The encoding of accidentals in ABC notation is also implicit like P&E.
http://abcplus.sourceforge.net/#choralmusic http://abcplus.sourceforge.net/Choral/Ave_Maria_Arcadelt.pdf http://abcplus.sourceforge.net/Choral/Ave_Maria_Arcadelt.abc
The fourth measure ABC encoding:
[V: S] (BA) !p!G2 |z AGA|(FG) A2|
w: ple -na, Do-mi-nus te -cum,
The B-flat is encoded as B in the data (the first note in the example data).
The MusicXML conversion: http://abcplus.sourceforge.net/Choral/Ave_Maria_Arcadelt.xml
identifies that note as flat:
<measure number="4">
<note>
<pitch>
<step>B</step>
<alter>-1</alter>
<octave>4</octave>
</pitch>
<duration>120</duration>
<voice>1</voice>
<type>quarter</type>
<notations>
<slur number="1" type="start"/>
</notations>
<lyric number="1">
<syllabic>single</syllabic>
<text>ple</text>
</lyric>
</note>
And likewise the flat from the signature is added to the MIDI conversion: http://abcplus.sourceforge.net/Choral/Ave_Maria_Arcadelt.mid
@craigsapp I never said a missing @accid.ges
would/could/should mean @accid.ges="undefined"
! Verovio basically just reacts to explicit accidentals in PAE.
(However the actual key written at the beginning is affecting @accid.ges
, which I added in #652).
And as I said, the first case, i.e. bar lines reset accidentals, would be really easy to add. Tied notes are a bit tricky.
You are saying it here:
Plaine & Easie code is for "entering music incipits in modern or mensural notation" (https://www.iaml.info/plaine-easie-code). So the "generalized test case" isn't really one.
Or you can elaborate on what that means.
That means, that how many notes are affected by an accidental, changed over time. E.g. in the 17th century a bar line not always cancels an accidental.
Yes, so this means that in the general case, 100% certainty in @accid.ges
for the converter is not possible. To be the most careful, the converter should be able to encode a state meaning "I do not know". You could then apply a particular ruleset for assigning @accid.ges
.
For amusement, here is a random Tasso musical setting published in 1602:
This one is interesting because on the third line of music there are three F-sharps in a row, and every note has a sharp in front of it. I think the general rule around that time was that the sharp would apply to all F's immediately following the first sharped F, but if there were any other pitch, that would cancel the sharp sign even if an F immediately followed that note. When they started putting barlines into the music, the still kept that basic rule and cancelling due to the barline was a later convention.
Modern transcription:
http://www.tassomusic.org/work/?id=Trm0025c
[ligature bracket starting in m7 is not added -- but that is now possible in verovio since last month, so I will add it soon]
Here is the Tenor part (no scan available online I think), where there is only one natural to cancel out the flat for a string of B's:
But there are two repeated C-sharps in a row that happen to cross a barline in the modern edition by coincidence.
The Alto part has the feature I was describing above:
In measure 26 there is a natural written in front of the B, then a C, then a B without a sign, which is interpreted to be a B-flat due to the key signature, and not B-natural due to the intervening C.
Then in the next measure the editor (Emiliano Ricciardi) seems to over interpret by saying that the first F in that measure should be sharped, eventhough only the second one has a written sharp (to generate a leading tone for the cadence).
fixed with 6083eb338e861f373ce4337ff262b88ebfe45ca5
This issue is constructed by using version 2.0.0-dev-61da81a of the javascript toolkit.
The musical notation rule is that an acccid is due to end of the measure - if not changed before. This means that the notation
that generates this score in playback using the generated midi should produce the midi notes 68, 68, 68, 68. It does not. It produces the notes 68,67,67,67
Examining the generated MEI it shows, that the notes after the accid does not get accid.ges applied as they should. So I believe this is happening when PAE is translated into MEI