Avoiding AudioThumbnail repaint - Tutorial: Draw audio waveforms

I’m new to Juce and relearning C++ in general. I do program C# daily. Apologies for the basic question, but I’m trying to understand how Juce works.

I’m following the Draw Audio Waveforms tutorial (JUCE: Tutorial: Draw audio waveforms), and completed the exercise at the end of the tutorial to split the code so that the waveform and playback position is drawn by separate components.

The tutorial states that this would avoid unnecessary repaints for the thumbnail components:

Not only will this make the code easier to follow but, if done correctly, it will be much more efficient since we can avoid redrawing the waveform every frame.

However, if I put a breakpoint in the paint method of the waveform thumbnail component, I see that it still gets called.

By experimenting, I see that waveform component paint is not called if I turn off the timer that repaints playback position component. So the repaint of the waveform is caused by the playback position component that is positioned on top of it and has the same bounds.

I’ve observed the same behaviour in the solution code (AudioThumbnailTutorial_04.h).

My question: Does this mean that there are no performance gains from splitting the two, since they’re on top of each other?

If that makes a difference, I’m on macOS Big Sur and use CLion.

Juce tends to be pretty eager to repaint the components even if you try optimizing the code by using separate components and so on. So it’s probably “normal”.

It might be possible to optimize the code by repainting only the “dirty” region in the waveform component, repaint() has an overload that takes in the dirty rectangle area. It can get tricky to keep track of the dirty areas, though. But maybe it’s not so bad with a relatively simple thing like a play cursor. You should check if this happening already anyway, though. (Observe what the getClipBounds returns from the Graphics instance passed into the thumbnail component, if the clip bounds are smaller than the full component, the AudioThumbNail class can take that into account and optimize the drawing.)

Another option could be to draw the waveform into an Image, it might be cheaper to draw that on the component than the full waveform.

1 Like

Wouldn’t setBufferedToImage(true) on the waveform be sufficient?

Thank you for those ideas!

Supplying the playback position component repaint() with a clip rectangle was easy - it works as expected and redraws only the selected portion of the playback position component.

The full bounds of the component gets passed as the clip rectangle to paint() of the waveform thumbnail component.

If I needed to optimize further, I’d explore the drawing to a bitmap idea and other ideas. Another idea I had was to try to make the position component narrow and moving it in position, rather than painting a narrow line in a large fixed rectangle that overlaps the entire waveform. But I’ll rather move on with the other tutorials.

Thank you very much, though. I feel that at least I understand Juce a little bit better