j0py / Pmini

Compact eventpattern generator for SuperCollider
6 stars 1 forks source link

Pattern crashes the interpreter #2

Open Bubobubobubobubo opened 1 month ago

Bubobubobubobubo commented 1 month ago

I think that I have identified a few bugs with the parser. Nothing dramatic but some of them are crashing / halting the interpreter such as this one: "[casio:2 casio:3/3]/<2 3 4>". I'm opening this new issue to identify some examples that I've found. Will post more if I find more :smile:

j0py commented 1 month ago

interesting!

so you want the number coming after the "/" be patternable too. is that possible in Tidal Cycles? not sure, but if so, then "wauw!"

i would like to know what patterns make the interpreter crash, as the Pmini parser must become as robuust as possible.

In return i fiddled this for you:

// class (Pm)ini(b)ind or any other short name // Pmb : Pbind { *new { arg ... pairs; pairs.asDict.at(\mini) !? { |pattern| var pair = [ [\trig, \delta, \dur, \str, \num], Pmini(pattern), // \str becomes \degree for example \degree, Pfunc({ |e| if(e.trig <= 0) { \rest } { e.str.asFloat } }) ]; pairs = pair ++ pairs; }; ^super.new.patternpairs_(pairs); } }

this leaves the Pbind class unaltered, and now you can say:

s.boot x = Pmb(\mini, "1 <2 5 _ 3> 3 4").play x.stop

Op 13-05-2024 22:39 CEST schreef Raphaël Forment @.***>:

I think that I have identified a few bugs with the parser. Nothing dramatic but some of them are crashing / halting the interpreter such as this one: "[casio:2 casio:3/3]/<2 3 4>". I'm opening this new issue to identify some examples that I've found. Will post more if I find more 😄

— Reply to this email directly, view it on GitHub https://github.com/j0py/Pmini/issues/2, or unsubscribe https://github.com/notifications/unsubscribe-auth/AWOBQYOXQERFLDHWEQMBABLZCEQJLAVCNFSM6AAAAABHU4WARCVHI2DSMVQWIX3LMV43ASLTON2WKOZSGI4TGOBQGA3TKNQ. You are receiving this because you are subscribed to this thread.Message ID: @.***>

Bubobubobubobubo commented 1 month ago

I have integrated Pmini in a convoluted way so my patterns can look like this:

(
~rhythm => [
  pat: "[kick:11(3,8)/2, hat:4(5,8)/2, fsnare:2(1,8)/4]",
  rate: [1, 0.5], release: 0.5,
];
~rhythm.fx1(0.1, {
  arg in;
  var sound = CombC.ar(in, 2, c.dur / 4, LFNoise0.kr(c.dur * 2).range(0.01, 1));
  sound = MiVerb.ar(sound, time: 0.1);
  sound
});
~rhythm.play;
)

Is that possible in Tidal Cycles?

Most things are possible yes. For instance, if I'm not wrong, you can also do kick:[2|3|4]. You can even pattern some of the values inside the euclidian operator. There a few impossible combinations but very few of them and there is usually a better way to express what the expression suggests.

I have other patterns crashing the interpreter but more strikingly, I can crash SC by playing a pattern without associating it with a default instrument. I don't think that this is possible in the regular Pbind examples you have in the README file. It means that if I write ~a => [pat: "0 1 2"], it is game over and SC crashes 😄. It doesn't produces any error message, it just.. crashes. I'm trying to debug it now!

EDIT: adding this one that does not behave like the regular Tidal: "[1 2|~ 3 4]/2". It looks like it chooses between 1 2 and ~ 3 4 even though it should be choosing between ~ and 2. You can get the right behavior with "[1 [2|~] 3 4]/2".

j0py commented 1 month ago

Nice code! Clear to see what is happening and to later come back to and tweak while being distracted on a dark stage..I studied the Tidal docs and watched the videos of Alex, but it seems there is a lot more under the Tidal hood to cover.Euclidian numbers are patternable in Pmini though, that should work..If I do "<a b>/<1 2>/<1 2>" what should happen? I have to run a few blocks to get my head around that.And I am going to feed it to Strudel 🤗I will put more effort in Pmini to make its parsing capabilities better and not crash interpreters and scsynths. Thank you for reporting the issues on GitHub.Cheers!On May 14, 2024 00:01, Raphaël Forment @.**> wrote: I have integrated Pmini in a convoluted way so my patterns can look like this: ( ~rhythm => [ pat: "[kick:11(3,8)/2, hat:4(5,8)/2, fsnare:2(1,8)/4]", rate: [1, 0.5], release: 0.5, ]; ~rhythm.fx1(0.1, { arg in; var sound = CombC.ar(in, 2, c.dur / 4, LFNoise0.kr(c.dur 2).range(0.01, 1)); sound = MiVerb.ar(sound, time: 0.1); sound }); ~rhythm.play; )

Is that possible in Tidal Cycles?

Most things are possible yes. For instance, if I'm not wrong, you can also do kick:[2|3|4]. You can even pattern some of the values inside the euclidian operator. There a few impossible combinations but very few of them and there is usually a better way to express what the expression suggests. I have other patterns crashing the interpreter but more strikingly, I can crash SC by playing a pattern without associating it with a default instrument. I don't think that this is possible in the regular Pbind examples you have in the README file. It means that if I write ~a => [pat: "0 1 2"], it is game over and SC crashes 😄. It doesn't produces any error message, it just.. crashes. I'm trying to debug it now!

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you commented.Message ID: @.***>

j0py commented 1 month ago

Thank you for the other issue with the | character. I had the impression that I had the correct behavior for that but I guess not. Will be fixed too.

The crashes of sclang are probably caused by the fact that my parser uses recursiveness. This appears to be not so handy if you want to build something robuust that does not crash on whatever input you give it. So I am now making a non recursive version, in which all loops will end in a predictable manner. It will also give info about syntax errors/misunderstandings.

Bubobubobubobubo commented 1 month ago

Yes, I think that I sometimes fall in these recursive traps. I ended up integrating quite nicely with my current setup. If you want to take a look: https://github.com/Bubobubobubobubo/BuboQuark. I can get various interesting behaviors thanks to Pmini (sample-based patterns, pitched samples, CC Messages, etc). Let me know if I can help you making it better/more robust. I can help for testing stuff, etc.

j0py commented 1 month ago

OKee i have started making the non-recursive parser. It can parse stuff like "[casio:2 casio:3/3]/<2 3 4> 12" without problems. I still have to then do something with the parsed data, that will come soon. I checked the video + description of Yaxu about the "|" character in mini notation (week 4 lesson 2, and to me it looks like that the surrounding square brackets must be there. It says:

-- The second step in this sequence is a randomly pick from
-- four subsequences:
d1 $ n "0 [0|1*3|2*8|3 4 5] 2 3" # sound "cpu"
   # speed 1.5

the four sequences are "0", "1*3", "2*8" and "3 4 5". omitting the brackets would give us these four sequences: "0 0", "1*3", "2*8" and "3 4 5 2 3" :-) What do you think?

Bubobubobubobubo commented 1 month ago

I think that your assumptions are correct! I've been playing with it more and more since it is now integrated and found other inconsistencies such as the {}% and (x, y) euclidian operator. I will do my best to summarize and explain because I think that the issue is the same in both cases:

Mark Zadel has written a wonderful document about the Tidal pattern syntax. It is not very well known but it goes in depth into the whole thing. Maybe it can help with the parser refactoring.

j0py commented 1 month ago

Indeed a wonderful document!
The part on mini-notation confirms most of my assumptions as to what a certain pattern should do.

About the euclidian patterns: i am not sure what you mean by unfolding the pattern.
The class that Pmini get's it's cycles from is JSMini, and class JSMini has a log method which will show what steps it generates for a cycle. Like so:

JSMini("1 2(3,8)").log

 "[" 1.0 
-- "1" 0.5 
-- "2" 0.5 
--** "(" 0.0 ,
--**-- "," 1.0 
--**---- "3" 1.0 
--**-- "," 1.0 
--**---- "8" 1.0 
cycle 0
[ 1, 0.5, 0.5, 1, nil ]
[ 1, 0.1875, 0.1875, 2, nil ]
[ 1, 0.1875, 0.1875, 2, nil ]
[ 1, 0.125, 0.125, 2, nil ]
-> a JSMini

First it logs the internal "tree" of nodes that will generate the steps, and then it will log the actual steps generated for the given cycle (default is cycle 0). Each step is an array with 5 value: trig, delta, dur, str and num.

The euclidian steps together occupy half the cycle, which is correct. And within that half cycle, the time is divided over 3 identical steps according to (3,8). Delta's are 0.5 * 3/8, 0.5 * 3/8 and 0.5 * 2/8. And so are the dur values.

Looking in the Mark Zadel doc (under "Use brackets to create a Euclidean rhythm:") step "a", which would normally last a whole cycle, is cut into 3 smaller steps, each lasting 1/7 of a cycle and spread out over the time of a cycle using the (3,7) notation.

The only difference i see with JSMini is that JSMini makes the duration of each euclydian step as long as possible (equal to the delta), while in Mark Zadel doc, each step gets a duration of 1/7th step.
Is this the difference that you encountered?

Bubobubobubobubo commented 1 month ago

The only difference i see with JSMini is that JSMini makes the duration of each euclydian step as long as possible (equal to the delta), while in Mark Zadel doc, each step gets a duration of 1/7th step. Is this the difference that you encountered?

I think so! Sorry for not looking into the whole thing at a deeper level! I suspect that this is also the case for {}%. It can be quite surprising for a user expecting to find the tidal notation as is. I should probably be more methodic and do a write-up of all the tiny differences I find here and there. They come naturally while playing but I don't have much time to play 🥲 .