mirror of
https://github.com/antopilo/Nuake.git
synced 2026-09-09 20:08:57 +03:00
Audio engine can now play sounds
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include "src/Scene/Systems/QuakeMapBuilder.h"
|
||||
#include <src/Core/FileSystem.h>
|
||||
|
||||
|
||||
class QuakeMapPanel : ComponentPanel {
|
||||
|
||||
public:
|
||||
|
||||
@@ -118,9 +118,10 @@ void EditorSelectionPanel::DrawEntity(Nuake::Entity entity)
|
||||
|
||||
void EditorSelectionPanel::DrawAddComponentMenu(Nuake::Entity entity)
|
||||
{
|
||||
if (entity.HasComponent<Nuake::NameComponent>())
|
||||
using namespace Nuake;
|
||||
if (entity.HasComponent<NameComponent>())
|
||||
{
|
||||
auto& entityName = entity.GetComponent<Nuake::NameComponent>().Name;
|
||||
auto& entityName = entity.GetComponent<NameComponent>().Name;
|
||||
ImGuiTextSTD("##Name", entityName);
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -129,27 +130,27 @@ void EditorSelectionPanel::DrawAddComponentMenu(Nuake::Entity entity)
|
||||
|
||||
if (ImGui::BeginPopup("ComponentPopup"))
|
||||
{
|
||||
MenuItemComponent("Wren Script", Nuake::WrenScriptComponent)
|
||||
MenuItemComponent("Camera", Nuake::CameraComponent)
|
||||
MenuItemComponent("Light", Nuake::LightComponent)
|
||||
MenuItemComponent("Wren Script", WrenScriptComponent);
|
||||
MenuItemComponent("Camera", CameraComponent);
|
||||
MenuItemComponent("Light", LightComponent);
|
||||
ImGui::Separator();
|
||||
MenuItemComponent("Model", Nuake::ModelComponent)
|
||||
MenuItemComponent("Skinned Model", Nuake::SkinnedModelComponent)
|
||||
MenuItemComponent("Bone", Nuake::BoneComponent)
|
||||
MenuItemComponent("Model", ModelComponent);
|
||||
MenuItemComponent("Skinned Model", SkinnedModelComponent);
|
||||
MenuItemComponent("Bone", BoneComponent)
|
||||
ImGui::Separator();
|
||||
MenuItemComponent("Sprite", Nuake::SpriteComponent)
|
||||
MenuItemComponent("Particle Emitter", Nuake::ParticleEmitterComponent)
|
||||
MenuItemComponent("Sprite", SpriteComponent)
|
||||
MenuItemComponent("Particle Emitter", ParticleEmitterComponent)
|
||||
ImGui::Separator();
|
||||
MenuItemComponent("Character Controller", Nuake::CharacterControllerComponent)
|
||||
MenuItemComponent("Rigid body", Nuake::RigidBodyComponent)
|
||||
MenuItemComponent("Character Controller", CharacterControllerComponent)
|
||||
MenuItemComponent("Rigid body", RigidBodyComponent)
|
||||
ImGui::Separator();
|
||||
MenuItemComponent("Box collider", Nuake::BoxColliderComponent)
|
||||
MenuItemComponent("Capsule collider", Nuake::CapsuleColliderComponent)
|
||||
MenuItemComponent("Cylinder collider", Nuake::CylinderColliderComponent)
|
||||
MenuItemComponent("Sphere collider", Nuake::SphereColliderComponent)
|
||||
MenuItemComponent("Mesh collider", Nuake::MeshColliderComponent)
|
||||
MenuItemComponent("Box collider", BoxColliderComponent)
|
||||
MenuItemComponent("Capsule collider", CapsuleColliderComponent)
|
||||
MenuItemComponent("Cylinder collider", CylinderColliderComponent)
|
||||
MenuItemComponent("Sphere collider", SphereColliderComponent)
|
||||
MenuItemComponent("Mesh collider", MeshColliderComponent)
|
||||
ImGui::Separator();
|
||||
MenuItemComponent("Quake map", Nuake::QuakeMapComponent)
|
||||
MenuItemComponent("Quake map", QuakeMapComponent)
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::Separator();
|
||||
|
||||
@@ -1,32 +1,43 @@
|
||||
#include "AudioManager.h"
|
||||
#include "src/Core/Logger.h"
|
||||
#include "src/Core/FileSystem.h"
|
||||
|
||||
#include <soloud.h>
|
||||
#include "soloud_speech.h"
|
||||
#include "soloud_thread.h"
|
||||
#include <dependencies/soloud/include/soloud_wav.h>
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
void AudioManager::Initialize()
|
||||
|
||||
namespace Nuake {
|
||||
|
||||
AudioManager::AudioManager() :
|
||||
m_AudioThreadRunning(true)
|
||||
{
|
||||
_soloud = CreateRef<SoLoud::Soloud>();
|
||||
_soloud->init();
|
||||
|
||||
_audioThreadRunning = false;
|
||||
_audioThread = std::thread(&AudioManager::AudioThreadLoop, this);
|
||||
}
|
||||
|
||||
AudioManager::~AudioManager()
|
||||
{
|
||||
Deinitialize();
|
||||
|
||||
_audioThreadRunning = false;
|
||||
_audioThread.join();
|
||||
m_AudioThreadRunning = false;
|
||||
m_AudioThread.join();
|
||||
}
|
||||
|
||||
void AudioManager::Initialize()
|
||||
{
|
||||
m_Soloud = CreateRef<SoLoud::Soloud>();
|
||||
|
||||
// TODO: Sample rate, back end, buffer size, flags.
|
||||
m_Soloud->init();
|
||||
|
||||
m_AudioThread = std::thread(&AudioManager::AudioThreadLoop, this);
|
||||
|
||||
Logger::Log("Audio manager initialized", "audio", VERBOSE);
|
||||
}
|
||||
|
||||
void AudioManager::Deinitialize()
|
||||
{
|
||||
_soloud->deinit();
|
||||
m_Soloud->deinit();
|
||||
}
|
||||
|
||||
void AudioManager::PlayTTS(const std::string& text)
|
||||
@@ -34,11 +45,51 @@ namespace Nuake
|
||||
|
||||
}
|
||||
|
||||
void AudioManager::QueueWavAudio(const std::string& filePath)
|
||||
{
|
||||
// Acquire mutex lock and push to queue
|
||||
const std::lock_guard<std::mutex> lock(m_AudioQueueMutex);
|
||||
|
||||
// Check if file exists and load
|
||||
const bool fileExists = FileSystem::FileExists(filePath, true);
|
||||
if (fileExists && !IsWavLoaded(filePath))
|
||||
{
|
||||
LoadWavAudio(filePath);
|
||||
}
|
||||
|
||||
m_AudioQueue.push({ filePath });
|
||||
}
|
||||
|
||||
bool AudioManager::IsWavLoaded(const std::string& filePath) const
|
||||
{
|
||||
return m_WavSamples.find(filePath) != m_WavSamples.end();
|
||||
}
|
||||
|
||||
void AudioManager::LoadWavAudio(const std::string& filePath)
|
||||
{
|
||||
m_WavSamples[filePath] = SoLoud::Wav();
|
||||
m_WavSamples[filePath].load(filePath.c_str());
|
||||
}
|
||||
|
||||
void AudioManager::AudioThreadLoop()
|
||||
{
|
||||
while(_audioThreadRunning)
|
||||
while(m_AudioThreadRunning)
|
||||
{
|
||||
|
||||
// Acquire mutex lock
|
||||
const std::lock_guard<std::mutex> lock(m_AudioQueueMutex);
|
||||
|
||||
// Check if we have audio queued
|
||||
while (!m_AudioQueue.empty())
|
||||
{
|
||||
auto& first = m_AudioQueue.front();
|
||||
const std::string& audioFilePath = first.audioFile;
|
||||
|
||||
// If file exists, play it
|
||||
m_Soloud->play(*&m_WavSamples[audioFilePath]);
|
||||
|
||||
// Remove item from queue.
|
||||
m_AudioQueue.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,21 +10,36 @@ namespace SoLoud
|
||||
class AudioSource;
|
||||
}
|
||||
|
||||
// Temp code
|
||||
struct audioQueueRequest
|
||||
{
|
||||
std::string audioFile;
|
||||
};
|
||||
|
||||
namespace SoLoud
|
||||
{
|
||||
class Wav;
|
||||
}
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
// This is a singleton that manages everything for audio.
|
||||
class AudioManager
|
||||
{
|
||||
private:
|
||||
Ref<SoLoud::Soloud> _soloud;
|
||||
|
||||
bool _audioThreadRunning;
|
||||
std::thread _audioThread;
|
||||
std::mutex _audioMutex;
|
||||
|
||||
const int MAX_VOICE_COUNT = 32;
|
||||
|
||||
Ref<SoLoud::Soloud> m_Soloud;
|
||||
|
||||
bool m_AudioThreadRunning;
|
||||
std::thread m_AudioThread;
|
||||
std::mutex m_AudioQueueMutex;
|
||||
std::atomic<bool> m_AudioQueued = { false };
|
||||
std::queue<audioQueueRequest> m_AudioQueue;
|
||||
|
||||
std::unordered_map<std::string, SoLoud::Wav> m_WavSamples;
|
||||
public:
|
||||
AudioManager() = default;
|
||||
AudioManager();
|
||||
~AudioManager();
|
||||
|
||||
static AudioManager& Get()
|
||||
@@ -42,6 +57,9 @@ namespace Nuake
|
||||
|
||||
void PlayTTS(const std::string& text);
|
||||
|
||||
void QueueWavAudio(const std::string& filePath);
|
||||
bool IsWavLoaded(const std::string& filePath) const;
|
||||
void LoadWavAudio(const std::string& filePath);
|
||||
private:
|
||||
void AudioThreadLoop();
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
|
||||
#define ASSERT(x) if (!(x)) assert(false)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user