-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
fix: division by zero in compatmidirenderer #24839
Conversation
217d774
to
264810b
Compare
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.
It might be nice to keep the logic somewhat synchronised with TremoloRenderer::doRender
(as far as possible, of course, because there are also differences of course).
264810b
to
c34dd05
Compare
c34dd05
to
bcee79a
Compare
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.
Sorry, I realised that there are still some issues...
if (t == 0) { // avoid crash on very short tremolo | ||
t = 1; | ||
} | ||
double tpoch = muse::RealIsNull(tremoloPartOfChord) ? 1.0 : tremoloPartOfChord; |
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 took another look and this check appears to be unnecessary: just at the top of CompatMidiRender::renderTremolo
, we already have
if (muse::RealIsNull(tremoloPartOfChord)) {
return;
}
int tremoloEventsSize = static_cast<int>(static_cast<double>(chord->ticks().ticks()) | ||
/ (static_cast<double>(t) * tpoch)); |
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 believe the double
casts don't make a difference here: when (static_cast<double>(t) * tpoch) > chord->ticks().ticks()
, then the result of the division would be between 0.0 and 1.0, so casting that back to int
will still result in 0.
But you are changing the meaning of the code. Essentially, this is what's happening:
-(chord->ticks().ticks() / t) * tremoloPartOfChord
+chord->ticks().ticks() / (t * tremoloPartOfChord)
I think that's incorrect: if the whole chord were a tremolo, then (chord->ticks().ticks() / t)
would be the correct number of events; and if only part of the chord is a tremolo (i.e. tremoloPartOfChord < 1
) then (chord->ticks().ticks() / t) * tremoloPartOfChord
would be the correct number.
It looks like the calculation of tremoloEventsSize
can stay as it is (even extra casts to double would not have any effect); all that's needed would be to check that tremoloEventsSize
is not zero. If it is zero, then just do an early return, since the for
loop below would not be run anyway in that case.
Apart from that, the precision of the calculations could of course be improved, by utilising Fraction
and/or double
everywhere, i.e. in t
, tremoloEventsSize
, tremoloTime
, tremoloEventStep
; and cast to int
only at the very end. (Note that that ensures so that t != 0
, since that would only happen as a result of rounding errors.)
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.
Ok
Initially I had a problem in another branch and this branch just doesn't have this check which you've mentioned.
if (muse::RealIsNull(tremoloPartOfChord)) {
return;
}
And this more than enough.
Thank you for your help and time, @cbjeukendrup
Closing this PR.
No description provided.