PooledPlayback mixin

PooledPlayback

Opt-in audio pooling for instant retrigger/overlap of short sounds. Intended for SFX-style channels that often replay the same clip rapidly.

What it does

  • Keeps a tiny pool of pre-prepared AudioPlayers per sound key.
  • Inherits the channel’s AudioContext so focus/ducking rules match.
  • Supports assets, device files, URLs, and bytes sources.
  • Automatically marks the channel as multi-player capable, so BaseAudioChannel.waitUntilStopped() / playAndWait() will throw (waiting is ambiguous when multiple players can run).

Typical usage

class SfxChannel extends BaseAudioChannel with PooledPlayback {
  SfxChannel() : super('sfx_player');

  @override PlayerMode get playerMode => PlayerMode.lowLatency;
  @override ReleaseMode get releaseMode => ReleaseMode.stop;

  // Make pooling transparent for .play(path)
  @override
  Future<void> play(String path) async {
    await playPooledPath(path, key: path, volume: volume);
  }

  @override
  Future<void> dispose() async {
    await disposePools();  // ← clean pooled players
    return super.dispose();
  }
}

// Configure pooling (optional; defaults shown)
SoundEngine.instance.sfx.enablePooling(
  enabled: true,
  poolSizePerSound: 4,     // max concurrent players for a given sound
  minPlayersPerSound: 1,   // pre-warmed instances per sound
);

// Fire-and-forget retriggers (instant overlaps)
await SoundEngine.instance.sfx.play('assets/sfx/click.mp3');

When to refresh pools

If you change a channel’s AudioContext after some pools were built, call refreshPoolsAudioContext to recreate existing pools with the new context:

await sfx.setAudioContext(newCtx);
await sfx.refreshPoolsAudioContext();

Waiting caveat

Pooling enables concurrent playbacks; a single “wait until stop” has no unambiguous target. The mixin reports concurrency via hasMultipleConcurrentPlayers, so waitUntilStopped / playAndWait will throw UnsupportedError. If you need blocking behavior, disable pooling (globally or for the duration) or use a dedicated non-pooled channel.

Superclass constraints
Mixin applications

Properties

currentAudioContext → AudioContext?
Current audio context getter (nullable if never set).
no setterinherited
hashCode int
The hash code for this object.
no setterinherited
hasMultipleConcurrentPlayers bool
Report concurrency to the base so wait-helpers throw automatically.
no setteroverride
isActive bool
Active Flag
no setterinherited
isMuted bool
Muted Flag
no setterinherited
isPlaying bool
Current Status
no setterinherited
isPoolingEnabled bool
Whether pooling is currently enabled.
no setter
minPlayersPerSound int
Pre-warmed players per sound key.
no setter
onDurationChanged Stream<Duration>
Duration Stream
no setterinherited
onIsPlayingChanged Stream<bool>
Reactive isPlaying Stream
no setterinherited
onPlayerComplete Stream<void>
Completion Event
no setterinherited
onPositionChanged Stream<Duration>
Position Stream
no setterinherited
playerId String
Stable Identifier
finalinherited
playerMode → PlayerMode
Player Mode
no setterinherited
poolSizePerSound int
Maximum concurrent players per sound key.
no setter
releaseMode → ReleaseMode
Release Mode
no setterinherited
runtimeType Type
A representation of the runtime type of the object.
no setterinherited
volume double
Current Volume (0.0 → 1.0)
no setterinherited

Methods

activate() → void
Activate
inherited
changeSource(AudioSourceBuilder builder) → void
Swap Loader
inherited
deactivate() → void
Deactivate
inherited
disableLifecycle() → void
Disable lifecycle handling for this channel.
inherited
dispose() Future<void>
Dispose
inherited
disposePools() Future<void>
Dispose all pools.
enableLifecycle([ChannelLifecycleConfig cfg = const ChannelLifecycleConfig()]) → void
Enable per-channel lifecycle handling
inherited
enablePooling({bool enabled = true, int poolSizePerSound = 4, int minPlayersPerSound = 1}) → void
Enable/disable pooling and configure pool sizes.
ensureWaitSupported(String methodName) → void
Throws if waiting semantics are unsupported for this channel.
inherited
fadeIn({Duration duration = const Duration(seconds: 2), Curve curve = Curves.easeInOut}) Future<void>
Fade In
inherited
fadeInVolume(FadePreset preset) Future<void>
Helper: Fade In via FadePreset
inherited
fadeOut({Duration duration = const Duration(seconds: 2), Curve curve = Curves.easeOut}) Future<void>
Fade Out
inherited
fadeOutVolume(FadePreset preset) Future<void>
Helper: Fade Out via FadePreset
inherited
fadeTo(double targetVolume, {Duration duration = const Duration(seconds: 2), Curve curve = Curves.linear}) Future<void>
Fade To Target Volume
inherited
getDuration() Future<Duration?>
Current Media Duration
inherited
mute() Future<void>
Mute (volume → 0.0)
inherited
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
onStateChanged(PlayerState state) → void
Subclass Hook: Player State Changed
inherited
pause() Future<void>
Pause
inherited
play(String path) Future<void>
Play by Path
inherited
playAndWait(String path, {Duration startTimeout = const Duration(seconds: 3), Duration timeout = const Duration(minutes: 2), bool forceStopOnTimeout = true}) Future<bool>
Convenience: play a path and wait for completion/stop
inherited
playFromSource(Source source) Future<void>
Play from Source
inherited
playFromSourceAndWait(Source source, {Duration startTimeout = const Duration(seconds: 3), Duration timeout = const Duration(minutes: 2), bool forceStopOnTimeout = true}) Future<bool>
Convenience: play a Source and wait for completion/stop
inherited
playPooled(String key, Source source, {double? volume}) Future<StopFunction?>
Play using a pooled player (or fallback to the single channel player).
playPooledPath(String path, {String? key, double? volume}) Future<StopFunction?>
Play a path using pooling, resolving the path with the channel’s current loader (respects changeSource(...)).
refreshPoolsAudioContext() Future<void>
Rebuild all pools so they inherit the channel’s current AudioContext. Useful after calling setAudioContext(...) at runtime.
resolveSource(String path) Source
Resolve a path into a Source using the current builder (assets/files/urls). Override via changeSource to switch the strategy at runtime.
inherited
resume() Future<void>
Resume
inherited
seek(Duration position) Future<void>
Seek
inherited
setAudioContext(AudioContext audioContext) Future<void>
Apply Platform Audio Context
inherited
setVolume(double volume) Future<void>
Set Volume
inherited
stop() Future<void>
Stop
inherited
toggleActive() → void
Toggle Active
inherited
toString() String
A string representation of this object.
inherited
unmute() Future<void>
Unmute (volume → 1.0)
inherited
waitUntilStarted({Duration timeout = const Duration(seconds: 3)}) Future<bool>
Wait until playback starts (first true)
inherited
waitUntilStopped({Duration startTimeout = const Duration(seconds: 3), Duration timeout = const Duration(minutes: 2), bool forceStopOnTimeout = true}) Future<bool>
Wait until playback stops/completes
inherited
withFade(Future<void> action(), {FadePreset fadeOut = FadePreset.fast, FadePreset fadeIn = FadePreset.normal}) Future<void>
withFade
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited