Skip to content

Conversation

@oddtime
Copy link
Contributor

@oddtime oddtime commented Jan 28, 2021

If I am not wrong, while the current max resolution is finite (192), the start time of notes can be already adjusted in H2 with resolution of sample rate, this happens for humanized timing, swing and leadLag.

From this idea I have added a time compensation note property to play the tuplets notes at sample rate precision.
This compensation is expressed as fraction of ticks so it is independent of Max Resolution.
Notes are still positioned at the rounded ticks in the grid, but they are drawn according to the time compensation.

The implementation is currently in progress but it is already working to test the tuplets (you may give opinions, consider that many things are not finished and will change, there are also some issues). I have opened discussion #1142 to share ideas on it, mainly for the User Interface.

Some collateral cool effects!
The tuplet feature allows also to draw custom grids in the editors (darker mark every n marks) ie for meters like 6/8, set a (fake) tuplet "3:3".
With tuplets you can set any rational resolution, even > 192 (set resolution "off" and enter a tuplet), even if I am currently imposing some arbitrary limits on the tuplet numerator and denominator.

here's a picture:
screenshot-409a1346

@oddtime oddtime marked this pull request as draft January 28, 2021 09:39
@oddtime oddtime mentioned this pull request Jan 28, 2021
@oddtime
Copy link
Contributor Author

oddtime commented Jan 30, 2021

Hi @cme! I bumped into the keyboard cursor position in PatternEditorPanel.cpp

	//TODO move cursor to the nearest grid mark. M
	int nTupletNumerator = Preferences::get_instance()->getPatternEditorGridTupletNumerator();
	m_nCursorIncrement = ( nTupletNumerator == 3 ? 4 : 3 ) * MAX_NOTES / ( nResolution * 3 );
	m_nCursorPosition = m_nCursorIncrement * ( m_nCursorPosition / m_nCursorIncrement );

The problem with tuplets is that the tick distances between consecutive grid marks are not uniform. So keyboard entry isn't working.
This could be resolved if cursor position was represented by an int nCursorGridIndex referring to the grid marks rather than the tick position of grid marks. It would be updated when changing resolution or tuplet ratio.

What do you think?

Also I made some mods to lines for getColumn() etc to make it more clear and probably changed some of the functions that you wrote (granularity()...)

@cme
Copy link
Contributor

cme commented Jan 30, 2021

The problem with tuplets is that the tick distances between consecutive grid marks are not uniform. So keyboard entry isn't working.
This could be resolved if cursor position was represented by an int nCursorGridIndex referring to the grid marks rather than the tick position of grid marks. It would be updated when changing resolution or tuplet ratio.

What do you think?

Sounds logical. I haven't looked at this change at all yet, but one thing I've been trying to do is commonise the calculations of mapping between screen x position, grid position, note position etc. Is there a common interface to the new mapping between time / x position / grid position that you've defined? If so, should be fine to just use that :)

Also I made some mods to lines for getColumn() etc to make it more clear and probably changed some of the functions that you wrote (granularity()...)

I'll take a wee look at some of this then when I can find the time. Thanks for the heads up.

@oddtime
Copy link
Contributor Author

oddtime commented Jan 30, 2021

Great!

one thing I've been trying to do is commonise the calculations of mapping between screen x position, grid position, note position etc. Is there a common interface to the new mapping between time / x position / grid position that you've defined?

Today I have finally understood some things about it (the meaning of m_nGridWidth, Resolution, fTickSize etc).
I didn't use a common interface but I learn how to do the conversions between pixel, ticks and gridIndex units (gridIndex is something I introduced for adding new tuplets notes).
I update you when I have a clearer idea. For the moment I will try to change the cursor position the way I wrote in previous message

I had also the impression that some members could be stored one time only (instead of having a resolution member in each note property editor for example)

Thanks

@oddtime
Copy link
Contributor Author

oddtime commented Jan 31, 2021

I did the change on keyboard cursor.
It's working now for any tuplet resolution.

@oddtime
Copy link
Contributor Author

oddtime commented Feb 1, 2021

Hi @cme, when you want I am ready to discuss the pattern editor GUI section.
Right now my Drum Pattern editor and keyboard cursor input handles the tuplet resolution, while the newer functions to copy/move/paste notes are not working yet.
Should we open a dedicated issue?

