< Back to IRCAM Forum

Rhythm tree "nested substitution"

Hello!

I’m trying to deepen my understanding (and application) of rhythm trees, but am getting stuck, probably with the conceptualisation of how to systematise the solution.

Desired process (but at much larger scale)
RT-0: (? ((6//4 (1 1 1 1 1))))

Then

Substitute random impulse from a list of duration values, say, the index 2 (impulse 3), but leave the rest of the impulse string in tact, such that:

(? ((6//4 (1 1 5 1 1)))) - this is simple enough, the subst-rhythm function does this. BUT

I want to then have the RT become ‘nested’ within the substitution, such that:

(? ((6//4 (1 1 (5 (1 1)))))) - it is getting to this part that I can’t get my head around. And preferably skipping the intermediary step, I just wanted to show the thinking. I’ve attached my attempt at it, though it’s not “working” (removing one of the list functions will yield the middle result, but randomised).

I did a good search through the forum but couldn’t find anything that dealt with this. Just the ‘accessing sublists’ post, but couldn’t glean a solution from it. So thank you in advance if anybody can point me in the right direction or offer a solution! I do want to be able to do this in larger voice objects at the measure level, but, little steps first!

rt-sub-demo.omp (19.8 KB)

Hi vgiles,

Unfotunately, to do this you need a custom function that is not available in the TREEs menu.
The problem is that you are removing a pulse from the original layer that contains 5. You are “pushing” the last two pulses in the third pulse of the first original layer.

So you need to construct a function for that.

Best
K

…however i can think in a tree function doing a “pop” of a certain pulse.
Will do this and get back to you.

Best
K

That would be great, thanks Karim.

Hi again,
I’ve had a bit of luck outside of the rhythm tree structure (with a little help from ChatGPT, because I do not know LISP and find the syntax incredibly difficult to parse compared to, say, Java or Python).

This works quite well provided I never try and substitute the final index (which makes sense anyway for the operation). Now I need to work out a way to apply this within an rtree structure.

Vince

Ok, more progress. I managed to integrate the above script into an OMLoop modified from Karim’s demo from Rhythm-trees and time-stretching this thread (helpful, thanks!)

I again have reached a knowledge limit, I think that the output is producing one level too many nested lists for the rtree to be valid (? ((**(**6 4 ...)) and am unsure how to reduce this on output. I think this is an artefact of the collection process within the loop, I assume it needs to be in the eachTime component of the loop.

Will keep trying, but if anybody jumps in then yay.

Vince

And found a solution. Possibly not the most elegant. Had to reformat the time signature component of the list, but here we go. Again, old mate ChatGPT helped with the LISP. I think I understand LISP syntax a bit better now, which may be helpful for Lilypond too.

Hi again folks.

I’m back on this silliness, but trying to apply the above into a more complex procedure for generating rhythm cells. I’m having difficulty with the logic/recursion process (see patch) in order to get the desired results. I suspect that my inability to code with lisp is a real problem, but since these rhythm trees are being constructed manually, I’m wondering if anybody has tips, or advice, on how to approach this particular problem?

Vince

rhythm-mwe.omp (81.2 KB)
Please excuse careless handwriting. It’s just to get the idea across.
Input durations (5 4 7 3) denominator (16)

Dear Vince,

Sorry to say, your patch is in no way a MWE ! There are a lot of missing abstractions.
Can you formulate your problem in simple terms. I see your sketch which is by the way perfectly readable. But sorry to ask, what do you want exactly?

Best
K

1 Like

Dear Karim,

Yes, it is… not really mwe. I tried though! I didn’t realise the abstractions were missing - sorry for that.

The idea is this an expansion of my original post (and solution), where given an input set of values (say, 7 6 5 4) and an input set of denominators (say, 16), I can then construct the following:

A: Measures of each time signature derived from those input values (7/16, 6/16, etc.) each with the relevant number of notes in it.
The result would be a rhythm tree like (((|7//16|)) ((7 (1 1 1 1 1 1 1))))) - this is pretty easy, and I’ve managed that.

B: Measures of those time signatures but with the other numbers from the input list as impulse-quantities (i.e. 7/16 but with 6:7 in it, 5:7 in it, and 4:7 in it, through all iterations.)
(((|7//16)) ((7 (1 1 1 1 1 1 1))))) + (((|7//16|)) ((7 (1 1 1 1 1 1))))) etc. - this is also complete.

C: Then, on each of THOSE generated measures, to take each impulse as an index (say, 7/16 16th note number 2 = index 1), and then start the process of rhythmic generation again but from that index, such that all indexes (except the last one as that results in nil values) get treated with this overlaying of numbers. I.e. (((|7//16|)) ((7 (1 (6 (1 1 1 1 1))))) this is the part I’m having difficulty with, and is shown in the second line of the handwritten materials above, with indexes above it.

So I can do that indexed manipulation on a single measure rhythm tree on input (see the final post before my new problem!), but not when generating many more rhythmic cells as long trees.

I believe that somewhere in there I am not constructing the rhythm trees correctly, but can’t figure out where. I either get an error like this: Error while evaluating the box VOICE 5 : In / of ((7 (1 1 1 1 1 1)) nil) arguments should be of type number., OR, if I reduce the trees enough, I get something like (((|7//16|)) 7 (1 1 1 1 1 1))), which is malformed also.

This screenshot shows the omloop into which the generated components of the rhythm tree are placed for processing. This creates to level B of the above scenario. Level C occurs in the ‘index-dur-sub’ loop and its internal loop ‘rhythm-tree-folder’

This screenshot is the last level.

Hope this all makes sense! I really appreciate the enthusiasm to help.

Vince

Can you send the patch again with the missing parts?

Forgive me, I actually don’t know how to embed the requisite parts, so I’ve made a standalone workspace with the requisite files. I’m not sure if this will work!

test2.zip (23.2 KB)

dear Vince,

still missing stuff. But whatever,

Can you just be concise about your problem: just send the voice/tree and do say what you want to do with it a very straight forward way. Your description above is not clear to me sorry.

best
K

Sorry Karim.

These values are arbitrary and I want to be able to do it with any list, but for example:
Input A → (7 6 5 4)
Input B → (8 16) ← denominators

Using these input lists to generate the following, noting the input A mapping against itself to produce polyrhythms.

And then taking that rtree, and doing this to it:

I got this working on single rhythm trees (as in this screenshot), but I can’t get it to operate on a longer, more complex rtree.

thank you Vince

This is much clearer.
But what about the last process. In my memory it is random. But can we say for the moment it is not? So can you describe me why, when do we substitute values and their indexes, just for the sake of getting it right. Then i can show you how. to do so.

BEst
K

Thanks Karim,

The problem I’m having is getting the process to operate on long-lists. My handwritten example wasn’t quite right, but close enough.

I want to be able to produce an effect like:

Generation 1:
(7 (1 1 1 1 1 1 1))
(6 (1 1 1 1 1 1))
(5 (1 1 1 1 1))
(4 (1 1 1 1))
Generation 2:
(7 (1 1 1 1 1 1)) (6:7)
(6 (1 1 1 1 1)) (5:6)
etc. through all permutations of input.

And Generation 3: ← the part I’m stuck on.
(7 (1 (6 (1 1 1 1 1))))
(7 (1 1 (6 (1 1 1 1))))
etc. through all possible iterations of the input string.

In this generation, the number of overall onset points within each measure stay the same. And because this is operating on the Generation 2 rhythm tree, it will end up with trees like:

(7 (1 (6 (1 (5 (1 1 1))))))

Hope that makes sense.

If i understand you well, the third generation on the first measure should look like that?:

But what doesn’t make sense to me is your last example measure:
(7 (1 (6 (1 (5 (1 1 1))))))
Screenshot_2024-03-01_02-06-12
I am missing some steps here.
sorry, i am a little bit slow… :slight_smile:

Hey Karim,

Yep - that top screenshot is exactly right. How does one access that tree editor window? I’ve seen that on the forum a bit and can’t figure out how to open it - it looks very useful.

It’s just a result of the iteration process, so it may not be a very ‘useful’ rhythm. This shows the result of the same basic manipulation but with a different value. It just leads to interesting relationships. I think I just chose a particularly poor example without checking it. :sweat_smile:

Hi Vince,

Following your logic of your third transformation, here is a complete variation:

The patch:
Patch 31.omp (153.2 KB)

Hope this is what you were looking for.

Now concerning the tree editor:

  1. Open a voice
  2. select either the voice or measure selection icon
  3. hit ‘r’

Best
K

Karim, thank you! That is very helpful, and once I go in and unpack it, instructive too. I really appreciate the time taken.