Skip to content

Latest commit

 

History

History
126 lines (90 loc) · 4.57 KB

EnumerateOutputDevices.md

File metadata and controls

126 lines (90 loc) · 4.57 KB

Enumerating Audio Devices

The technique you use to enumerate audio devices depends on what audio output (or input) driver type you are using. This article shows the technique for each supported output device.

WaveOut or WaveOutEvent

To discover the number of output devices you can use WaveOut.DeviceCount. Then you can call WaveOut.GetCapabilities passing in the index of a device to find out its name (and some basic information about its capabilities).

Note that you can also pass an index of -1 which is the "audio mapper". Use this if you want to keep playing audio even when a device is removed (such as USB headphones being unplugged).

Also note that the ProductName retured is limited to 32 characters, resulting in it often being truncated. This is a limitation of the underlying Windows API and there is unfortunately no easy way to fix it in NAudio.

for (int n = -1; n < WaveOut.DeviceCount; n++)
{
    var caps = WaveOut.GetCapabilities(n);
    Console.WriteLine($"{n}: {caps.ProductName}");
}

Once you've selected the device you want, you can open it by creating an instance of WaveOut or WaveOutEvent and specifying it as the DeviceNumber:

var outputDevice = new WaveOutEvent() { DeviceNumber = deviceNumber };

WaveIn or WaveInEvent

Getting details of audio capture devices for WaveIn is very similar to for WaveOut:

for (int n = -1; n < WaveIn.DeviceCount; n++)
{
    var caps = WaveIn.GetCapabilities(n);
    Console.WriteLine($"{n}: {caps.ProductName}");
}

Once you've selected the device you want, you can open it by creating an instance of WaveIn or WaveInEvent and specifying it as the DeviceNumber:

var recordingDevice = new WaveInEvent() { DeviceNumber = deviceNumber };

DirectSoundOut

DirectSoundOut exposes the Devices static method allowing you to enumerate through all the output devices. This has the benefit over WaveOut of not having truncated device names:

foreach (var dev in DirectSoundOut.Devices)
{
    Console.WriteLine($"{dev.Guid} {dev.ModuleName} {dev.Description}");
}

Each device has a Guid, and that can be used to open a specific device:

var outputDevice = new DirectSoundOut(deviceGuid);

There are also a couple of special device GUIDs you can use to open the default playback device (DirectSoundOut.DSDEVID_DefaultPlayback) or default voice playback device (DirectSoundOut.DSDEVID_DefaultVoicePlayback)

WASAPI Devices

WASAPI playback (render) and recording (capture) devices can both be accessed via the MMDeviceEnumerator class. This allows you to enumerate only the type of devices you want (DataFlow.Render or DataFlow.Capture or DataFlow.All).

You can also choose whether you want to include devices that are active, or also include disabled, unplugged or otherwise not present devices with the DeviceState bitmask. Here we show them all:

var enumerator = new MMDeviceEnumerator();
foreach (var wasapi in enumerator.EnumerateAudioEndPoints(DataFlow.All, DeviceState.All))
{
    Console.WriteLine($"{wasapi.DataFlow} {wasapi.FriendlyName} {wasapi.DeviceFriendlyName} {wasapi.State}");
}

To open the device you want, simply pass the device in to the appropriate WASAPI class depending on if you are playing back or recording...

var outputDevice = new WasapiOut(mmDevice, ...);
var recordingDevice = new WasapiIn(captureDevice, ...);
var loopbackCapture = new WasapiLoopbackCapture(loopbackDevice);

You can also use the MMEnumerator to request what the default device is for a number of different scenarios (playback or record, and voice, multimedia or 'console'):

enumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);

ASIO

You can discover the registered ASIO drivers on your system with AsioOut.GetDriverNames. There is no guarantee that the associated soundcard is currently connected to the system.

foreach (var asio in AsioOut.GetDriverNames())
{
    Console.WriteLine(asio);
}

You can then use the driver name to open the device:

new AsioOut(driverName);

Management Objects

Finally you can use Windows Management Objects to get hold of details of the sound devices installed. This doesn't map specifically to any of the NAudio output device types, but can be a source of useful information

var objSearcher = new ManagementObjectSearcher(
	   "SELECT * FROM Win32_SoundDevice");

var objCollection = objSearcher.Get();
foreach (var d in objCollection)
{
    Console.WriteLine("=====DEVICE====");
    foreach (var p in d.Properties)
    {
        Console.WriteLine($"{p.Name}:{p.Value}");
    }
}