Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@dots missing on mRest #429

Closed
rettinghaus opened this issue Apr 24, 2017 · 48 comments
Closed

@dots missing on mRest #429

rettinghaus opened this issue Apr 24, 2017 · 48 comments

Comments

@rettinghaus
Copy link
Member

Is there any reason why <mRest> is missing in att.augmentdots?

@craigsapp
Copy link
Member

Centered full-measure rests are not supposed to have augmentation dots.

@rettinghaus
Copy link
Member Author

meaning <mRest> is only one specific symbol? Even in 3/8 meter? And @dots is a visual attribute? Then why is it available on <space> and <mSpace>? And <bTrem>? And <fing>, and <harm>, and <tuplet>?

@craigsapp
Copy link
Member

meaning is only one specific symbol? Even in 3/8 meter?

Yes, especially in 3/8:

screen shot 2017-04-24 at 11 02 15 am

Putting a dot on the whole-measure centered rests (mRest) or making them a dotted-quarter rest in this case would be a serious offense to CMN.

An exception would be for meters equal or greater than 8/4, where a whole-measure rests looks stupid if using a whole rest, so a breve rest should be used. And by extension meters equal or greater than 16/4 should use a long rest, and equal or greater than 32/4 should use a maxima rest (and 64/4 and higher should use a double maxima rest, but now things are getting silly).

And @dots is a visual attribute?

@dots seem to have a dual purpose of being visual and modifying the @dur of elements. Are these functions separable in MEI? In other words, how is the visual dot supposed to be hidden on a dotted half note?


So actually the real reason for the lack of @dots is that <mRest> is supposed to receive its duration from the prevailing time signature, and it does not contain the duration within itself. <mRest> should also exclude @dur, but I see it listed:
http://music-encoding.org/documentation/3.0.0/mRest
so I would have a counter-issue complaining that @dur should be removed since @dur and @dots should always be linked together in their inclusion or exclusion from an element.

This is contrary to <space> which does contain duration, and by extension requires @dots. Notice that <space>, <note>, <rest> and other durational elements cannot represent all durations. For example, how should a duration of 11 eighth notes be represented? As far as I have been able to figure out it is impossible to do that in MEI, and therefore a <space> cannot have a duration of 11 eighth notes and must be split into multiple <space> which add up to 11 eighth notes (which by the way is why <space> is really an invisible rest, @kepper). So regular rests cannot fully represent as a single element in every possible meter duration.

Here is an example of music in 11/8:

screen shot 2017-04-24 at 11 20 04 am

Notice that it is impossible to have a single note representing a sustained note filling a measure in 11/8, so it must be split into two notes added together with a tie. Similarly there is no single rest which represents 11 eighths notes, so the <mRest> could not be assigned a correct duration even if @dots were allowed.

MEI test data:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="http://music-encoding.org/schema/3.0.0/mei-all.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="http://music-encoding.org/schema/3.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="3.0.0">
    <meiHead>
        <fileDesc>
            <titleStmt>
                <title />
            </titleStmt>
            <pubStmt />
        </fileDesc>
        <encodingDesc>
            <appInfo>
                <application isodate="2017-04-24T11:10:57" version="0.9.14-dev-98874c6">
                    <name>Verovio</name>
                    <p>Transcoded from Humdrum</p>
                </application>
            </appInfo>
        </encodingDesc>
        <workDesc>
            <work>
                <titleStmt>
                    <title />
                </titleStmt>
            </work>
        </workDesc>
    </meiHead>
    <music>
        <body>
            <mdiv>
                <score>
                    <scoreDef xml:id="scoredef-0000001194634597">
                        <staffGrp xml:id="staffgrp-0000001503258451">
                            <staffDef xml:id="staffdef-0000000102767551" n="1" clef.shape="G" clef.line="2" meter.count="11" meter.unit="8" lines="5" />
                        </staffGrp>
                    </scoreDef>
                    <section xml:id="section-0000001133282998">
                        <measure xml:id="measure-L3" n="1" type="m-1">
                            <staff xml:id="staff-L3F1N1" n="1">
                                <layer xml:id="layer-L3F1N1" n="1">
                                    <note xml:id="note-L4F1" type="qon-0 qoff-4 pname-c acc-n oct-4 b40c-2 b12c-0  tie-start" dur="1" oct="4" pname="c">
                                        <accid xml:id="accid-L4F1" accid.ges="n" />
                                    </note>
                                    <note xml:id="note-L5F1" type="qon-4 qoff-11_2 pname-c acc-n oct-4 b40c-2 b12c-0  tie-stop" dots="1" dur="4" oct="4" pname="c">
                                        <accid xml:id="accid-L5F1" accid.ges="n" />
                                    </note>
                                </layer>
                            </staff>
                            <tie xml:id="tie-L4F1-L5F1" startid="#note-L4F1" endid="#note-L5F1" />
                        </measure>
                        <measure xml:id="measure-L6" n="2" type="m-2">
                            <staff xml:id="staff-L6F1N1" n="1">
                                <layer xml:id="layer-L6F1N1" n="1">
                                    <mRest xml:id="mrest-0000001150793255" />
                                </layer>
                            </staff>
                        </measure>
                        <measure xml:id="measure-L8" n="3" right="end" type="m-3">
                            <staff xml:id="staff-L8F1N1" n="1">
                                <layer xml:id="layer-L8F1N1" n="1">
                                    <note xml:id="note-L9F1" type="qon-11 qoff-15 pname-c acc-n oct-4 b40c-2 b12c-0  tie-start" dur="1" oct="4" pname="c">
                                        <accid xml:id="accid-L9F1" accid.ges="n" />
                                    </note>
                                    <note xml:id="note-L10F1" type="qon-15 qoff-33_2 pname-c acc-n oct-4 b40c-2 b12c-0  tie-stop" dots="1" dur="4" oct="4" pname="c">
                                        <accid xml:id="accid-L10F1" accid.ges="n" />
                                    </note>
                                </layer>
                            </staff>
                            <tie xml:id="tie-L9F1-L10F1" startid="#note-L9F1" endid="#note-L10F1" />
                        </measure>
                    </section>
                </score>
            </mdiv>
        </body>
    </music>
</mei>

@pe-ro
Copy link
Contributor

pe-ro commented Apr 24, 2017

So actually the real reason for the lack of @dots is that is supposed to receive its duration from the prevailing time signature, and it does not contain the duration within itself. should also exclude @Dur

Precisely, <mRest> is time signature dependent. And, yes, @dur shouldn't be allowed.

This is contrary to which does contain duration, and by extension requires @dots. Notice that <space>, <note>, <rest> and other durational elements cannot represent all durations. For example, how should a duration of 11 eighth notes be represented? As far as I have been able to figure out it is impossible to do that in MEI, and therefore a <space> cannot have a duration of 11 eighth notes and must be split into multiple which add up to 11 eighth notes (which by the way is why <space> is really an invisible rest, @kepper). So regular rests cannot fully represent as a single element in every possible meter duration.

Again, spot on (except for the invisible rest part, 😀 ). But this is a limitation within CMN, which MEI simply mimics.

@kepper
Copy link
Member

kepper commented Apr 24, 2017

I guess @rettinghaus is coming from examples typical for Bach, where he writes a whole rest in one measure, and then an augmentation dot in the following. While this is not the way we would handle it nowadays, it's perfectly valid for CMN of his period, and, luckily, MEI allows to encode that in a much better way than using @dots: Use the <dot> element in the following measure. Otherwise you'd have to offset everything in there with spaces, and you would end up with a pretty messy encoding.
I think I don't have to comment on all the other aspects in here ;-)

@craigsapp
Copy link
Member

Bach, where he writes a whole rest in one measure, and then an augmentation dot in the following.

