Setting a waveform sample position in a timerCallback causes flickering


#1

It’s almost as if the old position is removed after the new one is drawn. So a slow moving marker almost completely disappears.

But it only happens on Windows. How can I fix this or, what’s best way of doing this, it seems to be a Windows version bug.
Looking at the DSPDemo, I see the whole waveform is being repainted on a timer, by using JUCE_ENABLE_REPAINT_DEBUGGING.
There is no way I can do that - it’s too time consuming.


#2

To solve this I had to call repaint with and area slightly wider than the marker. This is such a bodge, but it’s the only way I can get it to not flicker. Thanks for providing selectable rectangle repaints.


#3

If the marker is moving quicker I have to make a box out of the old and new positions and repaint that, this is kind of unacceptable. How are child object supposed to animate on their own? I’m moving bounds of the child object on a timer call back, is that not correct?


#4

If you can keep track of where you painted the last time, maybe repainting that position and the new position might be enough? I remember artefacts in professional DAWs that suggests that they are doing exactly that (and that it can easily fail, especially if the component scrolls at the same time, e.g. Viewport… :wink: )

Good luck


#5

Thanks for the reply. I’ve tried many routes, including disabling the marker component then redrawing the position, moving it then repainting again. But I think the problem is that the repaint is not immediate, so I have no idea when they actually happen or whether they are cued up or not.
The main thing I worry about is that I thought the child components were tracked and handled correctly, but this appears to be Mac only, so far.


#6

A more reliable way to draw some kind of moving cursor is with a Component, not by manually drawing/repainting it as a shape. E.g. see CaretComponent

I can 100% guarantee that if you move a child component, everything will be repainted correctly. That has been a solid part of JUCE for 15 years and all apps rely on it.

If you’re seeing artefacts, then it can only mean that you’re doing something silly, but I don’t know what that might be. Maybe you’re painting outside the bounds of your component and seeing it get clipped?


#7

I was drawing my marker by using:
(I’m not sure if it’s what I can do/legally do, or even ‘silly’)

g.fillAll(Colours::red);

Instead of:

   g.setColour(Colours::red);
   g.fillRect(getLocalBounds());

And for some reason the first one worked on Mac but not Windows.
Thanks anyway. It now works perfectly - a strange one though…


#8

Argh! It’s doing it again. Here is a really simple version that is going wrong for me - it consists of a waveform component that has a needle
child component. The needle just wraps around the waveform continuously. I can’t see it passed the first few pixels, until I move the window around. Can someone please tell me what’s wrong with this?
www.quikquak.com/Temp/TestNeedle.zip


#9
void Needle::resized()
{
    if (getParentComponent())
    {
        auto area = getParentComponent()->getLocalBounds();
        setBounds(area.getX(),0, 2, area.getHeight());
    }
}

The resized() method tells you when this component has been resized… it’s the worst possible time to attempt to change its bounds, because they’ve just been changed by something else (!)

And what are you trying to do with its parent’s position? getLocalBounds() always returns a rectangle with a position of (0, 0) so it’ll just always snap this needle component back to the origin.


#10

That’s got it man, thanks, sorry to be a pain, I had very little sleep yesterday, and staring at code all day doesn’t help things much.:disappointed:


#11

I’ve got the problem again, BUT only after the computer goes into sleep mode!
Yeah, it’s astonishing to find out. I went for a walk, came back and woke my machine up, and the problem was back. Only a ‘restart’ fixes the issue afterwards, it seems.
I’ve no idea why my Windows is going this, I may be the only one, here’s another bare bones project that demos it:-
www.quikquak.com/Temp/TestNeedle.zip

edit Just tried an old Windows 7 laptop. And it’s fine with post sleep mode rendering. I may be able to check another windows 10 machine tomorrow.


#12

I can confirm the issue, the needle is flickering on Windows 10
@jules
i guess the two invalid rects (old and new position) are differently prioritised and will be summarized with other (previous) invalid rects, and then somehow awkwardly merged, that there is sometime the illusion that the needle disappears…


#13

That’s good AND bad news. At least I’m not alone with this nightmare.

Did you try putting the PC in and out of sleep mode first?
On mine the needle DOES actually disappear for a while.


#14

No, it flickers only for ca. 1/10 second, but it makes the impression it disappears completely. Checked on windows 10 in a parallels VM


#15

Thanks, did you try after woken from ‘sleep’ mode on an actual Windows machine? It sounds mad, I know, but…


#16

In the code that DaveH shared? Don’t really want to spend time hunting for problems in that code because I don’t trust it to not contain other mistakes, but if anyone can share a short snippet that looks like it should work then we’ll happily debug it further.


#17

daveH code is actually very simple, i guess the trouble begins, when the timer is faster than the actually screen refreshment rate

i made a video, i made with quicktime, on a parallels vm window, can’t upload, because this forum doesn’t allow mov/zip, i have sent it to your mail address

i think the result will depend on the performance of the machine you test on


#18

Hmm, I guess it’s possible that the repaint and timer events could end up getting into some kind of beat-frequency sync thing. But not really sure whether there’s anything we could do about that.

@DaveH what happens if you just tweak the timer interval a bit?


#19

It doesn’t disappear at 25Hz it just flickers every redraw. At 30, 40, 50 and 60 it disappears for a while. It seems to disappear less at slower rates.

So you don’t double buffer?

Did I mention the sleep mode thing is very very important for this to happen?

I wanted to show you a gif of it doing it, but interestingly, the very act of recording the screen stops it flickering. No re-size is being called (and no quantum particles are being summoned! :slight_smile: )
Dave H.


#20

Yes, of course it double-buffers!

But if you imagine what’s happening is that you have a variable which says where to draw this block, and you’re updating that variable while asynchronously redrawing rectangles, then it’s possible in theory for the position variable to always be slightly ahead of the area that’s currently being drawn.

No, you’re missing the point there. When you enter sleep mode, apps are suspended and event queues get messed around, so the order and timing of events will change, possibly triggering or curing weird timing interactions like this. The act of sleeping won’t be a relevant factor, it’s purely the order of event delivery that matters.