Toast Engine
Toggle main menu visibility
Loading...
Searching...
No Matches
music_player.hpp
Go to the documentation of this file.
1
8
#pragma once
9
#include "
../assets.hpp
"
10
11
#include <atomic>
12
#include <mutex>
13
#include <string>
14
#include <
toast/events/signals.hpp
>
15
#include <
toast/export.hpp
>
16
#include <
toast/world/node.hpp
>
17
#include <unordered_map>
18
#include <vector>
19
20
namespace
toast {
21
30
class
TOAST_API [[ToastNode, Color(
"Beige"
), Icon(
"AudioStreamMP3"
)]]
MusicPlayer
:
public
Node {
31
public
:
32
void
play(
int
track_index = 0,
float
fade_in = 0.0f);
33
void
stop(
bool
allow_fadeout =
true
);
34
void
crossfadeTo(
int
track_index,
float
duration);
35
void
pause(
bool
value);
36
void
keyOff(
int
track_index = -1);
37
38
[[nodiscard]]
39
auto
getTimelinePosition(
int
track_index = 0)
const
-> int;
40
void
setTimelinePosition(
int
ms,
int
track_index = 0);
41
42
void
setParameter(std::string_view
name
,
float
value,
int
track_index = -1);
43
void
setParameter(std::string_view
name
,
bool
value,
int
track_index = -1);
44
45
void
masterVolume(
float
value);
46
void
masterPitch(
float
value);
47
48
private
:
49
void
updateInspectorMessages()
override
;
50
void
onEnable();
51
void
onDisable();
52
void
tick();
53
void
destroy();
54
55
public
:
56
struct
ActiveTrack
{
57
uint64_t instance_id = 0;
58
int
track_index = -1;
59
float
current_vol = 0.0f;
60
float
target_vol = 1.0f;
61
float
fade_duration = 0.0f;
62
float
fade_elapsed
= 0.0f;
63
};
64
65
// public so the static FMOD callback can read it without needing friend
66
//
67
// FMOD's event callback fires from its own Studio update thread, asynchronously from the game thread
68
// that stops/destroys the player. Unregistering the callback (SetCallback(nullptr)) before destruction
69
// only prevents FUTURE dispatches - it doesn't guarantee a callback already in flight on FMOD's thread
70
// has finished, so `player` must be checked atomically rather than trusted as always valid. Instances
71
// of this struct are deliberately never freed (see startTrack()) so the raw pointer FMOD holds via
72
// SetUserData is always safe to dereference, even after the MusicPlayer it refers to is long gone
73
struct
CallbackData
{
74
std::atomic<MusicPlayer*> player {
nullptr
};
75
uint64_t instance_id = 0;
76
};
77
78
enum class
CbType : uint8_t {
79
beat,
80
marker,
81
stopped
82
};
83
84
struct
QueuedCb
{
85
CbType type = CbType::beat;
86
uint64_t instance_id = 0;
87
int
bar
= 0;
88
int
beat = 0;
89
int
position_ms = 0;
90
float
tempo = 0.0f;
91
int
sig_upper
= 4;
92
int
sig_lower = 4;
93
std::string marker_name;
94
};
95
96
struct
ParamID
{
97
unsigned
int
data1 = 0;
98
unsigned
int
data2 = 0;
// FMOD caches parameter IDs so we don't string-lookup every frame
99
};
100
101
void
queueCallback(
const
QueuedCb
& cb);
102
103
signals::Signal<std::string_view> audio_started;
104
signals::Signal<std::string_view> audio_stopped;
105
signals::Signal<bool> audio_paused;
106
107
private
:
108
void
startTrack(
int
track_index,
float
fade_in);
109
void
stopTrack(
ActiveTrack
& at,
bool
allow_fadeout);
110
111
[[
Reflect
, Name(
"Tracks"
)]]
112
std::vector<assets::Handle<assets::AudioEvent>> m_tracks;
113
114
[[
Reflect
]]
115
bool
m_play_on_enable =
true
;
116
117
[[
Reflect
, Range(0.0, 1.0)]]
118
float
m_volume = 1.0f;
119
120
[[
Reflect
, Range(0.5, 2.0)]]
121
float
m_pitch = 1.0f;
122
123
std::vector<ActiveTrack> m_active_tracks;
124
// Each CallbackData is individually heap-allocated and deliberately never freed (see CallbackData's own
125
// comment for why) - this vector just tracks the pointers for our own bookkeeping, so reallocating IT is
126
// harmless; the addresses FMOD actually holds via SetUserData never move
127
std::vector<CallbackData*> m_callback_data;
128
129
std::mutex m_cb_mutex;
130
std::vector<QueuedCb> m_pending_cbs;
131
132
std::unordered_map<uint64_t, std::unordered_map<std::string, ParamID>>
133
m_param_ids;
134
};
135
136
}
assets.hpp
toast::MusicPlayer
Manages multi-track music with smooth crossfades between tracks.
Definition
music_player.hpp:30
toast::Node::name
auto name() const noexcept -> std::string_view
Display name. Siblings may share one - this is not an identifier.
Definition
node.cpp:45
toast::Reflect
Definition
reflect.hpp:244
export.hpp
node.hpp
Base object type for the scene graph.
signals.hpp
toast::MusicPlayer::ActiveTrack
Definition
music_player.hpp:56
toast::MusicPlayer::ActiveTrack::fade_elapsed
float fade_elapsed
current_vol/target_vol and fade_duration/elapsed drive the crossfade lerp
Definition
music_player.hpp:62
toast::MusicPlayer::CallbackData
Definition
music_player.hpp:73
toast::MusicPlayer::ParamID
Definition
music_player.hpp:96
toast::MusicPlayer::QueuedCb
Definition
music_player.hpp:84
toast::MusicPlayer::QueuedCb::bar
int bar
0-based bar and beat for musical timing
Definition
music_player.hpp:87
toast::MusicPlayer::QueuedCb::sig_upper
int sig_upper
time signature numerator and denominator
Definition
music_player.hpp:91
engine
src
toast
audio
nodes
music_player.hpp
Generated by
1.17.0