Implement temperament playback in MuseScore

• Feb 25, 2016 - 12:50
S4 - Minor

Currently MuseScore plays note in equal temperament, except if the soundfont is tuned different.
However, it's possible to tune each note individually. This tuning is stored in the mscz file. The tuning is sent to Fluidsynth which will play the soundfont with this tuning offset.

Started from there, Miwarre implemented a plugin in MuseScore 1.3 that would load SCALA files and apply the tuning to each note. Unfortunately that was a one time operation, a moved note, or a new note wouldn't obey the scale since it was only applied once and forgotten.

On github, @sraduvictor made an experiment to duplicate this feature in MuseScore 2.0 core. It's limited to 8 steps per scale for now. In any case, it will have the same limitation than the plugin above.
His use case is Byzantine music but of course it would be good to extend this to more temperaments. In particular the ones which can be currently properly notated with MuseScore (I mean without microtonal accidentals for now) : 7 notes, 12 notes (#/b), 17 (Gb - A#) and 21 (Fb - B#) (maybe even 35 the total number of pitch classes in MuseScore for now).

Next attempt by @sraduvictor is to apply the scale to the score and keep it with the score. New notes would be played according to the scale. But then more questions:

1/ Is a temperament a property of a score or an instrument? a staff?
2/ Does a temperament change during a score?
3/ A temperament should affect the tuning property of a note? or should we apply it transparently and add the tuning on top of it? or the temperament is a style and we can override the tuning for a note?
4/ Probably for later, do we ship some temperament in MuseScore? Do we let user create temperaments even without scala file? If yes, which UI?

Interesting point from Miwarre, the Scala format seems to be a good import format but not a good storage format since it lists the notes in pitch order without making a difference for enharmonic.


Some question that came up in irc :
- Is there a case where we would use different scala files for each instrument?
- Should the tuning of the scala file be invisible and applied only on playback, or should it affect the tuning property of the note, so that the user can only update it, and not set an offset to it?

1. In practice, temperament is a property of a score.
2. In practice, temperament doesn’t change during a score.
3. In practice, it’s not necessary to override tuning for a single note. We just need to be able to set some tuning for the whole score.
4. I don’t see a need for a temperament editor in MuseScore, as Scala files are standard and easy to create in any text editor (but please see my question at the end of this comment).

When I say “In practice”, I mean in any common situation. Other possibilities are not ruled out, but they are rare. M. Gavioli is right when he says Scala can’t make the right decision if C# > Db, but in fact, anything more than 12 different pitches in an octave is also not very common in western music (used especially in medieval and renaissance period or in a capella singing). Yes, MuseScore supports 35 notes, but in practice they use just 12 different pitches (enharmonically). For example, many music instruments simply cannot play more than 12 different pitches in an octave at a time (they must be always retuned to use some other set of 12 pitches). Most of the historical temperaments also use only 12 different pitches. Nevertheless, I think anything more than 12 different pitches in MuseScore is nice-to-have (ideal is 35), but 12-note standard Scala files should also be supported, because they are pretty much standard for the very most of the western music.
It would be great to have some baroque (or renaissance) orchestra player here to tell us more.

Question to M. Gavioli: Is it a problem, if we just can’t define C# > Db etc.? Can you provide some example temperament, where you need this case?

Here it is:
35 notes: Fbb, Cbb, Gbb, Dbb, Abb, Ebb, Bbb, Fb, Cb, Gb, Db, Ab, Eb, Bb, F, C, G, D, A, E, B, F#, C#, G#, D#, A#, E#, B#, F##, C##, G##, D##, A##, E##, B##
21 notes: Fb, Cb, Gb, Db, Ab, Eb, Bb, F, C, G, D, A, E, B, F#, C#, G#, D#, A#, E#, B#
17 notes: Gb, Db, Ab, Eb, Bb, F, C, G, D, A, E, B, F#, C#, G#, D#, A#

1. You just need 1 Scala file for a score.
2. Yes, I think offset is not necessary (at least for now).
Well, that is just my opinion. What do others think?

Do you happen to know the order of the notes in a Scala file when 35 are mentioned?
They way I'm reading them is : D_BB, C_S, D_B, D, E_BB, D_S, E_B, E, ...

(Note for the non-familiar with MS nicknames: I'm the same as the Maurizio Gavioli posting on github.)

More than 12 notes per octave:
Well, it is more common than often thought. Keyboard instruments are the notable exception, but all stringed instruments (included fretted instruments like lutes and viols), voices, and almost all wind instruments can play 'true' scales. And, in fact, good players (think of good string quartets) do it in many repertories.

'True' scales are very well suited to pre-Romantic Western music, which covers several centuries and can hardly be considered an exception.

Historic temperaments often only have 12 notes, because they are addressed to keyboard instruments; for instance, string instruments can do without temperaments, as they can play the correct intervals on a case-per-case basis, using a more-than-12-note scale.

Currently, MuseScore does not do this, because it uses MIDI as playback reference, and MIDI does not directly support 'true' scales. However, as seen in the past, it is possible to add this, via plug-ins (as for ver. 1.3) or possibly within the main code itself, as sraduvictor is proposing.

(Incidentally, implementing this in the main code and on-the-fly during playback, as in sraduvictor proposal, would be a major break-through!)

So, I remain convinced that any implementation of scales/temperaments in MuseScore should support more than 12 notes. In fact, supporting the full range of 35 TPC's would make the code so simpler than it would be curious not to do it.

Finally, note that supporting 35 notes per octave automatically means that all (or most) less complete scales are supported via trivial fill-up code (the 1.3 plug-in already contains such code). As I see it, MuseScore internally should only knows about 35 note per octave scales.

Note ordering:
As I already said in the github comments, for instance, in the Zarlinian scale C# < Db (and most other pseudo-enahrmonies as well), while in the Pythagorean scale C# > Db. So deciding which is which is vital.

Scala format:
The last time I looked at it was several years ago, while developing the 1.3 plug-in, but I doubt anything changed in the meantime. If I am wrong, please correct me.

The Scala file format lists the notes in pitch order, without qualifying them with the proper Tonal Pitch Class. In the cases described above, it would be impossible to tell which is the C# and which is the Db.

(Indirectly, this also answers #7: there is no note order in Scala files, notes follow in whatever order their pitches dictate).

I'm not saying that Scala is 'wrong'; possibly it is aimed at something else; what comes to my mind is a kind of ethno-musicologist approach, where the actual pitch of a note is much more important than its name (which is usually culture-dependent). Different is the approach of the musician, for whom the place a note has in the musical system is as important as its pitch (and, occasionally, even more important).

However, IMHO, this makes Scala format unsuitable as a property of a MuseScore file, as it would require some heuristics (or, worse, asking the user) each time each note is accessed.

In fact, again IMHO, the only order which would make sense in MuseScore is by TPC.

Coming to lasconic questions:

1) Scale/temperament applies to? In practice to the score as whole, as already said. There might be occasions where different scales for different instruments could be desired (a violin accompanied by an harpsichord, with players particularly fastidious...), but it really seems to "look for a hair in the egg", as we say in Italian...

2) Scale/temperament does change during a score? During a single piece definitely not. But from piece to piece within a single file, it might be possible. So, if possible, I would not close this route since the beginning. Even if this would not be implemented right now, I would leave open the way for scale to become a map of some kind. Limiting the change to a section break (reducing the on-the-fly look-ups) could make sense, though.

I would rate this point as no more than "nice to have", though.

3) Scale vs. note tuning property. My opinion is that the two should coexist, if at all possible, as I think the user should be able to locally override the scale setup.

