2nd Order Markov chains and [anal] (no joke)
Hi,
I'm really trying to follow the logic of this patch from the [anal] helpfile. I went through object by object, to see exactly what is happening, but it is still confusing me.
I don't understand why the encoding with the [<
Can someone try and help me understand this patch
Cheers
Danny
Hi Danny.
[<< 7] followed by [+] is a way of squeezing two numbers into one (because you want to get a 2nd order Markov chain from two objects that, strictly speaking, can only manage 1st order chains, right?)
So how do you squeeze, say, the two numbers 12 and 34 into one? That's easy: 1234. You can always make one 4-digit number out of two 2-digit numbers by just, so to speak, putting them one next the other. If your numbers were 5 and 6, you could pack them as 0506 (that is, 506). In general, if your original, 2-digit numbers are A and B, and their packed version is C, the operation you are performing is:
C = A * 100 + B
And what if you want to retrieve A and B from C?
A = C / 100 (I'm talking about integer division), and
B = C % 100, that is the remainder of the same division.
Does it make sense so far?
Now, if you think about it, this was ok because we knew that our numbers were always in the 0-99 range (that is, their decimal representations had 2 digits). But what happens if the range is different? If it is 0-999, we must multiply and divide by 1000. If it is 0-9999, we must multiply and divide by 10000. And if we know that it is 0-314, guess what, we can multiply and divide by 315. And if it is 0-127, which is the case with MIDI pitches, we'll multiply and divide by 128.
It turns out that performing << 7 upon a positive integer (that is, shifting its binary representation 7 digits to the left and padding it with zeroes) is a nerdy, and theoretically slightly more efficient, way of multiplying by 128. This happens for the same reason multiplying by 1000 shifts the number three decimal digits to the left, and pads it with zeroes, as in 123*1000 = 123000. And in fact, 1000 = 10ˆ3 (boiling down to 3 digits in base 10), and 128 = 2^7 (7 digits in base 2).
So, long story short, what happens in the example is that you take the two latest note-ons, pack them into a single number with the squeezing trick and feed them into [anal]. And you do the same when you receive a new note-on, and so on. In this way, your transition table always takes into account not one, but two previous notes. The problem is, if your three latest notes were X Y and Z, the transition table now has an entry for XY->YZ. So when you want to extract a new note following XY you won't get Z, but YZ: to get Z you need to get rid of Y, and you use [%] for that.
... well, I hope this makes it a little clearer...
aa
Andrea,
Thank you very much for sparing the time to try and explain this to me. I think I'm going to need to read and re-read this a few times whilst looking at the patch.
Cheers
D
Hi Andrea, just looking at your patch. Really awesome. Just trying to understand it better and see if i can do a higher order markov patch, based on your patch.
for example, if i plug the midi note 60 (the C4) twice, the number i get is 7680 (below the <<7 box). How do we get that result? i was expecting a 4 digit number like 6060.
Then , in the square below (besides the prob object) the number showing is 7740. can you please tell me how do you get that result? Also the 5163 below the prob object.
will really appreciate your insight. cheers
Enrique
if efficiency is not very high on your priority list, transforming two integer numbers into a symbol (tosymbol, fromsymbol) is another way of storing transition states, with the clear advantage of a better readability (you look in the coll, see a "60 67" there and know immediately that it means "c to g")
it is even more useful if you do anything with 3 variables (e.g. if you include velocity or duration) or for higher order markov chains.
thank you Roman, much appreciated, Just wonder if anybody made a higher order markov patch. thanks
the question is what is more useful to create melodies: 4th order pitch - or second order pitch and the inclusion of gain and length with every event.
try both with "fuer elise" (use a midi file with dramatic dynamics) and see what happens.
if you combine both, you almost get the original back even if you quantize lenghts and truncate the velocity to 4 values.
btw: of course it is also important to include chords. that is why i think making symbols is more flexible than digit padding or binary conversion tricks; symbols can contain arbitrary data.