1
0
Fork 0
mirror of https://github.com/TerryCavanagh/VVVVVV.git synced 2024-12-22 17:49:43 +01:00

Add support for sound OGG files

This adds support for OGG files as sound effects (via renaming them to
the wrong .wav file extension), because in previous versions of the
game, SDL_mixer didn't care what the file extension was, and so some
people relied on this, as described in #900.

This is accomplished by copy-pasting the OGG loading code for music
tracks. For a bit of cleanliness, I put the WAV and OGG loading code in
separate functions.

This is mostly the same code, except that because sound effects don't
loop and can't be paused or resumed, there's no reserve buffer, and
there's no data for loop points.

Also, for some reason, the music loading code divided by 20 in the
`size` calculation. I found that this prematurely cut off sound effects,
and that it made more sense to just not do the division. I don't know
why it was there, but removing it works.

Also also, some OGG files don't work with this. Namely, ones produced by
FFmpeg. To test this, I just extracted 0levelcomplete.ogg from
vvvvvvmusic.vvv and replaced terminal.wav with it. And it works, so
hopefully I won't have to touch audio code again, although I might if
someone complains about this. But either way, I'm committing this
because it's better than it was before.

Fixes #900.
This commit is contained in:
Misa 2023-03-18 18:24:30 -07:00
parent 05ed7e041c
commit ba7519106f

View file

@ -95,18 +95,32 @@ class SoundTrack
public:
SoundTrack(const char* fileName)
{
unsigned char *mem;
unsigned char* mem;
size_t length;
SDL_AudioSpec spec;
SDL_RWops *fileIn;
SDL_zerop(this);
FILESYSTEM_loadAssetToMemory(fileName, &mem, &length);
if (mem == NULL)
{
vlog_error("Unable to load WAV file %s", fileName);
SDL_assert(0 && "WAV file missing!");
vlog_error("Unable to load sound file %s", fileName);
SDL_assert(0 && "Sound file missing!");
return;
}
SDL_zerop(this);
if (SDL_memcmp(mem, "OggS", 4) == 0)
{
LoadOGG(fileName, mem, length);
}
else
{
LoadWAV(fileName, mem, length);
}
}
void LoadWAV(const char* fileName, unsigned char* mem, const size_t length)
{
SDL_AudioSpec spec;
SDL_RWops *fileIn;
fileIn = SDL_RWFromConstMem(mem, length);
if (SDL_LoadWAV_RW(fileIn, 1, &spec, &wav_buffer, &wav_length) == NULL)
{
@ -125,9 +139,41 @@ end:
VVV_free(mem);
}
void LoadOGG(const char* fileName, unsigned char* mem, const size_t length)
{
int err;
stb_vorbis_info vorbis_info;
vorbis = stb_vorbis_open_memory(mem, length, &err, NULL);
if (vorbis == NULL)
{
vlog_error("Unable to create Vorbis handle for %s, error %d", fileName, err);
VVV_free(mem);
return;
}
vorbis_info = stb_vorbis_get_info(vorbis);
format.wFormatTag = FAUDIO_FORMAT_IEEE_FLOAT;
format.wBitsPerSample = sizeof(float) * 8;
format.nChannels = vorbis_info.channels;
format.nSamplesPerSec = vorbis_info.sample_rate;
format.nBlockAlign = format.nChannels * format.wBitsPerSample;
format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
format.cbSize = 0;
channels = format.nChannels;
size = format.nAvgBytesPerSec;
decoded_buf_playing = (Uint8*) SDL_malloc(size);
ogg_file = mem;
valid = true;
}
void Dispose(void)
{
VVV_free(wav_buffer);
VVV_free(decoded_buf_playing);
VVV_freefunc(stb_vorbis_close, vorbis);
VVV_free(ogg_file);
}
void Play(void)
@ -151,7 +197,7 @@ end:
VVV_freefunc(FAudioVoice_DestroyVoice, voices[i]);
FAudio_CreateSourceVoice(faudioctx, &voices[i], &format, 0, 2.0f, NULL, NULL, NULL);
}
const FAudioBuffer faudio_buffer = {
FAudioBuffer faudio_buffer = {
FAUDIO_END_OF_STREAM, /* Flags */
wav_length * 8, /* AudioBytes */
wav_buffer, /* AudioData */
@ -162,6 +208,18 @@ end:
0, /* LoopCount */
NULL
};
if (vorbis != NULL)
{
stb_vorbis_seek_start(vorbis);
faudio_buffer.PlayLength = stb_vorbis_get_samples_float_interleaved(
vorbis,
channels,
(float*) decoded_buf_playing,
size / sizeof(float)
);
faudio_buffer.AudioBytes = size;
faudio_buffer.pAudioData = decoded_buf_playing;
}
if (FAudioSourceVoice_SubmitSourceBuffer(voices[i], &faudio_buffer, NULL))
{
vlog_error("Unable to queue sound buffer");
@ -241,6 +299,13 @@ end:
Uint8 *wav_buffer;
Uint32 wav_length;
FAudioWaveFormatEx format;
unsigned char* ogg_file;
stb_vorbis* vorbis;
int channels;
Uint32 size;
Uint8* decoded_buf_playing;
bool valid;
static FAudioSourceVoice** voices;