Automatic Sample Rate Conversion with WASAPI
14 years ago(!) I blogged about the (at the time) new WASAPI audio playback API introduced with Windows Vista and complained that WASAPI was missing the crucial feature of automatic sample rate conversion. In other words, if your soundcard was operating at 44.1kHz and you wanted to play a 16kHz audio file, it wouldn't let you. You were forced to resample it yourself.
Likewise if you wanted to record audio, you were forced to receive audio in the format used by the device, which was annoying if you were say recording a mono source like a USB microphone, but were forced to deal with stereo samples.
NAudio tried to help you round this by automatically creating an instance of ResamplerDmoStream
that attempted to convert your audio into a suitable playback format. The main downside of this is that ResamplerDmoStream
introduces some additional latency to your playback. It also required an ugly hack where we made the resampler on one thread to check it worked, but had to make it again on the playback thread due to not being able to use the same COM object across threads.
The good news is that at some point in the last 14 years, the AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM flag was added, instructing WASAPI to handle the sample rate conversion itself.
I tried this out and it works really well. In NAudio, with WasapiOut
, it will simply use the built in sample rate conversion, meaning playback should be faster and more responsive. And with WasapiCapture
, you will finally be able to pick the format you want - so if you'd like to capture 16kHz mono audio, you can do that.
The one caveat is that exclusive mode playback (as opposed to "shared mode" which is the default) doesn't support sample rate conversion, which makes sense. You're using exclusive mode because you want the fastest and most direct route and you're willing to provide audio in the right format. NAudio actually will still insert the ResamplerDmoStream
for you in this scenario, but I'm considering removing that and providing some bit depth conversion helpers that let you work with exclusive mode but require you to provide audio at the correct sample rate.
If you'd like to try out this new capability, it's currently in the 2.1.0-beta.1 release of NAudio. That's because I've also been experimenting a bit with the target frameworks used by the packages to try to resolve some pain point about .NET 6 apps needing to specify net6.0-windows
even if you had no plans to use the Windows-specific parts of NAudio. I need to do some more testing before it goes live.
But in summary, it's great that we finally have this feature that I think should have been in WASAPI from day one. It means that WasapiOut
and WasapiCapture
can finally be the primary recommended way of playing and recording audio with NAudio on Windows, and the older WaveOut
, WaveOutEvent
, WaveIn
and WaveInEvent
classes that use the legacy Windows audio APIs are now effectively obsoleted by this change.