Programmatically switch between audio devices in Windows

Recent versions of Windows offer simple ways to change your default audio devices to play or record sounds. In the case of Windows 10, that option is conveniently located in the task bar. But what if you want to automatically change the audio device?

Manage your audio devices from PowerShell with AudioDeviceCmdlets

AudioDeviceCmdlets is a module available in the “Powershell Gallery” website and it also has a GitHub repo. To install it run the following command:

Install-Module -Name AudioDeviceCmdlets

If you never installed something from PowerShell Gallery, you will see the “Untrusted repository” warning. Once it is installed, we get some useful commands to work with our audio devices:

Cmdlets available in the AudioDeviceCmdlets

In this case, we are going to use the ones with the set and get verbs. Let us run Get-AudioDevice to see what this module can do (you are supposed to pass a parameter to the cmdlet for it to work, so we used -List):

Get-AudioDevice cmdlent output

If we check what this cmdlet returns, GetType() method can provide us with that info:

Checking the type returned by Get-AudioDevice cmdlet

This is a great starting point to manipulate our audio devices. We have a way to identify them, now we need a way to change them. Set-AudioDevice is going to help us with that task. Let us check how we can change between audio devices.

To start working with audio devices, we need to define if we want to work with all the audio devices available, some devices specific devices or a category of them. By looking at the result of Get-AudioDevices we can see that we can easily identify a single device with an ID or target a category of them.  If you want to target a specific device, look for the ID property. In this case, I want to target my devices by type:

$playbackDevices = Get-AudioDevice -List | Where-Object {$_.Type -eq "Playback"}

Since we need at least two devices to be able to change between them, we need to validate that first:

if($playbackDevices.Count -gt 1) {}

The next thing is to check the index of the default device. In this context, default refers to the device that the OS will use primarily to play or record sound. If we have three audio devices, A, B and C, and A is the default device, we want to switch between B and C. The following instruction is going to return the default playback device currently being used:

$currentDefaultDevice = Get-AudioDevice -List | Where-Object {($_.Default -eq $true) -and ($_.Type -eq "Playback")}

Then, using a loop we can find and remove the index of the object that points to the default device. An easy way to that is to use an array list, that allow us to use the .Remove() method:

[System.Collections.ArrayList] $playbackDevicesIndex = $playbackDevices.Index
$currentDefaultDevice = Get-AudioDevice -List | Where-Object {($_.Default -eq $true) -and ($_.Type -eq "Playback")}

for ($i = 0; $i -lt $playbackDevicesIndex.Count; $i++) {
     if ($playbackDevicesIndex[$i] -eq $currentDefaultDevice.Index) {
          $playbackDevicesIndex.Remove($playbackDevicesIndex[$i])
     }
}

The for is iterating over $playbackDevicesIndex, an array list, and it is checking if the index is the same as the one for the default device. If that is true, .Remove() will delete that element from the array. That will leave us with an array that contains only the audio devices that we can switch to.

In the end, we just tell PS we want to switch between the elements of $playbackDevicesIndex. To do that, we can simply use a negative value like -1 or -2. If we do that, we are telling PS to look backwards for the element we want. But since we want to switch to different index each time, we need to include a dynamic value to calculate the right element in the array. For that, we can use the index of the current default device and then subtract 2:

Set-AudioDevice -Index $playbackDevicesIndex[$($currentDefaultDevice.Index)-2]

The full script looks like this:

$playbackDevices = Get-AudioDevice -List | Where-Object {$_.Type -eq "Playback"}

if($playbackDevices.Count -gt 1){
    [System.Collections.ArrayList] $playbackDevicesIndex = $playbackDevices.Index
    $currentDefaultDevice = Get-AudioDevice -List | Where-Object {($_.Default -eq $true) -and ($_.Type -eq "Playback")}

    for ($i = 0; $i -lt $playbackDevicesIndex.Count; $i++) {
        if ($playbackDevicesIndex[$i] -eq $currentDefaultDevice.Index) {
            $playbackDevicesIndex.Remove($playbackDevicesIndex[$i])
        }
    }

    Set-AudioDevice -Index $playbackDevicesIndex[$($currentDefaultDevice.Index)-2]
 
}

You can play with the different options to switch between different devices or to always switch from one device to the other.

| Theme: UPortfolio