First, let me just state that I am new to JUCE and extremely rusty with C++. A long time ago, I worked with puredata (which I believe is built with JUCE?). In that visual programming language, I remember an object called a “bang” which is basically just a event which can be used to trigger something. By connecting the same bang to multiple objects, you could synchronize them all to do their respective things at the exactly the same time, whether that be generating a sound or moving a rectangle across the screen. This is what I want, only I want to do it in code.
I want this to create a simple metronome with an animation that updates each time there is a “beep”. I have already figured out how to generate the beeps. The trouble comes in with the animation. Roughly my app is structured like this:
- My main component inherits from AudioAppComponent
- In the AudioAppComponent::getNextAudioBlock method, my main component passes the AudioSourceChannelInfo to a custom Metronome class that I created. This class then fills the buffer with the right amounts of silence or “beep”.
- The animation happens in another custom class I named MetronomeVisualizer that inherits from Component. Each time there is a “beep”, a custom method MetronomeVisualizer::onMetroTick has to be called which tells it another metronome tick has occurred. It would then have to be repainted using the Component::repaint method.
This is approach is problematic for two reasons:
- Which thread should call MetronomeVisualizer::onMetroTick? This can’t happen in the Metronome class’ thread. It only fills the buffer. The buffer doesn’t get played until sometime very shortly after by the audio thread (how do I even access that?).
- Assuming I even knew where to call MetronomeVisualizer::onMetroTick, Component::repaint is only a suggestion. The JUCE documentation states:
“Calling this will not do any repainting immediately, but will mark the component as ‘dirty’. At some point in the near future the operating system will send a paint message, which will redraw all the dirty regions of all components. There’s no guarantee about how soon after calling repaint() the redraw will actually happen, and other queued events may be delivered before a redraw is done.”
If that’s the case, what do I have to do to guarantee that the repaint will be fast enough that it does not fall out of sync with the audio beeping? AnimatedAppComponent looks promising, but it too simply calls the repaint method at regular intervals based on a timer (which is probably inaccurate on top of it). And again, how do I get access to the right thread to even trigger the animation to start at the right time?