Whether the note tuning property should replace the scale tuning or add to it, I cannot say right now; possibly a user-specified tuning should be taken literally, regardless of the current scale, as this would make things easier for the user, But this is just an opinion.

4a) Include built-in scales/temperaments in MuseScore? Definitely yes!!! It would look very strange otherwise. I agree that deciding which ones is likely to start religion wars, but we can easily afford to be inclusive.

4b) Include an editor? Definitely yes!!! Again, it is the obvious choice. Also taking into account that the editor of the old 1.3 plug-in can be used as a complete, working base.

As an aside: having 35 notes per octave, in addition to its basic cleanness given MuseScore context, would also have the added benefit of allowing implementing the playback of micro-tonal and non-Western music.

For instance, as micro-tonal music usually (again, please correct me in I am wrong) does not use double accidental, it would be possible to map half-accidentals to them and having the correct playback. An example: G-half# is very near to Abb (at least in most Renaissance scales); in a context where Abb is not used, a scale could be defined where G-half# is mapped to Abb (and similarly for the other). In addition, the half# accidental should be mapped to -19 fifths in the playback code (which is a reasonable choice anyway).

Possibly, the same might be true for non-Western music (about which my knowledge rapidly approaches zero).

But all this may follow in due time of course. The way is open, though.

Thank you, for all your comments. As you already saw I made changes to the diff to read more types of scales (7, 12, 17, 21, 35), assuming the order that full note comes before bb which comes before s which is before b which is before ss which is before the next full note.

