diff --git a/CMakeLists.txt b/CMakeLists.txt index f4bfc954f7..ceebbc1818 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,7 +83,11 @@ source_group("dusk" FILES ${DUSK_FILES}) # game_debug is for game code files that we know work when compiled with DEBUG=1 # Of course, if building a release build, this distinction is irrelevant -add_library(game_debug STATIC ${JSYSTEM_DEBUG_FILES} ${SSYSTEM_FILES}) +add_library(game_debug STATIC ${JSYSTEM_DEBUG_FILES} ${SSYSTEM_FILES} + src/dusk/audio/DuskAudioSystem.cpp + src/dusk/audio/JASCriticalSection.cpp + src/dusk/audio/DuskDsp.hpp + src/dusk/audio/DuskDsp.cpp) target_compile_definitions(game_debug PRIVATE TARGET_PC AVOID_UB=1 VERSION=0 $<$:DEBUG=1>) # Make these properties PUBLIC so that the regular game target also sees them. diff --git a/include/dusk/audio/DuskAudioSystem.h b/include/dusk/audio/DuskAudioSystem.h new file mode 100644 index 0000000000..0ea13125ad --- /dev/null +++ b/include/dusk/audio/DuskAudioSystem.h @@ -0,0 +1,3 @@ +#pragma once + +void DuskAudioInitialize(); diff --git a/libs/JSystem/src/JAudio2/JAUInitializer.cpp b/libs/JSystem/src/JAudio2/JAUInitializer.cpp index 9a9a3eeabd..7d56282b45 100644 --- a/libs/JSystem/src/JAudio2/JAUInitializer.cpp +++ b/libs/JSystem/src/JAudio2/JAUInitializer.cpp @@ -15,6 +15,8 @@ #include "JSystem/JKernel/JKRSolidHeap.h" #include "JSystem/JKernel/JKRThread.h" +#include "dusk/audio/DuskAudioSystem.h" + JAU_JASInitializer::JAU_JASInitializer() { audioMemory_ = 0; audioMemSize_ = 0; @@ -60,7 +62,11 @@ void JAU_JASInitializer::initJASystem(JKRSolidHeap* heap) { } JASDvd::createThread(dvdThreadPriority_, 0x80, 0x1000); +#if TARGET_PC + DuskAudioInitialize(); +#else JASAudioThread::create(audioThreadPriority_); +#endif JKRThreadSwitch* threadSwitch = JKRThreadSwitch::getManager(); if (threadSwitch) { if (dvdThreadId_ >= 0) { diff --git a/src/dusk/audio/DuskAudioSystem.cpp b/src/dusk/audio/DuskAudioSystem.cpp new file mode 100644 index 0000000000..566d2ab400 --- /dev/null +++ b/src/dusk/audio/DuskAudioSystem.cpp @@ -0,0 +1,82 @@ +#include "dusk/audio/DuskAudioSystem.h" + +#include +#include + +#include "JSystem/JAudio2/JASAiCtrl.h" +#include "JSystem/JAudio2/JASChannel.h" +#include "JSystem/JAudio2/JASCriticalSection.h" +#include "JSystem/JAudio2/JASDSPChannel.h" +#include "JSystem/JAudio2/JASHeapCtrl.h" + +#include "DuskDsp.hpp" + +static DspSubframe AllSubframeBuffers[DSP_OUTPUT_CHANNELS]; + +static SDL_AudioStream* PlaybackStream; + +static void SDLCALL GetNewAudio( + void *userdata, + SDL_AudioStream *stream, + int additional_amount, + int total_amount); + +static int RenderNewAudioFrame(); +static void RenderAudioSubframe(); + +static void InitSDL3Output() { + SDL_Init(SDL_INIT_AUDIO); + + constexpr SDL_AudioSpec spec = { + SDL_AUDIO_S16, + 1, + 32000, + }; + PlaybackStream = SDL_OpenAudioDeviceStream( + SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, + &spec, + &GetNewAudio, + nullptr); +} + +void DuskAudioInitialize() { + InitSDL3Output(); + + JASDsp::initBuffer(); + JASDSPChannel::initAll(); + + JASPoolAllocObject_MultiThreaded::newMemPool(0x48); + + SDL_ResumeAudioStreamDevice(PlaybackStream); +} + +void SDLCALL GetNewAudio( + void*, + SDL_AudioStream*, + int, + int total_amount) { + while (total_amount > 0) { + const int rendered = RenderNewAudioFrame(); + total_amount -= rendered; + } +} + +int RenderNewAudioFrame() { + JASCriticalSection section; + const u32 countSubframes = JASDriver::getSubFrames(); + + for (u32 i = 0; i < countSubframes; i++) { + RenderAudioSubframe(); + } + + return static_cast(countSubframes) * DSP_SUBFRAME_SIZE; +} + +void RenderAudioSubframe() { + DspSubframe& subFrame = AllSubframeBuffers[0]; + + JASDriver::updateDSP(); + DuskDspRender(subFrame); + + SDL_PutAudioStreamData(PlaybackStream, &subFrame, sizeof(subFrame)); +} diff --git a/src/dusk/audio/DuskDsp.cpp b/src/dusk/audio/DuskDsp.cpp new file mode 100644 index 0000000000..63cc5707e3 --- /dev/null +++ b/src/dusk/audio/DuskDsp.cpp @@ -0,0 +1,16 @@ +#include "DuskDsp.hpp" + +#include + +static float SinePos; + +void DuskDspRender(DspSubframe& subframe) { + subframe.fill(0); + + for (auto& elem : subframe) { + elem = static_cast(sinf(SinePos) * std::numeric_limits::max() * 0.2); + SinePos += 0.05f; + } + + auto& channels = *reinterpret_cast*>(JASDsp::CH_BUF); +} diff --git a/src/dusk/audio/DuskDsp.hpp b/src/dusk/audio/DuskDsp.hpp new file mode 100644 index 0000000000..418c285686 --- /dev/null +++ b/src/dusk/audio/DuskDsp.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "JSystem/JAudio2/JASDSPInterface.h" + +#include + +using DspSubframe = std::array; + +void DuskDspRender(DspSubframe& subframe);