Skip to content

NAudio 3.0.0

Latest

Choose a tag to compare

@github-actions github-actions released this 15 Aug 08:40
· 1 commit to main since this release
23922d2

NAudio 3 is a major release. The single NAudio assembly is now split into
focused, independently usable packages; the minimum target framework moves to
net9.0; the core is cross-platform and Native-AOT compatible; and several
large new subsystems — a cross-platform effects suite, a software sampler, VST 3
hosting, and ALSA and libsndfile backends — join the library.

Upgrading from NAudio 2? Migrating from NAudio 2 to NAudio 3
walks through every breaking change with before/after code. Most apps need only
re-target to net9.0, rename WaveOutEvent to WaveOut, and adjust custom
providers to the new Span<T> Read signature.

Packages and platform

  • Minimum target framework is now net9.0 — legacy .NET Framework and .NET Standard 2.0 support is dropped
  • NAudio is now a set of focused packages: NAudio.Core, NAudio.Midi, NAudio.WinMM, NAudio.Wasapi, NAudio.Asio, NAudio.Dmo, NAudio.WinForms, plus the new NAudio.Effects (shipped in NAudio.Core), NAudio.Sampler, NAudio.Vst3, NAudio.Alsa and NAudio.SoundFile. The NAudio meta-package still pulls the Windows stack together, so existing consumers see no change. See Docs/Architecture/NAudio3AssemblyLayoutPlan.md
  • NAudio.Core, NAudio.Midi, NAudio.Wasapi, NAudio.Dmo, NAudio.Sampler, NAudio.SoundFile and NAudio.Alsa are Native-AOT compatible (IsAotCompatible=true), enforced in CI by NAudioAotSmokeTest
  • NAudio.Wasapi targets plain net9.0 (Windows-only at runtime via [SupportedOSPlatform("windows")]), so cross-platform apps can reference it and build on Linux/macOS without EnableWindowsTargeting. The WinRT MIDI backend moved to NAudio.Midi, which now dual-targets net9.0;net9.0-windows10.0.19041.0 (#1384)
  • The NAudio.Uap package is removed — use WasapiPlayerBuilder / WasapiRecorderBuilder
  • Packages ship with SourceLink, .snupkg symbol packages and an embedded SPDX SBOM

New capabilities

Each new subsystem has its own tutorial or README; only the headline is listed here.

  • Audio effects — a cross-platform NAudio.Effects framework: IAudioEffect / EffectSampleProvider / EffectChain with click-free bypass, dry/wet mix and an optional parameter model, plus a broad effect set (EQ and filtering, dynamics, saturation/lo-fi, delay and modulation, reverb including FFT convolution, pitch shifting, and voice-comms AGC/noise suppression). See Docs/AudioEffects.md
  • Modern WASAPI — high-level WasapiPlayer / WasapiRecorder, built via WasapiPlayerBuilder / WasapiRecorderBuilder: IAudioClient3 low latency, MMCSS thread priority, IAsyncDisposable, zero-copy buffers, per-process loopback capture, automatic stream routing that follows the default endpoint (#942), acoustic-echo-cancellation reference control (#1223), communications mode, raw mode (#476), and resample-free bit-depth/channel adaptation in exclusive and low-latency modes. See Docs/WasapiPlayer.md and Docs/WasapiRecorder.md
  • Modern ASIO — a new AsioDevice replacing AsioOut: explicit playback/recording/duplex modes, non-contiguous channels, per-channel Span<float> callbacks, driver-reset recovery and per-buffer timing. AsioOut is preserved as a facade. See Docs/AsioMigration.md
  • Cross-platform audio files — new NAudio.SoundFile package: read and write WAV/AIFF/FLAC/Ogg-Vorbis/Opus/MP3 via a system libsndfile on Windows, Linux and macOS (the first cross-platform FLAC/Vorbis/Opus encoder in NAudio). See Docs/CrossPlatformAudioFilesWithSoundFile.md (#1289)
  • Linux audio — new NAudio.Alsa package: AlsaOut (IWavePlayer) and AlsaIn (IWaveIn) plus AlsaDeviceEnumerator, backed by libasound. See Docs/PlayAudioFileLinuxAlsa.md and Docs/RecordAudioFileLinuxAlsa.md (#1182)
  • VST 3 hosting — new NAudio.Vst3 package (Windows-only): discover, load and host VST 3 effects and instruments, with parameters, state and .vstpreset presets, native editor windows, program lists/units, latency compensation, and live/offline MIDI-file playback through the shared MIDI pipeline. See the NAudio.Vst3 README and Docs/Architecture/Vst3Hosting.md. VST is a registered trademark of Steinberg Media Technologies GmbH
  • Software sampler — new NAudio.Sampler package: polyphonic, cross-platform playback of SoundFont (.sf2) and SFZ instruments and single-sample instruments, rendered as an ISampleProvider (SF2 modulator engine, DAHDSR envelopes, LFOs, modulated filters, reverb/chorus sends, voice stealing, choke groups). See Docs/Sampler.md
  • Event-based device notificationsMMDeviceEnumerator.CreateNotificationClient() returns an MMDeviceNotificationClient exposing DeviceStateChanged, DeviceAdded, DeviceRemoved, DefaultDeviceChanged and PropertyValueChanged as ordinary events, so callers no longer implement a COM interface or manage CCW lifetime (#1395)
  • MIDINAudio.Midi's portable leg is now cross-platform; new WinRT WinRTMidiIn / WinRTMidiOut and backend-agnostic IMidiInput / IMidiOutput; and a new IMidiInstrument seam (MidiFileSequence / SequencedMidiPlayer / OfflineMidiRenderer / LiveMidiInstrument) giving an end-to-end MIDI-file → audio pipeline that drives the sampler or a hosted VST 3 instrument. MidiFile also reads RIFF-RMID (.rmi) files (#1236) and MidiFile.Export gains a Stream overload, thanks to @MaKiPL (#499)
  • Sequencing — a portable NAudio.Sequencing namespace in NAudio.Core (tempo and time-signature maps, transport, EventTimeline, swing, and a sample-accurate per-buffer dispatcher) underpinning MIDI-file playback and the sampler. See Docs/Architecture/Sequencing.md
  • Live capture mixing — new NAudio.Extras helpers CaptureMixerInput and RealtimeCaptureMixer capture and live-mix several sources with different sample rates and channel counts (e.g. microphone + system loopback) into one wall-clock-paced stream. See Docs/MixMicrophoneAndSystemAudio.md (#761)
  • Reading audio from streamsAudioFileReader and CachedSound gain Stream constructors, detecting WAV/AIFF from the contents and delegating anything else to Media Foundation, so embedded or in-memory audio plays without a temp file (#927, #963). StreamMediaFoundationReader also gains optional contentType / originName hints and Ogg container sniffing (#952)
  • WAV chunk modelWaveFileReader.Chunks with an IWaveChunkInterpreter<T> extension point and built-in interpreters for cue lists, BWF bext (BroadcastExtension, now read and write, with v2 loudness) and LIST/INFO (InfoMetadata); WaveFileWriter gains AddCue, WriteCueList, WriteBroadcastExtension, arbitrary AddChunk and RF64 promotion via WaveFileWriterOptions (#1013)
  • Latency reporting — new IWaveLatency interface in NAudio.Core exposing AverageLatency / CurrentLatency for A/V sync and drift detection, implemented across the playback and capture classes (#601)
  • Sample providers and DSP — new ChannelMixerSampleProvider with ready-made ChannelMixMatrix routings, thanks to @antiduh (#982); a new FftProcessor; Span<T> overloads across the codec/DSP surface; reusable building blocks (EnvelopeFollower, DelayLine, Lfo, Oversampler, LinkwitzRileyCrossover, PartitionedConvolver, …); plus improvements to SmbPitchShiftingSampleProvider (#922), AdsrSampleProvider (#671) and FadeInOutSampleProvider (#1136)
  • WaveFormatExtensible — new constructors for SubFormat, valid-bits-per-sample and channel mask, readable ValidBitsPerSample / ChannelMask, and a [Flags] Speakers enum for building channel masks (#1325)
  • WASAPI sessions and devicesAudioSessionControl.SetDuckingPreference(bool) (#760); WasapiPlayer / WasapiRecorder expose DeviceId and DeviceFriendlyName for the active endpoint (#681)

Breaking changes

The full upgrade walkthrough — every breaking change with before/after code — is
in Migrating from NAudio 2 to NAudio 3. The
highest-impact changes:

  • Minimum target framework is now net9.0 (legacy .NET Framework / .NET Standard 2.0 dropped)
  • IWaveProvider.Read / ISampleProvider.Read now take a single Span<byte> / Span<float> (was buffer/offset/count) — callers migrate via source.Read(buffer.AsSpan(offset, count)); implementations override the span method
  • WaveOutEvent is renamed to WaveOut and WaveInEvent to WaveIn (the old names remain as [Obsolete] subclasses). WaveOut / WaveIn now default to event-driven callbacks; the window-based variants are WaveOutWindow / WaveInWindow in NAudio.WinForms, and WaveCallbackInfo / WaveCallbackStrategy are removed
  • WaveOut.DesiredLatency is replaced by BufferMilliseconds, which sizes each individual buffer rather than the total across all of them. WaveIn's default record format changes from 8 kHz mono to 44.1 kHz stereo
  • WasapiOut, WasapiCapture and WasapiLoopbackCapture are [Obsolete] in favour of WasapiPlayer / WasapiRecorder (the legacy types still ship and work); WasapiOut's embedded exclusive-mode resampler was removed, though it now adapts bit depth and channels, so only a sample-rate mismatch requires upstream resampling
  • The low-level IMMNotificationClient interface and MMDeviceEnumerator.RegisterEndpointNotificationCallback / UnregisterEndpointNotificationCallback are now internal — use CreateNotificationClient() and its events. The raw Core Audio and Media Foundation COM interfaces are likewise internal, and PropertyStoreProperty.Value is now object rather than PropVariant
  • Some types moved package or namespace as part of the split — classic Windows MIDI I/O and winmm types to NAudio.WinMM; the DMO/DirectSound types into the new NAudio.Dmo package; plus smaller moves (AudioVolumeLevel, CaptureState, DmoMp3FrameDecompressor). Meta-package consumers are unaffected
  • Removed seven members that were already [Obsolete] throughout NAudio 2, each with a direct replacement on the same class: WaveFileWriter.WriteData (both overloads → Write / WriteSamples), WaveFileReader.TryReadFloat (→ ReadNextSampleFrame, which doesn't drop channels on stereo), AcmStream.Convert(int) (→ the overload returning sourceBytesConverted), WaveFormatConversionStream.SourceToDest / DestToSource (unreliable estimates with no replacement — use Position / Length), and AsioAudioAvailableEventArgs.GetAsInterleavedSamples() (→ the overload taking a reusable array, avoiding an allocation per ASIO callback). AsioOut.Volume is kept despite its obsolete notice — it's an IWavePlayer interface member
  • AudioMediaSubtypes moved from the NAudio.Dmo namespace to NAudio.Wave. It ships in NAudio.Core, so cross-platform code previously needed using NAudio.Dmo; to name the media subtype GUIDs even on Linux without the DMO package; it now sits alongside WaveFormatExtensible
  • SimpleCompressorStream, ImpulseResponseConvolution and NAudio.Extras.Equalizer were removed — superseded by NAudio.Effects (CompressorEffect, ConvolutionReverbEffect, Equalizer)
  • CueWaveFileReader, CueWaveFileWriter, BwfWriter and BextChunkInfo were removed, along with WaveFileReader.ExtraChunks / GetChunkData — the unified chunk model on WaveFileReader.Chunks and WaveFileWriter replaces them
  • MixingWaveProvider32 was removed — it was an untested float-only mixer that offered nothing over MixingSampleProvider. ImaAdpcmWaveFormat was removed — it was a non-functional stub used nowhere
  • WaveFileWriter / AiffFileWriter no longer dispose a caller-supplied stream, matching the readers' ownership rule; only the filename constructor owns and closes the file. IgnoreDisposeStream is no longer needed when writing to a stream you want to keep (#1040)
  • Finalizers were removed from MediaFoundationTransform, MediaFoundationEncoder and MediaBuffer, and MediaType is now IDisposable — call Dispose()
  • Core Audio, Media Foundation and DMO errors now throw CoreAudioException / MediaFoundationException, both subclasses of COMException, so existing catch (COMException) keeps working

Notable bug fixes

The sampler, effects and WASAPI subsystems also saw extensive correctness work during
development. The full per-PR list is on the GitHub Release; the fixes most likely to
affect existing NAudio 2 code are:

  • WaveFileWriter.WriteSample / WriteSamples: fixed 32-bit WaveFormatExtensible output writing near-silence or corrupt data — both paths ignored the declared SubFormat (#651)
  • ToSampleProvider() now handles WAVE_FORMAT_EXTENSIBLE PCM and IEEE float sources (e.g. multichannel or >16-bit WAV) instead of throwing Unsupported source encoding (#639); AudioFileReader no longer routes such WAVs through an unnecessary ACM conversion stream
  • WaveFileReader / AiffFileReader: malformed headers declaring BlockAlign=0 throw InvalidDataException from the constructor rather than DivideByZeroException later (#1254); an oversized data chunk length is clamped to the bytes actually present (#1090); an oversized fmt cbSize no longer throws (#482)
  • AiffFileReader / AiffFileWriter: 8-bit PCM is now read and written as signed two's-complement per the AIFF spec, fixing DC-shifted/garbled playback (#1178)
  • BlockAlignReductionStream.Read: a read larger than the 4-second internal buffer no longer silently truncates the stream — e.g. converting a non-PCM WAV via AudioFileReader (#1022)
  • WaveOut: fixed a race where stopping or disposing faster than the buffer latency could throw a NullReferenceException via PlaybackStopped (#804); DirectSoundOut: fixed a startup race that could collapse playback immediately (#759)
  • WasapiRecorder, WasapiCapture and WasapiLoopbackCapture: a capture device removed mid-recording no longer crashes the process — RecordingStopped always fires with the originating exception (#672). Silent packets no longer leak the uninitialised WASAPI buffer as a burst of stale audio
  • Fixed an access violation that could crash the process when an endpoint notification fired after RegisterEndpointNotificationCallback — Windows does not AddRef the client, so the CCW was being collected (#1394)
  • AudioClient.Dispose is now idempotent and safe against concurrent disposal (#1183); MMDevice.Dispose releases the property store deterministically (#1145); AudioSessionControl supports multiple event clients without leaking (#1263); AudioEndpointVolume.OnVolumeNotification reports the correct channel (#351)
  • AcmInterop: serialised all msacm32 P/Invokes process-wide, fixing process-killing access violations under concurrent ACM use
  • ResamplerDmoStream: fixed an infinite loop on Read after seeking and the loss of the resampler tail at end-of-stream (#607, #608); LoopStream.Read no longer spins at 100% CPU when the source can't satisfy a read (#1338)
  • FastFourierTransform.FFT: fixed drifting high-frequency bins at large FFT sizes by carrying the twiddle-factor recurrence in double precision (#520)
  • WdlResampler: backported upstream Cockos WDL fixes, including reinterleaving on channel-count change and denormal flushing in the IIR feedback path (#800)
  • WaveViewer: fixed rendering upside-down (#801, #818) and now renders any source format via ToSampleProvider() (#564)
  • Mp3FileReader: fixed false sample-rate-change errors near end of file, and more robust frame parsing against album art and trailing metadata; MidiFile preserves running status across meta events
  • WaveFormat.Serialize: PCM formats now write the canonical 16-byte fmt chunk (#934, #1098)
  • Hardened Media Foundation and DMO interop against COM ref leaks on error paths (#1293)

Demos and tooling

  • NAudioDemo and NAudioWpfDemo were substantially reworked against the new APIs, including a rebuilt WASAPI Recorder panel driven by WasapiRecorderBuilder, transport/volume/position controls across the playback panels, and a Graphic EQ panel on NAudio.Effects
  • The network chat demo is now UDP-only with a bounded jitter buffer and Opus codecs (via Concentus, replacing the vendored NSpeex binary), and gained a tutorial
  • The documentation site (tutorials plus a generated API reference) is published to GitHub Pages from Docs/ and the source XML comments. Every package's projectUrl and README now point at it; nuget.org still links the GitHub repo via the package's repository metadata