In my app, I want to let the user choose one of the available audio output devices (which can be multichannel, like the Fireface 400). Once they select an audio device, I would like to give them further choices, specific to the device, for mapping available input and output channels to my application’s functions.
However, when I enumerate device types and then device names, I get completely unexpected results. It seems that Juce is treating individual channel pairs as their own device? This is what I get from Juce:
[code]int id = 1;
for (int i = 0; i < m_adm.getAvailableDeviceTypes().size(); ++i)
{
const AudioIODeviceType* t = m_adm.getAvailableDeviceTypes()[i];
const StringArray deviceNames = t->getDeviceNames ();
I think that the IMMDeviceCollection implies that the result is a “collection” of channels and not individual devices.
Should I dig into the WASAPI implementation and see what happens if I change it to treat the IMMDeviceCollection as a set of channels instead of individual devices?
I get the feeling that there aren’t too many people out there using Juce and WASAPI to do multichannel output…has anyone else worked with the WASAPI output and encountered this? I mean, its fine for a single stereo channel output but it seems to be not possible to configure Juce to support more than one stereo channel pair with WASAPI.
Gah, it looks like I’m the guinea pig. I’m pretty confident that the IMMDeviceCollection interface is just a poorly named identifier for the list of channels. Along with other stupidly named identifiers (thanks Microsoft). I know this because…well, certain other commercial applications which shall not be named, treat it as such. They correctly list the available channels as a list instead of as different devices.
I will dig into it myself and attempt to re-write the affected portions of juce_win32_WASAPI.cpp
Okay, it seems that the AudioDeviceManager assumes that you have already called setCurrentAudioDeviceType to choose a type.
For example if you call initialise() and pass in a preferred default device name, and the current audio device type doesn’t match that device, the subsequent call to setAudioDeviceSetup() will fail, because the current type doesn’t have a device with that name.
It almost seems like the AudioDeviceSetup is missing a field “String audioDeviceType”. Actually I’m pretty confident of this because initialise() has this code to restore from Xml:
Without this line the call to setAudioDeviceSetup() can fail.
The “else” statement in initialise has no equivalent code - it assumes you have set the device type ahead of time. It is impossible to fully describe the current audio setup from the AudioDeviceSetup structure alone.
If this is BS please by all means call me out on it
Well, the intention with AudioDeviceSetup isn’t really to provide a class that you can use to store the state of the device manager (that’s what the XML is for). AudioDeviceSetup is just a temporary object - if you want to tweak a device setting, you’d call getAudioDeviceSetup(), mess with a couple of settings, and then apply them with setAudioDeviceSetup().
Yes and yes. However, what I am saying is that AudioDeviceSetup is missing the deviceTypeName field - it is not possible to fully describe the state of the audio hardware without this field. The only way to switch to a different device is to first call setCurrentAudioDeviceType and then call setAudioDeviceSetup.
It would be very convenient if AudioDeviceSetup had a field for deviceTypeName.
Take for example the situation when you call initialise() with preferredDefaultDeviceName set to the name of a valid device, but one that is from a deviceType different than the current one (which will simply be the first one with a freshly created manager), and the default device for the current type cannot be opened - for example, if another application is running that grabbed it exclusively.
When initialise() fails to get the exclusive device, it eventually calls setAudioDeviceSetup() with the preferredDefaultDeviceName, but that fails because the current device type is merely the first one in the list, not the type corresponding to the chosen preferredDefaultDeviceName.
In order to have initialise() work properly one would have to call setCurrentDeviceType() before initialise(), which is a bit of a hack.
I’ve got the same symptom: RME fireface showing up as a series of stereo devices instead of one multichannel device. Not having burrowed into this any further it’s difficult to follow your discussion. Did you find a solution, and did it involve changes in juce?
Yes I have the solution, the windows implementation needs to be changed. I am offering cash money for anyone who is knowledgable in these windows APIs to fix it.
I tracked it down to a specific GUID that can be used to identify when the different channels really belong to the same device. Check out this post:
Tangentially related - I’ve noticed that Juce DeviceManager seems to think many laptops audio systems (Win 7 this is) don’t have any common sample rates for inputs and outputs (meaning the Device Manager reports that the input is at a different sampling rate than the output).
This is of course not the case. I have verified that this seems to happen on a number of windows 7 laptops (using the JuceDemo or my own programs).
Please, someone take Vinn up on that cash money offer! It would be great to get it cleared up.