diff --git a/src/FAudioGMS.c b/src/FAudioGMS.c index 5333cc1..e5d222d 100644 --- a/src/FAudioGMS.c +++ b/src/FAudioGMS.c @@ -175,7 +175,7 @@ typedef struct FAudioGMS_StaticSound } FAudioGMS_StaticSound; /* if we don't triple buffer, we'll microstutter the voice while waiting for decode */ -#define STREAMING_BUFFER_COUNT 3 +#define STREAMING_BUFFER_COUNT 3 #define DEFAULT_STREAMING_BUFFER_SIZE 32768 typedef struct FAudioGMS_StreamingSound @@ -187,7 +187,6 @@ typedef struct FAudioGMS_StreamingSound uint32_t nextStreamBufferIndex; /* it's a ring buffer! */ uint32_t buffersLoadedCount; /* how many buffers are we buffering? */ uint32_t mostRecentSampleOffset; /* used for calculating track position */ - uint8_t isFinalBuffer; /* used to detect end of playback */ } FAudioGMS_StreamingSound; typedef struct FAudioGMS_SoundInstance FAudioGMS_SoundInstance; @@ -358,23 +357,22 @@ static void FAudioGMS_INTERNAL_OnBufferEndCallback( instance->soundData.streamingSound.mostRecentSampleOffset %= instance->playLength; - if (instance->soundData.streamingSound.isFinalBuffer) + if (stb_vorbis_get_sample_offset(instance->soundData.streamingSound.fileHandle) >= stb_vorbis_stream_length_in_samples(instance->soundData.streamingSound.fileHandle)) { - if (instance->loop) - { - stb_vorbis_seek(instance->soundData.streamingSound.fileHandle, instance->playBegin); - instance->soundData.streamingSound.mostRecentSampleOffset = instance->playBegin; - FAudioGMS_INTERNAL_SoundInstance_AddBuffers(instance); - } - else - { - FAudioGMS_INTERNAL_SoundInstance_Stop(instance); - } + FAudioGMS_INTERNAL_SoundInstance_Stop(instance); } - else + else if (instance->soundState != SoundState_Stopped) { FAudioGMS_INTERNAL_SoundInstance_AddBuffers(instance); } + + /* + SDL_LogInfo( + SDL_LOG_CATEGORY_APPLICATION, + "instance ID: %p, current streaming buffer offset: %u", + instance, + instance->soundData.streamingSound.mostRecentSampleOffset); + */ } if (instance->soundState == SoundState_Stopped) @@ -1018,6 +1016,22 @@ static void FAudioGMS_INTERNAL_SoundInstance_AddBuffers(FAudioGMS_SoundInstance .streamBuffer[instance->soundData.streamingSound.nextStreamBufferIndex], requestedSampleCount * instance->format.nChannels); + /* If the stream ran out and we need to loop, seek to beginning of play region and fill in the remaining samples */ + if (instance->loop && sampleCount < defaultRequestedSampleCount) + { + uint32_t fillInSampleCount = defaultRequestedSampleCount - sampleCount; + stb_vorbis_seek(instance->soundData.streamingSound.fileHandle, instance->playBegin); + + uint32_t remainingSampleCount = stb_vorbis_get_samples_float_interleaved( + instance->soundData.streamingSound.fileHandle, + instance->format.nChannels, + &instance->soundData.streamingSound + .streamBuffer[instance->soundData.streamingSound.nextStreamBufferIndex][sampleCount * instance->format.nChannels], + fillInSampleCount * instance->format.nChannels); + + sampleCount += remainingSampleCount; + } + FAudioBuffer buffer; buffer.AudioBytes = sampleCount * instance->format.nChannels * sizeof(float); buffer.pAudioData = @@ -1034,13 +1048,6 @@ static void FAudioGMS_INTERNAL_SoundInstance_AddBuffers(FAudioGMS_SoundInstance FAudioSourceVoice_SubmitSourceBuffer(instance->voice.handle, &buffer, NULL); - instance->soundData.streamingSound.isFinalBuffer = 0; - - if (sampleCount < defaultRequestedSampleCount) - { - instance->soundData.streamingSound.isFinalBuffer = 1; - } - instance->soundData.streamingSound.nextStreamBufferIndex = (instance->soundData.streamingSound.nextStreamBufferIndex + 1) % STREAMING_BUFFER_COUNT; instance->soundData.streamingSound.buffersLoadedCount += 1; @@ -1081,14 +1088,11 @@ double FAudioGMS_StreamingSound_LoadOGG(char *filePath, double bufferSizeInBytes instance->soundData.streamingSound.streamBufferSize = bufferSizeInBytesInt; instance->soundData.streamingSound.mostRecentSampleOffset = 0; - instance->soundData.streamingSound.isFinalBuffer = 0; instance->soundData.streamingSound.nextStreamBufferIndex = 0; instance->soundData.streamingSound.buffersLoadedCount = 0; instance->playLength = stb_vorbis_stream_length_in_samples(fileHandle); - FAudioGMS_INTERNAL_SoundInstance_AddBuffers(instance); - return instance->id; } @@ -1181,6 +1185,10 @@ static void FAudioGMS_INTERNAL_SoundInstance_Play(FAudioGMS_SoundInstance *insta &instance->soundData.staticSound->buffer, NULL); } + else + { + FAudioGMS_INTERNAL_SoundInstance_AddBuffers(instance); + } FAudioSourceVoice_Start(instance->voice.handle, 0, 0); instance->soundState = SoundState_Playing; @@ -1230,10 +1238,9 @@ static void FAudioGMS_INTERNAL_SoundInstance_Stop(FAudioGMS_SoundInstance *insta { if (instance != NULL) { + /* set before flush so we dont refill on OnBufferEnd callback */ instance->soundState = - SoundState_Stopped; /* set this before so flush - buffers - doesn't trigger buffer add callback */ + SoundState_Stopped; FAudioSourceVoice_Stop(instance->voice.handle, 0, 0); FAudioSourceVoice_FlushSourceBuffers(instance->voice.handle); @@ -1245,8 +1252,6 @@ static void FAudioGMS_INTERNAL_SoundInstance_Stop(FAudioGMS_SoundInstance *insta stb_vorbis_seek( instance->soundData.streamingSound.fileHandle, instance->playBegin); /* back to the start */ - FAudioGMS_INTERNAL_SoundInstance_AddBuffers( - instance); /* preload so we dont stutter on play */ } } else