@duck57
Copy link

duck57 commented Feb 6, 2021

@oddtime I wanted to chime in to let you know that I'm excited about the possibility of using those 3:3 tuplets for a proper 6/8 grid. Once this is merged, is there a spot in the documentation for me or you or someone to write down this tip?

@oddtime
Copy link
Contributor Author

oddtime commented Feb 6, 2021

@duck57

Once this is merged, is there a spot in the documentation for me or you or someone to write down this tip?

Yes! You will be welcome to do it
Consider that there's an open discussion on tuplets where we are thinking about the User Interface. You could help us with some ideas if you want. Here's the link: #1142

@cme
Copy link
Contributor

cme commented Feb 8, 2021

I managed to take a very quick look at this (catching up; sorry, i have been busy and some family matters have taken up a lot of time and energy the last weeks).

This works in a very different way to how I thought it would work (I cant find the previous discussion right now, and i may have misread even that), i shall have to do some thinking.

@oddtime
Copy link
Contributor Author

oddtime commented Feb 8, 2021

Ok! Don't worry.
I am curious to see the way you thought

@cme
Copy link
Contributor

cme commented Feb 12, 2021

Ok! Don't worry.
I am curious to see the way you thought

Okay, this might be a long answer, because it involved my wondering about things then going off and doing a bit of investigation and archaeology.

The way that I thought this would work, and that I still think it should work, is by allowing the tick resolution of the song to be changed to fit whatever subdivisions the user wants to use (which can be done automatically with GCD).

I wanted to figure out how much work in the core that would actually involve, and looking at that, I found that the core already supports arbitrary resolutions. It's not saved in songs, and there's no way to set it, but it works. There's a few bits that have broken because for years nobody's considered it.

The only real issue is the GUI, because the assumption of MAX_NOTES ticks per whole note is mostly a GUI thing.

This set me wondering where MAX_NOTES actually came from, because the name never really quite fit the way it's used -- something like TICKS_PER_WHOLE_NOTE would have made sense, but why MAX_NOTES?

The oldest version in the git repo is 0.9.3, and the data structures are quite different, but the fundamental structure in a pattern was already a map of <pos,note>. But some of the code around it, looks suspiciously like at some point in the past, patterns were a simple fixed size array of size MAX_NOTES. That's where MAX_NOTES comes from.

Because I wanted to check if this actually really does work, I've started work on flushing MAX_NOTES out of the core (PR coming up shortly) and it looks like this is the right way forward. There might be a little bit of core work needed as well to make sure that it'll work for extremely high resolutions (where rounding errors in tick size would be major issues).

So, if we enable and support variable resolution in the core and GUI, you can change the resolution of the song to anything appropriate for the tuplet selection the user wants, and there's no need to add extra properties to notes or anything else in the core, or change anything in the majority of the pattern editor.

And, MIDI export would just work :)

@cme cme mentioned this pull request Feb 12, 2021
5 tasks
@oddtime
Copy link
Contributor Author

oddtime commented Feb 12, 2021

something like TICKS_PER_WHOLE_NOTE would have made sense,

Exact

So, if we enable and support variable resolution in the core and GUI, you can change the resolution of the song to anything appropriate for the tuplet selection the user wants, and there's no need to add extra properties to notes or anything else in the core, or change anything in the majority of the pattern editor.

But when you decide to add a tuplet at some point while programming a drums-part, all the note positions should be recalculated according with the new max-resolution. If I am starting a song I really can't say what type of tuplet I would add in the future.

@oddtime
Copy link
Contributor Author

oddtime commented Feb 12, 2021

Also, do you think that increasing the maximum res is sufficient for arbitrary tuplets (of very high order, with sample rate frequency precision), without reducing the performance?
I don't know how the performance would be affected with a very high resolution (many thousands), but the possibility to change the TPQN resolution is very cool because this current pull request doesn't allow tuplet pattern lengths.
In case I would consider having both time compensations and custom TPQN resolution.

@oddtime
Copy link
Contributor Author

oddtime commented Apr 27, 2021

I am closing this pull request as I opened #1251

@oddtime oddtime closed this Apr 27, 2021
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.

3 participants