Struming and microtiming

Hello all! Naive question from a naive person: Is there a simple way to “strum” a chord?

For example, if i do

p1 >> pluck() + (0,2,4)

then p1 is playing a major triad, with all 3 notes occuring simultaneously. What I’d like to do is play the “0” note 30 milliseconds early (say), the “2” note 15 milliseconds early, and the “4” note on time, as though they were 3 strings on a guitar and i strummed downwards.

More generally I wonder what FoxDot can do in the way of microtiming (tiny adjustments in when notes are triggered). I’m aware of how to “swing” the clock, but is there anything finer than that? For instance, one might like to “humanize” a line by playing the notes a random amount early/late. Or always play the snare drum slightly behind the beat like the drummer in The Pixies does, or what have you.

Thanks!

Hi !

Not naive at all, it’s sometimes hard to bring more continuous “human” gestures into the live coding world, especially without using controllers.

The simplest way to do this that I’ve found is using the “delay” keyword arg, eg:

p1 >> pluck(delay=(0,0.015,0.03)) + (0,2,4)

However, this will make the strummed notes late rather than early - I’m not sure how to play notes early, sorry !

I would also love to know how to artificially add +/- offsets to notes to add a “humanizing” effect in FD. @ryan might be able to help here.

Thanks

Awesome, thanks! Never thought about assigning the delay itself to be a pattern, but of course you can do that.

Based on your answer I figured out how to do what I wanted - to get the notes to be early you just add a negative delay! Something like

p1 >> pluck(delay=(-0.03,-0.015,0)) + (0,2,4)

I say “something like” because it turns out that I cannot really perceive a 30 ms delay in this capacity - either the attack of the “pluck” instrument is too long, or I don’t really know what to listen for. So not a great example; best play around with that “30 ms” number a bit.

Anyway I… guess this probably answers basically all of my other questions: just set the delay accordingly. For humanizing, I bet you’re supposed to set the delay to be a timevar which behaves (pseudo)randomly - I mean, not that I know how to do that either, but at least I know where to start now!

folks i just have to say I love the sheer hackability of this language so much… This was one of those “…wait…no way is this gonna work…” moments for me.

1 Like

For humanizing, this should do the job especially on drum patterns

@player_method
def human(self, velocity=20, humanize=5, swing=0):
    """ Humanize the velocity, delay and add swing in % (less to more)"""
    humanize += 0.1
    if velocity!=0:
        self.delay=[0,PWhite((-1*humanize/100)*self.dur, (humanize/100)*self.dur) + (self.dur*swing/100)]
        self.amplify=[1,PWhite((100-velocity)/100,1)]
    else:
        self.delay=0
        self.amplify=1
    return self

d1 >> play("x-o-").human(80, 20, 30)
1 Like

@speedymollusc oh wow I didn’t know negative delays worked! great find :slight_smile: guess you could use something like delay=(-PWhite(0.02, 0.04), -PWhite(0.01, 0.03), -PWhite(0, 0.02)) but that is long-winded so the handy Player method from @CrashServer would be much better, especially live