Instantiate an instance of AudioDeviceManager using address of operator?


I’m trying to build my JUCE app from the ground up now. And I think I need an AudioDeviceManager object. (In fact, at the current moment, my belief is that I need to create an AudioSource class and an AudioDeviceManager and I should be set!)

I’m looking through the AudioAppComponent class to see how they have done it, (the respective JUCE tutorial also bases itself off that)

I noticed this among the public member variables:

AudioDeviceManager& deviceManager;

I’ve never seen an object being instantiated with the address of operator. If it were a pointer (AudioDeviceManager* deviceManager;), I would understand that it has merely created a pointer and I would need to look elsewhere to find where the object is actually being created (and then being pointed to by the aforementioned pointer)

Among the private member variables, AudioAppComponent does declare an object in the typical fashion:

AudioDeviceManager defaultDeviceManager;

And in the initialisation list of the default constructor of AudioAppComponent we see that the defaultDeviceManager object is passed into deviceManager.

    : deviceManager (defaultDeviceManager),
      usingCustomDeviceManager (false)

Help me break this down please. So… AudioAppComponent creates an object of AudioDeviceManager privately and publicly it creates a reference to a (emphasis on “a”) AudioDeviceManager, which it so happens to instantiate as the defaultDeviceManager in the default constructor, because alternatively in the parameterised constructor, you can feed it a DeviceManager that you have created elsewhere, and thus forth, publicly we can refer to either the default DeviceManager or any custom Device Manager that you have created by the same variable name deviceManager .

Is that correct?

Also, is there anything else I might need to know-about / look-into in order to add audio functionality to a GUI app?

Many thanks.

This is called a reference. If you define the member with the & operator, it will not create an instance. But the difference to a pointer is, that the compiler doesn’t allow this reference to be uninitialised. If you try, it says “Your class needs to initialise the member deviceManager in the constructor”.

After that you can use it like a normal member.
A word of caution though, it doesn’t prevent situations, when the original object is deleted, so accessing the reference after the original was deleted causes the same problems like a dangling pointer.
It is still the preferred way nowadays over raw pointers.

And you can return a reference like

AudioDeviceManager& getAudioDeviceManager()
   return deviceManager;

which grants access to the deviceManager without copying it. And the benefit is, it will always return a valid object.

Extra text here because I deleted this post and tried to post it again and now it won’t let me because the post is “too similar”

Thanks Daniel, so is my understanding of the logic behind it correct?

The AudioAppComponent has a public reference to a deviceManager, that you can use from anywhere.

It is like highlander: there must be only one AudioDeviceManager.
If you have already one constructed, you can hand in the reference in the constructor. If you don’t, the AudioAppComponent will create one.

The public reference will always contain an AudioDeviceManager, either the one you supplied or a new instance.

You the man Daniel.

Btw are you the same guy from the Youtube tutorial series? If you are, thank you doubly! It’s surprisingly effective just to watch another human go through the same problem. You particularly helped me with approaching the documentation, and making it appear less scary.

Since you are on the topic, can someone explain the usefulness of having a defaultDeviceManager in this situation? Why not just instantiate and use deviceManager directly?

When I began with JUCE, I thought this was to facilitate switching audio devices, but that should actually be done using AudioDeviceManager::getAudioDeviceSetup() and AudioDeviceManager::setAudioDeviceSetup() as far as I can tell.