Hi!
I’m working on an application that uses the engine through HostedAudioDeviceInterface
and I’m experiencing some performance issues when a larger number of channels (up to 128) is used.
Most of the time is spent in DeviceManager::rebuildWaveDeviceList
(see callstack below) and calling
WaveInputDevice::setStereoPair
on all inputs can take up to 3-4 seconds even in a release build.
Function Name Total CPU [unit, %] Self CPU [unit, %]
| + Application::initialise 82480 (55.30%) 0 (0.00%)
|| + juce::AudioSourcePlayer::setSource 80820 (54.18%) 0 (0.00%)
||| + Application::prepareToPlay 80820 (54.18%) 0 (0.00%)
|||| + lama::EngineWrapper::prepareToPlay 80820 (54.18%) 1 (0.00%)
||||| + tracktion::engine::HostedAudioDeviceInterface::initialise 55002 (36.87%) 0 (0.00%)
|||||| + tracktion::engine::WaveInputDevice::setStereoPair 54874 (36.79%) 0 (0.00%)
||||||| + tracktion::engine::DeviceManager::setDeviceInChannelStereo 54874 (36.79%) 0 (0.00%)
|||||||| - tracktion::engine::DeviceManager::rebuildWaveDeviceList 54874 (36.79%) 32 (0.02%) // [1]
|||||| - tracktion::engine::DeviceManager::initialise 127 (0.09%) 0 (0.00%)
|||||| + juce::AudioDeviceManager::setCurrentAudioDeviceType 1 (0.00%) 0 (0.00%)
||||||| - juce::AudioDeviceManager::setAudioDeviceSetup 1 (0.00%) 1 (0.00%)
A workaround I tried
Deferring the rebuild so it happens only once (after HostedAudioDevice::initialise()
, before
HostedAudioDevice::prepareToPlay()
) seems to help with the performance issue, and so far it does not seem to break
anything.
This required two changes. One in the engine to bypass the device list rebuild and and one in my application to call it
once the engine is initialized:
diff --git a/Source/Engine.cpp b/Source/Engine.cpp
index cfdcca9..e485e69 100644
@@ -1325,6 +1325,8 @@ void EngineWrapper::prepareToPlay(const te::HostedAudioDeviceInterface::Parameters)
waveInputDevice->setStereoPair(true);
}
}
+ engine_.getDeviceManager().rebuildWaveDeviceListIfNeeded();
hostedAudioDeviceInterface_.prepareToPlay(parameters.sampleRate, parameters.blockSize);
}
Submodule tracktion_engine contains modified content
diff --git a/tracktion_engine/modules/tracktion_engine/playback/tracktion_DeviceManager.cpp b/tracktion_engine/modules/tracktion_engine/playback/tracktion_DeviceManager>index b64e85eb99..eec4800de9 100644
@@ -923,7 +923,7 @@ void DeviceManager::setDeviceInChannelStereo (int chan, bool isStereoPair)
}
}
- rebuildWaveDeviceList();
+ // rebuildWaveDeviceList();
}
Questions
- Would an optimization like this make sense or is it necessary to rebuild the device list every time?
- If this can work, is there a chance that the engine could handle this, without the application having to trigger the rebuild?
- If that cannot work for any reason, is there anything else I could do to work around the issue?
- Am I using
HostedAudioDeviceInterface::initialise
correctly? the EngineInPlugin example only calls it once, but it takes parameters that might change after that, so I think I do need to call it inprepareToPlay
Thanks,
Daniel