#include "FACT.h"
#include "FACT3D.h"
#include "FAudio_internal.h"
#define ACCESSIBILITY_PUBLIC 0x1
#define ACCESSIBILITY_READONLY 0x2
#define ACCESSIBILITY_CUE 0x4
#define ACCESSIBILITY_RESERVED 0x8
enum max_instance_behavior
{
MAX_INSTANCE_BEHAVIOR_FAIL = 0,
MAX_INSTANCE_BEHAVIOR_QUEUE = 1,
MAX_INSTANCE_BEHAVIOR_REPLACE_OLDEST = 2,
MAX_INSTANCE_BEHAVIOR_REPLACE_QUIETEST = 3,
MAX_INSTANCE_BEHAVIOR_REPLACE_LOWEST_PRIORITY = 4,
};
typedef struct FACTAudioCategory
{
uint8_t instanceLimit;
uint16_t fadeInMS;
uint16_t fadeOutMS;
enum max_instance_behavior 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;
enum rpc_point_type
{
RPC_POINT_TYPE_LINEAR = 0,
RPC_POINT_TYPE_FAST = 1,
RPC_POINT_TYPE_SLOW = 2,
RPC_POINT_TYPE_SINCOS = 3,
};
typedef struct FACTRPCPoint
{
float x;
float y;
enum rpc_point_type type;
} FACTRPCPoint;
typedef enum FACTRPCParameter
{
RPC_PARAMETER_VOLUME,
RPC_PARAMETER_PITCH,
RPC_PARAMETER_REVERBSEND,
RPC_PARAMETER_FILTERFREQUENCY,
RPC_PARAMETER_FILTERQFACTOR,
RPC_PARAMETER_COUNT
} 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
{
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;
enum variation_type
{
VARIATION_TYPE_ORDERED = 0,
VARIATION_TYPE_ORDERED_FROM_RANDOM = 1,
VARIATION_TYPE_RANDOM = 2,
VARIATION_TYPE_RANDOM_NO_REPEATS = 3,
VARIATION_TYPE_SHUFFLE = 4,
};
#define VARIATION_TYPE_MASK 0x7
#define EVENT_WAVE_HAS_VARIATION 0x0040
#define EVENT_STOP_IMMEDIATE 0x01
#define EVENT_STOP_CUE 0x02
#define EVENT_SETTINGS_RAMP 0x01
#define EVENT_EQUATION_ADD 0x01
#define EVENT_EQUATION_VALUE 0x04
#define EVENT_EQUATION_RANDOM 0x08
typedef struct FACTEvent
{
uint16_t type;
uint16_t timestamp;
uint16_t randomOffset;
FAUDIONAMELESS union
{
struct
{
uint8_t flags;
uint8_t loopCount;
uint16_t position;
uint16_t angle;
bool isComplex;
FAUDIONAMELESS union
{
struct
{
uint16_t wave_index;
uint8_t wavebank;
} simple;
struct
{
enum variation_type variation_type;
bool has_variation;
uint16_t wave_count;
uint16_t *wave_indices;
uint8_t *wavebanks;
uint8_t *weights;
} complex;
};
int16_t minPitch;
int16_t maxPitch;
float minVolume;
float maxVolume;
float minFrequency;
float maxFrequency;
float minQFactor;
float maxQFactor;
uint16_t variationFlags;
} wave;
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;
struct
{
uint8_t flags;
} stop;
struct
{
uint32_t marker;
uint16_t repeats;
uint16_t frequency;
} marker;
};
} FACTEvent;
struct rpc_codes
{
const uint32_t *codes;
uint8_t count;
};
typedef struct FACTTrack
{
uint32_t code;
float volume;
uint8_t filter;
uint8_t qfactor;
uint16_t frequency;
struct rpc_codes rpc_codes;
uint8_t eventCount;
const FACTEvent *events;
} FACTTrack;
#define SOUND_FLAG_COMPLEX 0x01
#define SOUND_FLAG_HAS_RPC 0x02
#define SOUND_FLAG_HAS_TRACK_RPC 0x04
#define SOUND_FLAG_RPC_MASK 0x0e
#define SOUND_FLAG_HAS_DSP 0x10
typedef struct FACTSound
{
uint8_t flags;
uint16_t category;
float volume;
int16_t pitch;
uint8_t priority;
struct rpc_codes rpc_codes;
uint8_t trackCount;
uint8_t dspCodeCount;
const FACTTrack *tracks;
uint32_t *dspCodes;
} FACTSound;
#define CUE_FLAG_SINGLE_SOUND 0x04
typedef struct FACTCueData
{
uint8_t flags;
uint32_t sbCode;
uint32_t transitionOffset;
uint8_t instanceLimit;
uint16_t fadeInMS;
uint16_t fadeOutMS;
enum max_instance_behavior maxInstanceBehavior;
uint8_t instanceCount;
} FACTCueData;
typedef struct FACTVariation
{
FAUDIONAMELESS union
{
struct
{
uint16_t track;
uint8_t wavebank;
} simple;
uint32_t soundCode;
};
union
{
struct
{
uint8_t weight_min, weight_max;
} noninteractive;
struct
{
float var_min, var_max;
} interactive;
};
uint32_t linger;
} FACTVariation;
enum variation_table_type
{
VARIATION_TABLE_TYPE_WAVE = 0,
VARIATION_TABLE_TYPE_SOUND = 1,
VARIATION_TABLE_TYPE_CLIP = 2,
VARIATION_TABLE_TYPE_INTERACTIVE = 3,
VARIATION_TABLE_TYPE_COMPACT_WAVE = 4,
};
#define VARIATION_TABLE_TYPE_MASK 0x7
#define VARIATION_FLAG_VOLUME_ADD 0x0001
#define VARIATION_FLAG_PITCH_ADD 0x0004
#define VARIATION_FLAG_FREQUENCY_ADD 0x0010
#define VARIATION_FLAG_Q_ADD 0x0040
#define VARIATION_FLAG_PITCH_NEW_ON_LOOP 0x0100
#define VARIATION_FLAG_VOLUME_NEW_ON_LOOP 0x0200
#define VARIATION_FLAG_FREQUENCY_Q_NEW_ON_LOOP 0x0c00
#define VARIATION_FLAG_PITCH 0x1000
#define VARIATION_FLAG_VOLUME 0x2000
#define VARIATION_FLAG_FREQUENCY_Q 0xc000
#define VARIATION_FLAG_LOOP_MASK (VARIATION_FLAG_PITCH_NEW_ON_LOOP \
| VARIATION_FLAG_VOLUME_NEW_ON_LOOP | VARIATION_FLAG_FREQUENCY_Q_NEW_ON_LOOP)
typedef struct FACTVariationTable
{
uint32_t code;
enum variation_table_type type;
int16_t variable;
bool 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;
typedef struct FACTSeekTable
{
uint32_t entryCount;
uint32_t *entries;
} FACTSeekTable;
typedef struct FACTInstanceRPCData
{
float rpcVolume;
float rpcPitch;
float rpcReverbSend;
float rpcFilterFreq;
float rpcFilterQFactor;
} FACTInstanceRPCData;
typedef struct FACTEventInstance
{
uint32_t timestamp;
uint16_t loopCount;
bool finished;
FAUDIONAMELESS union
{
float value;
uint32_t valuei;
};
} FACTEventInstance;
typedef struct FACTTrackInstance
{
FACTEventInstance *events;
FACTInstanceRPCData rpcData;
float evtPitch;
float evtVolume;
struct
{
FACTWave *wave;
float baseVolume;
int16_t basePitch;
float baseQFactor;
float baseFrequency;
} activeWave, upcomingWave;
const FACTEvent *waveEvt;
FACTEventInstance *waveEvtInst;
} FACTTrackInstance;
typedef struct FACTSoundInstance
{
const FACTSound *sound;
FACTTrackInstance *tracks;
FACTInstanceRPCData rpcData;
uint32_t fadeStart;
uint16_t fadeTarget;
enum
{
SOUND_STATE_STOPPED,
SOUND_STATE_FADE_IN,
SOUND_STATE_PLAYING,
SOUND_STATE_FADE_OUT,
SOUND_STATE_RELEASE_RPC,
} state;
uint16_t variation_index;
FACTCue *parentCue;
} FACTSoundInstance;
typedef struct FACTWaveCallback
{
FAudioVoiceCallback callback;
FACTWave *wave;
} FACTWaveCallback;
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;
LinkedList *sbList;
LinkedList *wbList;
FAudioMutex sbLock;
FAudioMutex wbLock;
float *globalVariableValues;
FAudio *audio;
FAudioMasteringVoice *master;
FAudioSubmixVoice *reverbVoice;
FAudioWaveFormatExtensible output_format;
FAudioThread apiThread;
FAudioMutex apiLock;
bool initialized;
FAudioMallocFunc pMalloc;
FAudioFreeFunc pFree;
FAudioReallocFunc pRealloc;
FACTNotificationDescription *notifications;
size_t notification_count, notifications_capacity;
FACTWaveBank **prepared_wavebanks;
size_t prepared_wavebank_count, prepared_wavebanks_capacity;
void *settings;
};
struct FACTSoundBank
{
FACTAudioEngine *parentEngine;
FACTCue *cueList;
uint16_t cueCount;
uint8_t wavebankCount;
uint16_t soundCount;
uint16_t variationCount;
uint16_t transitionCount;
char **wavebankNames;
char **cueNames;
char *name;
FACTCueData *cues;
const FACTSound *sounds;
uint32_t *soundCodes;
FACTVariationTable *variations;
FACTTransitionTable *transitions;
uint32_t *transitionCodes;
};
struct FACTWaveBank
{
FACTAudioEngine *parentEngine;
LinkedList *waveList;
FAudioMutex waveLock;
char *name;
uint32_t entryCount;
FACTWaveBankEntry *entries;
uint32_t *entryRefs;
FACTSeekTable *seekTables;
char *waveBankNames;
uint32_t packetSize;
bool streaming;
uint8_t *packetBuffer;
uint32_t packetBufferLen;
void* io;
};
struct FACTWave
{
FACTWaveBank *parentBank;
FACTCue *parentCue;
uint16_t index;
bool background_music;
uint32_t state;
float volume;
int16_t pitch;
uint8_t loopCount;
uint32_t streamSize;
uint32_t streamOffset;
uint8_t *streamCache;
uint16_t srcChannels;
FAudioSourceVoice *voice;
FACTWaveCallback callback;
};
struct FACTCue
{
FACTSoundBank *parentBank;
FACTCue *next;
bool managed;
uint16_t index;
FACTCueData *data;
FAUDIONAMELESS union
{
FACTVariationTable *variation;
const FACTSound *sound;
};
float *variableValues;
float interactive;
uint32_t state;
FACTWave *simpleWave;
FACTSoundInstance *playingSound;
uint32_t maxRpcReleaseTime;
bool active3D;
uint32_t srcChannels;
uint32_t dstChannels;
float matrixCoefficients[2 * 8];
uint32_t start;
uint32_t elapsed;
};
void FACT_INTERNAL_GetNextWave(FACTCue *cue, const FACTSound *sound, const FACTTrack *track,
FACTTrackInstance *trackInst, const FACTEvent *evt, FACTEventInstance *evtInst);
void create_sound(FACTCue *cue);
bool play_sound(FACTCue *cue);
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, uint8_t type);
int32_t FAUDIOCALL FACT_INTERNAL_APIThread(void* enginePtr);
void FACT_INTERNAL_OnBufferEnd(FAudioVoiceCallback *callback, void* pContext);
void FACT_INTERNAL_OnStreamEnd(FAudioVoiceCallback *callback);
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
);
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,
bool isStreaming,
FACTWaveBank **ppWaveBank
);