645 lines
13 KiB
C
645 lines
13 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>
|
|
*
|
|
*/
|
|
|
|
#include "FACT.h"
|
|
#include "FACT3D.h"
|
|
#include "FAudio_internal.h"
|
|
|
|
/* Internal AudioEngine Types */
|
|
|
|
typedef struct FACTAudioCategory
|
|
{
|
|
uint8_t instanceLimit;
|
|
uint16_t fadeInMS;
|
|
uint16_t fadeOutMS;
|
|
uint8_t maxInstanceBehavior;
|
|
int16_t parentCategory;
|
|
float volume;
|
|
uint8_t visibility;
|
|
|
|
uint8_t instanceCount;
|
|
float currentVolume;
|
|
} FACTAudioCategory;
|
|
|
|
typedef struct FACTVariable
|
|
{
|
|
uint8_t accessibility;
|
|
float initialValue;
|
|
float minValue;
|
|
float maxValue;
|
|
} FACTVariable;
|
|
|
|
typedef struct FACTRPCPoint
|
|
{
|
|
float x;
|
|
float y;
|
|
uint8_t type;
|
|
} FACTRPCPoint;
|
|
|
|
typedef enum FACTRPCParameter
|
|
{
|
|
RPC_PARAMETER_VOLUME,
|
|
RPC_PARAMETER_PITCH,
|
|
RPC_PARAMETER_REVERBSEND,
|
|
RPC_PARAMETER_FILTERFREQUENCY,
|
|
RPC_PARAMETER_FILTERQFACTOR,
|
|
RPC_PARAMETER_COUNT /* If >=, DSP Parameter! */
|
|
} FACTRPCParameter;
|
|
|
|
typedef struct FACTRPC
|
|
{
|
|
uint16_t variable;
|
|
uint8_t pointCount;
|
|
uint16_t parameter;
|
|
FACTRPCPoint *points;
|
|
} FACTRPC;
|
|
|
|
typedef struct FACTDSPParameter
|
|
{
|
|
uint8_t type;
|
|
float value;
|
|
float minVal;
|
|
float maxVal;
|
|
uint16_t unknown;
|
|
} FACTDSPParameter;
|
|
|
|
typedef struct FACTDSPPreset
|
|
{
|
|
uint8_t accessibility;
|
|
uint16_t parameterCount;
|
|
FACTDSPParameter *parameters;
|
|
} FACTDSPPreset;
|
|
|
|
typedef enum FACTNoticationsFlags
|
|
{
|
|
NOTIFY_CUEPREPARED = 0x00000001,
|
|
NOTIFY_CUEPLAY = 0x00000002,
|
|
NOTIFY_CUESTOP = 0x00000004,
|
|
NOTIFY_CUEDESTROY = 0x00000008,
|
|
NOTIFY_MARKER = 0x00000010,
|
|
NOTIFY_SOUNDBANKDESTROY = 0x00000020,
|
|
NOTIFY_WAVEBANKDESTROY = 0x00000040,
|
|
NOTIFY_LOCALVARIABLECHANGED = 0x00000080,
|
|
NOTIFY_GLOBALVARIABLECHANGED = 0x00000100,
|
|
NOTIFY_GUICONNECTED = 0x00000200,
|
|
NOTIFY_GUIDISCONNECTED = 0x00000400,
|
|
NOTIFY_WAVEPREPARED = 0x00000800,
|
|
NOTIFY_WAVEPLAY = 0x00001000,
|
|
NOTIFY_WAVESTOP = 0x00002000,
|
|
NOTIFY_WAVELOOPED = 0x00004000,
|
|
NOTIFY_WAVEDESTROY = 0x00008000,
|
|
NOTIFY_WAVEBANKPREPARED = 0x00010000
|
|
} FACTNoticationsFlags;
|
|
|
|
/* Internal SoundBank Types */
|
|
|
|
typedef enum
|
|
{
|
|
FACTEVENT_STOP = 0,
|
|
FACTEVENT_PLAYWAVE = 1,
|
|
FACTEVENT_PLAYWAVETRACKVARIATION = 3,
|
|
FACTEVENT_PLAYWAVEEFFECTVARIATION = 4,
|
|
FACTEVENT_PLAYWAVETRACKEFFECTVARIATION = 6,
|
|
FACTEVENT_PITCH = 7,
|
|
FACTEVENT_VOLUME = 8,
|
|
FACTEVENT_MARKER = 9,
|
|
FACTEVENT_PITCHREPEATING = 16,
|
|
FACTEVENT_VOLUMEREPEATING = 17,
|
|
FACTEVENT_MARKERREPEATING = 18
|
|
} FACTEventType;
|
|
|
|
typedef struct FACTEvent
|
|
{
|
|
uint16_t type;
|
|
uint16_t timestamp;
|
|
uint16_t randomOffset;
|
|
FAUDIONAMELESS union
|
|
{
|
|
/* Play Wave Event */
|
|
struct
|
|
{
|
|
uint8_t flags;
|
|
uint8_t loopCount;
|
|
uint16_t position;
|
|
uint16_t angle;
|
|
|
|
/* Track Variation */
|
|
uint8_t isComplex;
|
|
FAUDIONAMELESS union
|
|
{
|
|
struct
|
|
{
|
|
uint16_t track;
|
|
uint8_t wavebank;
|
|
} simple;
|
|
struct
|
|
{
|
|
uint16_t variation;
|
|
uint16_t trackCount;
|
|
uint16_t *tracks;
|
|
uint8_t *wavebanks;
|
|
uint8_t *weights;
|
|
} complex;
|
|
};
|
|
|
|
/* Effect Variation */
|
|
int16_t minPitch;
|
|
int16_t maxPitch;
|
|
float minVolume;
|
|
float maxVolume;
|
|
float minFrequency;
|
|
float maxFrequency;
|
|
float minQFactor;
|
|
float maxQFactor;
|
|
uint16_t variationFlags;
|
|
} wave;
|
|
/* Set Pitch/Volume Event */
|
|
struct
|
|
{
|
|
uint8_t settings;
|
|
uint16_t repeats;
|
|
uint16_t frequency;
|
|
FAUDIONAMELESS union
|
|
{
|
|
struct
|
|
{
|
|
float initialValue;
|
|
float initialSlope;
|
|
float slopeDelta;
|
|
uint16_t duration;
|
|
} ramp;
|
|
struct
|
|
{
|
|
uint8_t flags;
|
|
float value1;
|
|
float value2;
|
|
} equation;
|
|
};
|
|
} value;
|
|
/* Stop Event */
|
|
struct
|
|
{
|
|
uint8_t flags;
|
|
} stop;
|
|
/* Marker Event */
|
|
struct
|
|
{
|
|
uint32_t marker;
|
|
uint16_t repeats;
|
|
uint16_t frequency;
|
|
} marker;
|
|
};
|
|
} FACTEvent;
|
|
|
|
typedef struct FACTTrack
|
|
{
|
|
uint32_t code;
|
|
|
|
float volume;
|
|
uint8_t filter;
|
|
uint8_t qfactor;
|
|
uint16_t frequency;
|
|
|
|
uint8_t rpcCodeCount;
|
|
uint32_t *rpcCodes;
|
|
|
|
uint8_t eventCount;
|
|
FACTEvent *events;
|
|
} FACTTrack;
|
|
|
|
typedef struct FACTSound
|
|
{
|
|
uint8_t flags;
|
|
uint16_t category;
|
|
float volume;
|
|
int16_t pitch;
|
|
uint8_t priority;
|
|
|
|
uint8_t trackCount;
|
|
uint8_t rpcCodeCount;
|
|
uint8_t dspCodeCount;
|
|
|
|
FACTTrack *tracks;
|
|
uint32_t *rpcCodes;
|
|
uint32_t *dspCodes;
|
|
} FACTSound;
|
|
|
|
typedef struct FACTCueData
|
|
{
|
|
uint8_t flags;
|
|
uint32_t sbCode;
|
|
uint32_t transitionOffset;
|
|
uint8_t instanceLimit;
|
|
uint16_t fadeInMS;
|
|
uint16_t fadeOutMS;
|
|
uint8_t maxInstanceBehavior;
|
|
uint8_t instanceCount;
|
|
} FACTCueData;
|
|
|
|
typedef struct FACTVariation
|
|
{
|
|
FAUDIONAMELESS union
|
|
{
|
|
struct
|
|
{
|
|
uint16_t track;
|
|
uint8_t wavebank;
|
|
} simple;
|
|
uint32_t soundCode;
|
|
};
|
|
float minWeight;
|
|
float maxWeight;
|
|
uint32_t linger;
|
|
} FACTVariation;
|
|
|
|
typedef struct FACTVariationTable
|
|
{
|
|
uint8_t flags;
|
|
int16_t variable;
|
|
uint8_t isComplex;
|
|
|
|
uint16_t entryCount;
|
|
FACTVariation *entries;
|
|
} FACTVariationTable;
|
|
|
|
typedef struct FACTTransition
|
|
{
|
|
int32_t soundCode;
|
|
uint32_t srcMarkerMin;
|
|
uint32_t srcMarkerMax;
|
|
uint32_t dstMarkerMin;
|
|
uint32_t dstMarkerMax;
|
|
uint16_t fadeIn;
|
|
uint16_t fadeOut;
|
|
uint16_t flags;
|
|
} FACTTransition;
|
|
|
|
typedef struct FACTTransitionTable
|
|
{
|
|
uint32_t entryCount;
|
|
FACTTransition *entries;
|
|
} FACTTransitionTable;
|
|
|
|
/* Internal WaveBank Types */
|
|
|
|
typedef struct FACTSeekTable
|
|
{
|
|
uint32_t entryCount;
|
|
uint32_t *entries;
|
|
} FACTSeekTable;
|
|
|
|
/* Internal Cue Types */
|
|
|
|
typedef struct FACTInstanceRPCData
|
|
{
|
|
float rpcVolume;
|
|
float rpcPitch;
|
|
float rpcReverbSend;
|
|
float rpcFilterFreq;
|
|
float rpcFilterQFactor;
|
|
} FACTInstanceRPCData;
|
|
|
|
typedef struct FACTEventInstance
|
|
{
|
|
uint32_t timestamp;
|
|
uint16_t loopCount;
|
|
uint8_t finished;
|
|
FAUDIONAMELESS union
|
|
{
|
|
float value;
|
|
uint32_t valuei;
|
|
};
|
|
} FACTEventInstance;
|
|
|
|
typedef struct FACTTrackInstance
|
|
{
|
|
/* Tracks which events have fired */
|
|
FACTEventInstance *events;
|
|
|
|
/* RPC instance data */
|
|
FACTInstanceRPCData rpcData;
|
|
|
|
/* SetPitch/SetVolume data */
|
|
float evtPitch;
|
|
float evtVolume;
|
|
|
|
/* Wave playback */
|
|
struct
|
|
{
|
|
FACTWave *wave;
|
|
float baseVolume;
|
|
int16_t basePitch;
|
|
float baseQFactor;
|
|
float baseFrequency;
|
|
} activeWave, upcomingWave;
|
|
FACTEvent *waveEvt;
|
|
FACTEventInstance *waveEvtInst;
|
|
} FACTTrackInstance;
|
|
|
|
typedef struct FACTSoundInstance
|
|
{
|
|
/* Base Sound reference */
|
|
FACTSound *sound;
|
|
|
|
/* Per-instance track information */
|
|
FACTTrackInstance *tracks;
|
|
|
|
/* RPC instance data */
|
|
FACTInstanceRPCData rpcData;
|
|
|
|
/* Fade data */
|
|
uint32_t fadeStart;
|
|
uint16_t fadeTarget;
|
|
uint8_t fadeType; /* In (1), Out (2), Release RPC (3) */
|
|
|
|
/* Engine references */
|
|
FACTCue *parentCue;
|
|
} FACTSoundInstance;
|
|
|
|
/* Internal Wave Types */
|
|
|
|
typedef struct FACTWaveCallback
|
|
{
|
|
FAudioVoiceCallback callback;
|
|
FACTWave *wave;
|
|
} FACTWaveCallback;
|
|
|
|
/* Public XACT Types */
|
|
|
|
struct FACTAudioEngine
|
|
{
|
|
uint32_t refcount;
|
|
FACTNotificationCallback notificationCallback;
|
|
FACTReadFileCallback pReadFile;
|
|
FACTGetOverlappedResultCallback pGetOverlappedResult;
|
|
|
|
uint16_t categoryCount;
|
|
uint16_t variableCount;
|
|
uint16_t rpcCount;
|
|
uint16_t dspPresetCount;
|
|
uint16_t dspParameterCount;
|
|
|
|
char **categoryNames;
|
|
char **variableNames;
|
|
uint32_t *rpcCodes;
|
|
uint32_t *dspPresetCodes;
|
|
|
|
FACTAudioCategory *categories;
|
|
FACTVariable *variables;
|
|
FACTRPC *rpcs;
|
|
FACTDSPPreset *dspPresets;
|
|
|
|
/* Engine references */
|
|
LinkedList *sbList;
|
|
LinkedList *wbList;
|
|
FAudioMutex sbLock;
|
|
FAudioMutex wbLock;
|
|
float *globalVariableValues;
|
|
|
|
/* FAudio references */
|
|
FAudio *audio;
|
|
FAudioMasteringVoice *master;
|
|
FAudioSubmixVoice *reverbVoice;
|
|
|
|
/* Engine thread */
|
|
FAudioThread apiThread;
|
|
FAudioMutex apiLock;
|
|
uint8_t initialized;
|
|
|
|
/* Allocator callbacks */
|
|
FAudioMallocFunc pMalloc;
|
|
FAudioFreeFunc pFree;
|
|
FAudioReallocFunc pRealloc;
|
|
|
|
/* Peristent Notifications */
|
|
FACTNoticationsFlags notifications;
|
|
void *cue_context;
|
|
void *sb_context;
|
|
void *wb_context;
|
|
void *wave_context;
|
|
|
|
/* Settings handle */
|
|
void *settings;
|
|
};
|
|
|
|
struct FACTSoundBank
|
|
{
|
|
/* Engine references */
|
|
FACTAudioEngine *parentEngine;
|
|
FACTCue *cueList;
|
|
uint8_t notifyOnDestroy;
|
|
void *usercontext;
|
|
|
|
/* Array sizes */
|
|
uint16_t cueCount;
|
|
uint8_t wavebankCount;
|
|
uint16_t soundCount;
|
|
uint16_t variationCount;
|
|
uint16_t transitionCount;
|
|
|
|
/* Strings, strings everywhere! */
|
|
char **wavebankNames;
|
|
char **cueNames;
|
|
|
|
/* Actual SoundBank information */
|
|
char *name;
|
|
FACTCueData *cues;
|
|
FACTSound *sounds;
|
|
uint32_t *soundCodes;
|
|
FACTVariationTable *variations;
|
|
uint32_t *variationCodes;
|
|
FACTTransitionTable *transitions;
|
|
uint32_t *transitionCodes;
|
|
};
|
|
|
|
struct FACTWaveBank
|
|
{
|
|
/* Engine references */
|
|
FACTAudioEngine *parentEngine;
|
|
LinkedList *waveList;
|
|
FAudioMutex waveLock;
|
|
uint8_t notifyOnDestroy;
|
|
void *usercontext;
|
|
|
|
/* Actual WaveBank information */
|
|
char *name;
|
|
uint32_t entryCount;
|
|
FACTWaveBankEntry *entries;
|
|
uint32_t *entryRefs;
|
|
FACTSeekTable *seekTables;
|
|
char *waveBankNames;
|
|
|
|
/* I/O information */
|
|
uint32_t packetSize;
|
|
uint16_t streaming;
|
|
uint8_t *packetBuffer;
|
|
uint32_t packetBufferLen;
|
|
void* io;
|
|
};
|
|
|
|
struct FACTWave
|
|
{
|
|
/* Engine references */
|
|
FACTWaveBank *parentBank;
|
|
FACTCue *parentCue;
|
|
uint16_t index;
|
|
uint8_t notifyOnDestroy;
|
|
void *usercontext;
|
|
|
|
/* Playback */
|
|
uint32_t state;
|
|
float volume;
|
|
int16_t pitch;
|
|
uint8_t loopCount;
|
|
|
|
/* Stream data */
|
|
uint32_t streamSize;
|
|
uint32_t streamOffset;
|
|
uint8_t *streamCache;
|
|
|
|
/* FAudio references */
|
|
uint16_t srcChannels;
|
|
FAudioSourceVoice *voice;
|
|
FACTWaveCallback callback;
|
|
};
|
|
|
|
struct FACTCue
|
|
{
|
|
/* Engine references */
|
|
FACTSoundBank *parentBank;
|
|
FACTCue *next;
|
|
uint8_t managed;
|
|
uint16_t index;
|
|
uint8_t notifyOnDestroy;
|
|
void *usercontext;
|
|
|
|
/* Sound data */
|
|
FACTCueData *data;
|
|
FAUDIONAMELESS union
|
|
{
|
|
FACTVariationTable *variation;
|
|
|
|
/* This is only used in scenarios where there is only one
|
|
* Sound; XACT does not generate variation tables for
|
|
* Cues with only one Sound.
|
|
*/
|
|
FACTSound *sound;
|
|
};
|
|
|
|
/* Instance data */
|
|
float *variableValues;
|
|
float interactive;
|
|
|
|
/* Playback */
|
|
uint32_t state;
|
|
FACTWave *simpleWave;
|
|
FACTSoundInstance *playingSound;
|
|
FACTVariation *playingVariation;
|
|
uint32_t maxRpcReleaseTime;
|
|
|
|
/* 3D Data */
|
|
uint8_t active3D;
|
|
uint32_t srcChannels;
|
|
uint32_t dstChannels;
|
|
float matrixCoefficients[2 * 8]; /* Stereo input, 7.1 output */
|
|
|
|
/* Timer */
|
|
uint32_t start;
|
|
uint32_t elapsed;
|
|
};
|
|
|
|
/* Internal functions */
|
|
|
|
void FACT_INTERNAL_GetNextWave(
|
|
FACTCue *cue,
|
|
FACTSound *sound,
|
|
FACTTrack *track,
|
|
FACTTrackInstance *trackInst,
|
|
FACTEvent *evt,
|
|
FACTEventInstance *evtInst
|
|
);
|
|
uint8_t FACT_INTERNAL_CreateSound(FACTCue *cue, uint16_t fadeInMS);
|
|
void FACT_INTERNAL_DestroySound(FACTSoundInstance *sound);
|
|
void FACT_INTERNAL_BeginFadeOut(FACTSoundInstance *sound, uint16_t fadeOutMS);
|
|
void FACT_INTERNAL_BeginReleaseRPC(FACTSoundInstance *sound, uint16_t releaseMS);
|
|
|
|
void FACT_INTERNAL_SendCueNotification(FACTCue *cue, FACTNoticationsFlags flag, uint8_t type);
|
|
|
|
/* RPC Helper Functions */
|
|
|
|
FACTRPC* FACT_INTERNAL_GetRPC(FACTAudioEngine *engine, uint32_t code);
|
|
|
|
/* FACT Thread */
|
|
|
|
int32_t FAUDIOCALL FACT_INTERNAL_APIThread(void* enginePtr);
|
|
|
|
/* FAudio callbacks */
|
|
|
|
void FACT_INTERNAL_OnBufferEnd(FAudioVoiceCallback *callback, void* pContext);
|
|
void FACT_INTERNAL_OnStreamEnd(FAudioVoiceCallback *callback);
|
|
|
|
/* FAudioIOStream functions */
|
|
|
|
int32_t FACTCALL FACT_INTERNAL_DefaultReadFile(
|
|
void *hFile,
|
|
void *buffer,
|
|
uint32_t nNumberOfBytesToRead,
|
|
uint32_t *lpNumberOfBytesRead,
|
|
FACTOverlapped *lpOverlapped
|
|
);
|
|
|
|
int32_t FACTCALL FACT_INTERNAL_DefaultGetOverlappedResult(
|
|
void *hFile,
|
|
FACTOverlapped *lpOverlapped,
|
|
uint32_t *lpNumberOfBytesTransferred,
|
|
int32_t bWait
|
|
);
|
|
|
|
/* Parsing functions */
|
|
|
|
uint32_t FACT_INTERNAL_ParseAudioEngine(
|
|
FACTAudioEngine *pEngine,
|
|
const FACTRuntimeParameters *pParams
|
|
);
|
|
uint32_t FACT_INTERNAL_ParseSoundBank(
|
|
FACTAudioEngine *pEngine,
|
|
const void *pvBuffer,
|
|
uint32_t dwSize,
|
|
FACTSoundBank **ppSoundBank
|
|
);
|
|
uint32_t FACT_INTERNAL_ParseWaveBank(
|
|
FACTAudioEngine *pEngine,
|
|
void* io,
|
|
uint32_t offset,
|
|
uint32_t packetSize,
|
|
FACTReadFileCallback pRead,
|
|
FACTGetOverlappedResultCallback pOverlap,
|
|
uint16_t isStreaming,
|
|
FACTWaveBank **ppWaveBank
|
|
);
|
|
|
|
/* vim: set noexpandtab shiftwidth=8 tabstop=8: */
|