w3c / mnx

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

Implement <system-layout> and associated ways to specify page/line breaks #245

Closed adrianholovaty closed 3 years ago

adrianholovaty commented 3 years ago

This branch changes the documentation to add support for <system-layout> and related elements/attributes. See #57 for discussion, specifically this comment:

https://github.com/w3c/mnx/issues/57#issuecomment-891916447

This includes one new example, which you can view here (this is taken directly from the code in this branch):

https://cdn.githubraw.com/w3c/mnx/system-layouts/docs/mnx-reference/examples/system-layouts/

Here's the documentation on the new <system-layout> element:

https://cdn.githubraw.com/w3c/mnx/system-layouts/docs/mnx-reference/elements/system-layout/

notator commented 3 years ago

As I pointed out in https://github.com/w3c/mnx/issues/57#issuecomment-892681094, this code means that the piano part always has to be notated on 2 staves. There is no way to define a <system-layout> in which the piano part is notated on three or more staves. That's obviously unrealistic: There are lots of scores in which the number of staves changes per system in a piano part.

So I think we need more discussion, and to reach a consensus in CG, before this pull request can be accepted.

adrianholovaty commented 3 years ago

@notator For piano (or other parts that use multiple staves), you would use the staves attribute on the <part>. This is the same approach that's worked well for MusicXML, and it's necessary because each note/rest needs to be able to assign itself to a stave.

notator commented 3 years ago

The staves attribute on the <part> element is fixed, so there's no way to describe a 3-staff grand staff for the piano, given that all the piano's music for the score is defined inside its one <part> element.

In MNX, <part> elements are independent of the way their content is distributed across systems, so notes and rests have to be assignable to particular staves inside the <part> definition without fixing the number of staves in the part at any one time (see #219 and its history). That's good because the number of measures per system can be different in scores having different page formats. But its an advance on the way MusicXML does things, so we can't use a MusicXML-like solution.

Maybe we have to agree on #219 before proceeding, but even if we don't do that, other, rather complex issues arise if we start trying to patch this pull request. I think it would be quicker/better to go back to my original proposal in issue #185 (which has not yet been discussed). In particular, I don't think there's any way to avoid defining the low-level group types:

  • <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)
adrianholovaty commented 3 years ago

@notator Thanks for going into more detail. Now I understand your point — that this proposal doesn't support the case of a <part> that has multiple staves, where some of the staves are hidden in certain systems. That's the main issue, right?

That is a great point, and relatedly I'm also starting to second-guess the approach of treating a grand staff with a single <staff>, as in the example. It seems slightly confusing to shove two staves (as in a piano grand staff) into a single <staff> element.

In the @notator proposal here, there are separate <partStaff> and <partStaves> elements, but I find that equally confusing. Shouldn't every visible staff correspond to one (and only one) <staff> element?

With that in mind, here is a small tweak to this pull request's proposal. The parts attribute of <staff> can now reference a specific staff index from the part. So this example would be encoded thusly:

<mnx>
   <global/>
   <part id="fl1" name="Flute 1" short-name="1"/>
   <part id="fl2" name="Flute 2" short-name="2"/>
   <part id="fl3" name="Flute 3" short-name="3"/>
   <part id="ob1" name="Oboe 1" short-name="1"/>
   <part id="ob2" name="Oboe 2" short-name="2"/>
   <part id="piano" name="Piano" staves="2"/>
   <system-layout id="fullscorelayout1">
      <staff-group symbol="bracket">
         <staff-group symbol="brace" label="Flutes">
            <staff parts="fl1 fl2" labelref="short-name"/>
            <staff parts="fl3" labelref="short-name"/>
         </staff-group>
         <staff parts="ob1 ob2" label="Oboes" labelref="short-name"/>
      </staff-group>
      <staff-group symbol="brace" label="Piano">
         <staff parts="piano:1"/>
         <staff parts="piano:2"/>
      </staff-group>
   </system-layout>
   <system-layout id="fullscorelayout2">
      <staff-group symbol="bracket">
         <staff-group symbol="brace" label="Fl.">
            <staff parts="fl1" labelref="short-name"/>
            <staff parts="fl2" labelref="short-name"/>
            <staff parts="fl3" labelref="short-name"/>
         </staff-group>
         <staff parts="ob1 ob2" name="Ob." labelref="short-name"/>
      </staff-group>
      <staff-group symbol="brace" label="Piano">
         <staff parts="piano:1"/>
         <staff parts="piano:2"/>
      </staff-group>
   </system-layout>
   <score name="Full score">
      <page>
         <system measure="1" layout="fullscorelayout1"/>
         <system measure="4" layout="fullscorelayout2"/>
      </page>
   </score>
</mnx>

Within <system-layout>, every visible five-line staff would correspond to one (and only one) <staff> element. Previously grand-staff elements were special-cased and treated as a single <staff>.

In order to make this possible, a <staff> element's parts attribute would allow for specifying particular indexes of the part's staves. So: <staff parts="piano:1"> means "use the first staff from the piano part.

The only thing I don't like about this is that it's a bit verbose for the common case of grand-staff piano parts. But it's not the end of the world, and the flexibility of hiding particular staves on a per-system basis is likely worth it.

Thoughts?

joeberkovitz commented 3 years ago

I think @adrianholovaty has an elegant proposal. The alternative one from @notator encodes the information just as effectively, but I didn't understand the need for a special <partStaves> element, as opposed to the equivalent of a <partStaffGroup> with nested <partStaff> elements referencing specific staves within the part (I'm using @notator's naming scheme here, but that is essentially what @adrianholovaty suggested). It seems like the attribute signature of a <partStaves> would be identical to <partStaffGroup> IIRC.

