I’m looking to improve the stability and performance of my audio callback. I’ve been doing some stress testing and I have 2 test configurations both with 30 tracks. The first is just straight file playback, the second includes 3 audio units per track.
I had been using an AudioProcessorGraph but for the sake of simplicity/testing I pulled together the essential processors for each track and placed them into respective “EngineTrack” objects.
[list]
[]The first processor on each track handles file reading. Each uses an AudioTransportSource and I’ve set the readAhead to 32768.[/]
[]There are 3 audio files used. There are 10 tracks per audio file.[/]
[]The audio units are plugins from MeldaProduction: MTuner, MEqualizer and MCompressor.[/]
[]The device is running 64 samples at 44100.[/]
[/list]
The callback:
[code] for (int i = 0; i < numOutputChannels; ++i)
if (outputChannelData[i] != 0)
zeromem (outputChannelData[i], sizeof (float) * numSamples);
if (isPlaying) {
for (int i = 0; i < enTrackSize; i++) {
EngineTrack * t = enTracks.getUnchecked(i);
for (int j = 0; j < t->plugSize; j++) {
AudioPluginInstance * inst = t->plugs.getUnchecked(j);
inst->processBlock(t->buff, t->midiBuff);
}
this->mixBuffs(t->buff, outputChannelData, numOutputChannels, numSamples);
}
this->trackPosition += numSamples * playbackSpeed;
}
[/code]
With just file playback, performance seems pretty good. Between 10 and 20% cpu usage (as per getCpuUsage()). Glitches do occur from time to time but I’m not sure what causes them. The buffering of the files seems to be healthy throughout playback. It seems that window resizing can encourage glitches, but not all the time.
When testing with the audio units added, the performance is terrible. Cpu usage is at 80-100% and the audio output is useless. To compare, I set up Logic using the same configuration and it happily chugs away. The cpu meter on it runs hot but it doesn’t seem to affect the output in any way. Of course I can only imagine what magic they are doing. I’ve profiled both my app and Logic and most of the time is spent in the audio units, particularly the compressor appears to take up most of the time. Not surprising as there isn’t really anything happening in the callback other than reading from the file buffers.
So with that said, I’m left scratching my head a bit. The callback is really basic and most of the time is taken up in the audio units. I can only guess that the load of the audio units needs to be spead out somehow, possibly using multiple threads. I’m imagining using 1 thread per track where the callback would signal to the tracks to process the incoming data, and then it would wait for the tracks to finish. Is that a rediculous concept? Would there be any parallel benefit? I’m not sure how else to look at it, so that’s why I’m reaching out and hoping someone might have some guidance to share. I’ve been following Vinn’s thread on lock free queues and lately I’ve been reading up on real time processing topics. Specifically Ross Bencina’s http://www.rossbencina.com/code/real-time-audio-programming-101-time-waits-for-nothing blog posting on real time processing and chapter on SuperCollider’s internals. Very interesting stuff, but I’m not sure how it would apply here.
Anyway, any thoughts are greatly appreciated!
thanks.