So there’s a number of things here, first if you’re filling a lot of rectangles to fill a visualizer I’d recommend fillRectList which i believe is more efficient.
Secondly id move the visualizer to its own component and then run the timer/refresh there, to help isolate the issue (generally juat a better system anway since then you can reuse this in the future easier), but using vblankattachment means you can do the processing based on the refresh rate of the display, which is typically smoother, however you may want to experiment to ensure at high refresh rates it’s not too much work.