ADD: Async Sound Loading + AudioLayer
This commit is contained in:
parent
a5a97d141e
commit
a1936d666c
@ -198,6 +198,8 @@ add_library(Engine STATIC
|
|||||||
engine/src/core/audio/SoundBuffer.h
|
engine/src/core/audio/SoundBuffer.h
|
||||||
engine/src/core/audio/SoundSource.cpp
|
engine/src/core/audio/SoundSource.cpp
|
||||||
engine/src/core/audio/SoundSource.h
|
engine/src/core/audio/SoundSource.h
|
||||||
|
engine/src/loader/sounds/SoundUploader.cpp
|
||||||
|
engine/src/loader/sounds/SoundUploader.h
|
||||||
)
|
)
|
||||||
target_include_directories(Engine PUBLIC engine/src ${dr_libs_SOURCE_DIR})
|
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)
|
target_link_libraries(Engine PUBLIC OpenGL::GL glfw glad glm::glm imgui spdlog::spdlog tinyobjloader stb_image OpenAL::OpenAL)
|
||||||
@ -252,6 +254,8 @@ add_executable(ColorRace
|
|||||||
game/src/ludo/LudoAiController.h
|
game/src/ludo/LudoAiController.h
|
||||||
game/src/ludo/ecs/highlight/HighlightSystem.cpp
|
game/src/ludo/ecs/highlight/HighlightSystem.cpp
|
||||||
game/src/ludo/ecs/highlight/HighlightSystem.h
|
game/src/ludo/ecs/highlight/HighlightSystem.h
|
||||||
|
game/src/AudioLayer.cpp
|
||||||
|
game/src/AudioLayer.h
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
#include "EngineConfig.h"
|
#include "EngineConfig.h"
|
||||||
|
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
|
#include "audio/AudioDevice.h"
|
||||||
#include "inputsOutputs/context/InputContextStack.h"
|
#include "inputsOutputs/context/InputContextStack.h"
|
||||||
#include "inputsOutputs/inputs/Keyboard.h"
|
#include "inputsOutputs/inputs/Keyboard.h"
|
||||||
#include "inputsOutputs/inputs/Mouse.h"
|
#include "inputsOutputs/inputs/Mouse.h"
|
||||||
@ -41,6 +42,7 @@ namespace engine {
|
|||||||
Mouse m_mouse{*m_window};
|
Mouse m_mouse{*m_window};
|
||||||
SceneManager m_sceneManager{m_inputContextStack};
|
SceneManager m_sceneManager{m_inputContextStack};
|
||||||
ImGuiContext m_imguiContext{*m_window}; // neu
|
ImGuiContext m_imguiContext{*m_window}; // neu
|
||||||
|
engine::audio::AudioDevice m_audioDevice;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -10,28 +10,22 @@
|
|||||||
#include "AudioDevice.h"
|
#include "AudioDevice.h"
|
||||||
|
|
||||||
namespace engine::audio {
|
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() {
|
SoundBuffer::~SoundBuffer() {
|
||||||
if (m_bufferID) alDeleteBuffers(1, &m_bufferID);
|
if (m_bufferID) alDeleteBuffers(1, &m_bufferID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SoundBuffer::SoundBuffer(SoundBuffer &&other) noexcept : m_bufferID(other.m_bufferID) {
|
||||||
|
other.m_bufferID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundBuffer & SoundBuffer::operator=(SoundBuffer &&other) noexcept {
|
||||||
|
if (this != &other) {
|
||||||
|
release();
|
||||||
|
|
||||||
|
m_bufferID = other.m_bufferID;
|
||||||
|
other.m_bufferID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
} // engine
|
} // engine
|
||||||
@ -11,17 +11,28 @@
|
|||||||
namespace engine::audio {
|
namespace engine::audio {
|
||||||
class SoundBuffer {
|
class SoundBuffer {
|
||||||
public:
|
public:
|
||||||
explicit SoundBuffer(const std::string& path);
|
explicit SoundBuffer(ALuint bufferID) : m_bufferID(bufferID) {}
|
||||||
~SoundBuffer();
|
~SoundBuffer();
|
||||||
|
|
||||||
SoundBuffer(const SoundBuffer&) = delete;
|
SoundBuffer(const SoundBuffer&) = delete;
|
||||||
|
|
||||||
SoundBuffer& operator=(const SoundBuffer&) = delete;
|
SoundBuffer& operator=(const SoundBuffer&) = delete;
|
||||||
|
|
||||||
|
SoundBuffer(SoundBuffer&& other) noexcept;
|
||||||
|
SoundBuffer& operator=(SoundBuffer&& other) noexcept;
|
||||||
|
|
||||||
ALuint id() const {
|
ALuint id() const {
|
||||||
return m_bufferID;
|
return m_bufferID;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
ALuint m_bufferID = 0;
|
ALuint m_bufferID = 0;
|
||||||
|
|
||||||
|
void release() {
|
||||||
|
if (m_bufferID != 0) {
|
||||||
|
alDeleteBuffers(1, &m_bufferID);
|
||||||
|
m_bufferID = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // engine
|
} // engine
|
||||||
|
|
||||||
|
|||||||
@ -23,6 +23,24 @@ namespace engine::audio {
|
|||||||
SoundSource(const SoundSource&) = delete;
|
SoundSource(const SoundSource&) = delete;
|
||||||
SoundSource& operator=(const SoundSource&) = delete;
|
SoundSource& operator=(const SoundSource&) = delete;
|
||||||
|
|
||||||
|
SoundSource(SoundSource&& other) noexcept
|
||||||
|
: m_source(other.m_source)
|
||||||
|
{
|
||||||
|
other.m_source = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundSource& operator=(SoundSource&& other) noexcept
|
||||||
|
{
|
||||||
|
if (this != &other) {
|
||||||
|
release();
|
||||||
|
|
||||||
|
m_source = other.m_source;
|
||||||
|
other.m_source = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
void setBuffer(const SoundBuffer& buffer) {
|
void setBuffer(const SoundBuffer& buffer) {
|
||||||
alSourcei(m_source, AL_BUFFER, static_cast<ALint>(buffer.id()));
|
alSourcei(m_source, AL_BUFFER, static_cast<ALint>(buffer.id()));
|
||||||
checkAlError("alSourcei(AL_BUFFER)");
|
checkAlError("alSourcei(AL_BUFFER)");
|
||||||
@ -50,6 +68,14 @@ namespace engine::audio {
|
|||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
ALuint m_source = 0;
|
ALuint m_source = 0;
|
||||||
|
|
||||||
|
void release()
|
||||||
|
{
|
||||||
|
if (m_source != 0) {
|
||||||
|
alDeleteSources(1, &m_source);
|
||||||
|
m_source = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void updateListener(float px, float py, float pz,
|
inline void updateListener(float px, float py, float pz,
|
||||||
|
|||||||
@ -4,10 +4,12 @@
|
|||||||
|
|
||||||
#include "AssetLoader.h"
|
#include "AssetLoader.h"
|
||||||
|
|
||||||
|
#include <dr_wav.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "models/ModelImporter.h"
|
#include "models/ModelImporter.h"
|
||||||
#include "models/ModelUploader.h"
|
#include "models/ModelUploader.h"
|
||||||
|
#include "sounds/SoundUploader.h"
|
||||||
#include "spdlog/spdlog.h"
|
#include "spdlog/spdlog.h"
|
||||||
#include "textures/TextureImporter.h"
|
#include "textures/TextureImporter.h"
|
||||||
#include "textures/TextureUploader.h"
|
#include "textures/TextureUploader.h"
|
||||||
@ -25,6 +27,8 @@ void engine::AssetLoader::scheduleAsset(const AssetRequest &request) {
|
|||||||
spdlog::debug("Scheduled Texture Request: {} -> {}", req.name, req.path);
|
spdlog::debug("Scheduled Texture Request: {} -> {}", req.name, req.path);
|
||||||
} else if constexpr (std::is_same_v<Type, ModelRequest>) {
|
} else if constexpr (std::is_same_v<Type, ModelRequest>) {
|
||||||
spdlog::debug("Scheduled Model Request: {} -> {}", req.name, req.path);
|
spdlog::debug("Scheduled Model Request: {} -> {}", req.name, req.path);
|
||||||
|
} else if constexpr (std::is_same_v<Type, SoundRequest>) {
|
||||||
|
spdlog::debug("Scheduled Sound Request: {} -> {}", req.name, req.path);
|
||||||
}
|
}
|
||||||
}, request);
|
}, request);
|
||||||
}
|
}
|
||||||
@ -62,6 +66,9 @@ std::vector<engine::LoadedAsset> engine::AssetLoader::processUploadQueue(int max
|
|||||||
std::cout << "Moddel Assets" << modelAssets.size() << std::endl;
|
std::cout << "Moddel Assets" << modelAssets.size() << std::endl;
|
||||||
result.insert(result.end(), modelAssets.begin(), modelAssets.end());
|
result.insert(result.end(), modelAssets.begin(), modelAssets.end());
|
||||||
std::cout << "Result size" << result.size() << std::endl;
|
std::cout << "Result size" << result.size() << std::endl;
|
||||||
|
} else if constexpr (std::is_same_v<T, RawSoundData>) {
|
||||||
|
auto soundAsset = SoundUploader::upload(rawData);
|
||||||
|
result.emplace_back(LoadedSound{rawData.name, std::make_shared<audio::SoundBuffer>(std::move(soundAsset))});
|
||||||
} else {
|
} else {
|
||||||
static_assert(
|
static_assert(
|
||||||
always_false<T>,
|
always_false<T>,
|
||||||
@ -104,6 +111,10 @@ void engine::AssetLoader::loadingThreadFunc() {
|
|||||||
return processTextureRequest(req);
|
return processTextureRequest(req);
|
||||||
} else if constexpr (std::is_same_v<T, ModelRequest>) {
|
} else if constexpr (std::is_same_v<T, ModelRequest>) {
|
||||||
return processModelRequest(req);
|
return processModelRequest(req);
|
||||||
|
} else if constexpr (std::is_same_v<T, SoundRequest>) {
|
||||||
|
return processSoundRequest(req);
|
||||||
|
} else {
|
||||||
|
static_assert(always_false<T>, "Unhandled asset type in AssetLoader::loadingThreadFunc");
|
||||||
}
|
}
|
||||||
}, request);
|
}, request);
|
||||||
|
|
||||||
@ -128,6 +139,35 @@ engine::RawModelBundle engine::AssetLoader::processModelRequest(const ModelReque
|
|||||||
return modelData;
|
return modelData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
engine::RawSoundData engine::AssetLoader::processSoundRequest(const SoundRequest &request) {
|
||||||
|
RawSoundData soundData;
|
||||||
|
unsigned int channels, sampleRate;
|
||||||
|
drwav_uint64 frameCount;
|
||||||
|
|
||||||
|
drwav_int16* pcmData = drwav_open_file_and_read_pcm_frames_s16(
|
||||||
|
request.path.c_str(), &channels, &sampleRate, &frameCount, nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!pcmData) {
|
||||||
|
throw std::runtime_error("Failed to load sound file: " + request.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
soundData.name = request.name;
|
||||||
|
soundData.channels = channels;
|
||||||
|
soundData.sampleRate = sampleRate;
|
||||||
|
soundData.bitsPerSample = 16;
|
||||||
|
size_t dataSize = frameCount * channels * sizeof(drwav_int16);
|
||||||
|
soundData.pcmData.resize(dataSize);
|
||||||
|
std::memcpy(
|
||||||
|
soundData.pcmData.data(),
|
||||||
|
pcmData,
|
||||||
|
dataSize
|
||||||
|
);
|
||||||
|
drwav_free(pcmData, nullptr);
|
||||||
|
|
||||||
|
return soundData;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<engine::IntermediateAsset> engine::AssetLoader::determineUploadQueue(int maxPerFrame) {
|
std::vector<engine::IntermediateAsset> engine::AssetLoader::determineUploadQueue(int maxPerFrame) {
|
||||||
std::vector<IntermediateAsset> result;
|
std::vector<IntermediateAsset> result;
|
||||||
std::lock_guard lock(readyMutex);
|
std::lock_guard lock(readyMutex);
|
||||||
|
|||||||
@ -46,6 +46,7 @@ inline constexpr bool always_false = false;
|
|||||||
|
|
||||||
static RawTextureData processTextureRequest(const TextureRequest& request);
|
static RawTextureData processTextureRequest(const TextureRequest& request);
|
||||||
static RawModelBundle processModelRequest(const ModelRequest& request);
|
static RawModelBundle processModelRequest(const ModelRequest& request);
|
||||||
|
static RawSoundData processSoundRequest(const SoundRequest& request);
|
||||||
std::vector<IntermediateAsset> determineUploadQueue(int maxPerFrame);
|
std::vector<IntermediateAsset> determineUploadQueue(int maxPerFrame);
|
||||||
|
|
||||||
std::queue<AssetRequest> pendingQueue;
|
std::queue<AssetRequest> pendingQueue;
|
||||||
|
|||||||
@ -28,6 +28,8 @@ void engine::AssetManager::insertAsset(LoadedAsset loadedAsset) {
|
|||||||
insertModel(loaded.name, loaded.model);
|
insertModel(loaded.name, loaded.model);
|
||||||
} else if constexpr (std::is_same_v<T, LoadedTexture>) {
|
} else if constexpr (std::is_same_v<T, LoadedTexture>) {
|
||||||
insertTexture(loaded.name, loaded.texture);
|
insertTexture(loaded.name, loaded.texture);
|
||||||
|
} else if constexpr (std::is_same_v<T, LoadedSound>) {
|
||||||
|
insertSound(loaded.name, loaded.sound);
|
||||||
}
|
}
|
||||||
}, loadedAsset);
|
}, loadedAsset);
|
||||||
}
|
}
|
||||||
@ -61,3 +63,24 @@ void engine::AssetManager::insertTexture(const std::string &name, std::shared_pt
|
|||||||
void engine::AssetManager::unloadTexture(const std::string &name) {
|
void engine::AssetManager::unloadTexture(const std::string &name) {
|
||||||
m_textures.erase(name);
|
m_textures.erase(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<engine::audio::SoundBuffer> engine::AssetManager::getSound(const std::string &name) const {
|
||||||
|
auto it = m_loadedAssets.find(name);
|
||||||
|
if (it == m_loadedAssets.end()) {
|
||||||
|
throw std::runtime_error("Sound not found: " + name);
|
||||||
|
}
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool engine::AssetManager::hasSound(const std::string &name) const {
|
||||||
|
return m_loadedAssets.contains(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void engine::AssetManager::insertSound(const std::string &name, std::shared_ptr<audio::SoundBuffer> sound) {
|
||||||
|
std::cout << "Inserting sound " << name << std::endl;
|
||||||
|
m_loadedAssets[name] = std::move(sound);
|
||||||
|
}
|
||||||
|
|
||||||
|
void engine::AssetManager::unloadSound(const std::string &name) {
|
||||||
|
m_loadedAssets.erase(name);
|
||||||
|
}
|
||||||
|
|||||||
@ -29,10 +29,16 @@ namespace engine {
|
|||||||
void insertTexture(const std::string& name, std::shared_ptr<Texture2D> texture);
|
void insertTexture(const std::string& name, std::shared_ptr<Texture2D> texture);
|
||||||
void unloadTexture(const std::string& name);
|
void unloadTexture(const std::string& name);
|
||||||
|
|
||||||
|
std::shared_ptr<audio::SoundBuffer> getSound(const std::string& name) const;
|
||||||
|
bool hasSound(const std::string& name) const;
|
||||||
|
void insertSound(const std::string& name, std::shared_ptr<audio::SoundBuffer> sound);
|
||||||
|
void unloadSound(const std::string& name);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string, std::shared_ptr<Texture2D>> m_textures;
|
std::unordered_map<std::string, std::shared_ptr<Texture2D>> m_textures;
|
||||||
std::unordered_map<std::string, std::shared_ptr<Model>> m_models;
|
std::unordered_map<std::string, std::shared_ptr<Model>> m_models;
|
||||||
|
std::unordered_map<std::string, std::shared_ptr<audio::SoundBuffer>> m_loadedAssets;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,9 @@
|
|||||||
#include <format>
|
#include <format>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "RawAssetData.h"
|
||||||
|
#include "loader/AssetLoader.h"
|
||||||
|
|
||||||
|
|
||||||
namespace engine {
|
namespace engine {
|
||||||
|
|
||||||
@ -27,17 +30,21 @@ namespace engine {
|
|||||||
req.name,
|
req.name,
|
||||||
req.path
|
req.path
|
||||||
);
|
);
|
||||||
}
|
} else if constexpr(std::is_same_v<Type, ModelRequest>)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
return std::format(
|
return std::format(
|
||||||
"ModelRequest{{name='{}', path='{}'}}",
|
"ModelRequest{{name='{}', path='{}'}}",
|
||||||
req.name,
|
req.name,
|
||||||
req.path
|
req.path
|
||||||
);
|
);
|
||||||
|
} else if constexpr(std::is_same_v<Type, SoundRequest>){
|
||||||
|
return std::format(
|
||||||
|
"SoundRequest{{name='{}', path='{}'}}",
|
||||||
|
req.name,
|
||||||
|
req.path);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
request);
|
request);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,11 +28,17 @@ namespace engine {
|
|||||||
ModelSplitPolicy splitPolicy = ModelSplitPolicy::Combined;
|
ModelSplitPolicy splitPolicy = ModelSplitPolicy::Combined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SoundRequest {
|
||||||
|
std::string name;
|
||||||
|
std::string path;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
using AssetRequest =
|
using AssetRequest =
|
||||||
std::variant<
|
std::variant<
|
||||||
TextureRequest,
|
TextureRequest,
|
||||||
ModelRequest
|
ModelRequest,
|
||||||
|
SoundRequest
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,8 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
|
#include "core/audio/SoundBuffer.h"
|
||||||
#include "loader/textures/Texture2D.h"
|
#include "loader/textures/Texture2D.h"
|
||||||
#include "loader/models/Model.h"
|
#include "loader/models/Model.h"
|
||||||
|
|
||||||
@ -24,7 +26,12 @@ namespace engine {
|
|||||||
std::shared_ptr<Model> model;
|
std::shared_ptr<Model> model;
|
||||||
};
|
};
|
||||||
|
|
||||||
using LoadedAsset = std::variant<LoadedTexture, LoadedModel>;
|
struct LoadedSound {
|
||||||
|
std::string name;
|
||||||
|
std::shared_ptr<audio::SoundBuffer> sound;
|
||||||
|
};
|
||||||
|
|
||||||
|
using LoadedAsset = std::variant<LoadedTexture, LoadedModel, LoadedSound>;
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif //COLORRACE_LOADEDASSETS_H
|
#endif //COLORRACE_LOADEDASSETS_H
|
||||||
|
|||||||
@ -76,11 +76,20 @@ namespace engine {
|
|||||||
std::vector<RawTextureData> textures;
|
std::vector<RawTextureData> textures;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct RawSoundData {
|
||||||
|
std::string name;
|
||||||
|
std::vector<std::byte> pcmData;
|
||||||
|
int channels;
|
||||||
|
int sampleRate;
|
||||||
|
int bitsPerSample;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
using IntermediateAsset =
|
using IntermediateAsset =
|
||||||
std::variant<
|
std::variant<
|
||||||
RawTextureData,
|
RawTextureData,
|
||||||
RawModelBundle
|
RawModelBundle,
|
||||||
|
RawSoundData
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
41
engine/src/loader/sounds/SoundUploader.cpp
Normal file
41
engine/src/loader/sounds/SoundUploader.cpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 04.08.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "SoundUploader.h"
|
||||||
|
|
||||||
|
#include <dr_wav.h>
|
||||||
|
|
||||||
|
#include "core/audio/AudioDevice.h"
|
||||||
|
|
||||||
|
engine::audio::SoundBuffer engine::SoundUploader::upload(const RawSoundData &data) {
|
||||||
|
auto* context = alcGetCurrentContext();
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
std::cerr << "NO OPENAL CONTEXT IN UPLOAD THREAD\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
ALenum format;
|
||||||
|
if (data.channels == 1) {
|
||||||
|
format = AL_FORMAT_MONO16;
|
||||||
|
} else if (data.channels == 2) {
|
||||||
|
format = AL_FORMAT_STEREO16;
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Unsupported channel count");
|
||||||
|
}
|
||||||
|
|
||||||
|
ALuint bufferID = 0;
|
||||||
|
alGenBuffers(1, &bufferID);
|
||||||
|
|
||||||
|
alBufferData(
|
||||||
|
bufferID,
|
||||||
|
format,
|
||||||
|
data.pcmData.data(),
|
||||||
|
static_cast<ALsizei>(data.pcmData.size()),
|
||||||
|
data.sampleRate
|
||||||
|
);
|
||||||
|
|
||||||
|
audio::checkAlError("alBufferData");
|
||||||
|
|
||||||
|
return audio::SoundBuffer(bufferID);
|
||||||
|
}
|
||||||
19
engine/src/loader/sounds/SoundUploader.h
Normal file
19
engine/src/loader/sounds/SoundUploader.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 04.08.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COLORRACE_SOUNDUPLOADER_H
|
||||||
|
#define COLORRACE_SOUNDUPLOADER_H
|
||||||
|
#include "loader/assets/LoadedAssets.h"
|
||||||
|
#include "loader/assets/RawAssetData.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace engine {
|
||||||
|
class SoundUploader {
|
||||||
|
public:
|
||||||
|
static audio::SoundBuffer upload(const RawSoundData& data);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif //COLORRACE_SOUNDUPLOADER_H
|
||||||
28
game/src/AudioLayer.cpp
Normal file
28
game/src/AudioLayer.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 04.08.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "AudioLayer.h"
|
||||||
|
|
||||||
|
#include "GLFW/glfw3.h"
|
||||||
|
|
||||||
|
void ludo::AudioLayer::onUpdate(float deltaTime) {
|
||||||
|
Layer::onUpdate(deltaTime);
|
||||||
|
if (getKeyboard().keyPressEvent(GLFW_KEY_P)) {
|
||||||
|
for (auto& soundSource : soundSources) {
|
||||||
|
soundSource.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ludo::AudioLayer::onAttachImpl() {
|
||||||
|
Layer::onAttachImpl();
|
||||||
|
auto rollingDiceSoundBufffer = m_assetManager.getSound("rolling_dice");
|
||||||
|
|
||||||
|
auto rollingDiceSoundSource = engine::audio::SoundSource();
|
||||||
|
rollingDiceSoundSource.setBuffer(*rollingDiceSoundBufffer);
|
||||||
|
rollingDiceSoundSource.setPosition(0.0f, 0.0f, 0.0f);
|
||||||
|
rollingDiceSoundSource.setGain(1.0f);
|
||||||
|
|
||||||
|
soundSources.push_back(std::move(rollingDiceSoundSource));
|
||||||
|
}
|
||||||
29
game/src/AudioLayer.h
Normal file
29
game/src/AudioLayer.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// Created by sebastian on 04.08.26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef COLORRACE_AUDIOLAYER_H
|
||||||
|
#define COLORRACE_AUDIOLAYER_H
|
||||||
|
#include "core/audio/SoundSource.h"
|
||||||
|
#include "layer/Layer.h"
|
||||||
|
#include "loader/assets/AssetManager.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace ludo {
|
||||||
|
class AudioLayer :public engine::Layer {
|
||||||
|
public:
|
||||||
|
AudioLayer(engine::AssetManager& assetManager, engine::Keyboard &keyboard, engine::Mouse &mouse): Layer(keyboard, mouse), m_assetManager(assetManager) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void onUpdate(float deltaTime) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onAttachImpl() override;
|
||||||
|
private:
|
||||||
|
engine::AssetManager& m_assetManager;
|
||||||
|
std::vector<engine::audio::SoundSource> soundSources;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //COLORRACE_AUDIOLAYER_H
|
||||||
@ -26,12 +26,6 @@ void GameLayer::onAttachImpl() {
|
|||||||
|
|
||||||
m_cameraController = std::make_unique<engine::CameraController>(getInputStack(), getInputContext());
|
m_cameraController = std::make_unique<engine::CameraController>(getInputStack(), getInputContext());
|
||||||
m_piecePresenter.spawnPieces(m_gameMode->getState());
|
m_piecePresenter.spawnPieces(m_gameMode->getState());
|
||||||
|
|
||||||
try {
|
|
||||||
m_soundBuffer = std::make_unique<audio::SoundBuffer>("assets/sounds/rolling_dice.wav");
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
std::cerr <<"Audiofehler: " << e.what() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameLayer::onDetachImpl() {
|
void GameLayer::onDetachImpl() {
|
||||||
@ -87,18 +81,6 @@ void GameLayer::onUpdate(float deltaTime) {
|
|||||||
m_gameMode->sendCommand(ludo::MovePieceCommand{m_localPlayer, *pieceIndex});
|
m_gameMode->sendCommand(ludo::MovePieceCommand{m_localPlayer, *pieceIndex});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
void GameLayer::onRender() {
|
||||||
|
|||||||
@ -59,7 +59,7 @@ private:
|
|||||||
|
|
||||||
std::vector<ludo::LudoAiController> aiControllers;
|
std::vector<ludo::LudoAiController> aiControllers;
|
||||||
|
|
||||||
engine::audio::AudioDevice m_audioDevice;
|
|
||||||
std::unique_ptr<engine::audio::SoundBuffer> m_soundBuffer;
|
std::unique_ptr<engine::audio::SoundBuffer> m_soundBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "GameScene.h"
|
#include "GameScene.h"
|
||||||
|
|
||||||
|
#include "AudioLayer.h"
|
||||||
#include "GameLayer.h"
|
#include "GameLayer.h"
|
||||||
#include "core/inputsOutputs/inputs/Mouse.h"
|
#include "core/inputsOutputs/inputs/Mouse.h"
|
||||||
#include "ecs/standardComponents/MeshComponent.h"
|
#include "ecs/standardComponents/MeshComponent.h"
|
||||||
@ -38,6 +39,7 @@ void GameScene::onEnter() {
|
|||||||
pieceModels["Green"] = assetManager->getModel("pawn_green");
|
pieceModels["Green"] = assetManager->getModel("pawn_green");
|
||||||
pieceModels["Yellow"] = assetManager->getModel("pawn_yellow");
|
pieceModels["Yellow"] = assetManager->getModel("pawn_yellow");
|
||||||
|
|
||||||
|
addLayer(std::make_unique<ludo::AudioLayer>(*assetManager, m_keyboard, m_mouse));
|
||||||
addLayer(std::make_unique<engine::DebugLayer>(*m_camera, entityRegistry, m_keyboard, m_mouse, engine::SphereFactory::createUVSphere(1.0f)));
|
addLayer(std::make_unique<engine::DebugLayer>(*m_camera, entityRegistry, m_keyboard, m_mouse, engine::SphereFactory::createUVSphere(1.0f)));
|
||||||
addLayer(std::make_unique<GameLayer>(m_gameMode, entityRegistry, m_camera, m_pointLight, m_keyboard, m_mouse, assetManager->getModel("gameboard"), pieceModels));
|
addLayer(std::make_unique<GameLayer>(m_gameMode, entityRegistry, m_camera, m_pointLight, m_keyboard, m_mouse, assetManager->getModel("gameboard"), pieceModels));
|
||||||
|
|
||||||
@ -54,5 +56,6 @@ std::vector<engine::AssetRequest> GameScene::getRequiredAssets() const {
|
|||||||
requests.emplace_back(engine::ModelRequest{"pawn_green", "assets/models/chess_green.obj", engine::ModelSplitPolicy::Combined});
|
requests.emplace_back(engine::ModelRequest{"pawn_green", "assets/models/chess_green.obj", engine::ModelSplitPolicy::Combined});
|
||||||
requests.emplace_back(engine::ModelRequest{"pawn_yellow", "assets/models/chess_yellow.obj", engine::ModelSplitPolicy::Combined});
|
requests.emplace_back(engine::ModelRequest{"pawn_yellow", "assets/models/chess_yellow.obj", engine::ModelSplitPolicy::Combined});
|
||||||
requests.emplace_back(engine::ModelRequest{ "gameboard", "assets/models/GameBoard.obj", engine::ModelSplitPolicy::Combined});
|
requests.emplace_back(engine::ModelRequest{ "gameboard", "assets/models/GameBoard.obj", engine::ModelSplitPolicy::Combined});
|
||||||
|
requests.emplace_back(engine::SoundRequest{ "rolling_dice", "assets/sounds/rolling_dice.wav"});
|
||||||
return requests;
|
return requests;
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user