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

Gain Modulation with calculated modulation per event #1095

Open
wants to merge 18 commits into
base: main
Choose a base branch
from

Conversation

daslyfe
Copy link
Collaborator

@daslyfe daslyfe commented May 10, 2024

This pattern could be used as the basis for all kinds of interesting modulations.

An example:

setCps(.5)
$: s("bd:4:4!4").gain(.4)
$: s("oh!16").gain(.1).am("4").amskew(1)

$: note("{f g c d}%16".add("{12 7 0}%16")).am("<4 16 6>").amskew("<1 0 .5>").s("sawtooth").release(.1)

The timing of the modulation for the non-synced clock is a little off, and I haven't been able to figure out why yet. Maybe @felixroos you might have an idea? The synced clock timing is accurate.

@felixroos
Copy link
Collaborator

just a quick idea: maybe tremolo should be an alias of am ? (Then also pm should be an alias of vibrato)
need to dig into the rest of it soon..

@daslyfe
Copy link
Collaborator Author

daslyfe commented May 13, 2024

just a quick idea: maybe tremolo should be an alias of am ? (Then also pm should be an alias of vibrato) need to dig into the rest of it soon..

Yeah that makes sense to me 👍

@daslyfe
Copy link
Collaborator Author

daslyfe commented May 14, 2024

Okay this should be ready to go now. The cycle calculation jitters a bit on the non synced chromium clock but isn't very noticeableand can probably be improved with better math.

@daslyfe
Copy link
Collaborator Author

daslyfe commented May 14, 2024

I updated the non synced clock to more closely match the synced clock in order to make the cps calculation more accurate on chrome. I also brought over the setCycle function that can be integrated in new features :)

@daslyfe daslyfe requested review from felixroos and yaxu May 14, 2024 03:30
@felixroos
Copy link
Collaborator

I've tested it and it works great!
It would be good to find a syntax to allow switching between absolute phase (like am) and relative phase (like all others rn). I imagine being able to apply tremolo with a relative/resetting phase could also be something desirable. It probably makes sense to make relative phase the default and add some keyword for absolute phase. Maybe something like am.lfo().
It also depends on which other effects might be suitable for absolute phase. Could this also be used for non repeating effects like envelopes?

if (this.num_ticks_since_cps_change === 0) {
this.num_cycles_at_cps_change = this.lastEnd;
this.seconds_at_cps_change = phase;
(phase, duration, _, time) => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

What's the idea behind these changes? I can't quite figure out the intention by just looking at the code o_O

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The cycle calculation has to be adjusted slightly to compensate for when the event is actually played so that the phase of the modulation can be lined up. I already had made the cycle calculation on the neocyclist, so I just brought that logic over as well as the setCycle function. I could not figure out how to get the cycle offset adjustment to calculate properly with current cyclist implementation. Maybe you might know a better way to get this value?

@@ -86,7 +83,7 @@ export class NeoCyclist {
this.latency +
this.worker_time_dif;
const duration = hap.duration / this.cps;
onTrigger?.(hap, 0, duration, this.cps, targetTime);
onTrigger?.(hap, 0, duration, this.cps, targetTime, this.cycle);
Copy link
Collaborator

Choose a reason for hiding this comment

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

could cycle potentially be deduced from the hap itself? something like hap.whole.begin.sam() ? not sure

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That was the original plan, but the events don't line up perfectly unless you get the adjusted cycle that accounts for latency etc. Honestly could use some help here, maybe there is a better way to do this.

@@ -260,7 +260,7 @@ export function resetGlobalEffects() {
analysersData = {};
}

export const superdough = async (value, t, hapDuration) => {
export const superdough = async (value, t, hapDuration, cps, cycle) => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

could there be a default value for cycle to make am (and potential future friends) be relative to seconds? so am(4) would be 4Hz. thinking about using superdough without strudel, where cycle is a non existing concept

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yeah you could just pass in the time in seconds since clock start and it should work that way. I agree having both options would be nice for different effects

@felixroos
Copy link
Collaborator

I've tested it and it works great! It would be good to find a syntax to allow switching between absolute phase (like am) and relative phase (like all others rn). I imagine being able to apply tremolo with a relative/resetting phase could also be something desirable. It probably makes sense to make relative phase the default and add some keyword for absolute phase. Maybe something like am.lfo(). It also depends on which other effects might be suitable for absolute phase. Could this also be used for non repeating effects like envelopes?

the switching between relative and absolute is probably not needed yet in this PR, just an idea for the future (tho it implies a breaking change)

@felixroos
Copy link
Collaborator

just a quick idea: maybe tremolo should be an alias of am ? (Then also pm should be an alias of vibrato) need to dig into the rest of it soon..

Yeah that makes sense to me 👍

thinking again about this, I realized there is a distinction between fm and vib:

  • fm is relative to the hap frequency, which allows keeping the timbre of different notes the same (fmh controls the ratio of modulator and carrier frequency)
  • vib uses an absolute modulator frequency, independent of the carrier frequency (typically used for lower frequency modulation)

just from a naming perspective, it might make sense for am to be frequency relative as well? The frequency independent version would probably be tremolo then? Combining this with absolute / relative phase, we have 4 variants:

absolute frequency  relative frequency
relative phase vib / tremolo fm / am
absolute phase vib.sync ? / tremolo.sync ? fm.sync ? / am.sync ?

not sure if relative frequency + absolute phase is even needed..

@daslyfe
Copy link
Collaborator Author

daslyfe commented May 18, 2024

just a quick idea: maybe tremolo should be an alias of am ? (Then also pm should be an alias of vibrato) need to dig into the rest of it soon..

Yeah that makes sense to me 👍

thinking again about this, I realized there is a distinction between fm and vib:

  • fm is relative to the hap frequency, which allows keeping the timbre of different notes the same (fmh controls the ratio of modulator and carrier frequency)
  • vib uses an absolute modulator frequency, independent of the carrier frequency (typically used for lower frequency modulation)

just from a naming perspective, it might make sense for am to be frequency relative as well? The frequency independent version would probably be tremolo then? Combining this with absolute / relative phase, we have 4 variants:

absolute frequency  relative frequency
relative phase vib / tremolo fm / am
absolute phase vib.sync ? / tremolo.sync ? fm.sync ? / am.sync ?
not sure if relative frequency + absolute phase is even needed..

I think having different words for cycle based speed and frequency based might limit us when other modulations are added that don’t have similar word equivalents. I think it would be better to have something like amBasis(“<frequency cycle”) with cycle always being the default because it is much more rhythmically useful

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.

2 participants