I am working on my monitor class (audio level visualisation) . And my solution is to make my monitor class inherit from Timer. I capture audio envelope in my processor AudioProcessor, and update the monitor in timerCallback(), and also in timerCallback() I call repaint(), like that:
My callbeck interval is set by startTimer(40), so it repaints 25 times per second.
And I tried to optimise my drawing code in paint(). So I started bit by bit turning off individual parts from paint(), until I found that nothing change in CPU usage even though I remove everything from paint().
I created some debug button which lets me turn off everything in paint(), like that:
So I can compare in the runtime. And I found out when turnOff_DEBUG == true my CPU usage is not less than case when turnOff_DEBUG == false. Maybe little bit less but it’s unnoticeable.
But when I remove repaint() from timerCallback() then CPU usage decreases distinctly.
So it looks like my code in paint() is not problem, but calling repaint() causes most CPU usage. Actually “problem” is wrong word. It’s not big problem, but I just try to optimise my plugin.
So I suppose I don’t need to optimise my drawing code. But I wonder maybe I can optimise in some way usage of repaint(). Maybe I could set my timer interval bigger, but it looks like 25 per second is at least to achieve fluid/smooth visual effect.
So I have no idea how to make it more efficient. I can’t clearly understand behaviour of paint(), repaint() and all those things. I found out paint() is often called even without calling repaint().
Could anyone give some advice?
Forgot to mention I checked all those thing in debug compilation with project optimisation set to none. And of course when I remove repaint() from timerCallback(), or I set turnOff_DEBUG = true then my monitor doesn’t work, but it’s not the case. The case is CPU usage.
Hello thanks for your advice. I will try to test it in release build.
But by the way, what kind of optimisation do you recommend for release build. I have no experience with that at all.
I always set release optimisation in xCode for
“Fastest, Aggressive Optimizations [-Ofast]”
But by default it is set to “Fastest, Smallest [-Os]”
I tried both but I see no difference. So I am not sure what is the best choice and for what purpose?
The defaults for a release build should work fine. If it doesn’t, the problem may be somewhere else, for example what I mentioned above : calling repaint() on your single component may be causing repaints in other components.
You can try calling setOpaque(true); in your monitor component’s constructor, if the component completely covers the components behind it. (For example, if you do a Graphics::fillAll call at the beginning of your paint method with a non-transparent color.)
last 2 days I’ve made a lot of experimenting with setOpaque(), repaint() and things like that.
Unfortunately there is some strange behaviour which I can’t understand.
I have three separated Components (like input monitor, output and gain reduction).
I’ve set all of them to setOpaque(true). They don’t overlap each other. And all Labels that can change text I disabled.
If you’re on Xcode 9 or lower, try adding JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS=1 into the Preprocessor Definitions section of your Projucer file. If it fixes the repaint calling issue we’ll know that CoreGraphics was the problem
If you’re on Xcode 10… Apple broke some things that JUCE was using so this won’t work anymore and CoreGraphics will be free to group multiple repaints into one, larger area
You are probably right, because I tried it also on Windows today, and there was no such problem. I thought maybe I do something wrong on Mac. But it looks like it’s not problem in my code.
And to be clear: yes I use xCode 10.
But the question is. How to work with that issue? Do you think if I make all of my monitors as a one Component would help? I mean one component with only one paint() method which paint all monitors.
Of course I can just check it. But actually it’s a lot of work for me now, changing all bounds and moves everything to one class. And I don’t know if is it worth to do that?
Ah, it sounds like it must be related to CoreGraphics then
Darn I was speaking with @t0m about it at ADC back in November and there wasn’t a workaround for that yet, as far as I know
That “could” work since it would let you specify exact regions to repaint… but I’ve found that doing things like this makes working on projects way more difficult. It’s must easier and less error-prone to use juce::Component when you need actual “widgets” in the GUI
If it’s really a problem or making the CPU usage high, you could start out by simplifying your drawing code.
You could also move components that repaint often closer together, so that if CoreGraphics does group repaint regions together that it won’t be such a large area
A good way to reduce calculations in paint is to put them in a data structure you can keep as member, e.g. Path or RectangleList are particularly useful for that purpose.
Or last resort drawing into an Image, which exists built in by setting setBufferedToImage()
my experience has been. On OSX multiple drawing components collapse the CPU in standalone version of the app, but the situation is non problematic in VST3 plugin version. This means it has to do something with how the DAW is handling the plugin drawing.