Vulkan Schnee 0.0.1 (22840dc8)
High-performance rendering engine
Loading...
Searching...
No Matches
AudioEngine.h
1#pragma once
2
3#include "AudioConfig.h"
4#include "Engine/Asset/AssetHandles.h"
5#include "Engine/Audio/AudioFlow.h"
6
7#include <filesystem>
8#include <memory>
9#include <optional>
10#include <vector>
11#include <unordered_map>
12#include <string>
13
14#include <glm/glm.hpp>
15#include <glm/gtc/quaternion.hpp>
16
17namespace Engine::Assets
18{
19 class Audio;
20 class AudioFlowStore;
21} // namespace Engine::Assets
22struct ma_engine;
23struct ma_context;
24struct ma_sound;
25
26namespace Engine::Core {
27 class AudioClipStore;
29
33 using AudioHandle = uint32_t;
35
37 {
38 std::string name;
39 bool isDefault = false;
40 };
41
50 public:
55 explicit AudioEngine(const AudioClipStore* audioClips = nullptr);
56
61
65 AudioEngine(const AudioEngine&) = delete;
66
71
76 bool init();
77
83 bool setPlaybackDevice( std::optional<uint32_t> deviceIndex );
84
88 [[nodiscard]] std::vector<AudioDeviceInfo> getPlaybackDevices() const;
89
93 [[nodiscard]] const std::string & getPlaybackDeviceName() const { return playbackDeviceName_; }
94
98 void cleanup();
99
106 void onAudioLoaded( Assets::Audio * asset, const std::filesystem::path& path);
107
115 AudioHandle play(Assets::AudioClipHandle clip, float volume = 1.0f, bool loop = false);
116
121 void setFlowStore( Assets::AudioFlowStore * store ) { flowStore_ = store; }
122
130 AudioHandle playFlow( Assets::AudioFlowHandle flow, float volume = 1.0f, bool loop = false );
131
138 void setFlowParam( AudioHandle handle, Assets::FlowSettingHandle setting, float value );
139
148 AudioHandle playSpatialized(Assets::AudioClipHandle clip, const glm::vec3& worldPosition,
149 float volume = 1.0f, bool loop = false);
150
156 void updateSpatializedSource(AudioHandle handle, const glm::vec3& worldPosition);
157
163 void setListener(const glm::vec3& worldPosition, const glm::quat& worldOrientation);
164
169 void stop(AudioHandle handle);
170
174 void stopAll();
175
180 void setMasterVolume(float volume);
181
182 [[nodiscard]] float getMasterVolume() const { return masterVolume_; }
183
189 [[nodiscard]] bool isPlaying(AudioHandle handle) const;
190
195 [[nodiscard]] bool isInitialized() const { return initialized_; }
196
201 void renderSpatialized(float* pFramesOut, std::uint64_t frameCount);
202
203 private:
204 bool init( std::optional<uint32_t> deviceIndex );
206
218 Assets::Audio * asset, const std::string & assetPath, float volume, bool loop,
219 const std::optional<glm::vec3> & worldPosition, AudioHandle handle
220 );
221
227 void drainPendingForPath( const std::filesystem::path & path, Assets::Audio * asset );
228
233
234 const AudioClipStore* audioClips_ = nullptr;
236 ma_context* context_ = nullptr;
237 ma_engine* engine_ = nullptr;
238 bool initialized_ = false;
239 float masterVolume_ = 1.0f;
241
242 std::unique_ptr<SteamAudioBackend> steamAudio_;
243
250 ma_sound* silenceSound_ = nullptr;
251 void* silenceBuffer_ = nullptr;
252
254
262 ma_sound* sound = nullptr;
263
267 std::string assetPath;
268 };
269 std::unordered_map<AudioHandle, PlayingSound> playingSounds_;
270
278 std::uint32_t source = 0;
279
283 std::string assetPath;
284 };
285 std::unordered_map<AudioHandle, SpatializedSound> spatializedSounds_;
286
290 struct PlayingFlow {
294 void* dataSource = nullptr;
295
299 ma_sound* sound = nullptr;
300 };
301 std::unordered_map<AudioHandle, PlayingFlow> playingFlows_;
302
311 struct PendingPlay {
316
320 std::string assetPath;
321
325 float volume = 1.0f;
326
330 bool loop = false;
331
335 std::optional<glm::vec3> worldPosition;
336 };
337 std::unordered_map<AudioHandle, PendingPlay> pendingPlays_;
338
340 };
341
342} // namespace EngineCore
Registry for audio flows keyed by (glTF path, flow name).
Holds decoded PCM audio data as an engine asset.
Definition AudioAsset.h:14
Registry store for authored audio clip handles.
std::unordered_map< AudioHandle, PlayingSound > playingSounds_
bool isPlaying(AudioHandle handle) const
Check if a sound is currently playing.
void setFlowParam(AudioHandle handle, Assets::FlowSettingHandle setting, float value)
Change a reactive flow setting on a playing flow instance.
std::string playbackDeviceName_
AudioHandle play(Assets::AudioClipHandle clip, float volume=1.0f, bool loop=false)
Play a loaded audio clip by its stable asset handle.
void drainPendingForPath(const std::filesystem::path &path, Assets::Audio *asset)
Starts pending (deferred) playback requests whose clip payload just landed.
float getMasterVolume() const
void updateSpatializedSource(AudioHandle handle, const glm::vec3 &worldPosition)
Move a playing spatialized source to a new world position.
void onAudioLoaded(Assets::Audio *asset, const std::filesystem::path &path)
Called by AudioAssetPipeline when an asset finishes loading. Starts any deferred playback requests th...
void setFlowStore(Assets::AudioFlowStore *store)
Set the flow registry used to resolve flow playback.
void stopAll()
Stop all currently playing sounds.
AudioHandle playFlow(Assets::AudioFlowHandle flow, float volume=1.0f, bool loop=false)
Play an audio flow (reactive node graph) non-spatialized.
AudioEngine(const AudioClipStore *audioClips=nullptr)
Construct an uninitialized audio engine.
~AudioEngine()
Shut down the audio engine on destruction.
AudioHandle playSpatialized(Assets::AudioClipHandle clip, const glm::vec3 &worldPosition, float volume=1.0f, bool loop=false)
Play an audio clip spatialized at a world position by stable handle.
void setListener(const glm::vec3 &worldPosition, const glm::quat &worldOrientation)
Update the HRTF listener pose from the headset.
bool setPlaybackDevice(std::optional< uint32_t > deviceIndex)
Rebuilds the audio backend using a playback device from getPlaybackDevices().
std::unique_ptr< SteamAudioBackend > steamAudio_
void cleanup()
Shut down the audio engine and free all resources.
std::unordered_map< AudioHandle, SpatializedSound > spatializedSounds_
void setMasterVolume(float volume)
Set the master volume.
AudioEngine(const AudioEngine &)=delete
AudioEngine owns native audio resources and cannot be copied.
AudioHandle startPlayback(Assets::Audio *asset, const std::string &assetPath, float volume, bool loop, const std::optional< glm::vec3 > &worldPosition, AudioHandle handle)
Starts playback of a decoded audio payload.
void renderSpatialized(float *pFramesOut, std::uint64_t frameCount)
Accumulate the Steam Audio binaural mix into the engine output. Called from the audio thread via the ...
bool init()
Initialize the miniaudio engine with AudioConfig settings.
ma_sound * silenceSound_
Silent looping sound that keeps the engine node graph producing frames, so the onProcess hook fires e...
bool init(std::optional< uint32_t > deviceIndex)
void purgeStalePending()
Drops deferred playback requests whose clip failed to load or expired.
AudioEngine & operator=(const AudioEngine &)=delete
AudioEngine owns native audio resources and cannot be copy-assigned.
const std::string & getPlaybackDeviceName() const
Returns the active playback device name, or an empty string when audio is disabled.
Definition AudioEngine.h:93
bool isInitialized() const
Check if the audio engine initialized successfully.
void stop(AudioHandle handle)
Stop a playing sound.
std::unordered_map< AudioHandle, PendingPlay > pendingPlays_
Assets::AudioFlowStore * flowStore_
std::unordered_map< AudioHandle, PlayingFlow > playingFlows_
std::vector< AudioDeviceInfo > getPlaybackDevices() const
Enumerates playback devices currently reported by miniaudio.
const AudioClipStore * audioClips_
Binaural HRTF spatialization backend built on Steam Audio.
AssetHandle< AudioClipHandleTag > AudioClipHandle
Handle to audio clip asset data.
constexpr AudioHandle INVALID_AUDIO_HANDLE
Invalid or failed playback handle.
Definition AudioEngine.h:34
uint32_t AudioHandle
Identifies a playing sound instance.
Definition AudioEngine.h:33
Stable identity of an audio flow: the glTF asset path plus the flow name (unique within the asset)....
Definition AudioFlow.h:15
Stable handle to a named, runtime-controllable setting of a flow.
Definition AudioFlow.h:38
Deferred playback request awaiting its clip's async payload.
Assets::AudioClipHandle clip
Clip handle whose payload this request waits on.
float volume
Volume multiplier requested at play time.
std::string assetPath
Source path of the clip (matches the pipeline's load path).
bool loop
Whether the sound should loop.
std::optional< glm::vec3 > worldPosition
World position for spatialized playback, or nullopt for non-spatialized.
Active flow graph playback instance.
ma_sound * sound
miniaudio sound wrapping the flow data source.
void * dataSource
Opaque FlowDataSource (AudioFlowGraph + ma_data_source_base).
Active miniaudio sound instance owned by the audio engine.
ma_sound * sound
Runtime miniaudio sound handle.
std::string assetPath
Asset path used to start this sound.
Active spatialized sound referencing a Steam Audio backend source.
std::uint32_t source
Backend source registered with SteamAudioBackend.
std::string assetPath
Asset path used to start this sound.