Beginner 'using a counter in a pattern' issue

Hello all,

This might well have a simple solution but I can’t find any example in the help documentation that appears to cover this.

Here is the code.

Pn(Pseq(melody[0], inf), cycles[0])

In both cases I want the arrays numbers “0” to increments by one after each Pn is completed. The “cycles” is a straight 1-10 number sequence, so first time the melody is repeated once, second time twice etc.

Similarly the melody chances with each new Pn cycle. There are 10 melody patterns in a nested array.

The result would be melody 1 repeats 1 time, melody 2 repeats twice…

Is it possible to do this simply using patterns, or does some additional code have to be used?

Thanks for any help!

If I understand the requirement, then… the pattern-idiomatic way would be to build it as a structure of patterns (whereas, what you’re describing is logic).

That is, given “melody” as a nested array and “cycles” as an array of integers:

Pseq(
	melody.collect { |row, i|
		Pseq(row, cycles[i])
	}
)

… which will play through melody[0] for cycles[0] times, then melody[1] for cycles[1] times, and so on.

The logic-based approach runs into trouble in that you would need a signal to increment the index, at the end of one Pseq. Patterns don’t emit this kind of signal, so to implement that, you would have to write it into your own routine:

Prout { |inval|
	melody.size.do { |i|
		inval = Pseq(melody[i], cycles[i]).embedInStream(inval);
	}
}

… so that an i increment occurs between embedInStream invocations. This “works” but the use of stream internals makes it harder to understand than the structural version that I proposed at first… so IMO a “fancy logic” version is kind of a red herring. I wouldn’t bother tbh.

(Btw… Pn(Pseq(melody[0], inf), cycles[0]), if performed literally as written, would be indistinguishable from Pseq(melody[0], inf) because the Pseq will never relinquish control – I’m pretty sure that’s either a typo or conceptual error, so I’ve ignored that in the solutions above.)

hjh

2 Likes

Hi JamShark, this is a really helpful reply. I’m just working through your answer, as there is still a little confusion for me, even though it appears to work. Will post a final response when I’m clear about things.

Main thing for me is that this is not possible with Patterns alone, and that is very helpful to know as I was primarily looking for a solution without using a function.

I’m very grateful for your help!

The first example that I posted is a pure pattern solution.

hjh

Yes, sorry what I meant was to achieve the goal without adding a function. E.g., just using Pseq, Pdup etc. But of course you’re right, it is a pure pattern solution.

Hi Jamshark,

Your solution works great, but I’m slightly confused as to why there are two Pseq required, rather than just one?

Pseq(
	melody.collect { |row, i|
		Pseq(row, cycles[i])
	}
)

I am expecting to see only one, as only one is required to play the pattern once the function is processed. Obviously I am wrong, but I do not understand why.

Let’s look at your requirement:

  • “The result would be melody 1 repeats 1 time…”
    • To play through one row (one melody) of the nested array, you need one layer of Pseq. (Actually you need one Pseq per row – think about this, if you have ten melodies in the nested array, how many Pseqs do you need for those?)
  • “… [then] melody 2 repeats twice…”
    • So, there is a sequence of sequences. If you have only one layer of Pseq then you can play one of the melodies n times and then stop, you’re done. If you want not to be done at that point, then you need an outer layer. (See the Practical Guide to Patterns Words to Phrases chapter.)

hjh

1 Like

Hi JamShark,

I realised I did not respond to this before, my apologies. Your response is very helpful and I have a much better understanding now! Thank you :blush: