-
-
Notifications
You must be signed in to change notification settings - Fork 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
Limit note length to quantization value #3998
Conversation
Closing this PR for now. It's not clear to me how to improve this and it's not important for 1.2 anyway. |
9776788
to
5b47419
Compare
🤖 Hey, I'm @LmmsBot from github.com/lmms/bot and I made downloads for this pull request, click me to make them magically appear! 🎩
Linux
Windows
macOS
🤖{"platform_name_to_artifacts": {"Linux": [{"artifact": {"title": {"title": "(AppImage)", "platform_name": "Linux"}, "link": {"link": "https://6375-15778896-gh.circle-artifacts.com/0/lmms-1.2.1.676-linux-x86_64.AppImage"}}, "build_link": "https://circleci.com/gh/LMMS/lmms/6375?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link"}], "Windows": [{"artifact": {"title": {"title": "32-bit", "platform_name": "Windows"}, "link": {"link": "https://6372-15778896-gh.circle-artifacts.com/0/lmms-1.2.1.676-mingw-win32.exe"}}, "build_link": "https://circleci.com/gh/LMMS/lmms/6372?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link"}, {"artifact": {"title": {"title": "64-bit", "platform_name": "Windows"}, "link": {"link": "https://6376-15778896-gh.circle-artifacts.com/0/lmms-1.2.1.676-mingw-win64.exe"}}, "build_link": "https://circleci.com/gh/LMMS/lmms/6376?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link"}, {"artifact": {"title": {"title": "32-bit", "platform_name": "Windows"}, "link": {"link": "https://ci.appveyor.com/api/buildjobs/wpn024tn0a7ek51h/artifacts/build/lmms-1.2.1-msvc2017-win32.exe"}}, "build_link": "https://ci.appveyor.com/project/Lukas-W/lmms/builds/32859425"}, {"artifact": {"title": {"title": "64-bit", "platform_name": "Windows"}, "link": {"link": "https://ci.appveyor.com/api/buildjobs/7ibrqfit5c3984sd/artifacts/build/lmms-1.2.1-msvc2017-win64.exe"}}, "build_link": "https://ci.appveyor.com/project/Lukas-W/lmms/builds/32859425"}], "macOS": [{"artifact": {"title": {"title": "", "platform_name": "macOS"}, "link": {"link": "https://6373-15778896-gh.circle-artifacts.com/0/lmms-1.2.1.676-mac10.13.dmg"}}, "build_link": "https://circleci.com/gh/LMMS/lmms/6373?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link"}]}, "commit_sha": "cb01991211606db8780eed53f14d61d0136b51ad"} |
Draging a note to it's minimum value of 1 will add this new length to the note if you later choose to stretch it which will not be clearly visible in the Piano Roll unless you zoom in a bit. Limit the note length to the quantization value and use <Alt> key to override and set a smaller value.
5b47419
to
aa08c52
Compare
Isn't this made reduntant by #4357? We also have a quantize button in piano roll. Isn't it better to fix that so it affects lengths as well? I ask because this reminds me of tresf asking for fine offsets to be removed when clips are moved (until he changed his mind). If I want to extend the length of a weird-length note by 1/4, it's much easier to do that at 1/4 Q than to do it by hand at 1/64th Q. |
Maybe, I'll look into it.
Again maybe, but the issue here are tiny stretches that users aren't aware of that causes the tco to come out the wrong length. If you don't see the note length as being the culprit you're not going to try and change it neither by stretching nor by quantization. |
Sorry, it seems I misunderstood what the PR did. I read "limit note length to quantization value" as "do not allow resized notes to be sizes other than n * Q, where Q is the quantization level, n is an integer". I should have looked at the detailed explanation/code instead. Setting the minimum length to the current Q is better, but still overkill IMO. I think we should only prevent resizing down if the resize would lead to a length of zero. That way a 3/8ths note can be resized to 1/8th even if you're at 1/4th Q, which is a totally valid operation IMO. |
src/gui/editors/PianoRoll.cpp
Outdated
@@ -2811,8 +2811,8 @@ void PianoRoll::dragNotes( int x, int y, bool alt, bool shift, bool ctrl ) | |||
if (note->selected()) | |||
{ | |||
int newLength = note->oldLength() + off_ticks; | |||
newLength = qMax(1, newLength); | |||
note->setLength( MidiTime(newLength) ); | |||
newLength = qMax(alt ? 1 : quantization(), newLength); |
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.
Implementation for my preferred behavior, since code might be easier to interpret than my explanation 😅
newLength = qMax(alt ? 1 : quantization(), newLength); | |
if (newLength <= 0) { newLength = quantization(); } |
Or if you prefer
newLength = qMax(alt ? 1 : quantization(), newLength); | |
newLength = (newLength > 0) ? newLength : quantization(); |
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.
That's elegant! I prefer the <Alt>
key in there somewhere. You can skip quantization when changing the length of the note with the <Alt>
key so I would prefer:
if (newLength <= 0){ newLength = alt ? 1 : quantization(); }
If you change that I'll commit it.
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.
Like so? :)
newLength = qMax(alt ? 1 : quantization(), newLength); | |
if (newLength <= 0) { newLength = alt ? 1 : quantization(); } |
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.
Yup!
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.
Reminder that newLength = alt
is not a boolean operation, but an assignment one. 😉
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.
Yes. We're assigning either the quantized value or if overriding with Alt key, 1. Then you can still set the note to any length if you want.
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.
Okay! Wanted to make sure since tertiary operator can be confusing sometimes.
EDIT: To quick glance that is. 😁 Looked like newLength == alt ? ...
when I saw it.
Co-authored-by: Spekular <Spekular@users.noreply.github.com>
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.
LGTM, and feels safe enough that I wouldn't even mind merging it on 1.2.
It has some quirks though. Select many different notes that start at different times and change their length. It looks a bit odd when you shorten them and they take turn to first become shorter and then jump up again and become the quantized length. |
Oh right, you could end up scaling 3/8->1/8->2/8... I didn't think it through enough huh 🙃 |
I wonder if using |
src/gui/editors/PianoRoll.cpp
Outdated
if (newLength <= 0) { newLength = alt ? 1 : quantization(); } | ||
note->setLength(MidiTime(newLength)); |
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 works the way I wanted, judging from an admittedly quick test.
if (newLength <= 0) { newLength = alt ? 1 : quantization(); } | |
note->setLength(MidiTime(newLength)); | |
int minLength = alt ? 1 : (note->oldLength() % quantization()); | |
if (minLength == 0) { minLength = quantization(); } | |
note->setLength(MidiTime(max(newLength, minLength))); |
Would love to figure out a shorter way to get
x % y
if x % y > 0
y
otherwise
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 works nice but if I set the length of notes of varying length I would want them to end up at the same min value. Example two notes starting at the same time. Lenths, 2/16 and 3/16. Set quantization to 1/8, hit Ctrl + A and set their length to min by dragging. Not the same value.
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.
In that case I think we need to iterate over the selction once before getting here to find the smallest minLength of any selected note, then use that for all of them.
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 had to test my latest research so the PR is for now back at my branch.
Back to my original commit. I'm experimenting with letting notes shorter than quantization be remembered and kept as minimum value(). int oldLength = note->oldLength();
int newLength = oldLength + off_ticks;
int minLength = qMin(oldLength,quantization());
newLength = qMax(alt ? 1 : minLength, newLength);
... |
New idea. Maybe just limit to the shortest note that isn't just a tick? It'll still give a short extra length if you drag it out with quantization but one that is more easy to spot. newLength = qMax(MidiTime::ticksPerTact()/64, newLength); In following order. |
I'm not a fan of this version, it doesn't allow 3/4 -> 1/4 @ 1/2 Q. |
Here's a branch that meets both my criteria and yours:
The minimum length is stored in a member variable on the initial mouse press in order to avoid recalculating it on every drag event. |
Good solution. I've played around with it for quite a while and can't seem to find any obvious weak spots. I think you should issue a separate PR for your solution and I'll close this one. On another but related note. If you have a group of notes with beat notes among them, select them all, and proceeds to extend them by dragging, the beat note won't react until after a whole measure has been covered. It looks like it's the full -192 ticks that has been covered first before there is a visible change. If I manually change the beat note length to -10 in the mmp file it will just stop for a brief moment before being extended. I don't know what a preferable behavior would be here. |
Done!
Confirmed, but just to clarify this doesn't seem to be a regression as it occurs in my master build and 1.2.1 as well. New issue for that problem once this one is closed? |
Yes, this is not new. It's there on 1.1.3. already.
Yes. |
Closed in favor of #5512 |
Adding this fixes the resize issue I think. At least it demos the issue. if (note->selected())
{
if(note->oldLength() <= 0){note->setOldLength(1);}
int newLength = qMax(minLength, note->oldLength() + off_ticks);
note->setLength(MidiTime(newLength));
m_lenOfNewNotes = note->length();
} |
Draging a note to it's minimum value of 1 will add this new length to
the note if you later choose to stretch it which will not be clearly
visible in the Piano Roll unless you zoom in a bit. Limit the note
length to the quantization value and use key to set a smaller
value.
PR explained in depth here: #3989 (comment)
Fixes #3989