Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transposing instruments and part-specific note data #287

Open
adrianholovaty opened this issue Nov 8, 2022 · 15 comments
Open

Transposing instruments and part-specific note data #287

adrianholovaty opened this issue Nov 8, 2022 · 15 comments

Comments

@adrianholovaty
Copy link
Contributor

adrianholovaty commented Nov 8, 2022

One of the remaining big structural to-dos for MNX is defining how to encode transposing instruments. And closely related is the need to encode how score-vs-part differences are encoded — such as differences in individual notes' enharmonic spellings in different contexts.

The goals, as far as I see it:

  • Allow a single MNX document to encode both a concert-pitch score (i.e., a conductor score) and its individual (possibly transposing) parts.
  • Encode each performed note as a single <note> element. In other words, the concert-pitch score and the individual parts should refer to the same underlying <note> elements. This lack of duplication brings many advantages.
  • Allow a <note> to have different enharmonic spellings in different contexts — either by specifying a clear and unambiguous transposition algorithm, or by encoding the spelling directly, or by encoding some meta information about the spelling, or some combination of these ideas.
  • Don't yet support other notational changes that might be needed for parts — such as ottavas that only apply to a part but don't apply to the same notes in the concert-pitch score. There comes a point at which a single document cannot be flexible enough to handle the wide variety of ways in which a part might differ from a score, without introducing brain-shattering complexity; in this case, we should encourage users to encode two separate documents. The goal is to balance flexibility with pragmatism and find a "good enough" solution for common cases.

Issues #34, #111 and #250 are all essentially about this (and the closed issue #138 also touched on it). I'm marking them as closed now, to focus discussion into a single place.

Example

Here's a short example. It's the same music, in three different instantiations: a concert score, a B♭ transposed part in a C♯ key signature, and a B♭ transposed part in a D♭ key signature.

enharmonic

Here is the basic MNX encoding of the music (in concert pitch):

<mnx>
   <global>
      <measure-global>
         <directions-global>
            <time signature="4/4"/>
            <key fifths="5"/>
         </directions-global>
      </measure-global>
      <measure-global/>
   </global>
   <part name="Clarinet in B♭">
      <measure>
         <directions-part>
            <clef sign="G" line="2"/>
         </directions-part>
         <sequence>
            <event value="/4">
               <note pitch="B4"/>
            </event>
            <event value="/4">
               <note pitch="C#5"/>
            </event>
            <event value="/4">
               <note pitch="D5" accidental="natural"/>
            </event>
            <event value="/4">
               <note pitch="E5"/>
            </event>
         </sequence>
      </measure>
      <measure>
         <sequence>
            <event value="/4">
               <note pitch="F#5"/>
            </event>
            <event value="/4">
               <note pitch="G5" accidental="natural"/>
            </event>
            <event value="/4">
               <note pitch="A5" accidental="natural"/>
            </event>
            <event value="/4">
               <note pitch="B5"/>
            </event>
         </sequence>
      </measure>
   </part>
</mnx>

How can we also encode the two transposed versions?

The first thing we can do is introduce a transpose attribute on the <part>. This would encode the instrument's default transposition — that is, the default number of (chromatic) semitones to apply as an offset to each <note> before rendering.

<part id="Clarinet" name="Clarinet in B♭" transpose="-2">

This is equivalent to MusicXML's transpose-chromatic.

Then, we can give <part-layout> a use-transposition attribute, which specifies whether the part.transpose should be applied. This lets one <score> use transpositions while the other doesn't.

<layouts>
   <system-layout id="ConcertLayout">
      <staff-layout>
         <part-layout part="Clarinet" use-transposition="false"></part-layout>
      </staff-layout>
   </system-layout>
   <system-layout id="ClarinetLayout">
      <staff-layout>
         <part-layout part="Clarinet"></part-layout>
      </staff-layout>
   </system-layout>
</layouts>

<score name="Concert" layout="ConcertLayout">
   <!-- Doesn't take part.transpose into account -->
</score>
<score name="ClarinetCSharp" layout="ClarinetLayout">
   <!-- Does take part.transpose into account -->
</score>

