NAudio.SoundFile
3.0.0-preview.10
Prefix Reserved
dotnet add package NAudio.SoundFile --version 3.0.0-preview.10
NuGet\Install-Package NAudio.SoundFile -Version 3.0.0-preview.10
<PackageReference Include="NAudio.SoundFile" Version="3.0.0-preview.10" />
<PackageVersion Include="NAudio.SoundFile" Version="3.0.0-preview.10" />
<PackageReference Include="NAudio.SoundFile" />
paket add NAudio.SoundFile --version 3.0.0-preview.10
#r "nuget: NAudio.SoundFile, 3.0.0-preview.10"
#:package NAudio.SoundFile@3.0.0-preview.10
#addin nuget:?package=NAudio.SoundFile&version=3.0.0-preview.10&prerelease
#tool nuget:?package=NAudio.SoundFile&version=3.0.0-preview.10&prerelease
NAudio.SoundFile
Cross-platform audio file reading and writing for NAudio, backed by libsndfile.
| Type | Role |
|---|---|
SoundFileReader |
WaveStream + ISampleProvider — decode WAV/AIFF/FLAC/Ogg/Opus/MP3 |
SoundFileWriter |
Stream sink — encode WAV/AIFF/FLAC/Ogg-Vorbis/Opus/MP3 |
SoundFileCapabilities |
query which codecs the installed libsndfile supports |
SoundFileException |
thrown on libsndfile errors (exposes ErrorCode) |
This is the first cross-platform FLAC/Vorbis/Opus encoder in NAudio, and on Linux/macOS the first general-purpose decoder (there is no Media Foundation off Windows).
Platform
Truly cross-platform — net9.0, no [SupportedOSPlatform]. It
P/Invokes a system libsndfile, resolved automatically per OS
(libsndfile.so.1 / libsndfile.1.dylib / sndfile.dll /
libsndfile-1.dll). You must provide it:
sudo apt install libsndfile1 # Debian/Ubuntu
brew install libsndfile # macOS
vcpkg install libsndfile # Windows (or the official binaries)
Not pulled in by the NAudio meta-package — reference it explicitly:
dotnet add package NAudio.SoundFile
Supported formats
| Format | Read | Write | Requires |
|---|---|---|---|
| WAV, AIFF, AU, CAF, W64, RAW | ✅ | ✅ | always |
| FLAC | ✅ | ✅ | libsndfile built with libFLAC (typical) |
| Ogg/Vorbis | ✅ | ✅ | libvorbis (typical) |
| Ogg/Opus | ✅ | ✅ | libsndfile ≥ 1.0.29 + libopus |
| MP3 | ✅ | ✅ | libsndfile ≥ 1.1.0 |
Codec availability depends on how libsndfile was built — query it:
foreach (var f in SoundFileCapabilities.GetSupportedMajorFormats())
Console.WriteLine(f);
bool canFlac = SoundFileCapabilities.IsFormatSupported(SoundFileMajorFormat.Flac);
AAC / M4A / ALAC / WMA are out of scope (the MPEG-4 family is FFmpeg territory).
Read any file
SoundFileReader decodes to 32-bit float, so it is both a WaveStream
and an ISampleProvider:
using NAudio.SoundFile;
using NAudio.Wave;
using var reader = new SoundFileReader("song.flac");
Console.WriteLine($"{reader.WaveFormat} {reader.TotalTime}");
// feed it into any NAudio output, mixer or sample pipeline
Write FLAC / Ogg / Opus
using (var source = new SoundFileReader("in.wav"))
SoundFileWriter.CreateSoundFile("out.flac", source,
SoundFileMajorFormat.Flac,
new SoundFileWriterOptions { CompressionLevel = 0.8 });
// Ogg Vorbis at VBR quality 0.6, with tags
using (var source = new SoundFileReader("in.wav"))
SoundFileWriter.CreateSoundFile("out.ogg", source,
SoundFileMajorFormat.OggVorbis,
new SoundFileWriterOptions
{
VbrQuality = 0.6,
Tags = new SoundFileTags { Title = "Demo", Artist = "NAudio" }
});
Read embedded metadata back:
using var reader = new SoundFileReader("song.flac");
Console.WriteLine($"{reader.Tags.Artist} – {reader.Tags.Title}");
Console.WriteLine(SoundFileCapabilities.LibraryVersion);
The output format is also inferred from the extension:
SoundFileWriter.CreateSoundFile("out.flac", source); // → FLAC
Streams
Both ends work over a System.IO.Stream (via libsndfile virtual I/O):
using var ms = new MemoryStream();
SoundFileWriter.WriteSoundFileToStream(ms, source, SoundFileMajorFormat.OggVorbis, null);
ms.Position = 0;
using var reader = new SoundFileReader(ms); // stream not disposed by the reader
FLAC/Ogg/Opus/MP3 stream fine to a forward-only target; WAV/AIFF back-patch their header at close and require a seekable stream (the writer throws early if you pair a non-seekable stream with such a format).
Notes
- The writer accepts 16-bit PCM or 32-bit IEEE float input — the
two container types NAudio pipelines naturally produce. Convert other
formats with
SampleToWaveProvider16or.ToSampleProvider()first. - AOT-compatible: source-generated
[LibraryImport],SafeHandlelifetime, and[UnmanagedCallersOnly]virtual-I/O callbacks. - The wrapper is MIT; libsndfile itself is LGPL-2.1+ and supplied by the
user as a system library (no binary is shipped) — the same model as
NAudio.Alsa.
Tutorial
For a worked walkthrough (reading, encoding, format conversion, streams, tags, capability detection) see Cross-platform audio file reading and writing with NAudio.SoundFile.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- NAudio.Core (>= 3.0.0-preview.10)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.0.0-preview.10 | 69 | 6/8/2026 |
| 3.0.0-preview.9 | 58 | 5/27/2026 |
| 3.0.0-preview.8 | 60 | 5/22/2026 |
| 3.0.0-preview.7 | 58 | 5/21/2026 |
| 3.0.0-preview.6 | 58 | 5/21/2026 |
#### Breaking changes
* `AudioVolumeLevel` moved from `NAudio.Wasapi.CoreAudioApi` to `NAudio.CoreAudioApi` — it now lives in the same namespace as the rest of the WASAPI/Core Audio API (`MMDevice`, `Part`, `DeviceTopology`, etc.) that it's returned from. The parallel `NAudio.Wasapi.CoreAudioApi` namespace (which otherwise held only internal COM-activation plumbing) is gone
* `DmoMp3FrameDecompressor` moved from `NAudio.FileFormats.Mp3` to `NAudio.Dmo` — it's a DMO wrapper and now shares the namespace of the `NAudio.Dmo` assembly it ships in (alongside `DmoEffectWaveProvider`, `ResamplerDmoStream`, etc.)
* `WaveFileChunkReader` is now `internal` (and moved from `NAudio.FileFormats.Wav` to `NAudio.Wave`) — it was internal plumbing for `WaveFileReader`. Read custom RIFF chunks via `WaveFileReader.Chunks` (`WaveChunks` / `RiffChunk` / `IWaveChunkInterpreter<T>`) instead
* `CaptureState` enum moved from `NAudio.CoreAudioApi` to `NAudio.Wave` — it's a backend-agnostic capture-state type used by `WaveIn`, `WasapiCapture`, and `WasapiRecorder`, and was only in `NAudio.CoreAudioApi` for historical reasons. Code that named the type via `using NAudio.CoreAudioApi;` now needs `using NAudio.Wave;`
* `IWaveProvider.Read` signature changed from `Read(byte[], int, int)` to `Read(Span<byte>)`. Existing callers with `byte[]` migrate via `source.Read(buffer.AsSpan(offset, count))`; implementations override `Read(Span<byte>)`
* `ISampleProvider.Read` signature changed from `Read(float[], int, int)` to `Read(Span<float>)` (same migration pattern)
* `MidiIn`, `MidiOut`, `MidiInCapabilities`, and `MidiOutCapabilities` moved from `NAudio.Midi` to `NAudio.WinMM` — all `winmm.dll` interop now lives in one assembly
* `MmResult`, `MmException`, and `Manufacturers` moved from `NAudio.Core` to `NAudio.WinMM`
* `DirectSoundOut` moved from `NAudio.Core` to `NAudio.Dmo` (DirectSound has always been Windows-only)
* **New `NAudio.Dmo` package.** DMO effects (echo, chorus, reverb, etc.), the DMO MP3 decoder (`DmoMp3FrameDecompressor`), the DMO resampler (`ResamplerDmoStream`), and `DirectSoundOut` carved out of `NAudio.Wasapi`. Namespaces preserved (`NAudio.Dmo`, `NAudio.Dmo.Effect`, `NAudio.Wave` for `DirectSoundOut`). Meta-package consumers see no change — `NAudio.Dmo` comes in transitively. Direct `NAudio.Wasapi` consumers who use the DMO/DirectSound types now need an explicit `<PackageReference Include="NAudio.Dmo" />`.
* `NAudio.Midi` is now cross-platform — its `net9.0` target no longer P/Invokes `winmm.dll`
* `MidiInMessageEventArgs.Timestamp` and `MidiInSysexMessageEventArgs.Timestamp` are now `TimeSpan` (previously `int` milliseconds) — preserves full WinRT 100 ns resolution on the WinRT backend
* `MidiIn.CreateSysexBuffers` removed — `MidiIn` now allocates sysex receive buffers automatically inside `Start()`
* `WasapiOut`, `WasapiCapture`, and `WasapiLoopbackCapture` are now `[Obsolete]` in favour of the new `WasapiPlayer` / `WasapiRecorder` APIs (the legacy types still ship and continue to work)
* `WasapiOut`'s embedded DMO resampler removed. Exclusive-mode callers whose source format is not natively supported now get a `NotSupportedException` from `Init` instead of silent on-the-fly resampling. Resample upstream (e.g. with `MediaFoundationResampler`), use shared mode (which still auto-converts via `AutoConvertPcm`), or switch to `WasapiPlayerBuilder`. Removes `NAudio.Wasapi`'s only intra-assembly dependency on DMO.
* `WaveOut` and `WaveIn` now default to event-driven callbacks; the legacy window-based variants are renamed `WaveOutWindow` / `WaveInWindow` and live in `NAudio.WinForms`
* `WaveInEventArgs` now fires one event per WASAPI packet (previously batched). A new `BufferSpan` property exposes the data without copying through the existing `Buffer` byte array
* Several `Mf*` Media Foundation wrapper types are now `internal` — only `MfActivate` and `MediaType` remain public
* `BufferedWaveProvider` buffer duration is now set in the constructor (default 5 seconds); `BufferLength` and `BufferDuration` are read-only
* `WaveBuffer` is deprecated — use `MemoryMarshal.Cast` instead
* `MMDevice.AudioClient` is `[Obsolete]` because it created a new instance per access; use `MMDevice.CreateAudioClient()`
* `PropertyStore[int]` now resolves `PropVariant` values safely; the indexer that returned the raw `PropVariant` is `[Obsolete]`
* Minimum target framework is now `net9.0` (previously supported legacy .NET Framework and .NET Standard 2.0)
* `CueWaveFileReader` removed - use `new WaveFileReader(...).Chunks.ReadCueList()` to get a `CueList`
* `StreamMediaFoundationReader` now throws `ArgumentException` for non-readable or non-seekable streams instead of failing later (#1288)
* Corrected `HResult.E_INVALIDARG` to `0x80070057` (was the legacy `0x80000003`) and deprecated `HResult.MAKE_HRESULT` in favour of `MakeHResult` (#1288)
* `SimpleCompressorEffect` (formerly `SimpleCompressorStream`) removed, along with the internal ChunkWare `SimpleCompressor` / `SimpleGate` / `EnvelopeDetector` — superseded by the new `NAudio.Effects` framework; high-quality dynamics effects follow in a later NAudio 3 phase
* `ImpulseResponseConvolution` removed — it was an unusable O(n²) time-domain stub; FFT-based convolution will replace it in a later NAudio 3 phase
* `NAudio.Extras.Equalizer` and `NAudio.Extras.EqualizerBand` removed — replaced by `NAudio.Effects.Equalizer` / `EqualizerBand` in `NAudio.Core`. The new EQ is per-channel, click-free when retuned, and adds shelves/pass/notch/band-pass/all-pass shapes. Band API changed: `Bandwidth`/`Gain` → `Q`/`GainDb` (or `ShelfSlope`), and the equaliser is an `IAudioEffect` (wrap with `EffectSampleProvider` instead of passing a source to the constructor)
#### New features
* **NAudio.SoundFile:** new cross-platform `SoundFileReader` / `SoundFileWriter` wrapping libsndfile — reads and writes WAV/AIFF/FLAC/Ogg-Vorbis/Opus/MP3 on Linux, macOS and Windows (the first cross-platform FLAC/Vorbis/Opus *encoder* in NAudio). `SoundFileReader` is a `WaveStream` and `ISampleProvider`; both reader and writer also work over a `System.IO.Stream`. Requires a system libsndfile; `SoundFileCapabilities` reports which codecs the build supports (#1289)
* **WASAPI:** new high-level `WasapiPlayer` and `WasapiRecorder` classes, built via `WasapiPlayerBuilder` / `WasapiRecorderBuilder`. Adds `IAudioClient3` low-latency support, MMCSS thread priority, `IAsyncDisposable`, zero-copy buffer access, and process-specific loopback via `WasapiRecorderBuilder.WithProcessLoopback()`
* **ASIO:** new `AsioDevice` class replacing `AsioOut` as the primary ASIO interface. Adds explicit `InitPlayback` / `InitRecording` / `InitDuplex` modes, non-contiguous channel selection, per-channel `Span<float>` callbacks, `Reinitialize()` for driver-reset recovery, and per-buffer timing fields (`SamplePosition`, `SystemTimeNanoseconds`, `Speed`, SMPTE `TimeCode`)
* **ASIO events:** `LatenciesChanged` and `ResyncOccurred` surfaced separately; buffer-size changes routed through `DriverResetRequest`
* **Media Foundation:** `MediaFoundationEncoder.EncodeToFlac` for lossless FLAC output. The FLAC/ALAC selector now falls back correctly on rate + channels
* **WinForms:** `WaveOutWindow` and `WaveInWindow` available as window-callback variants of the modernised event-driven `WaveOut` / `WaveIn`
* **DSP:** new `FftProcessor` with real-input specialisation and precomputed windowing
* **WAV chunks:** new `IWaveChunkInterpreter<T>` extension point, with built-in interpreters for cue lists, BWF `bext` (v1 and v2), and LIST/INFO metadata. RF64 promotion is now an explicit `WaveFileWriterOption`
* **`Span<T>` overloads:** added on `BiQuadFilter.Transform`, `ALawDecoder.Decode`, `MuLawDecoder.Decode`, and `IMp3FrameDecompressor.DecompressFrame` (default interface method preserves backward compatibility with `NLayer` and other third-party decoders)
* **MIDI:** new `WinRTMidiIn` / `WinRTMidiOut` classes in `NAudio.Wasapi` backed by `Windows.Devices.Midi`, with `MidiMessageConverter` for interop with the WinRT MIDI types. New `IMidiInput` / `IMidiOutput` interfaces (with a `Send(MidiEvent)` extension) let callers write backend-agnostic code; legacy `MidiIn` / `MidiOut` also implement them
* **MIDI:** `MidiFile` now reads RIFF-RMID (`.rmi`) files by unwrapping the RIFF container and parsing the embedded standard MIDI file (#1236)
* **ALSA (Linux):** new `NAudio.Alsa` package — `AlsaOut` (`IWavePlayer`) and `AlsaIn` (`IWaveIn`) backed by `libasound`, plus `AlsaDeviceEnumerator`. Linux-only (`[SupportedOSPlatform("linux")]`, AOT-compatible `[LibraryImport]`); reference it explicitly, it is not part of the `NAudio` meta-package (#1182)
* **Effects:** new cross-platform `NAudio.Effects` framework — `IAudioEffect`, an `AudioEffect` base with click-free bypass and dry/wet mix, `EffectSampleProvider`, and `EffectChain`. The chain is editable while it plays (`Add`/`Insert`/`RemoveAt`/`Move` publish a new chain atomically on the next block without resetting the other effects; `Read` stays lock-free) and exposes `Reset()` to clear all effect state (delay lines, filter history, reverb tails) for reuse after a seek
* **Effects:** an optional `IParameterized` / `EffectParameter` model lets effects expose their controls (continuous/toggle/choice/meter) as a uniform list for generic UIs, presets and automation without changing `IAudioEffect`; live edits are marshalled to the audio thread by a lock-free `ParameterDispatchQueue` / `IParameterDispatch` so parameter writes never race the realtime callback
* **Effects — EQ & filtering:** a per-channel multi-band `Equalizer` (peaking/shelf/pass/notch/band-pass/all-pass, click-free retune), a 10/31-band `GraphicEqualizer`, `MonoMakerEffect` (bass-mono) and `DcBlockerEffect`
* **Effects — level & stereo:** `GainEffect`, `PanEffect` and `StereoWidthEffect`
* **Effects — dynamics:** `CompressorEffect` (soft knee, peak/RMS detector, channel-linked), `LimiterEffect` (brick-wall with look-ahead and optional true-peak/inter-sample detection), `GateEffect` (gate/downward-expander with hysteresis and hold), `TransientShaperEffect` (dual-envelope attack/sustain shaping), split-band `DeEsserEffect`, and `MultibandCompressorEffect` (configurable LR4 bands, per-band threshold/ratio/attack/release/make-up); all expose live `GainReductionDb` for metering
* **Effects — saturation & lo-fi:** `SaturationEffect` (tanh/cubic/arctan/hard-clip wave-shaper with drive, output trim and optional 2×/4× oversampling) and `BitCrusherEffect` (bit-depth plus target-sample-rate reduction, e.g. 22.05/16/8 kHz, with an optional smoothing low-pass)
* **Effects — delay & modulation:** `DelayEffect` (tempo-syncable with read-only `EffectiveDelayMs`, feedback damping, ping-pong), `ChorusEffect`, `FlangerEffect`, `PhaserEffect` and `TremoloEffect` (with auto-pan)
* **Effects — reverb:** `ConvolutionReverbEffect` (partitioned FFT convolution, mono or per-channel IR, reports latency, replacing the removed `ImpulseResponseConvolution`), `ReverbEffect` (lightweight Freeverb-style Schroeder–Moorer) and `FdnReverbEffect` (modulated feedback-delay network with RT60, size, damping and width)
* **Effects — pitch:** `PitchShiftEffect` — framework-integrated per-channel phase-vocoder pitch shifting with semitone control and FFT latency reporting
* **Effects — voice comms:** `AutomaticGainControlEffect` (VAD-gated leveller), `NoiseSuppressionEffect` (STFT spectral suppression) and `ComfortNoiseEffect`
* **DSP:** new reusable building blocks underpinning the effects suite — `EnvelopeFollower`, `ParameterSmoother`, `DelayLine`, `CrossfadingBiQuadFilter`, `Lfo` (with `NoteDivision`/`TempoTime` tempo helpers), `Oversampler`, `LinkwitzRileyCrossover`, `PartitionedConvolver`, `VoiceActivityDetector`, plus `BiQuadFilter.ResetState()`
* **Docs:** added an Audio Effects guide (`Docs/AudioEffects.md`) covering the suite, chains, dry/wet & bypass, the parameter model and writing your own effect
* **Docs:** added `WasapiPlayer` and `WasapiRecorder` tutorials; the legacy `WasapiOut` and `WasapiLoopbackCapture` docs now point to them
* **Core:** `NAudio.Utils.HResult` gained constants for common COM/storage HRESULTs plus an `IsError` helper (#1288)
* **Sample providers:** new `ChannelMixerSampleProvider` remixes a source's channels through an arbitrary mixing matrix (downmix, upmix, weighted routing), with ready-made matrices in `ChannelMixMatrix` (mono↔stereo, stereo→5.1, etc.). Thanks to @antiduh (#982)
#### Demo apps and Test Harnesses
* **WPF demo:** new **Convolution Reverb** module — offline test bench for `ConvolutionReverbEffect`: pick an input file and a folder of impulse responses, render single-IR or batch-all, with IR auto-resample to the input rate and peak-normalisation to -3 dBFS, latency-compensated output, full tail flush, and per-render Nx-real-time + tail-length reporting. Renders land in a temp folder with Play/Delete/Open-folder commands
* **WPF demo:** new **Realtime Effects** module — full-duplex `AsioDevice` monitor (driver + mono/stereo input) with feedback safety (starts muted, headphone warning, runaway auto-mute), an add/remove/reorder effect-chain editor with auto-generated parameter panels (knobs/toggles/choices/meters + Bypass/Mix) driven by `IParameterized`, and WAV-file playback / offline render through the chain. Live parameter edits are marshalled to the audio thread via `ParameterDispatchQueue`, newly added effects are pre-warmed off the audio thread, and ASIO monitoring and file playback/render are mutually exclusive (the chain is shared). An input-channel offset selector allows mono/stereo capture from any base channel (e.g. a guitar on input 2, or a stereo pair on 5+6). Three demo-only effects (`SevenBandEqEffect`, `FilterEffect`, `ThreeBandCompressorEffect`) composed from the toolkit's `Equalizer` / `CrossfadingBiQuadFilter` / `MultibandCompressorEffect` primitives are wired into the harness — they smoke-test the underlying DSP and show how to build fixed-parameter effects on top of the dynamic-band primitives
* **NAudioConsoleTest:** new CLI test harness for driving various NAudio features without the need for GUI. Includes `run-batch` for JSON-driven test plans and `diagnose` for capturing a structured host audio snapshot (OS, ASIO drivers, WASAPI/WinMM/DirectSound devices, NAudio assembly versions).
* **WPF demos:** spectrum analyser rewritten with corrected dB formula (20·log₁₀), log-frequency mapping, real-input full-scale calibration, bars instead of polylines, peak-decay markers, and per-band smoothing. New `LiveWaveformControl` with configurable render styles, vertical scaling, and fill-between rendering
* **WAV recording demo:** added loopback support and a multi-API device combo with provenance embedding
* **MIDI In demo:** Refresh button for hot-plugged devices, device combos disabled while in use, test MIDI Out plays on channel 1 (was 2), Filter Auto-Sensing on by default, stopping test output now sends note-off so notes don't hang, and cleaner panel disposal
* **MfStressTest:** Reliability tests for the new Media Foundation interop implementation in NAudio 3.
* Replaced vendored NSpeex (deprecated) with Opus (Concentus) in the network chat demo; added round-trip unit tests
#### Performance
* Vectorised mix-add and volume kernels via `System.Numerics.Tensors` — significantly faster on AVX2 hardware for typical buffer sizes
* Eliminated per-`Read` allocations in `SmbPitchShiftingSampleProvider`
* `WaveStream.Read(Span<byte>)` overridden directly on every concrete reader (no intermediate byte-array copy)
* `WasapiCapture` capture path is now zero-copy via the native WASAPI buffer span
* `BiQuadFilter` state and coefficient fields hoisted to locals in batch loops for register retention
* `Mp3FileReader` now builds its table-of-contents lazily on first seek instead of eagerly during construction; the `Position` setter no longer blocks; rapid scrub seeks debounce and silence output
* Eliminated per-`Read` allocations in `ResamplerDmoStream` and `DmoMp3FrameDecompressor` (cached input buffer and output-buffer array) (#971)
#### Reliability and bug fixes
* `AudioSessionControl`: now supports multiple registered event clients. `RegisterEventClient` no longer leaks a prior registration, and `UnRegisterEventClient` now honours its `eventClient` argument instead of unregistering whichever handler happened to be stored (#1263)
* `CueListInterpreter`: fixed returning null for WAV files with cue points but no labels (e.g. unnamed Wavosaur markers); cues are now returned with empty labels (#549)
* `WaveViewer`: fixed waveform rendering upside-down (#801, #818)
* `WaveViewer`: now renders correctly for any source format — the legacy renderer hard-coded a 16-bit PCM byte walk, so feeding it an `AudioFileReader` (or any non-16-bit `WaveStream`) produced a garbled waveform. Rendering now goes through `ToSampleProvider()` and operates on floats (#564)
* `AcmInterop`: serialised all `msacm32` P/Invokes process-wide via a reentrant lock — fixes process-killing access violations under concurrent ACM access
* `AcmStream`: fixed double-close in finalizer by zeroing the handle field before close
* `MediaFoundationReader`: informational source-reader flags (`STREAMTICK`, `NEWSTREAM`, `NativeMediaTypeChanged`, `AllEffectsRemoved`) are now non-fatal instead of aborting reads
* `MediaFoundationReader`: cleanup `finally` block on `Read` no longer leaks COM objects when `Unlock` fails — the hresult is captured and thrown only after both the buffer and the sample have been freed.
* `MediaFoundationReader.Reposition`: fixed using a stale field instead of the parameter (seeks would default to stream start)
* `MediaFoundationEncoder`: unselected `MediaType` instances are now disposed to prevent finalizer-thread COM ref leaks
* `MediaFoundationEncoder`: In the `ConvertOneBuffer` method, there was a small possibility that if the sample creation was failed, the previously allocated buffer COM object would have been leaked.
* `StreamMediaFoundationReader` and stream-based `MediaFoundationEncoder` encoding now use a direct managed `IMFByteStream` wrapper instead of the `IStream`→`IMFByteStream` shim, improving reliability of reading and encoding audio through .NET streams (#1288)
* `Mp3FileReader`: fixed false sample-rate-change errors near end of file
* `WaveFormat.Serialize`: PCM formats now write the canonical 16-byte `fmt ` chunk (no `cbSize` field) instead of 18 bytes, matching the `PCMWAVEFORMAT` layout (#934, #1098)
* MP3 frame parsing: more robust against false frame detections from album art and trailing metadata
* `MidiFile`: preserved running-status across meta events (fixes "Read too far" errors when meta events interrupt running-status sequences)
* `WaveStream.CurrentTime` setter: now lands on a block boundary, preventing garbage audio on seek in custom readers
* `BlockAlignReductionStream.Position` setter: now validates the incoming value instead of the stale current position, so a block-aligned seek after an arbitrary-length read no longer wrongly throws "Position must be block aligned" (#368)
* `IconExtractor.Extract`: now guards against null icon handles from `ExtractIconEx`
* `DirectSoundOut.InitializeDirectSound`: wrapped notification setup in try/finally to prevent COM ref leak on `SetNotificationPositions` failure
* ASIO: implemented missing `Asio64Bit` conversions (Int24LSB and Float32LSB output sample types)
* ASIO: fixed byte-order bug in `AsioDriver.GetSamplePosition` for `Asio64Bit` reassembly
* `WdlResampler`: backported three upstream Cockos WDL bug fixes (latency calculation, `ResampleOut` clamping, Blackman-Harris window correction)
* `MediaBufferLease`: hardened against out-of-order disposal
* Added finalizers to DMO `MediaBuffer` and the `Mf*` wrappers that hold (RCW, IntPtr) pairs to prevent COM ref leaks
* `WaveFileChunkReader`: fixed `ArgumentException` parsing WAV files whose odd-length chunks are followed by non-UTF-8 bytes — the word-alignment pad-byte check no longer decodes via `BinaryReader.PeekChar()`, and is now guarded against end-of-stream (#959)
* Clarified `BiQuadFilter` `q` parameter docs (#1264)
* Removed dead `naudio.codeplex.com` links from README, MixDiff Help menu, and source comments (CodePlex was shut down by Microsoft in 2017) (#985)
* `AudioClient.Dispose`: made idempotent and safe against concurrent/re-entrant disposal — fixes an intermittent `NullReferenceException` from the COM interop layer when a WASAPI capture or playback wrapper is disposed more than once (#1183)
* `WaveFileReader` / `AiffFileReader`: malformed headers that declared `BlockAlign=0` now throw `InvalidDataException` from the constructor instead of `DivideByZeroException` from the `Position` setter (#1254)
* `AiffFileReader.Read`: truncated `SSND` chunks no longer trigger `IndexOutOfRangeException` in the byte-swap loop — the read count is rounded down to a whole block (#1254)
* `AudioEndpointVolume.OnVolumeNotification`: fixed per-channel volume notification returning channel 0's volume for every channel — the read pointer was not advanced per channel (#351)
* `MmException`: error messages now append a human-readable description of the `MmResult` via `waveOutGetErrorText`, e.g. `NoDriver calling waveOutSetVolume: No device driver is present` (#1192)
* `Id3v2Tag.ReadTag`: no longer throws and catches a `FormatException` for MP3 streams without an ID3v2 tag — the header check now returns `null` directly (#265)
* `WaveFileReader`: fixed `ArgumentException` reading WAV files whose `fmt` chunk declares more extra (`cbSize`) bytes than the fixed 100-byte buffer holds — the surplus is now discarded instead of throwing (#482)
* `MediaFoundationTransform`: cleanup `finally` blocks no longer leak COM objects when `Unlock`/`RemoveAllBuffers` fails — hresults are captured and thrown only after every buffer/sample has been released (#1293)
* `ResamplerDmoStream`: fixed infinite loop on `Read` after setting `Position`, and the loss of the resampler kernel's tail samples (~32 at the default quality of 30) when the input reaches end-of-stream. The DMO is now drained via `ProcessOutput` after `Discontinuity` — on seek the drained bytes are discarded so playback resumes from the new position, on EOS they're returned to the caller and subsequent reads return 0 cleanly (#607, #608)
* Named the background threads created by `DirectSoundOut`, `WasapiOut`, `WasapiCapture`, `WasapiPlayer`, and `WasapiRecorder` so they show meaningful names in debuggers and profilers (#557)
#### Modernisation (Native AOT, source-generated COM)
* `NAudio.Core`, `NAudio.Midi`, and `NAudio.Wasapi` are now `IsAotCompatible=true`. AOT compatibility is enforced at build-time by `NAudioAotSmokeTest`, which fails CI on any new trim or AOT analyzer warning
* Most COM interop migrated from `[ComImport]` to `[GeneratedComInterface]` / `ComWrappers`. Affected interfaces include the WASAPI / Core Audio activation chain (`IActivateAudioInterfaceCompletionHandler`, `IMMNotificationClient`, `IAudioSessionNotification`, `IAudioSessionEvents`, `IAudioEndpointVolumeCallback`, `IAgileObject`, `IPropertyStore`), the Media Foundation cascade, the DMO interfaces, DirectSound, and the `ComStream` CCW (now source-generated `IStream`)
* `Connector.ConnectTo`: fixed a source-generated COM leftover — it now projects the target connector via `ComWrappers` instead of `Marshal.GetComInterfaceForObject`, which is unsupported for `[GeneratedComInterface]` types and would fail at runtime (SYSLIB1099) (#1311)
* DirectSound P/Invokes migrated to `[LibraryImport]` with `[UnmanagedCallersOnly]` thunks; `BufferDescription` and `BufferCaps` converted from class to struct
* `AcmDriver` ported from legacy `NativeMethods` to `NativeLibrary`
* Most `MediaFoundationInterop` blittable P/Invokes migrated to `[LibraryImport]`
#### Packaging and dependencies
* Each NAudio package now ships its own README in the NuGet payload
* Each NAudio package now embeds an SPDX 2.2 Software Bill of Materials (SBOM) under `/_manifest/spdx_2.2/` in its `.nupkg`, generated at pack time via `Microsoft.Sbom.Targets`
* Test project migrated from VSTest to `Microsoft.Testing.Platform`
* `NAudioTests` split into `NAudio.Core.Tests` (cross-platform, `net10.0`) and `NAudio.Windows.Tests` (Windows-only, `net10.0-windows`) — eliminates the dual-TFM double-run on Windows CI and lets non-Windows devs run just the cross-platform suite
* `NAudio.Alsa.Tests` and `NAudio.SoundFile.Tests` now ignore MTP exit codes 8/9 so `dotnet test` succeeds on machines where the suite legitimately runs zero tests (ALSA off-Linux) or self-skips (libsndfile absent)
* Migrated to the modern `.slnx` solution format
* Renamed `license.txt` to `LICENSE` for GitHub license detection; refreshed copyright year to 2008–2026
* Added per-package `<Description>` metadata to every shipping NAudio NuGet package so each clearly identifies itself as part of the NAudio family
* Added a DocFX documentation site (tutorials + API reference) published to GitHub Pages, built automatically from `Docs/` and the source XML comments
* Fixed the published API reference dropping the cross-platform namespaces (`NAudio.Effects`, `NAudio.Dsp`, `NAudio.Codecs`, `NAudio.SoundFont`, etc.) from the navigation — DocFX's two metadata blocks both wrote to the same destination, so the second overwrote the first's table of contents. The projects are now documented from a single metadata block