diff --git a/core/include/cubos/core/al/audio_device.hpp b/core/include/cubos/core/al/audio_device.hpp index 98f3e62378..07668f5f04 100644 --- a/core/include/cubos/core/al/audio_device.hpp +++ b/core/include/cubos/core/al/audio_device.hpp @@ -9,7 +9,6 @@ #include #include -#include #include @@ -48,34 +47,35 @@ namespace cubos::core::al /// @return Audio device, or nullptr on failure. static std::shared_ptr create(); + /// @brief Enumerates the available devices. + /// @param[out] devices Vector to fill with the available devices. + static void enumerateDevices(std::vector& devices); + /// @brief Creates a new audio buffer - /// @param filePath File path to create buffer from. + /// @param data Data to be written to the buffer, cubos currently supports .wav, .mp3 and .flac files + /// @param datSize Size of the data to be written. /// @return Handle of the new buffer. - static Buffer createBuffer(const void* data, size_t dataSize); + virtual Buffer createBuffer(const void* data, size_t dataSize) = 0; /// @brief Creates a new audio source. /// @return Handle of the new source. - static Source createSource(); - - /// @brief Enumerates the available devices. - /// @param[out] devices Vector to fill with the available devices. - static void enumerateDevices(std::vector& devices); + virtual Source createSource() = 0; /// @brief Sets the position of the listener. /// @param position Position. - /// @param listenerIndex Index of the listener + /// @param listenerIndex Index of the listener. virtual void setListenerPosition(const glm::vec3& position, unsigned int listenerIndex = 0) = 0; /// @brief Sets the orientation of the listener. /// @param forward Forward direction of the listener. /// @param up Up direction of the listener. - /// @param listenerIndex Index of the listener + /// @param listenerIndex Index of the listener. virtual void setListenerOrientation(const glm::vec3& forward, const glm::vec3& up, unsigned int listenerIndex = 0) = 0; /// @brief Sets the velocity of the listener. Used to implement the doppler effect. /// @param velocity Velocity of the listener. - /// @param listenerIndex Index of the listener + /// @param listenerIndex Index of the listener. virtual void setListenerVelocity(const glm::vec3& velocity, unsigned int listenerIndex = 0) = 0; }; @@ -86,11 +86,8 @@ namespace cubos::core::al class CUBOS_CORE_API Buffer { public: - ma_decoder mDecoder; - virtual ~Buffer() = default; virtual size_t getLength() = 0; - static std::shared_ptr create(const void* data, size_t dataSize); protected: Buffer() = default; @@ -102,9 +99,6 @@ namespace cubos::core::al public: virtual ~Source() = default; - /// @brief Creates a source - static std::shared_ptr create(); - /// @brief Sets the buffer to be played by the source. /// @param buffer Buffer. virtual void setBuffer(cubos::core::al::Buffer buffer) = 0; diff --git a/core/include/cubos/core/al/miniaudio_device.hpp b/core/include/cubos/core/al/miniaudio_device.hpp index 00e3b0f782..47005e2093 100644 --- a/core/include/cubos/core/al/miniaudio_device.hpp +++ b/core/include/cubos/core/al/miniaudio_device.hpp @@ -2,56 +2,12 @@ #include +#include + #include namespace cubos::core::al { - class MiniaudioBuffer : public impl::Buffer - { - public: - ~MiniaudioBuffer() override; - size_t getLength() override; - - static std::shared_ptr create(const void* data, size_t dataSize) - { - return std::shared_ptr(new MiniaudioBuffer(data, dataSize)); - } - - protected: - MiniaudioBuffer(const void* data, size_t dataSize); - }; - - class MiniaudioSource : public impl::Source - { - public: - ~MiniaudioSource() override; - - static std::shared_ptr create() - { - return std::shared_ptr(new MiniaudioSource()); - } - - void setBuffer(cubos::core::al::Buffer buffer) override; - void setPosition(const glm::vec3& position) override; - void setVelocity(const glm::vec3& velocity) override; - void setGain(float gain) override; - void setPitch(float pitch) override; - void setLooping(bool looping) override; - void setRelative(bool relative) override; - void setMaxDistance(float maxDistance) override; - void setMinDistance(float minDistance) override; - void setCone(float innerAngle, float outerAngle, float outerGain) override; - void setConeDirection(const glm::vec3& direction) override; - void play() override; - - protected: - MiniaudioSource(); - - private: - ma_sound mSound; - ma_engine mEngine; - }; - /// Audio device implementation using miniaudio. class MiniaudioDevice : public AudioDevice { @@ -61,9 +17,9 @@ namespace cubos::core::al static void enumerateDevices(std::vector& devices); static std::string getDefaultDevice(); - static Buffer createBuffer(const void* data, size_t dataSize); - static Source createSource(); + Buffer createBuffer(const void* data, size_t dataSize) override; + Source createSource() override; void setListenerPosition(const glm::vec3& position, ma_uint32 listenerIndex = 0) override; void setListenerOrientation(const glm::vec3& forward, const glm::vec3& up, ma_uint32 listenerIndex = 0) override; diff --git a/core/src/al/miniaudio_device.cpp b/core/src/al/miniaudio_device.cpp index c8d2b3f1c3..9130e7a475 100644 --- a/core/src/al/miniaudio_device.cpp +++ b/core/src/al/miniaudio_device.cpp @@ -5,132 +5,153 @@ using namespace cubos::core::al; -MiniaudioBuffer::MiniaudioBuffer(const void* data, size_t dataSize) +class MiniaudioBuffer : public impl::Buffer { - if (ma_decoder_init_memory(data, dataSize, nullptr, &mDecoder) != MA_SUCCESS) +public: + ma_decoder mDecoder; + MiniaudioBuffer(const void* data, size_t dataSize) { - CUBOS_CRITICAL("Failed to initialize Decoder from data"); - abort(); + if (ma_decoder_init_memory(data, dataSize, nullptr, &mDecoder) != MA_SUCCESS) + { + CUBOS_ERROR("Failed to initialize Decoder from data"); + } } -} -size_t MiniaudioBuffer::getLength() -{ - ma_uint64 lengthInPCMFrames; - ma_result result = ma_decoder_get_length_in_pcm_frames(&mDecoder, &lengthInPCMFrames); - - if (result != MA_SUCCESS) + ~MiniaudioBuffer() override { - CUBOS_ERROR("Failed to get the length of audio in PCM frames."); - return 0; + ma_decoder_uninit(&mDecoder); } - // Calculate the length in seconds: Length in PCM frames divided by the sample rate. - return static_cast(lengthInPCMFrames) / mDecoder.outputSampleRate; -} + size_t getLength() override + { + ma_uint64 lengthInPCMFrames; + ma_result result = ma_decoder_get_length_in_pcm_frames(&mDecoder, &lengthInPCMFrames); -MiniaudioBuffer::~MiniaudioBuffer() -{ - ma_decoder_uninit(&mDecoder); + if (result != MA_SUCCESS) + { + CUBOS_ERROR("Failed to get the length of audio in PCM frames."); + return 0; + } + + // Calculate the length in seconds: Length in PCM frames divided by the sample rate. + return static_cast(lengthInPCMFrames) / mDecoder.outputSampleRate; + } }; -MiniaudioSource::MiniaudioSource() +class MiniaudioSource : public impl::Source { - if (ma_engine_init(nullptr, &mEngine) != MA_SUCCESS) +public: + MiniaudioSource() { - CUBOS_CRITICAL("Failed to initialize miniaudio engine."); - abort(); + if (ma_engine_init(nullptr, &mEngine) != MA_SUCCESS) + { + CUBOS_FAIL("Failed to initialize miniaudio engine."); + abort(); + } } -} -MiniaudioSource::~MiniaudioSource() -{ - ma_sound_uninit(&mSound); - ma_engine_uninit(&mEngine); -} + ~MiniaudioSource() override + { + ma_sound_uninit(&mSound); + ma_engine_uninit(&mEngine); + } -void MiniaudioSource::setBuffer(Buffer buffer) -{ - if (ma_sound_init_from_data_source(&mEngine, &buffer->mDecoder, 0, nullptr, &mSound) != MA_SUCCESS) + void setBuffer(Buffer buffer) override { - CUBOS_CRITICAL("Failed to initialize sound from buffer."); - abort(); + // Try to dynamically cast the Buffer to a MiniaudioBuffer. + auto miniaudioBuffer = std::dynamic_pointer_cast(buffer); + + if (miniaudioBuffer == nullptr) + { + CUBOS_FAIL("Buffer is not of type MiniaudioBuffer."); + abort(); + } + + if (ma_sound_init_from_data_source(&mEngine, &miniaudioBuffer->mDecoder, 0, nullptr, &mSound) != MA_SUCCESS) + { + CUBOS_ERROR("Failed to initialize sound from buffer."); + abort(); + } } -} -void MiniaudioSource::setPosition(const glm::vec3& position) -{ - ma_sound_set_position(&mSound, position.x, position.y, position.z); -} + void setPosition(const glm::vec3& position) override + { + ma_sound_set_position(&mSound, position.x, position.y, position.z); + } -void MiniaudioSource::setVelocity(const glm::vec3& velocity) -{ - ma_sound_set_velocity(&mSound, velocity.x, velocity.y, velocity.z); -} + void setVelocity(const glm::vec3& velocity) override + { + ma_sound_set_velocity(&mSound, velocity.x, velocity.y, velocity.z); + } -void MiniaudioSource::setGain(float gain) -{ - ma_sound_set_volume(&mSound, gain); -} + void setGain(float gain) override + { + ma_sound_set_volume(&mSound, gain); + } -void MiniaudioSource::setPitch(float pitch) -{ - ma_sound_set_pitch(&mSound, pitch); -} + void setPitch(float pitch) override + { + ma_sound_set_pitch(&mSound, pitch); + } -void MiniaudioSource::setLooping(bool looping) -{ - ma_sound_set_looping(&mSound, static_cast(looping)); -} + void setLooping(bool looping) override + { + ma_sound_set_looping(&mSound, static_cast(looping)); + } -void MiniaudioSource::setRelative(bool relative) -{ - relative ? ma_sound_set_positioning(&mSound, ma_positioning_relative) - : ma_sound_set_positioning(&mSound, ma_positioning_absolute); -} + void setRelative(bool relative) override + { + relative ? ma_sound_set_positioning(&mSound, ma_positioning_relative) + : ma_sound_set_positioning(&mSound, ma_positioning_absolute); + } -void MiniaudioSource::setMaxDistance(float maxDistance) -{ - ma_sound_set_max_distance(&mSound, maxDistance); -} + void setMaxDistance(float maxDistance) override + { + ma_sound_set_max_distance(&mSound, maxDistance); + } -void MiniaudioSource::setMinDistance(float minDistance) -{ - ma_sound_set_min_distance(&mSound, minDistance); -} + void setMinDistance(float minDistance) override + { + ma_sound_set_min_distance(&mSound, minDistance); + } -void MiniaudioSource::setCone(float innerAngle, float outerAngle, float outerGain = 1.0F) -{ - ma_sound_set_cone(&mSound, innerAngle, outerAngle, outerGain); -} + void setCone(float innerAngle, float outerAngle, float outerGain = 1.0F) override + { + ma_sound_set_cone(&mSound, innerAngle, outerAngle, outerGain); + } -void MiniaudioSource::setConeDirection(const glm::vec3& direction) -{ - ma_sound_set_direction(&mSound, direction.x, direction.y, direction.z); -} + void setConeDirection(const glm::vec3& direction) override + { + ma_sound_set_direction(&mSound, direction.x, direction.y, direction.z); + } -void MiniaudioSource::play() -{ - if (ma_sound_start(&mSound) != MA_SUCCESS) + void play() override { - CUBOS_CRITICAL("Failed to start sound."); - abort(); + if (ma_sound_start(&mSound) != MA_SUCCESS) + { + CUBOS_ERROR("Failed to start sound."); + abort(); + } } -} + +private: + ma_sound mSound; + ma_engine mEngine; +}; MiniaudioDevice::MiniaudioDevice() { // Initialize miniaudio context. if (ma_context_init(nullptr, 0, nullptr, &mContext) != MA_SUCCESS) { - CUBOS_CRITICAL("Failed to initialize miniaudio context."); + CUBOS_FAIL("Failed to initialize miniaudio context."); abort(); } // Initialize miniaudio engine if (ma_engine_init(nullptr, &mEngine) != MA_SUCCESS) { - CUBOS_CRITICAL("Failed to initialize miniaudio engine."); + CUBOS_FAIL("Failed to initialize miniaudio engine."); abort(); } @@ -143,7 +164,7 @@ MiniaudioDevice::MiniaudioDevice() // Initialize the audio device. if (ma_device_init(&mContext, &deviceConfig, &mDevice) != MA_SUCCESS) { - CUBOS_CRITICAL("Failed to initialize audio device."); + CUBOS_FAIL("Failed to initialize audio device."); ma_context_uninit(&mContext); abort(); } @@ -153,7 +174,6 @@ MiniaudioDevice::MiniaudioDevice() MiniaudioDevice::~MiniaudioDevice() { - ma_device_uninit(&mDevice); ma_context_uninit(&mContext); } @@ -163,7 +183,7 @@ void MiniaudioDevice::enumerateDevices(std::vector& devices) ma_context context; if (ma_context_init(nullptr, 0, nullptr, &context) != MA_SUCCESS) { - CUBOS_CRITICAL("Failed to initialize audio context."); + CUBOS_ERROR("Failed to initialize audio context."); abort(); } @@ -171,7 +191,7 @@ void MiniaudioDevice::enumerateDevices(std::vector& devices) ma_uint32 playbackDeviceCount; if (ma_context_get_devices(&context, &pPlaybackDeviceInfos, &playbackDeviceCount, nullptr, nullptr) != MA_SUCCESS) { - CUBOS_CRITICAL("Failed to enumerate devices."); + CUBOS_FAIL("Failed to enumerate devices."); ma_context_uninit(&context); // Uninitialize context before aborting abort(); } @@ -189,7 +209,7 @@ std::string MiniaudioDevice::getDefaultDevice() ma_context context; if (ma_context_init(nullptr, 0, nullptr, &context) != MA_SUCCESS) { - CUBOS_CRITICAL("Failed to initialize audio context."); + CUBOS_FAIL("Failed to initialize audio context."); abort(); } @@ -213,12 +233,12 @@ std::string MiniaudioDevice::getDefaultDevice() Buffer MiniaudioDevice::createBuffer(const void* data, size_t dataSize) { - return MiniaudioBuffer::create(data, dataSize); + return std::make_shared(data, dataSize); } Source MiniaudioDevice::createSource() { - return MiniaudioSource::create(); + return std::make_shared(); } void MiniaudioDevice::setListenerPosition(const glm::vec3& position, ma_uint32 listenerIndex) diff --git a/engine/include/cubos/engine/audio/audio.hpp b/engine/include/cubos/engine/audio/audio.hpp index 82a9aca1fc..8b08d2801f 100644 --- a/engine/include/cubos/engine/audio/audio.hpp +++ b/engine/include/cubos/engine/audio/audio.hpp @@ -20,7 +20,7 @@ namespace cubos::engine std::shared_ptr mData; // Raw data of the audio size_t mLength; // Audio length in seconds TODO: add getter in audio - explicit Audio(core::memory::Stream& stream); + explicit Audio(std::shared_ptr device, core::memory::Stream& stream); Audio(Audio&& other) noexcept; ~Audio(); }; diff --git a/engine/include/cubos/engine/audio/bridge.hpp b/engine/include/cubos/engine/audio/bridge.hpp index 576afe8cdd..8da3b821c2 100644 --- a/engine/include/cubos/engine/audio/bridge.hpp +++ b/engine/include/cubos/engine/audio/bridge.hpp @@ -17,9 +17,12 @@ namespace cubos::engine class AudioBridge : public FileBridge { public: + std::shared_ptr mDevice; + /// @brief Constructs a bridge. - AudioBridge() + AudioBridge(std::shared_ptr device) : FileBridge(core::reflection::reflect