Skip to content

Proposal to refactor the beam object in part.measure.beams #399

Closed
@rpatters1

Description

@rpatters1

I quite like the inclusion of an array of beams at the part.measure level. It elegantly solves a number of challenges, including

  • where a beam starts and ends
  • which events are in the beam
  • cross-staff beams.

(The one cross-staff beaming situation that may not be covered is multi-percussion layouts where there is cross-staff beaming across the entire layout, but I leave that as an aside for now. I have also seen full orchestra layouts in contemporary styles that cross-staff chords and beams across the entire full orchestra score. That also is an aside.)

Why a refactor

I am proposing this refactor because to me the current beam object seems very prescriptive and has a lot of opportunity for error in how it is to be interpreted. My proposal is driven by the following observations.

  • The number of beams/flags on a note is determined entirely by its note value. A 128th note inside a beam must have exactly 5 beams. If there is no adjacent 128th or smaller note value, it must have additional hooks so that the total number of beams equals 5.
  • Any software that draws beams will already be handling this. All it needs from MNX is where the primary beam starts and ends, and which events are included in it. The nested structure is overkill and will almost certainly be ignored, because:
  • There is a complex opportunity for mismatches between the nested beam structure, the hooks array (as currently specified), and the number of beams required by each note.

The proposal

Here is my proposal for a refactored beam object.

{
    "beams": [
        "events": [
            "aaaa",
            "bbbb",
            "cccc",
            "dddd",
            "eeee",
            "ffff"
        ],
        "breaks:" [
            {
                "event": "cccc",
                "beam": 2
            },
            {
                "event": "eeee",
                "beam": 3
            }
        ]
    ]
}

The events array would be exactly the same as it is now.

Instead of an inner array, there would be an array of breaks. These would specify secondary beam breaks. The beam number would be a number >= 2 specifying which beam to break (where 1 is the primary 8th beam, 2 is the 16th beam, etc.) Secondary beam breaks would only be required if the specified secondary beam would otherwise continue to the left and right of the specified event. Specifically, they would not be required in a situation like the two 16th notes in the Beams example.

Instead of the hooks array, I would propose that a hook object be added to the event object, since the event's note value is what determines the presence of a hook. However, whether hooks are moved to events or stay in beam, they should only be used when there is a desire to manually override the default hook direction, determined by consuming software. (See the 2nd bullet above. Any software that knows how to draw beams has to be able to draw hooks as well. And it has to have an algorithm to determine which direction the hooks should go without being told.)

Example refactor

Here is what a refactored beams array would look like in the secondary beam breaks example.

{
   "beams": [
      {
         "events": [
            "ev1",
            "ev2",
            "ev3",
            "ev4",
            "ev5",
            "ev6",
            "ev7",
            "ev8"
         ],
         "breaks" : [
            {
               "event": "ev5",
               "beam": 2
            }
         ]
      },
      {
         "events": [
            "ev9",
            "ev10",
            "ev11",
            "ev12",
            "ev13",
            "ev14",
            "ev15",
            "ev16"
         ],
         "breaks" : [
            {
               "event": "ev11",
               "beam": 3
            },
            {
               "event": "ev13",
               "beam": 2
            },
            {
               "event": "ev15",
               "beam": 3
            }
         ]
      }
   ]
}

And for the Beams example it is just a list of events in the beam:

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

The secondary beam of 2 16ths is implicit in their note values, and there is no need to specify it further.

(BTW: there is a typo in the sample file. The second beam in this example shows "ev15" as both the starting and ending event.)

Final thoughts

As you can see, this proposal produces much less verbose beam descriptions, yet it provides all the information that is needed by a consuming program to render the beam.

I proposed a numbering system of beams starting with 1 as the primary, but other schemes could be used instead. A starting value of 2 seems awkward in a computer program. We could number only the secondary beams and start with 1 as the 1st secondary beam (i.e., the 16th beam). We could use note value bases to specify the beams. I proposed the numbering scheme I did because it occurred to me there may be other situations where we need to refer to any beam, including the primary beam, and 1 as the primary seemed the most natural to me.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions