added audio stuff

This commit is contained in:
2026-01-18 19:42:25 +01:00
parent 5fdcb6989f
commit f9185e7b26
13 changed files with 471 additions and 1 deletions

View File

@@ -0,0 +1,10 @@
#include "AudioListener.hpp"
#include "Vector3.hpp"
#include "elements/Transformable.hpp"
#include "elements/AudioEngine.hpp"
void TSE::AudioListener::OnUpdate()
{
Vector3 pos = baseObject->GetGlobalPosition();
ma_engine_listener_set_position(AudioEngine::engine, 0, pos.x, pos.y, -pos.z);
}

View File

@@ -0,0 +1,17 @@
#pragma once
#define AUDIOLISTENER typeid(AudioListener).name()
#include "elements/BehaviourScript.hpp"
namespace TSE
{
class AudioListener : public BehaviourScript
{
void OnUpdate() override;
inline const char* GetName() override
{
return "Audio Listener";
}
};
} // namespace TSE

View File

@@ -0,0 +1,135 @@
#include "AudioSource.hpp"
#include "Vector3.hpp"
#include "elements/Transformable.hpp"
float TSE::AudioSource::GetMinDistance()
{
return minDistance;
}
float TSE::AudioSource::GetMaxDistance()
{
return maxDistance;
}
bool TSE::AudioSource::GetGlobal()
{
return global;
}
void TSE::AudioSource::SetGlobal(bool v)
{
if(global != v)
{
auto it = sounds.begin();
for (int j = 0; j < sounds.size(); j++)
{
it->second;
ma_sound_set_spatialization_enabled(it->second, !v);
it++;
}
}
global = v;
}
void TSE::AudioSource::SetMinDistance(float v)
{
minDistance = v;
auto it = sounds.begin();
for (int j = 0; j < sounds.size(); j++)
{
it->second;
ma_sound_set_min_distance(it->second, minDistance);
it++;
}
}
void TSE::AudioSource::SetMaxDistance(float v)
{
maxDistance = v;
auto it = sounds.begin();
for (int j = 0; j < sounds.size(); j++)
{
it->second;
ma_sound_set_max_distance(it->second, maxDistance);
it++;
}
}
void TSE::AudioSource::AddClip(AudioClip *clip)
{
clips[clip->name] = clip;
ma_sound* s = clip->GetAudioSound();
ma_sound_set_spatialization_enabled(s, !global);
ma_sound_set_attenuation_model(s, ma_attenuation_model_linear);
ma_sound_set_rolloff(s, 1.0f);
ma_sound_set_min_distance(s, minDistance);
ma_sound_set_max_distance(s, maxDistance);
ma_sound_set_min_gain(s, 0.0f);
ma_sound_set_max_gain(s, 1.0f);
sounds[clip->name] = s;
}
void TSE::AudioSource::RemoveClip(std::string name)
{
if(currentlyPlaying == name) StopPlaying();
clips[name]->DestroyAudioSound(sounds[name]);
clips.erase(name);
sounds.erase(name);
}
void TSE::AudioSource::StartClip(std::string name, bool forceRestart)
{
if(currentlyPlaying != name){
StopPlaying();
}
else if(forceRestart)
{
ma_sound_seek_to_pcm_frame(sounds[name], 0);
}
ma_sound_start(sounds[name]);
currentlyPlaying = name;
}
void TSE::AudioSource::StopPlaying()
{
if(currentlyPlaying == "") return;
ma_sound_stop(sounds[currentlyPlaying]);
ma_sound_seek_to_pcm_frame(sounds[currentlyPlaying], 0);
currentlyPlaying = "";
}
void TSE::AudioSource::PausePlaying()
{
if(currentlyPlaying == "") return;
ma_sound_stop(sounds[currentlyPlaying]);
}
TSE::AudioClip *TSE::AudioSource::GetClipAt(int i)
{
auto it = clips.begin();
for (int j = 0; j < i; j++)
{
it++;
}
return it->second;
}
TSE::AudioSource::~AudioSource()
{
int count = clips.size();
for (int i = 0; i < count; i++)
{
std::string name = GetClipAt(0)->name;
RemoveClip(name);
}
}
void TSE::AudioSource::OnUpdate()
{
if(!global)
{
Vector3 pos = baseObject->GetGlobalPosition();
ma_sound_set_position(sounds[currentlyPlaying], pos.x, pos.y, -pos.z);
}
}

View File

