Merge pull request #128 from Splendide-Imaginarius/mkxp-z-s32

Support S32 audio sample formats
This commit is contained in:
Splendide Imaginarius 2024-03-17 03:52:21 +00:00 committed by GitHub
commit 47030733c8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 60 additions and 8 deletions

View file

@ -207,7 +207,9 @@ inline uint8_t formatSampleSize(int sdlFormat)
case AUDIO_S16LSB : case AUDIO_S16LSB :
case AUDIO_S16MSB : case AUDIO_S16MSB :
return 2; return 2;
case AUDIO_S32LSB :
case AUDIO_S32MSB :
case AUDIO_F32LSB : case AUDIO_F32LSB :
case AUDIO_F32MSB : case AUDIO_F32MSB :
return 4; return 4;

View file

@ -56,7 +56,8 @@ struct ALDataSource
ALDataSource *createSDLSource(SDL_RWops &ops, ALDataSource *createSDLSource(SDL_RWops &ops,
const char *extension, const char *extension,
uint32_t maxBufSize, uint32_t maxBufSize,
bool looped); bool looped,
int fallbackMode);
ALDataSource *createVorbisSource(SDL_RWops &ops, ALDataSource *createVorbisSource(SDL_RWops &ops,
bool looped); bool looped);

View file

@ -204,10 +204,11 @@ struct ALStreamOpenHandler : FileSystem::OpenHandler
SDL_RWops *srcOps; SDL_RWops *srcOps;
bool looped; bool looped;
ALDataSource *source; ALDataSource *source;
int fallbackMode;
std::string errorMsg; std::string errorMsg;
ALStreamOpenHandler(SDL_RWops &srcOps, bool looped) ALStreamOpenHandler(SDL_RWops &srcOps, bool looped)
: srcOps(&srcOps), looped(looped), source(0) : srcOps(&srcOps), looped(looped), source(0), fallbackMode(0)
{} {}
bool tryRead(SDL_RWops &ops, const char *ext) bool tryRead(SDL_RWops &ops, const char *ext)
@ -240,7 +241,7 @@ struct ALStreamOpenHandler : FileSystem::OpenHandler
} }
} }
source = createSDLSource(*srcOps, ext, STREAM_BUF_SIZE, looped); source = createSDLSource(*srcOps, ext, STREAM_BUF_SIZE, looped, fallbackMode);
} }
catch (const Exception &e) catch (const Exception &e)
{ {
@ -261,6 +262,15 @@ void ALStream::openSource(const std::string &filename)
source = handler.source; source = handler.source;
needsRewind.clear(); needsRewind.clear();
// Try fallback mode, e.g. for handling S32->F32 sample format conversion
if (!source)
{
handler.fallbackMode = 1;
shState->fileSystem().openRead(handler, filename.c_str());
source = handler.source;
needsRewind.clear();
}
if (!source) if (!source)
{ {
char buf[512]; char buf[512];

View file

@ -37,11 +37,25 @@ struct SDLSoundSource : ALDataSource
SDLSoundSource(SDL_RWops &ops, SDLSoundSource(SDL_RWops &ops,
const char *extension, const char *extension,
uint32_t maxBufSize, uint32_t maxBufSize,
bool looped) bool looped,
int fallbackMode)
: srcOps(ops), : srcOps(ops),
looped(looped) looped(looped)
{ {
sample = Sound_NewSample(&srcOps, extension, 0, maxBufSize); if (fallbackMode == 0)
{
sample = Sound_NewSample(&srcOps, extension, 0, maxBufSize);
}
else
{
// We're here because a previous attempt resulted in S32 format.
Sound_AudioInfo desired;
SDL_memset(&desired, '\0', sizeof (Sound_AudioInfo));
desired.format = AUDIO_F32SYS;
sample = Sound_NewSample(&srcOps, extension, &desired, maxBufSize);
}
if (!sample) if (!sample)
{ {
@ -49,6 +63,30 @@ struct SDLSoundSource : ALDataSource
throw Exception(Exception::SDLError, "SDL_sound: %s", Sound_GetError()); throw Exception(Exception::SDLError, "SDL_sound: %s", Sound_GetError());
} }
if (fallbackMode == 0)
{
bool validFormat = true;
switch (sample->actual.format)
{
// OpenAL Soft doesn't support S32 formats.
// https://github.com/kcat/openal-soft/issues/934
case AUDIO_S32LSB :
case AUDIO_S32MSB :
validFormat = false;
}
if (!validFormat)
{
// Unfortunately there's no way to change the desired format of a sample.
// https://github.com/icculus/SDL_sound/issues/91
// So we just have to close the sample (which closes the file too),
// and retry with a new desired format.
Sound_FreeSample(sample);
throw Exception(Exception::SDLError, "SDL_sound: format not supported by OpenAL: %d", sample->actual.format);
}
}
sampleSize = formatSampleSize(sample->actual.format); sampleSize = formatSampleSize(sample->actual.format);
alFormat = chooseALFormat(sampleSize, sample->actual.channels); alFormat = chooseALFormat(sampleSize, sample->actual.channels);
@ -124,7 +162,8 @@ struct SDLSoundSource : ALDataSource
ALDataSource *createSDLSource(SDL_RWops &ops, ALDataSource *createSDLSource(SDL_RWops &ops,
const char *extension, const char *extension,
uint32_t maxBufSize, uint32_t maxBufSize,
bool looped) bool looped,
int fallbackMode)
{ {
return new SDLSoundSource(ops, extension, maxBufSize, looped); return new SDLSoundSource(ops, extension, maxBufSize, looped, fallbackMode);
} }