That is a different situation, is it not? In 4/4 that would indicate a rest with 6 quarter notes duration, but the dotted part of the duration is in the next measure. And that sort of notation was also applied to notes:

screen shot 2017-04-24 at 7 42 43 pm

The whole note rest still gets its duration from the meter, and the augmentation dot adds half of whatever that is.

@rettinghaus
Copy link
Member Author

It's not that I want to have a (visual) dot on mRest. I just wanted to point out the ambiguity of @dots and that there is something mixed up with att.duration.additive, att.duration.musical, and att.augmentdots.
It simply makes no sense to have @dots on mSpace but not on mRest.
I'm ok with dropping @dur from mRest, but then this should apply to mSpace, too.
If @dur is to stay, then mRest and mSpace should be part of att.duration.additive.
And elements that are part of att.duration.additive already must not be part of att.augmentdots, e.g. <annot> and <fing>.

@kepper
Copy link
Member

kepper commented Apr 25, 2017

@rettinghaus, I think we are on the same page then. Yes, @dots should go away from <mRest>. And in order to bring up something even more scary when thinking about "strict" rules of CMN, here's a snippet from Schütz' Matthäuspassion:
grafik
How do you solve that one, @craigsapp and @pe-ro ?

@craigsapp
Copy link
Member

craigsapp commented Apr 25, 2017

That is a funny one with a barline splitting a notehead.

A general problem is what is meant by CMN, with "C" meaning common? Is splitting the note in half by a barline something a publisher would do, or is it something that is a shorthand for writing the score out by hand (save time to not write out a separate note and draw a tie)? I wonder what would happen if there were a quarter note in the bottom staff on the last beat of the first measure? Would that cause the notation of the measure-split note to change? It would have to be moved to the left to align with the quarter note... And would the performance parts do the same thing?

Barlines had just been invented, and people were experimenting with their syntax, so this is a now extinct transitional species. Are there any tied notes in the manuscript? I presume that tied notes had been invented by the time this was written, but it would be interesting if not.

Another thing would be the flat in the bottom key signature. Notice that it splits the clef symbol in half. Should that be encoded?


Here is how I would do it in SCORE:

screen shot 2017-04-25 at 5 48 33 am

This turned out to be moderately easy. To split the notehead by the barline, I added a horizontal offset to the notehead to place it on the barline. The dot is represented by a note object that has no stem or notehead, just an augmentation dot and a duration of a quarter note. In theory I could have attached the dot to the previous note, but in SCORE there is a maximum dot displacement which is slightly less than I wanted, so I had to detach it from the owning note.

The main complication is that you cannot do LJ (line-up and justify for horizontal spacing) with the barline going through a note, even if it has an explicit horizontal offset, since SCORE will force them to not collide. However, I can make the barline only one staff high, then do LJ, and then make it 2 staves high again to get the proper horizontal spacing:

screen shot 2017-04-25 at 5 55 08 am

So the main fiddly part is to temporarily change the barline height.

Here is encoding the stem directions and lengths of the original:

screen shot 2017-04-25 at 6 04 33 am


In Humdrum I would encode it with a modern syntax of splitting the notes across the barline with ties. For analyses based on semantics I would not care about the syntax of the notes in this configuration, but I have dealt with a similar situation in JRP:

http://josquin.stanford.edu/cgi-bin/jrp?a=notationEditText&f=Jos0402a

screen shot 2017-04-25 at 6 15 11 am

In this case the long in the tenor part is twice as long as those of the other parts. This is a terminal long, and such a long can last for several measures. The note is supposed to be held until everyone comes to their final notes, so it functions similar to a fermata in modern notation while the other parts are finishing.

Here is the Humdrum score at that point in the music:

http://josquin.stanford.edu/cgi-bin/jrp?a=humdrum&f=Jos0402a

=62	=62	=62	=62
0.E	[0.el	2c\	2.g/
.	.	1B	.
.	.	.	4f/
.	.	.	2g/
.	.	2A/	1a
.	.	1B	.
.	.	.	2g#i/
=63	=63	=63	=63
0.AAl	0.e]	0.Al	0.al
==	==	==	==
*-	*-	*-	*-
!!!RDF**kern: l=long note in original notation

I add the character "l" to notes which should be displayed as long notes. This in turn causes all of the attached tied notes (and ties) of the secondary tied notes to be hidden in the rendering of the notation.

For the current example, I would probably do it like this in Humdrum:

**kern	**kern
*clefF4	*clefC4
*k[b-]	*k[b-]
2D	2d
[2B-i	4r
.	[4dN
=	=
4B-]	4d]
4F	4c
2G	2B-
=	=
*-	*-
!!!RDF**kern: i = augmentation dot after barline
!!!RDF**kern: N = notehead on barline

The "i" and the "N" would function similar to "l" in the previous example to instruct the renderer to use a non-modern syntax for those notes.

An advantage of this system is that it is renderable in verovio with my current converter and verovio's current rendering capability:

screen shot 2017-04-25 at 6 29 07 am

My converter is also set up to deal with such a representation in a useful way with verovio, where I can highlight the notes in the score that are an exception to current CMN:

screen shot 2017-04-25 at 6 34 02 am

I add the text "marked note" to the user signifier definitions, with the default rendering color being red, and then one category is given a green color.

**kern	**kern
*clefF4	*clefC4
*k[b-]	*k[b-]
2D	2d
[2B-i	4r
.	[4dN
=	=
4B-]	4d]
4F	4c
2G	2B-
=	=
*-	*-
!!!RDF**kern: i = augmentation dot after barline, marked note color=lawngreen
!!!RDF**kern: N = notehead on barline, marked note

For encoding in MEI, I leave that up to @per-ro :-) This is a hierarchy-crossing case which gets messy with tree structures. Notice that SCORE has no problem with such a case. Your solution of encoding <dot> works for the augmentation dot (although it is more complicated than the Humdrum solution above).

@pe-ro
Copy link
Contributor

pe-ro commented Apr 25, 2017

