10 #include <audio_manager.hpp>
12 static bool singleton_initialized =
false;
19 void audio_manager::update_task(
void *arg) {
21 mngr->handle_messages();
31 gTask_manager(gTask_manager) {
32 if (singleton_initialized) {
33 throw std::runtime_error(
"The audio manager cannot be initialized more than once!");
35 singleton_initialized =
true;
38 if (SDL_Init(SDL_INIT_AUDIO) < 0) {
39 fprintf(stderr,
"Failed to initialize SDL audio subsystem: %s\n", SDL_GetError());
42 if (Mix_OpenAudio(48000, AUDIO_F32SYS, 2, 1024) == -1) {
43 fprintf(stderr,
"Failure to open audio device\n");
46 if (Mix_Init(MIX_INIT_OGG) == 0) {
47 fprintf(stderr,
"Failed to initialize SDL_Mixer: %s\n", Mix_GetError());
50 Mix_Volume(-1, chunk_volume);
51 Mix_VolumeMusic(music_volume);
52 Mix_AllocateChannels(32);
55 gMessage_bus.
subscribe(PLAY_SOUND, &msg_sub);
56 gMessage_bus.
subscribe(PLAY_MUSIC, &msg_sub);
57 gMessage_bus.
subscribe(STOP_MUSIC, &msg_sub);
58 gMessage_bus.
subscribe(SET_AUDIO_ENABLED, &msg_sub);
59 gMessage_bus.
subscribe(MUSIC_ASSETS, &msg_sub);
60 gMessage_bus.
subscribe(CHUNKS_ASSETS, &msg_sub);
61 gMessage_bus.
subscribe(STOP_ALL_SOUNDS, &msg_sub);
62 gMessage_bus.
subscribe(SET_MUSIC_VOLUME, &msg_sub);
63 gMessage_bus.
subscribe(SET_SOUNDS_VOLUME, &msg_sub);
64 gMessage_bus.
subscribe(PAUSE_MUSIC, &msg_sub);
71 void audio_manager::handle_messages() {
73 while (temp !=
nullptr) {
74 switch (temp->msg_name) {
76 auto data = temp->base_data0;
77 uint16_t name = data & 0x0000ffffU;
78 uint8_t volume = (data >> 16U) & 0x000000ffU;
79 int8_t loops = (data >> 24U) & 0x000000ffU;
80 play_sound(name, volume, loops);
84 auto data = temp->base_data0;
85 uint16_t name = data & 0x0000ffffU;
86 uint8_t volume = (data >> 16U) & 0x000000ffU;
87 int8_t loops = (data >> 24U) & 0x000000ffU;
88 play_music(name, volume, loops);
93 gMessage_bus.
send_msg(
new message(LOG_SUCCESS, make_data<std::string>(
"Music stopped")));
98 gMessage_bus.
send_msg(
new message(LOG_SUCCESS, make_data<std::string>(
"Music paused")));
101 case STOP_ALL_SOUNDS: {
103 gMessage_bus.
send_msg(
new message(LOG_SUCCESS, make_data<std::string>(
"Sounds stopped")));
106 case SET_AUDIO_ENABLED: {
107 auto arg =
static_cast<bool>(temp->base_data0);
109 gMessage_bus.
send_msg(
new message(LOG_SUCCESS, make_data<std::string>(
"Audio muted")));
113 gMessage_bus.
send_msg(
new message(LOG_SUCCESS, make_data<std::string>(
"Audio unmuted")));
119 music_ptr = *
static_cast<ska::bytell_hash_map<uint16_t, Mix_Music *> **
>(temp->
get_data());
122 chunks_ptr = *
static_cast<ska::bytell_hash_map<uint16_t, Mix_Chunk *> **
>(temp->
get_data());
124 case SET_SOUNDS_VOLUME: {
125 set_chunk_volume(
static_cast<uint8_t
>(temp->base_data0));
131 case SET_MUSIC_VOLUME: {
132 set_music_volume(
static_cast<uint8_t
>(temp->base_data0));
156 void audio_manager::set_chunk_volume(uint8_t arg) {
158 chunk_playback_volume_ratio =
static_cast<float>(MIX_MAX_VOLUME) /
static_cast<float>(chunk_volume);
160 Mix_Volume(-1, chunk_volume);
168 void audio_manager::set_music_volume(uint8_t arg) {
170 music_playback_volume_ratio =
static_cast<float>(MIX_MAX_VOLUME) /
static_cast<float>(music_volume);
172 Mix_VolumeMusic(music_volume);
179 void audio_manager::mute() {
188 void audio_manager::unmute() {
189 Mix_Volume(-1, chunk_volume);
190 Mix_VolumeMusic(music_volume);
200 void audio_manager::play_sound(uint16_t arg, uint8_t volume, int8_t loops)
const {
201 auto data = chunks_ptr->find(arg);
202 auto chunk =
reinterpret_cast<Mix_Chunk *
>((data != chunks_ptr->end()) *
reinterpret_cast<uint64_t
>(data->second));
204 Mix_VolumeChunk(chunk,
static_cast<int>(
static_cast<float>(volume) / chunk_playback_volume_ratio));
206 if (Mix_PlayChannel(-1, chunk, loops) == -1) {
208 new message(LOG_ERROR, make_data<std::string>(
"Mix_PlayChannel Error " + std::string(Mix_GetError()))));
218 void audio_manager::play_music(uint16_t arg, uint8_t volume, int8_t loops)
const {
219 auto data = music_ptr->find(arg);
220 auto music =
reinterpret_cast<Mix_Music *
>((data != music_ptr->end()) *
reinterpret_cast<uint64_t
>(data->second));
222 Mix_VolumeMusic(
static_cast<int>(
static_cast<float>(volume) / music_playback_volume_ratio));
224 if (Mix_PlayMusic(music, loops) == -1) {
226 new message(LOG_ERROR, make_data<std::string>(
"Mix_PlayMusic Error " + std::string(Mix_GetError()))));
233 void audio_manager::stop_music() {
240 void audio_manager::pause_music() {
247 void audio_manager::stop_channels() {
256 SDL_QuitSubSystem(SDL_INIT_AUDIO);
258 singleton_initialized =
false;
An object representing a task to be run by the task manager.
This object is responsible for playing sounds and music.
audio_manager(task_manager &tsk_mngr, message_bus &gMessageBus)
The central messaging system of the engine. All subsystem make extensive use of it.
void subscribe(uint8_t msg, subscriber *sub)
void send_msg(message *msg)
A message object passed around in the message bus. Holds anything created with make_data<>().
message * get_next_message()
The Task Manager handles all things multi-threaded in the engine.
void start_task_lockfree(ST::task *arg)