-
Notifications
You must be signed in to change notification settings - Fork 48
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
Revert "Fix interaction between global offset and music rate." #300
Conversation
This reverts commit 343bbd0. Global offset is intended to compensate for input and audio latency in the PC used for playing. This latency stays constant regardless of music rate, so it's incorrect to multiply it. The original commit states that we need the multiply to arrive at the same position in the sound file regardless of music rate, but in fact we want the position to be different for different rates in order to compensate for the latency correctly.
This should fix Simply-Love/Simply-Love-SM5#557 |
Actually even though reverting the commit fixes the issue as described in the report (add 100s to song offset and -100 to global offset), I started getting second thoughts about if this is actually correct. I think I need to sleep on this a little bit and do some more testing of different cases. |
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.
Thank you very much for looking into this @phantom10111 .
Let's break down the commit you referenced:
In the original code, the GetBeatAndBPSFromElapsedTime
function modifies the elapsed_time by adding PREFSMAN->m_fGlobalOffsetSeconds
. Makes sense.
In Matt McCutchen's commit, the GetBeatAndBPSFromElapsedTime
function adds the product of GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate
and PREFSMAN->m_fGlobalOffsetSeconds
. This is wrong because it doesn't reconcile the differences in the different time formats correctly.
In Matt McCutchen's commit, the GetElapsedTimeFromBeat
function also incorrectly modifies the global offset value.
I dug up the PR that this came from, and I am not pleased with what I saw. My biggest issue with it is that it was known to break "haste" mode but they committed it anyway and said deal with it later if it breaks stuff. So I guess we are fixing it now. stepmania/stepmania#828
edit: happy ITGm issue 300 !
@@ -755,7 +754,7 @@ bool TimingData::DoesLabelExist( const RString& sLabel ) const | |||
|
|||
void TimingData::GetBeatAndBPSFromElapsedTime(GetBeatArgs& args) const | |||
{ | |||
args.elapsed_time += GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate * PREFSMAN->m_fGlobalOffsetSeconds; | |||
args.elapsed_time += PREFSMAN->m_fGlobalOffsetSeconds; |
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.
Instead of directly adding the global offset to elapsed_time, we should convert the global offset to the sound file offset. Then, we should apply the adjusted offset to elapsed_time
.
@@ -995,8 +994,7 @@ float TimingData::GetElapsedTimeInternal(GetBeatStarts& start, float beat, | |||
|
|||
float TimingData::GetElapsedTimeFromBeat( float fBeat ) const | |||
{ | |||
return TimingData::GetElapsedTimeFromBeatNoOffset( fBeat ) | |||
- GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate * PREFSMAN->m_fGlobalOffsetSeconds; | |||
return TimingData::GetElapsedTimeFromBeatNoOffset( fBeat ) - PREFSMAN->m_fGlobalOffsetSeconds; |
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.
We should also convert the global offset to the sound file offset here, then subtract the adjusted offset from the result.
After some testing I can definitely say that this revert isn't correct. I did some tests with introducing some offset at song level and then I could only get correct results with the revert applied. But I also did some tests with introducing offset at engine level (basically emulating severe audio lag) and then I could only get correct results without the revert. @sukibaby I'm not sure I understand your comment about converting the global offset to sound-file offset. Isn't multiplying by music rate doing exactly that? Purely from the point of maths, I don't have any other idea how to do it, either we multiply (and apply the offset in wall-clock time domain) or we skip the multiply (and apply the offset in music time domain). But I gave this issue a bit more thought and I don't think we can actually fix this easily (unless I'm mistaken about the math). But right now I'm thinking this - in the ideal case the song should be synced to 0ms and global offset only covers the audio and input lag. In that case we do the multiply and apply the offset in wall-clock time domain, which is what the code does currently. But in 9ms case the song is synced to 9ms and then global offset needs to account for audio and input lag + the 9ms. But the problem is that audio and input lag are both in wall-clock time domain (and therefore need the multiply), whereas the 9ms is in the song domain (and shouldn't be multiplied). So I right now I don't have any idea other than doing weird things like splitting global offset into 2 separate settings, or waiting until something like If I'm mistaken and we actually have all the information required to calculate this I'll be happy to hear it but right now I'm out of ideas. |
I think the problem is that beats and time in seconds are being mixed, which aren't the same time factor. So for
we could also optionally break early if |
regarding Simply-Love/Simply-Love-SM5#557 @phantom10111 you are correct in that we don't have all the information required to solve the issue for 9ms biased simfiles yet. With |
It seems to me that we need to be able to accurately determine the elapsed time and current BPM based on a given row, or we need to be able to determine the current beat. We can do something like this...
...and that should help us maintain greater accuracy than either keeping the current code or reverting to the old code. That code above needs to be tested better, especially by someone with a better sense of timing than I have, but it does build, so hopefully it works. |
The theory here is that converting the global offset to beats, instead of mixing beats and seconds, should keep the sync tighter when rate modding a song. The if-else statements inside TimingData::GetElapsedTimeFromBeat(float fBeat) and TimingData::GetBeatAndBPSFromElapsedTime(GetBeatArgs& args) only execute the new code if m_fMusicRate is anything other than 1. They are necessary because stuff will break theme side if it's not done like this. Without the if-else statements, the NPS display and density graph will be incorrect (at least in Simply Love). phantom10111 is listed as a co-author for their work on itgmania#300 Co-Authored-By: phantom10111 <3482004+phantom10111@users.noreply.github.com>
This reverts commit 343bbd0.
Global offset is intended to compensate for input and audio latency in the PC used for playing. This latency stays constant regardless of music rate, so it's incorrect to multiply it. The original commit states that we need the multiply to arrive at the same position in the sound file regardless of music rate, but in fact we want the position to be different for different rates in order to compensate for the latency correctly.