Selecting and enumerating audio devices

Hello everyone!

I’ve been fiddling around in the audio system to try and figure out if there is some way to enumerate all system audio devices and choose the one you want to use.

I haven’t really done audio before though, and there seems to be quite a few API’s in play (as always), especially if you want a cross-platform solution. After looking through the seemingly relevant classes:

AudioDeviceManager.h (Device manager)
AudioDevice.h (Device base class, and all of the platform impl. such as XAudio2Device.h for windows, CoreAudioDevice.h for mac etc.)
ALAudioDevice.h (Cross platform library I suppose)

None of these seem to expose functionality to do what I want however. Is this feature available in some roundabout way that I just haven’t found yet, or is it a feature waiting-to-be?

Best regards,
Temaran

The way it seems to work is that UnrealEngine.cpp loads the AudioDeviceModule based on the config value for AudioDeviceModuleName in the [Audio] section of the Engine.ini file. As you pointed out this is CoreAudio for Mac, AndroidAudio for Android, IOSAudio for IOS, ALAudio for HTML5 and Linux, XAudio2 for Windows.
If the module exsits, UEngine::InitializeAudioDeviceManager() in UnrealEngine.cpp then registers the AudioDeviceModule and calls CreateAudioDevice on the AudioDeviceManager which will eventually call CreateAudioDevice on the AudioDeviceModule after a number of checks.

This is all taken straight from UE soucre code. Since I am not familiar with XAudio2 details/implementation the following may not be correct.
But lets look at XAudio2Device.cpp or more specifically FXAudio2Device::InitializeHardware() anyway. There’s one important section which appears to be what you’re looking for, although not exposed. The section starts with #if XAUDIO_SUPPORTS_DEVICE_DETAILS and first retrieves the DeviceCount using IXAudio2::GetDeviceCount which “returns the number of audio output devices available”. Next it retrieves DeviceDetails for “the default device 0” and uses this for “all audio device instances” (it’s a static member of FXAudioDeviceProperties).

I guess instead of defaulting to 0 you could use a loop that has DeviceCount number of iterations and calls GetDeviceDetails with the loop index. Of course this would require you to customize your Engine. And secondly this would only be for the Windows platform. You could probably do the same for the other platforms as well though.

So to summarize and answer your question: no I don’t think it’s directly exposed and I wouldn’t expect it to be an upcoming feature. Although the UE4 Roadmap does have an entry for “Full Audio System rewrite/refactor” added on 24th of April 2015.

Hello UnrealEverything!

Thank you for your response! :slight_smile: I have also been looking quite a bit at the files in question, and also saw the device ID’s in there. The problems are two-fold however, as you point out it is not exposed from here, and they are completely anonymous. I looked around a bit on the documentation for the windows-APIs on the menu and it seems you can extract the device names using the platform APIs, but alas, it is a bit too much work for now.

As for my hopes regarding a feature-to-be, that was more a musing on that it would make a great pull request if I got some time over to fix it myself, although I suppose I wasn’t very clear there ^^;
The “Full Audio System rewrite/refactor” point is quite interesting though :slight_smile: Missed that one on the roadmap!

My takeaway at least is that you also seem to be in my camp when it comes to whether this is doable without engine modification, and that’s good enough for me :smiley:
Thank you again!

Best regards,
Temaran

Check out the code that lists all the connected devices used in windows project settings.

Check out XAudio2Support.h:

void GetAudioDeviceList(TArray<FString>& OutAudioDeviceList) const

All you need to do is get any audio device…

FAudioDevice* AudioDevice = GEngine->GetMainAudioDevice();

TArray<FString> AudioDeviceList;
AudioDevice->GetAudioDeviceList(AudioDeviceList);

Should do the trick.

If you need more info than name, just grab more data from the API call that gets device info.

I’ve managed to find a solution. You can check out the code

// Get Current Audio Output Name
FString AudioOutName;
if(GEngine)
		AudioOutName= GEngine->GetAudioDeviceManager()->GetAudioMixerDeviceFromWorldContext(GetWorld())->GetAudioMixerPlatform()->GetCurrentDeviceName();

// Get Current Audio Input Name
Audio::FAudioCaptureSynth CaptureSynth;
Audio::FCaptureDeviceInfo DeviceInfo;
CaptureSynth.GetDefaultCaptureDeviceInfo(DeviceInfo);
FString AudioInputName = DeviceInfo.DeviceName;