Hi!
I've been looking into the way Notes with NoAccidental are handled, and
I think there's room for improvement. As far as I understand, when the
accidental of a note is unknown, it will get 'NoAccidental' and
Rosegarden will take a shot at guessing the accidental to display based
on context, especially the current Key.
The current strategy to guess the accidental for out-of-key notes is to
use the 'useSharps' property of the key: if a key is made up of sharps
(including C major), a sharp is always used, if it's made up of flats
(including A minor), a flat is always used.
I think this heuristic is not optimal, I'll give an example to explain:
suppose I have an Ab in F major, I do not need to respell it. Now I
transpose this piece up by a major second (both notes and key), yielding
a piece in G major. Because G major uses sharps, now there's an A#
(which is an augmented prime from the Ab instead of a major second,
which means it suddenly needs respelling).
A more elegant solution, at least imho, would be to base the heuristic
on the major/minor mode of the key and the distance in semitones of the
note to the tonic.
For example for major keys, you could use this table (per distance in
semitones to the tonic):
0: step 0 (in-key)
1: step 0, +1
2: step 1 (in-key)
3: step 2, -1
4: step 2 (in-key)
5: step 3 (in-key)
6: step 3, +1
7: step 4 (in-key)
8: step 5, -1 (or step 6, +1)
9: step 5 (in-key)
10: step 6, -1
11: step 6 (in-key)
For example in F major, semitone 6 would be step 3, +1, which
corresponds to Bb +1, thus yields B-natural. (e.g."C C# D Eb E F F# G
Ab(?) A Bb B" or "F F# G Ab A Bb B(!) C Db(?) D Eb E", etc). It's hard
to explain clearly, but I think I've got this worked out :).
This way, going back to my example above, the Ab in F major would get a
flat (since it's 3 semitones from the F). After transposition, it's
still 3 semitones from the tonic, so it still gets a flat, yielding Bb,
which is indeed a major second from Ab.
This is of course not perfect, but I think it will handle the common
cases better, and the rare cases not worse :).
As for how to implement this, sometimes you do want to get the
accidental using specifically sharps or flats - hence code like:
Accidental
Pitch::getAccidental(bool useSharps) const
{
return getDisplayAccidental(useSharps ? Key("C major") : Key("A
minor"));
}
This sounds like it'd make sense to add some constants:
NoAccidentalStrategy::useSharps (always prefer sharps)
NoAccidentalStrategy::useFlats (always prefer flats)
NoAccidentalStrategy::useKeySharpness (current behaviour)
NoAccidentalStrategy::useKey (behaviour proposed above)
and pass that into functions like getAccidental and
rawPitchToDisplayPitch, i.e.:
Accidental
Pitch::getAccidental(bool useSharps) const
{
return getDisplayAccidental(Key("C major"), useSharps ?
NoAccidentalStrategy::useSharps : NoAccidentalStrategy::useFlats);
}
or even:
Accidental
Pitch::getAccidental(bool useSharps) const
{
return getAccidental(useSharps ? NoAccidentalStrategy::useSharps :
NoAccidentalStrategy::useFlats);
}
Accidental
Pitch::getAccidental(?? strategy) const
{
return getDisplayAccidental(Key("C major"), strategy);
}
I'm willing to give this a shot, but I'd like to discuss it here first,
and of course I will put any patch up for review first before committing.
Regards,
Arnout
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Rosegarden-devel mailing list
[EMAIL PROTECTED] - use the link below to unsubscribe
https://lists.sourceforge.net/lists/listinfo/rosegarden-devel