Posted in:

When I originally created NAudio in 2002, it was on the old .NET Framework which was Windows-only. The whole NAudio library was a single package, containing all the capabilities. Over time, I gradually split things out, trying to separate the "cross-platform" parts of NAudio, such as the core interfaces, WAV and MIDI file readers and writers, and fully managed DSP (e.g. FFT, WdlResampler), from things that were truly Windows-specific (such as WASAPI, Media Foundation etc.).

With the recent release of NAudio 3, I tried to tidy things up further, making the NAudio.Core package exclusively cross-platform, while packages like NAudio.Wasapi and NAudio.WinMM contain Windows-only features. I initially targeted those with Windows-specific TFMs (e.g. net9.0-windows), to indicate that they were Windows-specific. (Note that the reason .NET 9 is the base is that .NET 8 had a ComWrappers finalizer bug, so I decided 9 should be the minimum supported runtime going forwards).

NAudio also has a "meta-package", which is the top-level NAudio NuGet package, and adds a few convenience helpers such as AudioFileReader and Mp3FileReader, which are still (for historical reasons) Windows-specific. So that top-level package was multi-targeted to net9.0-windows which included everything, and net9.0 for just the cross-platform capabilities.

NAudio 3 also introduced several additional packages including NAudio.Alsa for Linux playback support, as well as the cross-platform NAudio.SoundFile, and also now has a preview NAudio.MacOS. These are not part of the "meta-package" which makes life much simpler - users can simply reference them if they are relevant.

However, multi-targeting the meta-package ended up causing some problems. First of all, I initially was targeting net9.0-windows10.0.19041.0, which was necessary for the WinRT MIDI capabilities. This ended up meaning that consumers of NAudio who targeted netX.0-windows and referenced the meta-package didn't get any Windows features at all, as that is interpreted by NuGet as Windows 7.

To resolve that issue, I went to simply net9.0-windows, but that still trips some people up. For example, if you build a console app and target netX.0 and reference the NAudio meta-package, you won't get any of the Windows-specific types (such as AudioFileReader). The fix is simple (target netX.0-windows) but it does confuse some users, so I've decided to revisit this decision for NAudio 3.3.0.

After a bit of research into how other projects handle this problem, it seems best to express Windows-only with [SupportedOSPlatform] rather than the TFM (target framework moniker). Of course, some NAudio packages such as NAudio.WinForms genuinely do still need to target netX.0-windows.

So from NAudio 3.3.0 onwards, the NAudio meta-package will have a single net9.0 TFM, and reference NAudio.Core, NAudio.Midi, NAudio.WinMM and NAudio.Wasapi. This provides access to the core features of NAudio, and supports AudioFileReader and Mp3FileReader (which still only work on Windows), but requires you to reference anything else yourself.

As part of this, I've streamlined the meta-package so it no longer includes NAudio.WinForms (which requires a -windows TFM), and also dropped NAudio.Dmo (which is legacy and should be avoided). I've also moved NAudio.Asio out, as it's a bit more niche, and users can just reference that directly.

The advantage of this setup is that people who reference the NAudio meta-package still get the vast majority of what they always got, but anyone not running on Windows doesn't bring in too much unnecessary baggage. Windows users who are targeting a plain netX.0 TFM will get CA1416 warnings which they can avoid in various ways (e.g. adding a -windows TFM, using [assembly:SupportedOSPlatform("windows")], or using OperatingSystem.IsWindows()).

A slight trade-off is that Linux or macOS users of the meta-package will now end up restoring the NAudio.WinMM and NAudio.Wasapi packages, but they won't be loaded and will be removed if you publish with trimming. I'd generally recommend Linux or macOS users to simply reference the relevant sub-assemblies they need directly (e.g. NAudio.Core plus NAudio.Alsa, NAudio.MacOS, or NAudio.SoundFile as applicable). The NAudio meta-package is not relevant to their needs.

It is a shame that the way I implemented AudioFileReader makes it a Windows-only class. I'd like to resolve that for a future NAudio but it's a bit tricky to do in an elegant non-breaking way, so I'll hold off until I've worked out something I'm happy with.

Another change that will come in NAudio 3.3.0 is that it is fully annotated for nullable reference types. This is another potentially breaking change if you have warnings-as-errors turned on (and <Nullable>enable</Nullable>), but you can either suppress those errors, or update your code to take advantage of improved null safety.

As always, thanks to everyone who provided feedback, and I hope this change will make NAudio 3 easier to work with in the future. If you want to try this out, I've released a preview version of NAudio 3.3.0, so please let me know if you have any issues trying that out. I hope to release the full version of NAudio 3.3.0 in the near future (as I have a number of other exciting features queued up for v3.4.0).

Want to get up to speed with the the fundamentals principles of digital audio and how to got about writing audio applications with NAudio? Be sure to check out my Pluralsight courses, Digital Audio Fundamentals, and Audio Programming with NAudio.