w3c / mnx

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

JSON: Encoding inner beams #299

Open adrianholovaty opened 1 year ago

adrianholovaty commented 1 year ago

When migrating to JSON, I needed to find a way to encode nested beams. Here's what I came up with:

"beams": [
   {
      "events": [
         "ev9",
         "ev10",
         "ev11",
         "ev12",
         "ev13"
      ],
      "inner": [
         {
            "events": [
               "ev11",
               "ev12"
            ]
         }
      ]
   },
   {
      "events": [
         "ev15",
         "ev15"
      ]
   }
]

This is taken from the Beams example document.

I think this is OK, but the approach is different enough from the XML approach that I wanted to bring it up for discussion. In the XML version, we relied on nesting XML elements implicitly, so there was no concept of an explicit "inner".

mscuthbert commented 1 year ago

It doesn't fit totally right to me. Is "inner" the right word for this? Looking at a slightly more complex example w/ 32nd notes: https://w3c.github.io/mnx/docs/mnx-reference/examples/beams-secondary-beam-breaks/ it seems to me that the right word for "inner" is in fact "beams" -- measures can contain a "beams" attribute which creates a beam object content is an element which has an attribute "events" (a single list) and a "beams":

"beams": [
   {
      "events": [
         "ev9",
         "ev10",
         "ev11",
         "ev12",
         "ev13"
      ],
      "beams": [
         {
            "events": [
               "ev11",
               "ev12"
            ]
         }
      ]
   },
   {
      "events": [
         "ev15",
         "ev15"
      ]
   }
]

I suppose one rationale for "inner" is that alphabetically it comes after "events" which is something we should be thinking about a bit. I'm just realizing that with "beams" coming alphabetically before "contents" parsers will have to hold on to "beams" until their content events are already defined. I can't have my "beams" parser apply beams to notes on parse since the notes won't be defined yet.

One little error here and in the example. The last "events" should refer to "ev14", "ev15" not "ev15", "ev15" - I was trying to figure out what a single beam looked like. Though it might be a better syntax for a hook. Rather than:

        "beams": [
                  {
                     "events": [
                        "ev1",
                        "ev2",
                        "ev3"
                     ],
                     "hooks": [
                        {
                           "direction": "right",
                           "event": "ev1"
                        },
                        {
                           "direction": "left",
                           "event": "ev3"
                        }
                     ]
                  },

maybe it's:

     "beams": [
                  {
                     "events": [
                        "ev1",
                        "ev2",
                        "ev3"
                     ],
                     "inner": [
                        {
                           "events": ["ev1"],
                           "hook": {"direction": "right"}
                        },
                        {
                           "events": ["ev3"],
                           "hook": {"direction": "left"}
                        },
                     ]
                  },

So that a hook is an inner beam on one note that specifies its "hook" properties. (It makes more sense to me that a hook is a specialized 16th beam, not an attribute on the 8th beam.