Re-encode S32 audio sample formats without re-enumerating the files

This commit is contained in:
Wayward Heart 2024-08-17 18:27:34 -05:00
parent 181192cb04
commit a3d028335c
3 changed files with 42 additions and 47 deletions

View file

@ -56,8 +56,7 @@ 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

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

View file

@ -24,10 +24,15 @@
#include <SDL_sound.h> #include <SDL_sound.h>
static int SDL_RWopsCloseNoop(SDL_RWops *ops) {
return 0;
}
struct SDLSoundSource : ALDataSource struct SDLSoundSource : ALDataSource
{ {
Sound_Sample *sample; Sound_Sample *sample;
SDL_RWops srcOps; SDL_RWops srcOps;
SDL_RWops unclosableOps;
uint8_t sampleSize; uint8_t sampleSize;
bool looped; bool looped;
@ -37,34 +42,23 @@ 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),
unclosableOps(ops),
looped(looped) looped(looped)
{ {
if (fallbackMode == 0) /* A copy of srcOps with a no-op close function,
{ * so we can reuse the ops if we need to change the format. */
sample = Sound_NewSample(&srcOps, extension, 0, maxBufSize); unclosableOps.close = SDL_RWopsCloseNoop;
}
else
{
// We're here because a previous attempt resulted in S32 format.
Sound_AudioInfo desired; sample = Sound_NewSample(&unclosableOps, extension, 0, maxBufSize);
SDL_memset(&desired, '\0', sizeof (Sound_AudioInfo));
desired.format = AUDIO_F32SYS;
sample = Sound_NewSample(&srcOps, extension, &desired, maxBufSize);
}
if (!sample) if (!sample)
{ {
SDL_RWclose(&ops); SDL_RWclose(&srcOps);
throw Exception(Exception::SDLError, "SDL_sound: %s", Sound_GetError()); throw Exception(Exception::SDLError, "SDL_sound: %s", Sound_GetError());
} }
if (fallbackMode == 0)
{
bool validFormat = true; bool validFormat = true;
switch (sample->actual.format) switch (sample->actual.format)
@ -83,7 +77,18 @@ struct SDLSoundSource : ALDataSource
// So we just have to close the sample (which closes the file too), // So we just have to close the sample (which closes the file too),
// and retry with a new desired format. // and retry with a new desired format.
Sound_FreeSample(sample); Sound_FreeSample(sample);
throw Exception(Exception::SDLError, "SDL_sound: format not supported by OpenAL: %d", sample->actual.format); SDL_RWseek(&unclosableOps, 0, RW_SEEK_SET);
Sound_AudioInfo desired;
SDL_memset(&desired, '\0', sizeof (Sound_AudioInfo));
desired.format = AUDIO_F32SYS;
sample = Sound_NewSample(&unclosableOps, extension, &desired, maxBufSize);
if (!sample)
{
SDL_RWclose(&srcOps);
throw Exception(Exception::SDLError, "SDL_sound: %s", Sound_GetError());
} }
} }
@ -95,8 +100,8 @@ struct SDLSoundSource : ALDataSource
~SDLSoundSource() ~SDLSoundSource()
{ {
/* This also closes 'srcOps' */
Sound_FreeSample(sample); Sound_FreeSample(sample);
SDL_RWclose(&srcOps);
} }
Status fillBuffer(AL::Buffer::ID alBuffer) Status fillBuffer(AL::Buffer::ID alBuffer)
@ -162,8 +167,7 @@ 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, fallbackMode); return new SDLSoundSource(ops, extension, maxBufSize, looped);
} }