A Windows filter driver that disables hardware volume control on audio devices.
Brought to you by Etienne Dechamps - GitHub
The goal of WinSoftVol is to stop Windows from using the hardware volume control that most audio devices provide, forcing Windows to use its own software volume control mechanism instead. See also example use cases.
WinSoftVol takes the form of a filter driver that can be inserted on top of any audio device driver. It works by intercepting hardware volume control queries from the Windows audio engine before they make their way to the audio device driver.
This project can also serve as a nice code sample for a trivial, minimalistic Kernel Streaming WDF filter driver.
That's a good question. To be honest, unless you find yourself in one of the example situations described below, it is unlikely you'd want to go through the hassle of deploying WinSoftVol. It is only useful in a very narrow set of scenarios.
Broadly, there are two main reasons why you'd want to use WinSoftVol:
A note about "clipping": this document uses the term "clipping" somewhat liberally. Technically the Windows audio engine never really lets its output "clip" because the final stage goes through a little-known limiting filter known as CAudioLimiter right before conversion to integer. This filter mitigates the worse effects of clipping by redistributing the nasty-sounding harmonics so that they become likely to be masked by the human auditory system. Subjectively, CAudioLimiter appears to be quite effective at making clipping much more difficult to notice. This explains why "clipping" in the Windows audio engine output doesn't really sound like digital clipping at all - though obviously this filter is not magic and one can still tell that the signal level is being limited. To keep things digestible, this document uses the term "clipping" throughout, even though what is really meant is "limited by CAudioLimiter".
To understand how Windows software volume control can be used to prevent digital clipping in specific scenarios, you need to keep in mind the following:
Now at this point you might be wondering where we're going with this. After all, these floating-point samples have to be converted to integer eventually so that a DAC can play them. Integer samples do not have infinite headroom, and neither does the DAC. Out-of-range floating-point samples will therefore clip as soon as they are converted to integer. So what is the point of all this?
The point is to make the volume control smarter by making it attenuate samples before they clip. Let me explain:
Imagine you're using hardware volume control, as would be the case with most Windows audio devices. You're playing content that happens to be quite loud (i.e. low headroom), such as unnormalized popular music. Because it is loud, you lower the Windows volume control to compensate. That volume control is hardware, meaning it attenuates samples after they've been converted to integer and sent to your DAC.
Now, let's also assume that something in the Windows audio engine (e.g. an APO) increases the signal gain on top of that already "loud" content. The resulting floating-point samples are likely to exceed full range. Here's the problem: these out-of-range floating-point samples will stay out of range when the final conversion to integer is taking place and they will clip! Your audio hardware still has plenty of output level headroom available, but that extra headroom sits there unused because of the device's own hardware volume control.
"Okay", I hear you say, "well I'll just add some attenuation to the APO to prevent clipping then, no big deal". Sure, you could do that, but now you have the opposite problem. Let's say you're now playing "quiet" (i.e. high headroom) content, such as most movies or normalized music. The problem is, now the output is too quiet because of the attenuation you just added! Even with the volume control at 100%, the output level is still insufficient.
Now, of course you could just switch the attenuation on and off depending on which type of content you're playing. So, if you're playing "loud" content (with the volume control set low), you enable attenuation to prevent clipping, and if you're playing "quiet" content (with the volume control set high), you disable it to increase output level, knowing that because the content is quiet, it's unlikely to clip.
Obviously it would be quite annoying to have to toggle that attenuation all the time. But what if I told you that could happen automatically and transparently, in such a way as to always exploit the full dynamic range of the system, no matter what type of content you're playing?
This is what Windows software volume control does. When software volume control is used, the master Windows volume control does not act on the hardware. Instead it acts on a volume control APO that Windows automatically inserts inside the Windows audio engine, right before the samples are converted to integer - and therefore, before they clip. In other words, the Windows volume control itself replaces the "anti-clipping" attenuation we've described above.
Here's what happens when you use Windows software volume control:
This is what WinSoftVol allows you to do. It forces Windows to ignore the "dumb" hardware volume control and to use its own "smart" software volume control instead.
If the above example doesn't resonate with you, here are some situations where clipping could be prevented by using software volume control:
Use one of the following techniques to determine if Windows is using software or hardware volume control. This can be used to check the "native" behaviour of an audio device, or to check that WinSoftVol is working as intended.
Use any application that offers a "WASAPI Exclusive" output mode; for example foobar2000 with the WASAPI plug-in.
If the Windows volume control works while playing audio in WASAPI Exclusive mode, you are using hardware volume control. If the volume control does nothing, you are using software volume control.
This is because software volume control operates inside the Windows audio engine, which is completely bypassed when WASAPI Exclusive is used.
Microsoft provides the KsStudio utility which can be used to examine
low-level technical details of Windows audio devices. The utility can be found
in the Windows Driver Kit, in the "Tools" directory, under the name
ksstudio.exe
.
KsStudio might display a number of warning messages and prompts on startup - you can usually ignore all of them.
Use the left hand pane to locate the KS filter factory that corresponds to your device. There might be more than one; you'll have to check all of them.
With a KS filter selected, on the right hand side, you are looking for a
KSNODETYPE_VOLUME
node. For example:
If WinSoftVol is active on the device, then what you will see instead is a
GUID_NULL
node. This is because WinSoftVol does not remove nodes, as that
would disrupt the KS topology and create a mess. Instead, WinSoftVol hides the
volume node by changing its identifier to a dummy "null" identifier, which is
ignored by the Windows audio engine.
Note that depending on the specific device involved, your picture might look
quite different from this example. You might have more than one matching node,
because your audio device might have multiple inputs and outputs. In that case,
figuring out which node (if any) is relevant might be challenging as you will
need to take the topology of the KS filter into account. However, if you see at
least one KSNODETYPE_VOLUME
node, it's probably safe to assume hardware volume
control is being used.
If you can't find a relevant KSNODETYPE_VOLUME
node, then your audio device
is not exposing any hardware volume control.
Using KsStudio you can read and set the value (as in, the actual level) of the
hardware volume control. You can do this even with WinSoftVol enabled (using the
properties below the "hidden" GUID_NULL
node).
The values for the hardware volume control itself are displayed by KsStudio
under "channel (0)" and "channel (1)" in the above screenshot. Interpreting
these values is a bit complicated - these are
signed integers using two's complement, so you will need to take the
hexadecimal value (the part after 0x
in parentheses) and plug it into a
converter. In the above screenshot, the raw value is ffef9966
which
translates to -1074842
. Divide by 65536 to get the value in decibels. In this
case the hardware volume control is set to -16.4 dB, and that value should match
the one in the Windows audio settings (if you are not using WinSoftVol, of
course).
You can change the hardware volume control by clicking on the value. You will need to follow the same conversion rules in reverse. Note that any changes you make will likely not survive a device reset or reboot.
Contrary to typical drivers, WinSoftVol does NOT meet the Microsoft signing requirements for Windows kernel-mode drivers. This is because getting a driver signed by Microsoft is a significant undertaking that requires a non-trivial amount of money.
This is a problem because modern versions of Windows (especially 64-bit, Windows 10+) will simply refuse to load a driver that is not signed by Microsoft. This includes WinSoftVol.
There are two known ways of working around this requirement:
If you still want to proceed after reading the above, then you are extremely motivated, brave, or foolish.
The following steps assume you are operating in Test Signing Mode. You will need to adjust them appropriately if you went for a different approach.
Go to the WinSoftVol releases page and download the appropriate .sys
file
for your system - x86 for 32-bit, x64 for 64-bit. Copy the file to an
appropriate location that the driver will run from (C:\Program Files
is a good
choice).
Windows will not trust the driver's signature by default, even in Test Signing Mode. To make that happen you need to add the driver's certificate to the appropriate store.
Go to the Properties of the .sys
file, Digital Signatures tab, Details,
View Certificate, Install Certificate…, Local Machine, Next, Place all
certificates in the following store, select the Trusted Root Certification
Authorities store, Next, and Finish.
Close the file properties and open them again. If you go to the certificate details again, Windows should now show the certificate as valid.
Windows drivers run as kernel-mode services that are managed by the Service
Control Manager, similar to the typical Windows services you might be used
to. They are not shown in the Services control panel though, so we need to use
the Windows built-in sc.exe
command line tool to manage them.
Run the following on the Windows command line:
sc.exe create WinSoftVol "binPath=c:\YOUR\PATH\TO\WinSoftVol_x64_SelfSigned.sys" type=kernel
This step is not strictly necessary as the Windows Device Manager (specifically, PNP) will start the service automatically as needed. However this is an easy way to determine if Windows is happy to load the driver:
sc.exe start WinSoftVol
The command should return a STATE
of RUNNING
. If it returns an error,
something is wrong and you need to retrace your steps. The most likely causes
are:
binPath
in the previous step is incorrect.
sc.exe delete WinSoftVol
and try again..sys
file (e.g. x86
instead of x64
).Go to the Sound control panel (the old Windows Vista/7 one, not the new one), then go to the Properties of the output device you are interested in. Go to Properties under Controller Information, then Details tab, Device instance path.
Make a note of that path; you will need it later. Right-click to copy it to the clipboard.
Note: WinSoftVol operates at the adapter device level; it will disable hardware volume control on all endpoints (i.e. inputs and outputs) that are present on the selected device.
Note: before you proceed any further, you might want to set your device's (currently hardware) volume control to 100%. Otherwise it might remember its current value and you won't be able to easily change it later.
In the Registry Editor, navigate to:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\<YOUR DEVICE INSTANCE PATH>
Add a new Multi-String Value called UpperFilters
with a single line:
WinSoftVol
.
Note: in the (unlikely) event there is already an UpperFilters
value, just
append WinSoftVol
to it on a separate line.
Note: after this step, if you are somehow running into trouble and your device appears to be corrupted or nonfunctional, go to the Device Manager, Uninstall the device and then use Scan for hardware changes in the Actions menu to reinstate it. This will reset the registry settings for this device.
If you wish, you can have Windows automatically attach WinSoftVol to all audio devices on the system, present and future. This effectively means hardware volume control will be disabled on all your devices.
One benefit of this approach is that WinSoftVol will survive audio device driver updates.
To do this, instead of adding the UpperFilters
value in the device-specific
registry key, add it in the MEDIA
device class registry key instead, which is
located here:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4d36e96c-e325-11ce-bfc1-08002be10318}
CAUTION: if you mess things up in this registry key, there is no going back. Make a backup of the key (File, Export…) before you proceed.
You will likely find there is already a UpperFilters
value defined there,
containing the line ksthunk
. Do NOT remove existing lines. Instead, add
WinSoftVol on a separate line before or after them. The order doesn't really
seem to matter.
A change to this registry key takes effect on individual devices as they are restarted (see next step), or the system is rebooted.
In order for Windows (PNP) to pick up the change you just made in the registry, the device needs to be restarted. Use the Windows built-in PnPUtil command line utility to do that:
pnputil.exe /restart-device "<YOUR DEVICE INSTANCE ID>"
This step is not always necessary, but it appears the Windows audio engine sometimes gets a bit confused if the properties of an audio device are changing right from under it.
Go to Windows Services and restart the Windows Audio (audiosrv
) service.
That's it! Windows should now be using software volume control with your device. Follow the instructions above to confirm this.
If it doesn't appear to work, or if your audio device has been rendered inoperable, follow the troubleshooting section below.
If you want to use WinSoftVol on more than one device (and you didn't use the class-wide method) simply resume from step 6.
Note: unless you used the class-wide method in step 6, WinSoftVol will not survive driver updates. If you update the audio device driver you will need to resume from step 6 to get WinSoftVol back.
To detach WinSoftVol from an audio device, revert the registry change you made in step 6 above, then continue with steps 7 and 8.
To completely remove WinSoftVol from the system, detach it from all active audio devices first, then delete the service:
sc.exe delete WinSoftVol
If this command fails, it likely means WinSoftVol is still in use on at least one device.
You can then delete the .sys
file. You might also want to remove the driver
certificate from the Windows Certificate Store.
If the Device Manager reports an error with the device, you might want to double check that WinSoftVol can load.
If WinSoftVol does load, verify that Windows does see it as an upper filter driver for the device:
(If you used the class-wide approach, you will find it under Class upper filters instead.)
You can also check kernel messages logged by the driver using DebugView. Make sure the Capture Kernel and Enable Verbose Kernel Output options are enabled. A healthy output will look like this after a restart of the device:
You might also want to look at the device using KsStudio.
If none of this helps, you might want to file an issue and ask for help.
Many thanks to Windows driver specialists Tim Roberts and Doron Holan who provided great assistance while I was struggling to understand the strange behaviour of Kernel Streaming requests.