Then there's the matter of the key signature in the ClarinetCSharp <score>. The underlying data is encoded as <key fifths="5">, but this effectively needs to be treated as <key fifths="7">. Here, I think we can document an algorithm to determine the transposed key signature for purposes of rendering. In pseudocode, it would be something like:

  1. Take the original (concert-pitch) key signature and convert it into a pitch (between A and G#).
  2. Subtract the number of semitones as specified by part.transpose.
  3. Convert this back into a fifths value.
  4. If the resulting key signature can be expressed with fewer accidentals, prefer that. (This decision should be configurable; more on this point later.)

Then there's the matter of note spelling for each individual <note>. Both the values note.pitch and note.accidental would need to change for the purposes of rendering the transposed score. Here, I also think we can document an algorithm:

  1. Take the original pitch.
  2. Subtract the number of semitones as specified by part.transpose.
  3. If the resulting pitch would require an accidental with respect to the transposed key signature, decide which accidental is most appropriate. This decision could be configurable on a per-<note> basis. Perhaps we specify default behavior, such as "choose whichever spelling is the simplest" (prefer no accidental to a single accidental, and prefer a single accidental to a double-flat or double-sharp).

Another, possibly better, algorithm is the following:

  1. Take the original pitch.
  2. Determine its scale degree with respect to the concert-pitch key signature.
  3. Apply this scale degree to the transposed key signature, hence calculating the transposed pitch and accidental.
  4. [Optional?] Apply the same cleanup as in step 4 from the previous algorithm.

Hooks for specifying transposition behavior

The trickiest part about this whole thing is providing hooks to customize the above algorithms at just the right conceptual level. I'll spell out some alternative solutions, so that you can see how complicated this can get.

Option 1. At the lowest level, each <note> could specify its concert pitch/accidental and transposed pitch/accidental:

<note pitch="D5" accidental="natural" transposed-pitch="Fb5" transposed-accidental="flat"/>

There are several problems here. It's verbose, it slightly duplicates information (technically the transposed pitch can be deduced automatically from the non-transposed pitch plus the instrument transposition), and it supports only one alternative spelling (it wouldn't support the separate ClarinetCSharp and ClarinetDFlat scores from above).

Option 2. So, moving up a conceptual level, each <note> could specify its transposition's relative enharmonic shift:

<note pitch="D5" accidental="natural" enharmonic-shift="up" />

This enharmonic-shift attribute would mean something like "When this note's pitch is transposed, if the resulting pitch would require an accidental with respect to the transposed key signature, change the note's pitch upward when determining the enharmonic spelling."

The problem here is: this is a pretty obscure concept to wrap your head around. But it's a bit more elegant, because it removes redundancy while preserving per-note customization.

Option 3. Moving up another conceptual level, we could put the decision in the layout:

<system-layout id="ClarinetLayout">
   <staff-layout>
      <part-layout part="Clarinet" keysig-strategy="simplify" accidental-strategy="simplify"></part-layout>
   </staff-layout>
</system-layout>

Here, the new attributes keysig-strategy and accidental-strategy would encode the answer to these two questions:

  • keysig-strategy: "When transposing the key signature, should we prefer fewer accidentals?
  • accidental-strategy: "When transposing note pitches, should we prefer simpler accidentals?

The advantage here is that the decisions live in a single place. The disadvantage is that you lose flexibility for treating individual notes as special cases.

Some possible strategies might be:

  • simplify: Prefer as few accidentals as possible
  • prefer-flats: Prefer flats
  • prefer-sharps: Prefer sharps
  • passthrough: Don't apply any optimizations [need a better name than "passthrough"]

Encoding written versus sounding pitch

Oh, no. I'm bringing it up again. The question of whether MNX should encode written or sounding pitch (#issue #4) was a huge, passionate discussion — and we landed on encoding written pitch. However, having thought through the repercussions for transposing instruments, I believe this was a bad decision that we should revert.

I don't mean to relitigate this simply for the sake of relitigating a decision I always thought was a bad one. I've just come to see that the current approach of encoding written pitch would result in a lot of confusion in this particular case. And I think the advocates of encoding written pitch likely didn't realize how much of a problem this would be, in practice, for transposing instruments. We can, and should, be open to changing things in our spec given deeper understanding and experience (as we did with <beamed> — see #193).

As it stands, because MNX encodes notes at their written pitch, we effectively have two types of MNX documents:

  • Those in which the <note> data is meant to be interpreted as already transposed
  • Those in which the <note> data is meant to be interpreted as concert pitch

I strongly believe this will result in...well, chaos. It means any documentation or algorithms involving transposed instruments will always need to be prefaced with "Is your <part> a transposing instrument? Then do this. Otherwise, do it this entirely different way."

