There are several possible reasons why the project may not behave as desired and give pseudo-random flashes, due to the system operating out - or nearly out of - specs. Not knowing the maker of your LEDs doesn't really help in figuring out the issue.
1- many WS2812B-style LEDs expect a digital input voltage - according to the datasheet - that is at least 0.7 * Vcc. Now, when the LEDs are powered from Vcc=5V, this means that in principle the 3.3V from the Bela's SPI output are not enough (though they work in many cases). See possible solutions here https://forum.bela.io/d/3001-control-neopixel-with-pure-data/25
2- timing (and tolerance of the timing) can also vary quite a lot among parts, see same post as above . You may want to get a few datasheets from parts that are likely to be on your boards and see if fine-tuning the T0L, T0H, T1L, T1H helps removing the issue.
3- I assume that the Linux driver will service buffers that are between 160 and 4096 bytes in length via a single DMA transaction. IIRC, I inferred this back in the day by looking at signals generated on a scope. I therefore assume that any CPU load on the board will only affect the delay between asking the transaction to start and the moment it is started, but it shouldn't affect inter-byte timing, which is what is critical here and could be the cause for the sort of behaviour you are seeing. It may be that what you are seeing is the effect of me being wrong on this assumption and in that case, having O2L running on its own reacting to OSC messages would put you in a situation where you can test that for yourself as there would be no load on the board except for the program responsible of parsing OSC and sending out SPI data. For this test, we'd need to also increase the priority of that thread (e.g.: running once in that thread:
struct sched_param p = {
.sched_priority = 90,
};
pthread_setschedparam(pthread_self(), SCHED_FIFO, &p);
)
noah How did you determine those numbers (e.g. kSpiLeadingZerosNs)
Most numbers come from reading the datasheet, e.g.:

The first four should be used for TH
and TL
in the code, while RES should be used for kSpiLeadingZerosNs
. From this specific datasheet, you'd get
const T_t TH[2] = {
{.min = 220, .max = 380}, // T0H
{.min = 580, .max = 1000}, // T1H
};
const T_t TL[2] = {
{.min = 580, .max = 1000}, // T0L
{.min = 580, .max = 1000}, // T1L
};
static constexpr double kSpiLeadingZerosNs = 280000;
You'll notice these are different from what's in the code right now, which goes to show the importance of knowing the device at hand.
Anyhow, in your case you may want to try and increase kSpiLeadingZerosNs
to something like 300000. Unless you are using an inverting FET on the output, in which case it should be set to 0 (see linked thread).