NAudio.Alsa
3.0.0-preview.9
Prefix Reserved
dotnet add package NAudio.Alsa --version 3.0.0-preview.9
NuGet\Install-Package NAudio.Alsa -Version 3.0.0-preview.9
<PackageReference Include="NAudio.Alsa" Version="3.0.0-preview.9" />
<PackageVersion Include="NAudio.Alsa" Version="3.0.0-preview.9" />
<PackageReference Include="NAudio.Alsa" />
paket add NAudio.Alsa --version 3.0.0-preview.9
#r "nuget: NAudio.Alsa, 3.0.0-preview.9"
#:package NAudio.Alsa@3.0.0-preview.9
#addin nuget:?package=NAudio.Alsa&version=3.0.0-preview.9&prerelease
#tool nuget:?package=NAudio.Alsa&version=3.0.0-preview.9&prerelease
NAudio.Alsa
ALSA playback and capture for NAudio on Linux.
This package provides:
| Type | Role |
|---|---|
AlsaOut |
IWavePlayer — play any NAudio IWaveProvider through ALSA |
AlsaIn |
IWaveIn — record from an ALSA capture device |
AlsaDeviceEnumerator |
list playback / capture devices (AlsaDeviceInfo) |
AlsaException |
thrown on libasound errors (exposes ErrorCode) |
Platform
Linux only — the assembly is marked [SupportedOSPlatform("linux")]. It
P/Invokes libasound; the runtime SONAME libasound.so.2 is resolved
automatically (you do not need the -dev package). Install the ALSA
runtime if it is missing:
sudo apt install libasound2t64 # Ubuntu 24.04+ (renamed from libasound2 in the t64 transition)
sudo apt install libasound2 # older Debian/Ubuntu
This package is not pulled in by the NAudio meta-package (there is
no net9.0-linux TFM). Reference it explicitly:
dotnet add package NAudio.Alsa
Supported input formats
AlsaOut plays any IWaveProvider, so it is format-agnostic — what you
can play depends on which decoder you feed it. MediaFoundationReader
and the bundled Mp3FileReader / AudioFileReader are Windows-only, but
the cross-platform NAudio.SoundFile
package (libsndfile) decodes the compressed/free codecs on Linux:
| Format | Reader | Status |
|---|---|---|
| WAV (PCM / IEEE float) | WaveFileReader |
✅ supported |
| AIFF (uncompressed PCM) | AiffFileReader |
✅ supported |
| Raw PCM | RawSourceWaveStream |
✅ supported |
| FLAC / Ogg-Vorbis / Opus | SoundFileReader (NAudio.SoundFile) |
✅ supported (needs system libsndfile) |
| MP3 | SoundFileReader (libsndfile ≥ 1.1), or Mp3FileReaderBase + a managed IMp3FrameDecompressor (e.g. NLayer) |
✅ / ⚠️ |
| AAC / M4A / ALAC / WMA | — | ❌ no cross-platform decoder (FFmpeg territory) |
SoundFileReader is the cross-platform MediaFoundationReader-style
decoder (it is a WaveStream / ISampleProvider); add the
NAudio.SoundFile package and a system libsndfile to play FLAC/Ogg/Opus/
MP3 through AlsaOut. NAudio.SoundFile also encodes those formats,
so it pairs with AlsaIn to capture straight to FLAC/Ogg/Opus.
Play a WAV file
using NAudio.Wave;
using NAudio.Wave.Alsa;
using (var audioFile = new WaveFileReader("test.wav"))
using (var outputDevice = new AlsaOut()) // default device
{
outputDevice.Init(audioFile);
outputDevice.Play();
while (outputDevice.PlaybackState == PlaybackState.Playing)
Thread.Sleep(200);
}
Play FLAC/Ogg/Opus/MP3 with SoundFileReader (cross-platform, needs a
system libsndfile — dotnet add package NAudio.SoundFile):
using NAudio.SoundFile;
using var audioFile = new SoundFileReader("test.flac");
using var output = new AlsaOut();
output.Init(audioFile);
output.Play();
Or play MP3 by wiring a managed decompressor into Mp3FileReaderBase
(no native dependency):
// using NLayer.NAudioSupport; // dotnet add package NLayer.NAudioSupport
using var mp3 = new Mp3FileReaderBase("test.mp3",
waveFormat => new Mp3FrameDecompressor(waveFormat));
using var output = new AlsaOut();
output.Init(mp3);
output.Play();
Record to a WAV file
using NAudio.Wave;
using NAudio.Wave.Alsa;
using var writer = new WaveFileWriter("captured.wav", new WaveFormat(44100, 16, 2));
using var input = new AlsaIn { WaveFormat = writer.WaveFormat };
input.DataAvailable += (s, a) => writer.Write(a.Buffer, 0, a.BytesRecorded);
input.StartRecording();
Thread.Sleep(5000);
input.StopRecording();
Swap WaveFileWriter for NAudio.SoundFile's SoundFileWriter to
capture straight to FLAC/Ogg-Vorbis/Opus instead of WAV.
Enumerate devices
foreach (var d in AlsaDeviceEnumerator.GetPlaybackDevices())
Console.WriteLine($"{d.Name} - {d.Description}");
AlsaDeviceInfo.Name is passed straight to new AlsaOut(name) /
new AlsaIn(name).
Notes
- Output is taken through a
SampleChannel, soAlsaOut.Volumeis a real software gain and mono sources are handled. The device format is negotiated as IEEE float, else 16-bit, else 24-bit PCM. Pause()uses hardware pause where the driver supports it, otherwise it drops and re-prepares the stream on resume.- A dedicated streaming thread does blocking I/O and recovers from xruns; it is always joined before the device handle is closed.
| 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.9)
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.9 | 41 | 5/27/2026 |
| 3.0.0-preview.8 | 56 | 5/22/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`
* `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)
#### 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)
* **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
* **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)
* `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
* `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)
#### 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
* 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