-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Analysis: Add support for overriding variable/constant BPM on a per-track basis #10931
Conversation
9c0a13e
to
38da6bc
Compare
38da6bc
to
6e8196d
Compare
Re track menu implementation:
where [constant | variable] is the opposite of the current setting. |
Yes this would help to get rid of the redundant menu. The other issue is that it is not that clear what exactly is reanalyzed with "Reanalyze" when we have two other options where BPM is explicit mentioned. Some ideas for discussion
Or:
default [✓] is from the preferences option |
I think @ronso0's
strikes a good balance. The checkbox one is intriguing too, but I like the above one because it saves a click (since, in my experience, a user that wants to reanalyze is likely to pick the [opposite of setting] option, especially if they already performed a batch analysis using the default setting). |
8a69b47
to
798a603
Compare
Since we'd need to update the menus whenever the setting changes, is there an elegant way to hook into/listen for settings changes? Or would we need to add a new signal e.g. in |
You may pipe the userSettings pointer into the class and recreate the menu just before showing. The other option is to backup the preferences option with a ControlObject and consume the value change signal. I think you will find templaes for both in the Mixxx code. |
Hm, I'm almost inclined to do that in a separate PR to keep this one focused if it requires a lot of wiring to make the menu dynamic. |
That would be OK for me. |
Both m_pConfig->getValue<bool>(
ConfigKey("[BPM]", "BeatDetectionFixedTempoAssumption"),
true); and configure the Reanalyze actions accordingly. |
915a2f2
to
ab6ad67
Compare
Ah thanks, I wasn't aware of the |
We now have basically: You introduce std::not_null to justify the use of std::optional and this comes with a lot of surprising magic and is slowing down the process. I assume that you are coming from languages where the std::optional equivalent is the only solution to express a null value. This is not the case in C++ where a pointer is already an "optional". Also the used std::shared_ptr has the "optional semantic" https://en.cppreference.com/w/cpp/memory/shared_ptr/operator_bool. This is a well established pattern in C++ and I strongly recommend to use it here. Let's move the Track not_null idea to a separate PR. I think we should create our own not_null track class that fixes the performance issues. Apart form that, this branch works good. Thank you. |
I'd say it's more like std::optional<std::pair<
gsl::not_null<std::shared_ptr<Track>>,
AnalyzerTrack::Options
>> which is not isomorphic to the type you suggested: std::pair<
std::shared_ptr<Track>,
AnalyzerTrack::Options
> So I'd argue that even though the difference is subtle, they do have different semantics and I would also argue that the upper one is the more correct one (since it doesn't really make sense to specify options on a
I really don't think this is a fair assessment of the situation.
I agree, it's a common pattern to write custom
I have worked in a bunch of languages, including ones that implicitly permit
We already do a null check, so there's no performance overhead.
This only applies to |
@fwcd I appreciate your efforts to modernize the code base and fully agree with your arguments about "encoding invariants at the type-level". |
for what it's worth, using nullptr as an optional type has several shortcomings -- code can crash if it doesn't handle null correctly, and variables can end up being null even if they weren't intended to be so. std::optional is a good feature to make this use explicit and does not impose a lot of computational overhead. So I am in favor of using a more modern approach than using pointers-and-null |
I sounds like you did not get my point correctly. The remaining issue in this case is wrapping That needs to be solved! I and I have already recomended to move that out of this PR. Just to continue here ... |
@ywwg std::optional suffers exactly the same issue as plain pointer. If you access it without a check Mixxx crashes. |
Summary: I see two possible solutions:
|
This is pretty much what we are doing right now. Since Also while I agree that it's important to optimize, going with battle-tested (and optimized) standard library types like |
I have just realized that since: This is actually the case. My concerns where regarding the previous version, which has the described overhead. |
Wait, I have misread the code The changes where introduced to support std::unique_ptr() So my conclusion is still stands: We may add a wrapper header that defines Ideas? |
The docs explicitly state that there's no (space) overhead: https://github.com/microsoft/GSL/blob/1683d87a3f45dff1817e858dbaf006e5ff84e784/include/gsl/pointers#L74 (this is a permalink, but points to the current main branch). With "deep copy" I assume you mean "copying the pointer to a track and maybe updating its reference count"? But even if there were some overhead, I think vendoring our own version is not a good idea, for reasons mentioned in my previous comments:
This is really not a case worth micro-optimizing. Tracks added to the analyzer queue change maybe once every few seconds and |
I have found a related bug microsoft/GSL#550
This is regarding size. My concerns are regarding runtime.
Yes, it counts always fore and back and may empty the CPU pipeline because of memory fences.
Look, we compare here the traditional solution with a solution that aims to give a better semantic. Both are ways of optimization. I am happy with the later if it actually has close to zero overhead as assumed, but since this is not yet the case, let's go for the traditional solution. It would be also a good solution if the we remove the deep copy somehow. |
Hm, that's a fair point, I wasn't aware that What do you think about adding an assertion or check to |
Good idea. That works for me. |
...to make clazy happy!
As per the discussion: mixxxdj#10931 (comment)
ab6ad67
to
c04bae8
Compare
Done! |
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. I have just added some code style comments.
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 for this nice improvement. LGTM
This PR, intended as a follow-up to #4806, wraps scheduled tracks in
AnalyzerScheduledTrack
andAnalyzerTrack
, depending on whether it contains aTrackId
or a resolvedTrackPointer
.These wrappers add the ability to override analysis options on a per-track basis. This PR also introduced one such option, namely
useFixedTempo
, which can be used to override the constant/variable BPM setting. Additionally, it adds two new entries toWTrackMenu
>Analyze
:Any feedback is of course welcome!