@@ -0,0 +1,50 @@
#pragma once
#define AUDIOSOURCE typeid(AudioSource).name()
#include "Types.hpp"
#include "elements/AudioClip.hpp"
#include "elements/BehaviourScript.hpp"
#include "miniaudio.h"
#include <unordered_map>
namespace TSE
{
class AudioSource : public BehaviourScript
{
public:
std::unordered_map<string, AudioClip*> clips;
string currentlyPlaying = "";
private:
bool global = false;
float minDistance = 5;
float maxDistance = 8;
std::unordered_map<std::string, ma_sound*> sounds;
public:
float GetMinDistance();
float GetMaxDistance();
bool GetGlobal();
void SetGlobal(bool v);
void SetMinDistance(float v);
void SetMaxDistance(float v);
void AddClip(AudioClip* clip);
void RemoveClip(std::string name);
void StartClip(std::string name, bool forceRestart = true);
void StopPlaying();
void PausePlaying();
AudioClip* GetClipAt(int i);
~AudioSource();
void OnUpdate() override;
inline const char* GetName() override
{
return "Audio Source";
}
};
} // namespace TSE

View File

@@ -0,0 +1,70 @@
#include "AudioClip.hpp"
#include "Debug.hpp"
#include <filesystem>
#include "AudioEngine.hpp"
TSE::AudioClip::AudioClip(string path)
{
description.path = path;
}
TSE::AudioClip::AudioClip(byte *stream, size_t size)
{
description.audiostream = stream;
description.dataSize = size;
}
ma_sound *TSE::AudioClip::GetAudioSound()
{
if(description.path != ""){
if(std::filesystem::exists(description.path))
{
ma_result res;
ma_sound* sound = (ma_sound*)malloc(sizeof(*sound));
res = ma_sound_init_from_file(AudioEngine::engine, description.path.c_str(), 0, nullptr, nullptr, sound);
if (res != MA_SUCCESS) {
TSE_WARNING("ma_sound_init_from_file failed: " + std::to_string(res));
delete(sound);
return nullptr;
}
return sound;
}
else
{
TSE_WARNING("Can't create ma_sound because the given path dose not exist: \n" + description.path);
}
}
else if(description.audiostream != nullptr && description.dataSize > 0)
{
ma_result res;
ma_decoder m_decoder;
res = ma_decoder_init_memory(description.audiostream, description.dataSize, nullptr, &m_decoder);
if (res != MA_SUCCESS) {
TSE_WARNING("ma_decoder_init_memory failed: " + std::to_string(res));
return nullptr;
}
ma_sound* sound = (ma_sound*)malloc(sizeof(*sound));
res = ma_sound_init_from_data_source(AudioEngine::engine, &m_decoder, MA_SOUND_FLAG_STREAM, nullptr, sound);
ma_decoder_uninit(&m_decoder);
if (res != MA_SUCCESS) {
TSE_WARNING("ma_sound_init_from_data_source failed: " + std::to_string(res));
delete(sound);
return nullptr;
}
return sound;
}
else
{
TSE_WARNING("Can't create ma_sound because description is not set, or unconfigured.");
}
return nullptr;
}
void TSE::AudioClip::DestroyAudioSound(ma_sound *sound)
{
if (!sound) return;
ma_sound_uninit(sound);
delete sound;
}

View File

@@ -0,0 +1,28 @@
#pragma once
#include "Types.hpp"
#include "miniaudio.h"
namespace TSE
{
struct AudioClipDescription
{
public:
string path = "";
byte* audiostream = nullptr;
size_t dataSize = 0;
};
class AudioClip
{
public:
string name = "";
AudioClipDescription description;
AudioClip(string path);
AudioClip(byte* stream, size_t size);
ma_sound* GetAudioSound();
void DestroyAudioSound(ma_sound* sound);
};
} // namespace TSE

View File

@@ -0,0 +1,22 @@
#include "AudioEngine.hpp"
#include "Debug.hpp"
ma_engine* TSE::AudioEngine::engine = nullptr;
void TSE::AudioEngine::Init()
{
ma_result res;
engine = (ma_engine*)malloc(sizeof(*engine));
res = ma_engine_init(nullptr, engine);
if(res != MA_SUCCESS)
{
TSE_WARNING("Couldn't init audio engine. error code: " + std::to_string(res));
}
}
void TSE::AudioEngine::Destroy()
{
ma_engine_uninit(engine);
delete(engine);
engine = nullptr;
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include "miniaudio.h"
namespace TSE
{
class AudioEngine
{
public:
static ma_engine* engine;
static void Init();
static void Destroy();
};
} // namespace TSE

2
TSE_Core/src/extern/miniaudio.c vendored Normal file
View File

@@ -0,0 +1,2 @@
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"

View File

@@ -4,6 +4,7 @@
#include "utils/Time.hpp"
#include "version.h"
#include "IInputManager.hpp"
#include "elements/AudioEngine.hpp"
TSE::IWindow* TSE::IWindow::lastWindow = nullptr;
@@ -12,6 +13,7 @@ bool TSE::IWindow::BaseInit() const
LuaStateHandler::InitLuaState();
Debug::Init();
Debug::Log("TSE:" + TSE_VERSION_STRING);
AudioEngine::Init();
return true;
}
@@ -22,6 +24,7 @@ void TSE::IWindow::BaseUpdate() const
TSE::IWindow::~IWindow()
{
AudioEngine::Destroy();
IInputManager::instance()->Delete();
Time::Destroy();
Debug::Close();