tweak stream loop behavior

main
cosmonaut 2021-11-24 10:55:24 -08:00
parent e12914177f
commit d3708f5e16
1 changed files with 34 additions and 29 deletions

View File

@ -175,7 +175,7 @@ typedef struct FAudioGMS_StaticSound
} FAudioGMS_StaticSound; } FAudioGMS_StaticSound;
/* if we don't triple buffer, we'll microstutter the voice while waiting for decode */ /* 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 #define DEFAULT_STREAMING_BUFFER_SIZE 32768
typedef struct FAudioGMS_StreamingSound typedef struct FAudioGMS_StreamingSound
@ -187,7 +187,6 @@ typedef struct FAudioGMS_StreamingSound
uint32_t nextStreamBufferIndex; /* it's a ring buffer! */ uint32_t nextStreamBufferIndex; /* it's a ring buffer! */
uint32_t buffersLoadedCount; /* how many buffers are we buffering? */ uint32_t buffersLoadedCount; /* how many buffers are we buffering? */
uint32_t mostRecentSampleOffset; /* used for calculating track position */ uint32_t mostRecentSampleOffset; /* used for calculating track position */
uint8_t isFinalBuffer; /* used to detect end of playback */
} FAudioGMS_StreamingSound; } FAudioGMS_StreamingSound;
typedef struct FAudioGMS_SoundInstance FAudioGMS_SoundInstance; typedef struct FAudioGMS_SoundInstance FAudioGMS_SoundInstance;
@ -358,23 +357,22 @@ static void FAudioGMS_INTERNAL_OnBufferEndCallback(
instance->soundData.streamingSound.mostRecentSampleOffset %= instance->playLength; 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) FAudioGMS_INTERNAL_SoundInstance_Stop(instance);
{
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);
}
} }
else else if (instance->soundState != SoundState_Stopped)
{ {
FAudioGMS_INTERNAL_SoundInstance_AddBuffers(instance); 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) if (instance->soundState == SoundState_Stopped)
@ -1018,6 +1016,22 @@ static void FAudioGMS_INTERNAL_SoundInstance_AddBuffers(FAudioGMS_SoundInstance
.streamBuffer[instance->soundData.streamingSound.nextStreamBufferIndex], .streamBuffer[instance->soundData.streamingSound.nextStreamBufferIndex],
requestedSampleCount * instance->format.nChannels); 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; FAudioBuffer buffer;
buffer.AudioBytes = sampleCount * instance->format.nChannels * sizeof(float); buffer.AudioBytes = sampleCount * instance->format.nChannels * sizeof(float);
buffer.pAudioData = buffer.pAudioData =
@ -1034,13 +1048,6 @@ static void FAudioGMS_INTERNAL_SoundInstance_AddBuffers(FAudioGMS_SoundInstance
FAudioSourceVoice_SubmitSourceBuffer(instance->voice.handle, &buffer, NULL); 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 =
(instance->soundData.streamingSound.nextStreamBufferIndex + 1) % STREAMING_BUFFER_COUNT; (instance->soundData.streamingSound.nextStreamBufferIndex + 1) % STREAMING_BUFFER_COUNT;
instance->soundData.streamingSound.buffersLoadedCount += 1; 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.streamBufferSize = bufferSizeInBytesInt;
instance->soundData.streamingSound.mostRecentSampleOffset = 0; instance->soundData.streamingSound.mostRecentSampleOffset = 0;
instance->soundData.streamingSound.isFinalBuffer = 0;
instance->soundData.streamingSound.nextStreamBufferIndex = 0; instance->soundData.streamingSound.nextStreamBufferIndex = 0;
instance->soundData.streamingSound.buffersLoadedCount = 0; instance->soundData.streamingSound.buffersLoadedCount = 0;
instance->playLength = stb_vorbis_stream_length_in_samples(fileHandle); instance->playLength = stb_vorbis_stream_length_in_samples(fileHandle);
FAudioGMS_INTERNAL_SoundInstance_AddBuffers(instance);
return instance->id; return instance->id;
} }
@ -1181,6 +1185,10 @@ static void FAudioGMS_INTERNAL_SoundInstance_Play(FAudioGMS_SoundInstance *insta
&instance->soundData.staticSound->buffer, &instance->soundData.staticSound->buffer,
NULL); NULL);
} }
else
{
FAudioGMS_INTERNAL_SoundInstance_AddBuffers(instance);
}
FAudioSourceVoice_Start(instance->voice.handle, 0, 0); FAudioSourceVoice_Start(instance->voice.handle, 0, 0);
instance->soundState = SoundState_Playing; instance->soundState = SoundState_Playing;
@ -1230,10 +1238,9 @@ static void FAudioGMS_INTERNAL_SoundInstance_Stop(FAudioGMS_SoundInstance *insta
{ {
if (instance != NULL) if (instance != NULL)
{ {
/* set before flush so we dont refill on OnBufferEnd callback */
instance->soundState = instance->soundState =
SoundState_Stopped; /* set this before so flush SoundState_Stopped;
buffers
doesn't trigger buffer add callback */
FAudioSourceVoice_Stop(instance->voice.handle, 0, 0); FAudioSourceVoice_Stop(instance->voice.handle, 0, 0);
FAudioSourceVoice_FlushSourceBuffers(instance->voice.handle); FAudioSourceVoice_FlushSourceBuffers(instance->voice.handle);
@ -1245,8 +1252,6 @@ static void FAudioGMS_INTERNAL_SoundInstance_Stop(FAudioGMS_SoundInstance *insta
stb_vorbis_seek( stb_vorbis_seek(
instance->soundData.streamingSound.fileHandle, instance->soundData.streamingSound.fileHandle,
instance->playBegin); /* back to the start */ instance->playBegin); /* back to the start */
FAudioGMS_INTERNAL_SoundInstance_AddBuffers(
instance); /* preload so we dont stutter on play */
} }
} }
else else