From 39ef3c10431fc544b6118e05e94ec71574aec818 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 26 Oct 2021 16:47:53 -0700 Subject: [PATCH] more API goodies --- src/FAudioGMS.c | 228 +++++++++++++++++++++++++++++++++++++++++++----- src/FAudioGMS.h | 30 +++++-- 2 files changed, 226 insertions(+), 32 deletions(-) diff --git a/src/FAudioGMS.c b/src/FAudioGMS.c index f737fa2..2d1f68f 100644 --- a/src/FAudioGMS.c +++ b/src/FAudioGMS.c @@ -203,6 +203,7 @@ typedef struct FAudioGMS_StaticSound uint32_t samplesPerSecond; uint32_t loopStart; uint32_t loopLength; + uint32_t lengthInSeconds; } FAudioGMS_StaticSound; typedef struct FAudioGMS_StreamingSound @@ -233,6 +234,10 @@ typedef struct FAudioGMS_SoundInstance FAudioSubmixVoice* reverbVoice; FAudioVoiceSends reverbSends; + uint8_t adjustingVolumeOverTime; + float targetVolume; + float volumeDelta; + uint8_t isStatic; uint8_t destroyOnFinish; @@ -274,6 +279,7 @@ typedef struct FAudioGMS_Device IdStack soundInstanceIndexStack; float streamStagingBuffer[STREAMING_BUFFER_SIZE]; + double timestep; } FAudioGMS_Device; static FAudioGMS_Device* device = NULL; @@ -304,7 +310,7 @@ static inline FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_LookupSoundInstance(ui } } -void FAudioGMS_Init(double spatialDistanceScale) +void FAudioGMS_Init(double spatialDistanceScale, double timestep) { device = SDL_malloc(sizeof(FAudioGMS_Device)); @@ -407,6 +413,8 @@ void FAudioGMS_Init(double spatialDistanceScale) device->soundInstanceCount = 0; IdStack_Init(&device->soundInstanceIndexStack); + device->timestep = timestep; + Log("FAudio initialized successfully!"); printf("Device: %ls", device->deviceDetails.DisplayName); fflush(stdout); @@ -494,6 +502,8 @@ double FAudioGMS_StaticSound_LoadWAV(char *filePath) sound->loopStart = 0; sound->loopLength = 0; + sound->lengthInSeconds = frameCount / sound->samplesPerSecond; + if (device->staticSoundIndexStack.count > 0) { sound->id = IdStack_Pop(&device->staticSoundIndexStack); @@ -802,6 +812,10 @@ static FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_SoundInstance_Init( instance->soundState = SoundState_Stopped; + instance->adjustingVolumeOverTime = 0; + instance->volumeDelta = 0; + instance->targetVolume = 1; + instance->is3D = 0; instance->emitter = NULL; instance->stereoAzimuth[0] = 0.0f; @@ -1102,19 +1116,20 @@ double FAudioGMS_StaticSound_PlaySpatial(double staticSoundID, double x, double } } -void FAudioGMS_SoundInstance_Play(double id) +void FAudioGMS_SoundInstance_Play(double soundInstanceID, double loop) { - FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)id); + FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); if (instance != NULL) { + instance->loop = (uint8_t) loop; FAudioGMS_INTERNAL_SoundInstance_Play(instance); } } -void FAudioGMS_SoundInstance_Pause(double id) +void FAudioGMS_SoundInstance_Pause(double soundInstanceID) { - FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)id); + FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); if (instance != NULL) { @@ -1147,10 +1162,10 @@ static void FAudioGMS_INTERNAL_SoundInstance_Stop(FAudioGMS_SoundInstance* insta } } -void FAudioGMS_SoundInstance_Stop(double id) +void FAudioGMS_SoundInstance_Stop(double soundInstanceID) { - FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)id); - FAudioGMS_INTERNAL_SoundInstance_Stop(instance); +FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); +FAudioGMS_INTERNAL_SoundInstance_Stop(instance); } static void FAudioGMS_INTERNAL_SoundInstance_StopImmediate(FAudioGMS_SoundInstance* instance) @@ -1173,12 +1188,52 @@ static void FAudioGMS_INTERNAL_SoundInstance_StopImmediate(FAudioGMS_SoundInstan } } -void FAudioGMS_SoundInstance_StopImmediate(double id) +void FAudioGMS_SoundInstance_StopImmediate(double soundInstanceID) { - FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)id); + FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); FAudioGMS_INTERNAL_SoundInstance_StopImmediate(instance); } +void FAudioGMS_SoundInstance_SetPan(double soundInstanceID, double pan) +{ + FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); + + if (instance != NULL) + { + FAudioGMS_INTERNAL_SoundInstance_SetPan(instance, pan); + } +} + +void FAudioGMS_SoundInstance_SetPitch(double soundInstanceID, double pitch) +{ + FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); + + if (instance != NULL) + { + FAudioGMS_INTERNAL_SoundInstance_SetPitch(instance, pitch); + } +} + +void FAudioGMS_SoundInstance_SetVolume(double soundInstanceID, double volume) +{ + FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); + + if (instance != NULL) + { + FAudioGMS_INTERNAL_SoundInstance_SetVolume(instance, volume); + } +} + +void FAudioGMS_SoundInstance_SetReverb(double soundInstanceID, double reverb) +{ + FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); + + if (instance != NULL) + { + FAudioGMS_INTERNAL_SoundInstance_SetReverb(instance, reverb); + } +} + void FAudioGMS_SoundInstance_Set3DPosition(double soundInstanceID, double x, double y, double z) { FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); @@ -1201,6 +1256,100 @@ void FAudioGMS_SoundInstance_Set3DPosition(double soundInstanceID, double x, dou } } +void FAudioGMS_SoundInstance_SetTrackPosition(double soundInstanceID, double trackPositionInSeconds) +{ + FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); + + if (instance != NULL) + { + uint32_t sampleFrame = instance->soundData.staticSound->samplesPerSecond * trackPositionInSeconds; + + FAudioGMS_SoundState currentState = instance->soundState; + if (currentState == SoundState_Playing) + { + FAudioGMS_INTERNAL_SoundInstance_StopImmediate(instance); + } + + if (instance->isStatic) + { + instance->soundData.staticSound->buffer.PlayBegin = instance->soundData.staticSound->samplesPerSecond * trackPositionInSeconds; + } + else + { + stb_vorbis_seek(instance->soundData.streamingSound.fileHandle, sampleFrame); + } + + if (currentState == SoundState_Playing) + { + FAudioGMS_INTERNAL_SoundInstance_Play(instance); + } + } +} + +void FAudioGMS_SoundInstance_SetVolumeOverTime(double soundInstanceID, double volume, double milliseconds) +{ + FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID);\ + + if (instance != NULL) + { + instance->adjustingVolumeOverTime = 1; + instance->targetVolume = volume; + instance->volumeDelta = (volume - instance->volume) / (milliseconds / device->timestep); + } +} + +double FAudioGMS_SoundInstance_GetPitch(double soundInstanceID) +{ + FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); + + if (instance != NULL) + { + return instance->pitch; + } + else + { + Log("Invalid sound instance!"); + return -1; + } +} + +double FAudioGMS_SoundInstance_GetVolume(double soundInstanceID) +{ + FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); + + if (instance != NULL) + { + return instance->volume; + } + else + { + Log("Invalid sound instance!"); + return -1; + } +} + +double FAudioGMS_SoundInstance_GetTrackLengthInSeconds(double soundInstanceID) +{ + FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); + + if (instance != NULL) + { + if (instance->isStatic) + { + return instance->soundData.staticSound->lengthInSeconds; + } + else + { + return stb_vorbis_stream_length_in_seconds(instance->soundData.streamingSound.fileHandle); + } + } + else + { + Log("Invalid sound instance!"); + return -1; + } +} + void FAudioGMS_SetListenerPosition(double x, double y, double z) { device->listener.Velocity.x = x - device->listener.Position.x; @@ -1234,9 +1383,9 @@ static void FAudioGMS_INTERNAL_SoundInstance_Destroy(FAudioGMS_SoundInstance* in } } -void FAudioGMS_SoundInstance_Destroy(double id) +void FAudioGMS_SoundInstance_Destroy(double soundInstanceID) { - FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)id); + FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); if (instance != NULL) { @@ -1244,9 +1393,9 @@ void FAudioGMS_SoundInstance_Destroy(double id) } } -void FAudioGMS_SoundInstance_DestroyWhenFinished(double id) +void FAudioGMS_SoundInstance_DestroyWhenFinished(double soundInstanceID) { - FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)id); + FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); if (instance != NULL) { @@ -1266,16 +1415,10 @@ static void FAudioGMS_INTERNAL_StaticSound_Destroy(FAudioGMS_StaticSound* sound) } } -void FAudioGMS_StaticSound_Destroy(double id) +void FAudioGMS_StaticSound_Destroy(double staticSoundID) { - if (id >= 0 && id < device->staticSoundCount) - { - FAudioGMS_INTERNAL_StaticSound_Destroy(device->staticSounds[(uint32_t)id]); - } - else - { - Log("Invalid ID for destroy!"); - } + FAudioGMS_StaticSound *sound = FAudioGMS_INTERNAL_LookupStaticSound((uint32_t)staticSoundID); + FAudioGMS_INTERNAL_StaticSound_Destroy(sound); } void FAudioGMS_Update() @@ -1293,6 +1436,33 @@ void FAudioGMS_Update() FAudioGMS_INTERNAL_Apply3D(instance); } + if (instance->adjustingVolumeOverTime) + { + float volume = instance->volume + instance->volumeDelta; + if (instance->volumeDelta > 0) + { + if (volume >= instance->targetVolume) + { + volume = instance->targetVolume; + instance->adjustingVolumeOverTime = 0; + } + } + else if (instance->volumeDelta < 0) + { + if (volume <= instance->targetVolume) + { + volume = instance->targetVolume; + instance->adjustingVolumeOverTime = 0; + } + } + else + { + instance->adjustingVolumeOverTime = 0; + } + + FAudioGMS_INTERNAL_SoundInstance_SetVolume(instance, volume); + } + /* Update streaming instance */ if (!instance->isStatic && instance->soundState == SoundState_Playing) { @@ -1313,9 +1483,19 @@ void FAudioGMS_Update() } } +void FAudioGMS_StopAll() +{ + uint32_t i; + + for (i = 0; i < device->soundInstanceCount; i += 1) + { + FAudioGMS_INTERNAL_SoundInstance_StopImmediate(device->soundInstances[i]); + } +} + void FAudioGMS_Destroy() { - uint32_t i = 0; + uint32_t i; for (i = 0; i < device->soundInstanceCount; i += 1) { diff --git a/src/FAudioGMS.h b/src/FAudioGMS.h index 70c9138..f4eac8a 100644 --- a/src/FAudioGMS.h +++ b/src/FAudioGMS.h @@ -39,27 +39,41 @@ extern "C" { #endif /* __cplusplus */ -FAUDIOGMSAPI void FAudioGMS_Init(double spatialDistanceScale); /* recommend about 50 for a 2D game, 1 for a 3D game */ +FAUDIOGMSAPI void FAudioGMS_Init(double spatialDistanceScale, double timestep); FAUDIOGMSAPI double FAudioGMS_StaticSound_LoadWAV(char *filePath); /* returns a static sound ID */ FAUDIOGMSAPI void FAudioGMS_StaticSound_PlayOneOff(double staticSoundID, double pan, double pitch, double volume, double reverb); /* automatically frees itself when done! */ FAUDIOGMSAPI void FAudioGMS_StaticSound_PlayOneOffSpatial(double staticSoundID, double x, double y, double z, double pitch, double volume, double reverb); /* automatically frees itself when done! */ FAUDIOGMSAPI double FAudioGMS_StaticSound_Play(double staticSoundID, double pan, double pitch, double volume, double reverb, double loop); /* returns a sound instance ID. must be freed! */ FAUDIOGMSAPI double FAudioGMS_StaticSound_PlaySpatial(double staticSoundID, double x, double y, double z, double pitch, double volume, double reverb, double loop); /* returns a sound instance ID. must be freed! */ -FAUDIOGMSAPI void FAudioGMS_StaticSound_Destroy(double id); +FAUDIOGMSAPI void FAudioGMS_StaticSound_Destroy(double staticSoundID); FAUDIOGMSAPI double FAudioGMS_StreamingSound_LoadOGG(char* filepath); /* returns a sound instance */ -FAUDIOGMSAPI void FAudioGMS_SoundInstance_Play(double id); -FAUDIOGMSAPI void FAudioGMS_SoundInstance_Pause(double id); -FAUDIOGMSAPI void FAudioGMS_SoundInstance_Stop(double id); -FAUDIOGMSAPI void FAudioGMS_SoundInstance_StopImmediate(double id); +FAUDIOGMSAPI void FAudioGMS_SoundInstance_Play(double soundInstanceID, double loop); +FAUDIOGMSAPI void FAudioGMS_SoundInstance_Pause(double soundInstanceID); +FAUDIOGMSAPI void FAudioGMS_SoundInstance_Stop(double soundInstanceID); +FAUDIOGMSAPI void FAudioGMS_SoundInstance_StopImmediate(double soundInstanceID); + +FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetPan(double soundInstanceID, double pan); +FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetPitch(double soundInstanceID, double pitch); +FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetVolume(double soundInstanceID, double volume); +FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetReverb(double soundInstanceID, double reverb); FAUDIOGMSAPI void FAudioGMS_SoundInstance_Set3DPosition(double soundInstanceID, double x, double y, double z); -FAUDIOGMSAPI void FAudioGMS_SoundInstance_Destroy(double id); -FAUDIOGMSAPI void FAudioGMS_SoundInstance_DestroyWhenFinished(double id); +FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetTrackPosition(double soundInstanceID, double trackPositionInSeconds); +FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetVolumeOverTime(double soundInstanceID, double volume, double milliseconds); + +FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetPitch(double soundInstanceID); +FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetVolume(double soundInstanceID); +FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetTrackLengthInSeconds(double soundInstanceID); + +FAUDIOGMSAPI void FAudioGMS_SoundInstance_Destroy(double soundInstanceID); +FAUDIOGMSAPI void FAudioGMS_SoundInstance_DestroyWhenFinished(double soundInstanceID); FAUDIOGMSAPI void FAudioGMS_SetListenerPosition(double x, double y, double z); +FAUDIOGMSAPI void FAudioGMS_StopAll(); + FAUDIOGMSAPI void FAudioGMS_Update(); FAUDIOGMSAPI void FAudioGMS_Destroy();