Repository navigation
Bump the nuget group with 2 updates - #33
Merged
tobymarks merged 4 commits intoOct 23, 2026
Merged
Conversation
Bumps NAudio from 2.2.1 to 3.3.0 Bumps NAudio.Wasapi from 2.2.1 to 3.3.0 --- updated-dependencies: - dependency-name: NAudio dependency-version: 3.3.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: nuget - dependency-name: NAudio.Wasapi dependency-version: 3.3.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: nuget ... Signed-off-by: dependabot[bot] <support@github.com>
NAudio 3.0 replaced Read(float[], int, int) with Read(Span<float>) on ISampleProvider, so the mono downmix provider no longer compiled with the 3.3.0 bump. Callers now pass the arrays as spans too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tobymarks
force-pushed
the
dependabot/nuget/windows/src/Inlaut.App/nuget-c59eef05e7
branch
from
October 23, 2026 06:46
766567a to
bd7aa02
Compare
NAudio 3 declares MIT only as a nuspec license expression and no longer ships a license file, so the installer build refused the package. Like sherpa-onnx, its text now comes from a pinned upstream original whose hash packaging verifies. NAudio 3 is split into Core, Midi, Wasapi and WinMM packages, all listed in nuget-packages.json, and NAudio.Core pulls in System.Numerics.Tensors, whose license and notices are copied from the package. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The update test over beta.9 found NAudio.Asio.dll, NAudio.WinForms.dll and the NAudio 2.2.1 license folder left behind: NAudio 3 no longer brings those assemblies and keeps its license in the pinned licenses\naudio. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Updated NAudio from 2.2.1 to 3.3.0.
Release notes
Sourced from NAudio's releases.
3.3.0
A packaging and nullability release. The
NAudiometa-package is now a singlenet9.0package that brings the Windows backends (WinMM and WASAPI) to plainnetX.0projects, so anet10.0console app on Windows gets working MP3decoding and playback rather than a cross-platform subset that threw
NotSupportedException. In exchange it no longer pulls inNAudio.Asio,NAudio.DmoorNAudio.WinForms, which must now be referenced directly ifused.
NAudio.WinMM,NAudio.Asio,NAudio.DmoandNAudio.Vst3likewisenow target plain
net9.0.Every NAudio package is now compiled with nullable reference types enabled.
This is a source-level change with no binary breaks, but projects with
nullable enabled may see new warnings, and a number of members that used to
throw
NullReferenceExceptionnow throwObjectDisposedExceptionorInvalidOperationExceptioninstead.The fixes centre on
WasapiRecorder/WasapiCapturerestarting cleanly afterboth successful and failed starts, buffer and handle lifetime bugs in the
winmm MIDI backend, and frame-aligned seeking in
MediaFoundationReader.NAudiometa-package is now a singlenet9.0package that pulls inNAudio.Core,NAudio.Midi,NAudio.WinMMandNAudio.Wasapion every target framework. A plainnetX.0project on Windows (e.g. a console app onnet10.0) now getsMp3FileReader,WaveOut,WasapiPlayerand anAudioFileReaderthat reads MP3, where previously it silently got a cross-platform subset that threwNotSupportedException(#1472). It no longer includesNAudio.Asio,NAudio.DmoorNAudio.WinForms: add those packages if you useAsioOut/AsioDevice,DirectSoundOutor the DMO effects, orWaveOutWindow/WaveInWindow/theNAudio.Guicontrols.AudioFileReadernow chooses its Media Foundation/ACM paths at runtime, and off Windows itsNotSupportedExceptionmessages point toNAudio.SoundFile.NAudio.Extrasis now single-targetnet9.0, withAudioPlaybackEnginemarked Windows-only (#1485)NAudio.WinMM,NAudio.Asio,NAudio.DmoandNAudio.Vst3now target plainnet9.0instead ofnet9.0-windows, matchingNAudio.Wasapi. They remain Windows-only, enforced by[SupportedOSPlatform("windows")], but can now be referenced directly from a plainnetX.0project (calls showCA1416warnings unless guarded or the project is marked Windows-only) and built on Linux/macOS withoutEnableWindowsTargeting. No change for projects targetingnetX.0-windows(#1482)NAudio.Coreis now compiled with nullable reference types enabled, so its public API carries nullability annotations (e.g.WaveFileReader.ReadNextSampleFrameandMp3Frame.LoadFromStreamreturn nullable types, andMp3Frame.RawDataisbyte[]?when a frame is read without its data). This is a source-level change only: there are no binary breaks, but projects with nullable enabled may see new warnings, and overrides of NAudio.Core virtual members may need matching annotations.XingHeader.LoadXingHeadernow returnsnullfor a frame read without its data instead of throwing. Thanks to @Seb-stian (#1452)NAudio.Midiis now also compiled with nullable reference types enabled (e.g.MidiInMessageEventArgs.MidiEventandNoteOnEvent.OffEventare nullable). Source-level change only; projects with nullable enabled may see new warnings.MidiEvent.ReadNextEventnow throwsFormatExceptioninstead ofNullReferenceExceptionfor running status with no previous event, andRawMetaEventtreats null data as empty (#825)NAudio.WinMMis now compiled with nullable reference types enabled (e.g.AcmDriver.FindByShortNameandWaveCapabilitiesHelpers.GetNameFromGuidreturn nullable types, andAcmDriver.ShowFormatChooseDialoghas nullableoutparameters). Source-level change only; projects with nullable enabled may see new warnings.WaveOut.OutputWaveFormatbeforeInitnow throwsInvalidOperationException,AcmStreammembers throwObjectDisposedExceptionafter dispose, andGetNameFromGuidreturns null instead of throwing when the registry key is missing, where each previously threwNullReferenceException(#825)SoundFileTagsfields,SoundFileWriterOptions.TagsandSoundFileException.Functionare nullable, and theTryLoadmethods onWaveSampleLoader/ISfzSampleLoadermarkleftas non-null on success andrightas null for mono). Source-level change only; projects with nullable enabled may see new warnings, and customISfzSampleLoaderimplementations may need matching annotations (#825)WaveViewer.WaveStream,AlsaException.Functionand the control/device events are nullable). Source-level change only; projects with nullable enabled may see new warnings.AlsaOut.OutputWaveFormatandWaveOutWindow.OutputWaveFormatnow throwInvalidOperationExceptionbeforeInit(previously null andNullReferenceExceptionrespectively), andWaveOutWindow.PlaybeforeInitthrowsInvalidOperationExceptioninstead ofNullReferenceException(#825)NAudio.Asiois now compiled with nullable reference types enabled (e.g. the optionalAsioPlaybackOptions.OutputChannels/AsioDuplexOptions.InputChannels, theAsioDevice/AsioOutevents and theAsioDriverExtcallbacks are nullable; required option members such asSourceandProcessorstay non-nullable). Source-level change only; projects with nullable enabled may see new warnings.AsioOutmembers now throwObjectDisposedExceptionafterDisposeandAsioOut.OutputWaveFormatthrowsInvalidOperationExceptionwhen no playback source is initialised, where they previously threwNullReferenceExceptionor returned null (#825)NAudio.Dmois now compiled with nullable reference types enabled (e.g.DirectSoundOut.PlaybackStoppedandDirectSoundDeviceInfo.ModuleNameare nullable). Source-level change only; projects with nullable enabled may see new warnings.DirectSoundOut.OutputWaveFormatnow throwsInvalidOperationExceptionbeforeInitinstead of returning null, and theMediaObjectwrappers,DmoResampler.MediaObject,WindowsMediaMp3Decoder.MediaObjectandDmoOutputDataBuffer.MediaBufferthrowObjectDisposedExceptionafterDisposeinstead of returning null or throwingNullReferenceException(#825)NAudio.CoreAudioApiandNAudio.MediaFoundationtypes are now annotated for nullable reference types (e.g.AudioClient.TryGetAcousticEchoCancellationControl,MMDeviceEnumerator.TryGetDefaultAudioEndpoint,MfSourceReader.ReadSample,PropertyStoreProperty.ValueandPart.AudioVolumeLevel/AudioMute/JackDescriptionare nullable);WasapiOut,WasapiCaptureand the other top-level classes follow in a separate change. Source-level change only; projects with nullable enabled may see new warnings. The CoreAudio and Media Foundation COM wrappers now throwObjectDisposedExceptionwhen used afterDisposeinstead ofNullReferenceException,AudioSessionManager.SessionsthrowsInvalidOperationExceptioninstead of returning null when sessions are unavailable, andAudioSessionControl.AudioMeterInformation/SimpleAudioVolumethrowNotSupportedExceptioninstead of returning null if the session does not expose those interfaces (#825)WasapiOut,WasapiCapture,WasapiPlayer,WasapiRecorder, their builders andMediaFoundationReader/StreamMediaFoundationReader/MediaFoundationEncoderare now annotated too, completing NAudio.Wasapi (e.g.WasapiPlayer/WasapiRecorder.DeviceIdandDeviceFriendlyName,LowLatencyUnavailableReason,WasapiRecorder.AcousticEchoCancellationControl,WasapiPlayer.GetSupportedExclusiveFormat,MediaFoundationEncoder.SelectMediaTypeand the playback/recording events are nullable). Source-level change only; projects with nullable enabled may see new warnings. The WASAPI classes now throwObjectDisposedExceptionwhen used afterDispose, and reportInvalidOperationExceptioninstead ofNullReferenceExceptionthroughPlaybackStoppedwhen playback is started withoutInit(#825)NAudio.MacOSis now compiled with nullable reference types enabled (e.g.AudioSystemObject.DefaultInputDevice/DefaultOutputDevice, theConvertUIDToDevice-style lookups,AudioObject.Owner,AudioDevice.Icon,ExtendedAudioFileReaderSettings.OutputFormat,ExtendedAudioFileWriterSettings.FileType/ProvidingFormatand the player, recorder and property-listener events are nullable). Source-level change only; projects with nullable enabled may see new warnings. Object-list properties such asAudioSystemObject.Devicesnow skip unknown object IDs instead of returning null entries, the parameterlessCoreAudioPlayer/CoreAudioRecorderconstructors throwInvalidOperationExceptioninstead ofArgumentNullExceptionwhen there is no default device, andExtendedAudioFileWritercapturesProvidingFormatwhen created rather than re-reading the settings object on every write (#825)WasapiRecorderandWasapiCapturefailing withAUDCLNT_E_ALREADY_INITIALIZEDwhen restarted after a start that failed late in initialization (e.g. no AEC reference control); the original error is now reported again (#1493)WasapiRecorderandWasapiCapturebeing left in theStartingstate when initialization throws, so laterStartRecordingcalls failed with"Already recording". (#1490)WasapiRecordernot able to re-start after successfully stopping the recorder. (#1479)MidiOut.SendBufferno longer frees a sysex buffer while the driver may still own it,MidiInnow stops input before resetting it, and neither class calls into winmm with a handle it never opened.MidiOut.SendBuffernow blocks until the driver releases the buffer and throwsMmExceptionif the send fails (#1478)MediaFoundationReaderreporting aPositionthat was not a whole number of frames after seeking a compressed file (e.g. MP3 or AAC), up to a frame before the requested position, and aLengththat could include a partial frame. Seeks now round down to a frame boundary and land exactly on it (#1488)3.2.0
A feature and tidy-up release. Its headline is a first preview of macOS
support: the new
NAudio.MacOSpackage wraps Core Audio for playback andrecording, Extended Audio File Services for reading and writing compressed
formats, and AudioConverter for resampling. It ships pre-release only while its
API settles, alongside the stable versions of the other packages. VB.NET users
also get base classes and a guide that keep the NAudio 2 array-based
Readsignature.
Several legacy APIs that have modern replacements are now
[Obsolete], to beremoved in the next major version. The
fixes include
DirectSoundOut, which failed every playback in 3.1.0, andWasapiPlayer/WasapiOutgetting stuck in thePlayingstate after a sourceerror.
NAudio.MacOSpackage ships pre-release only (X.Y.Z-preview.N) while its API settles, so it stays pre-release alongside stable releases of the other packages. Special thanks to @mdcdi1315 (#1325) for the work and the tests. For more information, see the design doc that describes the decisions that helped shape the wrappers. (#1398)SampleProviderBaseandWaveProviderBase, base classes that keep the NAudio 2Read(buffer, offset, count)signature for languages that cannot name aSpan<T>in a method signature, and a Using NAudio from VB.NET guide covering playback, recording and custom providers from VB (#1426)Wave16ToFloatProvider,WaveFloatTo16ProviderandWave32To16Stream(useToSampleProvider()/ToWaveProvider16()),IgnoreDisposeStream(no longer needed),ByteArrayExtensions(use the BCL),MidiMessage(use the typed MIDI events),ResamplerDmoStream/DmoResampler(useMediaFoundationResamplerorWdlResamplingSampleProvider),DmoEffectWaveProviderand theDmo*effects (useNAudio.Effects),AsioOut's recording path (useAsioDevice),WaveFilter, andProgressLog. AddedAsioOut.IsSupported()and deprecated the lowercaseisSupported()(#1466)WaveFileReader.ReadNextSampleFramein favour ofToSampleProvider(), which supports more formats and doesn't allocate an array per sample frame (#1465)ReadOnlySpan<byte>overloads ofWaveFileWriter.AddChunkandChunkIdentifier.ChunkIdentifierToInt32, and fixedWaveChunks.GetDataleaving the stream position changed when a read fails.ChunkIdentifierToInt32now throwsArgumentOutOfRangeExceptionfor identifiers that aren't four bytes (#1457)DirectSoundOutfailing every playback withDirectSoundException 0x80004001(or anArgumentExceptionfor a format with extra data, e.g. one read from a WAV byWaveFileReader): the secondary buffer'sWAVEFORMATEXwas still a GCHandle-pinnedWaveFormatinstance — a site missed in the #1432 marshalling conversion, sinceWaveFormatno longer carries[StructLayout]— and now marshals viaWaveFormat.MarshalToPtr(#1456)WasapiPlayerandWasapiOutbeing stranded in thePlayingstate, unable to play again, when the source'sReadthrew or the source ended before the first buffer was filled (#1442)WaveFileWriter.WriteSampleandWriteSamples(short[])throwing for plain (non-extensible) 32-bit integer PCM formats (#1463)WaveFileReader.ReadNextSampleFramenow throwsInvalidDataExceptionfor a WAV header with an invalid channel count or bit depth (#1464)WaveStream.CurrentTimesetter to clamp to the bounds of the stream, and corrected the XML documentation for the core audio interfaces (#1441)CoreAudioPlayerandCoreAudioRecordernon-interleaved path, used for devices that expose one mono stream per channel; the recorder now also drains buffered audio when stopped, and non-interleaved streams carrying more than one channel are rejected explicitly (preview) (#1461)ExtendedAudioFileServicesReader.CurrentTimeandTotalTimeon macOS now throwObjectDisposedExceptionafter the reader is disposed, rather than a native exception (preview) (#1451)3.1.0
A correctness release, with Native AOT as the theme. NAudio's remaining
[StructLayout]interop types —WAVEHDR,ACMSTREAMHEADERandWaveFormatitself — were passed to native code by value, which CoreCLR pins in place but
the AOT marshaller copies into a per-call temporary. Anything the driver or
codec wrote back was silently discarded, so
WaveIn/WaveOut, ACM conversion(and with it
Mp3FileReaderandAudioFileReader) and every WASAPI, MediaFoundation and DMO format negotiation were broken in an AOT-published app while
building and running cleanly. Those paths now marshal by hand into stable
unmanaged blocks, and
NAudio.WinMMjoins the AOT-compatible package set.The two breaking changes below both fall out of that work. Also fixed are two
3.0.0 regressions —
Mp3FileReaderBaseseeking on files with a Xing/Infoheader, and
WdlResamplingSampleProviderlosing samples when its sourceunder-feeds — and a pair of infinite loops in the WAV parser on corrupt files.
WaveFormatand its subclasses no longer carry[StructLayout], soMarshal.SizeOfandMarshal.PtrToStructureon them now throwArgumentExceptioninstead of silently returning wrong data under Native AOT (Marshal.SizeOf<WaveFormatExtensible>()returned 22 rather than 40, and a decoded format kept its constructor defaults). NAudio itself stopped marshalling these types in 3.1.0; useToWaveFormatExBytes,MarshalToPtrorMarshalFromPtrto cross a native boundary (#1432)AudioClient.IsFormatSupportedandWasapiPlayer.IsFormatSupportednow return the closest-match format asout WaveFormatrather thanout WaveFormatExtensible. WASAPI documents this format as either aWAVEFORMATEXor aWAVEFORMATEXTENSIBLE, and the old signature could only represent the latter — a plain format was previously decoded as aWaveFormatExtensiblewhose base fields were valid but whose extensible fields were meaningless. Callers needing the extensible fields should pattern-match (#1425)WaveIn/WaveOutfailing under Native AOT withWaveHeaderUnprepared("The wave header was not prepared"). TheWAVEHDRwas a[StructLayout]class passed to winmm by value, which CoreCLR pins in place but NativeAOT copies into a per-call temporary, so the driver'sWHDR_PREPARED/WHDR_DONE/dwBytesRecordedwrites were discarded. It is now a struct in a stable unmanaged block (#1425)WaveFormatConversionStream,AcmStreamand soMp3FileReaderandAudioFileReader.ACMSTREAMHEADERwas a[StructLayout]class passed to msacm32 by value, and the codec keeps private state in the header's reserved fields betweenacmStreamPrepareHeader,acmStreamConvertandacmStreamUnprepareHeader; the AOT marshaller's per-call copy round-trips only the declared fields, so that state was lost and conversion failed. It is now a struct in a stable unmanaged block, asWAVEHDRalready is (#1425)WaveFormat.MarshalToPtrandWaveFormat.MarshalFromPtrcorrupting anyWaveFormatsubclass under Native AOT — the AOT marshaller drops the inheritedWAVEFORMATEXfields of a class hierarchy, so aWaveFormatExtensiblewas written with its SubFormat GUID over the sample rate. Every remaining site that sized or wrote aWaveFormatwithMarshal.SizeOf/StructureToPtrwas converted too: WASAPI (AudioClient), Media Foundation (MFInitMediaTypeFromWaveFormatEx, reachable fromMediaFoundationResampler/MediaFoundationEncoder), DMO (DmoMediaType.SetWaveFormat,MediaObject) and ACM (AcmStream,AcmDriver) (#1425)WaveFormat.MarshalToPtrnow always allocates at least the18 + cbSizebytes it advertises. AWaveFormatsubclass that declaresextraSizebut doesn't write it inSerializepreviously produced a block shorter than its owncbSize, which a native consumer would read past (#1425)WaveFormat.ToWaveFormatExBytes(), which renders aWaveFormatas a native WAVEFORMATEX byte array.MarshalToPtris now a thin wrapper over it, for callers who need an unmanaged block rather than a buffer they already own (#1425)Serializeoverride toMp3WaveFormat, which previously advertisedcbSize= 12 but wrote none of its 12 MPEGLAYER3WAVEFORMAT extra bytes (#1425)WaveFormatExtraDatanow sizes its buffer fromcbSizeinstead of holding a fixed 100-byte array, so a fmt chunk declaring more than 100 bytes of extra data keeps it rather than having all of it discarded (#482). The fixed size existed only because[MarshalAs(ByValArray, SizeConst = 100)]needed a compile-time length.ExtraDatais now exactlyExtraSizebytes long rather than always 100 (#1432)NAudio.WinMMis now markedIsAotCompatible, and the AOT smoke test covers the winmm WAVEHDR/WAVEFORMATEX paths (#1425)Mp3FileReaderBaseseeking silently restarting playback from the beginning of the file on MP3s with a Xing/Info header — the lazy frame index was gated onIsLengthExact, which such a header sets without any frame having been scanned. Also fixed seeks landing on the wrong frame when the target fell exactly on a frame boundary, and Xing/Info header frames being indexed as audio (shifting every seek in those files ~26 ms early). A 3.0.0 regression (#1419)WdlResamplingSampleProviderlosing samples, and eventually returning 0 permanently, when asked for more output than the source could supply — a 3.0.0 regression that broke the common pattern of reading generously from aBufferedWaveProvider-backed capture chain.WdlResampler.ResampleOutalso no longer drifts in input-driven (feed) mode when handed fewer samples thanResamplePreparerequested (#1412)ds64chunk with a negativedataChunkLength, or aLIST/adtlsub-chunk with a negative size, made the chunk walk advance by zero bytes per iteration and spin at 100% CPU without throwing. Negative and oversized sizes are now rejected where they are read, and an undersizedds64chunk throwsFormatExceptionrather thanArgumentOutOfRangeException(#1428)NAudioConsoleTestWASAPI exclusive-mode quick scan reporting no supported formats at all on devices that support plenty — it built its probe formats with an emptyWAVEFORMATEXTENSIBLEchannel mask, which drivers such as Realtek reject outright. It now probes with the canonical layout for the channel count, the same mask the library's own format adaptation uses (#1431)3.0.1
A patch release. The headline fix is packaging: the
NAudioandNAudio.Extrasmeta-packages now ship a plain
net9.0-windowsleg, so WinForms and WPF projectstargeting
netX.0-windowsget the full Windows stack again.AudioFileReadernow throwsNotSupportedExceptioninstead ofInvalidOperationExceptionwhen the cross-platform build is asked for a format it cannot read, and the messages simply state that rather than suggesting anNAudio.Wasapiinstall that could never have helped (#1407)NAudioandNAudio.Extrasmeta-packages resolving their portablenet9.0asset on projects targeting a plainnetX.0-windowsTFM (the WinForms/WPF template default), which silently dropped the entire Windows stack — noWaveOut, WASAPI, Media Foundation, ASIO, DMO or WinForms types, andAudioFileReaderthrowing "MP3 file reading requires the NAudio.Wasapi package". Both packages now also ship a plainnet9.0-windowsleg (#1407)netX.0-windowsTFM may now seeCA1416warnings when calling WASAPI process-loopback capture. The warning is correct — those callers do need anOperatingSystem.IsWindowsVersionAtLeast(10, 0, 19041)guard — and was previously hidden because the only Windows asset available already implied that floor (#1407)AiffFileReaderreporting too long aLengthand throwingIndexOutOfRangeExceptionwhen the SSND chunk declares a non-zero offset (#1405)AiffFileReader.ReadthrowingIndexOutOfRangeExceptionwhen the source stream returns fewer bytes than requested (#1405)3.0.0
NAudio 3 is a major release. The single
NAudioassembly is now split intofocused, independently usable packages; the minimum target framework moves to
net9.0; the core is cross-platform and Native-AOT compatible; and severallarge 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, renameWaveOutEventtoWaveOut, and adjust customproviders to the new
Span<T>Readsignature.Packages and platform
net9.0— legacy .NET Framework and .NET Standard 2.0 support is droppedNAudiois now a set of focused packages:NAudio.Core,NAudio.Midi,NAudio.WinMM,NAudio.Wasapi,NAudio.Asio,NAudio.Dmo,NAudio.WinForms, plus the newNAudio.Effects(shipped inNAudio.Core),NAudio.Sampler,NAudio.Vst3,NAudio.AlsaandNAudio.SoundFile. TheNAudiometa-package still pulls the Windows stack together, so existing consumers see no change. SeeDocs/Architecture/NAudio3AssemblyLayoutPlan.mdNAudio.Core,NAudio.Midi,NAudio.Wasapi,NAudio.Dmo,NAudio.Sampler,NAudio.SoundFileandNAudio.Alsaare Native-AOT compatible (IsAotCompatible=true), enforced in CI byNAudioAotSmokeTestNAudio.Wasapitargets plainnet9.0(Windows-only at runtime via[SupportedOSPlatform("windows")]), so cross-platform apps can reference it and build on Linux/macOS withoutEnableWindowsTargeting. The WinRT MIDI backend moved toNAudio.Midi, which now dual-targetsnet9.0;net9.0-windows10.0.19041.0(#1384)NAudio.Uappackage is removed — useWasapiPlayerBuilder/WasapiRecorderBuilder.snupkgsymbol packages and an embedded SPDX SBOMNew capabilities
Each new subsystem has its own tutorial or README; only the headline is listed here.
NAudio.Effectsframework:IAudioEffect/EffectSampleProvider/EffectChainwith 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.mdWasapiPlayer/WasapiRecorder, built viaWasapiPlayerBuilder/WasapiRecorderBuilder:IAudioClient3low 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.mdAsioDevicereplacingAsioOut: explicit playback/recording/duplex modes, non-contiguous channels, per-channelSpan<float>callbacks, driver-reset recovery and per-buffer timing.AsioOutis preserved as a facade. See Docs/AsioMigration.mdNAudio.SoundFilepackage: 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)NAudio.Alsapackage:AlsaOut(IWavePlayer) andAlsaIn(IWaveIn) plusAlsaDeviceEnumerator, backed bylibasound. See Docs/PlayAudioFileLinuxAlsa.md and Docs/RecordAudioFileLinuxAlsa.md (#1182)NAudio.Vst3package (Windows-only): discover, load and host VST 3 effects and instruments, with parameters, state and.vstpresetpresets, native editor windows, program lists/units, latency compensation, and live/offline MIDI-file playback through the shared MIDI pipeline. See theNAudio.Vst3README andDocs/Architecture/Vst3Hosting.md. VST is a registered trademark of Steinberg Media Technologies GmbHNAudio.Samplerpackage: polyphonic, cross-platform playback of SoundFont (.sf2) and SFZ instruments and single-sample instruments, rendered as anISampleProvider(SF2 modulator engine, DAHDSR envelopes, LFOs, modulated filters, reverb/chorus sends, voice stealing, choke groups). See Docs/Sampler.mdMMDeviceEnumerator.CreateNotificationClient()returns anMMDeviceNotificationClientexposingDeviceStateChanged,DeviceAdded,DeviceRemoved,DefaultDeviceChangedandPropertyValueChangedas ordinary events, so callers no longer implement a COM interface or manage CCW lifetime (#1395)NAudio.Midi's portable leg is now cross-platform; new WinRTWinRTMidiIn/WinRTMidiOutand backend-agnosticIMidiInput/IMidiOutput; and a newIMidiInstrumentseam (MidiFileSequence/SequencedMidiPlayer/OfflineMidiRenderer/LiveMidiInstrument) giving an end-to-end MIDI-file → audio pipeline that drives the sampler or a hosted VST 3 instrument.MidiFilealso reads RIFF-RMID (.rmi) files (#1236) andMidiFile.Exportgains aStreamoverload, thanks to @MaKiPL (#499)NAudio.Sequencingnamespace inNAudio.Core(tempo and time-signature maps, transport,EventTimeline, swing, and a sample-accurate per-buffer dispatcher) underpinning MIDI-file playback and the sampler. SeeDocs/Architecture/Sequencing.mdNAudio.ExtrashelpersCaptureMixerInputandRealtimeCaptureMixercapture 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)AudioFileReaderandCachedSoundgainStreamconstructors, 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).StreamMediaFoundationReaderalso gains optionalcontentType/originNamehints and Ogg container sniffing (#952)WaveFileReader.Chunkswith anIWaveChunkInterpreter<T>extension point and built-in interpreters for cue lists, BWFbext(BroadcastExtension, now read and write, with v2 loudness) and LIST/INFO (InfoMetadata);WaveFileWritergainsAddCue,WriteCueList,WriteBroadcastExtension, arbitraryAddChunkand RF64 promotion viaWaveFileWriterOptions(#1013)IWaveLatencyinterface inNAudio.CoreexposingAverageLatency/CurrentLatencyfor A/V sync and drift detection, implemented across the playback and capture classes (#601)ChannelMixerSampleProviderwith ready-madeChannelMixMatrixroutings, thanks to @antiduh (#982); a newFftProcessor;Span<T>overloads across the codec/DSP surface; reusable building blocks (EnvelopeFollower,DelayLine,Lfo,Oversampler,LinkwitzRileyCrossover,PartitionedConvolver, …); plus improvements toSmbPitchShiftingSampleProvider(#922),AdsrSampleProvider(#671) andFadeInOutSampleProvider(#1136)ValidBitsPerSample/ChannelMask, and a[Flags] Speakersenum for building channel masks (#1325)AudioSessionControl.SetDuckingPreference(bool)(#760);WasapiPlayer/WasapiRecorderexposeDeviceIdandDeviceFriendlyNamefor 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:
net9.0(legacy .NET Framework / .NET Standard 2.0 dropped)IWaveProvider.Read/ISampleProvider.Readnow take a singleSpan<byte>/Span<float>(was buffer/offset/count) — callers migrate viasource.Read(buffer.AsSpan(offset, count)); implementations override the span method... (truncated)
2.4.0
DeviceCountandGetCapabilitiesstatic methods toWaveOutEventso outputdevices can be enumerated without referencing
NAudio.WinForms(#1331, #777)formatted class parameters as COM interfaces; they are now explicitly marked
[MarshalAs(UnmanagedType.LPStruct)](#1414)2.3.0
PropertyStoreand Core Audio property access (#1206)WasapiCapturefrom using exclusive mode (#1122)WaveFileChunkReader.ReadWaveHeader(#1231)PropVariantnow supportsVT_EMPTYby returningnull(#1071)AcmStream.Convert(#1108)AcmStreamHeaderfinalizer crash with corrupted data (#1199)net6.0targets forNAudio.AsioandNAudio.WinMMto remove registry dependency (#1139)Commits viewable in compare view.
Updated NAudio.Wasapi from 2.2.1 to 3.3.0.
Release notes
Sourced from NAudio.Wasapi's releases.
3.3.0
A packaging and nullability release. The
NAudiometa-package is now a singlenet9.0package that brings the Windows backends (WinMM and WASAPI) to plainnetX.0projects, so anet10.0console app on Windows gets working MP3decoding and playback rather than a cross-platform subset that threw
NotSupportedException. In exchange it no longer pulls inNAudio.Asio,NAudio.DmoorNAudio.WinForms, which must now be referenced directly ifused.
NAudio.WinMM,NAudio.Asio,NAudio.DmoandNAudio.Vst3likewisenow target plain
net9.0.Every NAudio package is now compiled with nullable reference types enabled.
This is a source-level change with no binary breaks, but projects with
nullable enabled may see new warnings, and a number of members that used to
throw
NullReferenceExceptionnow throwObjectDisposedExceptionorInvalidOperationExceptioninstead.The fixes centre on
WasapiRecorder/WasapiCapturerestarting cleanly afterboth successful and failed starts, buffer and handle lifetime bugs in the
winmm MIDI backend, and frame-aligned seeking in
MediaFoundationReader.NAudiometa-package is now a singlenet9.0package that pulls inNAudio.Core,NAudio.Midi,NAudio.WinMMandNAudio.Wasapion every target framework. A plainnetX.0project on Windows (e.g. a console app onnet10.0) now getsMp3FileReader,WaveOut,WasapiPlayerand anAudioFileReaderthat reads MP3, where previously it silently got a cross-platform subset that threwNotSupportedException(#1472). It no longer includesNAudio.Asio,NAudio.DmoorNAudio.WinForms: add those packages if you useAsioOut/AsioDevice,DirectSoundOutor the DMO effects, orWaveOutWindow/WaveInWindow/theNAudio.Guicontrols.AudioFileReadernow chooses its Media Foundation/ACM paths at runtime, and off Windows itsNotSupportedExceptionmessages point toNAudio.SoundFile.NAudio.Extrasis now single-targetnet9.0, withAudioPlaybackEnginemarked Windows-only (#1485)NAudio.WinMM,NAudio.Asio,NAudio.DmoandNAudio.Vst3now target plainnet9.0instead ofnet9.0-windows, matchingNAudio.Wasapi. They remain Windows-only, enforced by[SupportedOSPlatform("windows")], but can now be referenced directly from a plainnetX.0project (calls showCA1416warnings unless guarded or the project is marked Windows-only) and built on Linux/macOS withoutEnableWindowsTargeting. No change for projects targetingnetX.0-windows(#1482)NAudio.Coreis now compiled with nullable reference types enabled, so its public API carries nullability annotations (e.g.WaveFileReader.ReadNextSampleFrameandMp3Frame.LoadFromStreamreturn nullable types, andMp3Frame.RawDataisbyte[]?when a frame is read without its data). This is a source-level change only: there are no binary breaks, but projects with nullable enabled may see new warnings, and overrides of NAudio.Core virtual members may need matching annotations.XingHeader.LoadXingHeadernow returnsnullfor a frame read without its data instead of throwing. Thanks to @Seb-stian (#1452)NAudio.Midiis now also compiled with nullable reference types enabled (e.g.MidiInMessageEventArgs.MidiEventandNoteOnEvent.OffEventare nullable). Source-level change only; projects with nullable enabled may see new warnings.MidiEvent.ReadNextEventnow throwsFormatExceptioninstead ofNullReferenceExceptionfor running status with no previous event, andRawMetaEventtreats null data as empty (#825)NAudio.WinMMis now compiled with nullable reference types enabled (e.g.AcmDriver.FindByShortNameandWaveCapabilitiesHelpers.GetNameFromGuidreturn nullable types, andAcmDriver.ShowFormatChooseDialoghas nullableoutparameters). Source-level change only; projects with nullable enabled may see new warnings.WaveOut.OutputWaveFormatbeforeInitnow throwsInvalidOperationException,AcmStreammembers throwObjectDisposedExceptionafter dispose, andGetNameFromGuidreturns null instead of throwing when the registry key is missing, where each previously threwNullReferenceException(#825)SoundFileTagsfields,SoundFileWriterOptions.TagsandSoundFileException.Functionare nullable, and theTryLoadmethods onWaveSampleLoader/ISfzSampleLoadermarkleftas non-null on success andrightas null for mono). Source-level change only; projects with nullable enabled may see new warnings, and customISfzSampleLoaderimplementations may need matching annotations (#825)WaveViewer.WaveStream,AlsaException.Functionand the control/device events are nullable). Source-level change only; projects with nullable enabled may see new warnings.AlsaOut.OutputWaveFormatandWaveOutWindow.OutputWaveFormatnow throwInvalidOperationExceptionbeforeInit(previously null andNullReferenceExceptionrespectively), andWaveOutWindow.PlaybeforeInitthrowsInvalidOperationExceptioninstead ofNullReferenceException(#825)NAudio.Asiois now compiled with nullable reference types enabled (e.g. the optionalAsioPlaybackOptions.OutputChannels/AsioDuplexOptions.InputChannels, theAsioDevice/AsioOutevents and theAsioDriverExtcallbacks are nullable; required option members such asSourceandProcessorstay non-nullable). Source-level change only; projects with nullable enabled may see new warnings.AsioOutmembers now throwObjectDisposedExceptionafterDisposeandAsioOut.OutputWaveFormatthrowsInvalidOperationExceptionwhen no playback source is initialised, where they previously threwNullReferenceExceptionor returned null (#825)NAudio.Dmois now compiled with nullable reference types enabled (e.g.DirectSoundOut.PlaybackStoppedandDirectSoundDeviceInfo.ModuleNameare nullable). Source-level change only; projects with nullable enabled may see new warnings.DirectSoundOut.OutputWaveFormatnow throwsInvalidOperationExceptionbeforeInitinstead of returning null, and theMediaObjectwrappers,DmoResampler.MediaObject,WindowsMediaMp3Decoder.MediaObjectandDmoOutputDataBuffer.MediaBufferthrowObjectDisposedExceptionafterDisposeinstead of returning null or throwingNullReferenceException(#825)NAudio.CoreAudioApiandNAudio.MediaFoundationtypes are now annotated for nullable reference types (e.g.AudioClient.TryGetAcousticEchoCancellationControl,MMDeviceEnumerator.TryGetDefaultAudioEndpoint,MfSourceReader.ReadSample,PropertyStoreProperty.ValueandPart.AudioVolumeLevel/AudioMute/JackDescriptionare nullable);WasapiOut,WasapiCaptureand the other top-level classes follow in a separate change. Source-level change only; projects with nullable enabled may see new warnings. The CoreAudio and Media Foundation COM wrappers now throwObjectDisposedExceptionwhen used afterDisposeinstead ofNullReferenceException,AudioSessionManager.SessionsthrowsInvalidOperationExceptioninstead of returning null when sessions are unavailable, andAudioSessionControl.AudioMeterInformation/SimpleAudioVolumethrowNotSupportedExceptioninstead of returning null if the session does not expose those interfaces (#825)WasapiOut,WasapiCapture,WasapiPlayer,WasapiRecorder, their builders andMediaFoundationReader/StreamMediaFoundationReader/MediaFoundationEncoderare now annotated too, completing NAudio.Wasapi (e.g.WasapiPlayer/WasapiRecorder.DeviceIdandDeviceFriendlyName,LowLatencyUnavailableReason,WasapiRecorder.AcousticEchoCancellationControl,WasapiPlayer.GetSupportedExclusiveFormat,MediaFoundationEncoder.SelectMediaTypeand the playback/recording events are nullable). Source-level change only; projects with nullable enabled may see new warnings. The WASAPI classes now throwObjectDisposedExceptionwhen used afterDispose, and reportInvalidOperationExceptioninstead ofNullReferenceExceptionthroughPlaybackStoppedwhen playback is started withoutInit(#825)NAudio.MacOSis now compiled with nullable reference types enabled (e.g.AudioSystemObject.DefaultInputDevice/DefaultOutputDevice, theConvertUIDToDevice-style lookups,AudioObject.Owner,AudioDevice.Icon,ExtendedAudioFileReaderSettings.OutputFormat,ExtendedAudioFileWriterSettings.FileType/ProvidingFormatand the player, recorder and property-listener events are nullable). Source-level change only; projects with nullable enabled may see new warnings. Object-list properties such asAudioSystemObject.Devicesnow skip unknown object IDs instead of returning null entries, the parameterlessCoreAudioPlayer/CoreAudioRecorderconstructors throwInvalidOperationExceptioninstead ofArgumentNullExceptionwhen there is no default device, andExtendedAudioFileWritercapturesProvidingFormatwhen created rather than re-reading the settings object on every write (#825)WasapiRecorderandWasapiCapturefailing withAUDCLNT_E_ALREADY_INITIALIZEDwhen restarted after a start that failed late in initialization (e.g. no AEC reference control); the original error is now reported again (#1493)WasapiRecorderandWasapiCapturebeing left in theStartingstate when initialization throws, so laterStartRecordingcalls failed with"Already recording". (#1490)WasapiRecordernot able to re-start after successfully stopping the recorder. (#1479)MidiOut.SendBufferno longer frees a sysex buffer while the driver may still own it,MidiInnow stops input before resetting it, and neither class calls into winmm with a handle it never opened.MidiOut.SendBuffernow blocks until the driver releases the buffer and throwsMmExceptionif the send fails (#1478)MediaFoundationReaderreporting aPositionthat was not a whole number of frames after seeking a compressed file (e.g. MP3 or AAC), up to a frame before the requested position, and aLengththat could include a partial frame. Seeks now round down to a frame boundary and land exactly on it (#1488)3.2.0
A feature and tidy-up release. Its headline is a first preview of macOS
support: the new
NAudio.MacOSpackage wraps Core Audio for playback andrecording, Extended Audio File Services for reading and writing compressed
formats, and AudioConverter for resampling. It ships pre-release only while its
API settles, alongside the stable versions of the other packages. VB.NET users
also get base classes and a guide that keep the NAudio 2 array-based
Readsignature.
Several legacy APIs that have modern replacements are now
[Obsolete], to beremoved in the next major version. The
fixes include
DirectSoundOut, which failed every playback in 3.1.0, andWasapiPlayer/WasapiOutgetting stuck in thePlayingstate after a sourceerror.
NAudio.MacOSpackage ships pre-release only (X.Y.Z-preview.N) while its API settles, so it stays pre-release alongside stable releases of the other packages. Special thanks to @mdcdi1315 (#1325) for the work and the tests. For more information, see the design doc that describes the decisions that helped shape the wrappers. (#1398)SampleProviderBaseandWaveProviderBase, base classes that keep the NAudio 2Read(buffer, offset, count)signature for languages that cannot name aSpan<T>in a method signature, and a Using NAudio from VB.NET guide covering playback, recording and custom providers from VB (#1426)Wave16ToFloatProvider,WaveFloatTo16ProviderandWave32To16Stream(useToSampleProvider()/ToWaveProvider16()),IgnoreDisposeStream(no longer needed),ByteArrayExtensions(use the BCL),MidiMessage(use the typed MIDI events),ResamplerDmoStream/DmoResampler(useMediaFoundationResamplerorWdlResamplingSampleProvider),DmoEffectWaveProviderand theDmo*effects (useNAudio.Effects),AsioOut's recording path (useAsioDevice),WaveFilter, andProgressLog. AddedAsioOut.IsSupported()and deprecated the lowercaseisSupported()(#1466)WaveFileReader.ReadNextSampleFramein favour ofToSampleProvider(), which supports more formats and doesn't allocate an array per sample frame (#1465)ReadOnlySpan<byte>overloads ofWaveFileWriter.AddChunkandChunkIdentifier.ChunkIdentifierToInt32, and fixedWaveChunks.GetDataleaving the stream position changed when a read fails.ChunkIdentifierToInt32now throwsArgumentOutOfRangeExceptionfor identifiers that aren't four bytes (#1457)DirectSoundOutfailing every playback withDirectSoundException 0x80004001(or anArgumentExceptionfor a format with extra data, e.g. one read from a WAV byWaveFileReader): the secondary buffer'sWAVEFORMATEXwas still a GCHandle-pinnedWaveFormatinstance — a site missed in the #1432 marshalling conversion, sinceWaveFormatno longer carries[StructLayout]— and now marshals viaWaveFormat.MarshalToPtr(#1456)WasapiPlayerandWasapiOutbeing stranded in thePlayingstate, unable to play again, when the source'sReadthrew or the source ended before the first buffer was filled (#1442)WaveFileWriter.WriteSampleandWriteSamples(short[])throwing for plain (non-extensible) 32-bit integer PCM formats (#1463)WaveFileReader.ReadNextSampleFramenow throwsInvalidDataExceptionfor a WAV header with an invalid channel count or bit depth (#1464)WaveStream.CurrentTimesetter to clamp to the bounds of the stream, and corrected the XML documentation for the core audio interfaces (#1441)CoreAudioPlayerandCoreAudioRecordernon-interleaved path, used for devices that expose one mono stream per channel; the recorder now also drains buffered audio when stopped, and non-interleaved streams carrying more than one channel are rejected explicitly (preview) (#1461)ExtendedAudioFileServicesReader.CurrentTimeandTotalTimeon macOS now throwObjectDisposedExceptionafter the reader is disposed, rather than a native exception (preview) (#1451)3.1.0
A correctness release, with Native AOT as the theme. NAudio's remaining
[StructLayout]interop types —WAVEHDR,ACMSTREAMHEADERandWaveFormatitself — were passed to native code by value, which CoreCLR pins in place but
the AOT marshaller copies into a per-call temporary. Anything the driver or
codec wrote back was silently discarded, so
WaveIn/WaveOut, ACM conversion(and with it
Mp3FileReaderandAudioFileReader) and every WASAPI, MediaFoundation and DMO format negotiation were broken in an AOT-published app while
building and running cleanly. Those paths now marshal by hand into stable
unmanaged blocks, and
NAudio.WinMMjoins the AOT-compatible package set.The two breaking changes below both fall out of that work. Also fixed are two
3.0.0 regressions —
Mp3FileReaderBaseseeking on files with a Xing/Infoheader, and
WdlResamplingSampleProviderlosing samples when its sourceunder-feeds — and a pair of infinite loops in the WAV parser on corrupt files.
WaveFormatand its subclasses no longer carry[StructLayout], soMarshal.SizeOfandMarshal.PtrToStructureon them now throwArgumentExceptioninstead of silently returning wrong data under Native AOT (Marshal.SizeOf<WaveFormatExtensible>()returned 22 rather than 40, and a decoded format kept its constructor defaults). NAudio itself stopped marshalling these types in 3.1.0; useToWaveFormatExBytes,MarshalToPtrorMarshalFromPtrto cross a native boundary (#1432)AudioClient.IsFormatSupportedandWasapiPlayer.IsFormatSupportednow return the closest-match format asout WaveFormatrather thanout WaveFormatExtensible. WASAPI documents this format as either aWAVEFORMATEXor aWAVEFORMATEXTENSIBLE, and the old signature could only represent the latter — a plain format was previously decoded as aWaveFormatExtensiblewhose base fields were valid but whose extensible fields were meaningless. Callers needing the extensible fields should pattern-match (#1425)WaveIn/WaveOutfailing under Native AOT withWaveHeaderUnprepared("The wave header was not prepared"). TheWAVEHDRwas a[StructLayout]class passed to winmm by value, which CoreCLR pins in place but NativeAOT copies into a per-call temporary, so the driver'sWHDR_PREPARED/WHDR_DONE/dwBytesRecordedwrites were discarded. It is now a struct in a stable unmanaged block (#1425)WaveFormatConversionStream,AcmStreamand soMp3FileReaderandAudioFileReader.ACMSTREAMHEADERwas a[StructLayout]class passed to msacm32 by value, and the codec keeps private state in the header's reserved fields betweenacmStreamPrepareHeader,acmStreamConvertandacmStreamUnprepareHeader; the AOT marshaller's per-call copy round-trips only the declared fields, so that state was lost and conversion failed. It is now a struct in a stable unmanaged block, asWAVEHDRalready is (#1425)WaveFormat.MarshalToPtrandWaveFormat.MarshalFromPtrcorrupting anyWaveFormatsubclass under Native AOT — the AOT marshaller drops the inheritedWAVEFORMATEXfields of a class hierarchy, so aWaveFormatExtensiblewas written with its SubFormat GUID over the sample rate. Every remaining site that sized or wrote aWaveFormatwithMarshal.SizeOf/StructureToPtrwas converted too: WASAPI (AudioClient), Media Foundation (MFInitMediaTypeFromWaveFormatEx, reachable fromMediaFoundationResampler/MediaFoundationEncoder), DMO (DmoMediaType.SetWaveFormat,MediaObject) and ACM (AcmStream,AcmDriver) (#1425)WaveFormat.MarshalToPtrnow always allocates at least the18 + cbSizebytes it advertises. AWaveFormatsubclass that declaresextraSizebut doesn't write it inSerializepreviously produced a block shorter than its owncbSize, which a native consumer would read past (#1425)WaveFormat.ToWaveFormatExBytes(), which renders aWaveFormatas a native WAVEFORMATEX byte array.MarshalToPtris now a thin wrapper over it, for callers who need an unmanaged block rather than a buffer they already own (#1425)Serializeoverride toMp3WaveFormat, which previously advertisedcbSize= 12 but wrote none of its 12 MPEGLAYER3WAVEFORMAT extra bytes (#1425)WaveFormatExtraDatanow sizes its buffer fromcbSizeinstead of holding a fixed 100-byte array, so a fmt chunk declaring more than 100 bytes of extra data keeps it rather than having all of it discarded (#482). The fixed size existed only because[MarshalAs(ByValArray, SizeConst = 100)]needed a compile-time length.ExtraDatais now exactlyExtraSizebytes long rather than always 100 (#1432)NAudio.WinMMis now markedIsAotCompatible, and the AOT smoke test covers the winmm WAVEHDR/WAVEFORMATEX paths (#1425)Mp3FileReaderBaseseeking silently restarting playback from the beginning of the file on MP3s with a Xing/Info header — the lazy frame index was gated onIsLengthExact, which such a header sets without any frame having been scanned. Also fixed seeks landing on the wrong frame when the target fell exactly on a frame boundary, and Xing/Info header frames being indexed as audio (shifting every seek in those files ~26 ms early). A 3.0.0 regression (#1419)WdlResamplingSampleProviderlosing samples, and eventually returning 0 permanently, when asked for more output than the source could supply — a 3.0.0 regression that broke the common pattern of reading generously from aBufferedWaveProvider-backed capture chain.WdlResampler.ResampleOutalso no longer drifts in input-driven (feed) mode when handed fewer samples thanResamplePreparerequested (#1412)ds64chunk with a negativedataChunkLength, or aLIST/adtlsub-chunk with a negative size, made the chunk walk advance by zero bytes per iteration and spin at 100% CPU without throwing. Negative and oversized sizes are now rejected where they are read, and an undersizedds64chunk throwsFormatExceptionrather thanArgumentOutOfRangeException(#1428)NAudioConsoleTestWASAPI exclusive-mode quick scan reporting no supported formats at all on devices that support plenty — it built its probe formats with an emptyWAVEFORMATEXTENSIBLEchannel mask, which drivers such as Realtek reject outright. It now probes with the canonical layout for the channel count, the same mask the library's own format adaptation uses (#1431)3.0.1
A patch release. The headline fix is packaging: the
NAudioandNAudio.Extrasmeta-packages now ship a plain
net9.0-windowsleg, so WinForms and WPF projectstargeting
netX.0-windowsget the full Windows stack again.AudioFileReadernow throwsNotSupportedExceptioninstead ofInvalidOperationExceptionwhen the cross-platform build is asked for a format it cannot read, and the messages simply state that rather than suggesting anNAudio.Wasapiinstall that could never have helped (#1407)NAudioandNAudio.Extrasmeta-packages resolving their portablenet9.0asset on projects targeting a plainnetX.0-windowsTFM (the WinForms/WPF template default), which silently dropped the entire Windows stack — noWaveOut, WASAPI, Media Foundation, ASIO, DMO or WinForms types, andAudioFileReaderthrowing "MP3 file reading requires the NAudio.Wasapi package". Both packages now also ship a plainnet9.0-windowsleg (#1407)netX.0-windowsTFM may now seeCA1416warnings when calling WASAPI process-loopback capture. The warning is correct — those callers do need anOperatingSystem.IsWindowsVersionAtLeast(10, 0, 19041)guard — and was previously hidden because the only Windows asset available already implied that floor (#1407)AiffFileReaderreporting too long aLengthand throwingIndexOutOfRangeExceptionwhen the SSND chunk declares a non-zero offset (#1405)AiffFileReader.ReadthrowingIndexOutOfRangeExceptionwhen the source stream returns fewer bytes than requested (#1405)3.0.0
NAudio 3 is a major release. The single
NAudioassembly is now split intofocused, independently usable packages; the minimum target framework moves to
net9.0; the core is cross-platform and Native-AOT compatible; and severallarge 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, renameWaveOutEventtoWaveOut, and adjust customproviders to the new
Span<T>Readsignature.Packages and platform
net9.0— legacy .NET Framework and .NET Standard 2.0 support is droppedNAudiois now a set of focused packages:NAudio.Core,NAudio.Midi,NAudio.WinMM,NAudio.Wasapi,NAudio.Asio,NAudio.Dmo,NAudio.WinForms, plus the newNAudio.Effects(shipped inNAudio.Core),NAudio.Sampler,NAudio.Vst3,NAudio.AlsaandNAudio.SoundFile. TheNAudiometa-package still pulls the Windows stack together, so existing consumers see no change. SeeDocs/Architecture/NAudio3AssemblyLayoutPlan.mdNAudio.Core,NAudio.Midi,NAudio.Wasapi,NAudio.Dmo,NAudio.Sampler,NAudio.SoundFileandNAudio.Alsaare Native-AOT compatible (IsAotCompatible=true), enforced in CI byNAudioAotSmokeTestNAudio.Wasapitargets plainnet9.0(Windows-only at runtime via[SupportedOSPlatform("windows")]), so cross-platform apps can reference it and build on Linux/macOS withoutEnableWindowsTargeting. The WinRT MIDI backend moved toNAudio.Midi, which now dual-targetsnet9.0;net9.0-windows10.0.19041.0(#1384)NAudio.Uappackage is removed — useWasapiPlayerBuilder/WasapiRecorderBuilder.snupkgsymbol packages and an embedded SPDX SBOMNew capabilities
Each new subsystem has its own tutorial or README; only the headline is listed here.
NAudio.Effectsframework:IAudioEffect/EffectSampleProvider/EffectChainwith 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.mdWasapiPlayer/WasapiRecorder, built viaWasapiPlayerBuilder/WasapiRecorderBuilder:IAudioClient3low 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.mdAsioDevicereplacingAsioOut: explicit playback/recording/duplex modes, non-contiguous channels, per-channelSpan<float>callbacks, driver-reset recovery and per-buffer timing.AsioOutis preserved as a facade. See Docs/AsioMigration.mdNAudio.SoundFilepackage: 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)NAudio.Alsapackage:AlsaOut(IWavePlayer) andAlsaIn(IWaveIn) plusAlsaDeviceEnumerator, backed bylibasound. See Docs/PlayAudioFileLinuxAlsa.md and Docs/RecordAudioFileLinuxAlsa.md (#1182)NAudio.Vst3package (Windows-only): discover, load and host VST 3 effects and instruments, with parameters, state and.vstpresetpresets, native editor windows, program lists/units, latency compensation, and live/offline MIDI-file playback through the shared MIDI pipeline. See theNAudio.Vst3README andDocs/Architecture/Vst3Hosting.md. VST is a registered trademark of Steinberg Media Technologies GmbHNAudio.Samplerpackage: polyphonic, cross-platform playback of SoundFont (.sf2) and SFZ instruments and single-sample instruments, rendered as anISampleProvider(SF2 modulator engine, DAHDSR envelopes, LFOs, modulated filters, reverb/chorus sends, voice stealing, choke groups). See Docs/Sampler.mdMMDeviceEnumerator.CreateNotificationClient()returns anMMDeviceNotificationClientexposingDeviceStateChanged,DeviceAdded,DeviceRemoved,DefaultDeviceChangedandPropertyValueChangedas ordinary events, so callers no longer implement a COM interface or manage CCW lifetime (#1395)NAudio.Midi's portable leg is now cross-platform; new WinRTWinRTMidiIn/WinRTMidiOutand backend-agnosticIMidiInput/IMidiOutput; and a newIMidiInstrumentseam (MidiFileSequence/SequencedMidiPlayer/OfflineMidiRenderer/LiveMidiInstrument) giving an end-to-end MIDI-file → audio pipeline that drives the sampler or a hosted VST 3 instrument.MidiFilealso reads RIFF-RMID (.rmi) files (#1236) andMidiFile.Exportgains aStreamoverload, thanks to @MaKiPL (#499)NAudio.Sequencingnamespace inNAudio.Core(tempo and time-signature maps, transport,EventTimeline, swing, and a sample-accurate per-buffer dispatcher) underpinning MIDI-file playback and the sampler. SeeDocs/Architecture/Sequencing.mdNAudio.ExtrashelpersCaptureMixerInputandRealtimeCaptureMixercapture 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)AudioFileReaderandCachedSoundgainStreamconstructors, 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). `StreamMed...Description has been truncated