Also confusing to me was the need for separate <partGroupStaff> and <partStaff>, which appear to be the same except that the former references more than one part. @adrianholovaty simplifies this by letting a staff's part references be 1:N instead of 1:1 which seems more natural than having two differently named elements (again with the same attribute signature).

The verbosity of encoding a simple grand-staff piano part could be addressed by allowing an optional part= attribute in the <staff-group> element, mapping all the staves in the part into the staff group without the need to identify them. This has the virtue of not requiring multiple elements in the document to be aware of the default number of staves in the part.

However...

For the case where multiple parts are mapped to a single staff, I wonder where information lives about styling the mapping of each part. For instance, in this example Flute 1 has stems up and Flute 2 has stems down. Sure, this could be styled note-by-note, but is there a need to specify common styles that apply to all the notes in some staff which are mapped from some part? I could easily imagine parts in a reduction having distinct colors in a music theory text, for example.

ahankinson commented 3 years ago

You would need an MNX-specific processor to handle the XML lookups, since there are no elements with the piano:1 ID. This means that you couldn’t find the corresponding part from a staff For the piano using an xpath query, for example, while you could for the other instruments.

notator commented 3 years ago

@adrianholovaty said:

The parts attribute of <staff> can now reference a specific staff index from the part.

219 also shows how <part><sequence> elements can reference a specific staff index, so its a working alternative to the use of "piano:1" and "piano:2". #219 is also the result of earlier discussion, so its likely to fit better with the rest of MNX. Apart from the problems @ahankinson mentions, there are other problems with trying to treat a grand staff as a simple <staffGroup>. The best way to explain those is to clarify my proposal for having different staff types.

First, I'd like to do some refactoring: I obviously had "part" uppermost in my mind when choosing the original names, but using permutations of the words "part", "group" and "staff" is obviously confusing. I now have:

Maybe the names could be improved again, but I think that's just a question of comprehensibility, not function. Any suggestions? Note that a simple score for voice and keyboard (like our Fauré example) would then need only one <system-layout> definition, and that that definition would just contain a <staff> and a <grandStaff>.

The main reason I think the "staff" types need to be defined as separate elements is that it makes them simpler and easier to define. An ordinary <staff>, containing info from one <part>, could be defined more efficiently if it didn't have to deal with the complications associated with the other "staff" types. A <sharedStaff>, for example, needs to be able to describe how the different <part> information is distributed vertically. How, for example, do we say that two different parts are written as chords on the same stem? Should MNX common1900 only allow <sharedStaff> elements to have a maximum of one stem up and one stem down? The point here is that these questions (and their answers) are specific to <sharedStaff> elements, and need not concern the other "staff" types. A <grandStaff> needs to allow voices to cross its internal staves, and a way to describe how any of the staves inside the <grandStaff> can contain more than one voice. I think the strategy described in #219 and <grandStaff nStaves=... ...> is the best way to do that. Also, a <grandStaff> has special ways of dealing with brackets and barlines that is different from both the other "staff" elements and from <staffGroup>. Here again, the point is that these problems (and their answers) are specific to a particular "staff" type. Using a <staffGroup> to describe a <grandStaff> is therefore not a good idea.


Further thoughts:

  1. I think it should be made clear, in any examples in the documentation, where an element's content has been omitted. So, in the above example, <global/> should be written as <global>...</global>. Similarly for any other omitted info (e.g. the contents of <part> elements or the missing <score> and <page> attributes).
  2. In the above example, the <system-layout> id attributes should be named systemlayoutX, not fullscorelayoutX. These names should also be corrected in the <page> definition at the bottom of the example.
  3. The <score> element in the above example should reference a <score-layout> whose ID is fullscorelayout. That allows different <score>s (full-score and parts) to be defined with the same <part> information (as in my original proposal). As I remember, that was one of the main reasons for developing MNX in the first place.
  4. My proposal also includes the definition of <instrumentType>s (in <global>). These are an efficient way to describe naming. I think we need to discuss, and agree on, how naming should work. Its an important part of what goes on in the left margin. I could be wrong, but it seems to me that we are missing something if related instruments are given unrelated names. See "Naming" in https://github.com/w3c/mnx/issues/185#issuecomment-780403076
  5. See also the "Known Issues" mentioned in https://github.com/w3c/mnx/issues/185#issuecomment-780403076
  6. We should be careful not to assume that staves will always have five lines.
  7. Two questions of style:
    • I'm using camel case for element and attribute names, but that's only because I find them easier to read and type. My practice is also consistent with the Google XML Document Format Style Guide, which I expect to become the most widely used XML style on the web. I think it would be better in the long run, if MNX complied with this standard rather than MusicXML's (2000?) use of hyphen-separated names. But I don't think the decision to use one style or the other is absolutely crucial...
    • While I agree that using '#' characters to flag ID names in attributes is ultimately not necessary, I want to continue to do so while discussing XML code here because it adds information to the code that makes it easier to understand. I simply find it easier to understand things if attribute values are clearly marked as IDs.
adrianholovaty commented 3 years ago

@joeberkovitz: Thanks for the feedback, and nice to see you active here again!

@ahankinson: Yes, that's true about needing custom code for this "microsyntax." Frankly I don't think it's realistic to expect MNX to be able to be converted into other formats using xpath alone. Do you have a specific concern about this or were you just pointing it out?

@notator: Thanks, but I think you are confusing the concepts of "a rendered staff can specify which parts go on it" and "a note knows which staff it lives on." More on this below (I think we need to clarify it and use separate terminology). The general approach in #219 seems sound to me, but that's a different piece of the puzzle — it addresses how sequences/events are assigned to a staff in a semantic fashion, whereas this pull request addresses specific visual layouts of that semantic data (e.g., allowing certain parts to be combined in the same staff).

