Enumerating Audio Devices

September 9, 2026 · View on GitHub

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. On Windows, start with the WASAPI section — WasapiPlayer and WasapiRecorder are the recommended playback and capture devices, and MMDeviceEnumerator is how you discover the endpoints they use.

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}");
}

Unlike the WinMM device names below, these names are not truncated.

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

var outputDevice = new WasapiPlayerBuilder().WithDevice(mmDevice).Build();
var recordingDevice = new WasapiRecorderBuilder().WithDevice(captureDevice).Build();
var loopbackCapture = new WasapiRecorderBuilder().WithDevice(loopbackDevice).WithLoopbackCapture().Build();

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);

If you just want the default device, you don't need to enumerate at all — building a WasapiPlayer or WasapiRecorder with no WithDevice call uses the system default. See WasapiPlayer and WasapiRecorder.

ASIO

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

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

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

using var device = AsioDevice.Open(driverName);

(AsioDevice is the NAudio 3 ASIO API. The legacy AsioOut class still works — see Migrating from AsioOut to AsioDevice.)

WaveOut

WaveOut wraps the legacy WinMM APIs. Prefer WASAPI for new code, but the enumeration API is here if you need it.

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 and specifying it as the DeviceNumber:

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

WaveIn

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 and specifying it as the DeviceNumber:

var recordingDevice = new WaveIn() { 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)

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}");
    }
}