Using the second pair of outputs on your audio device


#1

I’m working on an application where you can have two stereo-audio outputs… I’ve managed to create my own semi-audiodevicemanager, that actually uses two audiodevicemanagers. This lets you select the outputs on one or two devices. Using a multi-out device (Native Instruments Audio Kontrol 1), when I try to use only the second pair of outputs on the device, there is no error when calling AudioDeviceManager::setAudioDevice, but there’s no output as well… I’ve checked this against the audio demo of the juce-demo, but this displays the same behavior… The audio interface is not to blame: reason works fine with only the second pair active. Maybe the problem lies in the fact that I use an AudioSourcePlayer as an AudioCallback… maybe it’s not suited for handling anything but the first pair of outputs?
There also is something called AudioDeviceManger::setOutputChannels, but this doesn’t seem to do the trick as well…


#2

The audio device manager lets you choose any set of channels to use, so you don’t need to use any crazy tricks like that. It does work, I use it all the time.


#3

Crazy tricks? What exactly do you mean?

The AudioDeviceManager is designed to handle only one audio device at a time, right? So for me it seems that if I wanted to use two devices I would need two audiodevicemanagers… This actually works fine.
When I try to select outputs 3 & 4 (from 4 available), there is no audio output , although I can see that callback are being made.

I think I should have mentioned that I only have the problem in OS X, when I’m running windows the two channel-groups are listed as seperate devices. ASIO also does exactly what it’s supposed to do…so maybe it’s just some CoreAudio thingy?

It might as well be the device’s fault, I haven’t got other hardware… Propellerhead’s Reason seems to run just fine on output 3 & 4 (CoreAudio) though…


#4

One audio device can have more than two channels… You just need one device manager, and open a device using all 4 channels. Or I’m completely misunderstanding you…


#5

Yes I think so… The application calls for a stereo master output and a stereo monitoring output. If your soundcard doesn’t have 4 channels, you can use a second audiodevice. Using two audiodevicemanagers to open the two devices, this works great.

The problem lies in when i’m using a 4-output device for the master and monitor output. I can’t get the second pair of outputs to turn on (even when using only one device manager, even when using the audio-demo provided with juce), but, as previously mentioned, only in os x…

To avoid letting the audiodevicemanagers use the same audiodevice (which doens’t work offcourse) when the master and monitor output to the same device,
I’ve created a audiocallback that routes the monitor and master channels to the appropriate channels on that device.


#6

To further explain myself:

When I’m using the jucedemo/audio and I select outputs 3/4, I hear nothing.
The file is playing though, it stops after a certain amount of time.
This problem only manifests itself under OS/X.


#7

I think you’ll hit problems if you try to use ASIO for both devices - it was only designed to cope with one device at a time.

I’ll take a look at the coreaudio thing, though it seems a bit unlikely that nobody else would have hit a problem with that before.


#8

True that, that seems very unlikely indeed…
It could just be a very device-specific problem… it’s a shame I dont have access to another multiple-out device on a mac.
For the ASIO thing, I could always disable the choosing of a second ASIO device… it a pity though…


#9

I’ve managed to create an aggregate device (using the Audio Midi Setup on os x) from the built-in output on my mac and an M-Audio Ozone, thus having a other device with 4 outputs. The same problem then occurs again in the audio-demo. but not in other audio-applications


#10

One more thing: I read somewhere about the amount of channels given when audioDeviceIOCallback is called. It seemed that you can have more numTotalOutputChannels than are actually active at that point, but you can check if the pointers where outPutChannelData[x] point to are valid…

Is it then true that:

  • numTotalOutputs could be less than the the index of the output that is active? (eg: outputs 3&4 active, numTotalOutputs = 2)

  • audiocallbacks always get the audio for all the active channels in one go? (eg: outputs 1&2&3&4 active, numTotalOutputs = 4 or more)


#11

No, I don’t think numTotalOutputs could be less than the index, and yes, the callback always gets all the channels. I need to revisit the channel ordering in these devices, and maybe alter the API, as there’s really not much point in leaving some channels null.


#12

Okay, it turns out the only way to get the extra channels to work is to initialise the audiodevicemanagers with a large enough number of channels (like 256). This really is a stupid mistake, but I must point out that the juce-audio demo doesn’t do this as well.

Then with red cheecks of shame, I went on trying to get it all to work like I intended. In Windows, the audiocallback I’ve made recieves 4 totalNumChannels, and the array to write the audio to contains 2 valid pointers. But, when I select another device, the valid pointers change location in the array:

Primary device: valid-valid-invalid-invalid
Realtek (same device): invalid-invaid-valid-valid

Ofcourse I use AudioDeviceManger::getOutputChannelNames and AudioIODevice::getOutputChannels to figure out what channels are active, but there seems to be no way of telling which array corresponds to which outputchannel…

Am I missing something here?


#13

I need to spend some time looking at the code for this.

The fact that you can’t understand it, and that I can’t remember all the details about how it works is a good indicator that it’s not a very good interface, and probably needs refactoring to make it more usable.


#14

[quote=“tim_is_tof”]In Windows, the audiocallback I’ve made recieves 4 totalNumChannels, and the array to write the audio to contains 2 valid pointers. But, when I select another device, the valid pointers change location in the array:

Primary device: valid-valid-invalid-invalid
Realtek (same device): invalid-invaid-valid-valid

Ofcourse I use AudioDeviceManger::getOutputChannelNames and AudioIODevice::getOutputChannels to figure out what channels are active, but there seems to be no way of telling which array corresponds to which outputchannel…

Am I missing something here?[/quote]

That seems to be exactly the problem I had, check this out: http://www.rawmaterialsoftware.com/juceforum/viewtopic.php?t=2839

On my system, this issue only occurs when using DirectSound, whereas ASIO always works like the JUCE docs specify. Is this true on your system, too? (If you don’t have ASIO drivers, you can always download ASIO4ALL).


#15

Yes I believe this is quite the same problem it occurs with me on ASIO drivers as well. I actually have a workaround for it now, but it’s really a big hack. I keep a couple of indexes to where the channel data needs to go. i do this:

while(index <numTotalOutputChannels && outputChannelData[index] = 0)
index++;

//then fill the outputarray like this:

if(outputChannelData[index] != 0)
for(int i=0;i<numSamples;i++)
outputChannelData[index][i] = left[i];

This seems to work fine, but it might be less suitable for dealing with lots of channels (there’s no guarantee that they don’t end up in the same channelbuffer)


#16

Oh boy, if this also happens with ASIO drivers then I have a big problem, cause my app is multichannel…


#17

Oops, It looks like i’m a big lyer, when using my 4 out ASIO card, I get numTotalOutputChannels = 4, all channels are active… Sorry


#18

Ok, so the problem only occurs with DirectSound, right?


#19

As far as i’ve tested this with types of drivers and different cards, yes.
The hack I described would then work all the time, because direct sound drivers offer only a stereo output per “device”.