At any rate, here's a tweak to my previous comment, based on all of your thoughts. This introduces a new <staff-part> element within <staff>, which saves us from having to use a microsyntax (to Andrew's point) and also provides a hook for future styling (to Joe's second point). The <staff-part> element can optionally specify which staff of the underlying <part> gets included (via the poorly named fromstaff attribute).

<mnx>
   <global/>
   <part id="fl1" name="Flute 1" short-name="1"/>
   <part id="fl2" name="Flute 2" short-name="2"/>
   <part id="fl3" name="Flute 3" short-name="3"/>
   <part id="ob1" name="Oboe 1" short-name="1"/>
   <part id="ob2" name="Oboe 2" short-name="2"/>
   <part id="piano" name="Piano" staves="2"/>
   <system-layout id="fullscorelayout1">
      <staff-group symbol="bracket">
         <staff-group symbol="brace" label="Flutes">
            <staff labelref="short-name">
               <staff-part part="fl1"/>
               <staff-part part="fl2"/>
            </staff>
            <staff labelref="short-name">
               <staff-part part="fl3"/>
            </staff>
         </staff-group>
         <staff label="Oboes" labelref="short-name">
            <staff-part part="ob1"/>
            <staff-part part="ob2"/>
         </staff>
      </staff-group>
      <staff-group symbol="brace" label="Piano">
         <staff>
            <staff-part part="piano" fromstaff="1"/>
         </staff>
         <staff>
            <staff-part part="piano" fromstaff="2"/>
         </staff>
      </staff-group>
   </system-layout>
   <system-layout id="fullscorelayout2">
      <staff-group symbol="bracket">
         <staff-group symbol="brace" label="Fl.">
            <staff labelref="short-name">
               <staff-part part="fl1"/>
            </staff>
            <staff labelref="short-name">
               <staff-part part="fl2"/>
            </staff>
            <staff labelref="short-name">
               <staff-part part="fl3"/>
            </staff>
         </staff-group>
         <staff name="Ob." labelref="short-name">
            <staff-part part="ob1"/>
            <staff-part part="ob2"/>
         </staff>
      </staff-group>
      <staff-group symbol="brace" label="Piano">
         <staff>
            <staff-part part="piano" fromstaff="1"/>
         </staff>
         <staff>
            <staff-part part="piano" fromstaff="2"/>
         </staff>
      </staff-group>
   </system-layout>
   <score name="Full score">
      <page>
         <system measure="1" layout="fullscorelayout1"/>
         <system measure="4" layout="fullscorelayout2"/>
      </page>
   </score>
</mnx>

It's more verbose but has the (big?) advantage that the concept of "a given meta-staff of a given part in a given visual staff" has a distinct XML element, <staff-part>, to which we could then attach more metadata. The previous approach with a parts attribute on <staff> was nice and compact but wouldn't have a natural place for that extra metadata.

Separately, the conversation is getting a bit abstract — so, if possible, I'd also like to find two distinct terms for these two distinct concepts:

Thoughts/ideas on any of the above?

ahankinson commented 3 years ago

Xpath can be used, for example, in a browser to traverse a DOM. This can be handy if you have a JavaScript component and want to process some XML. Verovio uses xpath statements, for example, to help extract and render selections from an MEI document. You could imagine the same used here: Given a full score, extract and pass just a selection of the XML (e.g., a single instrumental part) to a renderer.

notator commented 3 years ago

I can see how Xpath could be used to extract the data relating to a single part from a full score (that would be very easy in MNX), but think it would be impossible for a renderer to format that information properly to create an instrumental part. In particular, deciding where the system breaks are supposed to happen requires information that is not in the full score. Maybe I'm not understanding something?

cecilios commented 3 years ago

@joeberkovitz: Glad to see you here again! I value very much your oppinions on music representation and MNX.

notator commented 3 years ago

I've just posted an update to my proposal in #185, incorporating the refactoring and further issues that have arisen in the above discussion. Hopefully, the new code listing there removes any confusion. Note that all the issues/questions mentioned in #185 also need to be answered for @adrianholovaty's proposal. For example, @joeberkovitz asks:

For the case where multiple parts are mapped to a single staff, I wonder where information lives about styling the mapping of each part. For instance, in this example Flute 1 has stems up and Flute 2 has stems down. Sure, this could be styled note-by-note, but is there a need to specify common styles that apply to all the notes in some staff which are mapped from some part? I could easily imagine parts in a reduction having distinct colors in a music theory text, for example.

I think different rules apply for stem directions, depending on how many parts there are on the staff. If there's only one <part> on the staff (as in a simple orchestral flute part-booklet), then any special stem-direction info could go (per <event>) in the <part>. But if multiple parts are mapped to a single staff (as in the full-score), then the staff has to be able to override the stem-direction info in the <part>. In other words, a <sharedStaff> should have control over the stems, and which <part>s are allocated to which stem. For simplicity here, I'd first like to consider restricting the number of "voices" in a <sharedStaff> to a maximum of two: If there's one voice, then its stem can flip according to the usual rules for chords. If there are two voices, then one has its stems up, and the other has its stems down. Each stem can have noteheads deriving from multiple <part>s. So we could have alternatives, maybe something like these:

  1. all parts written as 4-part chords on single flippable, stems (i.e. as one "voice")
    <sharedStaff parts="#fl1 #fl2 #fl3 #fl4" displayPartNumbers="true" />
  2. the parts distributed over two polyphonic "voices"
    <sharedStaff displayPartNumbers="true">
    <stemUp parts="#fl1 #fl2 #fl3">
    <stemDown parts="#fl4">
    </sharedStaff>

    It would be possible to have multiple <stemUp> or <stemDown> voices, but I'm not sure if that should be supported in MNX common1900.

@joeberkovitz: I'm not sure exactly what you mean about having colored parts in a music theory text, but a solution might be to define a <partColor> element that could optionally be put inside any of the elements that contain parts (e.g. the <score> element):

<score>
    <partColor part="#fl2" color="red" />
    ...
</score>

There's nothing to stop specialized <score> definitions being defined in the same file for music theory texts or any other purpose.

joeberkovitz commented 3 years ago

Per @notator's question here's a more detailed explanation of the staff layout styling issue I raised.

One design theme of MNX is the notion of a subset of attributes that define a visual object's rendering style. Wherever they are applicable, these attributes are consistent: they take the same form and have the same interpretation wherever they apply. For example, there is an orientation= attribute which applies to many elements and determines the up/down orientation of events, slurs, directions, and lots more. There is also a more specific stem-direction= attribute for <event>. And the color= attribute is used identically in <event>, <rest>, <note> and <part> (and probably should be usable in many other places too).

For starters, take note that this approach to styling is based on attribute subsets, not on elements. This is intentional, since it keeps the schema simple, supports expansion to additional attributes very easily, and stylistic attributes tend to take scalar values. Changing this approach to favor an element-based scheme with <stemUp> or <partColor> and such is probably best handled as a new issue with its own rationale and I won't take it up further here.

As @notator said, the issue with stem directions comes to the fore mostly in the case where a system layout "reduces" multiple parts to one staff, since the stem direction in the underlying <event> elements needs to be overridden somehow. If we have an explicit element for the inclusion of a part into a system layout staff, that provides a locus for the stem-direction= attribute, for instance:

   <system-layout id="fullscorelayout1">
         <staff-group symbol="brace" label="Flutes">
            <staff labelref="short-name">
               <staff-part part="flute1" stem-direction="up"/>
               <staff-part part="flute2" stem-direction="down"/>
            </staff>
      </staff-group>
   </system-layout>

Alternate example: an analysis of a big-band chart in which the entire trumpet section is reduced to one staff, but the second-trumpet part is being called out in black while the other parts are gray:

   <system-layout id="trumpetsection-em-2">
            <staff labelref="short-name">
               <staff-part part="tr1" color="gray"/>
               <staff-part part="tr2" color="black"/>
               <staff-part part="tr3" color="gray"/>
               <staff-part part="tr4" color="gray"/>
            </staff>
   </system-layout>
joeberkovitz commented 3 years ago

Separately, I think it might be a good idea to avoid using the name <staff> in this layout-related part of the schema, since we already have some notion of a semantic staff (as encoded in the staff= attribute of <event> for a multi-staff part).

Perhaps a consistent suffix of -layout wouldn't hurt here, to keep things unambiguous. So we'd get something like this nesting:

system-layout
  group-layout (optional)
    staff-layout
      staff-part-layout

With reference to @ahankinson's comment https://github.com/w3c/mnx/issues/185#issuecomment-931266356, this may argue against renaming <system-layout> to <staff-layout>, since we'd have separate layout elements for the system and staff level.

notator commented 3 years ago

@joeberkovitz As I said in my reply to @ahankinson, I think the naming issues are a bit of a red herring. I have no problem with using the same name in different contexts (namespaces) providing the intention is clear. You do it yourself with part in the above examples, but that doesn't mean we have to rename <part>!

I don't think my use of the <partColor> element should be dismissed too quickly. Its good programming practice not to duplicate the same information multiple times at a low level if it can be defined in one place further up in the hierarchy. Note that <partColor> also leverages MNX's peripatetic color attribute.

There's a deep problem, relating to the staff classes, that affects both my current proposal and the proposal in this PR: How do we code a staff that changes class in the middle of a measure? Here's a concrete example: The staff contains a single line of pitches played by 4 horns, but begins by being played by horn 3 alone. Somewhere, in the middle of a measure, the line begins to be played by all 4 horns (à 4). How does the renderer know that it should write "à 4", and not four noteheads per stem? The answer might entail one or more of the following options:

But I don't have enough time to work out a concrete proposal before tomorrow's deadline.

Extracting parts from a score is much easier than assembling a score from the parts...

adrianholovaty commented 3 years ago

There's a deep problem, relating to the staff classes, that affects both my current proposal and the proposal in this PR: How do we code a staff that changes class in the middle of a measure? Here's a concrete example: The staff contains a single line of pitches played by 4 horns, but begins by being played by horn 3 alone. Somewhere, in the middle of a measure, the line begins to be played by all 4 horns (à 4). How does the renderer know that it should write "à 4", and not four noteheads per stem?

That's an interesting one! My gut says we should put that off for a post-1.0 version of MNX, but I'm interested to hear @dspreadbury and @mdgood's takes on it. If we do put it off, we should at least design the infrastructure of elements to be extensible to support this in the future, and I think the most natural solution would be "staves that are not as wide as the system."

joeberkovitz commented 3 years ago

I agree with @notator that changing system layouts mid-system and mid-measure is an important issue, and it comes up a lot, especially post-1900. I also agree with @adrianholovaty that perhaps it doesn't have to affect the 1.0 design of layout classes. My gut sense is that it's best to use instances of the layout classes (i.e. <system> elements) to somehow specify measure subranges when needed — after all, that is where measure indices already come into play in defining the extent of a simple system with a unitary layout.

There is a related notational problem waiting for a solution: the inclusion of cue notes from other parts (cue notes themselves are recorded as https://github.com/w3c/mnx/issues/102, but this is inclusion by reference rather than as a list of explicit cue events). Staves including cue parts look a lot like our example of an instrumental section reduced to one staff, potentially with the need for stem direction and orientation overrides, etc. Perhaps there is a single solution for cue parts and for N:1 part-to-staff inclusion?

With the many possible ways of addressing this subrange problem, I don't want to jump in prematurely with suggestions; we probably need a new issue to be opened.

clnoel commented 3 years ago

If you want a concrete example of "grouping changes in the middle of a staff (or even measure!)" Look at choral pieces, especially a cappela ones. Here's an example we can use in further discussions (and I'll post it over on #185 as well.)

image

The upper staff in this TTBB sample piece (Prayer of the Children, by Kurt Bestor) starts with chorded notes, changes to up/down stem 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.

It certainly would be possible to instead encode this as two parts (Tenor and Bass) but if you are talking on the level of actual performers using the Tenor staff... they are Tenor 1 or Tenor 2 and that is their "part", not the combined staff. It should be possible to "reprint" this as a four-staff TTBB piece from the way we encode the parts.

All that being said, I'm actually okay with the PR as written. I feel like it properly summarizes what we've been trying to do as far as specifying page-breaks, system-breaks, and the layout and grouping of staves on a system. As long as we acknowledge that we are still working on the staff element in #185 I think this can be accepted.

clnoel commented 3 years ago

Oh, shoot, just realized I missed the addition of staff-part in https://github.com/w3c/mnx/pull/245#issuecomment-930239639 My opinion is that we don't need this for the grand staff, if we just say that a part with multiple staves will render as a grand staff with a single "staff" element (see what I said in #185). We might need to add attributes to allow for suppression of an empty staff, but that can be added later, and can actually apply to any staff if we want (it would simplify the very common piano/vocal case where the first line is piano only and the voice staff starts on the second line without needing to specify two layouts). We also might want to consider adding "barline-type" to staff or to staff-group or both, to allow Mensurstich, but that's a different topic, I think.

On the other side, I like the staff-part idea for the multiple parts per stave. If we actually go that way, I'll modify my example in #185 to use that instead.

adrianholovaty commented 3 years ago

All right, I've updated this pull request to synthesize the feedback in this thread. Here is the updated example document, as it stands on the branch:

<mnx>
   <global>...</global>
   <part id="fl1" name="Flute 1" short-name="1">...</part>
   <part id="fl2" name="Flute 2" short-name="2">...</part>
   <part id="fl3" name="Flute 3" short-name="3">...</part>
   <part id="ob1" name="Oboe 1" short-name="1">...</part>
   <part id="ob2" name="Oboe 2" short-name="2">...</part>
   <part id="piano" name="Piano" staves="2">...</part>
   <system-layout id="fullscorelayout1">
      <group-layout symbol="bracket">
         <group-layout symbol="brace" label="Flutes">
            <staff-layout labelref="short-name">
               <staffpart-layout part="fl1"/>
               <staffpart-layout part="fl2"/>
            </staff-layout>
            <staff-layout labelref="short-name">
               <staffpart-layout part="fl3"/>
            </staff-layout>
         </group-layout>
         <staff-layout label="Oboes" labelref="short-name">
            <staffpart-layout part="ob1"/>
            <staffpart-layout part="ob2"/>
         </staff-layout>
      </group-layout>
      <group-layout symbol="brace" label="Piano">
         <staff-layout>
            <staffpart-layout part="piano" staff="1"/>
         </staff-layout>
         <staff-layout>
            <staffpart-layout part="piano" staff="2"/>
         </staff-layout>
      </group-layout>
   </system-layout>
   <system-layout id="fullscorelayout2">
      <group-layout symbol="bracket">
         <group-layout symbol="brace" label="Fl.">
            <staff-layout labelref="short-name">
               <staffpart-layout part="fl1"/>
            </staff-layout>
            <staff-layout labelref="short-name">
               <staffpart-layout part="fl2"/>
            </staff-layout>
            <staff-layout labelref="short-name">
               <staffpart-layout part="fl3"/>
            </staff-layout>
         </group-layout>
         <staff-layout name="Ob." labelref="short-name">
            <staffpart-layout part="ob1"/>
            <staffpart-layout part="ob2"/>
         </staff-layout>
      </group-layout>
      <group-layout symbol="brace" label="Piano">
         <staff-layout>
            <staffpart-layout part="piano" staff="1"/>
         </staff-layout>
         <staff-layout>
            <staffpart-layout part="piano" staff="2"/>
         </staff-layout>
      </group-layout>
   </system-layout>
   <score name="Full score">
      <page>
         <system measure="1" layout="fullscorelayout1"/>
         <system measure="4" layout="fullscorelayout2"/>
      </page>
   </score>
</mnx>

You can also view it (in the branch) here:

https://cdn.githubraw.com/w3c/mnx/system-layouts/docs/mnx-reference/examples/system-layouts/

The latest changes are:

I think this is a good time to merge, hence finishing this line of work. There are some remaining issues on the broader topic of "per-layout customization," but we can tackle them in follow-up work given the foundation this pull request gives us. Some remaining issues are:

Any final feedback on where this has landed?

adrianholovaty commented 3 years ago

Just a quick update here, based on feedback from @mdgood: I've renamed <staffpart-layout> to <part-layout>. Here's the updated example:

<mnx>
   <global>...</global>
   <part id="fl1" name="Flute 1" short-name="1">...</part>
   <part id="fl2" name="Flute 2" short-name="2">...</part>
   <part id="fl3" name="Flute 3" short-name="3">...</part>
   <part id="ob1" name="Oboe 1" short-name="1">...</part>
   <part id="ob2" name="Oboe 2" short-name="2">...</part>
   <part id="piano" name="Piano" staves="2">...</part>
   <system-layout id="fullscorelayout1">
      <group-layout symbol="bracket">
         <group-layout symbol="brace" label="Flutes">
            <staff-layout labelref="short-name">
               <part-layout part="fl1"/>
               <part-layout part="fl2"/>
            </staff-layout>
            <staff-layout labelref="short-name">
               <part-layout part="fl3"/>
            </staff-layout>
         </group-layout>
         <staff-layout label="Oboes" labelref="short-name">
            <part-layout part="ob1"/>
            <part-layout part="ob2"/>
         </staff-layout>
      </group-layout>
      <group-layout symbol="brace" label="Piano">
         <staff-layout>
            <part-layout part="piano" staff="1"/>
         </staff-layout>
         <staff-layout>
            <part-layout part="piano" staff="2"/>
         </staff-layout>
      </group-layout>
   </system-layout>
   <system-layout id="fullscorelayout2">
      <group-layout symbol="bracket">
         <group-layout symbol="brace" label="Fl.">
            <staff-layout labelref="short-name">
               <part-layout part="fl1"/>
            </staff-layout>
            <staff-layout labelref="short-name">
               <part-layout part="fl2"/>
            </staff-layout>
            <staff-layout labelref="short-name">
               <part-layout part="fl3"/>
            </staff-layout>
         </group-layout>
         <staff-layout name="Ob." labelref="short-name">
            <part-layout part="ob1"/>
            <part-layout part="ob2"/>
         </staff-layout>
      </group-layout>
      <group-layout symbol="brace" label="Piano">
         <staff-layout>
            <part-layout part="piano" staff="1"/>
         </staff-layout>
         <staff-layout>
            <part-layout part="piano" staff="2"/>
         </staff-layout>
      </group-layout>
   </system-layout>
   <score name="Full score">
      <page>
         <system measure="1" layout="fullscorelayout1"/>
         <system measure="4" layout="fullscorelayout2"/>
      </page>
   </score>
</mnx>
notator commented 3 years ago

My feeling is that this PR should not be merged until the outstanding sub-issues in #185 have been resolved.

The addition of a <part-layout> element may well be a good idea, but don't think it should be cast in stone until examples of its use have been discussed . Its also a bit off-topic for this PR. Best would be to open a new issue for it, to be discussed (with concrete examples) after we've finished with #185.

My main problem with the above code is with the coding of the piano. (see https://github.com/w3c/mnx/pull/245#issuecomment-930155607).

  1. I still think its a mistake to add a staves=2 attribute to <part>. The whole point of the <part><sequence> elements is to allow the <part> information to be displayed on different numbers of staves in different systems. All the cross-staff information (beams, arpeggii, slurs etc.) has to be coded inside <part>, so specifying <staff-layout> elements inside a one-part <group-layout> leads to duplication of information, and confusion. All the <system-layout> needs to be told is the current number of sub-staves it needs to render for the <part>. Note that this may be different in the full score and in the part-booklet: A piano could be notated on a single staff to save space in a particular system in the full-score, but the same music may need to be written on two, or even three, staves in the part-booklet (because the system breaks will be different). I think we need to agree about #219: Either it should be turned into a PR, or some improvement or alternative should be proposed.
  2. My instinct is that there are going to be problems down the line if we try to treat a <grand-staff-layout> (for one <part>) as if its a <group-layout> (for more than one <part>). For example, in an orchestral piano part-booklet, how does the renderer know:
    • that it only needs to print global information (rehearsal numbers, accel., rit. etc) once?
    • how it should print multi-measure rests? Renderers may do this differently when presented with the same code, but they all have to know that they are dealing with a grand staff. My own preference would be for the rest to have one fat beam and number, in the vertical middle of the grand staff, not one multi-rest per component staff. The author of this thread is also struggling to do something like that.
  3. There is an unresolved issue with percussion parts: 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. Here too, I think the use of <grand-staff-layout> (and/or the corresponding <grand-staff> ) is unavoidable. I also think that the number of lines per sub-staff should be related to the instrument (say 2 Bongos or 4 Cymbals), and somehow defined inside <part>. This needs to be resolved in #185.

Another sub-issue relates to the use of <system-layout> elements. I agree with @joeberkovitz that the solution to the problem of changing staff-classes in the middle of a system is to define real <system> objects inside <score><page>. He said:

My gut sense is that it's best to use instances of the layout classes (i.e. <system> elements) to somehow specify measure subranges when needed — after all, that is where measure indices already come into play in defining the extent of a simple system with a unitary layout.

These <system> elements would be unique, and not use the muster-systems defined as <system-layout> elements. If that's the case, and we decide how to code unique <system> objects, then this PR's simple, one-page score could be coded more simply without defining muster-systems.

As @clnoel said, it has to be acknowledged that we are still discussing staff elements in #185. I think that means we should wait before accepting this PR. Can we also agree on #219?

I've been away, and am getting this posting off in a hurry. Still need to look closely at @clnoel's https://github.com/w3c/mnx/issues/185#issuecomment-932402920 Will do that now.

All the best. James

adrianholovaty commented 3 years ago

@notator See responses inline below —

The addition of a <part-layout> element may well be a good idea, but don't think it should be cast in stone until examples of its use have been discussed . Its also a bit off-topic for this PR. Best would be to open a new issue for it, to be discussed (with concrete examples) after we've finished with #185.

We introduced <part-layout> as a replacement for a space-separated list of IDs. This is the old proposal:

<staff parts="fl1 fl2" />

The problem is this doesn't provide an easy way to add additional information to each "part within this staff". For example, it wouldn't let us easily say "for the fl1 part, use stems upward." The best solution given that design would be something like...

<staff parts="fl1 fl2" stems="up down" />

...but that has an implicit rather than explicit connection between parts and stems. Much better to make it explicit, like so:

<part-layout part="fl1" stemdir="up" />
<part-layout part="fl2" stemdir="down" />

In short: using a distinct <part-layout> element gives us the flexibility of attaching additional metadata to each "part within a layout." I expect the nature of this metadata will be mostly presentational (stem directions, colors, cue size?).

I still think its a mistake to add a staves=2 attribute to <part>.

I apologize, but I've read your comment slowly three times, and I still don't understand your argument. Can you provide a concrete example of music (an image plus markup) that is poorly handled by this proposal?

My instinct is that there are going to be problems down the line if we try to treat a <grand-staff-layout> (for one <part>) as if its a <group-layout> (for more than one <part>). For example, in an orchestral piano part-booklet, how does the renderer know:

  • that it only needs to print global information (rehearsal numbers, accel., rit. etc) once?
  • how it should print multi-measure rests? Renderers may do this differently when presented with the same code, but they all have to know that they are dealing with a grand staff.

The rendering engine will know that the underlying notation data comes from a <part> that has a staves value greater than 1. This is, for example, how my own rendering engine (Soundslice) works. A part is marked as having two staves, and that's enough information for the rendering engine to change various things in the engraving.

There is an unresolved issue with percussion parts: 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.

For this situation, I'd encode each of the instruments as a different <part>, then use <system-layout> to bunch them together for presentation. If you want the part to change mid-staff, this would require support for multiple layouts within a single staff, which I mentioned above likely won't get into MNX 1.0.

clnoel commented 3 years ago

First, I believe that supporting multiple layouts within a staff will need to make it into MNX 1.0.

Second, I think this pull request can move forward even though #185 is not resolved. Everything we are currently debating in that issue has to do with the specifics of the interior of the staff-layout, @notator. We have to compartmentalize at some point or we won't get anything done.

When we come to agreement on #185, then we can make a new PR that better defines the contents and attributes of the staff-layout.

--Christina

notator commented 3 years ago

@adrianholovaty Ah, I now understand <part-layout>! Agreed. Thanks for the explanation. The latest version of your proposal needs to be updated to match the stem-directions in the diagram:

<mnx>
    ...
   <system-layout id="fullscorelayout1">
      <group-layout symbol="bracket">
         <group-layout symbol="brace" label="Flutes">
            <staff-layout labelref="short-name">
                <part-layout part="fl1" stemdir="up" />
                <part-layout part="fl2" stemdir="down" />
            </staff-layout>
            ...
         </group-layout>
         <staff-layout label="Oboes" labelref="short-name">
            <part-layout part="ob1" stemdir="up"/>
            <part-layout part="ob2" stemdir="down"/>
         </staff-layout>
      </group-layout>
      ...
   </system-layout>
   <system-layout id="fullscorelayout2">
      <group-layout symbol="bracket">
         ...
         <staff-layout name="Ob." labelref="short-name">
            <part-layout part="ob1" stemdir="up"/>
            <part-layout part="ob2" stemdir="down"/>
         </staff-layout>
      </group-layout>
      ...
   </system-layout>
   <score name="Full score">
      <page>
         <system measure="1" layout="fullscorelayout1"/>
         <system measure="4" layout="fullscorelayout2"/>
      </page>
   </score>
</mnx>

To keep things consistent, and as simple as possible, I still think it would be better to rename fullscorelayout1 and fullscorelayout2 to systemlayout1 and systemlayout2. The layouts are system-layouts not full-score-layouts!


I still think its a mistake to add a staves=2 attribute to <part>.

The fundamental reason is that this is unnecessary, duplicate information in MNX. The maximum number of staves that a part may need in any <system> can be found while parsing the <part> element. And its not true that a <part> that needs multiple staves will always have a constant number of staves in all instantiated systems, so the information is actually incorrect/confusing.

in an orchestral piano part-booklet, how does the renderer know:

  • that it only needs to print global information (rehearsal numbers, accel., rit. etc) once?
  • how it should print multi-measure rests? Renderers may do this differently when presented with the same code, but they all have to know that they are dealing with a grand staff.

The rendering engine will know that the underlying notation data comes from a <part> that has a staves value greater than 1.

I think you are just using the "staves value greater than one" to flag a <part> written for a grand staff. That's not actually necessary on the <part> element, for the reasons given above. The information in a <part> element can only be instantiated by putting it in a concrete container of some sort, and I think we need <group-layout>, <staff-layout> and <grand-staff-layout> containers to encapsulate the different behaviours of those objects. (<group-layout>, <staff-layout> and <grand-staff-layout> all have different rules for drawing barlines, global information, multi-measure rests, stem directions, time-signatures etc.) Note, for example, that these three objects provide opportunities for describing how/where global information is to be printed in full-scores and parts -- but that's a separate issue. :-)

Your example currently uses a <group-layout> element to describe a two staff instantiation of (a section of) the piano part:

      <group-layout symbol="brace" label="Piano">
         <staff-layout>
            <part-layout part="piano" staff="1"/>
         </staff-layout>
         <staff-layout>
            <part-layout part="piano" staff="2"/>
         </staff-layout>
      </group-layout>

This duplicates the staff information already present in the piano's <part> element. Finer grained control over each event's staff number is already present there, together with info about cross-staff beams, slurs, arpeggios etc. So there's no reason to have <staff-layout> or <part-layout> elements here. <part-layout> elements are there to override stem directions in staves that contain more than one <part>, but there is only ever one part here. The only information the renderer needs, apart from the symbol, label and part-ID, is the concrete number of staves to provide for the <part> in this system. So the above code could be replaced by:

        <grand-staff-layout symbol="brace" label="Piano" part="piano" staves="2" />

As was the case with <part-layout> any special behaviours (how to draw multi-measure rests etc.) can be discussed and added later.

Hope that helps. :-)


Edit: There are no percussion parts in this PR, so I'll continue that discussion in #185. Basically, I agree with you...


@clnoel Sorry about the delay in replying to https://github.com/w3c/mnx/issues/185#issuecomment-932402920. I'll get there very soon. I also think that supporting multiple layouts within a staff must make it into MNX 1.0. But I disagree about accepting this PR before closing #185: I think #185 is actually quite close to being complete. There are some sub-issues that could be sorted out later, but the code that's necessary for grouping parts is nearly ready. I just think that once the code in this PR has been agreed, #185 should be refactored using the new syntax/structures and checked for any serious problems, before the PR is pushed. We need to be sure that the PR code doesn't cause any problems with the more advanced elements in #185 (multiple scores in the file, part-booklets, multiple layouts within a staff...). Indeed, if #185 (and #219) are agreed, they could be turned into PRs and pushed as well. That would get us further than pushing this PR in a possibly problematic state.

clnoel commented 3 years ago

@notator I've been reading this one, and #185, and I'm not sure what issues you still have with this PR other than the possible inclusion of scores and pages, which you listed over there, not here. Over there you listed "The issues I've already raised there". I've gotten a little lost. Can you make a bullet-point summary list of your remaining issues. Just as a quick reference so I can look back over your complete argument or issue in the above postings.

For what it's worth, I don't think we need the scores and pages, just we opted against parts to contain all the part elements. That's not the XML style we have established.

I think that this PR is complete, in that it was supposed to establish a method of page and system breaks, and has done that. #185 is the proper place to address changes to the contents and attributes of the system-layout, because it is all about "how to group parts", which is conceptually separate from what this PR was supposed to do. I guess, technically, this PR has already gone too far, because we only really need the score page system part of it to establish page-breaks.

As far as I can tell, all the places of remaining disagreement here and in #185 are either inside staff-layout (voice-layout, part-layout, spaces between staff lines), additions to system-layout (grand-staff-layout, multi-part time-signatures), or inside system (mid system layout changes, multi-part directions, and multi-measure rests). If we acknowledge that future PRs will be changing those elements (their attributes and contents), can we pass this one, as it seems to be doing what it's supposed to do?

--Christina

adrianholovaty commented 3 years ago

As far as I can tell, all the places of remaining disagreement here and in #185 are either inside staff-layout (voice-layout, part-layout, spaces between staff lines), additions to system-layout (grand-staff-layout, multi-part time-signatures), or inside system (mid system layout changes, multi-part directions, and multi-measure rests). If we acknowledge that future PRs will be changing those elements (their attributes and contents), can we pass this one, as it seems to be doing what it's supposed to do?

That's my exact understanding as well — nicely articulated! I'm planning to merge this as soon as I get a chance (likely tomorrow).

notator commented 3 years ago

Here are all the issues I think need settling in this PR before it can be pushed.

(The current state of this PR's code is in https://github.com/w3c/mnx/pull/245#issuecomment-941133898.)

The issues I mention above (in https://github.com/w3c/mnx/pull/245#issuecomment-943290014) are:

https://github.com/w3c/mnx/issues/185#issuecomment-946724953 Issue 2 raises the following question:

adrianholovaty commented 3 years ago

<part-layout> should have a stemdirattribute. (see also How to group parts? #185 (comment) Issue 3)

We'll need to add something like this eventually, but it wasn't essential at the moment. We need to give it more thought — especially for cascading (e.g., defining the interaction between hard-coded stem directions in an <event> vs. a <part-layout>).

fullscorelayout1 and fullscorelayout2 should be renamed systemlayout1 and systemlayout2. The layouts are system-layouts not full-score-layouts!

Yeah, they were called "fullscorelayout" to distinguish them from the "flutepartlayout", and the flute part layout had been removed from the example. I changed the IDs to "layout1" and "layout2" before merging.

<part> should not have a staves attribute

Sorry, I disagree on this. It should indeed have a staves attribute, so a notation-rendering system can know the range of possible staves to which an <event> or <sequence> can be assigned.

the piano part should be coded as a <grand-staff-layout>, not as a <group-layout>

Again, disagreed. You never made a clear case for why there would need to be a separate element for grand staff music. The system (as merged) handles it in a unified way, without needing a separate element.

notator commented 3 years ago

@adrianholovaty I think we'll have to revisit the areas of disagreement again later. Not just stemdir. I think the case for <part> not having a <staves> attribute is watertight, and @clnoel apparently agrees with me about the necessity for <grand-staff-layout>. We are still discussing a few things in #185. I don't understand the rush to merge before we've finished. Are you deliberately keeping this PR open?

adrianholovaty commented 3 years ago

@notator No, this is no longer open — it was merged a few hours ago.

clnoel commented 3 years ago

@notator , I am fully in agreement that this PR is finished. It is supposed to address #57, not #185. As per my recent post there, we still have 6 major questions to address in #185, so that is nowhere near done and there is no reason to hold this PR for that. It's not in a "problematic state." It's a solid basis for future work. If we held every PR until every child of every element was complete we would never merge any PRs at all.