Weird late message issues with seqP

I'm basically playing around with seqP for the first time, and doing so on a fairly powerful machine on which I haven't experienced latency issues before, even when running Tidal with OBS and Hydra.

Yet running what seems to me like fairly basic code with seqP has been causing late messages nearly every cycle. If I really strip down the code, it goes away. But even while experiencing the latency problems, when I look at Activity Monitor, the system usage is less than 10%. And interestingly adding complex parts at the end of the sequence still causes the late messages at the start of the sequence (the complex parts mess things up even when they're not currently being played).

Are there best (i.e. most efficient) practices for using seqP? Fwiw, I've got d1-d3 each with their own seqP contained within a do block. Also, changing the latency in my bootTidal.hs doesn't seem to have any impact.

That's strange. There's nothing about seqP in particular that would cause this as far as I know. Can you share an example that causes these late messages? Also, what version of Tidal are you on? It would be interesting to know whether reverting to an older version of tidal helps.

Thanks @yaxu - Here is a gist with the offending code.

I am on 1.7.2. Reverting back to 1.6.1 did eliminate the issue, but also involved significant code changes: removing press, nCountTo, and coarse (4 * (segment 16 (slow 4 saw))) - not sure why the last one worked on 1.7.2 and not 1.6.1.

I think I'm missing some shorthand function definitions to be able to reproduce this

Yep the coarse bit should work fine in 1.7.2

Usually the late messages for me are caused by "too many events" sent to superdirt... It's hard to tell on your code, but try to comment some jux/superimpose/ply functions. Eg applying ply on a pattern and then a superimpose could cause a lot of events sent.

@yaxu could be interesting a way to know how many events are generated by cycle, or how many events are evaluated by superdirt in realtime

I think in this case it's likely something to do with the new experimental features. Either things getting locked up around accessing state, or excessive messages being processed around the bus effects. Maybe the former as I don't think bus effects are being used here, and cpu usage is low.

Agree it would be nice to have a way to display stats for tidal - including events/bus messages sent per second

So here's something odd: I went back to 1.7.2, and tried removing the nCountTo, and this had no impact. But when I commented out one of the coarse (4 * (segment 16 (slow 4 saw))) lines, it improved significantly - when I commented out both (and note these two lines with coarse are not played simultaneously, but sequentially) the late messages completely stopped.

Will try to reproduce this with simpler code and no custom functions as soon as I can.

According to documentation,

Coarse turns a number pattern into a control pattern that lowers the sample rate of a sample. i.e. 1 for original 2 for half, 3 for a third and so on.

What is it's behavior with values lower than zero? Try to add a "+1" after "saw"

EDIT: I checked on superdirt, coarse is unactive with values lower than 1, so no problems with that.

Unfortunately I can't easily replicate this as simply as I hoped. But this new gist is (I think/hope) a version that should run on vanilla Tidal if anyone want to see for themself (i.e. no custom functions or samples). I did add an extra coarse (4 * (segment 16 (slow 4 saw))) for emphasis, but it's pretty clearly that that line is the one causing the issue.

Thanks changing leg > legato and inevery > whenmod (is that the right alias? it is a better name for whenmod!), and it runs and pegs cpu at 100%, creating skips and late messages. It's definitely a problem with tidal not superdirt, and so not coarse in particular. Will look into it!

I've made an issue here:

I can see why seqP is inefficient - it's calculating everything all the time and that should be an easy-ish fix. However I can't see why these patterns shouldn't run anyway, or why reducing the segment argument fixes things. So I think there is a stranger problem lurking here.

1 Like

Thanks - and sorry I didn't get all the custom functions (my BootTidal.hs is a bit of a mess). Fwiw, inevery n m f is just inside n (every m f)

Ok try running this for a more efficient seqP

playFor :: Time -> Time -> Pattern a -> Pattern a
playFor s e pat = Pattern $ \st -> maybe [] (\a -> query pat (st {arc = a})) $ subArc (Arc s e) (arc st)

seqP :: [(Time, Time, Pattern a)] -> Pattern a
seqP ps = stack $ map (\(s, e, p) -> playFor s e (sam s `rotR` p)) ps
1 Like

This is like night and day - thanks so much!

Great! This fix will be in the next release.

2 Likes