6#include <brenta/audio.hpp>
7#include <brenta/logger.hpp>
15std::vector<std::tuple<types::sound_id_t, std::string,
16 types::stream_id_t>> audio::init_sounds;
17std::vector<std::pair<types::stream_id_t, float>> audio::init_streams;
18std::unordered_map<types::sound_id_t, types::sound_t>
audio::sounds;
19std::unordered_map<types::stream_id_t, types::stream_t>
audio::streams;
20ma_engine audio::engine;
21bool audio::initialized =
false;
22const std::string audio::subsystem_name =
"audio";
32 result = ma_engine_init(NULL, &audio::engine);
33 if (result != MA_SUCCESS)
35 ERROR(
"{}: error initializing engine: {}",
36 audio::subsystem_name, ma_result_description(result));
37 return std::unexpected(
"Initializing audio backend");
40 for (
auto& f : audio::init_sounds)
42 if (!
audio::load(std::get<0>(f), std::get<1>(f), std::get<2>(f)).has_value())
43 return std::unexpected(
"Loading audio " + get<0>(f));
46 for (
auto& s : audio::init_streams)
48 if (!audio::create_stream(s.first).has_value())
49 return std::unexpected(
"Creating stream " + s.first);
51 return std::unexpected(
"Setting volume for stream " + s.first);
54 if (!audio::get_stream(
"default"))
56 if (!audio::create_stream(
"default").has_value())
57 return std::unexpected(
"Creating stream default");
60 audio::initialized =
true;
61 INFO(
"{}: initialized", audio::subsystem_name);
70 ma_sound_uninit(&sound.second);
73 ma_sound_group_uninit(&stream.second);
75 ma_engine_uninit(&audio::engine);
77 audio::initialized =
false;
78 INFO(
"{}: termianted", audio::subsystem_name);
84 return audio::subsystem_name;
89 return audio::initialized;
96audio &audio::instance()
102std::expected<void, audio::error>
104 const std::string &path,
105 const types::stream_id_t &stream_id)
107 types::stream_t *stream = audio::get_stream(stream_id);
110 audio::create_stream(stream_id);
111 stream = audio::get_stream(stream_id);
114 ERROR(
"{}: error stream {} not found",
115 audio::subsystem_name, stream_id);
116 return std::unexpected(audio::error::stream_not_found);
120 types::sound_t sound = {};
122 if (ma_sound_init_from_file(&audio::engine, path.c_str(), 0, stream, NULL,
125 ERROR(
"{}: error loading sound {} from path {}",
126 audio::subsystem_name, sound_id, path);
127 return std::unexpected(audio::error::init_from_file);
130 INFO(
"{}: loaded sound {} from {} in stream {}",
131 audio::subsystem_name, sound_id, path, stream_id);
135std::expected<void, audio::error>
141 ERROR(
"{}: sound with id {} not found",
142 audio::subsystem_name,
id);
143 return std::unexpected(audio::error::sound_not_found);
145 ma_sound_start(sound);
149std::expected<void, audio::error>
150audio::create_stream(
const types::stream_id_t &
id)
152 types::stream_t *stream = audio::get_stream(
id);
153 if (stream)
return {};
155 types::stream_t s = {};
158 if (ma_sound_group_init(&audio::engine, 0, NULL, stream)
161 ERROR(
"{}: error creating audio stream {}",
162 audio::subsystem_name,
id);
163 return std::unexpected(audio::error::stream_init);
166 INFO(
"{}: stream {} created", audio::subsystem_name,
id);
170types::stream_t *audio::get_stream(
const types::stream_id_t &
id)
179std::expected<void, audio::error>
182 types::stream_t *stream = audio::get_stream(
id);
185 ERROR(
"{}: could not set volume: Audio stream {} not found",
186 audio::subsystem_name,
id);
187 return std::unexpected(audio::error::stream_not_found);
190 ma_sound_group_set_volume(stream, volume);
192 INFO(
"{}: volume for stream {} set to {}",
193 audio::subsystem_name,
id, volume);
197std::expected<void, audio::error>
198audio::stream_stop(
const types::stream_id_t &
id)
200 types::stream_t *stream = audio::get_stream(
id);
201 if (stream ==
nullptr)
203 ERROR(
"{}: could not pause stream: stream {} not found",
204 audio::subsystem_name,
id);
205 return std::unexpected(audio::error::stream_not_found);
208 if (ma_sound_group_stop(stream) != MA_SUCCESS)
210 ERROR(
"{}: error stopping stream {}",
211 audio::subsystem_name,
id);
212 return std::unexpected(audio::error::stream_stop);
215 INFO(
"{}: stream {} stopped", audio::subsystem_name,
id);
219std::expected<void, audio::error>
220audio::stream_start(
const types::stream_id_t &
id)
222 auto stream = audio::get_stream(
id);
223 if (stream ==
nullptr)
225 ERROR(
"{}: could not start stream: Audio stream {} not found",
226 audio::subsystem_name,
id);
227 return std::unexpected(audio::error::stream_not_found);
230 if (ma_sound_group_start(stream) != MA_SUCCESS)
232 ERROR(
"{}: error starting stream {}", audio::subsystem_name,
id);
233 return std::unexpected(audio::error::stream_start);
236 INFO(
"{}: stream {} started", audio::subsystem_name,
id);
245audio::builder::sound(
const types::sound_id_t &sound_id,
246 const std::string &path,
247 const types::stream_id_t &stream_id)
249 this->init_sounds.push_back(std::make_tuple(sound_id, path, stream_id));
254audio::builder::stream(
const types::stream_id_t &
id,
257 this->init_streams.push_back(std::make_pair(
id, volume));
263 audio::init_sounds = this->init_sounds;
264 audio::init_streams = this->init_streams;
265 return audio::instance();
std::expected< void, subsystem::error > terminate() override
Terminate the audio system.
static std::unordered_map< types::sound_id_t, types::sound_t > sounds
Map of sound files.
std::expected< void, subsystem::error > initialize() override
Initialize the audio subsystem.
static std::expected< void, audio::error > load(const types::sound_id_t &sound_id, const std::string &path, const types::stream_id_t &stream_id="default")
Load a sound from path on a stream.
bool is_initialized() override
Returns true if the subsystem is initialized.
static std::unordered_map< types::stream_id_t, types::stream_t > streams
Map of audio streams.
static std::expected< void, audio::error > stream_set_volume(const types::stream_id_t &id, float volume)
Set the volume of a stream.
static std::expected< void, audio::error > play(const types::sound_id_t &id)
Play a sound on its stream.
std::string name() override
Returns the name of the sybsystem.