It would be much conceptually cleaner, and implementations would be simpler, if <note> and <key> data were treated as sounding (concert) pitch.

Next steps

Given all of this context, here's my personal take on how we should move forward:

  • Change <note> pitches to use sounding pitch.
  • Add <part transpose> as explained above.
  • Add <part-layout use-transposition> as explained above.
  • Agree on standard keysig and note pitch/accidental transposition algorithms and document them.
  • Choose from the "Hooks for specifying transposition behavior" options (or provide another option?). I don't frequently deal with transposing instruments in my own work, so I'd really like to hear from practitioners on which conceptual level is best.

Thoughts and feedback welcome!

[Update: I've altered the example image so that the ClarinetDFlat example deliberately uses an A natural as opposed to B double flat.]

@mscuthbert
Copy link
Contributor

Quick thought: I think that we're going to need a diatonic w/ a chromatic element for transposition, and also a way to do overrides for individual notes. -- more soon.

@dspreadbury
Copy link
Contributor

Overall I think this proposal is excellent and it will allow us to elegantly address the requirements for specifying the enharmonic spelling of the pitch independently in different layouts.

I think the benefits of switching MNX to use sounding pitch as its primary representation of pitch will be massive, especially for applications that want to use MNX as a native format. I know that this will make certain use cases a bit more awkward (such as e.g. encoding via OMR a part written at transposed pitch), but the ability to reason about the pitches in terms of what you will hear will pay us back many times over. (I hardly need to declare my interest that I was, and remained, dead against the original decision to encode pitches using written pitch in MNX!)

In terms of the right conceptual level at which the hooks for specifying the different transposition must be added, I think there's no alternative than to allow it to be encoded at the level of the individual note. Although there are certainly cases where a higher-level rule would make sense (e.g. where the combination of the standard transposition for a transposing instrument and an extreme key signature results in a whole passage written in an unhelpful key), there are enough cases where the encoding "just has to" vary (for reasons of performer preference or level of comfort with extreme enharmonics, or technical considerations for specific instruments, or what-have-you) that it seems simplest to allow the specification of a per-note enharmonic spelling.

We could encode a per-note transposition using a diatonic/chromatic pair, or we could simply encode the desired pitch. The latter has the benefit of being more explicit and also more easily human readable, but the former has the benefit of encoding the relationship between the original sounding pitch and the enharmonically-transposed pitch, which seems like it would be useful.

@clnoel
Copy link

clnoel commented Nov 22, 2022

@adrianholovaty Clarification: Are we forming this explicitly for transposing instruments or in order to allow a single piece of music to define multiple transpositions of the same piece (e.g. for different vocal ranges)? If it's the second, or we need to allow for the second, then I think that:

<part id="Clarinet" name="Clarinet in B♭" transpose="-2">

is not where this should be put. It should, instead, be put in the layout:

<system-layout id="ClarinetLayout">
       <staff-layout>
          <part-layout part="Clarinet" transpose="-2"></part-layout>
       </staff-layout>
</system-layout>

Then there's the matter of the key signature in the ClarinetCSharp <score>. The underlying data is encoded as <key fifths="5">, but this effectively needs to be treated as <key fifths="7">. Here, I think we can document an algorithm to determine the transposed key signature for purposes of rendering. In pseudocode, it would be something like:

  1. Take the original (concert-pitch) key signature and convert it into a pitch (between A and G#).
  2. Subtract the number of semitones as specified by part.transpose.
  3. Convert this back into a fifths value.
  4. If the resulting key signature can be expressed with fewer accidentals, prefer that. (This decision should be configurable; more on this point later.)

I feel like this is unnecessarily complicated. Let's just specify it: transpose-key="+2" moves form Bmajor to C#major. If we wanted Dbmajor, we would use transpose-key="-10". This kind of takes the place of "keysig-strategy" from option 3, but I feel it has more flexibility. If there is a keysig change partway through that needs a new "transpose-key" another layout can be formed to deal with that, and used in the appropriate place in the score.

<system-layout id="ClarinetLayout">
       <staff-layout>
          <part-layout part="Clarinet" transpose-key="+2" transpose-pitch="-2"></part-layout>
       </staff-layout>
</system-layout>

Then there's the matter of note spelling for each individual <note>. Both the values note.pitch and note.accidental would need to change for the purposes of rendering the transposed score. Here, I also think we can document an algorithm:

Another, possibly better, algorithm is the following:

  1. Take the original pitch.
  2. Determine its scale degree with respect to the concert-pitch key signature.
  3. Apply this scale degree to the transposed key signature, hence calculating the transposed pitch and accidental.

I like this alternative. I feel like this behavior will get us closer to the result we want, although it does require the reading algorithms to know that you always use F# in G major. The catch comes on the in-between notes that do not (technically) have a scale degree. For instance, do you use E# or F-natural in G major, the answer to which depends on which one reduces the number of visible accidentals in the measure. This is usually exemplified as using sharps on the way up and flats on the way down in C major. I assume this corresponds to sharps up and naturals down in "sharp" keys and naturals up and flats down in "flat" keys.

Hooks for specifying transposition behavior

The trickiest part about this whole thing is providing hooks to customize the above algorithms at just the right conceptual level. I'll spell out some alternative solutions, so that you can see how complicated this can get.

Option 1. At the lowest level, each <note> could specify its concert pitch/accidental and transposed pitch/accidental:

<note pitch="D5" accidental="natural" transposed-pitch="Fb5" transposed-accidental="flat"/>

How about this (Option 1b.)

  <note pitch="D5" accidental="natural">
       <transpose fifths="7" pitch="E5" accidental="natural"/>
       <transpose fifths="-5" pitch="Fb5" accidental="flat"/>
  </note>

This would only be used if the standard algorithm won't get the transpose right or if there is a courtesy accidental or something similar.

Encoding written versus sounding pitch

Oh, no. I'm bringing it up again. The question of whether MNX should encode written or sounding pitch (#issue #4) was a huge, passionate discussion — and we landed on encoding written pitch. However, having thought through the repercussions for transposing instruments, I believe this was a bad decision that we should revert.

Yay! I was never a fan of written pitch. This does leave an ongoing issue for what to do with pieces that do not have a "concert score" and therefore do not have a note spelling for their concert pitch. Do they just specify "transpose" pitches and leave out the concert pitch/accidental entirely?

--Christina

@mdgood
Copy link

mdgood commented Nov 22, 2022

This looks like a great starting point. I was one of the advocates for written pitch in MNX. But indeed this issue demonstrates the problems with that choice for MNX. MNX's main use cases are not the same as MusicXML's main use cases, so the design choices that work for MusicXML are not necessarily best for MNX. Let's fix this now while we can.

Here are some thoughts on some of the design issues:

  1. I don't think transpositions can be usefully specified for notation just with chromatic steps. You need to have diatonic steps as well. In MusicXML the diatonic encoding is optional, but I recommend making it mandatory in MNX. I think this is a case where MusicXML's selective encoding makes things more difficult than needed for use as a native format.

  2. I recommend representing transpositions with a <transpose> element that is a child of the <directions-part> element, similar to how <clef> works. Like clefs, transpositions can change midway through a piece, especially for parts for doubling instruments (like an Eb alto sax doubling flute in C or clarinet in Bb).

  3. I like option 2 in the hooks for specifying transposition behavior. As mentioned, we really will need a per-note override available. I would like to see if we can use the proposed enharmonic-shift attribute rather than providing the spelling. That would eliminate cases of inconsistent spelling data, where applications would have to figure out which conflicting information to use and which to ignore.

  4. I'd like to see if we can put the use-transposition attribute at a layout level where you specify concert or transposed encoding just once per layout, not allowing a combination of concert and transposed in a single layout. Octave-only transpositions can always be displayed whether in concert or transposed layout (one reason to have the octave-change part of the transposition encoded separately). I don't think we need to support an option where octave-only transpositions are not displayed in concert scores, but if people have repertoire examples that indicate otherwise it would be great to see them.

@adrianholovaty
Copy link
Contributor Author

@clnoel wrote:

Are we forming this explicitly for transposing instruments or in order to allow a single piece of music to define multiple transpositions of the same piece (e.g. for different vocal ranges)?

That's a good question. I'd been thinking only about transposing instruments, but we could handle that other use case effectively "for free" by putting the transpose value in the layout. It's an enticing idea.

I'm trying to think through the repercussions. The main downside I've come up with is: it's useful for a <part> to know its "default" transposition. Relegating that data to a layout (where it might be one of many layouts) seems like it loses semantic value. One concrete example is if the notation application wants to provide an "Edit instrument" UI — users would expect the transposition to be editable here, as opposed to a level of indirection like "Edit layout."

Maybe we could retain transpose within <part> but allow it as an override within a layout?

I feel like this is unnecessarily complicated. Let's just specify it: transpose-key="+2" moves from Bmajor to C#major. If we wanted Dbmajor, we would use transpose-key="-10".

Nice idea — I think that's a good approach.

How about this (Option 1b.)

<note pitch="D5" accidental="natural">
     <transpose fifths="7" pitch="E5" accidental="natural"/>
     <transpose fifths="-5" pitch="Fb5" accidental="flat"/>
</note>```

This is interesting in how explicit it is (and I wouldn't have thought to use subelements under <note>, so thanks for opening my mind on that). However, I think the flexibility leaves a bit too much room for error (by allowing encoding of any arbitrary pitch), and it's also slightly redundant. I agree with @mdgood's point number 3 on this.

Yay! I was never a fan of written pitch. This does leave an ongoing issue for what to do with pieces that do not have a "concert score" and therefore do not have a note spelling for their concert pitch. Do they just specify "transpose" pitches and leave out the concert pitch/accidental entirely?

That's the Achilles' heel of the sounded-pitch approach, for sure. Applications would need to "backfill" the concert pitch value for each note and choose a note spelling algorithmically. In practice, this likely wouldn't matter — since the application wouldn't actually be rendering the concert pitch value. My biggest concern would be the cognitive overhead for developers, because transposition can be so brain-melting (maybe I just speak for myself!). Our documentation, plus reference implementations/tests, would have to do some heavy lifting here.

@adrianholovaty
Copy link
Contributor Author

@mdgood wrote:

I recommend representing transpositions with a <transpose> element that is a child of the <directions-part> element, similar to how <clef> works. Like clefs, transpositions can change midway through a piece, especially for parts for doubling instruments (like an Eb alto sax doubling flute in C or clarinet in Bb).

Could this type of transposition change be considered an instrument change? If so, that would be handled by the layouts system. The two instruments would be encoded as two separate <part>s, and they'd be combined into a single stave via layouts.

Are there cases in which the layouts system wouldn't work (or would be super awkward)?

@mdgood
Copy link

mdgood commented Nov 22, 2022

@adrianholovaty It's an instrument change, but it's not a player change. Requiring individual instruments to be encoded separately when intended to be played by one person seems like it might be overly complicated.

To me, layouts seem more useful in encoding different arrangements of players. For instance, do 2 players share one staff - Trumpet 1 & 2 - or do they each have a separate staff? Often the answer is different for score and parts. That's perfect for layouts.

But if one player swaps instruments, what's the benefit of encoding them separately? This isn't something that tends to get displayed differently in different contexts. So where are the cases where that's beneficial, rather than just adding complexity? I could easily be missing something, so these aren't rhetorical questions.

@mscuthbert
Copy link
Contributor

mscuthbert commented Nov 22, 2022

A little bit more thought:

The <part id="Clarinet" name="Clarinet in B♭" transpose="-2"> should probably need to have a diatonic and a chromatic attribute.

One of the many issues that come up is with extreme sharps (or flats for the few instruments like G alto flute on the flat side of transposition). If there's a passage with many sharps, then the transposition strategy often depends on the musical context and whether or not the passing involves a change of key signature. Generally any key signature change that involves more than 7 sharps will always be rewritten in flats (and even most that require 7 sharps and many that require 6 [fn1]); this involves treating the Bb clarinet as essentially an A# clarinet (it's how I do it in Finale/MusicXML) where the chromatic remains -2 but the diatonic becomes 1. In many pieces, I will do several instrument changes from Bb to A# clarinet, always hoping that these changes are not visible to the reader.

However the same notes without a key signature change are quite likely to be written with the extra sharps since there's no problem of an F## key signature. But then in a context that approaches atonality, many individual notes are enharmonically swapped and not in a systematic manner but one that takes into account context (were you just on C#? then D# is probably better than Eb...unless you're going to D-natural next). So I don't think Option 3 will work (and it forces more implementation by consuming agents even if they don't care about such things).

Also Option 3 does not allow use cases such as multiple simultaneous transpositions happening on the same part. This is very common in cases of 17th and 20th c. violin scordatura where certain notes sound differently than how they are written depending on which string they are specified to be played on. Or for split octave harpsichords, where the lowest octave often repurposes the black keys to extend the range of the instrument. (For instance, a harpsichord with lowest note C2 often tunes C#2 to sound as G1 to get a [rather pathetic sounding] dominant below). These are not the cases that one builds a specification around, but it's always good to be able to support them when possible; otherwise when the system becomes successful they will be asked for. Notating transposed-pitch="..." when it conflicts with the current transposition allows that.

Between option 1 and option 2 -- if we go to an accidental-display='true/false' type world together with transposed-pitch="Fb5", does that solve all the problems? I don't think so. The example would be something like (concert pitch) C# D# E# F# A | Ab G Gb F E C (w/ | as a barline) which a naive transposition for clarinet might be D# E# F## G# B | Bb A Ab G F# D but which a composer or performer might want to remove the double-sharps and use only flats and naturals on descent, so they would prefer Eb F G Ab Cb | Bb A Ab G Gb D. But now there's some problems: the D# wants an accidental=true in concert pitch but transposed accidental=false, and the second note of the second measure (G) is probably accidental=false in the concert pitch, but in transposed pitch it wants accidental=true to display as A-natural because there was just recently an Ab. If we remove the barline, then the accidental=true becomes mandatory.

A couple of possible solutions:

  1. add a transposed-accidental attribute to <note> to deal with this. But then do we need transposed-accidental-editorial and transposed-accidental-cautionary as well? Are we going to end up duplicating the entire note attribute hierarchy in order to do this? That doesn't seem so good.

  2. use the Note Id (<note id="...">) to specify a set of overrides in the <part-layout> element giving it a content which is no longer empty (or putting this elsewhere). such as:

<note-overrides>
    <note overrides="...noteid..." pitch="Fb5" accidental="flat" cautionary="true"/>
</note-overrides>

Just some half-baked thoughts.

[fn1] -- the reason for some instruments such as saxophones, trumpets, etc. switching to flat key signatures even at 6 flats, despite the fact that their instruments being on the "sharp" side of the transposition spectrum (which you might think would make the players more used to reading sharps) is that many of the instruments and thus their players (especially semi-professional and below) are often more familiar band music which is more often associated with flat keys than with orchestral music (which because of the tuning of strings favors sharp keys). Plus with melodic minor, the key signature is not always a perfect predictor of the notes to expect.

(Edit to add: I started this comment before the rest of the comments came in and I didn't see them until after I hit Comment, so I wrote them without taking the other new ideas into account)

@mscuthbert
Copy link
Contributor

mscuthbert commented Nov 23, 2022

@mdgood wrote

I don't think we need to support an option where octave-only transpositions are not displayed in concert scores, but if people have repertoire examples that indicate otherwise it would be great to see them.

I definitely know I've seen cases where the "C"/"Concert" score has clefs with 8s attached to the clefs (so they are technically at written pitch) but where the parts do not.

Behind Bars, p. 255: "It is unnecessary to use octave-transposing clefs in a playing part, but they are helpful in a score"

Btw -- we haven't even gotten into this scenario (BB p. 33)

Screen Shot 2022-11-22 at 13 58 39

@mscuthbert
Copy link
Contributor

mscuthbert commented Nov 23, 2022

@adrianholovaty wrote:

Maybe we could retain transpose within but allow it as an override within a layout?

I'm glad we're on the same page as thinking of defaults and overrides. I agree that there is a semantic point to having a default transposition for a part/instrument.

@clnoel 's idea about encoding specifications for different transpositions has a lot of potential use cases. I hadn't considered it at all, but definitely worth thinking about

@mscuthbert
Copy link
Contributor

further on:

@mdgood wrote

I don't think we need to support an option where octave-only transpositions are not displayed in concert scores, but if people have repertoire examples that indicate otherwise it would be great to see them.

Berg Violin Concerto writes the Piccolo, Contrabassoon, and Double Bass parts at pitch:

Screen Shot 2022-11-22 at 15 53 42

(it's also one of the standard examples of slurs crossing player boundaries and cross-stemming to ossia staves)

Source credit: Donald Byrd, "Written and Sounding Pitch" (https://muse.jhu.edu/article/315059/pdf) which is an amazing resource for this discussion, even if quite a number of examples are too obscure for MNX to be built around. Timpani parts that omit accidentals (and thus need different transpositions per note)

@clnoel
Copy link

clnoel commented Nov 28, 2022

Maybe I'm getting into the weeds here, but I would like to clarify (for agreement) that we are not trying to encode "hypothetical" or "automatic" transpositions here. Any score that is encoded in an MNX document is one that an author has explicitly created, either for score-and-parts or for alternate voicing (e.g. several transpositions of the same solo piece for different instruments or vocal ranges).

For example, Musicnotes has a free song of the month that is always available in guitar tab, piano + solo, C-instrument, F-instrument, Eb-instrument, Bb-instrument, bass-clef, and viola. All of the transposed scores are explicitly created and defined by our publications experts. (Sorry if this sounds promotional, just trying to make an example). It would be convenient to be able to specify all of these versions in one MNX document, but I would not expect an MNX document that just had piano+solo to "correctly" produce a transposition to F-instrument. Are we agreed on this?


About player/instrument and "part", @mdgood wrote:

Like clefs, transpositions can change midway through a piece, especially for parts for doubling instruments (like an Eb alto sax doubling flute in C or clarinet in Bb).
It's an instrument change, but it's not a player change. Requiring individual instruments to be encoded separately when intended to be played by one person seems like it might be overly complicated.

Our specification allows for a sequence to be given a label voice which could be referenced by a part-layout. When I originally proposed it, I was envisioning this as allowing allowing a soprano part to have a sub-part for "second soprano" that didn't have to exist for the whole piece, but could still be called out as split-stem in a layout. Maybe this functionality would be useful for what you are trying to get at here? We can specify transpose-key in the layout for just the voice that is the doubling instrument.

Note: This is leaving aside the fact that I believe that "parts" are for instruments and "layout/score" is for the person (player or conductor), which might be a separate debate.


@mscuthbert
We have a lot of parts-only notation like the ottavas you describe that we haven't gotten to. I think we are generally intending to label these (in a css-esque manner) and use or not use them in layouts as needed. I believe that those might be out of scope, for now.

We also haven't gotten around to layout-specific clefs. However, we could put an entire octave shift in a layout using

<part-layout part="Violin" transpose-key="0" transpose-pitch="+12"></part-layout>

Note: I now think that the transpose-key that I specified above is not human-understandable. I think transpose-by-fifths (or something similar) is better.


I honestly don't know enough music theory to weigh in on chromatic/diatonic default transposition specifications. I will probably get it wrong if a transposition is imported without a note spelling unless someone lays out an algorithm very specifically. This whole thing is designed to be primarily machine readable/writable, but with humans being able to check up on it without being confused. Given that we are not going to be writing these by hand when we get around to actual use, is it really a bad thing to be specific about each note, given that both the original and transposed spellings actually exist somewhere else (reference document, internal representation of creating program, etc.)? Isn't it easier to just write it down, rather than checking it against the algorithm to find out if we need to? Are we worried about file size (I'm not)? Incorrect spellings, so that sounding and written end up off from each other?

--Christina

Note: I think the solution to "no concert-pitch score" is to write in the midi-pitch that is supposed to play, but I'm willing to adapt.

@mscuthbert
Copy link
Contributor

@clnoel wrote:

Given that we are not going to be writing these by hand when we get around to actual use, is it really a bad thing to be specific about each note, given that both the original and transposed spellings actually exist somewhere else (reference document, internal representation of creating program, etc.)? Isn't it easier to just write it down, rather than checking it against the algorithm to find out if we need to? Are we worried about file size (I'm not)? Incorrect spellings, so that sounding and written end up off from each other?

The three possible downsides I can think of of encoding the sounding and part-written pitch for each note (especially for systems using MNX as an internal data structure) are:

  1. If the score is displayed in concert pitch (and obviously playback always comes from concert pitch) then you're asking for a transposition to be created after each note is edited even if it's never displayed to the user or used.
  2. it requires MNX implementers to have a diatonic transposition algorithm if they want to round-trip a transposed part even if they don't deal with written pitch ever. It's not the easiest thing to implement so it might hurt adoptation of MNX.
  3. from a security/data-integrity standpoint, it's easy to end up writing out notes that might not be supported by the implementation. For instance, I might write the note "Dbb4" in my system which supports up to double-sharps/double-flats, but if someone gives a transposition of Diatonic=2 Chromatic=0 (write up a second, but sound the same) then I need to write out Ebbbb4 which might crash my software. So it becomes a second place to check for out-of-bound pitches that software writers might not consider.

(btw -- this might still be the opportunity instead of using musicians' terms like diatonic=2 chromatic=2 to mean a major second, to do something more computer oriented like name-shift=1 semitone-shift=2 so that there isn't that gap between 3, 2, 1, -2, -3. The amount of code I've written over the past 20 years to deal with invalid inputs like P-1 (descending perfect unison) or M0 (major zeroth? wtf!) probably amounts to a day's work by now.)

@clnoel
Copy link

clnoel commented Nov 29, 2022

@mscuthbert

For reference, I am still advocating for this explicit notation (possibly altered by whatever we decide in #288 ) for every note:

  <note pitch="D5" accidental="natural">
       <transpose fifths="7" pitch="E5" accidental="natural"/>
       <transpose fifths="-5" pitch="Fb5" accidental="flat"/>
  </note>

The three possible downsides I can think of of encoding the sounding and part-written pitch for each note (especially for systems using MNX as an internal data structure) are:

  1. If the score is displayed in concert pitch (and obviously playback always comes from concert pitch) then you're asking for a transposition to be created after each note is edited even if it's never displayed to the user or used.

This is an advantage to me. If the editing program doesn't care about transpositions, it can scrap the transpositions entirely when saving the MNX document. If it does care, then you want changes to the concert score to be reflected in the transpositions.

  1. it requires MNX implementers to have a diatonic transposition algorithm if they want to round-trip a transposed part even if they don't deal with written pitch ever. It's not the easiest thing to implement so it might hurt adoptation of MNX.

Once again, if you don't care about written pitch... then don't care about written pitch. If you are an audio-only or concert-pitch only app, then just ignore the transpositions. Leave them out of your internal model and out of any exported MNX document. If you do care about transpositions, then you can write an automatic diatonic/chromatic algorithm to generate transpositions (which will then probably need to be hand curated to look nice).

  1. from a security/data-integrity standpoint, it's easy to end up writing out notes that might not be supported by the implementation. For instance, I might write the note "Dbb4" in my system which supports up to double-sharps/double-flats, but if someone gives a transposition of Diatonic=2 Chromatic=0 (write up a second, but sound the same) then I need to write out Ebbbb4 which might crash my software. So it becomes a second place to check for out-of-bound pitches that software writers might not consider.

Which is why I like putting in exact spellings, not using diatonic/chromatic at all. If you are displaying the transposition on screen, you will be using the transposed note spellings instead of the regular note spellings, which means you will be checking them just as you would the regular spellings.

@mdgood
Copy link

mdgood commented Dec 6, 2022

Catching up on a few things from this discussion:

  1. @clnoel I think that forcing applications to write transposed note spellings is not appropriate for MNX. For a native format for interactive applications, I don't think changing a transposition should require changing every note in the part. It should just require one change.

Requiring the transposed spelling of each note will also lead to data inconsistency. If we specify the transposition with a chromatic / diatonic pair, and then allow an enharmonic change with a flip up or down, we can't get data inconsistency.

MusicXML gives applications far too many changes to encode inconsistent data with the duplication of sounding and visual data. We have found that when you give applications a chance to get it wrong, since they're programmed by people they will indeed get it wrong at some point. Dealing with inconsistent data is a pain for consuming applications. Let's remove that trap here like we remove it elsewhere in MNX.

  1. @clnoel I'm not quite sure what you mean about automatic transposition in apps. But if somebody changes a part from concert pitch to a transposed part, I would expect most music notation apps (including MNX apps) to give a decent first cut at that automatically. It would often need tweaking afterwards with manual enharmonic overrides.

  2. @mscuthbert Different clefs in score and parts are already handled in MusicXML with the <for-part> element so this should be straightforward to bring over to MNX. Treble clef for bass clarinet parts is a common use case there, as shown in the example.

  3. @mscuthbert I recommend scordatura be handled separately from transposition, using a tab-like representation similar to what is done in MusicXML. I don't know if any applications handle scordatura semantically yet, so we don't really know if the MusicXML scordatura design is that good. But I think it's out of scope for this issue.

  4. @mscuthbert Thanks for the Berg example! To clarify, the parts are displayed with an octave transposition and it's just the score that's at pitch, correct? If both parts and score are at pitch, then this wouldn't seem to apply.

adrianholovaty added a commit that referenced this issue Jan 17, 2023
…itch.

See #287 for discussion.

No example documents needed to be changed, because we don't
yet have any examples of transposing instruments. The
'Octave shifts (8va)' example document was already working
as expected, with the sounded pitches encoded.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants