Skip to content
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

Beats: Round positions to lower frame boundary on translate #4499

Merged
merged 2 commits into from
Nov 10, 2021

Conversation

Holzhaus
Copy link
Member

@Holzhaus Holzhaus commented Nov 3, 2021

This fixes the following debug assertion:

DEBUG ASSERT: "!m_endMarkerPosition.isFractional()" in function mixxx::Beats::Beats(std::vector<mixxx::BeatMarker>, mixxx::audio::FramePos, mixxx::Bpm, mixxx::audio::SampleRate, const QString&) at /home/jan/Projects/mixxx/src/track/beats.h:177

This fixes the following debug assertion:

    DEBUG ASSERT: "!m_endMarkerPosition.isFractional()" in function mixxx::Beats::Beats(std::vector<mixxx::BeatMarker>, mixxx::audio::FramePos, mixxx::Bpm, mixxx::audio::SampleRate, const QString&) at /home/jan/Projects/mixxx/src/track/beats.h:177
@Holzhaus Holzhaus added this to the 2.4.0 milestone Nov 3, 2021
src/track/beats.cpp Outdated Show resolved Hide resolved
@daschuer
Copy link
Member

daschuer commented Nov 9, 2021

Why we need to round at all?

I think our legacy beat grid has fractional frames anyway and our new format will support them as well. The only issue is when we save them as a beat map because it uses an int32, but that can be done at the final stage just before storing. That way we can easily get rid of it once we have a floating point enabled format.

@uklotzde
Copy link
Contributor

uklotzde commented Nov 9, 2021

Why we need to round at all?

I think our legacy beat grid has fractional frames anyway and our new format will support them as well. The only issue is when we save them as a beat map because it uses an int32, but that can be done at the final stage just before storing. That way we can easily get rid of it once we have a floating point enabled format.

Please avoid to extend the scope of PRs. This is not the place for discussing a major refactoring.

@daschuer
Copy link
Member

daschuer commented Nov 9, 2021

First I like to understand the reasons for the rounding. This is required to understand the whole change and decide if this PR is a good solution.

Without this, I would argue to just remove the assertion. This would be also a limited scope.

@Holzhaus
Copy link
Member Author

Holzhaus commented Nov 9, 2021

I think our legacy beat grid has fractional frames anyway and our new format will support them as well. The only issue is when we save them as a beat map because it uses an int32, but that can be done at the final stage just before storing. That way we can easily get rid of it once we have a floating point enabled format.

No, this is not correct. Both legacy formats (beatgrid and beatmap) store frame positions as int32:

message Beat {
  optional int32 frame_position = 1;
  optional bool enabled = 2 [ default = true ];
  optional Source source = 3 [ default = ANALYZER ];
}

message BeatMap {
  repeated Beat beat = 1;
}

message BeatGrid {
  optional Bpm bpm = 1;
  optional Beat first_beat = 2;
}

First I like to understand the reasons for the rounding. This is required to understand the whole change and decide if this PR is a good solution.

Without this, I would argue to just remove the assertion. This would be also a limited scope.

It's a minor issue, but for the non-technical user it's not obvious that unloading + reloading a track can result in a shifted beatgrid due to rounding. Hence, we always rounded the positions when mutating the beatgrid, not when only when saving it.

@daschuer
Copy link
Member

daschuer commented Nov 9, 2021

No, this is not correct. Both legacy formats (beatgrid and beatmap) store frame positions as int32:

I was referring the fact that you can have a beat at a fractional position when using beat grids, because the number of frames is unlikely a whole denominator of the number of beats.

In case of BeatMap every beat is forced to a int position because of the storage format.

So if we like to convert losslessly from one to another, we need to allow fractional end maker.

It's a minor issue, ...

Ah OK I understand.

But be aware that we have also users, insisting having int BPMs. We can only round one thing, the BPM or the frame.

Currently we have complex code implemented to round the BPM. The rounding to the lower frame here breaks it.
But it will be broken anyway after reloading. So your reasoning for now is OK.

I am only concerned that we build it deep into our business logic and have hard time to remove it once we are on the new format.
Can we build something around it that it is easy to remove later?

But I actually still prefer to just accept the rounding by storing during the transitional period, instead of creating to much work for it now and just proceed with removing the assertion.

@Holzhaus
Copy link
Member Author

Holzhaus commented Nov 9, 2021

I am only concerned that we build it deep into our business logic and have hard time to remove it once we are on the new format.

We had this explicit rounding on mutation with the legacy code, and we have it with the new code. This is just one instance where I forgot to add it. I don't think it makes sense to remove it only here, and I dont want to turn this tiny regression fix into a bigger rework of how frame positions are handled.

But be aware that we have also users, insisting having int BPMs. We can only round one thing, the BPM or the frame.

FWIW I don't think it makes sense to bother our users with a BPM display resolution of more than 2 digits behind the decimal point.

And the inaccuracy due to rounding fractional frame positions would be way less than 0.005 BPM, which means that users won't notice anyway.

But I actually still prefer to just accept the rounding by storing during the transitional period, instead of creating to much work for it now and just proceed with removing the assertion.

I'm not sure how the storage format will look like. Maybe we want to store marker positions as int32 frames as before. Or double frame positions? Or use a time-based format and use int64 nanoseconds?

At this point it would be more work to remove the assertion and be less correct with the legacy format IMHO. And we don't know if it becomes obsolete with the new format. So I suggest to just keep it for now and merge this PR as-is.

Copy link
Member

@daschuer daschuer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, than let's merge it. LGTM

@daschuer daschuer merged commit 21dacd6 into mixxxdj:main Nov 10, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

3 participants