Rhythm morphings / interpolations

Hi, I am really excited to make my first post here!!
I have been thinking a lot lately about implementing a function in tidal to morph between rhythms in the way that Malcom Braff explains here (2nd section):

i think it would be really cool to be able to create smooth transitions between different grooves
as he does often in his music (check out crimson waves for example).
Since it's a rhythmic concept first i would like to apply that to pattern structures, leaving aside the specific content of the patterns, but later on it would be cool to extend the concept adding linear interpolation between the played sound samples for instance, i think it would work great as well to
create transitions between sections.
As the big haskell n00b that I am, i really can't figure out a way to manipulate patterns this way,
but i made a sketch in js (p5) to visualise the effect here (instructions are in the code): p5.js Web Editor
what i would like to have is a function that takes 2 patterns as input and a mixing factor and returns the interpolated pattern: one approach i considered it would be to use <~ to shift the timings of the first pattern according to the second pattern and a value between 0 and 1,
but even if i could extract the pattern structure and manipulate it as the arrays in my js example,
i can already expect issues handling pauses and subdivisions with this method.
any clues on how to approach this?

thanksss,
luca

3 Likes

this is a very neat idea.

Thinking about a general procedure for morphing one rhythm into another, my first question would be what happens if there are an unqeual amount of note onsets? For example my first pattern is "t" while the second one is "t [~ t]". What would the morphed pattern at 50% be?

and reading the article, it seems to me that this would be rather modelled with a function that only expects one pattern? it is not actually an interpolation between two patterns but merely a shift of phrasing, right?

but then, considering examples ii) and iii), we can see that a single pattern can lead to different phrasings.. so maybe it is acutally a function of two patterns, but the patterns definitely have to be related for the procedure to give a sensible output, no?

For decades now, probably since early music education, I have visualized swing as a wave, so this totally resonates with me.

If you read the source code for swingBy, you can almost surely picture the wave it crafts with code. It’s a square wave, with one part of the cycle having zero amplitude and the other part of the cycle having the amplitude you specify via one of the arguments. The frequency is another argument, and phase is cycle-aligned.

Though I sadly can’t do so while writing this reply, I expect that the code for swingBy could be pretty-easily rewritten to make the wave generation explicit. It then wouldn’t take much at all to separate the wave generation from its application via -> aka rotR.

As long as a wave of interest can be generated in the first place, its application via -> / rotR is trivial. Extracting/generating waves then becomes where the magic lies.

Another page on that site gets into this (complete with some great diagrams) seems to be this one: Diversity of grooves: it’s all about da weight !

As an example, this diagram from the link above really resonated with me, looking very nearly like what I’ve long pictured in my mind:

That page also gets into some observations which could be used to help simplify the extraction/generation effort. For example, the observation that anything above 2:1 starts being perceived as a higher division. With that, I figure code could extract a wave much more easily, for a caller-provided level of division.

1 Like

My intuition is that this is similar to linear algebra/vector math. You need to first specify the basis underlying patterns before you can interpolate. One example is a requirement to define conversion from an integral number of beats to a real valued interpolation parameter between zero and one, say.

Specifying some basis, whether as simple as “16ths” or “32nds” or something more complex, seems necessary to me too, for extraction, interpolation, etc.