Vulkan Schnee 0.0.1 (22840dc8)
High-performance rendering engine
Loading...
Searching...
No Matches
Audio Integration

Audio uses miniaudio for decoding and playback and Steam Audio for binaural HRTF spatialization. The HRTF listener follows the headset each frame, and spatial sources are played at world positions through the audio engine.

Current Components

Component File Purpose
Audio Engine/include/Engine/Audio/AudioAsset.h Stores decoded PCM and clip metadata
AudioClipHandle Engine/include/Engine/Asset/AssetHandles.h Stable typed handle stored by gameplay code
AudioClipStore Engine/include/Engine/Asset/AssetRegistry.h Creates handles and requests backing audio payloads
AudioAssetRef Engine/include/Engine/Audio/AudioAssetRef.h Legacy ref used to inspect the backing payload and loading state
AudioLoader Engine/include/Engine/Audio/AudioLoader.h Decodes WAV, FLAC, and MP3 through miniaudio
AudioAssetPipeline Engine/include/Engine/Ecs/AudioAssetPipeline.h Async decode pipeline
AudioEngine Engine/include/Engine/Audio/AudioEngine.h Owns ma_engine, registers loaded clips, starts and stops playback

Asset Handle

Gameplay code should get audio handles from the scene's AssetRegistry.

scene->getAssetRegistry()->audioClips().load(clipPath);
static constexpr auto engineSounds()
Path to engine audio files.
Definition Path.h:252
AssetHandle< AudioClipHandleTag > AudioClipHandle
Handle to audio clip asset data.
Identifies a single asset file on disk.
Definition AssetPath.h:13

AudioClipStore::load() is a get-or-create operation. It immediately returns the stable handle for the path and requests asynchronous decoding when it creates a new handle. Calling it repeatedly with the same path returns the same handle and does not restart an active or completed load.

AssetManager::getAsset<Engine::Assets::Audio>() is the legacy payload-facing API. Use it only when code specifically needs an AudioAssetRef; do not store that ref as the asset's gameplay identity.

Loading Audio Assets

AudioAssetPipeline runs once per frame from EngineKern::processResourceLoadingPipelines().

assetManager->getAudioAssetPipeline().tick(true);

The pipeline has two stages.

Stage Work
submitDecodeJobs() Move queued paths to worker futures and call AudioLoader::load()
retrieveDecodedAudio() Poll ready futures, create Audio assets, resolve records, notify AudioEngine

Decoded audio is stored directly on Engine::Assets::Audio.

class Audio : public Asset::AssetBase {
uint32_t sampleRate_ = 0;
uint32_t channels_ = 0;
uint64_t frameCount_ = 0;
float durationSeconds_ = 0.0f;
std::vector<float> pcmData_;
};
Base class for asset wrappers. The data is stored in the private member variable 'data' in form of en...
Definition Asset.h:297

Audio does not use hidden ECS entities for PCM storage. Audio::setAudioData() moves decoded PCM into the asset object and marks it loaded.

Playback

Asset loading and playback are separate.

->getAudioEngine();
Engine::Core::AudioHandle handle = audioEngine->play(clipHandle, 1.0f, false);
static EngineManager & getInstance()
Returns the singleton engine manager instance.
EngineKern * getEngineModule()
Returns the active engine.
uint32_t AudioHandle
Identifies a playing sound instance.
Definition AudioEngine.h:33

AudioEngine::play() resolves the handle through AudioClipStore. It returns INVALID_AUDIO_HANDLE when the handle is invalid or its payload has not finished loading. The path overload remains available for legacy callers.

Spatial playback uses AudioEngine::playSpatialized() with a world position. AudioEngine::updateSpatializedSource() moves a playing source to a new position, for example when the emitting actor moves.

Example Actor

Store the typed handle on the actor and pass it directly to AudioEngine.

void SoundTestActor::beginPlay()
{
Actor::beginPlay();
soundHandle_ = getOwningScene()
->getAssetRegistry()
->audioClips()
.load(soundPath_);
}
void SoundTestActor::tick(double deltaTimeSeconds)
{
Actor::tick(deltaTimeSeconds);
if (playbackStarted_) {
return;
}
auto* audioEngine = Engine::EngineManager::getInstance()
->getAudioEngine();
currentHandle_ = audioEngine->play(soundHandle_, volume_, loop_);
playbackStarted_ = currentHandle_ != Engine::Core::INVALID_AUDIO_HANDLE;
}
constexpr AudioHandle INVALID_AUDIO_HANDLE
Invalid or failed playback handle.
Definition AudioEngine.h:34

Current Limits

Area Current State
Asset access Gameplay stores AudioClipHandle; payload readiness uses legacy AudioAssetRef
Playback access Accepts AudioClipHandle; a path overload remains for legacy callers
Spatial audio Implemented. AudioEngine::playSpatialized() plays at a world position through the Steam Audio HRTF backend; updateSpatializedSource() moves a playing source. The listener follows the headset each frame
Streaming music Not implemented; clips decode fully into memory
ECS audio source/listener components No dedicated source/listener ECS component; gameplay drives spatial sources from actors via AudioEngine::playSpatialized()
Cleanup AssetManager::unloadAllData() clears audio asset records with the other asset managers

Spatial playback uses AudioClipHandle and the Steam Audio HRTF backend. Future work can wrap this in a dedicated audio source component.

Configuration

miniaudio uses values from Engine/include/Engine/Audio/AudioConfig.h.

Setting Value
Sample rate Engine::Core::Audio::SAMPLE_RATE
Frame size Engine::Core::Audio::FRAME_SIZE
Output channels Engine::Core::Audio::OUTPUT_CHANNELS