forked from MoonsideGames/FAudioGMS
fix audio buffer stutter + add pass filter API
parent
e5b743d06b
commit
2ee6e8b5b5
186
src/FAudioGMS.c
186
src/FAudioGMS.c
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue