LMMS / lmms

Cross-platform music production software
https://lmms.io
GNU General Public License v2.0
8.15k stars 1.01k forks source link

Chord delay #2380

Open DeRobyJ opened 9 years ago

DeRobyJ commented 9 years ago

In Func menu, Chord section. Let's add a new knob for "delay", that is a delay between notes.

When I try to play some octaves or fifths manually and I like them, I often activate the Chord function, but they sound different, because all the note start at the same time. Instead, having a 1ms delay before each note of the chord could be really fun!

It's something like the Tempo knob for Arpeggios, but instead of releasing notes and playing them over and over, it keeps each note until the chord is complete. Of course it would be nice to select a tempo sync just like in the Tempo knob.

(this knob can be then randomized with an LFO controller, giving a more "human" or natural effect to chords)

If I didn't explain it well enough: Select Fifths and a range of 2 You play C3: current behaviour: it plays C3, G3, C4 and G4 simoultaneously.

With the Delay knob, put at 10ms: it plays C3, after 10 ms G3, after another 10 ms C4, and 10ms after G4.

tresf commented 9 years ago

Sounds like a "harp" feature, simulate the strumming of strings with a short gap between.

DeRobyJ commented 9 years ago

Exactly! In general every plucked string instrument could make use of that to sound more natural.

musikBear commented 9 years ago

Arent we really talking 'general humanizing' -eg ways to make both Quantization and or volume with just a few percent jitter or randomness? (Then this is a duplicate)

DeRobyJ commented 9 years ago

Duplicate of what issue?

tresf commented 9 years ago

Duplicate of what issue?

He's referring to #1165

general humanizing