I think this format will work nicely with scala format and we won't have to edit too many scala files as most follow this approach. In case we need something else you can always edit the file you are importing, and in a future diff either Miware or me could add the possibility of editing the scale.

1) and 2) Initial implementation will be one scale per score, but it should be easy to change if there is need (just a small change in storing it and in using it in rendermidi)

3) I think we should have tuning as being an additive property, as it would be hard for a user to imagine that adding 1 cent to tuning causes such a big difference in playback, because scale tuning was setting it to -199.

4a) I agree we should have built in scales. There are 3 standard scales I'd like to add for byzantine notation : diatonic, soft chromatic and hard chromatic. But I don't see this as an urgent need if we can use standard scala files (which incidentantly map perfectly for byzantine notation).

4b) I agree again

@sraduvictor in #10:

"I think this format will work nicely with scala format": I disagree, but I already made this abundantly clear... <g>

"Initial implementation will be one scale per score, but it should be easy to change if there is need": it would be relatively easy code-wise; what more concern me is the file format: if the initial file format implementation stores this as a property of the whole file, changing to a property of a section or of a single staff may raise file format compatibility issues. But, as I said, the whole point is not so important.

"it would be hard for a user to imagine that adding 1 cent to tuning causes such a big difference in playback, because scale tuning was setting it to -199": it depends; for me, if I set a -10 cent tuning for a note, I would mean 10 cent below the default, without bothering to change the value (or maybe dozens of values I may have entered) if the score scale changes.

"I don't see this as an urgent need if we can use standard scala files": I am not as confident about the thaumaturgical properties of Scala files. They are a God-sent for the initiated, but forcing the average user to deal with thousands of cryptically named files, on another site than MuseScore's and so on, is not really user-friendly.

Very good to have that import feature, but the programme should come with a decent selection of scales/temperaments ready to use and clearly labelled with human readable names.

But all these are details. The most important point right now is to arrive at an implementation of the basic feature(s) as solid, easy to maintain and forward-looking as possible.

I asked advices to two french music teachers / composers who I know are well versed in temperament for one, and microtonality for the other (@skunt, @daeavelwyn guys, feel free to correct me if I'm wrong). And here is what I gathered:

It's a simplification (sorry if it's politically incorrect..) but there are 3 cases for temperament use:
1. Historical "european" music
2. Contemporary music (XIX to XXI century)
3. Traditional music (Arabic, Persian, Turkish, Brittain etc...)

1. is more or less notated with Common Western Notation (CWN) which is also the notation supported by MuseScore. So it's relatively easy to support new temperaments. We only have to map the 35TPC (which is currently very linked to CWN) to tuning offsets. So I would set this at a first goal. (Also it seems that some from 3. can be covered by this since they don't use other accidentals when mapped to CWN)

2. and 3., when notated and "standardized" often use additional accidentals. Some are already accidentals in MuseScore but do not currently define TPC (koron, sori, arrows accidentals etc...) and so are mostly graphical. Others are purely graphical and only available as symbols in Bravura (see the numerous accidentals categories here Proper support of these accidentals, also in key signature, would need to be achieve if we want a solid basis to apply temperament on. Anything else would be hacky...

According to @daeavelwyn, it's not rare for Arabic music to change from one temperament to another since it's basically constructed on modes of unequal temperaments. So that would push us in the direction of having a way to change temperament along the score. A bit like tempo text. However we know that moving from score style property to text along the score is doable, we did it for swing for example.

So, I believe we agree on the following.
1. One temperament per score
2. MuseScore shouldn't store Scala format since it's not suitable for notation. Only import it best effort (meaning with a given order) and then store TPC -> offset internally.
3. We should embed some temperaments, in MuseScore format then, not in scala. They should have translatable names.
4. We should have an editor. For a start, I would only use it for MuseScore TCP -> offset. As explained above, I believe microtonal accidentals need to be put in the framework nicely before we think about changing their tuning according to temperament.

Where we don't agree yet.
1. Whether the note tuning property should replace the scale tuning or add to it.

Maurizio, is your use case of "offset to default" purely hypothetical or not? I found the style approach elegant but I don't know if it would work practically: When a temperament is applied, the tuning of the note is changed accordingly and visible inspector, except if the tuning of the note has been modified before. Reset to style button would reset the note to the current tuning, changing the line of the note would eventually reset it to style too.

“When a temperament is applied, the tuning of the note is changed accordingly and visible inspector, except if the tuning of the note has been modified before. Reset to style button would reset the note to the current tuning, changing the line of the note would eventually reset it to style too.”
I think that’s really the way to do it. But definition from M. Gavioli has one weak point. What are default values for, let’s say, 6-notes scale?
So we would need to enable just 7 / 12 / 17 / 21 / 35 possibilities, where is pretty clear what is default pitch for a note (always just whole hundreds of cents).
Anyway, I think only “offset to default” and also “absolute pitch in cents” settings make sense. “Offset to actually selected temperament” doesn’t make any practical sense for me, it would just produce really unexpected results (without any meaning or musical sense) after changing global temperament in a score, where already are some offsets.

@lasconic, #12:

your synthesis is perfect and, for what is worth, I agree with all the points.

The remaining point about tuning offset is not very important for me: I expressed my preference but, should the final outcome be different, it would not be a big problem. The use cases I had in mind were not purely hypothetical but, at a second thought, would be hard to make independent from scale/temperament anyway (there were about making pure the major thirds and fifths in cadential and final chords of Renaissance pieces; but, of course they would depend on any tuning applied to the fundamental; so, tough luck!). in #13: “offset to default” and “absolute pitch in cents” are conceptually the same value, simply with a different origin. Anyway, we agree that "offset to applied temperament" would be unpractical.

"What are default values for, let’s say, 6-notes scale?": well, whatever the TPC's for those 6 notes happen to tell us!

The point is precisely sticking to the Scala format, with its inherent limitation, which is limiting to the few cases in which the meaning of each value can be figured out with a decent reliability. The system in itself can accommodate any contiguous subset of TPC's; for instance, the 19EDO temperament (of medieval origin), with its 19 notes per octave, nicely mappable to the Cb-E# range, would be easy to implement in MuseScore, but quite hard to read from Scala files...

Somehow I missed all posts from here since 2/25.

From what I understand, we should store the scale format under style so that it will be easier to change it if we get a request for it.
We should add default temperaments. I could only add byzantine default temperaments, but I'll let other people add other defaults.
But for tuning I don't understand what is the requirement. Should we :
- apply scale tuning only when rendering (easiest, but I guess not desired)
- when showing note tuning add scale tuning to it but don't actually change the note tuning property (tuning might be out of [-200,200] range)
- change note tuning property based on the scale tuning (might be hard to figure out everywhere where pitch and tuning are changed. If tuning goes out of [-200, 200] we might need to change the pitch, and if we have any logic that looks at the pitch we might need to change it back for that logic to work properly)