-
-
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
Beats: Add editing controls for bar annotations #13330
Conversation
Just for completeness, #4489 was just a small part splitted of from this work: https://github.com/mixxxdj/mixxx/wiki/Measures-Downbeats-Bars-And-Phrases |
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.
haven't been able to look at the meat (beats.cpp
) yet. In the meantime, can you take care of CI failures. The inline annotations produced make it hard to review (and they need to resolved anyways, so better sooner than later).
Thanks for looking into this @Swiftb0y this quick! With my latest commit, I should fix most of the CI issues + failing test, and also started cleaning up some of the mess. Before looking too much into the code, I'd been keen to hear whether or not we are okay with approach I've taken from a UX perspective, and perhaps also gets some user testing first. As I said in introduction, I know there was a lot of discussion on the matter and I'd like to make sure this doesn't end up abandoned as well. |
636a042
to
b1967d9
Compare
With the last commit, I have introduce customizable beats per bar for each markers. To do so, I'm using a "double beat" in the beat map, meaning a beat with the same position that the previous one. This is used to infer the bar length. Pro: no need for a proto change @JoergAtGithub I tried many things but couldn't reproduce it. Could you please provide me with some steps and maybe a short recording? I'm probably missing a settings or something. |
And now I got the original again:
|
Right, my fault, The first one is related to the |
The link "here" doesn't point to a particular line of code. But I wonder if it's possible to add some code to the 2.4.2 release that just prevents the grid invalidation. And than merge this PR with the new beatgrid feature into 2.6. |
@JoergAtGithub I believe fixed most of the asserts and added some tests to cover the new introduced use-cases. I would appreciate if you could give it another go 🙏 |
94c256f
to
e06279c
Compare
e06279c
to
bc15b8d
Compare
It's worth to highlight the invalidation would only happen if one:
So while it feels quite an edge case, it may also feels fairly natural to need to regenerate the beatgrid to the user, so perhaps worth keeping as is. |
I tested again, and no asserts occured anymore!
The missing backward compatibility, was one of the main reasons, why the predecessor PRs got never merged. We need an commonly agreed strategy here. |
The markers in the waverforms are difficult to recognize. The visual representation in the original PR #2961 was more clear in my opinion: https://mixxx.zulipchat.com/#narrow/stream/109171-development/topic/beatgrid.20editing.20UI/near/206216183 |
Great to hear!
Make sense to me. What do you think of my proposition of backward compatibility, except if the multiple bar length feature is used?
Yeah it could be better I agree. The colour of the bar marker can be customised by the them. By default I wanted to have something not striking to much ( like the original red colour used before), but I guess we could find a middle ground. |
Overall, are we happy with getting this PR in as is? Just wondering if I should start looking at making it production ready, and clean up the implementation/fix conflict or of there is still outstanding controversial aspects. |
Well, the primary thing I'm confused about currently are the complications around |
One of the primary changes are that you changed the beatmarkers to store the beatlength instead of the total beatcount, right? Can you share some of the rationale behind that or link me to a previous discussion? |
I took the freedom to amend the changes directly to the commit.
Captured that in the issue so we don't block that PR |
@daschuer I think our long-term project experience of PRs of this kind is that it is unfortunately not possible to fix all the issues in large PRs before merge. This is one reason I try to insist on smaller PRs but that doesn't happen for a variety of reasons. After seeing this play out many times, I think the best approach may be to get it to "good enough" state and merge, then do fixes in whatever necessary followups. I do not love this mode of development and it leads to regressions, but after 15 years of working on mixxx I have seen more harm from developers getting frustrated than I have from bad code landing in the tree. I think it will also help if you better explain which of your notes are blocking vs which ones are not. Then we can go through and know exactly which issues are most important. My observation is often you make notes on PRs that are notes for the future and the author thinks it is a blocking comment. So if you can be explicit about this it will help make things easier. Do you think you can mark up your comments with this status by wednesday? |
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 have spotted some more issues. (sorry)
I like also finish my testing with the visuals before merge.
if (isDoubleBeat(beatPositions, i) && isBeatCounting) { | ||
isBeatCounting = false; | ||
beatsPerBar = static_cast<mixxx::audio::BeatsPerBar>( | ||
std::lround((std::floor(position - markerPosition) / |
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 using floor here is unnecessary. We must not use the long type in Mixxx, because it has different size on different targets. Position is audio::FramePos which is a double.
std::lround((std::floor(position - markerPosition) / | |
std::round((position - markerPosition) / |
isBeatCounting = false; | ||
beatsPerBar = static_cast<mixxx::audio::BeatsPerBar>( | ||
std::lround((std::floor(position - markerPosition) / | ||
previousBeatLengthFrames))); |
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 previousBeatLengthFrames be 0? Than we have diff by zero.
return nullptr; | ||
} | ||
auto position = beatPositions[i]; | ||
audio::FrameDiff_t beatLengthFrames = position - previousPosition; | ||
// If the current beat is a "closing" double beat | ||
if (isDoubleBeat(beatPositions, i) && isBeatCounting) { |
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 does assume that a beat_change_marker = double beat is a down beat, right?
We have discussed above, that the beat_change_maker can also be used to mark beat changes within a bar.
Since I consider this an exceptional use case this is OK for me to have than an incorrect beats per bar value.
However than it does not require a warning below.
if (!beatsPerBar.isValid()) { | ||
qWarning() << "Invalid bar definition found in the BeatMap:" | ||
<< beatsPerBar << "- Ignoring"; | ||
beatsPerBar = kDefaultBeatsPerBar; |
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 would rather keep here the invalid BeatsPerBar state. We can than consider indvidual set beats using beat_change_makers have no BeatsPerBar value = invalid.
The alternative would be using one.
} | ||
|
||
bool isDoubleBeat(const QVector<audio::FramePos>& beatPositions, int beatIdx) { | ||
if (beatIdx <= 0 || beatIdx > beatPositions.size()) { |
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.
if (beatIdx <= 0 || beatIdx > beatPositions.size()) { | |
if (beatIdx <= 0 || beatIdx >= beatPositions.size()) { |
I'm about to restart efforts to get this over the line. Just would like to confirm where are currently the vetos on:
Beat grid shift shouldn't be a blocker and I'm hoping my last explanation of the current behaviour will help lifting this one. @daschuer could you confirm this please? |
I don't understand stand the second point. My outer requirement is to not introduce unwanted padding beats. Once this is merged people will start using it, and may mess up the beat grid with padding beats. Let's go the safe route and not allow this here. Since this is anyway an intermediate step, we can iterate from there after gaining some experience in the alpha state. |
This is my trying to summarize #13330 (comment) and making sure I understood your issue well. Basically what i'm saying, it don't make padding, except if quantize is on.
Yes, unwanted == This would mean, with
with
Do we have an agreement? Padding beats are my must have since this is the core of #13308 |
I am sure we want the same final result since I can very much confirm #13308. Using Quantize, does probably not work well for "us". I say "us" because we have discussed to follow the "Respsys" approach and this has been dismissed because it does not allow to point to beats. With Quantize=On we can also not point to a beat, which makes the common GUI for the Quantize on/off approach hard to use/understand. We may decide to follow Respsys 1:1 though and revise our decision. Did you hat a chance to look at it. What are your pros and cons? What is the use case? Please confirm. We have discussed this alternative workflow: Lets imagine, you have an aligned beat grid in the first part of the track. You notice that at the end of the track the beats are no longer aligned. You seek through the track and find a first beat that is off. You cue the track to that beat by ears. And press "a button". Are we aligned with that? My Idea of the implementation is: Mixxx will automatically place a beat-change-marker at the previous down-beat, and adopt the new tempo from the distance between the placed beat and the beat-change-marker. It shall be close to the old beat, so maybe it is required to place a number of beats in between to not create insane low tempos. After that you can adjust the tempo of the new beat grid to cover a long new region as long as possible. Slight tempo/onset variations are typical if different instruments are used or when played live. (Quantize can here be used to snap to a detected onset in that region. See #2917) The shift-beat feature is useful by now, if the analyses has not picked the exact onset of the beat. You may adjust the whole track. Shifting a region between two other regions does not work because it will create two padding beats. This may be desired when a region is played with an instrument with a delayed onset. For syncing this means the follower track will speed up and slow down quite fast at that point which creates an unwanted yowling. This situation must be avoided. If this is still not possible you may create a phrase sized region with a slightly slower tempo. This avoids jouling in the follower track, because the tempo change is minimized. Does this match you approach? |
I think we have a fundamental disagreement here. Once again, I'm finding myself quite frustrated to see the essence of this PR being completely tore down after 5 months of effort and approval from the rest of the team. I appreciate you are approaching the problem from a more scientific aspect, thinking with music theory at heart, while I went for a more practical and UX oriented approach. For example:
As I'm sure you tried (since Jan's PR was already following the approach your are suggesting), doing this will change the BPM temporarily. Say you need to pad 1/5 on a 130 BPM track, you end up temporarily setting up the track tempo to 650 BPM. So as you are syncing with another track, this other track suddenly see its BPM multiplied by 5 and end up off by one beat. With this current approach, both track stay in BPM sync, with the second deck slightly slowed down to stay in sync with the track, and still align on phase. Beside all the respect and admiration I have for you and your dedication to the project, I am now pretty sure we are not going to agree and will likely both continuing to defend our approach with endless back'n'forth messages. Can you see a trade-off to be found in line with my proposal above, which does not:
If not, I suggest we pause the work and resolve that in the monthly December meeting, so we can quickly get a consensus. |
The frustration happens on both ends ... but as allways and especially after our latest discussion with other topic, I am willing to find a compromise. This requires a good understanding for each other. Let's not repeat the issue here and find this common understanding first. In my post above I have raised two questions, they are assential for me to find a compromize. Can you please egive a short answer:
Serato does also not allow padding beats by default. See this video: When you set a new beat-marker, the tempo of the region before and after is adjusted. You can even see that a slight change in the already propper aligned initial section when the tutor is placing the first beat change marker, without he noticed/mentioned int. This is the downside of this approach. You have alread stated that you don't whant that. Correct? This solution would be OK for me as an itermediate state to merge this PR, though.
Yes, I can aknowledge it. Here my comments:
This probabyl is sourced by a missanderstanding. Because I consider the majority of this PR as well done. Using the two modes with quantize as proposed increase the complexity even more. It would be easy to add another beat-change-marker at the begginning of the padding beat. A peading beat is a change, so a marke at this place is consistent. It is more work is to introduce the mode I have described. But the most work is probably to compare the models we found in the wild and pick the best for Mixxx. My idea is that we use "only" the change marker at the at the begining of the original padding beat and calculate the new bpm form the resulting distance. We can one by one add in follow up PRs helper that snap to reasonable values and such, to ease up the work for users. This all fits to the model of "no padding beat". |
This is another Serato one, showing how to annotatte changing tempos on the fly by tapping the down beat: |
I did. The major downside is how much additional feature and UX work will be needed to achieve sufficiently of this implementation and make it usable by user. This is what I meant by
The implicit change of BPM, as explained in intro
Traktor Pro does.
Happy with that. This is #13768 was about (adding the a "non-padding" CO, since I had already implemented the other approach). In order to limit the effort on this PR and iterate on the feature, I could reserve
This leads to the limitation stated above tho.
I'm glad to see we are in synch with this. This is already the approach taken with the UI. I just would to wrap up here to highlight that in the current state, none of the Serato usecase are blocker with the current approach, as Jan demonstrated here. Yes, it requires you to explicitly "acknowledge" the BPM change (which I explicitly didn't like on the Serato-like approach you are suggesting). This is why we talk about adding another CO next which would auto scale the grid, and this impact the BPM of the grid previous to the play position and translate the grid after (or scale it if it is already a defined grid?) |
Dealing with the padding beat without annotation as beat change will complicate the whole thing a lot.
I do not suggest the Serato approach. I also don't like the changing temp on the left. However if you are in the progress of editing the right site anyway we can effort the tempo change, which a new beat position actually is. |
Interesting summary how other tools do it: |
I'm struggling to see how this would complicate the whole thing. From what I can see, it is actually to opposite, and having to create an "end marker" or a "padding area" (that is, with a start and a stop) explicitly sounds like the complicating approach
Here you are taking the assumption that it is fine to "mess up" the right grid, since the user would have not proceed it yet. What if this is not true and we already have an explicitly set marker both on left and right? Shifting would be wrong, since it was likely set at the right place, and scaling would be wrong since it was likely already defined correctly.
Indeed. Traktor 3's lack of multiple BPM is a real pain for sure, but its habitability to pad without mutating other grid sections (BPM and position) is really something I got used to and I cannot believe I would be the only one. |
Traktor Pro 4 has also eleminated the padding beats by changing the tempo of the left zone: https://www.youtube.com/watch?v=l2Rn6dMG0dI |
Great to hear.
I guess this should be |
@mixxxdj/developers it would be great if you could give some feedback on whether you also think padding beats are a deal breaker? |
Not interested to work on this anymore |
@acolombier thank you for all of your effort in this. i'm sad to see all of this cumulative work abandoned (again), because this is such a fundamental feature. what is the process for starting a "developers" vote on this PR as mentioned earlier? |
@khimaros There is no such process, after all it needs a dev with the motivation and skills. |
Appreciate your support @khimaros
We do have a process, which may be run either internally or publicly on Zulip. It's still quite experimental, but in the current case it did not bare any fruits and no consensus could be found. |
I interpreted the question about "the process" rather about if/how we vote to force-revive a PR. |
Would you mind summarizing what's already done and what's missing to merge this PR for future developers who want to carry it to the finish line? |
This was meant to be an MVP, but the core design didn't get consensus. I would suggest any devs interested in this feature to pick this work off #12343 |
This PR is based on @fwcd 's PR #12343, itself based on @Holzhaus 's #4489 PR.
Kooha-2024-06-07-18-43-20.mp4
This attempt TL;DR; is: do not disrupt the way the beat grid currently works
This is how this attempt differs from the previous one:
TODO:
Fixes #13308 and #10164
Disclaimer:
I know there was a lot of discussion on these types of change in each of the above PRs as well as in the Zulip thread that goes with it. I'm sorry, but I only read the latest messages of each as there was a few hundreds of them, going over a few years of activity. Apologies if this proposal contains approaches that have been discussed and ruled out already.