fix audio buffer stutter + add pass filter API
parent
cd30405820
commit
92fdc4753b
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;
|
static const uint32_t MINIMUM_BUFFER_CHECK = 3;
|
||||||
|
|
||||||
#define MAX_BUFFER_QUEUE_COUNT 16
|
#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
|
typedef struct FAudioGMS_Device
|
||||||
{
|
{
|
||||||
|
@ -645,6 +645,16 @@ static void FAudioGMS_INTERNAL_SoundInstance_SetLowPassFilter(FAudioGMS_SoundIns
|
||||||
instance->lowPassFilter = lowPassFilter;
|
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)
|
static void FAudioGMS_INTERNAL_SoundInstance_SetHighPassFilter(FAudioGMS_SoundInstance* instance, float highPassFilter)
|
||||||
{
|
{
|
||||||
FAudioFilterParameters p;
|
FAudioFilterParameters p;
|
||||||
|
@ -657,6 +667,16 @@ static void FAudioGMS_INTERNAL_SoundInstance_SetHighPassFilter(FAudioGMS_SoundIn
|
||||||
instance->highPassFilter = highPassFilter;
|
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)
|
static void FAudioGMS_INTERNAL_SoundInstance_SetBandPassFilter(FAudioGMS_SoundInstance* instance, float bandPassFilter)
|
||||||
{
|
{
|
||||||
FAudioFilterParameters p;
|
FAudioFilterParameters p;
|
||||||
|
@ -669,6 +689,16 @@ static void FAudioGMS_INTERNAL_SoundInstance_SetBandPassFilter(FAudioGMS_SoundIn
|
||||||
instance->bandPassFilter = bandPassFilter;
|
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)
|
static void FAudioGMS_INTERNAL_SoundInstance_SetPan(FAudioGMS_SoundInstance* instance, float pan)
|
||||||
{
|
{
|
||||||
instance->pan = 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)
|
static void FAudioGMS_INTERNAL_SoundInstance_SetVolume(FAudioGMS_SoundInstance* instance, float volume)
|
||||||
{
|
{
|
||||||
|
instance->volume = volume;
|
||||||
FAudioVoice_SetVolume(instance->handle, volume, 0);
|
FAudioVoice_SetVolume(instance->handle, volume, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -852,6 +883,80 @@ static FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_SoundInstance_CreateFromStati
|
||||||
return instance;
|
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)
|
double FAudioGMS_StreamingSound_LoadOGG(char* filePath)
|
||||||
{
|
{
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
@ -876,6 +981,8 @@ double FAudioGMS_StreamingSound_LoadOGG(char* filePath)
|
||||||
instance->soundData.streamingSound.info = info;
|
instance->soundData.streamingSound.info = info;
|
||||||
BufferQueue_Init(&instance->soundData.streamingSound.bufferQueue, MAX_BUFFER_QUEUE_COUNT);
|
BufferQueue_Init(&instance->soundData.streamingSound.bufferQueue, MAX_BUFFER_QUEUE_COUNT);
|
||||||
|
|
||||||
|
FAudioGMS_INTERNAL_SoundInstance_StreamingUpdate(instance);
|
||||||
|
|
||||||
return instance->id;
|
return instance->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -920,83 +1027,6 @@ static void FAudioGMS_INTERNAL_StaticSound_AddEmitter(FAudioGMS_SoundInstance* i
|
||||||
FAudioGMS_INTERNAL_Apply3D(instance);
|
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)
|
static void FAudioGMS_INTERNAL_SoundInstance_ClearBuffers(FAudioGMS_SoundInstance* instance)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
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_Set3DPosition(double soundInstanceID, double x, double y, double z);
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetTrackPosition(double soundInstanceID, double trackPositionInSeconds);
|
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetTrackPosition(double soundInstanceID, double trackPositionInSeconds);
|
||||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetVolumeOverTime(double soundInstanceID, double volume, double milliseconds);
|
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_GetPitch(double soundInstanceID);
|
||||||
FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetVolume(double soundInstanceID);
|
FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetVolume(double soundInstanceID);
|
||||||
|
|
Loading…
Reference in New Issue