NAudio.SoundFile
3.0.0-preview.8
Prefix Reserved
dotnet add package NAudio.SoundFile --version 3.0.0-preview.8
NuGet\Install-Package NAudio.SoundFile -Version 3.0.0-preview.8
<PackageReference Include="NAudio.SoundFile" Version="3.0.0-preview.8" />
<PackageVersion Include="NAudio.SoundFile" Version="3.0.0-preview.8" />
<PackageReference Include="NAudio.SoundFile" />
paket add NAudio.SoundFile --version 3.0.0-preview.8
#r "nuget: NAudio.SoundFile, 3.0.0-preview.8"
#:package NAudio.SoundFile@3.0.0-preview.8
#addin nuget:?package=NAudio.SoundFile&version=3.0.0-preview.8&prerelease
#tool nuget:?package=NAudio.SoundFile&version=3.0.0-preview.8&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.8)
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.8 | 37 | 5/22/2026 |
| 3.0.0-preview.7 | 35 | 5/21/2026 |
| 3.0.0-preview.6 | 37 | 5/21/2026 |
#### Breaking changes
* `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`
#### 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)
#### Demo apps and Test Harnesses
* **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
* `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.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
* `Mp3FileReader`: fixed false sample-rate-change errors near end of file
* 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)
#### 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`)
* 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
* 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