Draft
Conversation
…ingleInputAs + EnsureFormat
… optimize Swap + rename EnsureFormat
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.
This PR adds a new system to manage encapsulated resources, allowing for automatic disposal of resources without the consumer having to store and dispose of everything.
Users are strongly encouraged to migrate to this system instead of manually disposing of audio resources.
Several helper extension methods and properties have been added to simplify code.
There are many breaking changes, however, most functionality should work when using binaries compiled against v1.
Migration Guide
See the wiki
Important notes
AudioPlayerand audio processors. If you manage a resource yourself, passfalseto methods with anisOwnedparameterWithUnmanagedProviderorWithProviderOwnership, or setOwnsProviderto control whether theAudioPlayershould dispose of the providerIAudioProcessorinterface and its existing implementations. See theProcessorsnamespaceISampleProviderandIDisposableProcessorChainclass (also available with theToCompatibleChainextension method) to stack effects while preserving public access to the original providerMixerclass instead ofMixingSampleProviderAudioQueueclass instead ofConcatenatingSampleProviderStreamAudioProcessorclass instead of managingWaveStreams yourself. Factory methods are available via static extensions or theCreateAudioProcessorandTryCreateAudioProcessorclassesUseFileon anAudioPlayerto have it play a file and dispose of the stream when the provider changes or if the player is destroyed/pooledAudioPlayerextension properties such asCurrentTimeandTotalTimewill work if the player uses aStreamAudioProcessor/RawSourceSampleProvider, or if there's a single mixer input with an aforementioned typeImportant
Obsolete members will be removed after the beta (when v2 is fully released).
Caution
Several
AudioPlayerextension methods and properties rely on getting the single mixer input. This means that either the provider itself has to match, or if the provider is aMixer, there should be exactly one input matching.Mixertakes precedence over theAudioQueuein such scenarios.Tip
Upgrade your project to C# 14 (optional, but encouraged). Add
<LangVersion>14</LangVersion>into aPropertyGroupin your csproj.You will need the .NET 10 SDK.
Example Changes
See the wiki
Changes (breaking)
To reduce ambiguity and breaking changes, old methods have been kept, and the ones using new functionality have received different names.
LoopingRawSampleProviderLoopingWaveProviderConditionalOneTimeDisposableRawSourceSampleProvidernow has aLooppropertyStreamAudioProcessorclass and set theLoopproperty (or callWithLoop)SampleProviderExtensions/WaveProviderExtensionsand their methods obsolete in favor of audio processors; if absolutely needed, most methods have been moved toSecretLabNAudio.Core.Extensions.Providers.NonProcessorExtensionsQueue- use theAudioQueueclassBuffer- use aProcessorChain, or call theBufferedSampleProviderconstructorMixWithuse aMixerAudioPlayerExtensionsobsolete:DisposeOnDestroy- encapsulate resources in an audio processor instead, or manage the disposal yourselfMixingSampleProvider-related methods - call the newMixmethodsWithProvidermethods - use audio processors, or callWithUnmanagedProviderif the provider shouldn't be disposed automaticallyBuffer- use aProcessorChainProviderAs- callImmediateProviderAsRawSampleProviderExtensions.Loopobsolete; callWithLoopWaveStreamExtensions.Loopobsolete; create aStreamAudioProcessorinsteadFixes
System.ValueTuple.dllis now included in releases (also as an embedded resource inSecretLabNAudio.dll), this fixes some.oggfiles not being able to loadSpeakerPersonalizationwill no longer throw an exception when changing the speaker settings for a disconnected playerShortClipCacheno longer sets theClipNameof the copy to the providedkeyAudioPlayerPool.Returnno longer throws if passing a destroyed playerAdditions
SpeakerToyGroupand extensionsAudioPlayerproperties:OwnsProviderAlwaysReadAudioPlayerextension properties:Queuegets the singleAudioQueueinputMixersafely casts theSampleProviderCurrentTimeTotalTimeIsLooping(when there's a singleILoopableorISeekableinput)GroupIsGroupedIsGroupControllerIsGroupChildAudioPlayerextension methods:ResumeWithoutProviderWithProviderOwnershipSourceAsMasterAsSingleInputAsto extract a type of processorMixer-related methodsLoopRestart(when there's a singleILoopableorISeekableinput)Usemethods to replace providersMixmethods to add providers to theMixerEnqueuemethods to queue inputs in theAudioQueueCloneOutputand other grouping methodsWithLivePersonalizedSendEngineoverload without theSpeakerPersonalizationcomponent (will use the attached component, or add one to the speaker if needed)SpeakerToyextensions:DestroySafedoesn't throw if the speaker's been destroyedSpeakerToyGroup-related methods and propertiesSpeakerPersonalizationextension methodClearAllOverridesAudioQueueMixerProcessorChainSampleProviderWrapperStreamAudioProcessorCreateAudioProcessorandTryCreateAudioProcessorclassesILoopableandISeekableinterfaces (implemented byStreamAudioProcessorandRawSourceSampleProvider, as well as the now obsoleteLoopingRawSampleProvider)LoopingWaveProvider(obsolete) implementsISeekableSpeakerSettings.GloballyAudiblepropertyClipNamestructShortClipCacheShortClipCachemethods:AddAllFromDirectoryGetSafeGetWaveFormatExtensionsmethods:TimeMatchesIsPooledmethods in pool classesREADMEto the demo projectNote
Extension properties are only available in C# 14 (or newer).
Changes (non-breaking)
AudioPlayer::OnDestroyUnity eventAudioPlayerExtensions.UnsetProviderOnEndnow sets theAlwaysReadproperty instead of subscribing toNoSamplesRead1.1.5