Although they both have their roots in adjusting timing (or in the case of #1165, pitch too), this isn't the same exact request. @DeRobyJ is requesting that a chord has a delay between attacks of the same chord.

For example a chord like this:

image

may actually be played like this

image

But he's requesting it on the FUNC, STACKING section, e.g.

image

DeRobyJ commented 9 years ago

Ok, that's right.

(even though I think just one knob could do it)

leeavital commented 8 years ago

Would this be for all chords, or just "stacked chords" -- i.e. created through the stacking function.

DeRobyJ commented 8 years ago

Stacked function only. If you play or write a chord, you can adjust it manually.

jackokring commented 8 years ago

Two dials add a circle around a centre, and honestly would not be far more complex than one knob. Flourish and Strum? For random pink crossing trigger and linear up or down sweeps.

Or a Poisson distribution mean and variance for triggering based n a seed of absolute song time. It would however make copying bars to a different time have a differing sequencing.

zonkmachine commented 6 years ago

@DeRobyJ Attempt at implementing this: https://github.com/LMMS/lmms/pull/4146

musikBear commented 4 years ago

@DeRobyJ I am making this now. What is the minimum size of individual distance between the notes in the chord, that make sense? Or should it be the Q-value that sets the distance? ATM i have 'made' it with 1/64 as distance, and that can be repeated in steps to n distance, but i kind of like the Q idea -What do you think? ('made' because ATM it only goes in direction to to bottom. I also want it to go bottom-to-top -Witch direction should be left-click, and witch right-click? )

musikBear commented 4 years ago

Should this be marked 'in progress' i cant do that @tresf

Spekular commented 4 years ago

I think you should set the distance with a knob and then interpolate as accurately as possible in between. A sweep with 1/192 offset between notes is definitely distinguishable from all of them hitting at once. Another possibility would be to use both a q knob and a distance knob, I suppose.

DeRobyJ commented 4 years ago

Nice!

What is the minimum size of individual distance between the notes in the chord, that make sense? Or should it be the Q-value that sets the distance? ATM i have 'made' it with 1/64 as distance, and that can be repeated in steps to n distance, but i kind of like the Q idea -What do you think?

I think the ideal would be to have a knob with milliseconds that can sync to tempo, just like the Arpeggio Time knob.

Witch direction should be left-click, and witch right-click?

I'm not sure what you mean here. I think we can just have a menu similar to the Arpeggio one. But I feel like there's not enough space, so I'm not really sure about the UI.

I'm also not really sure of what the Q knob does, is it like some random time variation to make it more or less human? In that case, we do need to have both. Randomness should be an option, not the only way to do it!

musikBear commented 4 years ago

@Spekular & @DeRobyJ You both favour a knob, but then there is a question of real-estate. The way i have it atm is a button. It can be clicked and the strum pattern is made (atm from top-to-down -That what i mean about left / right-click Like this: image If dials/ knobs also could react on mouse-clicks, then that could be neat, and it would not use to much of the speedbar. I will examine the arpeggio dial, and see if i can understand how that work

DeRobyJ commented 4 years ago

I think I've missed something. Are you making a button for the Pianoroll editor?

I think that's another feature, just like the Chord list in PianoRoll is a different feature from the Chord/Stacking Function in the Plugin window.

It's neat for the piano-roll, but it's not related to this issue I believe.

musikBear commented 4 years ago

Yes it is for piano-roll. All staked notes, reacts and become strumming-notes, so also those you insert as chords from the chord-table, i know that is a but different from one more feature on the 'Stacked-chords', but as you said 'a button could also work' It is what tresf made a picture of here: https://github.com/LMMS/lmms/issues/2380#issuecomment-143204547 But i would like to quantize the spacing, and there ms leads to yet an other issue: Calculate precise rhythmic position That is no issue, if the distance is set by: image Then the notes in the strum 'fits' all BPM and time-signatures

DeRobyJ commented 4 years ago

I see

Well, it can do too, might actually be more useful

musikBear commented 4 years ago

it would be for all stacks instead of only those chosen in chord-table. It also 'works' for a collection of chords. again 'works' because i have a glitch. I dont know if its a Linux issue, or a code issue, but after the 'strumming' only root-note will play, until one more note has been added.. That illudes me.. :| 'Otherwise' (ya..right) it works You can see it here: https://studio.youtube.com/video/PNvlrfELy9Q/

DeRobyJ commented 4 years ago

I could try and have a look at the code, which of your branches is it?

musikBear commented 4 years ago

I could try and have a look at the code, which of your branches is it?

It not on github yet, i only have it locally, but i can update :) I will look at it later today @DeRobyJ

I have added the files to my repository This is a direct link to pianoRoll.cpp https://github.com/musikBear/lmms/blob/master/src/gui/editors/PianoRoll.cpp where the method void strumNotes(); has a little strange behaviour The actual event does not take place imediately. The cursor must have contact to the note-inserting area, and the strummed chords wont play strummed, before one more note has been added Thanks for looking at this!

DeRobyJ commented 4 years ago

Ok it appears that you copied the quantizeNotes() function for reference. I'd rather take the "Shift pos" function as reference, as what we are actually doing is shifting notes, although I'm not sure if they are at the same "level".

::shiftPos() has three more updating methods:

These are methods of the Pattern class, the last one is probably used to update the length, in bars, of the pattern, to deal with the possibility that the position shift has put a note outside of the current bars. I don't know what the other two do, but you probably need to check them out to fix that problem.

I'm not sure what is happening with the actual new position tho, I didn't really like the behavior in the video, we'll check that later.

musikBear commented 4 years ago

::shiftPos() has three more updating methods:

m_pattern -> rearrangeAllNotes()
m_pattern -> dataChanged()
m_pattern -> updateLength()

Ahaa.. I will see what they do! Thanks! Where do you find the methods. Do you simply open the class .h and look for them, or does a class-API exists (NoOooo.. i think....... 😞

DeRobyJ commented 4 years ago

Yeah it's pretty much try and find some comments about the methods!

allejok96 commented 2 years ago

Reply to https://github.com/LMMS/lmms/issues/1165#issuecomment-1013885685 sorry @spechtstatt for tossing you around like this

I don't think that the missing "turn off" functionality is really much of an issue as long as you have the possibility to reduce the effect again and/or get back to an initial state.

Strumming and restoring a single chord is fairly easy, but the problem is if you want to strum multiple chords and then restore them.

bild

spechtstatt commented 2 years ago

You are welcome :-)

I am interpreting this as a kind of continuous strumming operation on two chords and we are now talking about the last state of this operation - I hope this is correct?

I think I had something like this in mind when I was talking about a grouping algorithm which does not only take the overlapping into account but allows also for a slight gap between the notes - as I was trying to describe with a kind of "beam" - and all the starts (because we are going to the right) inside the beam would be added to group.

Additionally it would require that the starts are sequential. Otherwise it would include the first note of the second chord. Also already grouped notes need to be excluded from being candidates for the next group.

We also need to decide if the stacks are shifting to the right or if they are instead stacks with two notes shifting to the left. But I think this would be determined by the first note and the subsequent inclusion of the additional "group" notes.

allejok96 commented 2 years ago

I am interpreting this as a kind of continuous strumming operation on two chords

Correct, think of the image above like a video with a smooth motion.

Thing to consider when making that grouping algorithm:

bild

The left is preferred when creating a strum. But eventually when notes start to overlap it will mess up bad. Even if you could reverse it, the result would probably be unpredictable.

spechtstatt commented 2 years ago

Thought a little bit about the grouping algorithm - maybe it is possible by just using a horizontal and vertical ordering?

The horizontal ordering would take precedence but with the additional condition that the vertical order of the successor has to be greater. If not it would take the next candidate or the group is finished. Then the algorithm would start again with the non grouped bars until all bars are assigned to a group.

For the numbering the algorithm would just start with the first bar. And depending on the shift direction he would either count up or down for the vertical positions.

image

Maybe we need to introduce some distance limits as an addition because there may be a point where it is not feasable anymore to group them together - maybe a full note hole would be enough?

Regarding the distance in your picture I would just use the same constant "step" amount for all notes. Humanization could be applied separately. As it would be the case for limiting the note length if some wants that the notes end at the same position - as with the following function: image

Of course there would be a limit of what you can do regarding reversing the effect but I think with some additional logical coherent edit operations this should be managenable.

Something like this (very rough sketch though): image

Left three buttons deal with extending the bars and right three buttons with shrinking (left, both sides, right respectively)

So if you messed up your strumming and the bars overlap at least you could press image and image if the strumming is shifted to the right.

BUT: of course you could not do this for multiple chords. You would need to select each of them separately.

To be honest when I was looking at the FL studio strumming settings I was a little bit skeptical if one knob could achieve the sturmming and provides enough control (the other functions like volume, pan and star/length humanization would be no problem though). So we could of course think about another button which would use the same group identification algorithm and which would simple reset the position to the earliest not in the group - this would be a "reset strumming" button.

allejok96 commented 2 years ago

Nice illustration. We'd have to take this into account. Some form of dynamic threshold... bild

I see three scenarios:

  1. I know how it works, I know when to use it, and when it won't work.
  2. I don't know how it works, I just click the button and it works.
  3. I don't know how it works, but it didn't work this time it so I'll complain on github.

I fear that this may turn into scenario 3 - complicated and unpredictable. Maybe we should just accept that strumming multiple chords is a destructive operation? Like quantizing. Information is lost. Ctrl+Z is your friend.

~That, or we edit the Note class to include some form of strum offset.~

Spekular commented 2 years ago

For now I would argue for a destructive and dumb strum (disable journaling, change note start positions as necessary, re-enable journaling and journal the new position). I say this because I think the logical conclusion for a "smarter" strum (taken to the extreme) might be non-destructive note filters/transforms/adjustments* and I don't think anyone wants to go there right now.

*Something like effects but for note data, adjusting the notes parameters to generate swing, humanization, transposition and so on.

spechtstatt commented 2 years ago

@allejok96: I completely agree that users need predictable operations but I think we have to differ between two different types of predictability:

1) the user can predict the outcome of the operation by looking at the current state 1) the user sees the future outcome of the operation because of a visual feedback (and can even have some influence on it before applying the operation)

