w3c / mnx

Music Notation CG next-generation music markup proposal.
179 stars 18 forks source link

How to group parts? #185

Closed cecilios closed 2 years ago

cecilios commented 4 years ago

I was looking at the new section for Parts to the MNX-Common by Example page and it raised the question of how to group parts (the MusicXML part-group elements). I've been looking in the specification and unless I've missed something, I have not found any reference to this.

I would appreciate some comments on this or what ideas are you considering for representing groups. Thank you.

In my oppinion grouping parts is a very important organizational element and this could affect current high level MNX structure, and should be addressed sooner than details of the specification.

notator commented 4 years ago

Thanks to the co-chair for taking this proposal seriously.

@adrianholovaty I'm not sure if this can all go in one pull request. The following two items should, I think, be dealt with immediately:

The following text in §4.1. Parts and staves needs to be rewritten:

A score consists of multiple parts. Each part is a grouping of related musical material that relates to a single performer or set of performers. It has the same temporal extent as the score overall, but presents a slice of content that is relevant to a single instrument or a group of related instruments.

Suggestion:

§6.1.9 The part Element contains the sentence

The part element represents a set of measures which describe a single part within the score.

The second half of that sentence is redundant (and rather irritating). It should be omitted. Simply replace the sentence by:

I think we need a new issue about reformulating §6.2.2 The sequence Element. Note that:


