Skip to content

Random and S&H LFOs and new LFO (and Delay, Arp, ...) sync types - #32

Merged
jamiefaye merged 7 commits into
SynthstromAudible:communityfrom
phfalk:random-lfos
Jun 20, 2023
Merged

Random and S&H LFOs and new LFO (and Delay, Arp, ...) sync types#32
jamiefaye merged 7 commits into
SynthstromAudible:communityfrom
phfalk:random-lfos

Conversation

@phfalk

@phfalk phfalk commented Jun 8, 2023

Copy link
Copy Markdown
Contributor

WIP on #26.

@m-m-adams

m-m-adams commented Jun 9, 2023

Copy link
Copy Markdown
Collaborator

For a more musical rand I think you want to lower the range - try using the random function with a limit that's within the bounds of the other LFO types. CONG on it's own is a linear congruential generator with a range of the entire u32 space

Another possibility would be generating Random Normal distributed values - generate 2 linear ones, cast to float and scale to 0-1, and then get two random normal values y1=sqrt(-2ln(n1))cos(2pin2) and y2 = sqrt(-2ln(n1))sin(2pin2). Alternatively you can make a 1000 points normal distribution lookup table and randomly choose an index in it.

Another possibility would be instead making the noise LFO into a random walk - to do this you would start at 0, generate a random number r between 0 and 10, and move the output r-5 spots. This will create a walk that trends around 0 but wanders up and down at different speeds

As an entirely seperate comment should the LFO types be switched to an enum if we're going to keep adding them? I suspect there will be more to come, I'd personally like to make some one shot decay and attack envelopes in different shapes
Similarly the if/else code should probably be replaced by a map before it expands too much more

@litui litui added the enhancement New feature or request label Jun 9, 2023
@phfalk

phfalk commented Jun 13, 2023

Copy link
Copy Markdown
Contributor Author

I have now tweaked the random LFO into a random walk, which is quite fun to use.

I have also done a lot of refactoring to add new triplet and dotted sync types and make them work with everything that uses tempo sync. The code is not great because everything is quite entangled, but adding enums for sync type and level adds some level of compile time checking as opposed to using ints and constants everywhere. I am still not completely sure if using enums instead of constants is a good idea over all, though.

The last commit in the chain isn't really necessary, because selecting the new sync types is disabled in the compressor menu, but it prepares the compressor to be used with the new sync types in case that is needed in the future.

@phfalk
phfalk marked this pull request as ready for review June 13, 2023 20:27
@phfalk phfalk changed the title Random and S&H LFOs Random and S&H LFOs and new LFO (and Delay, Arp, ...) sync types Jun 13, 2023
@phfalk
phfalk force-pushed the random-lfos branch 2 times, most recently from 494c5bd to 535bb76 Compare June 13, 2023 20:51

@m-m-adams m-m-adams left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Sounds good overall, some minor issues with the random walk not conforming to the LFO2 philosophy

Comment thread src/lfo.cpp Outdated
case LFO_TYPE_RWALK:
uint32_t range = 4294967295u / 20;
if (phase == 0) {
value = holdValue + (range / 2) - CONG % range;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

For LFO2 this should reset to a constant instead of using the holdValue

@phfalk phfalk Jun 16, 2023

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

You mean that LFO2 should essentially always start at zero modulation, every time a note is triggered? That is a little difficult to do when at the same time LFO1 sync should not return to zero at the start of every sync interval, which we can of course discuss as well. In both cases the LFO phase is reset to 0.

I think these random LFOs will always behave a little different than the original periodic ones. One example is that I made them tick half as fast, so only one value change per sync interval as opposed to two maxima in the periodic LFOs, which means two flips for square. In my opinion, that is not a bad thing as long as it is somewhat intuitive.

Interested to hear your opinion on this.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Yeah thats a good point, I didn't consider how it would interact with LFO1. I don't have a strong opinion on whether the LFO2 version would ideally reset to zero or to a random value on with every note on but the current free running behaviour is un intuitive with how LFO2 normally works.

I don't have a good solution since I forgot about LFO1 but I'll comment again if I think of one

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I tried to replicate what you describe, but I am not sure if I completely understand what you mean. To me, it sounds like LFO2 resets correctly on every trigger. Not to zero, but to a new random value, which would make sense with how it is implemented at the moment. The phase gets reset to zero when a new note triggers and that triggers a new LFO cycle, which means a new value for the random LFOs. That is very similar to the tempo synced behavior in LFO1, but feels a little different than for example "sine" which will always start at zero. To me, it feels somewhere in between free running (in terms of modulation) and re-triggering (in terms of rhythm).

Does that make sense? I might be completely misunderstanding your point, though.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The S+H mode sounds like you're describing but the random walk doesn't. If you wait until it's audibly at a low point then when you hit a new note on it stays low. I think this is because the phase reset at 0 still uses the previous hold value

It's not a huge deal and if it can't be changed without affecting LFO1 then I don't think it's a show stopper, the overall effect definitely sounds cool

@phfalk phfalk Jun 18, 2023

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Got it now, thank you. I just pushed some changes that should address that and the biasing. I think we might have to tweak the range and bias a little bit to make it move a little faster or further away.

Comment thread src/lfo.cpp Outdated
value = holdValue + (range / 2) - CONG % range;
holdValue = value;
}
else if (phase + phaseIncrement * numSamples < phase) holdValue += (range / 2) - CONG % range;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This can drift quite far from the midpoint (I had it mapped to filter and it totally closed it for a long time)

Suggest weighting the walk value so that it tends to come back towards range

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That makes sense. I am just testing a function that adds more bias for walking back the more the value deviates from the origin.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Let me know when this is ready to go into community branch.

@phfalk
phfalk force-pushed the random-lfos branch 3 times, most recently from 0e093aa to 6b57e17 Compare June 18, 2023 12:09
phfalk added 6 commits June 18, 2023 14:18
This commit does everything needed to prepare the compressor to work
with the new sync types, but it disables them in them menu by overriding
getNumOptions().
LFO_TYPE_RWALK will now reset to a new random value every time phase
resets to zero. This commit also adds a slight bias to make it stay
(in theory) within an area of around -8*range to 8*range, which in
practice means that it will stay much closer for most of the time.
@jamiefaye
jamiefaye merged commit d5bea57 into SynthstromAudible:community Jun 20, 2023
@soymonitus

Copy link
Copy Markdown
Collaborator

Please @phfalk I beg you, implement the same triplets and dotted options for the Delay sync!

@phfalk

phfalk commented Jul 21, 2023

Copy link
Copy Markdown
Contributor Author

@soymonitus, for some reason I can not reply directly to your comment, so I'm making a new comment. The new sync options for delay and arp are already implemented as part of this MR and the MR has been merged into the community branch. You should be able to try it if you flash a community build.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants