2#ifndef LIBSBX_AUDIO_AUDIO_MODULE_HPP_
3#define LIBSBX_AUDIO_AUDIO_MODULE_HPP_
15#include <libsbx/utility/logger.hpp>
17#include <libsbx/core/module.hpp>
18#include <libsbx/core/engine.hpp>
20#include <libsbx/scenes/scenes_module.hpp>
22#include <libsbx/assets/assets_module.hpp>
27 std::float_t gain = 1.0f;
34enum class playback : std::uint8_t {
43 std::float_t gain = 1.0f;
44 std::float_t pitch = 1.0f;
48 std::float_t reference_distance = 1.0f;
49 std::float_t max_distance = 100.0f;
50 std::float_t rolloff = 1.0f;
52 playback desired = playback::stopped;
56 ALuint bound_buffer = 0;
57 bool dirty_params =
true;
62 inline static const auto is_registered = register_module(stage::normal, dependencies<assets::assets_module>{});
70 ALsizei sample_rate = 0;
74 _device = alcOpenDevice(
nullptr);
77 throw std::runtime_error{
"Failed to open OpenAL device."};
80 _context = alcCreateContext(_device,
nullptr);
83 alcCloseDevice(_device);
85 throw std::runtime_error{
"Failed to create OpenAL context."};
88 if (!alcMakeContextCurrent(_context)) {
89 alcDestroyContext(_context);
90 alcCloseDevice(_device);
92 throw std::runtime_error{
"Failed to make OpenAL context current."};
96 ~audio_module()
override {
97 alcMakeContextCurrent(
nullptr);
98 alcDestroyContext(_context);
99 alcCloseDevice(_device);
102 auto get_or_load_clip_buffer(
const std::string& uri) -> sound_clip& {
103 if (
auto it = _clip_cache.find(uri); it != _clip_cache.end()) {
107 auto& assets = core::engine::get_module<assets::assets_module>();
109 auto path = assets.resolve_path(uri).string();
111 auto wav = _load_wav(path);
113 auto format = ALenum{};
115 if (wav.channels == 1) {
116 format = AL_FORMAT_MONO16;
117 }
else if (wav.channels == 2) {
118 format = AL_FORMAT_STEREO16;
120 throw std::runtime_error{
"Unsupported WAV channel count"};
123 auto clip = sound_clip{};
124 clip.format = format;
125 clip.sample_rate =
static_cast<ALsizei
>(wav.sample_rate);
127 alGenBuffers(1, &clip.buffer);
129 if (alGetError() != AL_NO_ERROR) {
130 throw std::runtime_error{
"alGenBuffers failed."};
133 alBufferData(clip.buffer, clip.format, wav.samples.data(),
static_cast<ALsizei
>(wav.samples.size() *
sizeof(std::int16_t)), clip.sample_rate);
135 if (alGetError() != AL_NO_ERROR) {
136 alDeleteBuffers(1, &clip.buffer);
138 throw std::runtime_error{
"alBufferData failed."};
141 auto [it, _] = _clip_cache.emplace(uri, clip);
146 auto update() ->
void override {
147 auto& scenes_module = sbx::core::engine::get_module<sbx::scenes::scenes_module>();
149 auto& scene = scenes_module.active_scene();
150 auto& environment = scene.environment();
151 auto& graph = scene.graph();
153 auto camera_node = environment.camera();
155 const auto& camera_transform = graph.get_component<scenes::transform>(camera_node);
157 alListener3f(AL_POSITION, camera_transform.position().x(), camera_transform.position().y(), camera_transform.position().z());
158 alListener3f(AL_VELOCITY, 0.0f, 0.0f, 0.0f);
160 if (graph.has_component<audio::sound_listener>(camera_node)) {
161 const auto& listener = graph.get_component<audio::sound_listener>(camera_node);
163 alListenerf(AL_GAIN, listener.gain);
166 const auto forward = camera_transform.forward();
167 const auto up = camera_transform.up();
169 auto orientation = std::array<std::float_t, 6u>{
170 forward.x(), forward.y(), forward.z(),
171 up.x(), up.y(), up.z()
174 alListenerfv(AL_ORIENTATION, orientation.data());
180 std::vector<std::int16_t> samples;
181 std::uint32_t sample_rate;
182 std::uint16_t channels;
185 auto _load_wav(
const std::string& filepath) -> wav_data {
188 if (!drwav_init_file(&wav, filepath.c_str(),
nullptr)) {
189 throw std::runtime_error(
"Failed to load WAV");
192 auto out = wav_data{};
193 out.sample_rate = wav.sampleRate;
194 out.channels = wav.channels;
196 out.samples.resize(wav.totalPCMFrameCount * wav.channels);
197 drwav_read_pcm_frames_s16(&wav, wav.totalPCMFrameCount, out.samples.data());
205 ALCcontext* _context;
207 std::unordered_map<std::string, sound_clip> _clip_cache;
Definition: audio_module.hpp:60
Definition: module.hpp:92
Definition: audio_module.hpp:67
Definition: audio_module.hpp:30
Definition: audio_module.hpp:26
Definition: audio_module.hpp:40