What if we replaced all invocations of data.DURATION; that is, powers-of-two values, with calls to data.DURATION.additive? (Actually, it's probably better just to rename data.DURATION.additive to data.DURATION.) This would put @dur squarely in the logical domain -- <note dur="2."/> is pretty unambiguous. Then, @dots can become a purely visual domain thing indicating how many augmentation dots are visually present. Or we can drop @dots entirely and use <dot> children. Either one provides a clearer separation between the logical and visual domains (though dropping @dots is the clearest). @dur.ges will continue to be used for the gestural/performance domain.

@rettinghaus
Copy link
Member Author

As this is a pretty huge step, I didn't dare to suggest something like this by myself. But merging data.DURATION and data.DURATION.additive seems like a good idea. And personally I'd like to use <dot>.

I'm just not sure if dropping @dots entirely would be good. Perhaps moving it to the analytical domain for now?

@pe-ro
Copy link
Contributor

pe-ro commented Apr 25, 2017

@rettinghaus: I understand your trepidation, but @dots isn't analytical domain material, in my opinion. It would be confusing to find it in MEI.analytical. If we don't want to drop it entirely just yet, then putting it in the visual domain makes the most sense to me.

But, one could still end up with markup like --

<note dur="4.." dots="1"/>

which is confusing at first, especially for those already familiar with MEI. (After the movement of @dots from the logical to the visual domain, this would indicate that the logical duration is a double-dotted quarter note, but that only 1 dot is actually displayed.)

@pe-ro
Copy link
Contributor

pe-ro commented Apr 25, 2017

Another thing to consider is how to easily control the number of dots that events are allowed to have. Right now, with a separate @dots attribute, one can customize the number of dots pretty easily by modifying the value of data.AUGMENTDOT.

@kepper
Copy link
Member

kepper commented Apr 25, 2017 via email

@pe-ro
Copy link
Contributor

pe-ro commented Apr 25, 2017

Having too many different types of duration is a major problem. I think this fixes it nicely.

The change is not as big a shift as one might think. It still leaves logical and visual duration coupled in @dur, it just changes the syntax; that is, collapses @dur + @dots into @dur alone.

@pe-ro
Copy link
Contributor

pe-ro commented Apr 25, 2017

This should, in fact, make hand coding easier/better. 😀

@kepper
Copy link
Member

kepper commented Apr 25, 2017 via email

@pe-ro
Copy link
Contributor

pe-ro commented Apr 25, 2017

Where would you like to change it?

@pe-ro
Copy link
Contributor

pe-ro commented Apr 25, 2017

Generally, I agree that attribute value parsing isn't good, but if it makes things simpler (i.e., more easy to understand), then why not?

@kepper
Copy link
Member

kepper commented Apr 25, 2017 via email

@pe-ro
Copy link
Contributor

pe-ro commented Apr 25, 2017

We've been down the road of breaking everything into multiple attribute values. The next stage of development is to look for those places where we can reduce the number of attributes even if the result is more complex values.

@pe-ro
Copy link
Contributor

pe-ro commented Apr 25, 2017

Breaking existing markup isn't a big deal if we provide a conversion mechanism.

@kepper
Copy link
Member

kepper commented Apr 25, 2017 via email

@pe-ro
Copy link
Contributor

pe-ro commented Apr 25, 2017

The conversion mechanism is to add the number of dot characters provided in @dots to @dur --

<note dur="4" dots="1"/>

becomes

<note dur="4."/>

@pe-ro
Copy link
Contributor

pe-ro commented Apr 25, 2017

4.0 is already going to break existing applications.

You're right, there's no rush to do this. But, it will hold up getting 4.0 out the door and therefore MEI Basic, because I don't want to release 4.0 without having Basic mostly done.

@kepper
Copy link
Member

kepper commented Apr 25, 2017 via email

@pe-ro
Copy link
Contributor

pe-ro commented Apr 25, 2017

At least we should proceed with the suggestions in #429 (comment).

@kepper
Copy link
Member

kepper commented Apr 25, 2017

agreed

@ahankinson
Copy link
Member

Please don't change something like this without adequate time for community notice and feedback. I agree that this should wait until 5.0 at the earliest.

@ahankinson
Copy link
Member

Conversion mechanisms are OK for converting data, but breaking changes also break software, and there is no conversion mechanism for that.

@pe-ro
Copy link
Contributor

pe-ro commented Apr 25, 2017

All the more reason to put as many breaking changes as possible into a single version. Parceling them out can feel like death by a thousand cuts.

But, if you want to wait, we'll wait.

@ahankinson
Copy link
Member

We need to give people time to adjust to changes, and understand the reasons for making them. MEI doesn't have the luxury of not bringing lots of people along for the ride now, and making changes to fundamental components, like the representation of durations, is something we need to communicate before, during, and after the change.

Do we really gain that much more by changing this? What sorts of operations does this affect? I know it will affect our ability to do math directly on number-like duration values, for one, which seems like a pretty significant loss of functionality. @dur=2. is not unambiguous if you consider a dot following a number to be a decimal point. There's probably also implications for removing numeric values for dots as well.

I'm with Johannes, that this feels very un-MEI and hearkens back to the string-parsing days. That's fine, but it's not MEI. The "." is really only a useful character because of its shape; an ASCII period is not an indicator that half the preceding value should be added to it.

@craigsapp
Copy link
Member

craigsapp commented Apr 26, 2017

http://music-encoding.org/documentation/2.1.1/att.duration.additive
http://music-encoding.org/documentation/2.1.1/data.DURATION.additive

When the duration is "irrational", as is sometimes the case with tuplets, multiple space-separated values that add up to the total duration may be used. When dotted values are present, the dots attribute must be ignored.

I would avoid using the word irrational since musical rhythms are mathematically called rational numbers (but that does not stop musicians from using the term irrational for rational numbers :-). An irrational rhythm would be pi-uplets or the square-root-of-three-uplets.

When dotted values are present, the dots attribute must be ignored.

It does not seem too large of a change due to this sentence: currently when there are dots in @dur[technically no dots currently allowed for regular notes/rests yet], then ignore @dots [they would become visual dots in that case]. But there is a problem with the case where there are visual dots but no logical dots.

What about @dots.vis for visual dots that do not match the rhythmic @dots value? mRest could ignore @dots when calculating visual dots (since an mRest should never have dots). If dots are wanted on mRest then they would be forced with @dots.vis. Otherwise using @dots.vis="0" on regular rests/notes would suppress display of augmentation dots. @dots would remain logical dots (always affect the value of @dur), and @dots.vis would indicate visual dots which do not match the value in @dots.

I have come across a few cases of visual dots not matching rhythmic dots in C.P.E. Bach digital scores (but I would have to search my notes for where they are). But they are very rare (other than for mensural music where augmentation dots are usually invisible :-)


So for this example:

screen shot 2017-04-24 at 11 20 04 am

The additive duration of the rest would be something like:

dur="1 4."

or

dur="8 8 8 8 8 16 16 8 8. 16 8 8"

It is a bit of a bother that there are innumerable ways to represent an additive rhythm...

In humdrum I describe that rhythm as the actual sum 8%11 which means 11/8ths of a whole note. Notice that I call 8%11 a rhythm, and its reciprocal 11/8 a duration (as it is 11/8ths of a whole note duration), analogous to 4 representing a quarter note which is 1/4 (a quarter) of a whole note. MEI calls rhythms durations (i.e., 4 = 1/4).

You could instead modify additive duration representation to represent an actual sum rather than a list of space separated durations with augmentation dots (space-delimited values are way too complex for some programmers who cannot parse strings). The addition has to be done on the inverse of the rhythms (i.e., as actual durations):

1/1 + 1/4 + 1/2 * 1/4 = 11/8   ==> 8%11

Augmentation dots could then be removed from such a representation since it is purely logical and visual dots are not needed, although you will have to decide if it should allow non-power-of-two rhythmic values before dots are applied . Also breves would be 1%2 (2/1 whole notes), longs are 1%4 (4 whole notes), and maximas are 1%8 (8 whole notes), at least in modern/imperfect mensurations.

"4." means 3/8ths of a whole note, so in Humdrum **recip representation (recip = reciprocal), this can be also represented by "8%3" without the dot.


Interlude:

In terms of rhythmic reforms, I would be most interested in phasing out variable-unit @tstamps in favor of a constant-unit stamp, such as @qstamp. In other words in 4/4 meters the units of @tstamps are quarter notes, in 3/8 they are eighth notes. What are they suppose to be in compound meters such as 2/4+1/8? Or in Debussy's sunken cathedral prelude where the meter shift unmarked between 6/4 and 3/2? Also identifying the reference rhythmic value of @tstamps for random access to the data is computationally expensive (you have to search backward in the music to find the most recent key signature). This forces most processing of MEI data to be linear. Properly extracting measure 382 of some music would require backtracking to the start of the score searching for the more recent meter in order to identify the units that @tstamp refer to in that measure.


The "." is really only a useful character because of its shape; an ASCII period is not an indicator that half the preceding value should be added to it.

That is a good point (as in decimal point). Computer programmers will first think it is a decimal point and get confused. Especially since some durational units such as @tstamp can contain floating-point decimal points.

I'm with Johannes, that this feels very un-MEI and hearkens back to the string-parsing days.

The good news is that SCORE is purely numeric. Here is the 11/8 meter represented in SCORE numeric form:

8 1 0 0 0 100
3 1 1.5
18 1 8.999 0 11 8
1 1 18.999 1 10 2 4
5 1 18.999 -0.2 -0.2 35.77 -1.603 -2
1 1 35.766 1 10 0 1.5 0 10
14 1 45.924 1
2 1 49.253 0 -2 0 5.5 0 56.24
14 1 69.352 1
1 1 72.681 1 10 2 4
5 1 72.681 -0.2 -0.2 89.45 -1.603 -2
1 1 89.448 1 10 0 1.5 0 10
14 1 100 1 2

All dots in the above data are decimal points.

This example also reminds me that SCORE has an additive duration representation for text-based user input. It is basically the spaced rhythms system of MEI additive-durations without the spaces or the dots). All rhythmic values can be represented by numbers, but the main power-of-two ones have letter abbreviations, and these letter abbreviations can be glued together to form an additive duration:

1 = whole note
w = whole note
4.  == dotted quarter note
q. == dotted quarer note
wqe = whole plus quarter plus eighth (for the dot on the quarter note)

So wqe is the text-based string I typed when entering whole-measure rest in the 11/8 example music.

Likewse, MEI additive durations could exclude dots by expanding them:

1 4. would expand to 1 4 8

@pe-ro
Copy link
Contributor

pe-ro commented Apr 26, 2017

@craigsapp:

I like the idea of expanding the dots in an additive duration --

1 4. would expand to 1 4 8

The idea behind making all durations adhere to the additive datatype was to be able to force @dots to record only visual information -- the number of dots (to be) rendered. Calling it @dots.vis, however, would definitely help to clarify its use. Making all durations potentially additive also has the effect of putting @dur truly in the logical domain.

Re: qtstamps -- Although it's not called @qstamp, @tstamp.ges can record Humdrum recip values, etc. Would you have a look there and let me know if it doesn't fit your needs? We're probably closer to a resolution of this than you think. It seems to me that mostly we have a terminological problem -- what is currently labelled as being in the gestural domain, you'd prefer to label as logical.

The ultimate goal is to resolve the issues MEI has regarding duration sooner rather than later by employing @dur (using data.DURATION.additive) for "logical" info, @dur.vis + @dots.vis for "visual" info, and @dur.ges for gestural/performance info.

@craigsapp
Copy link
Member

Re: qtstamps -- Although it's not called @qstamp, @tstamp.ges can record Humdrum recip values, etc. Would you have a look there and let me know if it doesn't fit your needs? We're probably closer to a resolution of this than you think. It seems to me that mostly we have a terminological problem -- what is currently labeled as being in the gestural domain, you'd prefer to label as logical.

I don't see this as related to gestural vs. logical. Here is an illustration of the problem:

screen shot 2017-04-26 at 7 26 18 am

In both cases the duration of each measure is the same: (3 quarter notes = 6 eighth notes), and rhythmically in both cases there is a fermata on each eighth note, but the @tstamps for each measure are all different:

        <fermata staff="1" tstamp="1" place="above" />
        <fermata staff="1" tstamp="1.5" place="above" />
        <fermata staff="1" tstamp="2" place="above" />
        <fermata staff="1" tstamp="2.5" place="above" />
        <fermata staff="1" tstamp="3" place="above" />
        <fermata staff="1" tstamp="3.5" place="above" />

versus:

        <fermata staff="1" tstamp="1" place="above" />
        <fermata staff="1" tstamp="2" place="above" />
        <fermata staff="1" tstamp="3" place="above" />
        <fermata staff="1" tstamp="4" place="above" />
        <fermata staff="1" tstamp="5" place="above" />
        <fermata staff="1" tstamp="6" place="above" />

What I am saying is that it seems more logical to have the same time unit for the stamps across all meters (or cases where there are no meters or compound meters):

        <fermata staff="1" qstamp="1" place="above" />
        <fermata staff="1" qstamp="1.5" place="above" />
        <fermata staff="1" qstamp="2" place="above" />
        <fermata staff="1" qstamp="2.5" place="above" />
        <fermata staff="1" qstamp="3" place="above" />
        <fermata staff="1" qstamp="3.5" place="above" />

versus:

        <fermata staff="1" qstamp="1" place="above" />
        <fermata staff="1" qstamp="1.5" place="above" />
        <fermata staff="1" qstamp="2" place="above" />
        <fermata staff="1" qstamp="2.5" place="above" />
        <fermata staff="1" qstamp="3" place="above" />
        <fermata staff="1" qstamp="3.5" place="above" />

Full measure 1:

    <scoreDef>
         <staffGrp>
                <staffDef n="1" clef.shape="G" clef.line="2" meter.count="3" meter.unit="4" lines="5" />
          </staffGrp>
    </scoreDef>
    <measure>
        <staff n="1">
            <layer n="1">
                <beam>
                    <note dur="8" oct="4" pname="e"/>
                    <note dur="8" oct="4" pname="f"/>
                </beam>
                <beam>
                    <note dur="8" oct="4" pname="e"/>
                    <note dur="8" oct="4" pname="f"/>
                </beam>
                <beam>
                    <note dur="8" oct="4" pname="e"/>
                    <note dur="8" oct="4" pname="f"/>
                </beam>
            </layer>
        </staff>
        <fermata staff="1" tstamp="1" place="above" />
        <fermata staff="1" tstamp="1.5" place="above" />
        <fermata staff="1" tstamp="2" place="above" />
        <fermata staff="1" tstamp="2.5" place="above" />
        <fermata staff="1" tstamp="3" place="above" />
        <fermata staff="1" tstamp="3.5" place="above" />
    </measure>

Full measure 2:

    <scoreDef meter.count="6" meter.unit="8" />
    <measure right="end" type="m--1">
        <staff n="1">
            <layer n="1">
                <beam>
                    <note xml:id="note-L12F1" dur="8" oct="4" pname="e"/>
                    <note xml:id="note-L13F1" dur="8" oct="4" pname="f"/>
                    <note xml:id="note-L14F1" dur="8" oct="4" pname="e"/>
                </beam>
                <beam>
                    <note xml:id="note-L15F1" dur="8" oct="4" pname="f"/>
                    <note xml:id="note-L16F1" dur="8" oct="4" pname="e"/>
                    <note xml:id="note-L17F1" dur="8" oct="4" pname="f"/>
                </beam>
            </layer>
        </staff>
        <fermata staff="1" tstamp="1" place="above" />
        <fermata staff="1" tstamp="2" place="above" />
        <fermata staff="1" tstamp="3" place="above" />
        <fermata staff="1" tstamp="4" place="above" />
        <fermata staff="1" tstamp="5" place="above" />
        <fermata staff="1" tstamp="6" place="above" />
    </measure>

Imagine that someone wants to change the 6/8 meter in:

    <scoreDef meter.count="6" meter.unit="8" />

to 3/4 (either explicitly, or by deleting it and letting the previous meter continue).

Then the @tstamps in measure 2 must be altered:

    <measure right="end" type="m--1">
        <staff n="1">
            <layer n="1">
                <beam>
                    <note xml:id="note-L12F1" dur="8" oct="4" pname="e"/>
                    <note xml:id="note-L13F1" dur="8" oct="4" pname="f"/>
                    <note xml:id="note-L14F1" dur="8" oct="4" pname="e"/>
                </beam>
                <beam>
                    <note xml:id="note-L15F1" dur="8" oct="4" pname="f"/>
                    <note xml:id="note-L16F1" dur="8" oct="4" pname="e"/>
                    <note xml:id="note-L17F1" dur="8" oct="4" pname="f"/>
                </beam>
            </layer>
        </staff>
        <fermata staff="1" tstamp="1" place="above" />
        <fermata staff="1" tstamp="1.5" place="above" />
        <fermata staff="1" tstamp="2" place="above" />
        <fermata staff="1" tstamp="2.5" place="above" />
        <fermata staff="1" tstamp="3" place="above" />
        <fermata staff="1" tstamp="3.5" place="above" />
    </measure>

