Audio Engine Fixes

This commit is contained in:
Isuru Samarathunga
2025-10-03 03:16:40 +05:30
parent 6a87771d8f
commit 8b308db058
3 changed files with 93 additions and 42 deletions

View File

@ -19,12 +19,26 @@
#include <SDL3/SDL_iostream.h>
#include <SDL3_mixer/SDL_mixer.h>
#include <condition_variable>
#include <thread>
namespace ia::iae
{
struct TrackData
{
BOOL IsActive{};
MIX_Track *Track{};
INT32 LoopTimes{};
TimePeriod LoopDelay{};
std::thread *PlaybackThread;
std::mutex Mutex;
std::condition_variable CV;
};
MIX_Mixer *g_mixer{};
Vector<MIX_Track *> g_tracks;
Vector<TrackData*> g_tracks;
Vector<INT64> g_destroyQueue;
Vector<MIX_Audio *> g_audioData;
VOID Audio::Initialize()
@ -38,7 +52,48 @@ namespace ia::iae
VOID Audio::Terminate()
{
for (SIZE_T i = 0; i < g_tracks.size(); i++)
{
{
std::lock_guard<std::mutex> lock(g_tracks[i]->Mutex);
g_tracks[i]->IsActive = false;
}
g_tracks[i]->CV.notify_one();
g_tracks[i]->PlaybackThread->join();
delete g_tracks[i];
}
MIX_StopAllTracks(g_mixer, 0);
g_audioData.clear();
g_tracks.clear();
}
VOID Audio::Update()
{
for (SIZE_T i = 0; i < g_tracks.size(); i++)
{
auto &t = g_tracks[i];
if (!t->IsActive && !MIX_TrackPlaying(t->Track))
DestroyTrack(i);
}
// [IATODO]: IMPL: Destroy queue
}
INT64 Audio::CreateTrack()
{
g_tracks.pushBack(new TrackData{true, MIX_CreateTrack(g_mixer)});
return g_tracks.size() - 1;
}
VOID Audio::DestroyTrack(IN INT64 trackHandle)
{
if(trackHandle >= g_tracks.size())
return;
auto& t = g_tracks[trackHandle];
ClearTrack(trackHandle);
MIX_StopTrack(t->Track, 0);
t->IsActive = false;
g_destroyQueue.pushBack(trackHandle);
}
Sound Audio::CreateSound(IN PCUINT8 audioData, IN SIZE_T audioDataSize)
@ -47,62 +102,55 @@ namespace ia::iae
return Sound(g_audioData.size() - 1);
}
INT64 Audio::CreateTrack()
{
g_tracks.pushBack(MIX_CreateTrack(g_mixer));
return g_tracks.size() - 1;
}
VOID Audio::DestroyTrack(IN INT64 trackHandle)
{
ClearTrack(trackHandle);
}
VOID Audio::QueueTrackData(IN INT64 trackHandle, IN INT64 dataHandle)
{
MIX_SetTrackAudio(g_tracks[trackHandle], g_audioData[dataHandle]);
MIX_SetTrackAudio(g_tracks[trackHandle]->Track, g_audioData[dataHandle]);
}
VOID Audio::PlayTrack(IN INT64 trackHandle, IN INT32 loopTimes, IN TimePeriod loopDelay)
{
struct __callback_data
{
INT32 loopTimes;
TimePeriod loopDelay;
};
const auto callbackData = new __callback_data{.loopTimes = loopTimes, .loopDelay = loopDelay};
MIX_PlayTrack(g_tracks[trackHandle], 0);
MIX_SetTrackStoppedCallback(
g_tracks[trackHandle],
[](PVOID _callbackData, MIX_Track *track) {
const auto callbackData = (__callback_data *) _callbackData;
if (callbackData->loopTimes < 0)
goto loop_next_iteration;
else if (callbackData->loopTimes == 0)
return;
else
callbackData->loopTimes -= 1;
loop_next_iteration:
std::this_thread::sleep_for(std::chrono::milliseconds((INT32) (callbackData->loopDelay.GetValue() * 1000)));
MIX_PlayTrack(track, 0);
},
callbackData);
auto &t = g_tracks[trackHandle];
t->LoopTimes = loopTimes;
t->LoopDelay = loopDelay;
if (t->LoopTimes == 0)
t->IsActive = false;
else
t->PlaybackThread = new std::thread([trackHandle]() {
auto &t = g_tracks[trackHandle];
while (t->IsActive)
{
if (MIX_TrackPlaying(t->Track))
continue;
if (t->LoopTimes < 0)
goto loop_next_iteration;
else if (!t->LoopTimes)
{
t->IsActive = false;
return;
}
t->LoopTimes--;
loop_next_iteration:
std::unique_lock<std::mutex> lock(t->Mutex);
t->CV.wait_for(lock, std::chrono::milliseconds((INT32) (t->LoopDelay.GetValue() * 1000)),
[t]() { return !t->IsActive; });
MIX_PlayTrack(t->Track, 0);
}
});
MIX_PlayTrack(t->Track, 0);
}
VOID Audio::ClearTrack(IN INT64 trackHandle)
{
MIX_StopTrack(g_tracks[trackHandle], 0);
MIX_StopTrack(g_tracks[trackHandle]->Track, 0);
}
VOID Audio::PauseTrack(IN INT64 trackHandle)
{
MIX_PauseTrack(g_tracks[trackHandle]);
MIX_PauseTrack(g_tracks[trackHandle]->Track);
}
VOID Audio::ResumeTrack(IN INT64 trackHandle)
{
MIX_ResumeTrack(g_tracks[trackHandle]);
MIX_ResumeTrack(g_tracks[trackHandle]->Track);
}
} // namespace ia::iae

View File

@ -138,6 +138,7 @@ namespace ia::iae
g_physicsDebugDrawEnabled = !g_physicsDebugDrawEnabled;
Physics::Update();
Audio::Update();
if B_LIKELY (g_activeScene)
g_activeScene->Update();

View File

@ -64,11 +64,13 @@ namespace ia::iae
STATIC VOID Initialize();
STATIC VOID Terminate();
STATIC Sound CreateSound(IN PCUINT8 audioData, IN SIZE_T audioDataSize);
STATIC VOID Update();
STATIC INT64 CreateTrack();
STATIC VOID DestroyTrack(IN INT64 trackHandle);
STATIC Sound CreateSound(IN PCUINT8 audioData, IN SIZE_T audioDataSize);
STATIC VOID QueueTrackData(IN INT64 trackHandle, IN INT64 dataHandle);
STATIC VOID PlayTrack(IN INT64 trackHandle, IN INT32 loopTimes, IN TimePeriod loopDelay);
STATIC VOID ClearTrack(IN INT64 trackHandle);