Skip to content

Commit

Permalink
Fix endless loop when decoding OGGs, #390
Browse files Browse the repository at this point in the history
In idSampleDecoderLocal::DecodeOGG() `totalSamples` was 1 and
`reqSamples` was 0, which caused an endless loop.. this was caused by
idSoundWorldLocal::ReadFromSaveGame() setting
`chan->openalStreamingOffset` to an odd number, I think due to
`currentSoundTime` being an odd number.
To fix that, I round up `chan->openalStreamingOffset` to a (very) even
number, and to be double-sure I also added a check in DecodeOgg() to
make sure it exits the loop if `reqSamples` is 0.
  • Loading branch information
DanielGibson committed Jun 22, 2021
1 parent 8eb91c7 commit aedf0b4
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 0 deletions.
10 changes: 10 additions & 0 deletions neo/sound/snd_decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,16 @@ int idSampleDecoderLocal::DecodeOGG( idSoundSample *sample, int sampleOffset44k,
float* samples[2] = { samplesBuf[0], samplesBuf[1] };
int reqSamples = Min( MIXBUFFER_SAMPLES, totalSamples / sample->objectInfo.nChannels );
int ret = stb_vorbis_get_samples_float( stbv, sample->objectInfo.nChannels, samples, reqSamples );
if ( reqSamples == 0 ) {
// DG: it happened that sampleCount was an odd number in a *stereo* sound file
// and eventually totalSamples was 1 and thus reqSamples = totalSamples/2 was 0
// so this turned into an endless loop.. it shouldn't happen anymore due to changes
// in idSoundWorldLocal::ReadFromSaveGame(), but better safe than sorry..
common->DPrintf( "idSampleDecoderLocal::DecodeOGG() reqSamples == 0\n for %s ?!\n", sample->name.c_str() );
readSamples += totalSamples;
totalSamples = 0;
break;
}
if ( ret == 0 ) {
int stbVorbErr = stb_vorbis_get_error( stbv );
if ( stbVorbErr == VORBIS__no_error && reqSamples < 5 ) {
Expand Down
5 changes: 5 additions & 0 deletions neo/sound/snd_world.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1383,6 +1383,11 @@ void idSoundWorldLocal::ReadFromSaveGame( idFile *savefile ) {
// make sure we start up the hardware voice if needed
chan->triggered = chan->triggerState;
chan->openalStreamingOffset = currentSoundTime - chan->trigger44kHzTime;
// DG: round up openalStreamingOffset to multiple of 8, so it still has an even number
// if we calculate "how many 11kHz stereo samples do we need to decode" and don't
// run into a "I need one more sample apparently, so decode 0 stereo samples"
// situation that could cause an endless loop.. (44kHz/11kHz = 4; *2 for stereo => 8)
chan->openalStreamingOffset = (chan->openalStreamingOffset+7) & ~7;

// adjust the hardware fade time
if ( chan->channelFade.fadeStart44kHz != 0 ) {
Expand Down

0 comments on commit aedf0b4

Please sign in to comment.