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

Saved beat jumps #13216

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open

Saved beat jumps #13216

wants to merge 9 commits into from

Conversation

acolombier
Copy link
Member

This addresses the feature request #13161

Currently, the activating the saved jump result in enabling or disabling the auto jump (different icon used to provided feedback on jump status)

Kooha-2024-05-06-18-58-03.mp4

TODO:

  • Normal hotcue behaviour if playback ahead
  • Other theme?
  • Manual update

Depends on #13215

}
if (pCue->getPosition() > m_lastProcessedPosition &&
pCue->getPosition() <= currentPosition) {
auto delta = pCue->getPosition() - currentPosition;
Copy link
Member

Choose a reason for hiding this comment

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

That does not work well, because the jump is quantized by the engine buffer size. Normally you want to jump beat exact and which can be somewhere within the buffer.

So we need something like the looping engine.

How about actually using the looping engine. Isn't a jump just the same as a loop which disables itself after one iteration.

Copy link
Member Author

Choose a reason for hiding this comment

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

Why does it not work? This is already a simplified version of LoopingControl::process, except that we do not need adjustedPositionInsideAdjustedLoop, but can seek to the "target" directly, (corrected with the engine delay to prevent desync, as done with that delta var)

There is a few drawback I can think about using the looping engine:

  • Loop engine expects start < end, but jump may have from > to. Allowing start > end in LoopingControl sounds wrong
  • They maybe be a loop defined (but not active) and using the LoopingControl will override it for a "one frame" loop (or will have to deal with state restoration, which sounds overkill)

Isn't a jump just the same as a loop which disables itself after one iteration.

To some degree, except it is more simple that a loop, and doesn't need to complexity around the loop (no concept of seekMode for example, or direction). Disabling it at the next iteration implies that is had to be enable at some point, which is why making the most of EngineControl seems a better approach. The engine is already able to perform jumps, so I'm not sure what is the value of using the LoopingControl for a simple unique unidirectional jump

Copy link
Member

Choose a reason for hiding this comment

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

The seeking code in LoopingControl::process handled only the exceptional cases when adjusting the loop size. The looping itself is done here:

const mixxx::audio::FramePos loopTriggerPosition =

Your current implementation does not work for reverse playing and jumps before the track, and small jumps, < delta.

It took quite some iterations to have the looping code rock solid and I have not a big interest to repeat these iterations with beat jumps again. So let's consider what is the best way for trying that code.

Loop engine expects start < end, but jump may have from > to. Allowing start > end in LoopingControl sounds wrong

I think we have discussed earlier to allow forward loops. The engine don't mind if it is a repeated jump backward or a single jump forward.
However we need to take care not to create surprises when we allow to edit jumps with looping controls. So I agree to not reuse them in the first attempt.

They maybe be a loop defined (but not active) and using the LoopingControl will override it for a "one frame" loop (or will have to deal with state restoration, which sounds overkill)

We have this issue already with saved loops.
For example I would love to have a saved loop at the end of the track to extend a short outro that is always active. Maybe we can solve both in one run.

Copy link
Member Author

Choose a reason for hiding this comment

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

Your current implementation does not work for reverse playing and jumps before the track, and small jumps, < delta.

It does need to, because of the unidirectional aspect of a jump. IMO, you wouldn't expect to jump back to the from position if you play reverse above to

For example I would love to have a saved loop at the end of the track to extend a short outro that is always active

Definitely would like to see this behaviour too as I could use it as well. But perhaps that is out of scope for this feature?

Copy link
Member

Choose a reason for hiding this comment

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

For the reverse case, my expectation was that it jumps form the "to" position to "from" just as if you would play backwards a forward recording of the jump. But It is also OK for the first version to not jump at all in reverse, which is is probably not yet the case . (not tested)

Copy link
Member Author

Choose a reason for hiding this comment

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

The idea of this feature is to "automate" a beatjump_forward so not sure it would make sense to "undo" this jump if playing reverse.
I guess we could make it work with a minimal amount of change, without using the LoopingControl if that the behaviour with would expect.

@ronso0
Copy link
Member

ronso0 commented May 7, 2024

Currently this behaves like a loop, i.e. the jump cue is not deactivated after the jump if the the target is behind to cue.

@ronso0
Copy link
Member

ronso0 commented May 7, 2024

Having to deactivate a special mode in order to get the hotcue mode feels.
I'd vote for three buttons in the popup:

  • hotcue (flag icon?)
  • loop
  • jump

IMO they can be very close (like the hotcue grid), to somehow mimic radio buttons?

@acolombier
Copy link
Member Author

acolombier commented May 7, 2024

the jump cue is not deactivated after the jump if the the target is behind to cue.

That's right, and it was on purpose. Do you think it would be best to have it deactivated on run? My thought for the usecase was, when a DJ prepare their track cues, and decide to say that a section should be jumped over, this is likely that they want not to play the section of the track, so we should keep it on at all time. If they decide live to actually play this section, they can trigger the hotcue (hotcue_X_activate/hotcue_X_status=1) which will disable the jump (different icon on LateNight/Palemoon, to be brought on other theme once we've iron the details)

Having to deactivate a special mode in order to get the hotcue mode feels [wrong].

You don't have to. Like for the saved loop, you can use the activate or status CO to change its status to set instead of active. This can be done on the UI (again LateNight/Palemoon only for now) by clicking on the cue, no need to change the type (and lost the jumping destination)

somehow mimic radio buttons?

I like the idea, happy to make it work like this once we are happy with the state of feature

@acolombier acolombier force-pushed the feat/saved-jump branch 2 times, most recently from 4d7c46e to bf74e6e Compare May 9, 2024 15:40
@acolombier
Copy link
Member Author

acolombier commented May 9, 2024

I have upgraded the button to behave like a radio group. Also, I adjusted slightly the delete button to put the emphases that they are not part of the radio group.

Kooha-2024-05-09-16-45-06.mp4

@acolombier acolombier marked this pull request as ready for review May 9, 2024 15:50
@acolombier acolombier marked this pull request as draft May 9, 2024 15:51
const mixxx::BeatsPointer pBeats = m_pTrack->getBeats();
const auto position = mixxx::audio::FramePos::fromEngineSamplePos(
m_pPlayPos.get() * m_pTrackSample.get());
if (position == m_pCue->getPosition()) {
Copy link
Member

Choose a reason for hiding this comment

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

For some reason this doesn't work for me:
when clicking Jump while at the cue position a zero-sized jump is created. When activating thus jump cue I run into an inifinite tiny loop.

Copy link
Member

Choose a reason for hiding this comment

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

in the display start and end seem to be idetical.

Maybe a rounding issue with fromEngineSamplePos()?

Copy link
Member Author

Choose a reason for hiding this comment

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

This should be fixed now

@ronso0
Copy link
Member

ronso0 commented May 11, 2024

I think at least in LateNight we need better styling for the 'active state' of loop/jump cues.
The current inactive jump icon should be the dark/bright active icon, and we could use a highlight border.

I'll tr ysomething.

@acolombier
Copy link
Member Author

I've made some minor UI tweak - does that look better @ronso0 ?

Also, I have made the saved beat jump to disable itself if jumping backward, to prevent them making unwanted loops. My use case for this feature was the ability to jump above certain part of track with the low interest, so I would appreciate we don't disable jump forward when possible so a track can be prepared with auto forwarded sections.

If you think it should be different, I can add a setting in preference.

@ronso0
Copy link
Member

ronso0 commented May 25, 2024

For some reason I can't assign a "free" jump target anymore, it'll always use the current jump size, both for righ- and left-click.

@ronso0
Copy link
Member

ronso0 commented May 25, 2024

For some reason I can't assign a "free" jump target anymore, it'll always use the current jump size, both for righ- and left-click.

Strange, I can't reproduce that anymore.

@acolombier
Copy link
Member Author

That weird indeed. It sounds like a bug I fixed when I rebased main yesterday tho, couldn't it be some cached sources?

@ronso0
Copy link
Member

ronso0 commented May 25, 2024

What I find a bit disturbing is that the jump range in the overview always appears as 'active', unlike saved loops which are less opaque if disabled.
(ranges covering the signal is another story on its own...)

@acolombier
Copy link
Member Author

(ranges covering the signal is another story on its own...)

Yep, agreed. This is why this is still a draft ;)
I want to get rid of the MarkerRange and use custom Marker which allow to display some kind of "cue with a jump flag" on the from and to positions.

I've paused that work because implementing the above requires to touch on lot of waveform renderers atm, which we are hopefully being retired as part of #13226.
I will look at that after. In the meantime, if you have some asset suggestion for the cue design, feel free to help! You probably know by now, but my UI taste are pretty 💩

@ronso0
Copy link
Member

ronso0 commented May 26, 2024

Just an idea I had while reading https://mixxx.discourse.group/t/timing-a-fireworks-show/29693/3
Let's add a 4th cue type 😆
Stop Cue
activate it, and as soon as the play pos hits it... stop

@ronso0
Copy link
Member

ronso0 commented May 26, 2024

For some reason I can't assign a "free" jump target anymore, it'll always use the current jump size, both for righ- and left-click.

Might stem from a previous version where the end was not cleared after changing back to hot/jump cue.

@acolombier
Copy link
Member Author

Some rather larger rework of this feature. Please note the code quality has taken a bit of a hit, so don't review code style/quality just yet 🙏

I have changed saved jump so

  • Start position is now the "jump to" position. This means that the cue can be used like a normal cue and will point to the position you want fast forward (or backward) to instead of the one you want to skip, which was defying the purpose.
  • By mirror, end position is now the "position from"
  • I have added the waveform rendering to display a "Jump" marker at the "position from", and some opacity to indicate whether or not this is active
  • The range isn't displayed any more
  • There default colour is implemented (although I suspect a bug to be investigated)
  • The way to set a saved jump is swapped: You first set the "hot" cue (understand the position of interest), then you can put the play position to a "from" position (or will set the from as -beatjump_size in auto)

There is likely some weird behaviour/bug to iron out, but I think we are making progress. Let me know your thoughts

Kooha-2024-06-10-22-24-41.mp4

@acolombier acolombier force-pushed the feat/saved-jump branch 3 times, most recently from d57bd7d to e96b213 Compare June 11, 2024 15:53
@@ -46,6 +46,7 @@
<Align>bottom|right</Align>
<Color>#FF0000</Color>
<TextColor>#FFFFFF</TextColor>
<EndIcon>skins:LateNight/palemoon/buttons/btn__beatjump_right.svg</EndIcon>
Copy link
Member Author

Choose a reason for hiding this comment

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

This is quite nasty, but I couldn't think of an elegant way to customise the the end marker only. Any suggestion to do that better without needing a major refactor of Mark?

@ronso0
Copy link
Member

ronso0 commented Jul 8, 2024

I just did a brief test, in general this feels good!

Start position is now the "jump to" position. This means that the cue can be used like a normal cue and will point to the position you want fast forward (or backward) to instead of the one you want to skip, which was defying the purpose.

👍

Some notes, observations and ideas:

  • "This means that the cue can be used like a normal cue"
    Hmm, if play position is behind that cue I expected clicking the cue would jump to it, but that just toggles the jump
  • setting a jump pos after the cue (target) will paint a range in the overview
  • setting a jump pos after the cue (target) will essentially create a loop incl. the range being painted in th eoverview
  • I'd love to have a jump marker in the overview
  • it would be nice if the skipped range is dimmed in the overview if the cue is active
  • cue menu: could clicking the Jump button always use the curr. play pos, regardless if there is already a position set?

@acolombier
Copy link
Member Author

acolombier commented Jul 8, 2024

Thanks for your feedback @ronso0 !

  Hmm, if play position is behind that cue I expected clicking the cue would jump to it, but that just toggles the jump

I will look into that!

* setting a jump pos **after** the cue (target) will paint a range in the overview> 
* setting a jump pos **after** the cue (target) will essentially create a loop incl. the range being painted in th eoverview

Ah thanks for the feedback. The waveform renderer still needs some care IMO, but I was hopping to get an initial review on the approach, before looking at edge cases.

Perhaps @m0dB you could give me your thoughts with my approach with the marker updates if you get the time?

* I'd love to have a jump marker in the overview

Me too :D
Working with the overview is something I don't have experience with yet, and since saved jump also don't have custom visual, there wasn't any logic I could inspire the change from. That might have to come in a follow up PR.

* it would be nice if the skipped range is dimmed in the overview if the cue is active

Noted and agreed. I'm not sure how easy it is going to be, but I could look at adding the BackgroundColorRenderer on top of the waveform with some level of opacity. I'll play with it and see how hard it can be.

* cue menu: could clicking the Jump button always use the curr. play pos, regardless if there is already a position set?

This is already the case when using right click. This also quick undoing e.g you have saved jump, accidentally change it to a save loop, but can make it back saved jump without losing the from/to position.

@ronso0
Copy link
Member

ronso0 commented Jul 8, 2024

Ah, note that for the visual aspects, I was referring to the overview waveform only.

Copy link

github-actions bot commented Oct 7, 2024

This PR is marked as stale because it has been open 90 days with no activity.

@github-actions github-actions bot added the stale Stale issues that haven't been updated for a long time. label Oct 7, 2024
@acolombier acolombier marked this pull request as ready for review October 10, 2024 22:59
@acolombier
Copy link
Member Author

if play position is behind that cue I expected clicking the cue would jump to it, but that just toggles the jump

I have added the behaviour now.

As this PR is getting quite big already, I'd like to keep it to an MVP, and potentially revisit the UI/UX in the future. What do you think?

@acolombier acolombier removed the stale Stale issues that haven't been updated for a long time. label Oct 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants