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

Limit note length to quantization value #3998

Closed
wants to merge 3 commits into from

Conversation

zonkmachine
Copy link
Member

@zonkmachine zonkmachine commented Nov 22, 2017

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

@zonkmachine
Copy link
Member Author

Closing this PR for now. It's not clear to me how to improve this and it's not important for 1.2 anyway.

@zonkmachine zonkmachine reopened this May 9, 2020
@zonkmachine zonkmachine changed the base branch from stable-1.2 to master May 9, 2020 20:54
@zonkmachine zonkmachine force-pushed the minimumnotelength branch from 9776788 to 5b47419 Compare May 9, 2020 21:32
@LmmsBot
Copy link

LmmsBot commented May 9, 2020

🤖 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.
@zonkmachine zonkmachine force-pushed the minimumnotelength branch from 5b47419 to aa08c52 Compare May 9, 2020 22:18
@Spekular
Copy link
Member

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.

@zonkmachine
Copy link
Member Author

Isn't this made reduntant by #4357?

Maybe, I'll look into it.

We also have a quantize button in piano roll. Isn't it better to fix that so it affects lengths as well?

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.

@Spekular
Copy link
Member

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.

@@ -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);
Copy link
Member

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 😅

Suggested change
newLength = qMax(alt ? 1 : quantization(), newLength);
if (newLength <= 0) { newLength = quantization(); }

Or if you prefer

Suggested change
newLength = qMax(alt ? 1 : quantization(), newLength);
newLength = (newLength > 0) ? newLength : quantization();

Copy link
Member Author

@zonkmachine zonkmachine May 11, 2020

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.

Copy link
Member

Choose a reason for hiding this comment

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

Like so? :)

Suggested change
newLength = qMax(alt ? 1 : quantization(), newLength);
if (newLength <= 0) { newLength = alt ? 1 : quantization(); }

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup!

Copy link
Contributor

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. 😉

Copy link
Member Author

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.

Copy link
Contributor

@Veratil Veratil May 11, 2020

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>
Copy link
Member

@Spekular Spekular left a 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.

@zonkmachine
Copy link
Member Author

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.

@Spekular
Copy link
Member

Oh right, you could end up scaling 3/8->1/8->2/8...

I didn't think it through enough huh 🙃

@Spekular
Copy link
Member

I wonder if using note->oldLength() % quantization() as a minimum instead of quantization() would work, or if oldLength is updated too frequently. That could also become zero, so then you'd need two checks for zero or something clever.

Comment on lines 2814 to 2815
if (newLength <= 0) { newLength = alt ? 1 : quantization(); }
note->setLength(MidiTime(newLength));
Copy link
Member

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.

Suggested change
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

Copy link
Member Author

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.

Copy link
Member

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.

Copy link
Member Author

@zonkmachine zonkmachine May 13, 2020

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.

@zonkmachine
Copy link
Member Author

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);
...

@zonkmachine
Copy link
Member Author

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.
A whole note with a 64th note
A whole note with a tick
A whole note

64th

@Spekular
Copy link
Member

I'm not a fan of this version, it doesn't allow 3/4 -> 1/4 @ 1/2 Q.

@Spekular
Copy link
Member

Spekular commented May 20, 2020

Here's a branch that meets both my criteria and yours:

  • Notes can be resized to length % quantization, or quantization if the previous math leads to zero
  • All notes can be resized to be as small as the shortest note's minimum length

master...Spekular:noteLen

The minimum length is stored in a member variable on the initial mouse press in order to avoid recalculating it on every drag event.

@zonkmachine
Copy link
Member Author

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.

@Spekular
Copy link
Member

I think you should issue a separate PR for your solution

Done!

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.

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?

@zonkmachine
Copy link
Member Author

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.

Yes, this is not new. It's there on 1.1.3. already.

New issue for that problem once this one is closed?

Yes.

@zonkmachine
Copy link
Member Author

Closed in favor of #5512

@zonkmachine
Copy link
Member Author

zonkmachine commented May 21, 2020

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();
}

@zonkmachine zonkmachine deleted the minimumnotelength branch June 1, 2020 10:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Some patterns in "Song-Editor" and "Beat+Bassline editor" are displayed larger than they are
4 participants