diff --git a/include/soloud.h b/include/soloud.h index e3b47d8e..8f984cf8 100644 --- a/include/soloud.h +++ b/include/soloud.h @@ -194,6 +194,7 @@ namespace SoLoud MINIAUDIO, NOSOUND, NULLDRIVER, + SDL3, BACKEND_MAX, }; diff --git a/include/soloud_c.h b/include/soloud_c.h index bac939cc..7459bdf4 100644 --- a/include/soloud_c.h +++ b/include/soloud_c.h @@ -55,7 +55,8 @@ enum SOLOUD_ENUMS SOLOUD_MINIAUDIO = 14, SOLOUD_NOSOUND = 15, SOLOUD_NULLDRIVER = 16, - SOLOUD_BACKEND_MAX = 17, + SOLOUD_SDL3 = 17, + SOLOUD_BACKEND_MAX = 18, SOLOUD_CLIP_ROUNDOFF = 1, SOLOUD_ENABLE_VISUALIZATION = 2, SOLOUD_LEFT_HANDED_3D = 4, diff --git a/include/soloud_internal.h b/include/soloud_internal.h index c0589abd..0838ce6f 100644 --- a/include/soloud_internal.h +++ b/include/soloud_internal.h @@ -41,6 +41,9 @@ namespace SoLoud // SDL2 "non-dynamic" back-end initialization call result sdl2static_init(SoLoud::Soloud *aSoloud, unsigned int aFlags = Soloud::CLIP_ROUNDOFF, unsigned int aSamplerate = 44100, unsigned int aBuffer = 2048, unsigned int aChannels = 2); + // SDL3 "non-dynamic" back-end initialization call + result sdl3static_init(SoLoud::Soloud *aSoloud, unsigned int aFlags = Soloud::CLIP_ROUNDOFF, unsigned int aSamplerate = 44100, unsigned int aBuffer = 2048, unsigned int aChannels = 2); + // OpenAL back-end initialization call result openal_init(SoLoud::Soloud *aSoloud, unsigned int aFlags = Soloud::CLIP_ROUNDOFF, unsigned int aSamplerate = 44100, unsigned int aBuffer = 2048, unsigned int aChannels = 2); diff --git a/src/backend/sdl3_static/soloud_sdl3_static.cpp b/src/backend/sdl3_static/soloud_sdl3_static.cpp new file mode 100644 index 00000000..22346229 --- /dev/null +++ b/src/backend/sdl3_static/soloud_sdl3_static.cpp @@ -0,0 +1,101 @@ +/* +SoLoud audio engine +Copyright (c) 2013-2015 Jari Komppa + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*/ +#include + +#include "soloud.h" + +#if !defined(WITH_SDL3_STATIC) + +namespace SoLoud +{ + result sdl3static_init(SoLoud::Soloud *aSoloud, unsigned int aFlags, unsigned int aSamplerate, unsigned int aBuffer) + { + return NOT_IMPLEMENTED; + } +} + +#else + +#include +#include + +namespace SoLoud +{ + static unsigned int gSamples; + static SDL_AudioSpec gActiveAudioSpec; + static SDL_AudioStream *gAudioStream; + + void soloud_sdl3static_audiomixer(void *userdata, SDL_AudioStream* stream, int additional_amount, int total_amount) + { + if (additional_amount > 0) { + Uint8 *data = SDL_stack_alloc(Uint8, additional_amount); + if (data) { + SoLoud::Soloud *soloud = (SoLoud::Soloud *)userdata; + + int samples = additional_amount / (gActiveAudioSpec.channels * sizeof(float)); + // TODO: in practice it seems like it's safe to ignore the case where samples > gSamples + // because the scratch buffers are always so big, but is this really safe? + soloud->mix((float*)data, samples); + + SDL_PutAudioStreamData(stream, data, additional_amount); + SDL_stack_free(data); + } + } + } + + static void soloud_sdl3static_deinit(SoLoud::Soloud *aSoloud) + { + SDL_DestroyAudioStream(gAudioStream); + } + + result sdl3static_init(SoLoud::Soloud *aSoloud, unsigned int aFlags, unsigned int aSamplerate, unsigned int aBuffer, unsigned int aChannels) + { + if (!SDL_WasInit(SDL_INIT_AUDIO)) + { + if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) + { + return UNKNOWN_ERROR; + } + } + + gSamples = aBuffer; + + gActiveAudioSpec = { SDL_AUDIO_F32LE, (int)aChannels, (int)aSamplerate }; + + gAudioStream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &gActiveAudioSpec, soloud_sdl3static_audiomixer, (void*)aSoloud); + if (!gAudioStream) + { + return UNKNOWN_ERROR; + } + + aSoloud->postinit_internal(gActiveAudioSpec.freq, gSamples, aFlags, gActiveAudioSpec.channels); + + aSoloud->mBackendCleanupFunc = soloud_sdl3static_deinit; + + SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(gAudioStream)); + aSoloud->mBackendString = "SDL3 (static)"; + return 0; + } +}; +#endif diff --git a/src/core/soloud.cpp b/src/core/soloud.cpp index 0b0bfa02..2263808d 100644 --- a/src/core/soloud.cpp +++ b/src/core/soloud.cpp @@ -46,7 +46,7 @@ freely, subject to the following restrictions: !defined(WITH_WASAPI) && !defined(WITH_OSS) && !defined(WITH_SDL1_STATIC) && \ !defined(WITH_SDL2_STATIC) && !defined(WITH_ALSA) && !defined(WITH_OPENSLES) && \ !defined(WITH_NULL) && !defined(WITH_COREAUDIO) && !defined(WITH_VITA_HOMEBREW) &&\ - !defined(WITH_JACK) && !defined(WITH_NOSOUND) && !defined(WITH_MINIAUDIO) + !defined(WITH_JACK) && !defined(WITH_NOSOUND) && !defined(WITH_MINIAUDIO) && !defined(WITH_SDL3_STATIC) #error It appears you haven't enabled any of the back-ends. Please #define one or more of the WITH_ defines (or use premake) ' #endif @@ -261,6 +261,25 @@ namespace SoLoud } #endif +#if defined(WITH_SDL3_STATIC) + if (!inited && + (aBackend == Soloud::SDL3 || + aBackend == Soloud::AUTO)) + { + if (aBufferSize == Soloud::AUTO) buffersize = 2048; + + int ret = sdl3static_init(this, aFlags, samplerate, buffersize, aChannels); + if (ret == 0) + { + inited = 1; + mBackendID = Soloud::SDL3; + } + + if (ret != 0 && aBackend != Soloud::AUTO) + return ret; + } +#endif + #if defined(WITH_SDL2) if (!inited && (aBackend == Soloud::SDL2 ||