Best practice for getting samples into `AudioVisualiserComponent` in a plugin?

Hi, I am building a plugin to visualize the incoming audio as a scrolling waveform using AudioVisualiserComponent to start learning JUCE.

My current approach is having the AudioVisualiserComponent live as a public member on the processor class:

class PluginProcessor : public juce::AudioProcessor {
public:
  /* ... */
  juce::AudioVisualiserComponent visualiser;
};

I call pushBuffer inside of processBlock to feed the visualiser samples.

The editor class calls addAndMakeVisible on this component in its constructor:

PluginEditor::PluginEditor(PluginProcessor &p)
    : AudioProcessorEditor(&p), processorRef(p) {
  /* ... */
  addAndMakeVisible(p.visualiser);
}

With this, I get a working and visible visualiser in my plugin’s GUI.


However, this doesn’t feel right to me. My intuition says that since AudioVisualiserComponent is a GUI-related component, it should be owned by the editor class, not the processor.

One idea I had was to add a method to the processor class to register a AudioVisualiserComponent to feed samples to. The editor can now own the visualiser instance, register it with the processor, and the processor can still call pushBuffer inside of processBlock, assuming a visualiser has been registered.

I imagine there is an obvious answer here that I’m missing due to inexperience with JUCE. What is the recommended way of handling this type of communication?

AFAIK, you can’t do something like that without some dirty workarounds. The key issue is that if AudioVisualiserComponent is owned by the editor, it will be destroyed when the editor is closed. But at the same time the audio thread is using it.

I would recommend splitting that code into two parts.

  • the processor owns a FIFO and push samples into it.
  • the editor pulls samples from that FIFO.

Will try this, thanks!