So we could add a small visual feedback which just shows the identified groups somehow like this (the single red one would e.g. not be included because it would be a "group" with just a single note):

image

This way the user would be able to deselect notes which should not be included or even decide to do it more step-by-step for each chord separately if it is a very special or complex situation - which would then be more or less similar how @Spekular suggested.

I think we can improve the algorithm a little bit to include an overlapping (or distance if the group does not overlap) treshold between the notes in a group because it does not really make sense to include notes which have a completely different overlapping or distance value.

But of course it would also be possible to go just the brute force way as @Spekular suggested (if I understood it correctly) by just moving everything what is selected and just hold e.g. the bottom note fixed (and maybe the top note if shifting to the left). It would be really easy to understand and a small but helpful addition.

Monospace-V commented 2 years ago

How would a slider work, one end for equal time and the other direction for progressively more obvious linear skew? Controllable parameter

spechtstatt commented 2 years ago

If we reach the conclusion that more controls are needed - e.g. also for the group selection parameters - we may go into the direction of a separate strum control panel.

Also a possible approach (more like the FL Studio solution which has more parameters). https://www.edmprod.com/fl-studio-piano-roll/#tip-20-strum

musikBear commented 2 years ago

How would a slider work, one end for equal time and the other direction for progressively more obvious linear skew? Controllable parameter

Atm afair the finest graining that is possible for notes in pianoroll, is 1/196. So weather a button a dial or a slider is used the smallest movement of a note is still 1/196 I will have a version up later where note-size dropdown is used as grain

musikBear commented 2 years ago

First part of this is awaiting review Second part is done https://github.com/LMMS/lmms/pull/6293