fix audio buffer stutter + add pass filter API

main
cosmonaut 2021-10-27 11:41:04 -07:00
parent e5b743d06b
commit 2ee6e8b5b5
2 changed files with 111 additions and 78 deletions

View File

@ -257,7 +257,7 @@ static const float DOPPLER_SCALE = 1.0f;
static const uint32_t MINIMUM_BUFFER_CHECK = 3;
#define MAX_BUFFER_QUEUE_COUNT 16
#define STREAMING_BUFFER_SIZE 1024 * 128 * sizeof(float) /* FIXME: what should this value be? */
#define STREAMING_BUFFER_SIZE 1024 * 8 * sizeof(float) /* FIXME: what should this value be? */
typedef struct FAudioGMS_Device
{
@ -645,6 +645,16 @@ static void FAudioGMS_INTERNAL_SoundInstance_SetLowPassFilter(FAudioGMS_SoundIns
instance->lowPassFilter = lowPassFilter;
}
void FAudioGMS_SoundInstance_SetLowPassFilter(double soundInstanceID, float lowPassFilter)
{
FAudioGMS_SoundInstance *instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID);
if (instance != NULL)
{
FAudioGMS_INTERNAL_SoundInstance_SetLowPassFilter(instance, lowPassFilter);
}
}
static void FAudioGMS_INTERNAL_SoundInstance_SetHighPassFilter(FAudioGMS_SoundInstance* instance, float highPassFilter)
{
FAudioFilterParameters p;
@ -657,6 +667,16 @@ static void FAudioGMS_INTERNAL_SoundInstance_SetHighPassFilter(FAudioGMS_SoundIn
instance->highPassFilter = highPassFilter;
}
void FAudioGMS_SoundInstance_SetHighPassFilter(double soundInstanceID, float highPassFilter)
{
FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID);
if (instance != NULL)
{
FAudioGMS_INTERNAL_SoundInstance_SetHighPassFilter(instance, highPassFilter);
}
}
static void FAudioGMS_INTERNAL_SoundInstance_SetBandPassFilter(FAudioGMS_SoundInstance* instance, float bandPassFilter)
{
FAudioFilterParameters p;
@ -669,6 +689,16 @@ static void FAudioGMS_INTERNAL_SoundInstance_SetBandPassFilter(FAudioGMS_SoundIn
instance->bandPassFilter = bandPassFilter;
}
void FAudioGMS_SoundInstance_SetBandPassFilter(double soundInstanceID, float bandPassFilter)
{
FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID);
if (instance != NULL)
{
FAudioGMS_INTERNAL_SoundInstance_SetBandPassFilter(instance, bandPassFilter);
}
}
static void FAudioGMS_INTERNAL_SoundInstance_SetPan(FAudioGMS_SoundInstance* instance, float pan)
{
instance->pan = pan;
@ -713,6 +743,7 @@ static void FAudioGMS_INTERNAL_SoundInstance_SetPitch(FAudioGMS_SoundInstance* i
static void FAudioGMS_INTERNAL_SoundInstance_SetVolume(FAudioGMS_SoundInstance* instance, float volume)
{
instance->volume = volume;
FAudioVoice_SetVolume(instance->handle, volume, 0);
}
@ -852,6 +883,80 @@ static FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_SoundInstance_CreateFromStati
return instance;
}
static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance* instance)
{
/* NOTE: this function returns samples per channel, not total samples */
uint32_t samples = stb_vorbis_get_samples_float_interleaved(
instance->soundData.streamingSound.fileHandle,
instance->format.nChannels,
device->streamStagingBuffer,
STREAMING_BUFFER_SIZE
);
uint32_t sampleCount = samples * instance->format.nChannels;
uint32_t bufferLength = sampleCount * sizeof(float);
uint8_t* nextBuffer = SDL_malloc(bufferLength);
SDL_memcpy(nextBuffer, device->streamStagingBuffer, bufferLength);
BufferQueue_Enqueue(&instance->soundData.streamingSound.bufferQueue, nextBuffer);
FAudioBuffer buffer;
buffer.AudioBytes = bufferLength;
buffer.pAudioData = nextBuffer;
buffer.PlayLength =
bufferLength /
instance->format.nChannels /
(instance->format.wBitsPerSample / 8);
buffer.PlayBegin = 0;
buffer.Flags = 0;
buffer.LoopBegin = 0;
buffer.LoopCount = 0;
buffer.LoopLength = 0;
buffer.pContext = NULL;
FAudioSourceVoice_SubmitSourceBuffer(instance->handle, &buffer, NULL);
/* We have reached the end of the file! */
if (sampleCount < STREAMING_BUFFER_SIZE)
{
if (instance->loop)
{
stb_vorbis_seek_start(instance->soundData.streamingSound.fileHandle);
}
else
{
instance->soundState = SoundState_Stopped;
}
}
}
static void FAudioGMS_INTERNAL_SoundInstance_StreamingUpdate(FAudioGMS_SoundInstance* instance)
{
uint32_t i;
FAudioVoiceState voiceState;
if (instance->isStatic) { return; }
FAudioSourceVoice_GetState(
instance->handle,
&voiceState,
FAUDIO_VOICE_NOSAMPLESPLAYED
);
while (instance->soundData.streamingSound.bufferQueue.count > voiceState.BuffersQueued)
{
uint8_t* buffer = BufferQueue_Dequeue(&instance->soundData.streamingSound.bufferQueue);
SDL_free(buffer);
}
for (i = MINIMUM_BUFFER_CHECK - instance->soundData.streamingSound.bufferQueue.count; i > 0; i -= 1)
{
FAudioGMS_INTERNAL_SoundInstance_AddBuffer(instance);
}
}
double FAudioGMS_StreamingSound_LoadOGG(char* filePath)
{
int error = 0;
@ -876,6 +981,8 @@ double FAudioGMS_StreamingSound_LoadOGG(char* filePath)
instance->soundData.streamingSound.info = info;
BufferQueue_Init(&instance->soundData.streamingSound.bufferQueue, MAX_BUFFER_QUEUE_COUNT);
FAudioGMS_INTERNAL_SoundInstance_StreamingUpdate(instance);
return instance->id;
}
@ -920,83 +1027,6 @@ static void FAudioGMS_INTERNAL_StaticSound_AddEmitter(FAudioGMS_SoundInstance* i
FAudioGMS_INTERNAL_Apply3D(instance);
}
static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance* instance)
{
/* NOTE: this function returns samples per channel, not total samples */
uint32_t samples = stb_vorbis_get_samples_float_interleaved(
instance->soundData.streamingSound.fileHandle,
instance->format.nChannels,
device->streamStagingBuffer,
STREAMING_BUFFER_SIZE
);
uint32_t sampleCount = samples * instance->format.nChannels;
uint32_t bufferLength = sampleCount * sizeof(float);
uint8_t* nextBuffer = SDL_malloc(bufferLength);
SDL_memcpy(nextBuffer, device->streamStagingBuffer, bufferLength);
BufferQueue_Enqueue(&instance->soundData.streamingSound.bufferQueue, nextBuffer);
if (instance->soundState != SoundState_Stopped)
{
FAudioBuffer buffer;
buffer.AudioBytes = bufferLength;
buffer.pAudioData = nextBuffer;
buffer.PlayLength =
bufferLength /
instance->format.nChannels /
(instance->format.wBitsPerSample / 8);
buffer.PlayBegin = 0;
buffer.Flags = 0;
buffer.LoopBegin = 0;
buffer.LoopCount = 0;
buffer.LoopLength = 0;
buffer.pContext = NULL;
FAudioSourceVoice_SubmitSourceBuffer(instance->handle, &buffer, NULL);
}
/* We have reached the end of the file! */
if (sampleCount < STREAMING_BUFFER_SIZE)
{
if (instance->loop)
{
stb_vorbis_seek_start(instance->soundData.streamingSound.fileHandle);
}
else
{
instance->soundState = SoundState_Stopped;
}
}
}
static void FAudioGMS_INTERNAL_SoundInstance_StreamingUpdate(FAudioGMS_SoundInstance* instance)
{
uint32_t i;
FAudioVoiceState voiceState;
if (instance->isStatic) { return; }
FAudioSourceVoice_GetState(
instance->handle,
&voiceState,
FAUDIO_VOICE_NOSAMPLESPLAYED
);
while (instance->soundData.streamingSound.bufferQueue.count > voiceState.BuffersQueued)
{
uint8_t* buffer = BufferQueue_Dequeue(&instance->soundData.streamingSound.bufferQueue);
SDL_free(buffer);
}
for (i = MINIMUM_BUFFER_CHECK - instance->soundData.streamingSound.bufferQueue.count; i > 0; i -= 1)
{
FAudioGMS_INTERNAL_SoundInstance_AddBuffer(instance);
}
}
static void FAudioGMS_INTERNAL_SoundInstance_ClearBuffers(FAudioGMS_SoundInstance* instance)
{
uint32_t i;

View File

@ -62,6 +62,9 @@ FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetReverb(double soundInstanceID, doub
FAUDIOGMSAPI void FAudioGMS_SoundInstance_Set3DPosition(double soundInstanceID, double x, double y, double z);
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetTrackPosition(double soundInstanceID, double trackPositionInSeconds);
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetVolumeOverTime(double soundInstanceID, double volume, double milliseconds);
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetLowPassFilter(double soundInstanceID, float lowPassFilter);
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetHighPassFilter(double soundInstanceID, float highPassFilter);
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetBandPassFilter(double soundInstanceID, float bandPassFilter);
FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetPitch(double soundInstanceID);
FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetVolume(double soundInstanceID);