Although I have been developing NAudio for six years now, I have never really written much by way of documentation for it. This post is the first in a series that will attempt to rectify this shortcoming.
What Is NAudio?
NAudio is an open source .NET audio toolkit, containing a variety of classes for working with audio files and devices in Windows. Its key features are:
- Standard WAV file reading and writing
- A pluggable wave streaming architecture including various mixers, format conversion and some basic effects
- Full access to installed ACM codecs
- Individual WAV samples can be accessed
- Audio playback and recording using the WinMM APIs
- Handling compressed WAV files using
- Extensive MIDI file handling and processing
- Ability to receive MIDI events
- Soundfont reading
- OGG file encoding
- Various experimental DSP functions
- A selection of Windows Forms controls for audio related GUIs
- Cakewalk drum map reading
- RGCAudio sfz sampler file reading
- Audio output using DirectSound
- Audio output using ASIO
- Vista CoreAudio API wrappers
- DirectX Media Object wrappers
All this resides in NAudio.dll which can easily be linked to and used from your projects. Not all the features listed are production quality yet, but I will be writing up tutorials on some of the more mature parts of the framework in the future.
In addition to this, NAudio is the basis for a variety of utilities, some of which have moved off into their own CodePlex projects.
- AudioFileInspector is a debugging tool that allows you to simply get textual information on WAV files, MIDI files and SoundFonts.
- MIDI File Converter can convert MIDI files between different MIDI file types (useful for fixing up some drum loops to work with different sequencers)
- MIDI File Mapper can batch process MIDI files remapping their notes, and performing other transformations on the data. Very useful for converting MIDI drum loops to work with different drum samplers.
- MIDI File Splitter is another utility for working with drum loops. It can split long MIDI files at markers.
- MixDiffdemonstrates how to use the Wave Playback features of NAudio. It is intended to allow you to perform double-blind listening tests on different versions of a mix you are working on. It has yet to be properly released.
- NAudioDemo is still very incomplete, but the intention is to create an application that showcases all the features of NAudio, and so serve as a coding tutorial.
When .NET came out I was very excited that Microsoft had created a technology that combined the strengths of MFC, Visual Basic 6 and Java, whilst having very few of their limitations. I wanted to do as much future development in .NET as possible. The only trouble was, a lot of the applications I was writing were dealing with various audio file formats, or processing audio and playing it back.
It seemed that very few open source projects dealing with audio were around back then, and today there still are not that many. So I decided to create my own library, slowly adding whatever bits and pieces I needed to it. I fully expected Microsoft to come along and blow most of it away with a low-level audio stack for .NET but that never happened. And while a handful of other .NET audio libraries have showed up, none seem to have quite the same focus.
I started work on NAudio shortly after .NET 1.0 first came out. I had a Pentium III 450MHz PC back then, and one of the first things I implemented was the interop to the WinMM mixer APIs, complete with forms that auto-populated themselves with sliders. I haven't used the code much since, and I expect I would cringe if I looked back at it now.
The next task was to read Wave Files and play them back using the WaveOut APIs. This took me into a whole world of pain - interop in a garbage collected language. Eventually I got it all working and could play 44.1kHz wave files at a latency of around 400ms.
It was about this time I set up a SourceForge project for NAudio but I never really got on with using CVS.
I also ported a lot of code I had written for working with SoundFonts to C#. The only thing I couldn't get working in C# was the API for loading SoundFonts into the Soundblaster Live card. It used pointers to tables of function pointers, which was out of my depth for interop. I did create a managed C++ library for it though, but before long I had become fed up with Soundblaster's appalling driver support in XP and bought a new soundcard so that part of NAudio came to an end.
The next few years were spent slowly ramping up the MIDI library, and enhancing the Wave playback. I also added DirectSound ouput option. In 2005 I started work at a new company, and realised that a lot of the work I had done in NAudio could be useful for one of their products. I started working in earnest on getting ACM working well which eventually allowed me to use NAudio to form the basis of the audio mixing library for one of my company's key products. It performs well, mixing upwards of 30 concurrent streams of audio (albeit at 8kHz sample rate), and passing through various ACM effects. We work at a latency of around 200ms with no noticeable stuttering even on fairly modest PCs (Pentium IV 2Ghz).
During this time some features were added to NAudio that were eventually dropped. I ported JavaLayer (a Java MP3 decoder) over to C#, but got fed up of constantly needing to update it. Version 1 is out now though, so perhaps it might be worth another go. I also attempted to create wrappers for Steinberg's VST, but the job took longer than I was hoping, and in any case, a promising new project has been created by someone else - VST.NET.
In more recent times, I have added an ASIO output option, and am currently working on adding Vista's CoreAudio WASAPI interface, and access to DirectX Media Objects. I am increasingly trying to write NUnit unit tests for the new features I am developing.
As for the future, NAudio will continue to progress based on the features I need for the applications I am working on. I have no shortage of ideas for audio utilities, but sadly time is at a premium. I'm hoping to create a new release in the near future if I can get the Resampler DMO object working nicely with WASAPI.