Skip to main content
Topic: RangePitchMarker.hmm (0.1) (Read 3693 times) previous topic - next topic

RangePitchMarker.hmm (0.1)

Here is a plugin that highlights notehead depending on their pitch. The most common use is to indicate notes falling outside a given range ("ambitus") of a voice. However, it can also be used to higlight notes inside a range, notes from a fixed list (a "scale") or notes outside a scale.

Each RangePitchMarker object requires one more subsequent chords ("range chords") which define the pitches of the range or scale to be highlighted. No items are allowed between the object and the range chords, with the exception of clefs. Typically, invisible grace chords are used as range chords.

Multiple RangePitchMarkers with different colors can be specified - then, the second RangePitchMarker only marks pitches not marked by the first; the next RangePitchMarker, only those not marked by the previous two; etc. In practice, using three colors red, amber, and green could be useful to highlight unacceptable, somewhat acceptable, and essentially ok pitches.
A marker with the same color replaces the previous specification for that color. The order of colors is not changed by this - it remains the same throughout the staff. Repeating a marker color which is immediately followed by an (invisible grace) rest will stop marking noteheads with this color.

For more and detailed uses, see the attached examples:

  • MarkRanges shows the standard use - both with multiple colors and with "interpolating" marks (this image shows what it looks like; it's also in the attachments);
  • SATB is a possible setup for a choir's ranges;
  • Ave Maria shows a use for the fixed scale of a "31er" crank organ.

"For technical reasons" (see below), RangePitchMarker objects must have class "Span".

A tale of programming this object

I just wanted to implement this "quickly" between other things to do - much music I have to write, and more work on my planned "complete introduction to NWC." However ... implementing this plugin was much harder than I thought - but, admittedly only because I wanted the plugin to work also in print mode. In that case, auto-inserted objects must do the duty of drawing the marker circles; but they still must visit all other RangePitchMarker plugins to find out for which pitches they are responsible. It took me a day or so to find out that only Span-class objects would work: "Standard" objects do not replicate down to subsequent staves on a print page, and hence cannot do drawing down there; "StaffSig" objects forcefully replace all previous objects of the same class, so that only the last marker color would arrive there. However, with Span objects, I had to calculate the span correctly up to the next plugin of the same color - having an infinite span would accumulate the objects on each staff, and I would not know which one is the last one of a certain color (trying this, I found a quirk: math.huge is not a valid span value - it works like 0; however, 1000000 - 1 million - does work; but I needed precise spans anyways). Anyway, these was only the beginning of troubles ...

... because then I found that the drawpos position of auto-inserted Span-class objects behaves quite strangely: It does not start at the auto-insert position (as with StaffSig-class ones), but at the original position. However, doing :find('next') will then jump to the object after the auto-inserted position - and a :find('prior') will jump back to the original position. Thus, with Span-class objects, one cannot iterate over the objects between the original and the auto-inserted position! - which I needed to find out whether other RangeMarkerObjects, of other colors, would claim some pitches. It took me a few hours (i.e., days, because I only have an hour or so per day for this hobby) to pinpoint down all this, which first looked more like a random jumping around. I feel this is a buggy, or at least, unexpected behavior - but by using spcific :indexOffset() values, I finally found a working algorithm. So it goes -

- but now all is fine (I hope).