-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
[MU3] Fix #309371: Ambitus for transposing instruments doesn't update when toggling concert pitch #6494
Conversation
libmscore/score.cpp
Outdated
for (Element* e : segment->elist()) { | ||
if (e->isAmbitus()) { | ||
Ambitus* a = toAmbitus(e); | ||
a->updateRange(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the wrong approach.
Ambiti may be hand-edited in inspector (which I often do if there’s an optional extra note that can be left out that is rather out of a normal range). Toggling concert pitch should not update the range from the score; it must rather transpose the top and bottom notes the same as it does to regular notes in that stave.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I see. But a) how to and b) how to get it to work for octave transposing instruments too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is in the break
after the a->updateRange();
. Now the iterations stops at the first Ambitus
found but the segment might contain more Ambitus
's.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Segment, of course, more Ambiti in the same measure, but different staves! Bad thinko on my side I guess.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's better the move the Ambitus
loop outside the for (Staff* staff : _staves)
loop since you end up doing the same thing nstaves()
times.
This solves your first problem but still leaves the issue as mentioned by @mirabilos . I indeed do similar things, especially when newer instruments have a larger range (e.g. Baritone Saxophones, even Bb Clarinets which can be extended in the lower range)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still needs the check for whether the staff is transposing or not, at least as an optimization. Would solve (a good part of) @mirabilos' issue too, as there it is not about transposing instruments but human singing voices IIRC ;-).
So I added that check.
@mirabilos you can avoid the manual changes of the Ambitus by disabling "Play" for those extra notes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, bad, that change to skip non-transposing instruments/segments causes a crash :-(
Joachim Schmitz dixit:
Hmm, I see. But a) how to and b) how to get it to work for octave
transposing instruments too?
Probably by duplicating (or extracting and calling) the logic used
for these cases elsewhere in the code. Sorry, I didn’t look at this
from the code level, but I saw the change which, from a user PoV,
I think was incorrect.
|
I didn't check but that's related to "transposing" clefs? E.g. |
Yes (at least I think it is) |
Did a quick check, it seems to works for the first staff only. My example uses a Bb Clarinet and a Bb Bass Clarinet. Now the Bb clarinet staff works fine but the Bass clarinet remains it originals ambitus. Next, switch the staves (in the Instrument Form). Now the Bass clarinet is fine but the the ambitus of the Bb Clarinet is wrong. |
libmscore/score.cpp
Outdated
for (Element* e : segment->elist()) { | ||
if (e->isAmbitus()) { | ||
Ambitus* a = toAmbitus(e); | ||
a->updateRange(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is in the break
after the a->updateRange();
. Now the iterations stops at the first Ambitus
found but the segment might contain more Ambitus
's.
BTW: attach here is my test score (rename the |
e6d9864
to
f7a1a2e
Compare
OK, left to do: check for and obey manually changed ambitus |
642fa14
to
d4615e5
Compare
int tpcTop = 0; // Initialized to prevent warning | ||
int tpcBottom = 0; // Initialized to prevent warning | ||
int pitchTop = SCHAR_MIN-1; // just outside Interval::{chromatic,diatonic} | ||
int pitchBottom = SCHAR_MAX+1; // just outside Interval::{chromatic,diatonic} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better than some 'magic numbers' IMHO
int pitchTop = SCHAR_MIN-1; // just outside Interval::{chromatic,diatonic} | ||
int pitchBottom = SCHAR_MAX+1; // just outside Interval::{chromatic,diatonic} | ||
int tpcTop = Tpc::TPC_INVALID; // Initialized to prevent warning | ||
int tpcBottom = Tpc::TPC_INVALID; // Initialized to prevent warning |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't really matter here, but looks cleaner to me
@@ -621,7 +621,8 @@ void Ambitus::updateRange() | |||
segm = segm->nextCR(); | |||
} | |||
|
|||
if (pitchTop > -1000) { // if something has been found, update this | |||
if (pitchTop > SCHAR_MIN-1/* || pitchBottom < SCHAR_MAX+1 || tpcTop != Tpc::TPC_INVALID || tpc_Bottom != Tpc::TPC_INVALID*/) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Getting rid if the 'magic numbers'. Not sure whether to uncomment that commented part, or whether it matters at all, tcp_Top
always gets changed along with pitchTop
, tpc_Bottom
along with pitchBottom
, and I don't see how pitchBottom
could ever get changed without also changing pitchTop
or vice versa, so it seems save to assume that checking for one is sufficient.
for (Element* e : segment->elist()) { | ||
if (e && e->isAmbitus()) { | ||
Ambitus* a = toAmbitus(e); | ||
a->updateRange(); // TODO: honor manually modified ambitus |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here indeed we'd need to transpose rather than update to not loose 'hand-made' settings
@@ -2692,6 +2693,15 @@ void Score::cmdConcertPitchChanged(bool flag, bool /*useDoubleSharpsFlats*/) | |||
{ | |||
undoChangeStyleVal(Sid::concertPitch, flag); // change style flag | |||
|
|||
for (Segment* segment = firstSegment(SegmentType::Ambitus); segment; segment = segment->next1(SegmentType::Ambitus)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather leave this loop early for all non-transposing instruments (including percussion), but attempts to do so, like using code similar to the one in the below loop, leads to crashes when calculating the Interval
.
We'd get all that, if moving this block (back) into that loop, but at a cost: we'd now traverse the segments nstaves()
times, which really doesn't make much sense. The upside is that we gather the interval
, needed for transposing.
The problem with this is though, that while we can update multiple times, that'd just be a waste, we can't transpose multiple times...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we just add two Note objects into the innards of an Ambitus object, recreated upon reading from MSCX or creating the ambitus (i.e. transient, not stored by themselves), and set their properties to the respective highest and lowest note’s on update, and then use the usual transposition functions (epitch()
, ppitch()
, tpc1()
, tpc2()
, etc.) internally in the Ambitus’ functions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code sample?
I won't mind you to PR on top of mine ;-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wish I had any… but that’s going to be something major, and I’m behind on billable hours as is. Sorry.
d4615e5
to
e82ce14
Compare
e82ce14
to
94f64de
Compare
…toggling concert pitch
94f64de
to
fd62d12
Compare
3.x is closed for any changes |
resolves https://musescore.org/en/node/309371