Order of addAudioCallback


#1

Hi all. I have managed to confuse myself regarding the behaviour of addAudioCallback. I have chopped up the JUCE demo code and have 3 audio callbacks in the following snippet. The one in “latencyTester” puts stuff in the output buffer. The other two are modified live audio scopes from the demo that are placed within one component. They are identical and both should show the output. If I register the callbacks in the following order then both scopes show output from latencyTester:

[code]//[Constructor] You can add your own custom stuff here…
latencyTester = new LatencyTester (testResultsBox);
socketServer = new SocketServer(*this);
socketServer->open(true, false);

deviceManager.addAudioCallback (outAudioScopeA);
deviceManager.addAudioCallback (outAudioScopeB);

deviceManager.addAudioCallback (latencyTester);
//[/Constructor][/code]

However, if I flick to another tab to the audio device selector, and then hit the test tone button, and then flick back to the tab containing my scopes, only outAudioScopeA shows the test tone waveform. :expressionless:

If I do it this way round then I see nothing in the scopes whatever …

[code]//[Constructor] You can add your own custom stuff here…
latencyTester = new LatencyTester (testResultsBox);
socketServer = new SocketServer(*this);
socketServer->open(true, false);

deviceManager.addAudioCallback (latencyTester);

deviceManager.addAudioCallback (outAudioScopeA);
deviceManager.addAudioCallback (outAudioScopeB);
//[/Constructor][/code]

The latencyTester callback works whatever order I register the callbacks in.


#2

OK, ok. I think I’m on to something but I still lack clarity. It has something to do with the following code exerpt found at the end of the audio callback in the liveAudioDisplay . .

// We need to clear the output buffers, in case they're full of junk. for (int i = 0; i < numOutputChannels; ++i) if (outputChannelData[i] != 0) zeromem (outputChannelData[i], sizeof (float) * numSamples);

I get different results depending on whether I comment the above code out or not. The strange thing is, the liveAudioDisplay only accesses the data from outputChannelData. Nothing is ever written to it, so why is the above code necessary at all? :shock:


#3

If you have multiple callbacks, they are completely independent, and do NOT have access to each other’s output.

Like it explains in the comments, the output data buffer that you are given initially contains undefined junk, and MUST be overwritten by your device’s output, even if it’s just with zeros. The junk may of course sometimes be data that was written by a previous callback, but that’s just a side-effect, not something you should try to use (!)


#4

Many thanks Jules. This makes me feel a little less insane. Where would I go about accessing the final output stream once the outputs from many callbacks had been summed (in the hypothetical situation that I had many callbacks all independently outputting different stuff)?


#5

The audio device is for playing your finished audio, not for providing any kind of stream mixing service. If you want to mix things, then use a MixerAudioSource or your own custom code to do so.


#6

Jules,

I have some related questions. Here is the code piece:

    deviceManager.addAudioCallback (&audioSourcePlayer);
    audioSourcePlayer.setSource (&mysource); 
    deviceManager.addAudioCallback (&anothercallback);

audioSourcePlayer is an instance of AudioSourcePlayer, mysource is an instance of a derivative class of AudioSource, and anothercallback is an instance of a class implementing AudioIODeviceCallback.

Assuming mysource prepares the output data buffer correctly regardless of input buffer, will that output buffer be sent to the output device (speaker/headphone) directly or the data might go through anothercallback before reaching the output device? If not directly to the output device, what should be done here?
Also, I want anothercallback to receive the input data from microphone directly. Will the input data of anothercallback be independent from the output data buffer of mysource? If not, what should be done here?

Thanks.


#7

All the callbacks are handled completely separately, and won’t be influenced by any other callbacks that happen to be present.