Audio Engine Fixes
This commit is contained in:
@ -19,12 +19,26 @@
|
|||||||
#include <SDL3/SDL_iostream.h>
|
#include <SDL3/SDL_iostream.h>
|
||||||
#include <SDL3_mixer/SDL_mixer.h>
|
#include <SDL3_mixer/SDL_mixer.h>
|
||||||
|
|
||||||
|
#include <condition_variable>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
namespace ia::iae
|
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{};
|
MIX_Mixer *g_mixer{};
|
||||||
Vector<MIX_Track *> g_tracks;
|
Vector<TrackData*> g_tracks;
|
||||||
|
Vector<INT64> g_destroyQueue;
|
||||||
Vector<MIX_Audio *> g_audioData;
|
Vector<MIX_Audio *> g_audioData;
|
||||||
|
|
||||||
VOID Audio::Initialize()
|
VOID Audio::Initialize()
|
||||||
@ -38,7 +52,48 @@ namespace ia::iae
|
|||||||
|
|
||||||
VOID Audio::Terminate()
|
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_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)
|
Sound Audio::CreateSound(IN PCUINT8 audioData, IN SIZE_T audioDataSize)
|
||||||
@ -47,62 +102,55 @@ namespace ia::iae
|
|||||||
return Sound(g_audioData.size() - 1);
|
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)
|
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)
|
VOID Audio::PlayTrack(IN INT64 trackHandle, IN INT32 loopTimes, IN TimePeriod loopDelay)
|
||||||
{
|
{
|
||||||
struct __callback_data
|
auto &t = g_tracks[trackHandle];
|
||||||
{
|
t->LoopTimes = loopTimes;
|
||||||
INT32 loopTimes;
|
t->LoopDelay = loopDelay;
|
||||||
TimePeriod loopDelay;
|
if (t->LoopTimes == 0)
|
||||||
};
|
t->IsActive = false;
|
||||||
|
else
|
||||||
const auto callbackData = new __callback_data{.loopTimes = loopTimes, .loopDelay = loopDelay};
|
t->PlaybackThread = new std::thread([trackHandle]() {
|
||||||
|
auto &t = g_tracks[trackHandle];
|
||||||
MIX_PlayTrack(g_tracks[trackHandle], 0);
|
while (t->IsActive)
|
||||||
MIX_SetTrackStoppedCallback(
|
{
|
||||||
g_tracks[trackHandle],
|
if (MIX_TrackPlaying(t->Track))
|
||||||
[](PVOID _callbackData, MIX_Track *track) {
|
continue;
|
||||||
const auto callbackData = (__callback_data *) _callbackData;
|
if (t->LoopTimes < 0)
|
||||||
if (callbackData->loopTimes < 0)
|
goto loop_next_iteration;
|
||||||
goto loop_next_iteration;
|
else if (!t->LoopTimes)
|
||||||
else if (callbackData->loopTimes == 0)
|
{
|
||||||
return;
|
t->IsActive = false;
|
||||||
else
|
return;
|
||||||
callbackData->loopTimes -= 1;
|
}
|
||||||
loop_next_iteration:
|
t->LoopTimes--;
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds((INT32) (callbackData->loopDelay.GetValue() * 1000)));
|
loop_next_iteration:
|
||||||
MIX_PlayTrack(track, 0);
|
std::unique_lock<std::mutex> lock(t->Mutex);
|
||||||
},
|
t->CV.wait_for(lock, std::chrono::milliseconds((INT32) (t->LoopDelay.GetValue() * 1000)),
|
||||||
callbackData);
|
[t]() { return !t->IsActive; });
|
||||||
|
MIX_PlayTrack(t->Track, 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
MIX_PlayTrack(t->Track, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID Audio::ClearTrack(IN INT64 trackHandle)
|
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)
|
VOID Audio::PauseTrack(IN INT64 trackHandle)
|
||||||
{
|
{
|
||||||
MIX_PauseTrack(g_tracks[trackHandle]);
|
MIX_PauseTrack(g_tracks[trackHandle]->Track);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID Audio::ResumeTrack(IN INT64 trackHandle)
|
VOID Audio::ResumeTrack(IN INT64 trackHandle)
|
||||||
{
|
{
|
||||||
MIX_ResumeTrack(g_tracks[trackHandle]);
|
MIX_ResumeTrack(g_tracks[trackHandle]->Track);
|
||||||
}
|
}
|
||||||
} // namespace ia::iae
|
} // namespace ia::iae
|
||||||
@ -138,6 +138,7 @@ namespace ia::iae
|
|||||||
g_physicsDebugDrawEnabled = !g_physicsDebugDrawEnabled;
|
g_physicsDebugDrawEnabled = !g_physicsDebugDrawEnabled;
|
||||||
|
|
||||||
Physics::Update();
|
Physics::Update();
|
||||||
|
Audio::Update();
|
||||||
|
|
||||||
if B_LIKELY (g_activeScene)
|
if B_LIKELY (g_activeScene)
|
||||||
g_activeScene->Update();
|
g_activeScene->Update();
|
||||||
|
|||||||
@ -63,12 +63,14 @@ namespace ia::iae
|
|||||||
public:
|
public:
|
||||||
STATIC VOID Initialize();
|
STATIC VOID Initialize();
|
||||||
STATIC VOID Terminate();
|
STATIC VOID Terminate();
|
||||||
|
|
||||||
STATIC Sound CreateSound(IN PCUINT8 audioData, IN SIZE_T audioDataSize);
|
STATIC VOID Update();
|
||||||
|
|
||||||
STATIC INT64 CreateTrack();
|
STATIC INT64 CreateTrack();
|
||||||
STATIC VOID DestroyTrack(IN INT64 trackHandle);
|
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 QueueTrackData(IN INT64 trackHandle, IN INT64 dataHandle);
|
||||||
STATIC VOID PlayTrack(IN INT64 trackHandle, IN INT32 loopTimes, IN TimePeriod loopDelay);
|
STATIC VOID PlayTrack(IN INT64 trackHandle, IN INT32 loopTimes, IN TimePeriod loopDelay);
|
||||||
STATIC VOID ClearTrack(IN INT64 trackHandle);
|
STATIC VOID ClearTrack(IN INT64 trackHandle);
|
||||||
|
|||||||
Reference in New Issue
Block a user