play regions and queueing sound instances

pull/1/head
cosmonaut 2021-11-03 16:15:34 -07:00
parent 8c8d481dcf
commit 878a9b035b
4 changed files with 228 additions and 81 deletions

View File

@ -25,8 +25,7 @@
{"externalName":"FAudioGMS_StaticSound_LoadWAV","kind":1,"help":"FAudioGMS_StaticSound_LoadWAV(filePath)","hidden":false,"returnType":2,"argCount":0,"args":[ {"externalName":"FAudioGMS_StaticSound_LoadWAV","kind":1,"help":"FAudioGMS_StaticSound_LoadWAV(filePath)","hidden":false,"returnType":2,"argCount":0,"args":[
1, 1,
],"resourceVersion":"1.0","name":"FAudioGMS_StaticSound_LoadWAV","tags":[],"resourceType":"GMExtensionFunction",}, ],"resourceVersion":"1.0","name":"FAudioGMS_StaticSound_LoadWAV","tags":[],"resourceType":"GMExtensionFunction",},
{"externalName":"FAudioGMS_SoundInstance_Play","kind":1,"help":"FAudioGMS_SoundInstance_Play(id, loop)","hidden":false,"returnType":2,"argCount":0,"args":[ {"externalName":"FAudioGMS_SoundInstance_Play","kind":1,"help":"FAudioGMS_SoundInstance_Play(id)","hidden":false,"returnType":2,"argCount":0,"args":[
2,
2, 2,
],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_Play","tags":[],"resourceType":"GMExtensionFunction",}, ],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_Play","tags":[],"resourceType":"GMExtensionFunction",},
{"externalName":"FAudioGMS_SoundInstance_Pause","kind":1,"help":"FAudioGMS_SoundInstance_Pause(id)","hidden":false,"returnType":2,"argCount":0,"args":[ {"externalName":"FAudioGMS_SoundInstance_Pause","kind":1,"help":"FAudioGMS_SoundInstance_Pause(id)","hidden":false,"returnType":2,"argCount":0,"args":[
@ -157,11 +156,11 @@
],"resourceVersion":"1.0","name":"FAudioGMS_SetListenerVelocity","tags":[],"resourceType":"GMExtensionFunction",}, ],"resourceVersion":"1.0","name":"FAudioGMS_SetListenerVelocity","tags":[],"resourceType":"GMExtensionFunction",},
{"externalName":"FAudioGMS_PauseAll","kind":1,"help":"FAudioGMS_PauseAll()","hidden":false,"returnType":2,"argCount":0,"args":[],"resourceVersion":"1.0","name":"FAudioGMS_PauseAll","tags":[],"resourceType":"GMExtensionFunction",}, {"externalName":"FAudioGMS_PauseAll","kind":1,"help":"FAudioGMS_PauseAll()","hidden":false,"returnType":2,"argCount":0,"args":[],"resourceVersion":"1.0","name":"FAudioGMS_PauseAll","tags":[],"resourceType":"GMExtensionFunction",},
{"externalName":"FAudioGMS_ResumeAll","kind":1,"help":"FAudioGMS_ResumeAll()","hidden":false,"returnType":2,"argCount":0,"args":[],"resourceVersion":"1.0","name":"FAudioGMS_ResumeAll","tags":[],"resourceType":"GMExtensionFunction",}, {"externalName":"FAudioGMS_ResumeAll","kind":1,"help":"FAudioGMS_ResumeAll()","hidden":false,"returnType":2,"argCount":0,"args":[],"resourceVersion":"1.0","name":"FAudioGMS_ResumeAll","tags":[],"resourceType":"GMExtensionFunction",},
{"externalName":"FAudioGMS_SoundInstance_SetLoopPoints","kind":1,"help":"FAudioGMS_SoundInstance_SetLoopPoints(soundInstanceID, startInMilliseconds, endInMilliseconds)","hidden":false,"returnType":2,"argCount":0,"args":[ {"externalName":"FAudioGMS_SoundInstance_SetPlayRegion","kind":1,"help":"FAudioGMS_SoundInstance_SetPlayRegion(soundInstanceID, startInMilliseconds, endInMilliseconds)","hidden":false,"returnType":2,"argCount":0,"args":[
2, 2,
2, 2,
2, 2,
],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_SetLoopPoints","tags":[],"resourceType":"GMExtensionFunction",}, ],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_SetPlayRegion","tags":[],"resourceType":"GMExtensionFunction",},
{"externalName":"FAudioGMS_SetMasteringEffectChain","kind":1,"help":"FAudioGMS_SetMasteringEffectChain(effectChainID, effectGain)","hidden":false,"returnType":2,"argCount":0,"args":[ {"externalName":"FAudioGMS_SetMasteringEffectChain","kind":1,"help":"FAudioGMS_SetMasteringEffectChain(effectChainID, effectGain)","hidden":false,"returnType":2,"argCount":0,"args":[
2, 2,
2, 2,
@ -169,6 +168,14 @@
{"externalName":"FAudioGMS_SetMasteringEffectGain","kind":1,"help":"FAudioGMS_SetMasteringEffectGain(effectGain)","hidden":false,"returnType":2,"argCount":0,"args":[ {"externalName":"FAudioGMS_SetMasteringEffectGain","kind":1,"help":"FAudioGMS_SetMasteringEffectGain(effectGain)","hidden":false,"returnType":2,"argCount":0,"args":[
2, 2,
],"resourceVersion":"1.0","name":"FAudioGMS_SetMasteringEffectGain","tags":[],"resourceType":"GMExtensionFunction",}, ],"resourceVersion":"1.0","name":"FAudioGMS_SetMasteringEffectGain","tags":[],"resourceType":"GMExtensionFunction",},
{"externalName":"FAudioGMS_SoundInstance_SetLoop","kind":1,"help":"FAudioGMS_SoundInstance_SetLoop(soundInstanceID, loop)","hidden":false,"returnType":2,"argCount":0,"args":[
2,
2,
],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_SetLoop","tags":[],"resourceType":"GMExtensionFunction",},
{"externalName":"FAudioGMS_SoundInstance_QueueSoundInstance","kind":1,"help":"FAudioGMS_SoundInstance_QueueSoundInstance(soundInstanceID, queueSoundInstanceID)","hidden":false,"returnType":2,"argCount":0,"args":[
2,
2,
],"resourceVersion":"1.0","name":"FAudioGMS_SoundInstance_QueueSoundInstance","tags":[],"resourceType":"GMExtensionFunction",},
],"constants":[],"ProxyFiles":[ ],"constants":[],"ProxyFiles":[
{"TargetMask":7,"resourceVersion":"1.0","name":"libFAudioGMS.so","tags":[],"resourceType":"GMProxyFile",}, {"TargetMask":7,"resourceVersion":"1.0","name":"libFAudioGMS.so","tags":[],"resourceType":"GMProxyFile",},
{"TargetMask":3,"resourceVersion":"1.0","name":"FAudioGMSAndroidDummy.ext","tags":[],"resourceType":"GMProxyFile",}, {"TargetMask":3,"resourceVersion":"1.0","name":"FAudioGMSAndroidDummy.ext","tags":[],"resourceType":"GMProxyFile",},
@ -182,13 +189,14 @@
{"name":"FAudioGMS_SoundInstance_Play","path":"extensions/FAudioGMS/FAudioGMS.yy",}, {"name":"FAudioGMS_SoundInstance_Play","path":"extensions/FAudioGMS/FAudioGMS.yy",},
{"name":"FAudioGMS_SoundInstance_Pause","path":"extensions/FAudioGMS/FAudioGMS.yy",}, {"name":"FAudioGMS_SoundInstance_Pause","path":"extensions/FAudioGMS/FAudioGMS.yy",},
{"name":"FAudioGMS_SoundInstance_Stop","path":"extensions/FAudioGMS/FAudioGMS.yy",}, {"name":"FAudioGMS_SoundInstance_Stop","path":"extensions/FAudioGMS/FAudioGMS.yy",},
{"name":"FAudioGMS_SoundInstance_SetLoop","path":"extensions/FAudioGMS/FAudioGMS.yy",},
{"name":"FAudioGMS_SoundInstance_SetPan","path":"extensions/FAudioGMS/FAudioGMS.yy",}, {"name":"FAudioGMS_SoundInstance_SetPan","path":"extensions/FAudioGMS/FAudioGMS.yy",},
{"name":"FAudioGMS_SoundInstance_SetPitch","path":"extensions/FAudioGMS/FAudioGMS.yy",}, {"name":"FAudioGMS_SoundInstance_SetPitch","path":"extensions/FAudioGMS/FAudioGMS.yy",},
{"name":"FAudioGMS_SoundInstance_SetVolume","path":"extensions/FAudioGMS/FAudioGMS.yy",}, {"name":"FAudioGMS_SoundInstance_SetVolume","path":"extensions/FAudioGMS/FAudioGMS.yy",},
{"name":"FAudioGMS_SoundInstance_Set3DPosition","path":"extensions/FAudioGMS/FAudioGMS.yy",}, {"name":"FAudioGMS_SoundInstance_Set3DPosition","path":"extensions/FAudioGMS/FAudioGMS.yy",},
{"name":"FAudioGMS_SoundInstance_Set3DVelocity","path":"extensions/FAudioGMS/FAudioGMS.yy",}, {"name":"FAudioGMS_SoundInstance_Set3DVelocity","path":"extensions/FAudioGMS/FAudioGMS.yy",},
{"name":"FAudioGMS_SoundInstance_SetTrackPositionInSeconds","path":"extensions/FAudioGMS/FAudioGMS.yy",}, {"name":"FAudioGMS_SoundInstance_SetTrackPositionInSeconds","path":"extensions/FAudioGMS/FAudioGMS.yy",},
{"name":"FAudioGMS_SoundInstance_SetLoopPoints","path":"extensions/FAudioGMS/FAudioGMS.yy",}, {"name":"FAudioGMS_SoundInstance_SetPlayRegion","path":"extensions/FAudioGMS/FAudioGMS.yy",},
{"name":"FAudioGMS_SoundInstance_SetVolumeOverTime","path":"extensions/FAudioGMS/FAudioGMS.yy",}, {"name":"FAudioGMS_SoundInstance_SetVolumeOverTime","path":"extensions/FAudioGMS/FAudioGMS.yy",},
{"name":"FAudioGMS_SoundInstance_SetLowPassFilter","path":"extensions/FAudioGMS/FAudioGMS.yy",}, {"name":"FAudioGMS_SoundInstance_SetLowPassFilter","path":"extensions/FAudioGMS/FAudioGMS.yy",},
{"name":"FAudioGMS_SoundInstance_SetHighPassFilter","path":"extensions/FAudioGMS/FAudioGMS.yy",}, {"name":"FAudioGMS_SoundInstance_SetHighPassFilter","path":"extensions/FAudioGMS/FAudioGMS.yy",},
@ -197,6 +205,7 @@
{"name":"FAudioGMS_SoundInstance_GetVolume","path":"extensions/FAudioGMS/FAudioGMS.yy",}, {"name":"FAudioGMS_SoundInstance_GetVolume","path":"extensions/FAudioGMS/FAudioGMS.yy",},
{"name":"FAudioGMS_SoundInstance_GetTrackLengthInSeconds","path":"extensions/FAudioGMS/FAudioGMS.yy",}, {"name":"FAudioGMS_SoundInstance_GetTrackLengthInSeconds","path":"extensions/FAudioGMS/FAudioGMS.yy",},
{"name":"FAudioGMS_SoundInstance_GetTrackPositionInSeconds","path":"extensions/FAudioGMS/FAudioGMS.yy",}, {"name":"FAudioGMS_SoundInstance_GetTrackPositionInSeconds","path":"extensions/FAudioGMS/FAudioGMS.yy",},
{"name":"FAudioGMS_SoundInstance_QueueSoundInstance","path":"extensions/FAudioGMS/FAudioGMS.yy",},
{"name":"FAudioGMS_SoundInstance_Destroy","path":"extensions/FAudioGMS/FAudioGMS.yy",}, {"name":"FAudioGMS_SoundInstance_Destroy","path":"extensions/FAudioGMS/FAudioGMS.yy",},
{"name":"FAudioGMS_SoundInstance_DestroyWhenFinished","path":"extensions/FAudioGMS/FAudioGMS.yy",}, {"name":"FAudioGMS_SoundInstance_DestroyWhenFinished","path":"extensions/FAudioGMS/FAudioGMS.yy",},
{"name":"FAudioGMS_EffectChain_Create","path":"extensions/FAudioGMS/FAudioGMS.yy",}, {"name":"FAudioGMS_EffectChain_Create","path":"extensions/FAudioGMS/FAudioGMS.yy",},

View File

@ -19,17 +19,29 @@ function StaticSound(_staticSoundID) constructor
{ {
staticSoundID = _staticSoundID; staticSoundID = _staticSoundID;
// Returns a sound instance! // Create a sound instance from this static sound.
static CreateSoundInstance = function()
{
var instanceID = FAudioGMS_StaticSound_CreateSoundInstance(staticSoundID);
var instance = new SoundInstance(instanceID);
return instance;
}
// Plays and returns a sound instance!
// MUST be destroyed when you aren't referencing it any more or you will leak memory! // MUST be destroyed when you aren't referencing it any more or you will leak memory!
static Play = function(pan = 0, pitch = 1, volume = 1, loop = false, loopStartInMilliseconds = 0, loopEndInMilliseconds = 0) static Play = function(pan = 0, pitch = 1, volume = 1, loop = false, loopStartInMilliseconds = 0, loopEndInMilliseconds = 0)
{ {
var instanceID = FAudioGMS_StaticSound_CreateSoundInstance(staticSoundID); var instanceID = FAudioGMS_StaticSound_CreateSoundInstance(staticSoundID);
var instance = new SoundInstance(instanceID); var instance = new SoundInstance(instanceID);
instance.SetLoopPoints(loopStartInMilliseconds, loopEndInMilliseconds); instance.SetLoop(loop);
if (loop)
{
instance.SetPlayRegion(loopStartInMilliseconds, loopEndInMilliseconds);
}
instance.SetPan(pan); instance.SetPan(pan);
instance.SetPitch(pitch); instance.SetPitch(pitch);
instance.SetVolume(volume); instance.SetVolume(volume);
instance.Play(loop); instance.Play();
return instance; return instance;
} }
@ -41,12 +53,13 @@ function StaticSound(_staticSoundID) constructor
instance.DestroyWhenFinished(); instance.DestroyWhenFinished();
} }
// Returns a sound instance! // Plays and returns a sound instance!
// MUST be destroyed when you aren't referencing it any more or you will leak memory! // MUST be destroyed when you aren't referencing it any more or you will leak memory!
static PlaySpatial = function(xPosition, yPosition, zPosition, pitch = 1, volume = 1, loop = false) static PlaySpatial = function(xPosition, yPosition, zPosition, pitch = 1, volume = 1, loop = false)
{ {
var instanceID = FAudioGMS_StaticSound_CreateSoundInstance(staticSoundID); var instanceID = FAudioGMS_StaticSound_CreateSoundInstance(staticSoundID);
var instance = new SoundInstance(instanceID); var instance = new SoundInstance(instanceID);
instance.SetLoop(loop);
instance.Set3DPosition(xPosition, yPosition, zPosition); instance.Set3DPosition(xPosition, yPosition, zPosition);
instance.SetPitch(pitch); instance.SetPitch(pitch);
instance.SetVolume(volume); instance.SetVolume(volume);
@ -89,7 +102,7 @@ function SoundInstance(_soundInstanceID) constructor
// Plays the sound or resumes from pause. // Plays the sound or resumes from pause.
static Play = function(loop = false) static Play = function(loop = false)
{ {
FAudioGMS_SoundInstance_Play(soundInstanceID, loop); FAudioGMS_SoundInstance_Play(soundInstanceID);
} }
// Pauses playback. // Pauses playback.
@ -116,6 +129,12 @@ function SoundInstance(_soundInstanceID) constructor
FAudioGMS_SoundInstance_Set3DVelocity(soundInstanceID, xVelocity, yVelocity, zVelocity); FAudioGMS_SoundInstance_Set3DVelocity(soundInstanceID, xVelocity, yVelocity, zVelocity);
} }
// Sets whether the sound instance loops (true) or does not (false).
static SetLoop = function(loop)
{
FAudioGMS_SoundInstance_SetLoop(soundInstanceID, loop);
}
// Sets the panning value of the sound. -1 is farthest left, 1 is farthest right, 0 is center. // Sets the panning value of the sound. -1 is farthest left, 1 is farthest right, 0 is center.
// NOTE: This is ignored if you have called Set3DPosition. // NOTE: This is ignored if you have called Set3DPosition.
static SetPan = function(pan) static SetPan = function(pan)
@ -146,14 +165,13 @@ function SoundInstance(_soundInstanceID) constructor
// Sets the position of track playback. // Sets the position of track playback.
static SetTrackPosition = function(seconds) static SetTrackPosition = function(seconds)
{ {
FAudioGMS_SoundInstance_SetTrackPosition(soundInstanceID, seconds); FAudioGMS_SoundInstance_SetTrackPositionInSeconds(soundInstanceID, seconds);
} }
// Sets loop points for the sound instance. // Sets the playback region for the sound instance.
// MUST Be called before Play. static SetPlayRegion = function(loopStartInMilliseconds, loopEndInMilliseconds)
static SetLoopPoints = function(loopStartInMilliseconds, loopEndInMilliseconds)
{ {
FAudioGMS_SoundInstance_SetLoopPoints(soundInstanceID, loopStartInMilliseconds, loopEndInMilliseconds); FAudioGMS_SoundInstance_SetPlayRegion(soundInstanceID, loopStartInMilliseconds, loopEndInMilliseconds);
} }
// Sets a low pass filter on the sound. // Sets a low pass filter on the sound.
@ -196,6 +214,11 @@ function SoundInstance(_soundInstanceID) constructor
FAudioGMS_SoundInstance_SetEffectGain(soundInstanceID, gain); FAudioGMS_SoundInstance_SetEffectGain(soundInstanceID, gain);
} }
static QueueSoundInstance = function(queueSoundInstance)
{
FAudioGMS_SoundInstance_QueueSoundInstance(soundInstanceID, queueSoundInstance.soundInstanceID);
}
// Gets the pitch of the sound. // Gets the pitch of the sound.
static GetPitch = function() static GetPitch = function()
{ {

View File

@ -176,9 +176,12 @@ typedef struct FAudioGMS_StreamingSound
float* streamBuffer; float* streamBuffer;
uint32_t streamBufferSize; uint32_t streamBufferSize;
uint32_t mostRecentBufferOffset; /* used for calculating track position */ uint32_t mostRecentBufferOffset; /* used for calculating track position */
uint8_t isFinalBuffer; /* used to detect end of playback */
} FAudioGMS_StreamingSound; } FAudioGMS_StreamingSound;
typedef struct FAudioGMS_SoundInstance typedef struct FAudioGMS_SoundInstance FAudioGMS_SoundInstance;
struct FAudioGMS_SoundInstance
{ {
uint32_t id; uint32_t id;
FAudioGMS_Voice voice; FAudioGMS_Voice voice;
@ -207,15 +210,17 @@ typedef struct FAudioGMS_SoundInstance
uint8_t isGlobalPaused; uint8_t isGlobalPaused;
uint32_t loopStart; uint32_t playBegin;
uint32_t loopLength; uint32_t playLength;
FAudioGMS_SoundInstance *queuedSoundInstance;
union union
{ {
FAudioGMS_StaticSound *staticSound; /* static sounds are loaded separately, so they do not belong to the instance */ FAudioGMS_StaticSound *staticSound; /* static sounds are loaded separately, so they do not belong to the instance */
FAudioGMS_StreamingSound streamingSound; FAudioGMS_StreamingSound streamingSound;
} soundData; } soundData;
} FAudioGMS_SoundInstance; };
typedef enum FAudioGMS_EffectType typedef enum FAudioGMS_EffectType
{ {
@ -312,15 +317,38 @@ static inline FAudioGMS_EffectChain* FAudioGMS_INTERNAL_LookupEffectChain(uint32
} }
} }
/* Forward declare this to avoid annoying BS */ /* Forward declarations to avoid some annoying BS */
static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance* instance);
static void FAudioGMS_INTERNAL_StreamingBufferEndCallback(FAudioVoiceCallback* callback, FAudioGMS_SoundInstance *instance) static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance* instance);
static void FAudioGMS_INTERNAL_SoundInstance_Play(FAudioGMS_SoundInstance* instance);
static void FAudioGMS_INTERNAL_SoundInstance_Stop(FAudioGMS_SoundInstance* instance);
static void FAudioGMS_INTERNAL_OnBufferEndCallback(FAudioVoiceCallback* callback, FAudioGMS_SoundInstance *instance)
{ {
if (instance->soundState == SoundState_Playing) if (instance->isStatic)
{ {
FAudioGMS_INTERNAL_SoundInstance_AddBuffer(instance); FAudioGMS_INTERNAL_SoundInstance_Stop(instance);
} }
else
{
if (instance->soundData.streamingSound.isFinalBuffer)
{
FAudioGMS_INTERNAL_SoundInstance_Stop(instance);
}
else
{
FAudioGMS_INTERNAL_SoundInstance_AddBuffer(instance);
}
}
if (instance->soundState == SoundState_Stopped)
{
if (instance->queuedSoundInstance != NULL)
{
FAudioGMS_INTERNAL_SoundInstance_Play(instance->queuedSoundInstance);
instance->queuedSoundInstance = NULL;
}
}
} }
void FAudioGMS_Init(double spatialDistanceScale, double timestep) void FAudioGMS_Init(double spatialDistanceScale, double timestep)
@ -448,7 +476,7 @@ void FAudioGMS_Init(double spatialDistanceScale, double timestep)
device->listener.Velocity.z = 0; device->listener.Velocity.z = 0;
device->listener.pCone = NULL; device->listener.pCone = NULL;
device->voiceCallbacks.OnBufferEnd = FAudioGMS_INTERNAL_StreamingBufferEndCallback; device->voiceCallbacks.OnBufferEnd = FAudioGMS_INTERNAL_OnBufferEndCallback;
device->voiceCallbacks.OnBufferStart = NULL; device->voiceCallbacks.OnBufferStart = NULL;
device->voiceCallbacks.OnLoopEnd = NULL; device->voiceCallbacks.OnLoopEnd = NULL;
device->voiceCallbacks.OnStreamEnd = NULL; device->voiceCallbacks.OnStreamEnd = NULL;
@ -546,14 +574,14 @@ double FAudioGMS_StaticSound_LoadWAV(char *filePath)
} }
sound->buffer.AudioBytes = (uint32_t)(frameCount * sound->channels * sizeof(float)); sound->buffer.AudioBytes = (uint32_t)(frameCount * sound->channels * sizeof(float));
sound->buffer.Flags = FAUDIO_END_OF_STREAM; sound->buffer.Flags = 0;
sound->buffer.LoopBegin = 0; sound->buffer.LoopBegin = 0;
sound->buffer.LoopCount = 0; sound->buffer.LoopCount = 0;
sound->buffer.LoopLength = 0; sound->buffer.LoopLength = 0;
sound->buffer.PlayBegin = 0;
sound->buffer.PlayLength = frameCount;
sound->buffer.pAudioData = (uint8_t*) pSampleData; sound->buffer.pAudioData = (uint8_t*) pSampleData;
sound->buffer.pContext = NULL; sound->buffer.pContext = NULL;
sound->buffer.PlayBegin = 0;
sound->buffer.PlayLength = frameCount;
sound->lengthInSeconds = frameCount / sound->samplesPerSecond; sound->lengthInSeconds = frameCount / sound->samplesPerSecond;
@ -697,8 +725,10 @@ static FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_SoundInstance_Init(
instance->stereoAzimuth[0] = 0.0f; instance->stereoAzimuth[0] = 0.0f;
instance->stereoAzimuth[1] = 0.0f; instance->stereoAzimuth[1] = 0.0f;
instance->loopStart = 0; instance->playBegin = 0;
instance->loopLength = 0; instance->playLength = 0;
instance->queuedSoundInstance = NULL;
if (device->soundInstanceIndexStack.count > 0) if (device->soundInstanceIndexStack.count > 0)
{ {
@ -815,6 +845,28 @@ void FAudioGMS_SoundInstance_SetBandPassFilter(double soundInstanceID, double ba
} }
} }
void FAudioGMS_SoundInstance_QueueSoundInstance(double soundInstanceID, double queueSoundInstanceID)
{
FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID);
FAudioGMS_SoundInstance* queueInstance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)queueSoundInstanceID);
if (instance != NULL && queueInstance != NULL)
{
instance->queuedSoundInstance = queueInstance;
}
else
{
if (instance == NULL)
{
Log("QueueSoundInstace: Invalid instance ID!");
}
else
{
Log("QueueSoundInstance: Invalid queue sound instance ID!");
}
}
}
static void FAudioGMS_INTERNAL_Apply3D(FAudioGMS_SoundInstance* instance) static void FAudioGMS_INTERNAL_Apply3D(FAudioGMS_SoundInstance* instance)
{ {
F3DAUDIO_EMITTER* emitter = instance->emitter; F3DAUDIO_EMITTER* emitter = instance->emitter;
@ -849,10 +901,10 @@ static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance*
uint32_t defaultRequestedSampleCount = instance->format.nSamplesPerSec / 4; uint32_t defaultRequestedSampleCount = instance->format.nSamplesPerSec / 4;
uint32_t requestedSampleCount = defaultRequestedSampleCount; uint32_t requestedSampleCount = defaultRequestedSampleCount;
if (instance->loop && instance->loopLength != 0) if (instance->playLength != 0)
{ {
uint32_t distanceToLoopPoint = (instance->loopStart + instance->loopLength) - stb_vorbis_get_sample_offset(instance->soundData.streamingSound.fileHandle); uint32_t distanceToEndPoint = (instance->playBegin + instance->playLength) - stb_vorbis_get_sample_offset(instance->soundData.streamingSound.fileHandle);
requestedSampleCount = SDL_min(requestedSampleCount, distanceToLoopPoint); requestedSampleCount = SDL_min(requestedSampleCount, distanceToEndPoint);
} }
uint32_t requiredStagingBufferSize = requestedSampleCount * instance->format.nChannels * sizeof(float); uint32_t requiredStagingBufferSize = requestedSampleCount * instance->format.nChannels * sizeof(float);
@ -879,10 +931,6 @@ static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance*
buffer.PlayLength = sampleCount; buffer.PlayLength = sampleCount;
buffer.Flags = 0; buffer.Flags = 0;
/*(sampleCount < instance->soundData.streamingSound.info.sample_rate) ?
FAUDIO_END_OF_STREAM :
0;
*/
buffer.LoopBegin = 0; buffer.LoopBegin = 0;
buffer.LoopCount = 0; buffer.LoopCount = 0;
buffer.LoopLength = 0; buffer.LoopLength = 0;
@ -890,19 +938,19 @@ static void FAudioGMS_INTERNAL_SoundInstance_AddBuffer(FAudioGMS_SoundInstance*
FAudioSourceVoice_SubmitSourceBuffer(instance->voice.handle, &buffer, NULL); FAudioSourceVoice_SubmitSourceBuffer(instance->voice.handle, &buffer, NULL);
/* We have reached the end of the loop region or file! */ instance->soundData.streamingSound.isFinalBuffer = 0;
/* FIXME: maybe move this to a OnStreamEnd callback? */
if (sampleCount < defaultRequestedSampleCount) if (sampleCount < defaultRequestedSampleCount)
{ {
if (instance->loop) if (instance->loop)
{ {
stb_vorbis_seek_frame(instance->soundData.streamingSound.fileHandle, instance->loopStart); stb_vorbis_seek_frame(instance->soundData.streamingSound.fileHandle, instance->playBegin);
} }
else else
{ {
instance->soundState = SoundState_Stopped; instance->soundData.streamingSound.isFinalBuffer = 1;
} }
} }
} }
double FAudioGMS_StreamingSound_LoadOGG(char* filePath) double FAudioGMS_StreamingSound_LoadOGG(char* filePath)
@ -931,6 +979,7 @@ double FAudioGMS_StreamingSound_LoadOGG(char* filePath)
instance->soundData.streamingSound.streamBuffer = NULL; instance->soundData.streamingSound.streamBuffer = NULL;
instance->soundData.streamingSound.streamBufferSize = 0; instance->soundData.streamingSound.streamBufferSize = 0;
instance->soundData.streamingSound.mostRecentBufferOffset = 0; instance->soundData.streamingSound.mostRecentBufferOffset = 0;
instance->soundData.streamingSound.isFinalBuffer = 0;
FAudioGMS_INTERNAL_SoundInstance_AddBuffer(instance); FAudioGMS_INTERNAL_SoundInstance_AddBuffer(instance);
@ -987,11 +1036,13 @@ static void FAudioGMS_INTERNAL_SoundInstance_Play(FAudioGMS_SoundInstance* insta
if (instance->isStatic) if (instance->isStatic)
{ {
instance->soundData.staticSound->buffer.pContext = instance;
if (instance->loop) if (instance->loop)
{ {
instance->soundData.staticSound->buffer.LoopCount = FAUDIO_LOOP_INFINITE; instance->soundData.staticSound->buffer.LoopCount = FAUDIO_LOOP_INFINITE;
instance->soundData.staticSound->buffer.LoopBegin = instance->loopStart; instance->soundData.staticSound->buffer.LoopBegin = instance->playBegin;
instance->soundData.staticSound->buffer.LoopLength = instance->loopLength; instance->soundData.staticSound->buffer.LoopLength = instance->playLength;
} }
else else
{ {
@ -1000,6 +1051,19 @@ static void FAudioGMS_INTERNAL_SoundInstance_Play(FAudioGMS_SoundInstance* insta
instance->soundData.staticSound->buffer.LoopLength = 0; instance->soundData.staticSound->buffer.LoopLength = 0;
} }
if (instance->soundState == SoundState_Paused)
{
FAudioSourceVoice_FlushSourceBuffers(instance->voice.handle);
instance->soundData.staticSound->buffer.PlayBegin = instance->voice.handle->src.curBufferOffset;
instance->soundData.staticSound->buffer.PlayLength = instance->playLength;
}
else
{
instance->soundData.staticSound->buffer.PlayBegin = instance->playBegin;
instance->soundData.staticSound->buffer.PlayLength = instance->playLength;
}
FAudioSourceVoice_SubmitSourceBuffer(instance->voice.handle, &instance->soundData.staticSound->buffer, NULL); FAudioSourceVoice_SubmitSourceBuffer(instance->voice.handle, &instance->soundData.staticSound->buffer, NULL);
} }
@ -1007,14 +1071,13 @@ static void FAudioGMS_INTERNAL_SoundInstance_Play(FAudioGMS_SoundInstance* insta
instance->soundState = SoundState_Playing; instance->soundState = SoundState_Playing;
} }
void FAudioGMS_SoundInstance_Play(double soundInstanceID, double loop) void FAudioGMS_SoundInstance_Play(double soundInstanceID)
{ {
RETURN_ON_NULL_DEVICE() RETURN_ON_NULL_DEVICE()
FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID);
if (instance != NULL) if (instance != NULL)
{ {
instance->loop = (uint8_t) loop;
FAudioGMS_INTERNAL_SoundInstance_Play(instance); FAudioGMS_INTERNAL_SoundInstance_Play(instance);
} }
} }
@ -1053,7 +1116,7 @@ static void FAudioGMS_INTERNAL_SoundInstance_Stop(FAudioGMS_SoundInstance* insta
if (!instance->isStatic) if (!instance->isStatic)
{ {
stb_vorbis_seek_start(instance->soundData.streamingSound.fileHandle); /* back to the start */ stb_vorbis_seek_frame(instance->soundData.streamingSound.fileHandle, instance->playBegin); /* back to the start */
FAudioGMS_INTERNAL_SoundInstance_AddBuffer(instance); /* preload so we dont stutter on play */ FAudioGMS_INTERNAL_SoundInstance_AddBuffer(instance); /* preload so we dont stutter on play */
} }
} }
@ -1070,6 +1133,24 @@ void FAudioGMS_SoundInstance_Stop(double soundInstanceID)
FAudioGMS_INTERNAL_SoundInstance_Stop(instance); FAudioGMS_INTERNAL_SoundInstance_Stop(instance);
} }
void FAudioGMS_SoundInstance_SetLoop(double soundInstanceID, double loop)
{
RETURN_ON_NULL_DEVICE()
FAudioGMS_SoundInstance *instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID);
if (instance != NULL)
{
instance->loop = (uint8_t)loop;
if (instance->isStatic && instance->soundState == SoundState_Playing)
{
/* We need to pause and play so that static buffers get resubmitted */
FAudioGMS_INTERNAL_SoundInstance_Pause(instance);
FAudioGMS_INTERNAL_SoundInstance_Play(instance);
}
}
}
void FAudioGMS_SoundInstance_SetPan(double soundInstanceID, double pan) void FAudioGMS_SoundInstance_SetPan(double soundInstanceID, double pan)
{ {
RETURN_ON_NULL_DEVICE() RETURN_ON_NULL_DEVICE()
@ -1179,31 +1260,71 @@ void FAudioGMS_SoundInstance_SetTrackPositionInSeconds(double soundInstanceID, d
} }
} }
void FAudioGMS_SoundInstance_SetLoopPoints(double soundInstanceID, double startInMilliseconds, double endInMilliseconds) static uint32_t FAudioGMS_INTERNAL_SoundInstance_GetTrackPositionInSampleFrames(FAudioGMS_SoundInstance* instance)
{
if (instance != NULL)
{
if (instance->isStatic)
{
return instance->voice.handle->src.curBufferOffset / sizeof(float);
}
else
{
return instance->soundData.streamingSound.mostRecentBufferOffset + instance->voice.handle->src.curBufferOffset;
}
}
Log("Invalid sound instance!");
return 0;
}
void FAudioGMS_SoundInstance_SetPlayRegion(double soundInstanceID, double startInMilliseconds, double endInMilliseconds)
{ {
RETURN_ON_NULL_DEVICE() RETURN_ON_NULL_DEVICE()
FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID); FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_LookupSoundInstance((uint32_t)soundInstanceID);
if (instance != NULL) if (instance != NULL)
{ {
uint32_t loopBeginSampleFrame = instance->format.nSamplesPerSec * (startInMilliseconds / 1000); uint32_t playBeginSampleFrame = instance->format.nSamplesPerSec * (startInMilliseconds / 1000);
uint32_t loopEndSampleFrame = instance->format.nSamplesPerSec * (endInMilliseconds / 1000); uint32_t playEndSampleFrame = instance->format.nSamplesPerSec * (endInMilliseconds / 1000);
uint32_t loopLength = loopEndSampleFrame - loopBeginSampleFrame; uint32_t playLength = playEndSampleFrame - playBeginSampleFrame;
if (loopLength <= 0) if (playLength <= 0)
{ {
Log("Loop end is less than or equal to loop start! Bailing!"); Log("Play end is less than or equal to play start! Bailing!");
return; return;
} }
instance->loopStart = loopBeginSampleFrame; instance->playBegin = playBeginSampleFrame;
instance->loopLength = loopLength; instance->playLength = playLength;
if (!instance->isStatic) uint32_t currentFrame = FAudioGMS_INTERNAL_SoundInstance_GetTrackPositionInSampleFrames(instance);
if (
currentFrame < instance->playBegin ||
(currentFrame > instance->playBegin + instance->playLength)
) {
/* we are outside the play region */
if (instance->isStatic && instance->soundState == SoundState_Playing)
{
FAudioGMS_INTERNAL_SoundInstance_Stop(instance);
FAudioGMS_INTERNAL_SoundInstance_Play(instance);
}
else if (!instance->isStatic)
{
FAudioSourceVoice_FlushSourceBuffers(instance->voice.handle);
stb_vorbis_seek_frame(instance->soundData.streamingSound.fileHandle, instance->playBegin);
FAudioGMS_INTERNAL_SoundInstance_AddBuffer(instance);
}
}
else
{ {
FAudioSourceVoice_FlushSourceBuffers(instance->voice.handle); /* we are inside the play region */
stb_vorbis_seek_frame(instance->soundData.streamingSound.fileHandle, instance->loopStart); if (instance->isStatic && instance->soundState != SoundState_Stopped)
FAudioGMS_INTERNAL_SoundInstance_AddBuffer(instance); {
FAudioGMS_INTERNAL_SoundInstance_Pause(instance);
FAudioGMS_INTERNAL_SoundInstance_Play(instance);
}
} }
} }
} }
@ -1283,15 +1404,7 @@ double FAudioGMS_SoundInstance_GetTrackPositionInSeconds(double soundInstanceID)
if (instance != NULL) if (instance != NULL)
{ {
if (instance->isStatic) return FAudioGMS_INTERNAL_SoundInstance_GetTrackPositionInSampleFrames(instance) / instance->format.nSamplesPerSec;
{
uint32_t sampleFrame = instance->voice.handle->src.curBufferOffset / sizeof(float);
return sampleFrame / instance->format.nSamplesPerSec;
}
else
{
return ((double)instance->soundData.streamingSound.mostRecentBufferOffset + instance->voice.handle->src.curBufferOffset) / instance->format.nSamplesPerSec;
}
} }
else else
{ {

View File

@ -47,23 +47,25 @@ FAUDIOGMSAPI void FAudioGMS_StaticSound_Destroy(double staticSoundID);
FAUDIOGMSAPI double FAudioGMS_StreamingSound_LoadOGG(char* filepath); /* returns a sound instance ID */ FAUDIOGMSAPI double FAudioGMS_StreamingSound_LoadOGG(char* filepath); /* returns a sound instance ID */
FAUDIOGMSAPI void FAudioGMS_SoundInstance_Play(double soundInstanceID, double loop); FAUDIOGMSAPI void FAudioGMS_SoundInstance_Play(double soundInstanceID);
FAUDIOGMSAPI void FAudioGMS_SoundInstance_Pause(double soundInstanceID); FAUDIOGMSAPI void FAudioGMS_SoundInstance_Pause(double soundInstanceID);
FAUDIOGMSAPI void FAudioGMS_SoundInstance_Stop(double soundInstanceID); FAUDIOGMSAPI void FAudioGMS_SoundInstance_Stop(double soundInstanceID);
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetPlayRegion(double soundInstanceID, double startInMilliseconds, double endInMilliseconds);
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetLoop(double soundInstanceID, double loop);
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetPan(double soundInstanceID, double pan); FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetPan(double soundInstanceID, double pan);
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetPitch(double soundInstanceID, double pitch); FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetPitch(double soundInstanceID, double pitch);
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetVolume(double soundInstanceID, double volume); FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetVolume(double soundInstanceID, double volume);
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_Set3DVelocity(double soundInstanceID, double xVelocity, double yVelocity, double zVelocity); FAUDIOGMSAPI void FAudioGMS_SoundInstance_Set3DVelocity(double soundInstanceID, double xVelocity, double yVelocity, double zVelocity);
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetTrackPositionInSeconds(double soundInstanceID, double trackPositionInSeconds); FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetTrackPositionInSeconds(double soundInstanceID, double trackPositionInSeconds);
/* remember to set loop points BEFORE calling Play */
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetLoopPoints(double soundInstanceID, double startInMilliseconds, double endInMilliseconds);
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, double lowPassFilter, double Q); FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetLowPassFilter(double soundInstanceID, double lowPassFilter, double Q);
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetHighPassFilter(double soundInstanceID, double highPassFilter, double Q); FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetHighPassFilter(double soundInstanceID, double highPassFilter, double Q);
FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetBandPassFilter(double soundInstanceID, double bandPassFilter, double Q); FAUDIOGMSAPI void FAudioGMS_SoundInstance_SetBandPassFilter(double soundInstanceID, double bandPassFilter, double Q);
FAUDIOGMSAPI void FAudioGMS_SoundInstance_QueueSoundInstance(double soundInstanceID, double queueSoundInstanceID);
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);
FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetTrackLengthInSeconds(double soundInstanceID); FAUDIOGMSAPI double FAudioGMS_SoundInstance_GetTrackLengthInSeconds(double soundInstanceID);