Would you mind duplicating the relevant parts of your proposal into [issues #188, #34, #57]

Not at all, I'm working on it! I see that @clnoel has already done #57 very well. Many thanks! Note that #121 is also affected.

notator commented 3 years ago

[Edit 04.08.2021: updated the file links (again)]

Starting from the above proposal, I have now created a fully worked, concrete example, demonstrating how

As always, this posting should be regarded as the basis for further discussion. Constructive comments would be very welcome. Working on the details led to some refinements, but the basic ideas have not changed.

The examples in MNX by example need to be updated to take account of these new capabilities. The changes are small, and depend on the relation between parts and staves in each example. See below.

The new partGroups.mnx example defines the following 2-system full-score page:

partGroupsSmall

Note that the flutes are grouped differently in the two systems. The complete .mnx file can be viewed at https://github.com/notator/mnx/blob/main_ji/_ingram/mnx-examples/common1900/graphicsOnly/parts-voices-staves/partGroups.mnx

Grouping Overview

  1. At the lowest level of grouping, there are three basic elements that relate parts to staves:

    • <partStaff>: a staff containing a single part
    • <partGroupStaff>: a staff containing more than one part
    • <partStaves>: more than one staff for a single part (e.g. a keyboard)

    and an element that groups the above elements and instances of itself (this is a recursive element)

    • <staffGroup>
  2. At the next level, the above, low level elements can be grouped into different <systemLayout> definitions, each of which can be used to define one or more <system> elements. A <system> contains a particular, closed sequence of measures formatted according to a particular <systemLayout>.
  3. At the next level, <system>s can be grouped into <page> definitions
  4. At the top level, one or more <score> elements can be defined. each of which can contain one of the following:
    • <pages> -- a sequence of pages
    • <page> -- a single page (containing a sequence of <system> definitions)
    • <system> -- a single system
    • <partStaff> -- a single staff containing a single part
    • <partGroupStaff>: a single staff containing more than one part
    • <partStaves>: more than one staff for a single part (e.g. a keyboard)

This means that the top level structure of a generalised MNX file has the following form:

<mnx>
    <global>...</global>
    <parts>...</parts>
    <systemLayouts>...</systemLayouts>
    <scores>...</scores>
</mnx>

As a design principle, I have always included sequences of more than one identical element in a container element, but the container element can be omitted if there is only one contained element. This enables better verification of instantiations by the schema. For example, if there is only one <part> in the file, it can be used directly instead of the <parts> element. Similarly for <systemLayouts>-<systemLayout>, <scores>-<score>, <pages>-<page> and <measures>-<measure>. Additionally, since a <score> element can contain a single instance of a low level part-grouping element directly, it is not always necessary to define a <systemLayout>. So the top level structure of many MNX by example examples reduces to:

<mnx>
    <global>...</global>
    <part>...</part>
    <score>...</score>
</mnx>

Naming

In order to enable group naming (for the names in the left columns in the above example), it was expedient to define an optional <global><instrumentTypes> element containing a list of <instrumentType> elements. This element, which defines the associated groupName, name and nameAbbreviation, can be omitted completely if parts are not named in the score. The <part><part-name> element has therefore been deleted in all the conforming .mnx files. If the part has a printed name of any kind, it is found via a reference to the part's <instrumentType>. If the part is a member of a group of similar instruments, its partNumberInGroup is defined. <part id="fl1" instrumentType="#flute" partNumberInGroup="1"> The names and part numbers are combined in different ways by the low level part grouping elements described above.

Changes to the MNX by example examples

Current versions of all my MNX examples can be found in the folders at https://github.com/notator/mnx/blob/main_ji/_ingram/mnx-examples/common1900/graphicsOnly These

Known issues:

I've tried to provide solutions to the issues that arose in the discussion with @clnoel after making my original proposal, but the following two still need to be addressed:

adrianholovaty commented 3 years ago

I've just synthesized @notator's proposal with other various feedback into a new proposal in the comment here: https://github.com/w3c/mnx/issues/57#issuecomment-891916447

notator commented 3 years ago

The current discussion in #245 has shown that the names "partStaff", "partGroupStaff" and "partStaves" in my original proposal are confusing, so l've decided to refactor them as follows:

Also, its difficult to see the wood for the trees in the original, complete example, so here it is again refactored and in reduced form:

<mnx>
    <global>
        <instrumentTypes>
            <instrumentType id="flute" groupName="Flutes" name="Flute" nameAbbrev="Fl." />
            <instrumentType id="oboe" groupName="Oboes" name="Oboe" nameAbbrev="Ob." />
            <instrumentType id="piano" groupName="Pianos" name="Piano" nameAbbrev="Piano" />
        </instrumentTypes>
        <measures>...</measures>
    </global>
    <parts>
        <part id="fl1" instrumentType="#flute" partNumberInGroup="1">...</part>
        <part id="fl2" instrumentType="#flute" partNumberInGroup="2">...</part>
        <part id="fl3" instrumentType="#flute" partNumberInGroup="3">...</part>
        <part id="ob1" instrumentType="#oboe" partNumberInGroup="1">...</part>
        <part id="ob2" instrumentType="#oboe" partNumberInGroup="2">...</part>
        <part id="piano" instrumentType="#piano">...</part>
    </parts>

    <systemLayouts>
        <systemLayout id="fullScoreSystemLayout1">
            <staffGroup staffGroupClass="Woodwind" bracket="straight" barline="true" >
                <staffGroup staffGroupClass="Flutes" bracket="curly" barline="true" displayGroupName="true" >
                    <sharedStaff parts="#fl1 #fl2" displayPartNumbers="true" />
                    <staff part="#fl3" displayPartNumber="true" />
                </staffGroup>
                <sharedStaff parts="#ob1 #ob2" displayGroupName="true" displayPartNumbers="true" />
            </staffGroup>
            <grandStaff part="#piano" nStaves="2" displayName="true"/>
        </systemLayout>

        <systemLayout id="fullScoreSystemLayout2">
            <staffGroup staffGroupClass="Woodwind" bracket="straight" barline="true" >
                <staffGroup bracket="curly" barline="true" displayNameAbbrev="true" >
                    <staff part="#fl1" displayPartNumber="true" />
                    <staff part="#fl2" displayPartNumber="true" />
                    <staff part="#fl3" displayPartNumber="true" />
                </staffGroup>
                <sharedStaff parts="#ob1 #ob2" displayNameAbbrev="true" displayPartNumbers="true" />
            </staffGroup>
            <grandStaff part="#piano" nStaves="2" displayNameAbbrev="true"/>
        </systemLayout>

        <!-- systemLayout-definitions for the flute 1 part booklet -->
        <systemLayout id="flute1PartSystem1Layout">
            <staff part="#fl1" displayName="true" displayPartNumber="true"/>
        </systemLayout>

        <systemLayout id="flute1PartDefaultSystemLayout">
            <staff part="#fl1" />
        </systemLayout>

        <!-- etc. for all the woodwind part "scores" (booklets) -->

        <!-- systemLayout-definitions for the piano part -->
        <systemLayout id="pianoSystem1Layout">
            <grandStaff part="#piano" nStaves="2" displayName="true"/>
        </systemLayout>

        <systemLayout id="pianoDefaultSystemLayout">
            <grandStaff part="#piano" nStaves="2" />
        </systemLayout>
    </systemLayouts>

    <!-- all the scores in this mnx file -->
    <scores>

        <score name="Full Score" relWidth="500" relHeight="707" relMargins="30">
            <pages>
                <page>
                    <system startMeasureNumber="1" systemLayout="#fullScoreSystemLayout1"/>
                    <system startMeasureNumber="4" systemLayout="#fullScoreSystemLayout2"/>
                </page>
            </pages>
        </score>

        <score name="Flute 1 part"  relWidth="500" relHeight="707" relMargins="30">
            <system startMeasureNumber="1" systemLayout="#flute1PartSystem1Layout"/>
            <!-- all 7 bars are printed in this one system -->
        </score>

        <!-- etc., all the woodwind part "scores" (booklets) -->

        <score name="Piano part"  relWidth="460" relHeight="552" relMargins="30">
            <page>
                <system startMeasureNumber="1" systemLayout="#pianoSystem1Layout"/>
                <system startMeasureNumber="5" systemLayout="#pianoDefaultSystemLayout"/>
            </page>
        </score>
    </scores>
</mnx>

Known Issues:

Apart from the issues mentioned in the original proposal, the following need to be addressed:

adrianholovaty commented 3 years ago

@notator Thanks for keeping that proposal up to date. But I do agree with @joeberkovitz's comment (link) — I don't see the need to have three separate elements to describe a staff.

Specifically, <staff>, <sharedStaff> and <grandStaff> could all just be <staff>, which contains data about which part(s) lie within. Much simpler and more elegant. The comment here contains the latest revision of this idea.

ahankinson commented 3 years ago

I originally wrote this response on the PR, but it felt out-of-place to respond there (and mucks up the review process), so I'll put it here. But it should be read as a response to the discussion there, as well as pertinent to this one. Specifically, it answers @notator's question about system breaks.


"System" (see note below on the specific meaning of this terminology) breaks are only needed when you reach the edge of a given width. In printed materials, this is set by the physical width of a page. In the digital environment this is not fixed, and varies with the size of the screen / viewport, as well as the zoom level and device viewing it. There are times when explicit system breaks are necessary, but most of the time they can be calculated automatically. So it is possible for a renderer to automatically extract and render individual parts given a full score -- this has been demonstrated with Verovio and other tools several times.

Back on the topic of this conversation: In MEI the system/staff/grouping/parts functionality is handled with the <staffDef>, <staffGrp>, and <scoreDef> elements, which define the settings of the different staffs and their groupings. If you want more control over how parts are explicitly encoded, the <part> element is also available, but it is usually possible to extract instrumental parts from the score using the *Def elements as the definitions of each part, and then using the attributes encoded in the *Def elements to traverse the DOM and select the appropriate instrumental content in the body of the encoding.

The behaviour and encoding of these are described in the MEI documentation, if you want some prior art to help guide this implementation, and you can see a fairly readable example of an orchestral piece. (Sorry, GitHub doesn't allow me to link directly to the scoreDef section...)

On terminology: MEI makes a distinction between a 'staff' (considered a single, unbroken line of music) and a 'system', which are "staffs" that are broken to fit a given width (even though in colloquial usage they are largely interchangeable terminology). MEI has the <sb /> element which is a milestone element that explicitly encodes a "system begin" (a.k.a, a system break, but placed at the beginning -- I won't go into the reasons why here, but this is by design). Renderers can either choose to keep or ignore explicit system begin markers, or insert their own dynamic system begins according to the current rendering environment.

It might be clearer to be similarly consistent with terminology here. It seems that <system-layout> could become <staff-layout>, since it seems that every child element is staff-something. This would also make compatibility with MEI easier later down the road.

notator commented 3 years ago

Thanks @ahankinson for this response to my https://github.com/w3c/mnx/pull/245#issuecomment-930428028. Yes you're right. Its not impossible for a renderer to extract and render a part from a full-score. Its just very difficult. Verovio might produce an acceptable result, but I don't think we can get away without human checking and manual tweaking yet: Are Verovio's system breaks always in the best places? Are staves containing multiple bars rest always spaced optimally? Are multiple bars rest correctly broken at rehearsal numbers? Do the page turns always happen in the best places? The situation may change with the advent of AI though. Sometime, someone ought to be able to train an AI to do the job by feeding it large numbers of existing orchestra scores and parts (that have been manually produced by human experts).

On terminology (also applies to #245): I think this is a bit of a red-herring . Its far more important to get the structures right than to give them their ultimate names. Providing the names are not actively confusing, they can easily be changed further down the line. As the Germans might say, "Take care of the structures, and the names will take care of themselves.".

notator commented 3 years ago

Tracking Known Issues:

clnoel commented 3 years ago

How about this: A part knows how many staves it needs to display properly. If a part has staves specified in its part description (as more than 1 staff), then a specification of

<staff parts="piano" labelref="short-name" symbol="brace"/>

will produce a grand staff with that many staves by default, including the usual grand-staff barlines. Then we add a yes/no attribute (default no) called suppress-if-empty that is valid only for parts with multiple staves that suppress a particular stave if it has no music specified (or only rests) for a given system.

I feel like this hits the necessary requirements for grand staff display, but would, of course, welcome examples in which it would not work or would break things.


On the other side, representing how to group parts onto one stave, I have an excellent example piece to try to puzzle out how to encode:

image

The upper staff in this TTBB sample piece (Prayer of the Children, by Kurt Bestor) starts with chorded notes, changes to up/down stems with the stems sharing a notehead because the notes are in unison, changes to standard up/down due to rhythmic differences between the parts, goes back to chorded notes, goes back to up/down, then actually hits "unison" rather than up/down unison for a bit. While this is an "extreme" example in that you get so many changes in just three systems, it's definitely not unusual to get things like this in choral pieces.

I feel like proper MNX parts for this would encode the Tenor 1 and Tenor 2 line as separate parts, since that's the way the performers would break out and need to practice. On top of that, what if someone wanted to lay this out differently, perhaps with four choral parts and a combined "piano" part that was just for rehearsal? That should also be creatable in the same MNX document, I think.

So, as I was writing the below, I realized that all the above examples actually shook out into fewer cases than I thought.

<system-layout id="chorded">
    <staff-group symbol="bracket">
        <staff part="t1 t2" stem="chord chord"/>
        <staff part="b1 b2" stem="chord chord"/>
    </staff-group>
</system-layout>

<system-layout id="split>
    <staff-group symbol="bracket">
        <staff part="t1 t2" stem="up down"/>
        <staff part="b1 b2" stem="chord chord"/>
    </staff-group>
</system-layout>

<system-layout id="unison">
    <staff-group symbol="bracket">
        <staff part="t1 t2" stem="chord chord" label="unis."/>
        <staff part="b1 b2" stem="chord chord"/>
    </staff-group>
</system-layout>

.....

<score name="Condensed">
...
   <page>
...
      <system measure="11" layout="chorded">
          <mid-system-layout location="12:4/5" layout="split"/>
      </system>
      <system measure="13" layout="split">
          <mid-system-layout location="14:0" layout="chorded"/>
      </system>
      <system measure="15" layout="split">
          <mid-system-layout location="15:3/4" layout="chorded"/>
          <mid-system-layout location="16:0" layout="unison"/>
          <mid-system-layout location="16:3/4" layout="split"/>
      </system>
...
   </page>
</score>

I think this works out. We can expand the "stem" types to include chord-up and chord-down if there are more than two parts on a staff, and to include "cue" for small notes, maybe?

--Christina

notator commented 3 years ago

@clnoel My current position on <grand-staff> elements can be found in https://github.com/w3c/mnx/pull/245#issuecomment-943290014. Contrary to what you said above, I don't think that <part> elements define a constant number of staves on which the part has to be displayed in all systems. If a <part> that needs a maximum of three staves has nothing in two of them for the width of a particular system in a full-score, then it could be treated as an ordinary 1-staff part for grouping purposes during that system, possibly saving valuable vertical space. Maybe something like this:

    <staff-layout label="Piano">
        <part-layout part="piano" staff-number="1" />
    </staff-layout>

or even this:

    <staff-layout>
        <part-layout part="fl1" label="Fl. 1" stemdir="up" />
        <part-layout part="piano" staff-number="1" label="Piano" stemdir="down" />
    </staff-layout>

Possibly, @adrianholovaty's open-source MNX semantic validator could warn if there are events in piano staves that are being left out! :-)


Changing layout mid-system

Thanks very much for the music example! I think it ought to end up in the MNX documentation. The <page> definition at the bottom of your code is really great! Its also in line with @joeberkovitz' comment about the solution lying in that direction. Bravo! This solution is much simpler than I originally imagined it would be.

@adrianholovaty's https://github.com/w3c/mnx/pull/245#issuecomment-942222471 explains that <staff> has been renamed <staff-layout> since you wrote the above code, and that it now contains <part-layout> elements. So, while the intent of your three <system-layout> definitions is perfectly clear, they need to be changed internally. The recent changes also affect the way you define chords. Below is how I think they might now be done. Alternative suggestions very welcome!

I have three small quibbles:

  1. I don't think the label attribute can simply be part of the unison <system-layout>. If you put it there without any qualifier, it will be printed every time the <system-layout> is used -- even when its used as a continuation of the same layout at the beginning of a <system>. The issue of exactly how to code texts like that can probably be left until after we've decided how parts should be grouped (i.e. which containers we need).
  2. I'd prefer to rename <mid-system-layout> as <system-layout>. Its obvious from the code, that it changes the layout of the current <system>, and the layout it references is a <system-layout>.
  3. I think the location attributes for <system> and <mid-system-layout> should have the same name in both cases. Both should be "location", for consistency in MNX. That was probably my mistake originally.

Chordal and unison passages

We need a way to describe separate <part> elements being grouped on the same stem. For example if, in some score, flutes 1 and 2 share the same rhythm, and flutes 3 to 6 share the same rhythm, then they could be grouped into two voices (each of which is notated in chords) on the same staff. Maybe something like this:

    <staff-layout>
        <voice-layout label = "Fl. 1,2" stemdir="up" minimum-noteheads="yes">
            <part-layout part="fl1" />
            <part-layout part="fl2" />
        </voice-layout>
        <voice-layout label = "Fl. 3,4,5,6" stemdir="down" minimum-noteheads="yes">
            <part-layout part="fl3" />
            <part-layout part="fl4" />
            <part-layout part="fl5" />
            <part-layout part="fl6" />
        </voice-layout>
    </staff-layout>

If minimum-noteheads="yes" and all the flutes in the voice are playing in unison, then there would only be one notehead in the chord. If minimum-noteheads="no", then each part would get its own notehead.

Could passages played in unison by more than one <part> somehow be defined just once inside the <part> definitions? If Fl. 1 and 2 play the same thing, and Fl. 3,4,5,6 play the same thing, the code might then just look something like this:

    <staff-layout>
        <voice-layout label="Fl. 1,2" stemdir="up" part="fl1" />
        <voice-layout label="Fl. 3,4,5,6" stemdir="down" part="fl3"/>
    </staff-layout>

@adrianholovaty's open-source MNX semantic validator might come in handy here too! :-)


Going back to your code example: Note that <system-layout> elements could be put together very flexibly/efficiently if they referenced pre-defined <group-layout>, <staff-layout> and <grand-staff-layout> elements by ID. Defining new <system-layout> elements that differ only slightly from existing ones, would then be no problem. For example, using the new <staff-layout> syntax, and the <voice-layout> element I'm imagining above for chords, your <system-layout id="chorded"> definition could be rewritten like this:

<staff-layout label="T 1, 2" id="chordedtenorsstaff">
    <voice-layout>
        <part-layout part="t1" />
        <part-layout part="t2" />
    </voice-layout>
</staff-layout>

<staff-layout label="B 1, 2" id="chordedbassesstaff">
    <voice-layout>
        <part-layout part="b1" />
        <part-layout part="b2" />
    </voice-layout>
</staff-layout>

<system-layout id="chorded">
    <group-layout symbol="bracket">
        <staff-layout layout="chordedtenorsstaff" />
        <staff-layout layout="chordedbassesstaff"  />
    </group-layout>
</system-layout>
notator commented 3 years ago

Apologies for this posting being unusually long, but it leads to what I think is a complete description of all the containers MNX 1.0 needs for grouping parts. Once we agree on the containers and how they nest, this issue can be closed, #245 can be pushed (if/when it conforms), and any unsolved issues that have been raised here can be resolved in other threads. Because this posting is so long, I'm splitting it into two, with the final section in the following posting.


percussion parts

I raised an issue about the grouping of percussion parts in https://github.com/w3c/mnx/pull/245#issuecomment-942181207, but am moving the discussion here because, strictly speaking, its off-topic there: There are no percussion parts in the diagram being coded in #245:

How do we define a percussion part using a number of different instruments, each of which has a staff having a different number of staff-lines, maybe with different vertical spacing between the staff-lines?

@adrianholovaty replied

For this situation, I'd encode each of the instruments as a different <part>, then use <system-layout> to bunch them together for presentation.

Agreed, but this means that we need to implement various special behaviours for <system-layout>. How, for example, can we force the printing of just one global instruction (accel.----, rit.---- etc.) or time-signature per system, rather than one global instruction or time-signature per staff, in the percussion booklet? (See also the discussion about percussion parts earlier in this issue, beginning at https://github.com/w3c/mnx/issues/185#issuecomment-637422613)

The number of lines in a staff and the distance between them is specific to each instrument, so I think these parameters should be defined inside each <part> element. This is true for all <part> types, not just percussion instruments. The default could be a normal 5-line staff for each staff required by a <part> element. Small staves would also be defined in this way. See Units of size below.

Time-signatures: By default, there would be one of these per staff, but a single, vertically centred, time-signature could be coded for a <system> by enclosing a <time-sig> element inside its <system-layout> element:

<system-layout ... >
    <time-sig width="3" height="10" />
    <part-layout ... />
    <part-layout ... />
    ...
</system-layout>

A time-signature would only be printed in measures that have one in the <global> definition. Note that we can define relative dimensions here:

Units of size: This <system-layout> is going to be used inside a <score> having known external proportions, so its also possible to describe the relative dimensions of the <time-sig>. My preference would be to define the size of a gap -- the distance between standard staff-lines in the score -- and to use that as the unit of size for objects inside the score such as time-signatures, small staves, distance between staff-lines in non-standard staves, etc. In the code example above, a score's relative proportions are described as follows:

<score name="Full Score" relWidth="500" relHeight="707" relMargins="30">... </score>

The size of a gap can be defined simply by adding a gap attribute. The numbers in this declaration are relative (not related to any specific unit), so the attributes could be more elegantly named like this:

<score name="Full Score" width="500" height="707" margins="30" gap="8">...</score>

Multi-measure rests could be implemented in a percussion part-booklet, either directly (as below) or using a specially defined <system-layout>, as a (mid-)<system-layout> change (as per @clnoel's solution above):

<mnx>
    ...
    <system-layout ... id="allinstruments">
        <part-layout ... />
        <part-layout ... />
        <part-layout ... />
        <part-layout ... />
        ...
    </system-layout>

    <score name="Percussion part" width="500" height="707" margins="30" gap="8" >
        <page>
            <system location="1" layout="allinstruments">
                ...
            </system>
            <system location="11" layout="allinstruments">
                <multi-measure-rest location="12" label="50" width="30" padding="2" ... />
                <system-layout location="62" layout="allinstruments"/>
            </system>
            <system location="65" layout="allinstruments">
                ...
            </system>
            ...      
        </page>
        ...
    </score>
</mnx>

In a full score, containing other instruments that play during the percussionist's long rest, the percussionist's music would, of course, have its measure rests written out in the usual way, with one measure-rest symbol per measure and staff. Full score <system-layout> definitions can, of course, leave the percussion out completely.

Note that objects such as rehearsal-numbers and globally defined text instructions (accel., rit. etc.) could use a similar strategy, and that all such objects can be given styling information: size, colour, vertical position, left-right padding etc.


full scores

As it stands, the above <system-layout> strategy works for a score (booklet) for a single (percussion) player playing multiple instruments. It would obviously be useful to extend it for use in <group-layout>, so that it can be used in scores that are to be played by more than one player.

Here's how that would look for a single-system full score, having a 4/4 time-signature at the beginning, and a 3/4 time-signature in measure 3:

<mnx>
    <global>
        <measure>
            <directions>
                <time signature="4/4"/>
            </directions>
        </measure>
        </measure>
        <measure>
            <directions>
                <time signature="3/4"/>
            </directions>
        </measure>
        ... (more measures)
    </global>

    <part ... >...</part>
    <part ... >...</part>
    <part ... >...</part>
    ... (more parts)

    <group-layout id="woodwindslayout1" ... >
        <time-sig width="3" height="20" />
        <staff-layout ... >
            <part-layout ... >...</part-layout>
            <part-layout ... >...</part-layout>
        </staff-layout>
        ... (more staff-layouts)
    </group-layout>

    <group-layout id="percussionlayout1" ... >
        <time-sig width="3" height="10" />
        <part-layout ... >...</part-layout>
        <part-layout ... >...</part-layout>
        <part-layout ... >...</part-layout>
        ... (more part-layouts)
    </group-layout>

    <grand-staff-layout id="pianolayout1" ...>
        <time-sig width="3" height="8" />
    </grand-staff-layout>

    <system-layout id="systemlayout1">
        <group-layout layout="woodwindslayout1" ...  />
        <group-layout layout="percussionlayout1" ... />
        <grand-staff-layout layout="pianolayout1" ... />
        ...
    </system-layout>

    <score name="Full Score" width="500" height="707" margins="30" gap="8">
        <page>
            <system location="1" layout="systemlayout1" />     
        </page>
    </score>
</mnx>

Note the different (relative) heights of time-signature in each group.

Something similar could be done to notate any globally defined instruction that needs to be printed either once per staff, once per group, or once per system.


notes

Colours and Transpositions I think colours and transpositions should, like the staff-line parameters, be defined inside <part> elements. Both colours and transpositions may involve high-level human decisions so they need to be stored separately from the un-coloured or un-transposed originals. I wouldn't trust any current algorithm always to transpose the way I'd like. So, if a specially coloured or transposed version of a <part> is required, then it should be duplicated, coloured or transposed differently, and the duplicate given a new ID. It would be up to applications to ensure that different versions of the same <part> remain consistent. We should probably provide some way of indicating that there is a special link between different versions of the same <part>, so that parsers can read them as such.

General Pauses See this interesting MuseScore feature request thread). Apropos: For me, a General Pause is simply a reassuring annotation that tells everyone that its correct for nobody to be playing anything in the measure. Classically, the annotation is just the string "G.P." above each of the ordinary measure-rests in the score and parts. G.P.s have nothing to do with fermatas or caesuras -- that's a mistake that I think probably comes from a mistranslating the German Pause, which simply means a rest (not a pause). Germans call a quarter-note rest a Viertelpause.

A (multi-measure) General Pause (G.P.) could be coded in a multi-instrument score as a <system-layout> containing a list of specialized <group-layout> elements parallel to the groups in the enclosing <system>. Each <group-layout> would contain a <multi-measure-rest> whose location, label and visual style cascades downwards from the enclosing <system-layout>:

<mnx>

    // <global>, <part> and <group-layout> elements as above

    <group-layout id="group-GP">
        <multi-measure-rest ... /> // can include style info
    </group-layout>

    <grand-staff-layout id="grand-staff-GP">
        <multi-measure-rest ... /> // can include style info
    </group-layout>

    <system-layout id="systemGP" width="30" padding="2" ...>
        <group-layout layout="groupGP" ...  />
        <group-layout layout="groupGP" ... />
        <grand-staff-layout layout="grandstaffGP" ... />
        ...
    </system-layout>

    <score name="Full Score" width="500" height="707" margins="30" gap="8">
        <page>
            <system location="1" layout="systemlayout1">
                <system-layout location="3" label="5" layout="systemGP" />
                <system-layout location="8" layout="systemlayout1">
            </system>     
        </page>
    </score>
</mnx>

Note that a one-measure "multi-measure G.P." could be notated with label="G.P." instead of label="1".

Pull Request #245 I'll have no objection to accepting #245 when

  1. The issues I've already raised there have been resolved.
  2. The issues with the containers described in the following post have been resolved
  3. We have agreed about the containers, and the code in the PR conforms to what we have agreed
notator commented 3 years ago

containers that group parts

Here's a list of all the containers I think we need for grouping parts, and how they nest. I've tried to express this as precisely as I can, so that meaningful corrections and suggestions can be made before trying to convert the information into formal Schema definitions. Some issues may only surface when that attempt is made, but I think its worth trying to agree here first. There are a few known issues listed below, but it should be quite easy to resolve those. Note that these containers don't include those that might contain a score's titles, preface, page numbers, headers, footers, index etc. It should be easy to add such elements later.

Issues:

  1. Should lists of same-class elements have (optional?) intermediary containers? For example, should <score> (be able to?) contain a <pages> element that only contains <page> elements? My preference would be for lists of more than one same-class element always to be contained in such an element.
  2. Must containers be used even if they only contain one element? My feeling is that the answer is no, and that this should be a general principle: If a container only contains one element, then it should be possible to use that element directly, instead of the container. For example, must <part-layout> elements always be contained in <voice-layout> elements, or can <staff-layout> really contain <part-layout> elements directly?
  3. I think <staff-layout> should never contain more than two elements in MNX 1.0. If there is only one element (either a <voice-layout> or a <part-layout>), then its stem directions can be determined algorithmically according to the usual rules. If there are two elements, then the first element has all stems up, the second element has all stems down in the <staff-layout>. Do we then need explicit stem-dir attributes? My feeling is yes, because MNX 2.0 might allow more than one voice or part to have stems up or stems down (think Bach).
clnoel commented 3 years ago

@notator

Thanks very much for the music example! I think it ought to end up in the MNX documentation.

You're welcome, but that's a bad idea because this is a sample of a copyrighted work. If we're going to put it into the official documentation, we'd have worry about that.


Now, if you haven't already, go read https://github.com/w3c/mnx/pull/245#issuecomment-947046000, and preferably respond. We really need to demarcate areas of concern.


I see the following points that need their own issues:

  1. grand-staff-layout: We can debate there whether it is a child or sibling of group-layout and exactly what it should contain, and how it should interact with the part or parts it represents (like where the stave count should live). I'm going to concede the point that we do need an element explicitly for this.
  2. multi-part directions: We can debate whether this goes in system or in one of the layout layers, or maybe both. General Pause falls into this, I think.
  3. multi-staff time signatures: I had never heard of this before, I would love to see an image of what that looks like, but I'm also not sure this has to be MNX 1.0. How common is it?
  4. staff line layout: Numbers of staff lines and the spaces between them.
  5. Special noteheads: Symbolic (diamond, X, etc.), colored, and "letter note". Are these represented in the part or in the part-layout?

In addition, multi-measure rests also have their own issue, so other than making sure there is room for them, we don't need to keep discussing them here.

What I do feel like needs to be hashed out here is:

  1. voice-layout: Do we need this, and why exactly?
  2. Parts that are in different clefs or on a different staff line in their part and the full-score: Example 1: a Tenor part that is in an octava-down G-clef on a choral score, but is in the bass clef and combined with the Bass part on the conductor's full-orchestra score. Example 2: percussion parts that need to be on a particular staff line in a combined part, but are on their own single-line staff in the percussion player's score. Note that this is different from "transposing instruments" ending up different in a full score, since there is no respelling needed.
  3. Whether to allow group-layout and part-layout definitions that are then used by later system-layout elements in order to save a bunch of space in complicated scores.
  4. Mid-system layout changes: Are we good with my earlier proposal? If not, what needs changing.

If people agree with me on the "separate issue" list, I'll go ahead and write them up, with links or quotes back to here for reference.

If we've already hashed out one of the "TBD" questions in the second list, please remind me what got decided. It's getting hard to keep track of stuff, which is why I want to split off issues so we can talk about them separately. If I've missed something, can you please repost the list with your discussion point appended?


In general, though, I would like to keep further discussion in this thread to changes to system and to staff-layout, both their contents and their attributes. I think everything else needs to find it's own space to be worked on.


For the record, here's my opinion on the 5 TBD questions I've identified:

  1. 'voice-layout`: I'm on the fence about this. I can see the advantage, especially with being able to be very clear about stem directions if we use this. However, I'm still not sure it's entirely necessary. Which is better:
    
    <system-layout id="chorded">
    <group-layout symbol="bracket">
        <staff-layout label="T 1, 2">
            <voice-layout>
                <part-layout part="t1" />
                <part-layout part="t2" />
            </voice-layout>
        </staff-layout>
        <staff-layout label="B 1, 2">
            <voice-layout>
                <part-layout part="b1" />
                <part-layout part="b2" />
            </voice-layout>
        </staff-layout>
    </group-layout>
    </system-layout>
or

I'm still leaning toward the second option, especially if `stem="chord"` is considered the default option. It's more compact, but it might not be clear enough as we move forward with things like multi-part directions. We might need the voice-layout so we can add things in there.

2. I feel like a clef or staff-line specifier needs to be defined in the part-layout, but I'm not sure if it should be an attribute or a child element.
3. My original proposal for the system and staff layouts used reusable chunks. I would be cool with adding that back in if we want it back.
4. It looks like @notator has adjusted my original proposal for mid-system-layout-change to reuse the system-layout element name. While being open to a name change in general, I strenuously disagree with changing it to that. There shouldn't be two `system-layout` elements that are entirely different and serve different purposes.

--Christina
notator commented 3 years ago

points that need separate issues

(We should be careful not to create new issues where appropriate issues already exist.)

@clnoel Here are my initial thoughts on your original list:

  1. I think <grand-staff-layout> is a sibling of <staff-layout>, and that both of these elements should be usable both as siblings and as children of <group-layout>.
  2. I think the styles (including position and size) of multi-part directions should cascade. So it should be possible to put them in a container at any meaningful level.
  3. multi-staff time-signatures are often used in large conducting scores and percussion parts. Time-sigs can simply become illegible if they are only the size of individual staves. Example: Schönberg's Pelleas und Melisande (score first printed in 1912).
  4. Yes, we need to discuss how to define staff-parameters inside <part>.
  5. Special noteheads should definitely be defined in <part>, not <part-layout>. <part-layout> is only there to override the stem-direction information that's already in <part>, or to be a <voice-layout> component. <voice-layout> elements are also only about organizing stem-directions (of chords).

The following further points spring to mind:

  1. multi-measure rests and G.P.s: Yes, I think these need a separate issue. Multi-measure rests may only be necessary at the <system> level, for use in part-booklets. I may have got a bit carried away, extending the idea to G.P.s, but I'd like to think a bit more about that.
  2. Is my proposed strategy for colours and transpositions (connected copies of edited <part> elements) correct? If so:
    • how do we tell parsers that different <part> definitions have such a connection.
    • how do we define colours inside <part>.
  3. It has now been decided (in #73) that we are going to produce an MNX schema for MNX 1.0. I think a new issue should be created in which versions of the schema can be discussed. (I've already written one that works for the MNX-Examples as they were earlier this year. It should be fairly easy to refactor and update it for the current state of the examples, and to include the new containers.)

I'll reply to the rest of your posting separately. Somehow we need to keep order here! :-)

--James

notator commented 3 years ago

points that need clarifying here

@clnoel This is in reply to the second part of your comment above.

  1. voice-layout: Do we need this, and why exactly?

A <voice-layout> element is necessary whenever the pitches from two or more <part> elements need to be put on a single stem. The problem I see with using a stem="chord" attribute (without a <voice-layout>) is that there seems to be no way to code a staff that has two voices, both of which contain chords (as in 1.6 below). Maybe there's a way to achieve that using stem attributes, but I have the feeling it would be more complicated than simply using <voice-layout> elements. Here are some examples that use <part-layout> and <voice-layout> inside single <staff-layout> elements, so that we can think about exactly how these are supposed to work: Single-stem:

        // 1.1: single stem, the stem direction can change with pitch register
        <staff-layout>
            <part-layout part="sop" label ="S" />
        </staff-layout>

        // 1.2: single stem, the stem direction can change with pitch register
        <staff-layout>
            <voice-layout>
                <part-layout part="sop" label="S"/>
            </voice-layout>
        </staff-layout>

        // 1.3: single stem with two parts, the stem direction can change with pitch register
        <staff-layout>
            <voice-layout>
                <part-layout part="sop" label="S"/>
                <part-layout part="alt" label ="A" />
            </voice-layout>
        </staff-layout>

I think both 1.1 and 1.2 should be allowed. In other words, the <voice-layout> can be omitted when it would only have one child. Maybe the <voice-layout> must be omitted in such cases. This needs to be decided.

Two-stems. The following examples all look fine to me:

        // 1.4: two stems, one up, one down.
        <staff-layout>
            <part-layout part="sop" label="S" stem-dir="up"/>
            <part-layout part="alt" label ="A" stem-dir="down"/>
        </staff-layout>

        // 1.5:  two stems, one up, one down.
        <staff-layout>
            <voice-layout stem-dir="up">
                <part-layout part="sop" label="S"/>
            </voice-layout>
            <voice-layout  stem-dir="down">
                <part-layout part="alt" label="A"/>
            </voice-layout>
        </staff-layout>

        // 1.6:  two stems, one up, one down.
        <staff-layout>
            <voice-layout stem-dir="up">
                <part-layout part="sop" label="S"/>
                <part-layout part="alt" label="A"/>
            </voice-layout>
            <voice-layout  stem-dir="down">
                <part-layout part="ten" label="T"/>
                <part-layout part="bass" label="B"/>
            </voice-layout>
        </staff-layout>

        // 1.7:  two stems, one up, one down.
        <staff-layout>
            <voice-layout stem-dir="up">
                <part-layout part="sop" label="S"/>
            </voice-layout>
            <voice-layout  stem-dir="down">
                <part-layout part="alt" label="A"/>
                <part-layout part="ten" label="T"/>
                <part-layout part="bass" label="B"/>
            </voice-layout>
        </staff-layout>

        // 1.8:  two stems, one up, one down.
        <staff-layout>
            <part-layout part="sop" label="S" stem-dir="up"/>
            <voice-layout  stem-dir="down">
                <part-layout part="alt" label="A"/>
            </voice-layout>
        </staff-layout>

        // 1.9:  two stems, one up, one down.
        <staff-layout>
            <part-layout part="sop" label="S" stem-dir="up"/>
            <voice-layout  stem-dir="down">
                <part-layout part="alt" label="A"/>
                <part-layout part="ten" label="T"/>
                <part-layout part="bass" label="B"/>
            </voice-layout>
        </staff-layout>

Whatever we decide should be the exact usage for <voice-layout>, it must be the same in all 9 cases. If it can be omitted in 1.1, then 1.8 and 1.9 must also be allowed - even though they look a bit odd. Note that the stem-dir attribute value cascades, so the following code would result in all the stems on the staff having stem-dir="down".

        <staff-layout>
            <voice-layout stem-dir="up">
                <part-layout part="sop" label="S" stem-dir="down"/>
            </voice-layout>
        </staff-layout>

and the following code would be a two-stems-down error:

        <staff-layout>
            <voice-layout stem-dir="up">
                <part-layout part="sop" label="S" stem-dir="down"/>
            </voice-layout>
            <voice-layout  stem-dir="down">
                <part-layout part="alt" label="A"/>
            </voice-layout>
        </staff-layout>

I think MNX 1.0 should only support one stem-up and one stem-down in each staff. Can we decide on that here, or do we need a separate issue?

  1. I feel like a clef or staff-line specifier needs to be defined in the part-layout, but I'm not sure if it should be an attribute or a child element.

As I said in the previous post, I think <part-layout> and <voice-layout> are <staff-layout> components that are only there for organizing stems. If that's not clear, maybe they should be renamed -- but I can't think of any better names... Clef and staff-line info should be defined inside <part> elements. (As I remember, clefs are there already.)

  1. renaming <mid-system-layout> to <system-layout>

I don't feel very strongly about this. I changed the name because I think the intent is clear enough without the mid-, making code simpler to read is always a good idea, and the object it references is a <system-layout>, not a <mid-system-layout>. I have no problem using the same name in different contexts (namespaces). Had a similar disagreement with @joeberkovitz about that. We probably need arbitration. :-)

clnoel commented 3 years ago

New lists, then.

Out of scope

Please do not actually respond to any of these! Only comment on them if you think they are central to "How to group parts" and are not an easily separable side-issue.

A. Discussion of the grand staff. For here and now, let's keep our discussions about multiple parts on a staff, not multiple staves for a part. Yes, that needs to be resolved, but we can keep going with our existing part-layout solution until we've resolved the rest of the definitely in-scope issues. (Needs an issue)

B. Multi-part directions/Single-part directions on multi-part staves: Where should a direction that applies to all parts in a multi-part staff be displayed? What about directions that only apply on multi-part staves (like the unis. label in our mid-system layout example)? What about directions that only apply to one part of a multi part stave, like directing the sopranos to be quiet and the altos to be loud? For that matter, what about lyrics, which might sometimes be the same for the parts and sometimes will be different? (Some of this seems to be covered in #196, but I don't feel like they are exactly the same).

C. Staff styling: Distance between staff lines, small staves with cue notes, etc.

D. Multi-staff time signatures (Needs an issue)

E. Special noteheads. A quick look did not find any issue that was about giving a note a "diamond" or an "X" or any other notehead other than the standard open/filled oval. This is going to be vital for representing percussion. (Needs an issue)

F. Multi-measure rests: I think we are in agreement that this needs to be a child element of the <system> but exactly what it looks like is still under disussion. (Issue #121)

Aside from that, @notator , feel free to make a schema issue (your point 8). That is entirely separate from what we are talking about here. And your last point (7) should probably stay in this issue, so I'll add it to the list below. I'm going to make separate issues for the above that don't already have issues next week unless I get some severe push back, but in the mean time I considered them tabled and will not be discussing them here.


In-scope

Note: We should also look at https://github.com/w3c/mnx/issues/104#issuecomment-419682599, which has a great set of examples!

  1. voice-layout: I was going to say we don't need this because we can chord all stem-up and all stem-down parts together, and then I thought again, because eventually we might want to support two stem-up voices. So we'll go with it. I prefer defined rather than optional layouts, so I would like voice-layout to be mandatory. This also allows stem-dir to exist only only the voice-layout. The default stem-dir is "default", which means that the stem directions defined for the individual notes in the part are respected, with the assumption that notes with undefined stem directions are attempted to be chorded together as in the "chorded" option. The other options are "up" for all parts to be up-stem; "down" for all parts to be down-stem; and "chorded" for forcing the parts into chords with up/down stems depending on their location in the staff. In all of these cases, the notes inside a voice-layout share a stem whenever their stem directions and durations allow. The notes in different voice-layout elements inside a staff-layout never share a stem even if they happen to have the same stem direction. If you agree with this verbal description, I'll start working on examples and formal definitions.

  2. It is not sufficient to claim that clef should be defined in the part. If we want to group a part that is defined with a C-clef with a part that is defined with an F-clef, we have to be able to define which (if either) to use in the system layout. Therefore, <staff-layout> at least needs to be able to contain more information. I propose allowing the <clef> element to be allowed in a <staff-layout> as an override to the parts involved. If there are any clef changes in any part when such a staff-layout is in effect, it is ignored, and the note is rendered on the correct line for the pitch it is on the staff-layout's clef.

  3. I'll concede the staff line location thing as not being important. It would only be important for percussion parts that are each on their own one-line staff in the "percussion score" but need to be compressed for a "conductor score" and I was unable to find an actual example of this happening, so I'll let it go until we come up with an actual case where we need to worry about it.

  4. I think we're in agreement in being able to define a staff-layout or voice-layout in it's own element, then be able to reference them in later system layouts.

  5. A system can reference the id of a system-layout using the layout attribute, and so an a mid-system-layout I fail to see the issue, but I'm willing to call it layout-change or system-layout-change instead as a compromise.

  6. Colors: I would like to see an example of score-and-parts that use colors, so I can visually see what we are trying to encode. Without that, all I can say is that if all scores are expected to use the same color for the part, It should be defined in the <part>. If only some scores are expected to use colors, then it should be defined in the <part-layout>.

  7. Transposing Instruments: Sigh. Part of me wants to shove this proposal off on another issue, since the problems with transposing instruments and respelling got hashed and rehashed in #34 and I am heartily sick of it. One thing I am absolutely opposed to is having two <part> tags for the same part because it happens to be a transposing instrument. I feel like that is just a bad idea, but I don't have a better idea right now.


So I believe we have 6 open questions right now, since I'm dropping (3.) (staff line specifiers). @notator and I are in agreement on (4.), but I haven't heard anything from anyone else on that. We also have six questions that are separable from this one, five of which need new issues.

--Christina

notator commented 3 years ago

@clnoel Thanks very much for the above posting. Very useful!

Except for A, which I think is essential to this thread, I agree that all your "Out of scope" points should be dealt with in separate issues. Apropos point E: #184 contains an interesting discussion about using Unicode to notate special accidentals. I think the new issue should be about both accidentals and noteheads, and that it should mention #184 in its intro. Maybe you could simply name the new issue "The note element" or something like "Unicode noteheads and accidentals".

Except for 6. and 7, I also agree with your In scope list. As I said in https://github.com/w3c/mnx/issues/185#issuecomment-947598381, I think we need to discuss how to code colours and transpositions separately. That will be much easier to do, once we've got the container hierarchy sorted out. If you open a new issue for that, I'll copy in my proposal from the "notes" section of https://github.com/w3c/mnx/issues/185#issuecomment-946724652). Maybe I should wait until we have agreed about the containers.

I'll be referring back to your In-scope list (above) until we've got agreement on all points. To kick off, here's some more about point 1 <voice-layout>, including why I think Discussion of the grand staff, needs to be In-scope:

I'm not sure that I completely understand your comments about "chorded" parts. (Note that chords can be defined in single-voice <part> elements. See the "Three-note chord and half rest" example in Comparing MNX and MusicXML). But I think we agree that both <part-layout> and <voice-layout> are necessary for grouping <part> elements inside a <staff-layout>. Unfortunately, this only works for <part> elements that define a single sequence of <sequence> elements (i.e. define a single voice), and whose pitches can therefore be put on stems that

If a <part> contains multiple voice layers (parallel sequences of <sequence> elements) then the stem directions are already determined inside the <part>, and can't be overridden. Its simply not possible to override all the stem directions in a multi-voice <part> in order to add them to a single stem shared by other <part> elements. So we need an element, parallel to <staff-layout>, whose stem directions are determined inside its <part> definition, and are not overridable.

Note that a <part> can contain multiple voices, even if it only uses one staff. See the "Multiple voices" example in Comparing MNX and MusicXML. Such <part> elements also can't be combined with other <part> elements using <part-layout> and <voice-layout>. They need their own staff. If we make <voice-layout> compulsory (as you suggest), that would mean that the two-voice <part> in the "Multiple voices" example would have to be coded like this:

        <staff-layout>
            <voice-layout>
                <part-layout part="sop-alt" label="S, A"/>
            </voice-layout>
        </staff-layout>

That looks a bit strange for a part that has two voices. One alternative (that you probably won't like) might be to leave out the <voice-layout>:

        <staff-layout>
            <part-layout part="sop-alt" label="S, A"/>
        </staff-layout>

Another would be to use a single-staff <grand-staff-layout>

    <grand-staff-layout part="sop-alt"  staves="1" ... >...</grand-staff-layout>

Which also looks a bit strange.

Maybe the answer is to have two alternatives to <staff-layout>:

Those would look like this

    // This part="piano" can be written on either 2 or 3 staves, depending on
    // the range of measures in the system.
    // 3 staves are required for the piano in the system that uses this layout.

    <multi-staff-layout ... part="piano"  staves="3">...</multi-staff-layout>

and

    <multi-voice-staff-layout ... part="sop-alt">...</multi-voice-staff-layout>

Note that

  1. Neither of these elements can contain <part-layout> or <voice-layout> elements that override the stem directions they require.
  2. <multi-voice-staff-layout> needs no staves attribute since it always has just one.

What do you think?

joeberkovitz commented 3 years ago

A few comments follow. I'm doing my best to provide real rationales and not just say "I prefer..." or "I like...".

As I see it, the crux of the problem is that grand-staff is simplest with a hierarchy of group/part/staff whereas sections and multipart staves are simplest with a hierarchy of group/staff/part.

notator commented 3 years ago

@joeberkovitz

I believe that layouts as a whole are optional...

Agreed, but I think an MNX file must contain a description of a particular full score and/or set of part-booklets. There's nothing to stop an application using the info in the file to create a score and/or part-booklets formatted in some other way. Those applications can then store the new layout in a new MNX file. The current strategy does not make a particular layout compulsory. Similarly, specialized applications can then convert MNX scores to Braille, or any other music notation format. Note also that my current proposal is for score size parameters to be described in relative units: A score described in an MNX file, can be printed on paper of any size, and an MNX renderer for low-vision users is free to display the symbols at any size it likes. (See https://github.com/w3c/mnx/issues/185#issuecomment-946724652, percussion parts/Units of size.)

Here's why I think <voice-layout> should be not be nested inside <part-layout>: First, I'd like to emphasize that <voice-layout> and <part-layout> are slight misnomers. They are parameters of <staff-layout> that determine stem directions in the <staff-layout>, not objects that need to affect <part> definitions or voices inside <part> definitions. My <voice-layout> is a staff <voice-layout>, not a part <voice-layout>. I think <part> elements should own the objects (sequences, events, staff-line parameters, colours etc) that they define. These should be read-only. That does not mean that the elements that use the <part> definition are forced to use all its internal definitions. Those can simply be overridden if necessary, and if that does not create a conflict with the other data in the <part>. Note that

In the end, I think that making <part> definitions read-only is going to lead to simpler code.

I completely agree with you that we need more concrete examples. In particular, grand staff instruments need sorting out. I'll soon be posting an example of a minimal score containing a one-page piano piece containing three grand staves having two, three and two sub-staves respectively.

clnoel commented 3 years ago

Status update on list in https://github.com/w3c/mnx/issues/185#issuecomment-948018127: We now need issues for B, C, D, E, 6, and 7 (I'm happy to push off transposing instruments!), and probably not A, because @notator feels really strongly. That means our in-scope discussions are around A, 1, 2, 5, and maybe 4, if someone strongly disagrees.


@joeberkovitz Yes, layouts are optional. That's actually part of the definition of <score>. <page>, and <system>. Unlike @notator I firmly believe that if you really don't care what the layout is you shouldn't have to specify it. But then you also can't complain when a consuming application splits up the system breaks in a way you didn't envision. You can also specify <score>. <page>, and <system> without any system-layouts defined in order to specify page and system breaks. In this case, the layout is assumed to be all parts on every system (in the order they are in the MNX file). The parts use the stem direction defined in the part, and braces/brackets are only on the grand-staff for a multi-stave part.

On (1) - voice-layout @joeberkovitz has requested examples! Here's what I'm currently thinking! As it happens, I was not trying to put voice-layout inside part-layout but your suggestion brought up a good issue, that I've added my solution to in the example below.

Here's the parts for a choral piece designed to be performed with piano accompaniment and a flute duet. For most of the piece the basses sing in unison, but there are a few passages where they split and have opposing stems. The sequence-id identifier is new to this proposal, and I envision it being something that could be used again and again to represent a coherent voice that goes cross-measure but should not be it's own part for whatever reason.

...
<part id="soprano"/>
<part id="alto"/>
<part id="tenor"/>
<part id="bass">
...
<sequence sequence-id="bass1"/>
<sequence sequence-id="bass2"/>
...
</part>
<part id="piano" max-staves=2/>
<part id="flute1"/>
<part id="flute2"/>

First, exactly how a grand staff would look is still under debate. We have two conflicting proposals, one involving <grand-staff-layout/> and one involving <group-layout symbol=brace/>. Because I haven't decided what I like best, I'm going to simply put [Grand Staff] into the examples below for where the pianist's part goes.

Here's what the system layout could look like for the conductor. The SATB parts are separated out with a bracket, and use the stemming indicated in their <part> (stem="default") the Flutes are on a combined staff where they combine stems whenever possible and those stems can be up or down (stem="float"), and the piano part is at the bottom. Note: I like the term "floating stem" better than "chorded stem" to represent a voice is that is allowed to be stem up or stem down based on standard stemming rules, so I'm changing it. See the bottom of this post for a more formal description of my proposed stem enumeration.

<system-layout id="conductor">
   <group-layout symbol=bracket/>
        <staff-layout label="Sop.">
            <part-layout id="soprano"/>
        </staff-layout>
        <staff-layout label="Alto">
                <part-layout id="alto"/>
            </voice-layout>
        </staff-layout>
        <staff-layout label="Ten.">
            <part-layout id="tenor"/>
        </staff-layout>
        <staff-layout label="Bass">
                <part-layout id="bass"/>                              
        </staff-layout>
   </group-layout>
   <staff-layout label = "Flutes">
        <voice-layout stem="float">
            <part-layout id="flute1"/>
            <part-layout id="flute2"/>
        </voice-layout>
   </staff-layout>
   [Grand Staff]
</system-layout>

Here's what the system layout could look like for the pianist's score. The pianist score has a shared SA staff with split stems, a shared TB staff with split stems, a shared flute staff that uses floating stems, and the piano grand staff.
Note: The sequence-layout is a new proposal, and it says that when the "bass1" voice is present, it goes upstem and joins the tenor part, while the "bass2" voice stays downstem. Indicating how the split happens through labels or lines is currently out-of-scope (B). Note: In my head, the choir staves and the flute staff would be small "cue" staves, to allow for less page turning for the pianist, but that's out-of-scope (C).

<system-layout id="pianist">
   <group-layout symbol=bracket/>
        <staff-layout label="SA">
            <voice-layout stem="up">
                <part-layout id="soprano"/>
            </voice-layout>
            <voice-layout stem="down">
                <part-layout id="alto"/>
            </voice-layout>
        </staff-layout>
        <staff-layout label="TB">
            <voice-layout stem="up">
                <part-layout id="tenor"/>
                <sequence-layout id="bass1"/>
            </voice-layout>
            <voice-layout stem="down">
                <part-layout id="bass"/>                    
                 <sequence-layout id="bass2"/>
            </voice-layout>
        </staff-layout>
   </group-layout>
   <staff-layout label = "Flutes">
        <voice-layout stem="float">
            <part-layout id="flute1"/>
            <part-layout id="flute2"/>
        </voice-layout>
   </staff-layout>
   [Grand Staff]
</system-layout>

The layout for the members of the choir would not include the flute parts at all:

<system-layout id="choir">
   <group-layout symbol=bracket/>
        <staff-layout label="Sop.">
            <part-layout id="soprano"/>
        </staff-layout>
        <staff-layout label="Alto">
                <part-layout id="alto"/>
            </voice-layout>
        </staff-layout>
        <staff-layout label="Ten.">
            <part-layout id="tenor"/>
        </staff-layout>
        <staff-layout label="Bass">
                <part-layout id="bass"/>                              
        </staff-layout>
   </group-layout>  
   [Grand Staff]
</system-layout>

The layout for the flautists would not include the choir parts or piano parts at all, and has the two flutes on separate staves, using the stemming defined in their <part> (stem="default") Note that there is no bracket around flute 1 and flute 2 in this layout.

<system-layout id="flutes">
   <staff-layout label="Flute 1">
        <part-layout id="flute1"/>
    </staff-layout>
    <staff-layout label="Flute 2">
            <part-layout id="flute2"/>
        </voice-layout>
   </staff-layout>        
</system-layout>

In addition, you could always make a "Flute 1" layout and a "Flute 2" layout for each flute part separately, but I'm sure you get the idea.

Importantly, the same layout does not have to apply throughout an entire score. For instance, there could be an additional "choir-with-flute" layout that is in the choir's booklet that shows the flute part for just a system or two.


My proposal for a stem direction enumeration for use on voice-layout:

default : Use the stem direction defined in the part (default)
up: Put all stems up.
down: Put all stems down.
float: Stem up or stem down depending on the location of the notehead or noteheads on each stem.

In all cases, if there is more that one part in the voice-layout, you stem them together whenever possible. In "default" mode this means only when the stem directions in the "part" align. In "up", "down" and "float" mode this means whenever the notes of the same duration occur at the same time. This stem direction value can only be changed by a voice-layout. If you have a part directly defined under a staff, it uses "default" mode. If you need to define the stem direction more precisely due to a rhythm change, you need a new layout, or need to apply a sequence-layout. If you are in "default" mode and there isn't a stem direction defined for any of the notes on the stem, you use "float" rules for that stem.


My proposal for sequence-id and sequence-layout: In the part, you can identify sequences that are special or that "go together" across measure boundaries by putting the same "sequence-id" on them. These sequences can then be slotted into voice-layouts for the short time that they exist without having to create an entirely new layout for them. They could probably be named better.


Finally, in regards to (4), You can see that in the above layouts, several group-layouts and staff-layouts were reused over and over, so we also propose being able to define and reuse these.

<staff-layout id="combinedFlute" label = "Flutes">
        <voice-layout stem="float">
            <part-layout id="flute1"/>
            <part-layout id="flute2"/>
        </voice-layout>
</staff-layout>
<group-layout id="separateChoir" symbol=bracket/>
        <staff-layout label="Sop.">
            <part-layout id="soprano"/>
        </staff-layout>
        <staff-layout label="Alto">
                <part-layout id="alto"/>
            </voice-layout>
        </staff-layout>
        <staff-layout label="Ten.">
            <part-layout id="tenor"/>
        </staff-layout>
        <staff-layout label="Bass">
                <part-layout id="bass"/>                              
        </staff-layout>
   </group-layout>  

<system-layout id="conductor">
   <group-layout layout="separateChoir"/>
   <staff-layout layout="combinedFlute"/>
   [Grand Staff]
</system-layout>
<system-layout id="choir">
   <group-layout layout="separateChoir"/>  
   [Grand Staff]
</system-layout>

I think this summarizes my current thinking on (1) and (4). @notator, I haven't fully read your proposal on the grand-staff-layout (A), yet. I'm a little swamped at work right now, so I'll get around to it tonight or Monday.

--Christina

notator commented 3 years ago

layout (<score>)

This posting continues the discussion about top-level layout in the previous posting. I'll continue the <voice-layout> discussion in a separate post.

@clnoel said in https://github.com/w3c/mnx/issues/185#issuecomment-949701140

Unlike @notator I firmly believe that if you really don't care what the layout is you shouldn't have to specify it.

I was assuming that an MNX file always has to contain at least one <score> definition, and that that definition must contain elements that have layout info. That assumption may not be correct.

Assuming I'm wrong: We could agree that MNX files should be allowed to leave <score> definitions out altogether, and just supply <part> definitions. That's probably not a good idea because users of MNX files (both humans and parsers) will have expectations that we shouldn't just ignore. So lets assume that MNX files must contain a <score> definition of some sort, even if it contains no layout info other than line breaks.

You can also specify <score>. <page>, and <system> without any system-layouts defined in order to specify page and system breaks. In this case, the layout is assumed to be all parts on every system (in the order they are in the MNX file). The parts use the stem direction defined in the part, and braces/brackets are only on the grand-staff for a multi-stave part.

Yes, and the staves would all have the same gap size. That would look like this:

<mnx>
    <global ...>...</global>
    <part ...>...</part>
    <part ...>...</part>
    ... // more parts

    <score ... width="500" height="707" margins="30" gap="8" font="Bravura">
        <page>
            <system measure="1" />
            <system measure="6" />
            <system measure="16" />
            ... // more systems  
        </page>

        <page>...</page>
        ... // more pages

    </score>

</mnx>

Note that I've included the <score>'s (= the <page>'s) relative dimensions and music font. System breaks can't be decided without reference to each staff's relative dimensions (width, gap) and the widths of the noteheads etc. in the music font. That information should therefore be saved in the file. (The staff width can be calculated from the score's width and margins.) Ideally, fonts designed for larger absolute gap sizes should have wider noteheads, so some fonts have much wider noteheads than others.

I'm not really convinced that we can leave out all the info about the vertical sizes of the elements on these pages. How do we know that the systems really fit on the pages as specified? And if the author of the file knows all that information, why shouldn't they save it in the file? Sorry, but I still think that if you really don't care what the layout is, you should simply ignore it.

adrianholovaty commented 3 years ago

@notator wrote:

I was assuming that an MNX file always has to contain at least one <score> definition, and that that definition must contain elements that have layout info. That assumption may not be correct.

Assuming I'm wrong: We could agree that MNX files should be allowed to leave <score> definitions out altogether, and just supply <part> definitions. That's probably not a good idea because users of MNX files (both humans and parsers) will have expectations that we shouldn't just ignore. So lets assume that MNX files must contain a <score> definition of some sort, even if it contains no layout info other than line breaks.

I've always been operating under the assumption that <score> is totally optional. It's additional metadata that can aid in achieving specific renderings, whereas the semantic notation data (from <global> and <part>) is really the meat of the document. All of the existing MNX example documents make sense without having defined <score>.

To make an analogy to web pages: <global> and <part> are the semantic HTML, whereas <score> is CSS (presenational style rules).

Furthermore, some modern notation apps, such as my own, don't particularly care about line break data, nor do they even have the concept of pages. If they were required to generate layout information despite not actually having real layout information, that would (at best) feel a lot like unnecessary hoop-jumping and (at worst) lead to buggy/bad layouts.

notator commented 3 years ago

@adrianholovaty Interesting! :-)

My own MNXtoSVG application also supplies its own layout information to create a rendering of the <part> elements in the existing MNX example documents (without looking for a <score> element). So we could have an MNX format that has no <score> or layout elements. My problem with that is that we then have two different MNX formats. How can we tell, by looking at an MNX (.mnx) file from the outside, whether it contains a score or not? There are going to be lots of applications that rely on having a (default) score rendition defined in the file. Possible solutions might be:

  1. define different file extensions for the two file types
  2. require MNX files always to contain at least one (ignorable) <score> element

I don't much like option 1, since I think we are going to need different file extensions later, for different MNX profiles. Option 2 would mean adding (ignorable) score definitions to the existing MNX Example documents.

Any other ideas would be very welcome.

Edit: Note that if you have an application that reads an MNX file containing a default score definition, but that ignores the definition in order to display the score in some other way, that application is only reading the file, not writing it. The app only needs to supply a new score definition if it wants to save the layout it has just created. Maybe that helps?

adrianholovaty commented 3 years ago

My problem with that is that we then have two different MNX formats. How can we tell, by looking at an MNX (.mnx) file from the outside, whether it contains a score or not? There are going to be lots of applications that rely on having a (default) score rendition defined in the file.

That's not two different formats, it's a single format with some (non-essential) data being optional.

I think you might be overvaluing line-break and page-break data? MusicXML doesn't require line-break or page-break data, and that hasn't caused any problems to my knowledge.

On a practical level, I'd be curious to hear about any existing notation software that wouldn't be able to handle notation data that didn't have line breaks explicitly encoded. Determining line breaks automatically — assuming the most naïve algorithm possible — is among the easier parts of developing a music-notation rendering engine.

And even if there were a notation app that didn't include a line-break algorithm, the solution there would be for the notation app to say "Sorry, your file doesn't include line-break information, so we don't know how to render it." Much as my own app does if it encounters a notational situation it cannot handle, such as multiple parts that have different time signatures in the same bar.

clnoel commented 3 years ago

My problem with that is that we then have two different MNX formats. How can we tell, by looking at an MNX (.mnx) file from the outside, whether it contains a score or not? There are going to be lots of applications that rely on having a (default) score rendition defined in the file.

That's not two different formats, it's a single format with some (non-essential) data being optional.

I agree, this is not two different formats. Our current description says score is optional, and I don't think that needs to be changed. If you are writing a reader program that cares about layout, you have to handle the case where you have to figure out your own system and page breaks. Just like you would have to figure those out if the only score is written for A4, or for that small marching-band-sheet size, and you only do Letter size. Finally, we have no idea what applications are going to be written for this, other than the ones we are currently forming to test our ideas with, so saying "lots of applications" are going to do anything is assuming a lot.


After consideration, I think I prefer <grand-staff-layout> Here's what I see as needed: 1) A part with multiple staves has a staves or max-staves attribute. 2) A <grand-staff-layout> with no children can exist as a child of either <system-layout> or <group-layout> 3) This element has a required part attribute, that can point to any part, even one with a max-staves of 1. 4) This element has an optional symbol attribute that matches the enum for the <group-layout> symbol attribute, but defaults to brace. 5) This element has an optional staves attribute that is either all or a space-delimited list of which staves should appear in which order, defaulting to all. Other layout attributes that we will later put on staff-layout, such as distance between staff lines, should also be added to the grand-staff-layout.

So, a standard piano grand staff could be added with just:

<part id=piano max-staves=2/>
...
<system-layout>
    <grand-staff-layout part="piano"/>
</system-layout>

A more complicated grand staff with three staves some of the time might have three different layouts:

<part id="piano" max-staves=3/>
...
<grand-staff-layout part="piano" />
...
<grand-staff-layout part="piano" staves="1 2"/>
...
<grand-staff-layout part="piano" staves="2 3"/>

The only negative I can see to this is if it is necessary to define staff line attributes separately on the different staves of the grand staff. If that's needed, we need to go back to using <group-layout> and adding a staff attribute to the part-layout.

--Christina

notator commented 3 years ago

layout (<score>)

Consider the following scenario: A user wants to create a set of <part> elements to save in an MNX file. They do that in a music editing application such as Dorico. Dorico is going to save the file.

Dorico needs a framework within which to create the <part> elements. It creates one by asking the user to define page sizes, font sizes, part-groupings etc, So Dorico will always be able to save the file with a <score> element. In other words: its necessary to create the layout information, even if you don't really care what it is. I don't think its possible for any music editing software to create <part> elements without providing them with some kind of high-level context.

If Dorico saves the MNX file without the <score> element, then its going to have difficulty reading it back in in order to edit it. The user would then have to go through the whole procedure of re-defining the page-sizes, font-sizes, part-groupings etc, even though they have already done that once, and its something they are not really interested in. Dorico is one of the applications that "relies on having a (default) score rendition defined in the file".


P.S. I'm still working on a reply to @clnoel's <voice-layout> thread.

cecilios commented 3 years ago

@notator Consider an application oriented to sound, such as many DAW. They produce scores oriented to be played, not to be displayed and thus, they do not care about display layouts. These applications will be forced to "improvise" some layout description (possible buggy) just to be able to export a mandatory score element.

notator commented 3 years ago

@cecilios Great to have you back here! You started this thread! :-)

I don't think DAW applications should be expected to create/originate MNX files containing high-class printed music. Neither do I think that they will be "forced to improvise some layout description". DAW applications should be able to edit and save sounds related to (the <event> elements in) <part>s in existing MNX files.

If a DAW application wants to edit and save sounds defined in <part> elements, it can do so without changing the <score>. It can just save the original <score>, unchanged, back into the file. The <score> only contains spatial information, so need not concern the DAW app, but there's nothing to stop <part>s containing both spatial and temporal information...

I see that the Agenda for next week's TPAC meeting now includes "Instrument data". We're obviously moving in that direction...

cecilios commented 3 years ago

@notator If a DAW application creates some music from scratch there is no an existing MNX file to edit.

there's nothing to stop <part>s containing both spatial and temporal information...

The fact that <score> be optional or mandatory does not affect to your above sentence. It is always true.

IMO there are no solid arguments to impose a mandatory <score> element. A good separation between content and layout (e.g. CSS) does not force to having to obligatorily include layout information. If not present, any renderer should be able to apply some defaults or reject the document.

notator commented 3 years ago

Even if a DAW application only created a rudimentary score, it could then be edited by a specialized music notation application that understood the format. But having no score at all to edit would cause unnecessary difficulties. ...But maybe you are right, and there could be a set of defaults that the notation app could use as a starting point. Needs thinking about.

cecilios commented 3 years ago

Needs thinking about.

It is not so difficult to create an acceptable layout without layout information. Think about many notation applications that can import MIDI files and display acceptable layouts.

joeberkovitz commented 3 years ago

If there needs to be more discussion, could we please move this debate about requiring score layout information to a different issue so this one can get back to focusing on grouping of parts?

I don't see that issue as having a promising future. There are many use cases in which an MNX encoding is created in a context where layout information simply doesn't exist. @cecilios already pointed out that DAWs need to be able to export encoded notation—requiring the DAW to alter an existing MNX file including layout info is not a realistic solution, as that is no longer a file export in any sense. Historians encode music manuscripts written by hand on bits of scrap paper. Sight reading programs dynamically generate snippets of 1 or 2 bars to be displayed inline. Everyday composers work on incomplete scores all the time in notation editors, without no thought given to layout because it makes no sense at that point in their creative process (how would they know where the system breaks will ultimately go?).

In the end, we should not be encoding information that doesn't reflect intent on the document creator's part. And we don't have to: it is straightforward for a renderer to generate a default layout on the fly. This is not going to prevent Dorico or any other application from importing a layout-free MNX file. It will read it, and apply (or ask the importer for) whatever default layout settings it needs. Much like importing a plain text file into Word.

notator commented 3 years ago

@joeberkovitz Agreed on all points (I think). If, as I think likely, we can all agree on the following summary about <score> elements (the top level of the container hierarchy), then I think we can close the "layout <score>" sub-issue and continue discussing the low level (<voice-layout>) sub-issue. (I'll be doing that very soon in a separate posting.)

Takeaways from the above discussion are:

  1. <score> elements contain purely graphical information, and are optional in MNX documents. This means that all applications have to assume that there may be no <score> element in the file. (It does not mean that there are "two different MNX formats".) Applications, such as Dorico or my MNXtoSVG, therefore have to be able to create new <score> elements. New <score> elements can be
    • created in any of the following ways:
      • edit an existing <score> element
      • ask users for further information
      • use a default <score> format that is adapted to use information in the <part> elements
    • saved to a new MNX file together with the original <part> elements.
  2. <part> elements can contain both graphical and temporal information. The discussion about the content of <part> elements belongs in an issue of its own. That issue should be opened as soon as we have agreed on the complete container hierarchy and this issue (#185) has been closed. (Please don't reply to the following remarks here unless you have a point to add to the list below.) Note that <part> elements can have complete graphical and temporal styles. Graphical distances can be expressed in gaps. A gap is the vertical distance between the stafflines in the most commonly used staves in the file (<score> and/or set of <part> elements). A small cue staff could, for example, be defined as having a distance of 80/100 gaps between its stafflines. Font heights can also be defined in gaps. I think it should also be possible to define CSS-like graphical styles in the <score> element, and that such styles should cascade from the <score> downwards in the container hierarchy. The new <part> issue has to decide how to code (at least) the following:
    • how many stafflines the <part> has in its staff (or staves), and the distances between them
    • colours
    • temporal data (We need to think carefully about how DAW apps can create <part> elements.)
    • transpositions
notator commented 3 years ago

<voice-layout>

@clnoel This is in reply to your thoughts on lower level layout elements in https://github.com/w3c/mnx/issues/185#issuecomment-949701140. I'll reply to your second comment (about <grand-staff-layout> elements) in a separate post with a graphic example.

I'm trying to keep this post as short as possible. Apologies if these remarks sometimes seem a bit curt.

Ex. 1, the <part> definitions: It was really worth looking closely at your <sequence> elements proposal, but I'd prefer the following solution to the problem: Define two bass parts, <part id="bass1"> and <part id="bass2">, and connect them internally with a construction that says that the bass2 part has the same sequence of <sequence> elements as the bass1 part from measure location X to (non-inclusive) measure location Y. (The connection code would be internal to <part>, so its off-topic for this issue (#185). This proposal should be added to the TODO list for the <part> issue.) That would:

Adding a max-staves=2 attribute to the piano <part> is a mistake. It duplicates information that will be found when parsing the <part>, so its a maintenance problem and a source of future errors.

So I'd recode Ex. 1 like this:

<mnx>
    <global ...>...</global>

    <part id="soprano">...</part>
    <part id="alto">...</part>
    <part id="tenor">...</part>
    <part id="bass1">...</part>
    <part id="bass2">...</part>

    <part id="piano">...</part>

    <part id="flute1">...</part>
    <part id="flute2">...</part>
    ...
</mnx>

Ex. 2, the "conductor" <system-layout> Can you confirm that we now agree that <voice-layout> tags can be omitted in <staff-layout> elements that only contain one <part-layout>? Is that "can be omitted" or "must be omitted"? My preference would be for tolerance here: I'd go for "can".

I don't think we need the "default" item in your stem direction enumeration. Its enough just to have ["up", "down", "float"]. (But see below.) The default value for a <part> would, as you say, be "float", and that value can be overridden using "up" or "down" in <voice-layout> elements (and <part-layout> elements? see below).

Basses: If there are both bass1 and bass2 parts, then both of these have to be assigned to the <staff-layout> somehow. If we know that bass1 and bass2 are identical for the duration of the <staff-layout>, we could use

   <staff-layout label="Bass">
            <part-layout id="bass1"/>
   </staff-layout>

But if their pitches are sometimes the same, sometimes different, we could use:

   <staff-layout label="Bass">
        <voice-layout stem="float" minimum-noteheads="yes">
            <part-layout id="bass1"/>
            <part-layout id="bass2"/>
        </voice-layout>
   </staff-layout>

That would print one notehead per stem if the pitches are the same, otherwise two. minimum-noteheads="no" would always put two noteheads on each stem.

Flutes: I'm not sure what you mean by:

the Flutes are on a combined staff where they combine stems whenever possible and those stems can be up or down (stem="float"),

This implies that there should sometimes be one stem, and sometimes two, so this could be an example where different <voice-layout>s have to be defined, and then referenced by ID in a special <system-layout> definition. As it stands, the Flutes <staff-layout> says that there is always just one (floating) stem, as in my "Bass" example above.

Theoretically, if we also let <part-layout> override the stem type, we could also omit the <voice-layout>s in such situations:

<system-layout id="conductor">
    ...
    <staff-layout label="Flutes">
        <part-layout id="flute1" stem="up"/>
        <part-layout id="flute2" stem="down"/>
   </staff-layout>
   ...
</system-layout>

I think that's a bad idea (What do you think?), since it

Note that the <part-layout> elements (correctly) don't contain anything in either your examples or mine. In particular, they don't contain any elements that are containers. They are the lowest elements in the container hierarchy.

Ex. 3 the "pianist" <system-layout> I think there must be an error in the TB <staff-layout> (otherwise I'm not understanding something): Having a "bass" <part-layout> doesn't seem to make sense while you are also using the bass <sequence-layout> elements. The stem-down <voice-layout> should just be:

            <voice-layout stem="down">               
                 <sequence-layout id="bass2"/>
            </voice-layout>

In my version, with separate <part> elements for bass1 and bass2, the TB <staff-layout> becomes the usual:

        <staff-layout label="TB">
            <voice-layout stem="up">
                <part-layout id="tenor"/>
                <part-layout id="bass1"/>
            </voice-layout>
            <voice-layout stem="down">                   
                 <part-layout id="bass2"/>
            </voice-layout>
        </staff-layout>

As I said above, I think we need a way, inside the <part> definitions, to say that a part is identical to another part for a range of measures. That would solve the problem of having different parts that are identical for long periods of time.

In my head, the choir staves and the flute staff would be small "cue" staves, to allow for less page turning for the pianist, but that's out-of-scope.

The solution is to define the staff sizes using gap units - see point 2 in https://github.com/w3c/mnx/issues/185#issuecomment-950764557 above. A note about size dimensions: Each of your <system-layout> definitions is going to be used inside a different <score> definition, so the gap lengths used inside the <part> elements are going to have a different relation to the page size in each case. The staves in the Flute part-booklet(s) need to be bigger (larger rastral) than the staves for the flutes in the conductor's or pianist's scores. But the gap is still the unit of length inside all the <part> definitions. Nobody has commented yet on this proposal. What do you think?

Ex. 4 the "choir" <system-layout> and Ex. 5 the "flutes" <system-layout>: I have nothing to add here.


I don't really understand your stem direction proposal: As I said above, I don't think we need stem="default". Are you proposing one or both of the following?


Your <sequence-layout> proposal: As I said above, I think this should be solved inside the <part> definitions. I think it can probably be done without using IDs for sequences of <sequence> elements, but that's off-topic here.


We agree about the re-use of predefined -layout> elements (sub-issue 4). Great example! :-)

ahankinson commented 3 years ago

The solution is to define the staff sizes using gap units - see point 2 in #185 (comment) above. ... Nobody has commented yet on this proposal. What do you think?

MEI has vu (virtual unit) measurements, which are defined as "half the distance between the vertical center point of a staff line and that of an adjacent staff line."

Making it half of a staff height instead of a whole means that you're more likely to be working with integers, since there are a number of measurements and placements that use 1/2 height as a unit (such as the default placement of a slur end point below a note head).

Verovio uses this extensively to provide even scaling.

notator commented 3 years ago

@ahankinson Thanks for that. The most important things are that

  1. we agree that some kind of virtual unit must exist, and that
  2. we understand how it is going to be used.

How big it is is a matter of taste and convenience. (My gap would be twice as big as a vu.) Personally, I find it easier to visualize the distances I want to stipulate in terms of the whole "distance between the vertical center point of a staff line and that of an adjacent staff line.". I don't think that the distance "gap/2" has anything special about it. There are lots of places where other fractions are required: the size of small staves or font heights, for example.

Note that this topic is related to both <score> and <part> elements.

clnoel commented 3 years ago

@notator (And others, I'd love to hear other opinions rather than just have a back-and-forth debate!)

Ex. 1, the definitions: That would:

  • be simpler (we don't need to define a new <sequence> element),
  • a bit more flexible (we can print separate booklets for bass1 and bass2 if we want to)
  • lead to more robust code (<sequence> elements are hidden inside <part> elements.)

I disagree with your proposal for mostly-similar sub-parts.

First, the sequence element already exists. It's the mandatory level between measure and event. And as I look at it, it already has a voice attribute that does what I'm picturing my sequence-id attribute doing. We might want to change the name of that attribute (in order to avoid confusion with the voice-layout element), but it certainly simpler to use the already existing element and attribute than define a whole new structure to avoid duplicating the information for parts that are mostly alike. We do have to define a <sequence-layout> element, which might be what you meant.

Second, it doesn't take much to make it possible to make a bass1 and bass2 booklet. If I add a mode to it, then in any case in which the bass1 sequence exists, we only include it, not the rest of the parts in that voice. We could make this be "alone" (write just this sequence, not any others that happen to coincide with it), and "exclude" (meaning write all other sequence parts and not this one). There might be other options we want.

<system-layout id="bass1">
    <staff-layout>
        <voice-layout stem="default">
            <part-layout id="bass"/>
            <sequence-layout id="bass1" mode="alone"/>
        </voice-layout>
    </staff-layout>
</system-layout>

Third, I'm not sure what the downside of having a sequence inside part being specifically layout-able in the system layout. Maybe this is because you thought sequence is new?


Ex. 2, the "conductor" Can you confirm that we now agree that tags can be omitted in elements that only contain one ? Is that "can be omitted" or "must be omitted"? My preference would be for tolerance here: I'd go for "can".

I can confirm this. And I also go for "can" here. One way is easier to hand-code. The other is probably easier to machine-code.

I don't think we need the "default" item in your stem direction enumeration.

Basses: If there are both bass1 and bass2 parts, then both of these have to be assigned to the somehow.

In my system, if you have assigned "bass" to a voice or staff, then you have by default assigned all of its sequences to that staff. There was no mistake in what I wrote, except that I would add mode="alone" to the bass1 sequence layout now that I've invented that.

The only time you need to list the sequence-layouts explicitly is if you (a) are not using default stemming and the rhythms are different, or (b) you need to move one or more sequences to another staff temporarily. I think our fundamental issue here is that I didn't actually write out the bass part I was picturing. The "bass1" and "bass2" sequences do not exist for the whole piece, or they should indeed be separate parts. The sequence-layout only takes effect for those portions of the piece for which a sequence with the correct id is defined, and so therefore the "parent" part needs to also be in the layout, unless that layout will only ever be used for the portion of the piece where the sequence exists.

I approve of the minimum-noteheads attribute.


A note about size dimensions:

Size dimensions are out-of-scope (C), unless you are trying to make a case for why it is in-scope. If so, don't debate the internals, but rather the inseparableness of sizing from grouping.

Unless I hear otherwise, I'll be making new issues for B, C, D, E, 6, and 7 Thursday, after the TPAC meeting. (In case something there changes the list of out-of-scope issues).

--Christina

joeberkovitz commented 3 years ago

A few quick comments here after rereading everything.

clnoel commented 3 years ago

As you guys can see, I've made issues for our out-of-scope topics. #246 is for (B), #247 is for (C), #248 is for (D), #249 is for (E) and (6), and #250 is for (7).


@joeberkovitz I can get behind the name changes if we go for my proposal there.

However, I'm not sure I agree with putting stem direction overrides in the part-layout. I deliberately avoided that in my examples because I didn't like putting it there and being able to specify it in both the staff-voice-layout and the part-layout if they are both listed.

clnoel commented 3 years ago

Here we go with an attempt at (2): Clef changes in a layout

Here's the issue. What if we want to represent both of the following SATB scores in one mnx document. No, problem, you say. They're just the same notes. However, in one score, the tenors are in an 8vb G clef, and in the other they are in an F clef. Hmm...

image Image above is probably copyrighted and copied from https://musicnotesbox.com/rollo-dilworth-joshua-fit-the-battle-of-jericho-115741/

image Image above made by me in Noteflight to match the previous image except in system layout

(I'm experimenting with the details markdown tag to reduce post length. I'm not sure how that's going to translate into emails, If you need this to work in an email and it doesn't, let me know, please, and I'll try something else.)

First, an encoding choice. I'm deciding to represent the score as 4 parts, and put the two soprano parts in named sequences when they exist. Depending on how the rest of the piece went, it might be better to truly make a Soprano 1 and Soprano 2 part. But I'm assuming that these two measures are the only place where they split. Similarly for Bass 1 and Bass 2.

Global and Parts description ``` ```

Now for the layouts. First, the 4-staff one. Please note that here, I'm conceding/accepting adding stemming to the part-layout. This allows for sequences to be stemmed together.

<system-layout id="FourStaff">
    <group-layout symbol="bracket">
        <staff-layout>
            <part-layout id="soprano" stem="float" minimal-noteheads="yes"/>
        </staff-layout>
        <staff-layout>
            <part-layout id="alto"/>
        </staff-layout>
        <staff-layout>
            <part-layout id="tenor"/>
        </staff-layout>
        <staff-layout>
            <part-layout id="bass" stem="float" minimal-noteheads="yes"/>
        </staff-layout>
    </group-layout>
</system-layout>

Here's a theoretical additional layout for use in the four-staff case when the rhythms for soprano1/soprano2 and bass1/bass2 are different, so the sequences need to be stemmed opposed to each other. Note that here, I'm accepting the idea from @joeberkovitz that the voice-layout element should be applied to the sequences, not the the groups of parts.

<system-layout id="FourStaffOpposed">
    <group-layout symbol="bracket">
        <staff-layout>    
            <voice-layout id="soprano1" stem="up"/>
            <voice-layout id="soprano2" stem="down"/>
        </staff-layout>
        <staff-layout>
            <part-layout id="alto"/>
        </staff-layout>
        <staff-layout>
            <part-layout id="tenor"/>
        </staff-layout>
        <staff-layout>
            <voice-layout id="bass1" stem="up"/>
            <voice-layout id="bass2" stem="down"/>
        </staff-layout>
    </group-layout>
</system-layout>

And the 2-staff one. Here, I'm renaming the layout for groups of parts/voices to stemming-layout, which I like better than @joeberkovitz's proposed staff-voice-layout, as it makes clear the primary purpose of the element is to group parts on the same stem. It also shows why I feel the clef element must be allowed in the staff-layout. Note, please, that I don't consider this a solution to the transposed-pitch part/concert-pitch score issue (out of scope (7), #250), just this one that does not require respelling.

<system-layout id="FourStaff">
    <group-layout symbol="brace">
        <staff-layout>
            <stemming-layout stem="float" minimal-noteheads="yes">
                <part-layout id="soprano"/>        
                <part-layout id="alto"/>
            </stemming-layout>
        </staff-layout>
        <staff-layout>
            <clef sign="F" line="4"/>
            <stemming-layout stem="float" minimal-noteheads="yes">
                <part-layout id="tenor"/>        
                <part-layout id="bass"/>
            </stemming-layout>
        </staff-layout>
    </group-layout>
</system-layout>

There are other issues in this example that are out-of-scope. In particular, I'm going to post this on #246 so we can discuss the "div" directions. Also, on the issue of making a "booklet" for the split parts:

<system-layout id="Soprano1">
    <staff-layout>
        <part-layout id="soprano"/>
        <voice-layout id="soprano1" mode="exclusive"/>        
    </staff-layout>
</system-layout>

<system-layout id="Soprano2">
    <staff-layout>
        <part-layout id="soprano"/>
        <voice-layout id="soprano2" mode="exclusive"/>        
    </staff-layout>
</system-layout>

<system-layout id="AltoSoprano">
    <staff-layout>
        <part-layout id="alto"/>
        <voice-layout id="soprano2" mode="exclusive"/>
    </staff-layout>
</system-layout>

In these cases, we get the Soprano1 part and the Soprano2 part as written, and even the possibility of an Alto/Soprano2 part where someone who usually sings Alto switches to Soprano2 when it exists, which would not be possible if we encoded Soprano2 as it's own part.

Thoughts?

cecilios commented 3 years ago

Allowing to define the clef in the staff-layout is a partial solution, only valid when the clef does not change along a system. It doesn't allow to deal with intermediate clef changes for one of the voices. Also, it looks ugly for my taste.

What if we add an attribute to <clef>, e.g.: <clef layouts="Soprano1 Soprano2">, to restrict the element to be meaningful only when any of the referenced layouts are used?. In your example, this would require to define a clef for each layout. e.g.:

<part>
    <measure>
        <directions>
            <clef sign="G" line="2" octave="-1" layouts="lay1 lay2"/>
            <clef sign="F" line="4" layouts="lay3"/>
        </directions>

This solution can, perhaps, be extended to other elements requiring this.

clnoel commented 3 years ago

Hmm... You are right, in a way, @cecilios

Under my solution, mid-system clef changes defined in a part would be ignored in any layout that has a clef specified in it. (Of course, the clef is optional, so the default behavior is to respect the clef changes in the part.) I appreciate the alternate idea, but I dislike the mixing of layout information into the semantic part elements.

However, I think that a tweak involving mid-system layout changes can apply a layout-specific clef change:

<system-layout id="FourStaff">
    <group-layout symbol="brace">
        <staff-layout>
            <stemming-layout stem="float" minimal-noteheads="yes">
                <part-layout id="soprano"/>        
                <part-layout id="alto"/>
            </stemming-layout>
        </staff-layout>
        <staff-layout>
            <clef sign="F" line="4"/>
            <stemming-layout stem="float" minimal-noteheads="yes">
                <part-layout id="tenor"/>        
                <part-layout id="bass"/>
            </stemming-layout>
        </staff-layout>
    </group-layout>
</system-layout>
<system-layout id="FourStaffClefChange">
    <group-layout symbol="brace">
        <staff-layout>
            <stemming-layout stem="float" minimal-noteheads="yes">
                <part-layout id="soprano"/>        
                <part-layout id="alto"/>
            </stemming-layout>
        </staff-layout>
        <staff-layout>
            <clef sign="G" octave="-1" line="2"/>
            <stemming-layout stem="float" minimal-noteheads="yes">
                <part-layout id="tenor"/>        
                <part-layout id="bass"/>
            </stemming-layout>
        </staff-layout>
    </group-layout>
</system-layout>

<score>
    <page>
        <system measure="1" layout="FourStaff">
            <system-layout-change location="4" layout="FourStaffClefChange"/>
        </system>
        <system measure="6" layout="FourStaffClefChange"/>
        <system measure="10" layout="FourStaff"/>
    </page>
</score>

As you can see, this makes the clef change possible, both as a mid-system clef change (at measure 4) and as a clef change that happens at a system break (at measure 10).

--Christina

cecilios commented 3 years ago

@clnoel Yes, that second approach is a possibility to solve the intermediate clef change issue.

But in both cases, your proposals and my proposal, we are mixing layout information with music content.

I do not know how styles will be defined and used in MNX, but attributes to define style is the same idea that defining applicability of the element when certain layout is used, e.g. visibility attribute.

To me your solution looks more complex, but certainly has the advantage of preserving the music content for consumer applications not using the <score> layouts part or for music analysis.

joeberkovitz commented 3 years ago

Let me throw out a few thoughts on this so far, some large and some small.

While it's desirable to partition layout info into a separate <score> element, that doesn't mean that there can't be elements in <part> that relate to layout. @cecilios suggestion about encoding clefs that are specific to certain layouts is one example. What's perhaps not so great though, is to allow two-way references between layouts and music content, where layout elements refer to music content IDs and music content refers to layout IDs. That becomes very messy and hard to validate.

I wonder if something analogous to the HTML/CSS class= attribute would help out here: an arbitrary label slapped onto semantic content, that layouts can refer to, e.g.

<part>
    <measure>
        <directions>
            <clef sign="G" line="2" octave="-1" class="reduced"/>
            <clef sign="F" line="4" layouts="expanded"/>
        </directions>

and elsewhere, one or more part layouts that indicates what classes are being selected for use in a layout:

        <part-layout part="soprano" class="reduced">

This is a crude proposal and has holes but hopefully conveys the idea: classes are a neutral set of IDs that serve to connect any number of layouts with any number of semantic elements, without everything referring to everything else.

clnoel commented 3 years ago

Oh, wow, ok. I'm going to copy the proposals by @joeberkovitz and @cecilios to #246, which is for how to deal with directions on these layouts. I think that that same solution just proposed can be used for directions in general, not just clefs. So clefs might now be out of scope for this discussion. I forgot that in MNX, clefs are a "direction" and might not need to be handled differently than the difference between needing "div" on the "expanded score" and "Sop. div." on the reduced score. If everyone's okay with that, I'd like to declare clefs out-of-scope for this topic and move the discussion over there.


Topic update: Unless there are strenuous objections, in-scope for this issue are (numbers and letters are from https://github.com/w3c/mnx/issues/185#issuecomment-948018127 (A) How to represent a grand staff in a layout: Currently, I believe @notator's <grand-staff-layout> element, a child of <system-layout>, (and also <group-layout>?) is winning there. (1) How to group stems: Currently, I believe an element called <stemming-layout>, a child of <staff-layout>, is winning, with the possible addition of <voice-layout> which references sequences, and which might a child or a sibling of <part-layout> (4) Reusable layouts: Nobody seems to have objected to putting id's on the various child -layout elements in order to reuse them in different system layouts. (5) Mid-system layout changes: There is an element named either <mid-system-layout> or <system-layout-change> that can reference a system-layout that starts at a certain measure location. This is a child element of <system>. All other topics have been relegated to other issues or dropped entirely.


I think we might almost have consensus here.

notator commented 3 years ago

Thanks @clnoel, for the above update.

Contrary to my previous position, I now think grand staff objects should, after all, be coded as <group-layout>s. Sorry about the confusion. Note that, as per (4) above, grand staves with two and three staves can be predefined and referenced by id in different <system-layout>s:

    // piano grand staff with two staves
    <group-layout labelref="piano" part="piano" symbol="brace" id="grandStaff2layout">
         <staff-layout>
            <part-layout part="piano" staff="1"/>
         </staff-layout>
         <staff-layout>
            <part-layout part="piano" staff="2"/>
         </staff-layout>
    </group-layout>

    // piano grand staff with three staves
    <group-layout labelref="piano" part="piano" symbol="brace" id="grandStaff3Layout">
        <staff-layout>
            <part-layout part="piano" staff="1"/>
         </staff-layout>
         <staff-layout>
            <part-layout part="piano" staff="2"/>
         </staff-layout>
         <staff-layout>
            <part-layout part="piano" staff="3"/>
         </staff-layout>
    </group-layout>

    <system-layout id="systemLayout1">
        ...
        <group-layout  layout="grandStaff2Layout" />
   </system-layout>

    <system-layout id="systemLayout2">
        ...
        <group-layout  layout="grandStaff3Layout" />
   </system-layout>

Possibly, <part-layout>'s staff attribute could be better named as part-staff since it references something defined inside the part. See part-voice below.


I prefer <voice-layout> over <staff-voice-layout>, and <staff-voice-layout> over <stemming-layout>, for the reasons @joeberkovitz gives.

As I understand it, @joeberkovitz is suggesting that a <voice-layout> should be nested inside <part-layout>, and @clnoel is suggesting that we add identifiers to sequences of sequences (=voices). I think there's a simpler way to solve the problem: A <part> can be parsed as a ragged array: part[measure][voice][sequence]. If a <sequence> is missing at a particular address, then that voice has an empty measure at that point. In other words, we can retrieve all the sequences for a particular voice simply by indexing in the array. We don't need a voice identifier to do that. We can just do:

    <staff-layout>
        <part-layout part="soprano" part-voice="1"/>
    </staff-layout>

or

    <staff-layout>
        <staff-voice-layout  stem="up"  minimum-noteheads="yes">
            <part-layout part="soprano" part-voice="1"/>
            <part-layout part="soprano" part-voice="2"/>
        </staff-voice-layout>
        <staff-voice-layout  stem="down" minimum-noteheads="yes">
            <part-layout part="soprano" part-voice="3"/>
            <part-layout part="alto" part-voice="1"/>
        </staff-voice-layout>
    </staff-layout>

or (using <voice-layout> instead of<staff-voice-layout>)

    <staff-layout>
        <voice-layout  stem="up"  minimum-noteheads="yes">
            <part-layout part="soprano" part-voice="1"/>
            <part-layout part="soprano" part-voice="2"/>
        </voice-layout>
        <voice-layout  stem="down" minimum-noteheads="yes">
            <part-layout part="soprano" part-voice="3"/>
            <part-layout part="alto" part-voice="1"/>
        </voice-layout>
    </staff-layout>

As I said, I prefer <voice-layout> to <staff-voice-layout>. Using <staff-voice-layout> means that I have to look twice to see how many staves we are talking about. Obviously, a <voice-layout> nested directly inside a <staff-layout> describes a staff's voice (layout).

This "scopes" the voices inside particular parts: The indices begin at 1 inside each part. And I don't think we should add any further info to the part-voice here (we are just referencing it), so it should not be made into an enclosed element.

This strategy is very similar to the proposals for

(But I don't think we need to add an explicit voice attribute to <sequence>.)


Contrary to my tentative agreement to making <score> objects optional in MNX files, I now think my original position was correct, and that they should be compulsory. This means that a <score> element needs to be added to each example in the current docs. That would be very easy to do: just measure the existing diagrams, and add the corresponding <score> elements. All the information is there in the graphics, it just hasn't made it into the code. I'm very willing to help with the housekeeping.


<system-layout-change> is a more accurate name for <mid-system-layout>, so that's what I'd prefer. Note that this element has a location attribute, not a measure attribute. Measure location's Regex pattern is not yet defined in the docs. The algorithm in the original Draft Spec says that a Measure location consists of:

    EITHER
    {
        an optional (measure number followed by a ':' character) followed by
        EITHER
        {
            a decimal floating-point number indicating the positive number
            of whole-notes after the start of the measure
        }
        OR
        { 
            a multiple note value (2/4, 3/8, 4/2 6/1d 4*4 etc.
        }
    }
    OR
    {
        an eventID (an alphanumeric string, beginning with a letter).
        Should this really begin with a '#' character?
        All other possible measure locations begin with a number.
    }

The original Draft Spec gives the following examples: measureLocationSyntaxExamples

My original attempt at a Regex isn't good enough. I can have another crack at it, but maybe someone else would like to have a go? :-)


I think MNX should include a top-level <style> element as in HTML and SVG:

<mnx>

    // Is type="text/css" correct here?
    // All measurements are in (floating point) gaps (dimensionless numbers)
    <style type="text/css"> 
        .fullScore
        {
            width: 2280;
            height: 2765;
            margins: 148 145 148 356;
            gap: 20
        }

        .oboe1Part
        {
            width: 2200;
            height: 373;
            margins: 159 76 135 272;
            gap: 20
        }

        .multi-rest
        {
            font-face: Arial ;
            height: 2.3;   // gaps (I prefer height to font-height here)
            bottom: -0.25  // gaps above the top of staff
            // ... etc.
        }
        // etc. more styles
    </style>

    <global>...</global>

    <part>...<part>
    <part id="ob1">...<part>
    // etc. more parts

    <score name="FullScore" class="fullScore" >...</score>

    /*********************/

    // Oboe 1 system
    <system-layout id="Oboe1SystemLayout">
        <part-layout part="ob1" label="Oboe 1"/> // I've omitted the redundant <staff-layout> here (okay?)
    </system-layout>

    <score  name="Oboe1PartBooklet" class="oboe1Part" >
        <page>
            <system  layout="Oboe1SystemLayout" measure="1" >
                <multi-measure-rest measure="6" label="2" class="multi-rest" />
                <multi-measure-rest measure="8" label="6" class="multi-rest" />
                <multi-measure-rest measure="14" label="3" class="multi-rest" />
            </system>
        </page>
    </score>

Ob1SmallFramed The frame around this example is just to show where the edges of the page are. Its not part of the example itself.

cecilios commented 3 years ago

If <style> is added just to specify sizes and margins, it would be simpler to use the the xml syntax instead of introducing a different syntax (css). No need for more complexity in parsers just for this.

clnoel commented 3 years ago

In response to @notator :

Re grand staff: Fine, let's use <group-layout> with the addition of a staff or part-staff attribute on the <part-layout>. I don't really have a stake in that game. Plus, our code is out dated and has trouble rendering three-staff grand staves anyway, and using group-layout will give us a better way to fake it.

A <part> can be parsed as a ragged array: part[measure][voice][sequence]. If a <sequence> is missing at a particular address, then that voice has an empty measure at that point. In other words, we can retrieve all the sequences for a particular voice simply by indexing in the array.

This is incorrect by the current MNX spec. there is no voice element: image Unless you are proposing to add such a voice element, the rest of your argument about this is invalid due to an invalid premise. Right now the only way to connect to sequences in different measures is through the use of the sequence's voice attribute (which already exists).

Re optional <score>: I believe you are still outvoted on this one. Not all programs producing an MNX document are geared toward pages, or even graphics at all. A program might represent the score as an infinite horizontal scroll, or not care about layout at all because it is creating MNX documents from audio.

Re system layout change: I think we are in agreement here. I don't currently care about the involved definition of a measure-location, but the system layout change has to be able to happen mid-measure.

Re style: I would prefer to have each individual score declare the size of paper or image they are designed to be displayed on. I feel like that is a more direct method of doing what you are trying to do here. However, this sizing conversation belongs in #247, not here, as it is not part of "how to group parts".

joeberkovitz commented 3 years ago

@cecilios There's no suggestion here to introduce CSS syntax (that's an old debate that is over now :). All I'm suggesting is that CSS offers two structural ideas that can help here: inline styles that decorate semantic elements, and class names that classify semantic elements which are to be styled the same (but whose actual styling is specified elsewhere).

@clnoel +1 on all your comments immediately above.

cecilios commented 3 years ago

@joeberkovitz Sorry for the misunderstanding. My comment referred to @notator s idea of expressing size using a <style > element with CSS syntax, not to your previous comment :)