w3c / mnx

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

Inner-bar clef changes #313

Closed adrianholovaty closed 1 year ago

adrianholovaty commented 1 year ago

How should inner-bar clef changes be encoded? More precisely, how should the "position" of a positioned-clef object be encoded?

Some requirements:

See #312, #96 and #45 for prior discussion.

The most complete solution so far is @clnoel's offhanded proposal from this comment:

I would almost rather that the clef be given an "appears before note-reference-id" location, rather than a timed location.

Just to kick off a fresh conversation, here's how that might look:

{
    "clef": {"line": 2, "sign": "G"},
    "startEvent": "id_of_event"
}

...where id_of_event would be the "id" of the first event object that the clef applies to. In multi-voice music, this would need to be encoded twice, though — which is a bit inelegant. Any thoughts or other ideas?

williamclocksin commented 1 year ago

In Calliope, clefs (and other non-timed elements) are simply in sequence on the staff in with the notes, barlines, etc. Every element has a voice ID, but it is also possible for an element such as a clef or other signature to have a list of voice IDs, that are used to show one clef that applies to multiple voices on the staff. The system formatting algorithm places the clef in the right place relative to the other elements, and the performance algorithm can tell that the clef applies to certain voices. So clefs aren’t duplicated, and they don’t have a timed location, and this could be represented by the proposed StartEvent ID. But it would be easier not to make it exceptional, but simply put it in the sequence of elements on the staff without needing the StartEvent? On 24 Sep 2023, at 22:05, Adrian Holovaty @.***> wrote: How should inner-bar clef changes be encoded? More precisely, how should the "position" of a positioned-clef object be encoded? Some requirements:

Using a rhythmic position in the bar is the simplest solution, but that doesn't handle the case of clef changes within a run of grace notes. (Grace notes all have the same rhythmic position.) In a multi-staff part, a clef should be able to be associated with a specific staff. In multi-voice music, a clef should be able to be associated with a certain voice. See this comment and this comment for examples. In multi-voice music, it would be nice not to need to encode an inner-bar clef change multiple times (once per sequence), though that may be unavoidable.

See #312, #96 and #45 for prior discussion. The most complete solution so far is @clnoel's offhanded proposal from this comment:

I would almost rather that the clef be given an "appears before note-reference-id" location, rather than a timed location.

Just to kick off a fresh conversation, here's how that might look: { "clef": {"line": 2, "sign": "G"}, "startEvent": "id_of_event" } ...where id_of_event would be the "id" of the first event object that the clef applies to. In multi-voice music, this would need to be encoded twice, though — which is a bit inelegant. Any thoughts or other ideas?

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you are subscribed to this thread.Message ID: @.***>

mscuthbert commented 1 year ago

If it's helpful, after years of dealing with problems of how to ensure elements appear in their "proper" order, music21 ended up specifying all musical objects with a six-element list/tuple, which has ended up serving the project well for the past decade-plus:

[atEnd=[0,1], offset=rational_number, priority=int, classSortOrder=int, isNotGrace=[0,1], insertIndex=non_negative_int]

languages that allow for < and > comparison of lists/tuples of the same length of numbers can sort elements based on this information.

Anyone who hasn't developed a full-fledged system will find this overkill, but over time something with this level of complexity always seems to be created. :-)

clnoel commented 1 year ago

After thinking about this, here's an expansion on my off-hand proposal:

{
    "clef": {"line": 2, "sign": "G", "staff": 0},
    "startEvents": {"event-id-1", "event-id-2"}
}

Notable here:

I believe this addresses the problem of not wanting to specify one visible object multiple times, while also allowing the clef to apply to all voices on a staff or one voice on a staff.

The only time this gets complicated is when we need to decide if a clef carries over to the next measure, if it was applied to just one sequence.

--Christina

Edited to add: Just had a thought... We might allow events sequences in following measures to be in the "startEvents" field if the clef carries over for one voice only. The clef would still be placed horizontally before the earliest of the start events, so would not be repeated at the next measure.

adrianholovaty commented 1 year ago

@clnoel Nice, thanks for giving this thought and expanding the idea!

Just to make sure I understand startEvents: the purpose is to handle multiple voices, right? So in case of a measure with two voices (a part-measure containing two sequences), startEvents would contain two event IDs, one for each sequence? I think this is what you meant, but I got confused by "placed horizontally before the earliest" (emphasis mine). Let me know if I'm misunderstanding here.

Also, I think the "staff" should go directly on this structure, not within the "clef". This keeps the "clef" object nice and pure — it represents only an abstract clef, without a position.

clnoel commented 1 year ago

@adrianholovaty Maybe I should have said "leftmost" instead of earliest. As an example: image In the above picture, both the down-stem grace and the up-stem half note would be in the startEvents array, and the clef would position itself to the left of the leftmost note (the grace note), regardless of the order that they are listed in the startEvents array.

Also, I included staff in the clef definition because line was already there. If those are conceptually different vertical placement definitions, then I don't mind splitting it out.

adrianholovaty commented 1 year ago

Just to note: I've opened a separate issue, #314, for the more general problem of addressability for notes (including grace notes). I think once we have a solution there, it'll be reasonably easy to do inner-bar clef changes.

adrianholovaty commented 1 year ago

This is now done, via the new "rhythmic position" object:

https://w3c.github.io/mnx/docs/mnx-reference/objects/rhythmic-position/

To see it in action, see the new clef changes example document. The inner-bar clef change is encoded with that rhythmic position:

https://w3c.github.io/mnx/docs/mnx-reference/examples/clef-changes/

This uses the new concept of a "positioned clef", documented here:

https://w3c.github.io/mnx/docs/mnx-reference/objects/positioned-clef/