Skip to content

Design audio playback abstraction layer supporting diverse engine patterns #20

@JohnLudlow

Description

@JohnLudlow

Overview

GameEngineAdapter is an engine abstraction layer targeting multiple engines (MonoGame, Stride, Raylib, TUI, Headless). The audio system must maintain compatibility across engines with different audio API philosophies.

Current state: IAudioPlayer uses a method-based pattern (StartPlayback/StopPlayback/SetVolume with asset IDs). This works for simple audio but may limit full feature parity with target engines.

Investigation goal: Design an audio abstraction that balances compatibility with target engines while maintaining a clean, usable interface for game logic.

Architectural Considerations and Constraints

Target engines have divergent audio patterns:

Engine Pattern API Style Notes
Raylib Method-based (functional) PlaySound/StopSound/SetSoundVolume Direct function calls, no entities
MonoGame Dual: SoundEffect (method) + SoundEffectInstance (state) Method-based with instances Fire-and-forget or full control; 3D via AudioEmitter/AudioListener
Stride Entity-based with component pattern AudioEmitterComponent/AudioListenerComponent Hierarchical, spatial by default
Godot/Unity Entity-based with components AudioSource/AudioStreamPlayer attached to nodes Scene hierarchy integration

Key design tension:

  • Method-based pattern: Simple, stateless, non-entity-dependent (Raylib/basic MonoGame)
  • Entity/DTO pattern: Rich, stateful, hierarchical, enables 3D/spatial audio (Stride/Godot/Unity)

Current gaps:

  • No 3D positional audio support (needed for Stride, future 3D engines)
  • No multi-instance playback control (needed for Stride's AudioEmitterSoundController)
  • No spatial audio (AudioEmitter/AudioListener pattern)

Definition of Terms

Term Meaning Reference
Audio Entity Engine-specific object representing an audio source (MonoGame: SoundEffectInstance, Stride: AudioEmitterComponent) Engine-specific
Audio DTO Data Transfer Object bundling audio parameters for submission to engine (analogous to SpriteDrawDto for rendering) Drawing analogy
3D/Spatial Audio Positional audio with attenuation, panning based on listener position OpenAL docs
Fire-and-forget Play sound without tracking/controlling playback state Raylib pattern
Sound Instance Controllable audio handle supporting volume, pitch, pan, looping mutations MonoGame SoundEffectInstance

Plan Requirements

  • (In discovery) Investigate whether a dual-abstraction (method-based + entity/DTO pattern) is necessary or if one unified pattern can bridge all target engines

    • GIVEN a target engine with spatial audio capabilities (e.g., Stride)
    • WHEN the adapter layer must support 3D positional audio
    • THEN the abstraction must either expose spatial audio parameters or provide entity/component integration
  • (In discovery) Define what audio features are "phase 1 minimum" vs. "future extensions"

    • GIVEN limited scope for Phase 1 (audio playback for TUI/Headless/basic rendering)
    • WHEN advanced features (3D, spatial) are not yet needed
    • THEN current method-based IAudioPlayer may be sufficient with a design path for future extension
  • (In discovery) Evaluate whether audio should follow rendering's DTO pattern (SpriteDrawDto, etc.) or remain method-based

    • GIVEN rendering uses DTOs for batching complex parameters
    • WHEN audio playback is typically immediate and stateless
    • THEN determine if DTO overhead is justified or adds unnecessary complexity

Related Plan Documentation

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-libItems related to reusable librariesenhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions