Hairpins with arbitrary end points in terms of beat position

• Feb 18, 2019 - 15:47

Hairpins in MuseScore must start or end on a note or rest. This behaviour is simple to code and easy for users to understand, but it causes problems for the common case where there are two hairpins on one note:

double-hairpin.png

This particular case could be solved by having a "double hairpin" element, but there are other cases (admittedly more rare) where hairpins do not have any relation to note boundaries. These cases can be notated by manually adjusting the length of the hairpins, but doing so has the following drawbacks:

  • Playback is incorrect
  • The hairpins will move if the score reflows, leading to the notation also being incorrect

These problems arise due to the fact that the hairpin's length is a purely visual concept in MuseScore: its musical position is still "logically" connected to a note or rest.

A common workaround is to use invisible rests in higher-numbered voices as spacers:

double-hairpin-hint.png

This allows the hairpin to be logically connected to the rests, which leads to correct behaviour on reflow, and potentially also during playback once single-note dynamics is enabled.

However, this is not the solution adopted by the common interchange format MusicXML or its successor MNX. These formats both allow hairpins to be placed at arbitrary locations in a bar, but they each have a different method for doing so.

MusicXML Offsets

The approach used by MusicXML is to add hairpins (or "wedges") to notes or rests (like MuseScore) but then to specify a Start Offset and End Offset in terms of musical divisions away from the fixed location of the note or rest.

This would be relatively straightforward to implement in MuseScore. It could be accomplished by adding new Inspector properties for Line Start Offset and Line End Offset, which would be measured in beats (or possibly in fractions of a whole note) rather than in terms of position on a printed page.

However, it means that hairpins are still in some way "attached" to notes and rests, which leaves open the question of what should happen if those notes or rests were to be changed later on. If a note or rest is moved, deleted, or its durations changed, should the hairpin be moved, deleted or duration changed too? Alternatively, should we go through the score looking for hairpins and updating all their offsets to be relative to new notes and rests that are closest to where the old ones used to be? Should the new offset be given as a positive offset from a prior note or a negative offset from a later note, etc?

MNX Locations

MNX is a draft specification and subject to change, but the approach currently used is to give each hairpin (or "wedge") a location attribute and an end attribute, both of which are specified in terms of beats relative to the current measure, or to the start of the piece. This means that hairpin positions in MNX do not bear any relation to the placement of notes or rests in the measure.

The MNX approach has the advantage that hairpins are unaffected by notes and rests being moved, deleted or having their durations changed. (Of course if you want to move or delete the hairpin and the notes at the same time then you would simply select both in MuseScore, so it is not limited in that regard). However, the implementation is very different to the way hairpins are currently implemented in MuseScore, so some thought would need to be given to how this would be presented in the UI and stored in the MSCX file format.

Questions

  1. Should we allow hairpins to be placed at arbitary points in a bar?
    • Or should we continue using the trick with hidden rests?
  2. If we allow this, which approach should we adopt?
    • The MusicXML approach with offsets, or the MNX approach with locations?

This is purely a discussion about how to store the positions in MuseScore's internal representation, and how to present it in the UI. In terms of export to and from MusicXML and MNX, it doesn't actually matter which approach we take as you can get the same information both ways. However, we would need to pick one of them because the trick with hidden rests doesn't translate well during import and export.


Comments

To me it makes perfect sense to allow arbitrary beat positions just as we do for chord symbols. In fact, the same shortcuts could be used: while in edit mode, press ";" to move by beat, Ctrl+number to advance by the specified duration, etc. Internally we probably depend on there being a start and end element for hairpins, but I suspect it wouldn't be too hard to re-code that.

BTW, same would apply to pedal lines, thus allowing pedal markings to be attached to the bottom staff but aligned with notes in the top.

In reply to by Marc Sabatella

Right. It sounds like you are in favour of the MNX approach. I agree that this is probably the right way to go. I'm not sure that chord symbols is the best example of usability though, as they appear to be attached to random places in the bar. If we just added a location property to the Inspector that displayed the actual beat number (and allowed you to edit it) that would be a big improvement. Hairpins (and other lines) would of course need two locations: one for start and one for end.

In reply to by shoogle

With chord symbols you can see the position in the status bar, and that is true for hairpins too. No harm I guess in duplicating this info in the Inspector, but I also don't see the benefit. Sure, it gives a way of modifying the time position, but we already have a well-understood way of specifying a position - the chord symbol method has been in use for years with essentially no complaints - so I'd just as soon leverage it as invent a new one. If we did do that, would we also have this for other elements with a time position?

In reply to by Marc Sabatella

I imagine most people have been adding chord symbols to notes and rests; I certainly had no idea it was possible to do otherwise.

I don't know what other elements are able to be stored at arbitrary positions, but I would say that all of them should have this Inspector property. Doing this would enable:

  • Elements to be moved without copying and pasting.
    • You also wouldn't need to create a note or rest to paste onto, then delete it again afterwards.
  • Putting elements on half-beats and quarter-beats, etc.
    • Of course, certain elements could be restricted to whole-beats if it is not appropriate for them to go on half-beats, just like rests (used to be) restricted to an integer Y offset.

Come to think of it, Lines would probably want a location and a length property rather than start and end properties, as this would prevent problems like the end being before the start, etc.

In reply to by Marc Sabatella

Ooh, arbitrary start and end positions for pedal lines! That is also a limitation of MuseScore currently. I would just also ask that if the pedal lines are redone, code is written to correctly always position the pedal line below the bottom staff of the instrument and allow it to be anchored to a note in one staff of the grand staff for a begin element and a note in a different staff of the same instrument's grand staff for an end element. Or at least consider this problem too, so that what you do doesn't make it difficult to change the architecture in the future to accommodate this extra functionality for pedal lines.

In reply to by shoogle

That would be an improvement over the current state of affairs already. I am envisaging, however, that you can click on a note, Shift + click on a note of the same instrument, but in a different staff of the grand staff, add a pedal line, and the pedal line would automatically start at the note first in time, end at the note last in time and be below the bottom staff of the instrument's grand staff. The same should happen if you select two notes in an upper staff of the grand staff. The pedal line should automatically be positioned below the bottom staff of the instrument's grand staff, starting at the note first in time's segment and end at the note last in time's segment. What I mean, is that we keep that in mind while designing the new feature discussed here.

In reply to by Louis Cloete

I see, well that certainly should be possible. In general anything is possible in the UI as long as the data structures defined in libmscore don't preclude it (as they do currently). If the data structures are fixed then it would only be a matter of time before the desired behaviour was implemented in the UI.

Do you still have an unanswered question? Please log in first to post your question.