-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Pitch Bending Directly in the Piano Roll #7759
base: master
Are you sure you want to change the base?
Conversation
@szeli1 I believe you had similar ideas, but it was for manually editing automation clips directly in the Song Editor? |
What if I slide pitch from one note onto a place where another note already exists, and then click on that other note? If you don't get what I mean, I'll record a video demo when I can. |
Just tried it, it works on selections, so even if you overlap notes, there's no issue! And it supports making selections in the automation mode! Excellent! 😁 |
Mind the quality of the video, I overcompressed it. But I found a bug! out.mp4 |
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 didn't test this PR, but I reviewed it.
@@ -365,6 +365,7 @@ protected slots: | |||
static const std::vector<float> m_zoomYLevels; | |||
|
|||
MidiClip* m_midiClip; | |||
NoteVector m_selectedParameterEditNotes; |
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.
It would be better if getSelectedNotes()
returned a reference to the selected notes. This way the code is more general and optimized. So essentially I'm asking you to implement something like this:
NoteVector m_selectedNotes
void setSelectionChanged(Note*)
this will add or remove a note fromm_selectedNotes
, call this when a note is selected or unselectedgetSelectedNotes()
will returnm_selectedNotes
I hope this will improve the code quality in the long run
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.
Are you asking me to change PianoRoll::getSelectedNotes
or m_selectedParameterEditNotes
? I have not touched PianoRoll::getSelectedNotes
, so I'm not sure if that would be in the scope of this PR.
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'm asking you to rename m_selectedParameterEditNotes
to a generic name (I can't decide if it is already), make it always store all selected notes with a method called void setSelectionChanged(Note*)
, and rewrite getSelectedNotes()
so it returns m_selectedParameterEditNotes
.
I'm not sure if that would be in the scope of this PR.
I believe it will make future contributions easier, but it might be a bad idea to implement it here. Maybe you or I can refactor it in an other PR. The idea is to make it optimized (so it doesn't have to loop through all notes to return the selected ones) and make it (the selected notes) use a single vector.
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.
Oh you're right I realized m_selectedParameterEditNotes
is always just the currently selected notes lol. So I could technically replace it with calls to getSelectedNotes
. But I see why you want to refactor getSelectedNotes
, it literally loops through all the notes to find the selected ones, which is probably not ideal. Caching them in a vector would definitely be more efficient (which is sort of what m_selectedParameterEditNotes
does, but that's only for this feature).
} | ||
else if (noteUnderMouse()) | ||
{ | ||
m_selectedParameterEditNotes.assign(1, noteUnderMouse()); |
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 you decide to refactor note selection, I believe you could just select manually that note here, so it is added to a variable called something like m_selectedNotes
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 should add a comment to clarify; the only purpose for selecting the note under the mouse is to keep track of it even if the user's cursor leaves the note while drawing the curve. It's a bit hacky but it works.
Co-authored-by: Sotonye Atemie <[email protected]>
Co-authored-by: Sotonye Atemie <[email protected]>
@regulus79, could very well be! My exact steps were Ctrl+A, Shift-Dragging new notes into existence, and then attempting to change the pitch of those new notes, since they were selected afterwards. I'll try that on master and let you know if that's the same behavior. |
…rning the right automation clip (Currently only detuning is supported)
I have added a lot of comments and refactored the switch statement out into a separate function. Hopefully the PR is easier to read now. |
Out of scope for this PR, i see a chance we can replace |
@regulus79, the named issue definitely exists on master. Adding it to my notes and opening a corresponding issue if there isn't one. |
…ecks to prevent holding left and right at the same time
I see the MMB issue has been fixed. Saving and loading works. Please merge ASAP! 😎 |
I just realized that currently the detuning is locked to whole semitone steps. I guess that's fine, but if velocity/panning/whatever per-note parameter automation is implemented, that might have to change. |
Co-authored-by: Sotonye Atemie <[email protected]>
Cool feature, thanks. The feature only allows detuning up until the max length of the note, which I think wasn't the same as when it was done through the editor. I also think its a problem because you can have release on a note, as to which the user may want to apply the detuning beyond the length of the note. |
Also wanted to mention something: if you feel the need to add comments (excluding documentation comments) everywhere, it's always a good idea to see if you can improve your naming and simplify your interfaces. It will help developers understand what's going on better. Try not to use comments as a crutch. |
Okay, so...... This is a bit more difficult to implement, since previously I was relying on the vertical distance form the mouse to the detuning curve to determine the closest note, but this would require also calculating the distance to the last node in the curve. But, after a while, I actually did get it to work fairly well 4dbcf93. So now you can pitchbend past the end of the note! On a separate note, I also changed the color and size of the automation nodes, and I added a |
This may not be the right place to discuss this, but I think the bending automation editor is somewhat bugged, since it places the notes off-center, for some reason. I also think this is generally the "correct" way to pitch bend. Is there any reason we're keeping the bend automation editor at all now that this is coming to LMMS? |
I think the addition of an infobox is great, but I think the current text could cause confusion. "Click on a note [...] to edit its detuning curves [...]" could incentivize that clicking begins the editing process, whereas that's "not true" and it actually places a point immediately. So say someone reads that, clicks on a note to edit it, and immediately places a point they didn't want, so they have to undo. Of course, the user has to get adjusted to the fact that they actually click-and-drag the point into place, but maybe there's a better way to word this? |
Yeah, the more I think about it, the more I think we just have to incentivize the "click-and-drag" idea, the rest of the text is good as-is! |
I kind of made a PR to fix that a while ago, but I closed it in favor of this one #7465 |
If we are keeping the bend automation editor, and a fix exist, I'm all for merging it upstream! |
Keeping the automation editor could help for pitch bends with non-slope shapes, so unless this editor also implements those, I think the automation editor is valuable enough to keep around. At least for now. |
Actually, great point, @rdrpenguin04! Thank you, that slipped my mind! 🙏 I noticed we don't display those curves, it's probably a performance thing. @regulus79 might have more info. |
Also, @regulus79, have you given a different text in the infobox any thought? Are you for keeping this one or focusing on the "click-and-drag" idea more? |
Yes, that was kind of what I was thinking. Since changing between discrete, linear, and cubic curves, and changing tangents, or out/in values are not implemented in this PR, we need to have the automation editor version still accessible for advanced editing.
Discrete and linear curves should display just fine in the piano roll, but as of now no one has yet implemented proper drawing for cubic pitch bending curves. Aside from adding the circles, I did not change the drawing code in this PR.
I could change it to something like "Click and drag on a note or selection to edit their detuning curves", or maybe you have ideas on what it should say? |
Nice! I'd just like to notice it's one curve, but multiple points. How about: "Click and drag on a note/selection/point to edit the detuning curve" ? |
You're right, "curves" should be "curve" since it's just talking about a single note, thanks for catching that. |
This PR modifies how the Detuning tool works in the piano roll to let the user modify the automation curve right on the notes. This is actually fairly simple, as automation clips already contain the functions for dragging and removing points like in the Automation Editor. So essentially all that's being done is calculating the relative pos of the mouse to the nearest note, and setting the drag value in the automation clip to that position and key.
You can still access the old automation editor version by shift-click (should I change it to be double-click?)
pitchbending_demo.mp4
(Apologies for the non-standard theme; I didn't feel like recording another demo)
@messmerd asked if the code could be made general for any future note parameter besides detuning, in preparation for CLAP per-note parameter automation. I have refactored the relevant functions to accept an enum type for the kind of note parameter, although currently only detuning is supported.
Changes
Note::ParameterType
, which currently only hasDetuning
.PianoRoll.h
, to store the mouse states, the current notes being operated on, and the last changed tick.Note::ParameterType
and use a switch statement to get the right automation clip in the note (currently only detuning is supported). Another function was also added to get the closest note to the mouse taking into account the shape of the automation curve.