diff --git a/CMakeLists.txt b/CMakeLists.txt index 99112c0..8afe3ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,6 +83,29 @@ target_link_libraries(imgui PUBLIC glfw glad) add_library(glad STATIC third_party/glad/src/glad.c) target_include_directories(glad PUBLIC third_party/glad/include) +# --- OpenAL-Soft --- +CPMAddPackage( + NAME openal-soft + GITHUB_REPOSITORY kcat/openal-soft + GIT_TAG 1.24.3 + OPTIONS + "LIBTYPE STATIC" + "ALSOFT_UTILS OFF" + "ALSOFT_EXAMPLES OFF" + "ALSOFT_TESTS OFF" + "ALSOFT_INSTALL OFF" +) + +# --- dr_libs (dr_wav.h, dr_mp3.h – header-only) --- +CPMAddPackage( + NAME dr_libs + GITHUB_REPOSITORY mackron/dr_libs + GIT_TAG master + DOWNLOAD_ONLY YES +) + +message(STATUS "dr_libs_SOURCE_DIR = ${dr_libs_SOURCE_DIR}") + # Engine als statische Lib add_library(Engine STATIC engine/src/core/Window.h @@ -102,8 +125,6 @@ add_library(Engine STATIC engine/src/utils/openglWrapper/openglObjects/Vao.h engine/src/utils/openglWrapper/shader/ShaderProgram.cpp engine/src/utils/openglWrapper/shader/ShaderProgram.h - engine/src/renderer/primitives/CubeFactory.cpp - engine/src/renderer/primitives/CubeFactory.h engine/src/renderer/primitives/SphereFactory.cpp engine/src/renderer/primitives/SphereFactory.h engine/src/utils/openglWrapper/shader/Uniform.cpp @@ -170,19 +191,22 @@ add_library(Engine STATIC engine/src/loader/models/AABB.h engine/src/loader/models/Ray.h engine/src/ecs/standardComponents/HighlightComponent.h + third_party/audio_impl.cpp + engine/src/core/audio/AudioDevice.cpp + engine/src/core/audio/AudioDevice.h + engine/src/core/audio/SoundBuffer.cpp + engine/src/core/audio/SoundBuffer.h + engine/src/core/audio/SoundSource.cpp + engine/src/core/audio/SoundSource.h ) -target_include_directories(Engine PUBLIC engine/src) -target_link_libraries(Engine PUBLIC OpenGL::GL glfw glad glm::glm imgui spdlog::spdlog tinyobjloader stb_image) +target_include_directories(Engine PUBLIC engine/src ${dr_libs_SOURCE_DIR}) +target_link_libraries(Engine PUBLIC OpenGL::GL glfw glad glm::glm imgui spdlog::spdlog tinyobjloader stb_image OpenAL::OpenAL) # --- Executable --- add_executable(ColorRace game/src/main.cpp game/src/ColorRaceApp.cpp game/src/ColorRaceApp.h - engine/src/renderer/model/RawModel.cpp - engine/src/renderer/model/RawModel.h - engine/src/renderer/entities/Entity.cpp - engine/src/renderer/entities/Entity.h engine/src/renderer/shader/StaticShader.cpp engine/src/renderer/shader/StaticShader.h engine/src/renderer/entities/Camera.cpp diff --git a/assets/sounds/rolling_dice.wav b/assets/sounds/rolling_dice.wav new file mode 100644 index 0000000..81b87f5 Binary files /dev/null and b/assets/sounds/rolling_dice.wav differ diff --git a/engine/src/core/audio/AudioDevice.cpp b/engine/src/core/audio/AudioDevice.cpp new file mode 100644 index 0000000..4b78297 --- /dev/null +++ b/engine/src/core/audio/AudioDevice.cpp @@ -0,0 +1,24 @@ +// +// Created by sebastian on 04.08.26. +// + +#include "AudioDevice.h" + +engine::audio::AudioDevice::AudioDevice() { + m_device = alcOpenDevice(nullptr); + if (!m_device) { + throw std::runtime_error("Kein Audio-Device gefunden"); + } + + m_context = alcCreateContext(m_device, nullptr); + if (!m_context) { + throw std::runtime_error("Kein Audio-Context gefunden"); + } + alcMakeContextCurrent(m_context); +} + +engine::audio::AudioDevice::~AudioDevice() { + alcMakeContextCurrent(nullptr); + if (m_context) alcDestroyContext(m_context); + if (m_device) alcCloseDevice(m_device); +} diff --git a/engine/src/core/audio/AudioDevice.h b/engine/src/core/audio/AudioDevice.h new file mode 100644 index 0000000..a82c33d --- /dev/null +++ b/engine/src/core/audio/AudioDevice.h @@ -0,0 +1,37 @@ +// +// Created by sebastian on 04.08.26. +// + +#ifndef COLORRACE_AUDIODEVICE_H +#define COLORRACE_AUDIODEVICE_H +#include +#include + +#include "al.h" +#include "alc.h" + + +namespace engine::audio { + class AudioDevice { + public: + AudioDevice(); + + ~AudioDevice(); + // Kein Kopieren/Verschieben nötig für den Anfang + AudioDevice(const AudioDevice&) = delete; + AudioDevice& operator=(const AudioDevice&) = delete; + private: + ALCdevice* m_device = nullptr; + ALCcontext* m_context = nullptr; + }; + + inline void checkAlError(const char* location) { + ALenum err = alGetError(); + if (err != AL_NO_ERROR) { + std::cerr << "OpenAL Error: " << alGetString(err) << " at " << location << std::endl; + } + } +} + + +#endif //COLORRACE_AUDIODEVICE_H diff --git a/engine/src/core/audio/SoundBuffer.cpp b/engine/src/core/audio/SoundBuffer.cpp new file mode 100644 index 0000000..f3f092d --- /dev/null +++ b/engine/src/core/audio/SoundBuffer.cpp @@ -0,0 +1,37 @@ +// +// Created by sebastian on 04.08.26. +// + +#include "SoundBuffer.h" + +#include +#include + +#include "AudioDevice.h" + +namespace engine::audio { + SoundBuffer::SoundBuffer(const std::string &path) { + unsigned int channels, sampleRate; + drwav_uint64 frameCount; + + drwav_int16* pcmData = drwav_open_file_and_read_pcm_frames_s16( + path.c_str(), &channels, &sampleRate, &frameCount, nullptr + ); + + if (!pcmData) { + throw std::runtime_error("Failed to load sound file: " + path); + } + + ALenum format = (channels == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16; + drwav_uint64 dataSize = frameCount * channels * sizeof(drwav_int16); + + alGenBuffers(1, &m_bufferID); + alBufferData(m_bufferID, format, pcmData, dataSize, sampleRate); + checkAlError("alBufferData"); + drwav_free(pcmData, nullptr); + } + + SoundBuffer::~SoundBuffer() { + if (m_bufferID) alDeleteBuffers(1, &m_bufferID); + } +} // engine \ No newline at end of file diff --git a/engine/src/core/audio/SoundBuffer.h b/engine/src/core/audio/SoundBuffer.h new file mode 100644 index 0000000..7e2ea58 --- /dev/null +++ b/engine/src/core/audio/SoundBuffer.h @@ -0,0 +1,28 @@ +// +// Created by sebastian on 04.08.26. +// + +#ifndef COLORRACE_SOUNDBUFFER_H +#define COLORRACE_SOUNDBUFFER_H +#include + +#include "al.h" + +namespace engine::audio { + class SoundBuffer { + public: + explicit SoundBuffer(const std::string& path); + ~SoundBuffer(); + + SoundBuffer(const SoundBuffer&) = delete; + SoundBuffer& operator=(const SoundBuffer&) = delete; + + ALuint id() const { + return m_bufferID; + } + private: + ALuint m_bufferID = 0; + }; +} // engine + +#endif //COLORRACE_SOUNDBUFFER_H diff --git a/engine/src/core/audio/SoundSource.cpp b/engine/src/core/audio/SoundSource.cpp new file mode 100644 index 0000000..5d6ddca --- /dev/null +++ b/engine/src/core/audio/SoundSource.cpp @@ -0,0 +1,8 @@ +// +// Created by sebastian on 04.08.26. +// + +#include "SoundSource.h" + +namespace engine { +} // engine \ No newline at end of file diff --git a/engine/src/core/audio/SoundSource.h b/engine/src/core/audio/SoundSource.h new file mode 100644 index 0000000..5737de0 --- /dev/null +++ b/engine/src/core/audio/SoundSource.h @@ -0,0 +1,64 @@ +// +// Created by sebastian on 04.08.26. +// + +#ifndef COLORRACE_SOUNDSOURCE_H +#define COLORRACE_SOUNDSOURCE_H +#include "al.h" +#include "AudioDevice.h" +#include "SoundBuffer.h" + +namespace engine::audio { + + class SoundSource { + public: + SoundSource() { + alGenSources(1, &m_source); + } + + ~SoundSource() { + if (m_source) alDeleteSources(1, &m_source); + } + + SoundSource(const SoundSource&) = delete; + SoundSource& operator=(const SoundSource&) = delete; + + void setBuffer(const SoundBuffer& buffer) { + alSourcei(m_source, AL_BUFFER, static_cast(buffer.id())); + checkAlError("alSourcei(AL_BUFFER)"); + } + + void setPosition(float x, float y, float z) { + alSource3f(m_source, AL_POSITION, x, y, z); + } + + void setGain(float gain) { + alSourcef(m_source, AL_GAIN, gain); + } + + void setLooping(bool loop) { + alSourcei(m_source, AL_LOOPING, loop ? AL_TRUE : AL_FALSE); + } + + void play() { alSourcePlay(m_source); } + void stop() { alSourceStop(m_source); } + + bool isPlaying() const { + ALint state; + alGetSourcei(m_source, AL_SOURCE_STATE, &state); + return state == AL_PLAYING; + } + private: + ALuint m_source = 0; + }; + + inline void updateListener(float px, float py, float pz, + float fx, float fy, float fz, + float ux, float uy, float uz) { + alListener3f(AL_POSITION, px, py, pz); + ALfloat orientation[] = { fx, fy, fz, ux, uy, uz }; + alListenerfv(AL_ORIENTATION, orientation); + } +} // engine + +#endif //COLORRACE_SOUNDSOURCE_H diff --git a/engine/src/renderer/RenderQueue.h b/engine/src/renderer/RenderQueue.h index 5891608..2c6aecd 100644 --- a/engine/src/renderer/RenderQueue.h +++ b/engine/src/renderer/RenderQueue.h @@ -10,7 +10,6 @@ #include "glm/glm.hpp" #include "loader/models/Model.h" -#include "model/RawModel.h" namespace engine { struct RenderCommand { diff --git a/game/src/ColorRaceApp.h b/game/src/ColorRaceApp.h index 8c1f51a..1563e7e 100644 --- a/game/src/ColorRaceApp.h +++ b/game/src/ColorRaceApp.h @@ -13,7 +13,6 @@ #include "layer/SceneManager.h" #include "renderer/MeshRenderer.h" #include "renderer/entities/Camera.h" -#include "renderer/primitives/CubeFactory.h" #include "renderer/shader/StaticShader.h" #include "utils/openglWrapper/GLRenderState.h" #include "utils/openglWrapper/openglObjects/Vao.h" diff --git a/game/src/GameLayer.cpp b/game/src/GameLayer.cpp index 2841d3a..6dd9411 100644 --- a/game/src/GameLayer.cpp +++ b/game/src/GameLayer.cpp @@ -12,9 +12,11 @@ #include "ecs/standardComponents/TransformComponent.h" #include "renderer/MeshRenderer.h" #include "renderer/MeshRenderSystem.h" -#include "renderer/primitives/CubeFactory.h" #define GLM_ENABLE_EXPERIMENTAL #include + +#include "core/audio/SoundSource.h" +#include "GLFW/glfw3.h" using namespace engine; void GameLayer::onAttachImpl() { m_renderState.depthTesting = false; @@ -24,6 +26,12 @@ void GameLayer::onAttachImpl() { m_cameraController = std::make_unique(getInputStack(), getInputContext()); m_piecePresenter.spawnPieces(m_gameMode->getState()); + + try { + m_soundBuffer = std::make_unique("assets/sounds/rolling_dice.wav"); + } catch (const std::exception& e) { + std::cerr <<"Audiofehler: " << e.what() << std::endl; + } } void GameLayer::onDetachImpl() { @@ -80,7 +88,17 @@ void GameLayer::onUpdate(float deltaTime) { } } + if (getKeyboard().keyPressEvent(GLFW_KEY_P)) { + audio::SoundSource source; + source.setBuffer(*m_soundBuffer); + source.setPosition(0.0f, 0.0f, 0.0f); + source.setGain(1.0f); + source.play(); + while (source.isPlaying()) { + + } + } } void GameLayer::onRender() { diff --git a/game/src/GameLayer.h b/game/src/GameLayer.h index 650adbd..0d23c87 100644 --- a/game/src/GameLayer.h +++ b/game/src/GameLayer.h @@ -6,6 +6,8 @@ #define COLORRACE_GAMELAYER_H #include +#include "core/audio/AudioDevice.h" +#include "core/audio/SoundBuffer.h" #include "core/inputsOutputs/controller/CameraController.h" #include "ecs/EntityRegistry.h" #include "ecs/systems/PickingSystem.h" @@ -57,6 +59,10 @@ private: std::vector aiControllers; + engine::audio::AudioDevice m_audioDevice; + std::unique_ptr m_soundBuffer; + + void renderHud(); }; diff --git a/third_party/audio_impl.cpp b/third_party/audio_impl.cpp new file mode 100644 index 0000000..6670765 --- /dev/null +++ b/third_party/audio_impl.cpp @@ -0,0 +1,9 @@ +// +// Created by sebastian on 04.08.26. +// +// audio_impl.cpp +#define DR_WAV_IMPLEMENTATION +#include "dr_wav.h" + +#define STB_VORBIS_IMPLEMENTATION // falls du Vorbis nutzt +#include "stb_vorbis.c" \ No newline at end of file