778 lines
17 KiB
C
778 lines
17 KiB
C
/* FAudio - XAudio Reimplementation for FNA
|
|
*
|
|
* Copyright (c) 2011-2021 Ethan Lee, Luigi Auriemma, and the MonoGame Team
|
|
*
|
|
* This software is provided 'as-is', without any express or implied warranty.
|
|
* In no event will the authors be held liable for any damages arising from
|
|
* the use of this software.
|
|
*
|
|
* Permission is granted to anyone to use this software for any purpose,
|
|
* including commercial applications, and to alter it and redistribute it
|
|
* freely, subject to the following restrictions:
|
|
*
|
|
* 1. The origin of this software must not be misrepresented; you must not
|
|
* claim that you wrote the original software. If you use this software in a
|
|
* product, an acknowledgment in the product documentation would be
|
|
* appreciated but is not required.
|
|
*
|
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
|
* misrepresented as being the original software.
|
|
*
|
|
* 3. This notice may not be removed or altered from any source distribution.
|
|
*
|
|
* Ethan "flibitijibibo" Lee <flibitijibibo@flibitijibibo.com>
|
|
*
|
|
*/
|
|
|
|
/* FAudio_operationset.c originally written by Tyler Glaiel */
|
|
|
|
#include "FAudio_internal.h"
|
|
|
|
/* Core OperationSet Types */
|
|
|
|
typedef enum FAudio_OPERATIONSET_Type
|
|
{
|
|
FAUDIOOP_ENABLEEFFECT,
|
|
FAUDIOOP_DISABLEEFFECT,
|
|
FAUDIOOP_SETEFFECTPARAMETERS,
|
|
FAUDIOOP_SETFILTERPARAMETERS,
|
|
FAUDIOOP_SETOUTPUTFILTERPARAMETERS,
|
|
FAUDIOOP_SETVOLUME,
|
|
FAUDIOOP_SETCHANNELVOLUMES,
|
|
FAUDIOOP_SETOUTPUTMATRIX,
|
|
FAUDIOOP_START,
|
|
FAUDIOOP_STOP,
|
|
FAUDIOOP_EXITLOOP,
|
|
FAUDIOOP_SETFREQUENCYRATIO
|
|
} FAudio_OPERATIONSET_Type;
|
|
|
|
struct FAudio_OPERATIONSET_Operation
|
|
{
|
|
FAudio_OPERATIONSET_Type Type;
|
|
uint32_t OperationSet;
|
|
FAudioVoice *Voice;
|
|
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
uint32_t EffectIndex;
|
|
} EnableEffect;
|
|
struct
|
|
{
|
|
uint32_t EffectIndex;
|
|
} DisableEffect;
|
|
struct
|
|
{
|
|
uint32_t EffectIndex;
|
|
void *pParameters;
|
|
uint32_t ParametersByteSize;
|
|
} SetEffectParameters;
|
|
struct
|
|
{
|
|
FAudioFilterParameters Parameters;
|
|
} SetFilterParameters;
|
|
struct
|
|
{
|
|
FAudioVoice *pDestinationVoice;
|
|
FAudioFilterParameters Parameters;
|
|
} SetOutputFilterParameters;
|
|
struct
|
|
{
|
|
float Volume;
|
|
} SetVolume;
|
|
struct
|
|
{
|
|
uint32_t Channels;
|
|
float *pVolumes;
|
|
} SetChannelVolumes;
|
|
struct
|
|
{
|
|
FAudioVoice *pDestinationVoice;
|
|
uint32_t SourceChannels;
|
|
uint32_t DestinationChannels;
|
|
float *pLevelMatrix;
|
|
} SetOutputMatrix;
|
|
struct
|
|
{
|
|
uint32_t Flags;
|
|
} Start;
|
|
struct
|
|
{
|
|
uint32_t Flags;
|
|
} Stop;
|
|
/* No special data for ExitLoop
|
|
struct
|
|
{
|
|
} ExitLoop;
|
|
*/
|
|
struct
|
|
{
|
|
float Ratio;
|
|
} SetFrequencyRatio;
|
|
} Data;
|
|
|
|
FAudio_OPERATIONSET_Operation *next;
|
|
};
|
|
|
|
/* Used by both Commit and Clear routines */
|
|
|
|
static inline void DeleteOperation(
|
|
FAudio_OPERATIONSET_Operation *op,
|
|
FAudioFreeFunc pFree
|
|
) {
|
|
if (op->Type == FAUDIOOP_SETEFFECTPARAMETERS)
|
|
{
|
|
pFree(op->Data.SetEffectParameters.pParameters);
|
|
}
|
|
else if (op->Type == FAUDIOOP_SETCHANNELVOLUMES)
|
|
{
|
|
pFree(op->Data.SetChannelVolumes.pVolumes);
|
|
}
|
|
else if (op->Type == FAUDIOOP_SETOUTPUTMATRIX)
|
|
{
|
|
pFree(op->Data.SetOutputMatrix.pLevelMatrix);
|
|
}
|
|
pFree(op);
|
|
}
|
|
|
|
/* OperationSet Execution */
|
|
|
|
static inline void ExecuteOperation(FAudio_OPERATIONSET_Operation *op)
|
|
{
|
|
switch (op->Type)
|
|
{
|
|
case FAUDIOOP_ENABLEEFFECT:
|
|
FAudioVoice_EnableEffect(
|
|
op->Voice,
|
|
op->Data.EnableEffect.EffectIndex,
|
|
FAUDIO_COMMIT_NOW
|
|
);
|
|
break;
|
|
|
|
case FAUDIOOP_DISABLEEFFECT:
|
|
FAudioVoice_DisableEffect(
|
|
op->Voice,
|
|
op->Data.DisableEffect.EffectIndex,
|
|
FAUDIO_COMMIT_NOW
|
|
);
|
|
break;
|
|
|
|
case FAUDIOOP_SETEFFECTPARAMETERS:
|
|
FAudioVoice_SetEffectParameters(
|
|
op->Voice,
|
|
op->Data.SetEffectParameters.EffectIndex,
|
|
op->Data.SetEffectParameters.pParameters,
|
|
op->Data.SetEffectParameters.ParametersByteSize,
|
|
FAUDIO_COMMIT_NOW
|
|
);
|
|
break;
|
|
|
|
case FAUDIOOP_SETFILTERPARAMETERS:
|
|
FAudioVoice_SetFilterParameters(
|
|
op->Voice,
|
|
&op->Data.SetFilterParameters.Parameters,
|
|
FAUDIO_COMMIT_NOW
|
|
);
|
|
break;
|
|
|
|
case FAUDIOOP_SETOUTPUTFILTERPARAMETERS:
|
|
FAudioVoice_SetOutputFilterParameters(
|
|
op->Voice,
|
|
op->Data.SetOutputFilterParameters.pDestinationVoice,
|
|
&op->Data.SetOutputFilterParameters.Parameters,
|
|
FAUDIO_COMMIT_NOW
|
|
);
|
|
break;
|
|
|
|
case FAUDIOOP_SETVOLUME:
|
|
FAudioVoice_SetVolume(
|
|
op->Voice,
|
|
op->Data.SetVolume.Volume,
|
|
FAUDIO_COMMIT_NOW
|
|
);
|
|
break;
|
|
|
|
case FAUDIOOP_SETCHANNELVOLUMES:
|
|
FAudioVoice_SetChannelVolumes(
|
|
op->Voice,
|
|
op->Data.SetChannelVolumes.Channels,
|
|
op->Data.SetChannelVolumes.pVolumes,
|
|
FAUDIO_COMMIT_NOW
|
|
);
|
|
break;
|
|
|
|
case FAUDIOOP_SETOUTPUTMATRIX:
|
|
FAudioVoice_SetOutputMatrix(
|
|
op->Voice,
|
|
op->Data.SetOutputMatrix.pDestinationVoice,
|
|
op->Data.SetOutputMatrix.SourceChannels,
|
|
op->Data.SetOutputMatrix.DestinationChannels,
|
|
op->Data.SetOutputMatrix.pLevelMatrix,
|
|
FAUDIO_COMMIT_NOW
|
|
);
|
|
break;
|
|
|
|
case FAUDIOOP_START:
|
|
FAudioSourceVoice_Start(
|
|
op->Voice,
|
|
op->Data.Start.Flags,
|
|
FAUDIO_COMMIT_NOW
|
|
);
|
|
break;
|
|
|
|
case FAUDIOOP_STOP:
|
|
FAudioSourceVoice_Stop(
|
|
op->Voice,
|
|
op->Data.Stop.Flags,
|
|
FAUDIO_COMMIT_NOW
|
|
);
|
|
break;
|
|
|
|
case FAUDIOOP_EXITLOOP:
|
|
FAudioSourceVoice_ExitLoop(
|
|
op->Voice,
|
|
FAUDIO_COMMIT_NOW
|
|
);
|
|
break;
|
|
|
|
case FAUDIOOP_SETFREQUENCYRATIO:
|
|
FAudioSourceVoice_SetFrequencyRatio(
|
|
op->Voice,
|
|
op->Data.SetFrequencyRatio.Ratio,
|
|
FAUDIO_COMMIT_NOW
|
|
);
|
|
break;
|
|
|
|
default:
|
|
FAudio_assert(0 && "Unrecognized operation type!");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void FAudio_OPERATIONSET_CommitAll(FAudio *audio)
|
|
{
|
|
FAudio_OPERATIONSET_Operation *op, *next, **committed_end;
|
|
|
|
FAudio_PlatformLockMutex(audio->operationLock);
|
|
LOG_MUTEX_LOCK(audio, audio->operationLock)
|
|
|
|
if (audio->queuedOperations == NULL)
|
|
{
|
|
FAudio_PlatformUnlockMutex(audio->operationLock);
|
|
LOG_MUTEX_UNLOCK(audio, audio->operationLock)
|
|
return;
|
|
}
|
|
|
|
committed_end = &audio->committedOperations;
|
|
while (*committed_end)
|
|
{
|
|
committed_end = &((*committed_end)->next);
|
|
}
|
|
|
|
op = audio->queuedOperations;
|
|
do
|
|
{
|
|
next = op->next;
|
|
|
|
*committed_end = op;
|
|
op->next = NULL;
|
|
committed_end = &op->next;
|
|
|
|
op = next;
|
|
} while (op != NULL);
|
|
audio->queuedOperations = NULL;
|
|
|
|
FAudio_PlatformUnlockMutex(audio->operationLock);
|
|
LOG_MUTEX_UNLOCK(audio, audio->operationLock)
|
|
}
|
|
|
|
void FAudio_OPERATIONSET_Commit(FAudio *audio, uint32_t OperationSet)
|
|
{
|
|
FAudio_OPERATIONSET_Operation *op, *next, *prev, **committed_end;
|
|
|
|
FAudio_PlatformLockMutex(audio->operationLock);
|
|
LOG_MUTEX_LOCK(audio, audio->operationLock)
|
|
|
|
if (audio->queuedOperations == NULL)
|
|
{
|
|
FAudio_PlatformUnlockMutex(audio->operationLock);
|
|
LOG_MUTEX_UNLOCK(audio, audio->operationLock)
|
|
return;
|
|
}
|
|
|
|
committed_end = &audio->committedOperations;
|
|
while (*committed_end)
|
|
{
|
|
committed_end = &((*committed_end)->next);
|
|
}
|
|
|
|
op = audio->queuedOperations;
|
|
prev = NULL;
|
|
do
|
|
{
|
|
next = op->next;
|
|
if (op->OperationSet == OperationSet)
|
|
{
|
|
if (prev == NULL) /* Start of linked list */
|
|
{
|
|
audio->queuedOperations = next;
|
|
}
|
|
else
|
|
{
|
|
prev->next = next;
|
|
}
|
|
|
|
*committed_end = op;
|
|
op->next = NULL;
|
|
committed_end = &op->next;
|
|
}
|
|
else
|
|
{
|
|
prev = op;
|
|
}
|
|
op = next;
|
|
} while (op != NULL);
|
|
|
|
FAudio_PlatformUnlockMutex(audio->operationLock);
|
|
LOG_MUTEX_UNLOCK(audio, audio->operationLock)
|
|
}
|
|
|
|
void FAudio_OPERATIONSET_Execute(FAudio *audio)
|
|
{
|
|
FAudio_OPERATIONSET_Operation *op, *next;
|
|
|
|
FAudio_PlatformLockMutex(audio->operationLock);
|
|
LOG_MUTEX_LOCK(audio, audio->operationLock)
|
|
|
|
op = audio->committedOperations;
|
|
while (op != NULL)
|
|
{
|
|
next = op->next;
|
|
ExecuteOperation(op);
|
|
DeleteOperation(op, audio->pFree);
|
|
op = next;
|
|
}
|
|
audio->committedOperations = NULL;
|
|
|
|
FAudio_PlatformUnlockMutex(audio->operationLock);
|
|
LOG_MUTEX_UNLOCK(audio, audio->operationLock)
|
|
}
|
|
|
|
/* OperationSet Compilation */
|
|
|
|
static inline FAudio_OPERATIONSET_Operation* QueueOperation(
|
|
FAudioVoice *voice,
|
|
FAudio_OPERATIONSET_Type type,
|
|
uint32_t operationSet
|
|
) {
|
|
FAudio_OPERATIONSET_Operation *latest;
|
|
FAudio_OPERATIONSET_Operation *newop = voice->audio->pMalloc(
|
|
sizeof(FAudio_OPERATIONSET_Operation)
|
|
);
|
|
|
|
newop->Type = type;
|
|
newop->Voice = voice;
|
|
newop->OperationSet = operationSet;
|
|
newop->next = NULL;
|
|
|
|
if (voice->audio->queuedOperations == NULL)
|
|
{
|
|
voice->audio->queuedOperations = newop;
|
|
}
|
|
else
|
|
{
|
|
latest = voice->audio->queuedOperations;
|
|
while (latest->next != NULL)
|
|
{
|
|
latest = latest->next;
|
|
}
|
|
latest->next = newop;
|
|
}
|
|
|
|
return newop;
|
|
}
|
|
|
|
void FAudio_OPERATIONSET_QueueEnableEffect(
|
|
FAudioVoice *voice,
|
|
uint32_t EffectIndex,
|
|
uint32_t OperationSet
|
|
) {
|
|
FAudio_OPERATIONSET_Operation *op;
|
|
|
|
FAudio_PlatformLockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
|
|
|
|
op = QueueOperation(
|
|
voice,
|
|
FAUDIOOP_ENABLEEFFECT,
|
|
OperationSet
|
|
);
|
|
|
|
op->Data.EnableEffect.EffectIndex = EffectIndex;
|
|
|
|
FAudio_PlatformUnlockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
|
|
}
|
|
|
|
void FAudio_OPERATIONSET_QueueDisableEffect(
|
|
FAudioVoice *voice,
|
|
uint32_t EffectIndex,
|
|
uint32_t OperationSet
|
|
) {
|
|
FAudio_OPERATIONSET_Operation *op;
|
|
|
|
FAudio_PlatformLockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
|
|
|
|
op = QueueOperation(
|
|
voice,
|
|
FAUDIOOP_DISABLEEFFECT,
|
|
OperationSet
|
|
);
|
|
|
|
op->Data.DisableEffect.EffectIndex = EffectIndex;
|
|
|
|
FAudio_PlatformUnlockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
|
|
}
|
|
|
|
void FAudio_OPERATIONSET_QueueSetEffectParameters(
|
|
FAudioVoice *voice,
|
|
uint32_t EffectIndex,
|
|
const void *pParameters,
|
|
uint32_t ParametersByteSize,
|
|
uint32_t OperationSet
|
|
) {
|
|
FAudio_OPERATIONSET_Operation *op;
|
|
|
|
FAudio_PlatformLockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
|
|
|
|
op = QueueOperation(
|
|
voice,
|
|
FAUDIOOP_SETEFFECTPARAMETERS,
|
|
OperationSet
|
|
);
|
|
|
|
op->Data.SetEffectParameters.EffectIndex = EffectIndex;
|
|
op->Data.SetEffectParameters.pParameters = voice->audio->pMalloc(
|
|
ParametersByteSize
|
|
);
|
|
FAudio_memcpy(
|
|
op->Data.SetEffectParameters.pParameters,
|
|
pParameters,
|
|
ParametersByteSize
|
|
);
|
|
op->Data.SetEffectParameters.ParametersByteSize = ParametersByteSize;
|
|
|
|
FAudio_PlatformUnlockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
|
|
}
|
|
|
|
void FAudio_OPERATIONSET_QueueSetFilterParameters(
|
|
FAudioVoice *voice,
|
|
const FAudioFilterParameters *pParameters,
|
|
uint32_t OperationSet
|
|
) {
|
|
FAudio_OPERATIONSET_Operation *op;
|
|
|
|
FAudio_PlatformLockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
|
|
|
|
op = QueueOperation(
|
|
voice,
|
|
FAUDIOOP_SETFILTERPARAMETERS,
|
|
OperationSet
|
|
);
|
|
|
|
FAudio_memcpy(
|
|
&op->Data.SetFilterParameters.Parameters,
|
|
pParameters,
|
|
sizeof(FAudioFilterParameters)
|
|
);
|
|
|
|
FAudio_PlatformUnlockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
|
|
}
|
|
|
|
void FAudio_OPERATIONSET_QueueSetOutputFilterParameters(
|
|
FAudioVoice *voice,
|
|
FAudioVoice *pDestinationVoice,
|
|
const FAudioFilterParameters *pParameters,
|
|
uint32_t OperationSet
|
|
) {
|
|
FAudio_OPERATIONSET_Operation *op;
|
|
|
|
FAudio_PlatformLockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
|
|
|
|
op = QueueOperation(
|
|
voice,
|
|
FAUDIOOP_SETOUTPUTFILTERPARAMETERS,
|
|
OperationSet
|
|
);
|
|
|
|
op->Data.SetOutputFilterParameters.pDestinationVoice = pDestinationVoice;
|
|
FAudio_memcpy(
|
|
&op->Data.SetOutputFilterParameters.Parameters,
|
|
pParameters,
|
|
sizeof(FAudioFilterParameters)
|
|
);
|
|
|
|
FAudio_PlatformUnlockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
|
|
}
|
|
|
|
void FAudio_OPERATIONSET_QueueSetVolume(
|
|
FAudioVoice *voice,
|
|
float Volume,
|
|
uint32_t OperationSet
|
|
) {
|
|
FAudio_OPERATIONSET_Operation *op;
|
|
|
|
FAudio_PlatformLockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
|
|
|
|
op = QueueOperation(
|
|
voice,
|
|
FAUDIOOP_SETVOLUME,
|
|
OperationSet
|
|
);
|
|
|
|
op->Data.SetVolume.Volume = Volume;
|
|
|
|
FAudio_PlatformUnlockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
|
|
}
|
|
|
|
void FAudio_OPERATIONSET_QueueSetChannelVolumes(
|
|
FAudioVoice *voice,
|
|
uint32_t Channels,
|
|
const float *pVolumes,
|
|
uint32_t OperationSet
|
|
) {
|
|
FAudio_OPERATIONSET_Operation *op;
|
|
|
|
FAudio_PlatformLockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
|
|
|
|
op = QueueOperation(
|
|
voice,
|
|
FAUDIOOP_SETCHANNELVOLUMES,
|
|
OperationSet
|
|
);
|
|
|
|
op->Data.SetChannelVolumes.Channels = Channels;
|
|
op->Data.SetChannelVolumes.pVolumes = voice->audio->pMalloc(
|
|
sizeof(float) * Channels
|
|
);
|
|
FAudio_memcpy(
|
|
op->Data.SetChannelVolumes.pVolumes,
|
|
pVolumes,
|
|
sizeof(float) * Channels
|
|
);
|
|
|
|
FAudio_PlatformUnlockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
|
|
}
|
|
|
|
void FAudio_OPERATIONSET_QueueSetOutputMatrix(
|
|
FAudioVoice *voice,
|
|
FAudioVoice *pDestinationVoice,
|
|
uint32_t SourceChannels,
|
|
uint32_t DestinationChannels,
|
|
const float *pLevelMatrix,
|
|
uint32_t OperationSet
|
|
) {
|
|
FAudio_OPERATIONSET_Operation *op;
|
|
|
|
FAudio_PlatformLockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
|
|
|
|
op = QueueOperation(
|
|
voice,
|
|
FAUDIOOP_SETOUTPUTMATRIX,
|
|
OperationSet
|
|
);
|
|
|
|
op->Data.SetOutputMatrix.pDestinationVoice = pDestinationVoice;
|
|
op->Data.SetOutputMatrix.SourceChannels = SourceChannels;
|
|
op->Data.SetOutputMatrix.DestinationChannels = DestinationChannels;
|
|
op->Data.SetOutputMatrix.pLevelMatrix = voice->audio->pMalloc(
|
|
sizeof(float) * SourceChannels * DestinationChannels
|
|
);
|
|
FAudio_memcpy(
|
|
op->Data.SetOutputMatrix.pLevelMatrix,
|
|
pLevelMatrix,
|
|
sizeof(float) * SourceChannels * DestinationChannels
|
|
);
|
|
|
|
FAudio_PlatformUnlockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
|
|
}
|
|
|
|
void FAudio_OPERATIONSET_QueueStart(
|
|
FAudioSourceVoice *voice,
|
|
uint32_t Flags,
|
|
uint32_t OperationSet
|
|
) {
|
|
FAudio_OPERATIONSET_Operation *op;
|
|
|
|
FAudio_PlatformLockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
|
|
|
|
op = QueueOperation(
|
|
voice,
|
|
FAUDIOOP_START,
|
|
OperationSet
|
|
);
|
|
|
|
op->Data.Start.Flags = Flags;
|
|
|
|
FAudio_PlatformUnlockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
|
|
}
|
|
|
|
void FAudio_OPERATIONSET_QueueStop(
|
|
FAudioSourceVoice *voice,
|
|
uint32_t Flags,
|
|
uint32_t OperationSet
|
|
) {
|
|
FAudio_OPERATIONSET_Operation *op;
|
|
|
|
FAudio_PlatformLockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
|
|
|
|
op = QueueOperation(
|
|
voice,
|
|
FAUDIOOP_STOP,
|
|
OperationSet
|
|
);
|
|
|
|
op->Data.Stop.Flags = Flags;
|
|
|
|
FAudio_PlatformUnlockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
|
|
}
|
|
|
|
void FAudio_OPERATIONSET_QueueExitLoop(
|
|
FAudioSourceVoice *voice,
|
|
uint32_t OperationSet
|
|
) {
|
|
FAudio_PlatformLockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
|
|
|
|
QueueOperation(
|
|
voice,
|
|
FAUDIOOP_EXITLOOP,
|
|
OperationSet
|
|
);
|
|
|
|
/* No special data for ExitLoop */
|
|
|
|
FAudio_PlatformUnlockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
|
|
}
|
|
|
|
void FAudio_OPERATIONSET_QueueSetFrequencyRatio(
|
|
FAudioSourceVoice *voice,
|
|
float Ratio,
|
|
uint32_t OperationSet
|
|
) {
|
|
FAudio_OPERATIONSET_Operation *op;
|
|
|
|
FAudio_PlatformLockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
|
|
|
|
op = QueueOperation(
|
|
voice,
|
|
FAUDIOOP_SETFREQUENCYRATIO,
|
|
OperationSet
|
|
);
|
|
|
|
op->Data.SetFrequencyRatio.Ratio = Ratio;
|
|
|
|
FAudio_PlatformUnlockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
|
|
}
|
|
|
|
/* Called when releasing the engine */
|
|
|
|
void FAudio_OPERATIONSET_ClearAll(FAudio *audio)
|
|
{
|
|
FAudio_OPERATIONSET_Operation *current, *next;
|
|
|
|
FAudio_PlatformLockMutex(audio->operationLock);
|
|
LOG_MUTEX_LOCK(audio, audio->operationLock)
|
|
|
|
current = audio->queuedOperations;
|
|
while (current != NULL)
|
|
{
|
|
next = current->next;
|
|
DeleteOperation(current, audio->pFree);
|
|
current = next;
|
|
}
|
|
audio->queuedOperations = NULL;
|
|
|
|
FAudio_PlatformUnlockMutex(audio->operationLock);
|
|
LOG_MUTEX_UNLOCK(audio, audio->operationLock)
|
|
}
|
|
|
|
/* Called when releasing a voice */
|
|
|
|
static inline void RemoveFromList(
|
|
FAudioVoice *voice,
|
|
FAudio_OPERATIONSET_Operation **list
|
|
) {
|
|
FAudio_OPERATIONSET_Operation *current, *next, *prev;
|
|
|
|
current = *list;
|
|
prev = NULL;
|
|
while (current != NULL)
|
|
{
|
|
const uint8_t baseVoice = (voice == current->Voice);
|
|
const uint8_t dstVoice = (
|
|
current->Type == FAUDIOOP_SETOUTPUTFILTERPARAMETERS &&
|
|
voice == current->Data.SetOutputFilterParameters.pDestinationVoice
|
|
) || (
|
|
current->Type == FAUDIOOP_SETOUTPUTMATRIX &&
|
|
voice == current->Data.SetOutputMatrix.pDestinationVoice
|
|
);
|
|
|
|
next = current->next;
|
|
if (baseVoice || dstVoice)
|
|
{
|
|
if (prev == NULL) /* Start of linked list */
|
|
{
|
|
*list = next;
|
|
}
|
|
else
|
|
{
|
|
prev->next = next;
|
|
}
|
|
|
|
DeleteOperation(current, voice->audio->pFree);
|
|
}
|
|
else
|
|
{
|
|
prev = current;
|
|
}
|
|
current = next;
|
|
}
|
|
}
|
|
|
|
void FAudio_OPERATIONSET_ClearAllForVoice(FAudioVoice *voice)
|
|
{
|
|
FAudio_PlatformLockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_LOCK(voice->audio, voice->audio->operationLock)
|
|
|
|
RemoveFromList(voice, &voice->audio->queuedOperations);
|
|
RemoveFromList(voice, &voice->audio->committedOperations);
|
|
|
|
FAudio_PlatformUnlockMutex(voice->audio->operationLock);
|
|
LOG_MUTEX_UNLOCK(voice->audio, voice->audio->operationLock)
|
|
}
|
|
|
|
/* vim: set noexpandtab shiftwidth=8 tabstop=8: */
|