forked from MoonsideGames/FAudioGMS
change streaming to use OnBufferEnded callback
parent
9983fa3275
commit
23eab952c1
149
src/FAudioGMS.c
149
src/FAudioGMS.c
|
@ -142,52 +142,6 @@ static inline uint32_t IdStack_Pop(IdStack* stack)
|
|||
return stack->array[stack->count];
|
||||
}
|
||||
|
||||
typedef struct BufferQueue
|
||||
{
|
||||
uint32_t head;
|
||||
uint32_t tail;
|
||||
uint32_t size; /* DO NOT MUTATE */
|
||||
uint32_t count; /* number of currently enqueued elements */
|
||||
uint8_t** buffers;
|
||||
} BufferQueue;
|
||||
|
||||
static inline void BufferQueue_Init(BufferQueue* queue, uint32_t size)
|
||||
{
|
||||
queue->head = 0;
|
||||
queue->tail = 0;
|
||||
queue->size = size;
|
||||
queue->count = 0;
|
||||
queue->buffers = SDL_malloc(size * sizeof(uint8_t*));
|
||||
}
|
||||
|
||||
static inline uint8_t* BufferQueue_Dequeue(BufferQueue *queue)
|
||||
{
|
||||
if (queue->tail == queue->head)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t* buffer = queue->buffers[queue->tail];
|
||||
queue->buffers[queue->tail] = NULL;
|
||||
queue->tail = (queue->tail + 1) % queue->size;
|
||||
|
||||
queue->count -= 1;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static inline void BufferQueue_Enqueue(BufferQueue *queue, uint8_t* buffer)
|
||||
{
|
||||
if (((queue->head + 1) % queue->size) == queue->tail)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
queue->buffers[queue->head] = buffer;
|
||||
queue->head = (queue->head + 1) % queue->size;
|
||||
|
||||
queue->count += 1;
|
||||
}
|
||||
|
||||
typedef enum FAudioGMS_SoundState
|
||||
{
|
||||
SoundState_Playing,
|
||||
|
@ -210,7 +164,6 @@ typedef struct FAudioGMS_StreamingSound
|
|||
{
|
||||
stb_vorbis* fileHandle;
|
||||
stb_vorbis_info info;
|
||||
BufferQueue bufferQueue;
|
||||
} FAudioGMS_StreamingSound;
|
||||
|
||||
typedef struct FAudioGMS_SoundInstance
|
||||
|
@ -272,10 +225,8 @@ typedef struct FAudioGMS_EffectChain
|
|||
|
||||
static const float SPEED_OF_SOUND = 343.5f;
|
||||
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 * 8 * sizeof(float) /* FIXME: what should this value be? */
|
||||
#define STREAMING_BUFFER_SIZE 1024 * 16 * sizeof(float) /* FIXME: what should this value be? */
|
||||
|
||||
typedef struct FAudioGMS_Device
|
||||
{
|
||||
|
@ -288,6 +239,8 @@ typedef struct FAudioGMS_Device
|
|||
F3DAUDIO_LISTENER listener;
|
||||
float spatialDistanceScale;
|
||||
|
||||
FAudioVoiceCallback voiceCallbacks;
|
||||
|
||||
FAudioGMS_StaticSound **staticSounds;
|
||||
uint32_t staticSoundCount;
|
||||
IdStack staticSoundIndexStack;
|
||||
|
@ -348,6 +301,17 @@ static inline FAudioGMS_EffectChain* FAudioGMS_INTERNAL_LookupEffectChain(uint32
|
|||
}
|
||||
}
|
||||
|
||||
/* Forward declare this to avoid annoying BS */
|
||||
static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance* instance);
|
||||
|
||||
static void FAudioGMS_INTERNAL_StreamingBufferEndCallback(FAudioVoiceCallback* callback, FAudioGMS_SoundInstance *instance)
|
||||
{
|
||||
if (instance->soundState == SoundState_Playing)
|
||||
{
|
||||
FAudioGMS_INTERNAL_SoundInstance_AddBuffer(instance);
|
||||
}
|
||||
}
|
||||
|
||||
void FAudioGMS_Init(double spatialDistanceScale, double timestep)
|
||||
{
|
||||
device = SDL_malloc(sizeof(FAudioGMS_Device));
|
||||
|
@ -443,6 +407,14 @@ void FAudioGMS_Init(double spatialDistanceScale, double timestep)
|
|||
device->listener.Velocity.z = 0;
|
||||
device->listener.pCone = NULL;
|
||||
|
||||
device->voiceCallbacks.OnBufferEnd = FAudioGMS_INTERNAL_StreamingBufferEndCallback;
|
||||
device->voiceCallbacks.OnBufferStart = NULL;
|
||||
device->voiceCallbacks.OnLoopEnd = NULL;
|
||||
device->voiceCallbacks.OnStreamEnd = NULL;
|
||||
device->voiceCallbacks.OnVoiceError = NULL;
|
||||
device->voiceCallbacks.OnVoiceProcessingPassEnd = NULL;
|
||||
device->voiceCallbacks.OnVoiceProcessingPassStart = NULL;
|
||||
|
||||
device->staticSounds = NULL;
|
||||
device->staticSoundCount = 0;
|
||||
IdStack_Init(&device->staticSoundIndexStack);
|
||||
|
@ -458,7 +430,7 @@ void FAudioGMS_Init(double spatialDistanceScale, double timestep)
|
|||
device->timestep = timestep;
|
||||
|
||||
Log("FAudio initialized successfully!");
|
||||
printf("Device: %ls", device->deviceDetails.DisplayName);
|
||||
printf("Device: %ls\n", device->deviceDetails.DisplayName);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
@ -716,12 +688,14 @@ static void FAudioGMS_INTERNAL_Apply3D(FAudioGMS_SoundInstance* instance)
|
|||
|
||||
static FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_SoundInstance_Init(
|
||||
uint32_t channelCount,
|
||||
uint32_t samplesPerSecond
|
||||
uint32_t samplesPerSecond,
|
||||
uint8_t isStatic
|
||||
) {
|
||||
FAudioGMS_SoundInstance* instance = SDL_malloc(sizeof(FAudioGMS_SoundInstance));
|
||||
|
||||
instance->handle = NULL;
|
||||
|
||||
instance->isStatic = isStatic;
|
||||
instance->loop = 0;
|
||||
instance->destroyOnFinish = 0;
|
||||
|
||||
|
@ -738,7 +712,7 @@ static FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_SoundInstance_Init(
|
|||
&instance->format,
|
||||
FAUDIO_VOICE_USEFILTER,
|
||||
FAUDIO_DEFAULT_FREQ_RATIO,
|
||||
NULL,
|
||||
isStatic ? NULL : &device->voiceCallbacks,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
|
@ -802,7 +776,8 @@ static FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_SoundInstance_CreateFromStati
|
|||
) {
|
||||
FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_SoundInstance_Init(
|
||||
staticSound->channels,
|
||||
staticSound->samplesPerSecond
|
||||
staticSound->samplesPerSecond,
|
||||
1
|
||||
);
|
||||
|
||||
instance->isStatic = 1;
|
||||
|
@ -827,8 +802,6 @@ static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance*
|
|||
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;
|
||||
|
@ -842,7 +815,7 @@ static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance*
|
|||
buffer.LoopBegin = 0;
|
||||
buffer.LoopCount = 0;
|
||||
buffer.LoopLength = 0;
|
||||
buffer.pContext = NULL;
|
||||
buffer.pContext = instance; /* context for OnBufferEnd callback */
|
||||
|
||||
FAudioSourceVoice_SubmitSourceBuffer(instance->handle, &buffer, NULL);
|
||||
|
||||
|
@ -860,31 +833,6 @@ static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance*
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
RETURN_ON_NULL_DEVICE(-1.0)
|
||||
|
@ -902,15 +850,14 @@ double FAudioGMS_StreamingSound_LoadOGG(char* filePath)
|
|||
|
||||
FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_SoundInstance_Init(
|
||||
info.channels,
|
||||
info.sample_rate
|
||||
info.sample_rate,
|
||||
0
|
||||
);
|
||||
|
||||
instance->isStatic = 0;
|
||||
instance->soundData.streamingSound.fileHandle = fileHandle;
|
||||
instance->soundData.streamingSound.info = info;
|
||||
BufferQueue_Init(&instance->soundData.streamingSound.bufferQueue, MAX_BUFFER_QUEUE_COUNT);
|
||||
|
||||
FAudioGMS_INTERNAL_SoundInstance_StreamingUpdate(instance);
|
||||
FAudioGMS_INTERNAL_SoundInstance_AddBuffer(instance);
|
||||
|
||||
return instance->id;
|
||||
}
|
||||
|
@ -956,18 +903,6 @@ static void FAudioGMS_INTERNAL_StaticSound_AddEmitter(FAudioGMS_SoundInstance* i
|
|||
FAudioGMS_INTERNAL_Apply3D(instance);
|
||||
}
|
||||
|
||||
static void FAudioGMS_INTERNAL_SoundInstance_ClearBuffers(FAudioGMS_SoundInstance* instance)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t bufferCount = instance->soundData.streamingSound.bufferQueue.count;
|
||||
|
||||
for (i = 0; i < bufferCount; i += 1)
|
||||
{
|
||||
uint8_t* buffer = BufferQueue_Dequeue(&instance->soundData.streamingSound.bufferQueue);
|
||||
SDL_free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static void FAudioGMS_INTERNAL_SoundInstance_Play(FAudioGMS_SoundInstance* instance)
|
||||
{
|
||||
if (instance->soundState == SoundState_Playing)
|
||||
|
@ -992,10 +927,6 @@ static void FAudioGMS_INTERNAL_SoundInstance_Play(FAudioGMS_SoundInstance* insta
|
|||
|
||||
FAudioSourceVoice_SubmitSourceBuffer(instance->handle, &instance->soundData.staticSound->buffer, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
FAudioGMS_INTERNAL_SoundInstance_StreamingUpdate(instance);
|
||||
}
|
||||
|
||||
FAudioSourceVoice_Start(instance->handle, 0, 0);
|
||||
instance->soundState = SoundState_Playing;
|
||||
|
@ -1114,17 +1045,16 @@ static void FAudioGMS_INTERNAL_SoundInstance_Stop(FAudioGMS_SoundInstance* insta
|
|||
{
|
||||
if (instance != NULL)
|
||||
{
|
||||
instance->soundState = SoundState_Stopped; /* set this before so flush buffers doesn't trigger buffer add callback */
|
||||
|
||||
FAudioSourceVoice_Stop(instance->handle, 0, 0);
|
||||
FAudioSourceVoice_FlushSourceBuffers(instance->handle);
|
||||
|
||||
if (!instance->isStatic)
|
||||
{
|
||||
FAudioGMS_INTERNAL_SoundInstance_ClearBuffers(instance);
|
||||
stb_vorbis_seek_start(instance->soundData.streamingSound.fileHandle); /* back to the start */
|
||||
FAudioGMS_INTERNAL_SoundInstance_StreamingUpdate(instance); /* preload so we dont stutter on play */
|
||||
FAudioGMS_INTERNAL_SoundInstance_AddBuffer(instance); /* preload so we dont stutter on play */
|
||||
}
|
||||
|
||||
instance->soundState = SoundState_Stopped;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1317,7 +1247,6 @@ static void FAudioGMS_INTERNAL_SoundInstance_Destroy(FAudioGMS_SoundInstance* in
|
|||
FAudioVoice_DestroyVoice(instance->handle);
|
||||
if (!instance->isStatic)
|
||||
{
|
||||
SDL_free(instance->soundData.streamingSound.bufferQueue.buffers);
|
||||
stb_vorbis_close(instance->soundData.streamingSound.fileHandle);
|
||||
}
|
||||
if (instance->is3D)
|
||||
|
@ -1667,12 +1596,6 @@ void FAudioGMS_Update()
|
|||
FAudioGMS_INTERNAL_SoundInstance_SetVolume(instance, volume);
|
||||
}
|
||||
|
||||
/* Update streaming instance */
|
||||
if (!instance->isStatic && instance->soundState == SoundState_Playing)
|
||||
{
|
||||
FAudioGMS_INTERNAL_SoundInstance_StreamingUpdate(instance);
|
||||
}
|
||||
|
||||
if (instance->destroyOnFinish)
|
||||
{
|
||||
FAudioVoiceState state;
|
||||
|
|
Loading…
Reference in New Issue