To go back to the C.P.E. Bach Fantasia in C major (Wq 61/6) that I used for the measure number letters discussion:

screen shot 2017-04-26 at 7 52 05 am

What should the @tstamp of the fermata in the last system top staff be? The measure is technically unmeasured (as often happend in fantasias). Should the meter of the last metric measure be used (2/4). But looking at the beaming in the free measure (four eighth-notes beamed together), is fits better with a meter that has "2" on the bottom.

@pe-ro
Copy link
Contributor

pe-ro commented Apr 26, 2017

In both cases the duration of each measure is the same: (3 quarter notes = 6 eighth notes)

Not necessarily. It depends on what remains constant in the change from 3/4 to 6/8. If the 8th notes take the same amount of time in both measures, then the performed duration of the measures is the same. But, if the quarter note in m. 1 is equal to the dotted quarter note in m. 2, then the performed duration of the measures is different.

MEI currently expects

<fermata staff="1" tstamp.ges="1p" place="above" />
<fermata staff="1" tstamp.ges="2p" place="above" />
<fermata staff="1" tstamp.ges="3p" place="above" />
<fermata staff="1" tstamp.ges="4p" place="above" />
<fermata staff="1" tstamp.ges="5p" place="above" />
<fermata staff="1" tstamp.ges="6p" place="above" />

Other than the trailing "p" (for pulse), which is required because @tstamp.ges allows different values which must be differentiated, this is the same as your example. If we were to decide that @tstamp.ges should henceforth use only one kind of value, then the "p" could be removed.

But thinking about your example more carefully, I think you're probably right that @tstamp.ges is the wrong label. Assuming equivalence at the 8th-note level needs a different name -- I have no objection to @qstamp. I think we still must retain @tstamp for time signature-based input. Both @tstamp and @qstamp describe the notation. @tstamp.ges may still be necessary to resolve any conflicts between the notation and its performance.

@craigsapp
Copy link
Member

Not necessarily. It depends on what remains constant in the change from 3/4 to 6/8. If the 8th notes take the same amount of time in both measures, then the performed duration of the measures is the same. But, if the quarter note in m. 1 is equal to the dotted quarter note in m. 2, then the performed duration of the measures is different.

OK to be more precise, they have the same score-time duration of three quarter notes (as you noticed after thinking more carefully :-).

score-time is a symbolic time unit based on rational numbers (integers and fractions)

real-time or performance-type is based on physical measurements of time such as seconds, hours, years, eons. These values are real numbers rather than rational numbers, such as

@tstamp and @qstamp are durations in score-time (not rhythms such as @dur and humdrum **recip values) and a 3/4 and 6/8 measure have the same duration of 3 quarter notes regardless of the tempo that a performance would realize them in.

But thinking about your example more carefully, I think you're probably right that @tstamp.ges is the wrong label. Assuming equivalence at the 8th-note level needs a different name -- I have no objection to @qstamp. I think we still must retain @tstamp for time signature-based input. Both @tstamp and @qstamp describe the notation. @tstamp.ges may still be necessary to resolve any conflicts between the notation and its performance.

I can see how current @tstamp is useful for hand-encoding, but I don't do much of that :-). However it is also a bit confusing because 6/8 has two beats of a dotted quarter note. So if you want to put a fermata on beat 2 in 6/8, the @tstamp has to be set to 4. This seems just as bad as using @qstamp with a value of 2.5, since a musician would want to use 2 for beat 2.

Adding @qstamp would be nice since it adds no additional complexity for software support of both @tstamp and @qstamp at the same time (@tstamp is the complicated one to support).
How these two interact would have to be defined: does one have precedence over the other if both attributes are given for the same element? Or should that be marked as invalid syntax or a warning on syntax with schemotrion? Or should only @tstamp or @qstamp be used exclusively in a given file (i.e., if you are using one in a file, then don't use the other)?

@pe-ro
Copy link
Contributor

pe-ro commented Apr 26, 2017

How these two interact would have to be defined: does one have precedence over the other if both attributes are given for the same element? Or should that be marked as invalid syntax or a warning on syntax with schemotrion? Or should only @tstamp or @qstamp be used exclusively in a given file (i.e., if you are using one in a file, then don't use the other)?

It's possible to do any of these using Schematron after consensus is achieved.

We've discussed this before and I don't think we're going to convince each other, but I see no inconsistency in how MEI deals with @tstamp. If 2/2 has 2 beats, 3/4 has 3 beats, and 5/8 has 5 beats, why is it radical or confusing to assert that 6/8 has 6 beats? 😀

@pe-ro
Copy link
Contributor

pe-ro commented Apr 26, 2017

Some example markup using my conception of the new regime--

A whole-measure rest in 11/8:

<mRest tstamp="1" qstamp="1" dur="1 4 8" dots.vis="1"/>

A dotted quarter note:

<note tstamp="1" dur="4 8"/>

The same dotted quarter note captured by a hand-coder:

<note tstamp="1" dur.vis="4" dots.vis="1"/>

The same note with both sets of attributes:

<note tstamp="1" qstamp="1" dur="4 8" dur.vis="4" dots.vis="1"/>
  • @tstamp indicates the starting point in terms of the time signature
  • @qstamp records a non time signature based starting point
  • @dur holds the duration as a set of values to be added together; dotted values aren't allowed
  • @dots is renamed to @dots.vis and is an indication of how many dots actually appear; it no longer plays any role in determining the logical or gestural/performed duration.
  • @dur.ges is untouched by this proposal but may be modified in the future.

It would be useful to also add @dur.vis to capture the written duration when it differs from the so-called "logical" duration. In this example, @dur.vis could be set to 1 to represent a whole-note rest. Using @tstamp, @dur.vis, and @dots.vis, hand coders can continue in much the same way they have before. One advantage of the change is that it makes a clearer separation between the logical and visual realms.

As @craigsapp suggests, Schematron can be added to disallow (or at least warn against) the simultaneous use of @tstamp and @qstamp.

@craigsapp
Copy link
Member

We've discussed this before and I don't think we're going to convince each other, but I see no inconsistency in how MEI deals with @tstamp. If 2/2 has 2 beats, 3/4 has 3 beats, and 5/8 has 5 beats, why is it radical or confusing to assert that 6/8 has 6 beats? 😀

Yes, you will never move me from my current musician-based viewpoint: 6/8 is a compound meter with two beats. This time signature comes from the decay of mensural music, representing music which would have been notated with C-Dot in mensural music: the breve (measure) is divided into two semi-breves [beats], and the semi-breve [beat] is divided into three minims [sub-beats]. Ideally this should have been converted to 2/4. (two beats, where each beat is a dotted quarter), but instead it was converted into 6/8 which was originally hard-wired to mean C-Dot (probably because 17th-century musicians were also computer programmers and they did not want to use the dot). But over time, 6/8 was used for cases where there are actually 6 beats in the measure, such as slow middle movements in sonatas. So CMN time signature are ambiguous: traditionally compound meters such as 6/8 can also be used as simple meters.

@tstamps are a purely simple-meter viewpoint of time-signatures (which is one of my objections to them, but that is not the main objection). I would make an analogy to the arguments about using 4. as a duration: the . confuses programmers who think it is a decimal point rather than an augmentation dot. For musicians, the same thing occurs when you call an eighth note a beat in 6/8. Luckily you did not call @tstamp @beat or @bstamp, because then I would be complaining a lot more. But I sometimes complain about @tstamp as well because as explained above there is score time which is symbolic and real time which is physical. Scores are written in score time and performers convert these into real-time. The conversion is not linear since performers will add phrasing, rits, accels., and agogic accents. These two are conflated in music all of the time. Usually "time" has a primary definition of being physical time, so the label @tstamp is ambiguous when used to indicate score time, particularly to a novice MEI user as to whether or not it refers to physical time or score time.

But my complaint is more that beats have variable widths in different meters rather than about what is called the beat in a particular time signature. We both agree that 2/2 has a beat every half note and 5/4 has a quarter note beat and 3/8 has an eighth note beat. But even these that we agree on have computational complexity built into them due to their dependency on the need to reference a time-signature. The problem with computational processing is illustrated in the above example where the time signature of a measure is changed (or the measure is extracted out of context of the meter). When the beat width changes, then all @tstamps in measures belonging to the old time signature have to be changed. For manual encoding of a fixed score, this will not happen too often. But for a score editing program, this could happen more often.

And there is still the case of extracting a musical excerpt from a score. How should that be handled? For example, if someone wanted to extract a measure from an MEI score to use as a musical example in a paper analyzing the piece, the meter would somehow have to be included in the extraction. That means it would have to be found during the extraction process. When it is included in the musical excerpt, suppose that the author of the paper does not want the time signature shown (typically it is not shown for a musical excerpt, as the music is not for performance and it can mostly be inferred from the duration of the measure and the beaming patterns). Is there a way to make the time signature invisible? With @qstamps (or @estamps for eighth-notes, or @wstamps for whole-notes, etc.), it does not matter what the time signature is, so when extracting the measure you do not need to search for the prevailing time signature to include in the excerpt so that @tstamps remain valid.

@craigsapp
Copy link
Member

A whole-measure rest in 11/8:

<mRest tstamp="1" qstamp="1" dur="1 4 8" dots.vis="1"/>

I am presuming that you mean:

<mRest tstamp="1" qstamp="1" dur="1 4 8" dots.vis="0"/>

As dots on whole-measure rests got this thread started :-)

@pe-ro
Copy link
Contributor

pe-ro commented Apr 26, 2017

I am presuming that you mean:

Well, yes and no. I wasn't trying to be entirely accurate, just trying to illustrate that the number of dots displayed has nothing to do with duration.

@pe-ro
Copy link
Contributor

pe-ro commented Apr 26, 2017

Or can have nothing to do with duration if we adopt this new approach.

@craigsapp
Copy link
Member

Or can have nothing to do with duration if we adopt this new approach.

Yes, being able to split visual dots from logical dots will be useful. One application is that it more or less makes it possible to print mensural music with a CMN typesetting program (i.e., augmentation dots are usually dropped in mensural music).

@pe-ro pe-ro changed the title dots missing on mRest @dots missing on mRest Apr 27, 2017
@craigsapp
Copy link
Member

What about adding optional units to @tstamp? Without units it behaves as currently. @qstamp would be equivalent to @tstamp with a unit of "q", such as @tstamp="3q". There could also be units of "e" for eighth notes, h for half, w for whole, as desired. Perhaps even dq meaning dotted quarter note units.

@pe-ro
Copy link
Contributor

pe-ro commented Apr 28, 2017

Sounds like a reasonable proposal, at least something we should discuss, but anything having to do with revision of @dur, @tstamp, and such won't make it into the next release.

@pe-ro
Copy link
Contributor

pe-ro commented Apr 28, 2017

Here's where I got to in the ODD before placing #429 on hold --

  <!-- @dots missing on mRest, issue #429 -->
  <!-- Remove data.DURATION.additive; it's only used by att.duration.additive/@dur -->
  <macroSpec ident="data.DURATION.additive" module="MEI" type="dt" mode="delete"/>
  <!-- Revise data type of att.duration.additive/@dur; use list of data.DURATION values -->
  <classSpec ident="att.duration.additive" module="MEI.shared" type="atts" mode="replace">
    <desc>Attributes that permit total duration to be represented by multiple values.</desc>
    <attList>
      <attDef ident="dur" usage="opt">
        <desc>Records duration using optionally dotted, relative durational values provided by the
          data.DURATION datatype. Multiple space-separated values that add up to the total duration
          may be used. When dotted values are present, the dots attribute must be ignored.</desc>
        <datatype maxOccurs="unbounded">
          <rng:ref name="data.DURATION"/>
        </datatype>
        <!--<constraintSpec ident="ignore_dots_attribute" scheme="isoschematron">
                <constraint>
                  <sch:rule context="mei:*[contains(@dur, '.')]">
                    <sch:assert test="not(@dots)">An element with a dur attribute that contains
                      dotted values must not have a dots attribute.</sch:assert>
                  </sch:rule>
                </constraint>
              </constraintSpec>-->
      </attDef>
    </attList>
  </classSpec>
  <!-- Revise duration on control events -->
  <classSpec ident="att.annot.log" module="MEI.shared" type="atts" mode="replace">
    <desc>Logical domain attributes for annot. Values for the type attribute can be taken from any
      convenient typology of annotation suitable to the work in hand; e.g. annotation, gloss,
      citation, digression, preliminary, temporary, etc.</desc>
    <!-- Some attributes defined in att.controlEvent (att.timestamp.logical, att.timestamp.gestural,
           att.staffIdent, and att.layerIdent) are provided here directly instead of making annot a 
           member of att.controlEvent. -->
    <classes>
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.layerIdent"/>
      <memberOf key="att.staffIdent"/>
      <memberOf key="att.startEndId"/>
      <memberOf key="att.timestamp.logical"/>
      <memberOf key="att.timestamp.gestural"/>
      <memberOf key="att.timestamp2.logical"/>
    </classes>
  </classSpec>
  <classSpec ident="att.beamSpan.log" module="MEI.cmn" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.controlEvent"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.beamedWith"/>
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.startEndId"/>
      <memberOf key="att.timestamp2.logical"/>
    </classes>
  </classSpec>
  <classSpec ident="att.bend.log" module="MEI.cmn" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.controlEvent"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.startEndId"/>
      <memberOf key="att.timestamp2.logical"/>
    </classes>
  </classSpec>
  <classSpec ident="att.dir.log" module="MEI.shared" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.controlEvent"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.startEndId"/>
      <memberOf key="att.timestamp2.logical"/>
    </classes>
  </classSpec>
  <classSpec ident="att.dynam.log" module="MEI.shared" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.controlEvent"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.startEndId"/>
      <memberOf key="att.timestamp2.logical"/>
    </classes>
  </classSpec>
  <classSpec ident="att.f.log" module="MEI.shared" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.controlEvent"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.startEndId"/>
      <memberOf key="att.timestamp2.logical"/>
    </classes>
  </classSpec>
  <classSpec ident="att.fing.log" module="MEI.fingering" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.controlEvent"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.startEndId"/>
      <memberOf key="att.timestamp2.logical"/>
    </classes>
  </classSpec>
  <classSpec ident="att.fingGrp.log" module="MEI.fingering" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.controlEvent"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.startEndId"/>
      <memberOf key="att.timestamp2.logical"/>
    </classes>
    <attList>
      <attDef ident="form" usage="opt">
        <valList type="closed">
          <valItem ident="alter">
            <desc>alternation of fingers.</desc>
          </valItem>
          <valItem ident="combi">
            <desc>combination of fingers.</desc>
          </valItem>
          <valItem ident="subst">
            <desc>substitution of fingers.</desc>
          </valItem>
        </valList>
      </attDef>
    </attList>
  </classSpec>
  <classSpec ident="att.gliss.log" module="MEI.cmn" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.controlEvent"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.startEndId"/>
      <memberOf key="att.timestamp2.logical"/>
    </classes>
  </classSpec>
  <classSpec ident="att.hairpin.log" module="MEI.cmn" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.controlEvent"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.startEndId"/>
      <memberOf key="att.timestamp2.logical"/>
    </classes>
    <attList>
      <attDef ident="form" usage="req">
        <desc>Captures the visual rendition and function of the hairpin; that is, whether it
          indicates an increase or a decrease in volume.</desc>
        <valList type="closed">
          <valItem ident="cres">
            <desc>Crescendo; i.e., louder.</desc>
          </valItem>
          <valItem ident="dim">
            <desc>Diminuendo; i.e., softer.</desc>
          </valItem>
        </valList>
      </attDef>
      <attDef ident="niente" usage="opt">
        <desc>Indicates that the hairpin starts from or ends in silence. Often rendered as a small
          circle attached to the closed end of the hairpin. See Gould, p. 108.</desc>
        <datatype>
          <rng:ref name="data.BOOLEAN"/>
        </datatype>
      </attDef>
    </attList>
  </classSpec>
  <classSpec ident="att.harm.log" module="MEI.harmony" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.controlEvent"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.startEndId"/>
      <memberOf key="att.timestamp2.logical"/>
    </classes>
    <attList>
      <attDef ident="chordref" usage="opt">
        <desc>Contains a reference to a <gi scheme="MEI">chordDef</gi> element elsewhere in the
          document.</desc>
        <datatype>
          <rng:ref name="data.URI"/>
        </datatype>
        <constraintSpec ident="check_chordrefTarget" scheme="isoschematron">
          <constraint>
            <sch:rule context="@chordref">
              <sch:assert role="warning" test="not(normalize-space(.) eq '')">@chordref attribute
                should have content.</sch:assert>
              <sch:assert role="warning"
                test="every $i in tokenize(., '\s+') satisfies substring($i,2)=//mei:chordDef/@xml:id"
                >The value in @chordref should correspond to the @xml:id attribute of a chordDef
                element.</sch:assert>
            </sch:rule>
          </constraint>
        </constraintSpec>
      </attDef>
    </attList>
  </classSpec>
  <classSpec ident="att.ligatureSpan.log" module="MEI.cmn" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.controlEvent"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.startEndId"/>
      <memberOf key="att.timestamp2.logical"/>
    </classes>
  </classSpec>
  <classSpec ident="att.line.log" module="MEI.shared" type="atts" mode="replace">
    <desc>Attributes for describing the logical behaviour of a line.</desc>
    <classes>
      <memberOf key="att.controlEvent"/>
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.startEndId"/>
      <memberOf key="att.timestamp2.logical"/>
    </classes>
  </classSpec>
  <classSpec ident="att.octave.log" module="MEI.cmn" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.controlEvent"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.octaveDisplacement"/>
      <memberOf key="att.startEndId"/>
      <memberOf key="att.timestamp2.logical"/>
    </classes>
    <attList>
      <attDef ident="coll" usage="opt">
        <desc>Indicates whether the octave displacement should be performed simultaneously with the
          written notes, i.e., "coll' ottava". Unlike other octave signs which are indicated by
          broken lines, coll' ottava typically uses an unbroken line or a series of longer broken
          lines, ending with a short vertical stroke. See Read, p. 47-48.</desc>
        <valList type="closed">
          <valItem ident="coll">
            <desc>Coll' ottava (with the octave).</desc>
          </valItem>
        </valList>
      </attDef>
    </attList>
  </classSpec>
  <classSpec ident="att.ornam.log" module="MEI.shared" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.controlEvent"/>
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.ornamentAccid"/>
      <memberOf key="att.startEndId"/>
      <memberOf key="att.timestamp2.logical"/>
    </classes>
  </classSpec>
  <classSpec ident="att.phrase.log" module="MEI.shared" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.controlEvent"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.startEndId"/>
      <memberOf key="att.timestamp2.logical"/>
    </classes>
  </classSpec>
  <classSpec ident="att.slur.log" module="MEI.cmn" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.controlEvent"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.startEndId"/>
      <memberOf key="att.timestamp2.logical"/>
    </classes>
  </classSpec>
  <classSpec ident="att.trill.log" module="MEI.cmnOrnaments" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.controlEvent"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.ornamentAccid"/>
      <memberOf key="att.startEndId"/>
      <memberOf key="att.timestamp2.logical"/>
    </classes>
  </classSpec>
  <classSpec ident="att.tuplet.log" module="MEI.cmn" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.event"/>
      <memberOf key="att.beamedWith"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.duration.ratio"/>
      <memberOf key="att.startEndId"/>
    </classes>
  </classSpec>
  <classSpec ident="att.tupletSpan.log" module="MEI.cmn" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.controlEvent"/>
      <memberOf key="att.beamedWith"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.duration.ratio"/>
      <memberOf key="att.startEndId"/>
      <memberOf key="att.timestamp2.logical"/>
    </classes>
  </classSpec>
  <!-- Rename @dots to @dots.vis -->
  <classSpec ident="att.augmentDots" module="MEI.shared" type="atts" mode="replace">
    <desc>Attributes that record the number of dots of augmentation.</desc>
    <attList>
      <attDef ident="dots.vis" usage="opt">
        <desc>Records the number of augmentation dots displayed.</desc>
        <datatype>
          <rng:ref name="data.AUGMENTDOT"/>
        </datatype>
        <!--<constraintSpec ident="dots_attribute_requires_dur" scheme="isoschematron">
                <constraint>
                  <sch:rule context="mei:*[@dots]">
                    <sch:assert test="@dur">An element with a dots attribute must also have a dur
                      attribute.</sch:assert>
                  </sch:rule>
                </constraint>
              </constraintSpec>-->
      </attDef>
    </attList>
    <remarks>
      <p>The <att>dots.vis</att> attribute records the number of augmentation dots displayed.</p>
    </remarks>
    <!--<remarks>
            <p>The <att>dots</att> attribute records the number of augmentation dots necessary to
              represent a non-power-of-two duration. This is usually, but not always, the number of
              dots displayed. For example, a note with this attribute will result in displayed dots,
              while a glissando will not.</p>
          </remarks>-->
  </classSpec>
  <!-- Revise duration on whole-measure events -->
  <classSpec ident="att.mRest.log" module="MEI.cmn" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <!--<memberOf key="att.augmentDots"/>-->
      <!--<memberOf key="att.duration.logical"/>-->
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.event"/>
    </classes>
  </classSpec>
  <classSpec ident="att.mSpace.log" module="MEI.cmn" type="atts" mode="replace">
    <desc>Logical domain attributes in the CMN repertoire.</desc>
    <classes>
      <!--<memberOf key="att.augmentDots"/>-->
      <!--<memberOf key="att.duration.logical"/>-->
      <memberOf key="att.duration.additive"/>
      <memberOf key="att.event"/>
    </classes>
  </classSpec>
  <!-- Revise duration on other events -->
  <classSpec ident="att.ambNote.log" module="MEI.shared" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.accidental"/>
      <memberOf key="att.coloration"/>
      <memberOf key="att.duration.additive"/>
      <!--<memberOf key="att.duration.logical"/>-->
      <memberOf key="att.pitched"/>
    </classes>
  </classSpec>
  <classSpec ident="att.bTrem.log" module="MEI.cmn" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.event"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <!--<memberOf key="att.duration.logical"/>-->
      <memberOf key="att.numbered"/>
    </classes>
    <attList>
      <attDef ident="form" usage="opt">
        <desc>Indicates whether the tremolo is measured or unmeasured.</desc>
        <valList type="closed">
          <valItem ident="meas">
            <desc>Measured tremolo.</desc>
          </valItem>
          <valItem ident="unmeas">
            <desc>Unmeasured tremolo.</desc>
          </valItem>
        </valList>
      </attDef>
    </attList>
  </classSpec>
  <classSpec ident="att.chord.log" module="MEI.shared" type="atts" mode="replace">
    <desc>Logical domain attributes for chord. The artic, dots, and dur attributes encode the
      written articulations, augmentation dots, and duration values. The beam, fermata, lv, slur,
      syl, tie, and tuplet attributes may be used to indicate the attachment of these things to this
      chord. If visual information about these things needs to be recorded, then either the elements
      corresponding to these attributes or the attributes available in the att.vis.chord class
      should be employed.</desc>
    <classes>
      <memberOf key="att.articulation"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.chord.log.cmn"/>
      <memberOf key="att.duration.additive"/>
      <!--<memberOf key="att.duration.logical"/>-->
      <memberOf key="att.event"/>
      <memberOf key="att.sylText"/>
    </classes>
  </classSpec>
  <classSpec ident="att.chord.vis" module="MEI.visual" type="atts" mode="replace">
    <desc>Visual domain attributes for chord.</desc>
    <classes>
      <memberOf key="att.altSym"/>
      <memberOf key="att.augmentDots"/>
      <memberOf key="att.color"/>
      <memberOf key="att.enclosingChars"/>
      <memberOf key="att.extSym"/>
      <memberOf key="att.stems"/>
      <memberOf key="att.typography"/>
      <memberOf key="att.visibility"/>
      <memberOf key="att.visualOffset.ho"/>
      <memberOf key="att.visualOffset.to"/>
      <memberOf key="att.xy"/>
      <memberOf key="att.chord.vis.cmn"/>
    </classes>
    <attList>
      <attDef ident="cluster" usage="opt">
        <desc>Indicates a single, alternative note head should be displayed instead of individual
          note heads. The highest and lowest notes of the chord usually indicate the upper and lower
          boundaries of the cluster note head.</desc>
        <datatype>
          <rng:ref name="data.CLUSTER"/>
        </datatype>
      </attDef>
    </attList>
  </classSpec>
  <classSpec ident="att.fTrem.log" module="MEI.cmn" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.event"/>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <!--<memberOf key="att.duration.logical"/>-->
    </classes>
    <attList>
      <attDef ident="form" usage="opt">
        <desc>Describes the style of the tremolo.</desc>
        <valList type="closed">
          <valItem ident="meas">
            <desc>Measured tremolo.</desc>
          </valItem>
          <valItem ident="unmeas">
            <desc>Unmeasured tremolo.</desc>
          </valItem>
        </valList>
      </attDef>
    </attList>
  </classSpec>
  <classSpec ident="att.fTrem.vis" module="MEI.visual" type="atts" mode="replace">
    <desc>Visual domain attributes.</desc>
    <classes>
      <memberOf key="att.augmentDots"/>
    </classes>
    <attList>
      <attDef ident="beams" usage="opt">
        <desc>Indicates the number of beams present.</desc>
        <datatype>
          <rng:data type="positiveInteger">
            <rng:param name="minInclusive">1</rng:param>
            <rng:param name="maxInclusive">6</rng:param>
          </rng:data>
        </datatype>
      </attDef>
      <attDef ident="beams.float" usage="opt">
        <desc>Captures the number of "floating" beams, i.e., those not attached to stems.</desc>
        <datatype>
          <rng:data type="nonNegativeInteger"/>
        </datatype>
        <constraintSpec ident="check_beams.floating" scheme="isoschematron">
          <constraint>
            <sch:rule context="mei:fTrem[@beams and @beams.float]">
              <sch:assert test="@beams.float &lt;= @beams">The number of floating beams must be less
                than or equal to the total number of beams.</sch:assert>
            </sch:rule>
          </constraint>
        </constraintSpec>
      </attDef>
      <attDef ident="float.gap" usage="opt">
        <desc>Records the amount of separation between floating beams and stems.</desc>
        <datatype>
          <rng:ref name="data.MEASUREMENTABS"/>
        </datatype>
      </attDef>
    </attList>
  </classSpec>
  <classSpec ident="att.halfmRpt.log" module="MEI.cmn" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <memberOf key="att.event"/>
      <memberOf key="att.duration.additive"/>
      <!--<memberOf key="att.duration.logical"/>-->
    </classes>
  </classSpec>
  <classSpec ident="att.halfmRpt.vis" module="MEI.visual" type="atts" mode="replace">
    <desc>Visual domain attributes.</desc>
    <classes>
      <memberOf key="att.altSym"/>
      <memberOf key="att.augmentDots"/>
      <memberOf key="att.color"/>
      <memberOf key="att.expandable"/>
      <memberOf key="att.extSym"/>
      <memberOf key="att.typography"/>
      <memberOf key="att.visualOffset"/>
    </classes>
  </classSpec>
  <classSpec ident="att.note.log" module="MEI.shared" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.coloration"/>
      <memberOf key="att.duration.additive"/>
      <!--<memberOf key="att.duration.logical"/>-->
      <memberOf key="att.event"/>
      <memberOf key="att.note.log.cmn"/>
      <memberOf key="att.note.log.mensural"/>
      <memberOf key="att.pitched"/>
    </classes>
  </classSpec>
  <classSpec ident="att.note.vis" module="MEI.visual" type="atts" mode="replace">
    <desc>Visual domain attributes.</desc>
    <classes>
      <memberOf key="att.altSym"/>
      <memberOf key="att.augmentDots"/>
      <memberOf key="att.color"/>
      <memberOf key="att.enclosingChars"/>
      <memberOf key="att.extSym"/>
      <memberOf key="att.noteHeads"/>
      <memberOf key="att.staffLoc"/>
      <memberOf key="att.stems"/>
      <memberOf key="att.typography"/>
      <memberOf key="att.visibility"/>
      <memberOf key="att.visualOffset.ho"/>
      <memberOf key="att.visualOffset.to"/>
      <memberOf key="att.xy"/>
      <memberOf key="att.note.vis.cmn"/>
    </classes>
  </classSpec>
  <classSpec ident="att.rest.log" module="MEI.shared" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <!--<memberOf key="att.duration.logical"/>-->
      <memberOf key="att.event"/>
      <memberOf key="att.rest.log.cmn"/>
    </classes>
  </classSpec>
  <classSpec ident="att.rest.vis" module="MEI.visual" type="atts" mode="replace">
    <desc>Visual domain attributes.</desc>
    <classes>
      <memberOf key="att.altSym"/>
      <memberOf key="att.augmentDots"/>
      <memberOf key="att.color"/>
      <memberOf key="att.enclosingChars"/>
      <memberOf key="att.rest.vis.cmn"/>
      <memberOf key="att.rest.vis.mensural"/>
      <memberOf key="att.staffLoc"/>
      <memberOf key="att.staffLoc.pitched"/>
      <memberOf key="att.typography"/>
      <memberOf key="att.visualOffset"/>
      <memberOf key="att.xy"/>
    </classes>
  </classSpec>
  <classSpec ident="att.space.log" module="MEI.shared" type="atts" mode="replace">
    <desc>Logical domain attributes.</desc>
    <classes>
      <!--<memberOf key="att.augmentDots"/>-->
      <memberOf key="att.duration.additive"/>
      <!--<memberOf key="att.duration.logical"/>-->
      <memberOf key="att.event"/>
    </classes>
  </classSpec>

The element-by-element approach is probably overkill. That is, it might be possible to accomplish the same thing by altering att.event and att.controlEvent. Still, some "shifting" might be required.

In any case, at this point we can fix the issue with regard to <mRest> and <mSpace>; that is, remove @dots, but anything beyond that too hot to handle, it seems.

@craigsapp
Copy link
Member

When the duration is "irrational", as is sometimes the case with tuplets, multiple space-separated values that add up to the total duration may be used. When dotted values are present, the dots attribute must be ignored.

I would avoid using the word irrational since musical rhythms are mathematically called rational numbers (but that does not stop musicians from using the term irrational for rational numbers :-). An irrational rhythm would be pi-uplets or the square-root-of-three-uplets.

Here is some music with irrational durations:

http://www.finalemusic.com/blog/pi-day-finale-font-update
screen shot 2017-05-04 at 7 29 04 am

@pe-ro pe-ro closed this as completed in 268d802 May 8, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants