forked from MoonsideGames/FAudioGMS
playing sound effects
parent
2880dd42bf
commit
f449b135c2
|
@ -1,3 +1,6 @@
|
|||
[submodule "FAudio"]
|
||||
path = lib/FAudio
|
||||
url = https://github.com/FNA-XNA/FAudio
|
||||
[submodule "lib/SDL"]
|
||||
path = lib/SDL
|
||||
url = https://github.com/libsdl-org/SDL.git
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 25f9ed87ff6947d9576fc9d79dee0784e638ac58
|
540
src/FAudioGMS.c
540
src/FAudioGMS.c
|
@ -24,6 +24,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "../lib/SDL/include/SDL.h"
|
||||
|
||||
#include "FAudioGMS.h"
|
||||
#include "../lib/FAudio/include/FAPOBase.h"
|
||||
#include "../lib/FAudio/include/FAudioFX.h"
|
||||
|
@ -33,12 +35,11 @@
|
|||
#define DR_WAV_IMPLEMENTATION
|
||||
#include "../lib/dr_wav.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static inline void Log(char *string)
|
||||
{
|
||||
printf("%s", string);
|
||||
printf("%s\n", string);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
@ -75,6 +76,19 @@ typedef struct FAudioGMS_SoundInstance
|
|||
float lowPassFilter;
|
||||
float highPassFilter;
|
||||
float bandPassFilter;
|
||||
|
||||
uint8_t reverbAttached;
|
||||
FAudioSubmixVoice* reverbVoice;
|
||||
FAudioVoiceSends reverbSends;
|
||||
|
||||
uint8_t isStatic;
|
||||
uint8_t destroyOnFinish;
|
||||
|
||||
union
|
||||
{
|
||||
FAudioGMS_StaticSound *staticSound;
|
||||
/* TODO: streaming */
|
||||
} parent;
|
||||
} FAudioGMS_SoundInstance;
|
||||
|
||||
typedef struct FAudioGMS_Device
|
||||
|
@ -82,28 +96,26 @@ typedef struct FAudioGMS_Device
|
|||
FAudio* handle;
|
||||
FAudioDeviceDetails deviceDetails;
|
||||
FAudioMasteringVoice *masteringVoice;
|
||||
FAudioSubmixVoice *reverbVoice;
|
||||
FAudioVoiceSends reverbSends;
|
||||
|
||||
FAudioGMS_StaticSound **staticSounds;
|
||||
uint32_t staticSoundCount;
|
||||
|
||||
FAudioGMS_SoundInstance **staticSoundInstances;
|
||||
uint32_t staticSoundInstanceCount;
|
||||
FAudioGMS_SoundInstance **soundInstances;
|
||||
uint32_t soundInstanceCount;
|
||||
} FAudioGMS_Device;
|
||||
|
||||
static FAudioGMS_Device *device = NULL;
|
||||
|
||||
void FAudioGMS_Init()
|
||||
{
|
||||
device = malloc(sizeof(FAudioGMS_Device));
|
||||
device = SDL_malloc(sizeof(FAudioGMS_Device));
|
||||
|
||||
uint32_t result = FAudioCreate(&device->handle, 0, FAUDIO_DEFAULT_PROCESSOR);
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
Log("Failed to create device! Bailing!");
|
||||
free(device);
|
||||
SDL_free(device);
|
||||
device = NULL;
|
||||
return;
|
||||
}
|
||||
|
@ -117,7 +129,7 @@ void FAudioGMS_Init()
|
|||
{
|
||||
Log("No audio devices found! Bailing!");
|
||||
FAudio_Release(device->handle);
|
||||
free(device);
|
||||
SDL_free(device);
|
||||
device = NULL;
|
||||
return;
|
||||
}
|
||||
|
@ -162,96 +174,88 @@ void FAudioGMS_Init()
|
|||
{
|
||||
Log("No mastering voice found! Bailing!");
|
||||
FAudio_Release(device->handle);
|
||||
free(device);
|
||||
SDL_free(device);
|
||||
device = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Init reverb */
|
||||
|
||||
FAPO *reverb = malloc(sizeof(FAPO));
|
||||
|
||||
FAudioCreateReverb(&reverb, 0);
|
||||
|
||||
FAudioEffectChain *reverbChain = malloc(sizeof(FAudioEffectChain));
|
||||
|
||||
reverbChain->EffectCount = 1;
|
||||
reverbChain->pEffectDescriptors = malloc(sizeof(FAudioEffectDescriptor));
|
||||
|
||||
FAudioEffectDescriptor *reverbDescriptor = reverbChain->pEffectDescriptors;
|
||||
|
||||
reverbDescriptor->InitialState = 1;
|
||||
reverbDescriptor->OutputChannels = device->deviceDetails.OutputFormat.Format.nChannels == 6 ? 6 : 1;
|
||||
reverbDescriptor->pEffect = reverb;
|
||||
|
||||
FAudio_CreateSubmixVoice(
|
||||
device->handle,
|
||||
&device->reverbVoice,
|
||||
1, /* omnidirectional reverb */
|
||||
device->deviceDetails.OutputFormat.Format.nSamplesPerSec,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
reverbChain);
|
||||
|
||||
FAPOBase_Release((FAPOBase*)reverb);
|
||||
free(reverb);
|
||||
free(reverbChain->pEffectDescriptors);
|
||||
free(reverbChain);
|
||||
|
||||
FAudioFXReverbParameters *reverbParams = malloc(sizeof(FAudioFXReverbParameters));
|
||||
|
||||
reverbParams->WetDryMix = 100.0f;
|
||||
reverbParams->ReflectionsDelay = 7;
|
||||
reverbParams->ReverbDelay = 11;
|
||||
reverbParams->RearDelay = FAUDIOFX_REVERB_DEFAULT_REAR_DELAY;
|
||||
reverbParams->PositionLeft = FAUDIOFX_REVERB_DEFAULT_POSITION;
|
||||
reverbParams->PositionRight = FAUDIOFX_REVERB_DEFAULT_POSITION;
|
||||
reverbParams->PositionMatrixLeft = FAUDIOFX_REVERB_DEFAULT_POSITION_MATRIX;
|
||||
reverbParams->PositionMatrixRight = FAUDIOFX_REVERB_DEFAULT_POSITION_MATRIX;
|
||||
reverbParams->EarlyDiffusion = 15;
|
||||
reverbParams->LateDiffusion = 15;
|
||||
reverbParams->LowEQGain = 8;
|
||||
reverbParams->LowEQCutoff = 4;
|
||||
reverbParams->HighEQGain = 8;
|
||||
reverbParams->HighEQCutoff = 6;
|
||||
reverbParams->RoomFilterFreq = 5000.0f;
|
||||
reverbParams->RoomFilterMain = -10.0f;
|
||||
reverbParams->RoomFilterHF = -1.0f;
|
||||
reverbParams->ReflectionsGain = -26.0200005f;
|
||||
reverbParams->ReverbGain = 10.0f;
|
||||
reverbParams->DecayTime = 1.49000001f;
|
||||
reverbParams->Density = 100.0f;
|
||||
reverbParams->RoomSize = FAUDIOFX_REVERB_DEFAULT_ROOM_SIZE;
|
||||
|
||||
FAudioVoice_SetEffectParameters(
|
||||
device->reverbVoice,
|
||||
0,
|
||||
reverbParams,
|
||||
sizeof(FAudioFXReverbParameters),
|
||||
0);
|
||||
|
||||
free(reverbParams);
|
||||
|
||||
/* Init reverb sends */
|
||||
|
||||
device->reverbSends.SendCount = 2;
|
||||
device->reverbSends.pSends = malloc(2 * sizeof(FAudioSendDescriptor));
|
||||
|
||||
device->reverbSends.pSends[0].Flags = 0;
|
||||
device->reverbSends.pSends[0].pOutputVoice = device->masteringVoice;
|
||||
device->reverbSends.pSends[1].Flags = 0;
|
||||
device->reverbSends.pSends[1].pOutputVoice = device->reverbVoice;
|
||||
|
||||
device->staticSounds = NULL;
|
||||
device->staticSoundCount = 0;
|
||||
|
||||
device->soundInstances = NULL;
|
||||
device->soundInstanceCount = 0;
|
||||
|
||||
Log("FAudio initialized successfully!");
|
||||
printf("Device: %ls", device->deviceDetails.DisplayName);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
static void FAudioGMS_INTERNAL_SoundInstance_Destroy(FAudioGMS_SoundInstance* instance)
|
||||
{
|
||||
if (instance != NULL)
|
||||
{
|
||||
device->soundInstances[instance->id] = NULL;
|
||||
FAudioSourceVoice_Stop(instance->handle, 0, 0);
|
||||
FAudioSourceVoice_FlushSourceBuffers(instance->handle);
|
||||
FAudioVoice_DestroyVoice(instance->handle);
|
||||
SDL_free(instance->dspSettings.pMatrixCoefficients);
|
||||
SDL_free(instance);
|
||||
}
|
||||
}
|
||||
|
||||
void FAudioGMS_SoundInstance_Destroy(double id)
|
||||
{
|
||||
FAudioGMS_INTERNAL_SoundInstance_Destroy(device->soundInstances[(uint32_t)id]);
|
||||
}
|
||||
|
||||
void FAudioGMS_SoundInstance_DestroyWhenFinished(double id)
|
||||
{
|
||||
FAudioGMS_SoundInstance *instance = device->soundInstances[(uint32_t)id];
|
||||
|
||||
if (instance != NULL)
|
||||
{
|
||||
instance->destroyOnFinish = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: this will die horribly if a sound is playing */
|
||||
static void FAudioGMS_INTERNAL_StaticSound_Destroy(FAudioGMS_StaticSound* sound)
|
||||
{
|
||||
if (sound != NULL)
|
||||
{
|
||||
device->staticSounds[sound->id] = NULL;
|
||||
SDL_free((void*)sound->buffer.pAudioData);
|
||||
SDL_free(sound);
|
||||
}
|
||||
}
|
||||
|
||||
void FAudioGMS_StaticSound_Destroy(double id)
|
||||
{
|
||||
FAudioGMS_INTERNAL_StaticSound_Destroy(device->staticSounds[(uint32_t)id]);
|
||||
}
|
||||
|
||||
void FAudioGMS_Update()
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < device->soundInstanceCount; i += 1)
|
||||
{
|
||||
FAudioGMS_SoundInstance* instance = device->soundInstances[i];
|
||||
|
||||
if (instance != NULL)
|
||||
{
|
||||
if (instance->destroyOnFinish)
|
||||
{
|
||||
FAudioVoiceState state;
|
||||
FAudioSourceVoice_GetState(instance->handle, &state, FAUDIO_VOICE_NOSAMPLESPLAYED);
|
||||
|
||||
if (state.BuffersQueued == 0)
|
||||
{
|
||||
FAudioGMS_INTERNAL_SoundInstance_Destroy(instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Taken from https://github.com/FNA-XNA/FNA/blob/master/src/Audio/SoundEffectInstance.cs */
|
||||
|
@ -313,7 +317,7 @@ double FAudioGMS_StaticSound_LoadWAV(char *filePath)
|
|||
{
|
||||
drwav_uint64 frameCount;
|
||||
|
||||
FAudioGMS_StaticSound *sound = malloc(sizeof(FAudioGMS_StaticSound));
|
||||
FAudioGMS_StaticSound *sound = SDL_malloc(sizeof(FAudioGMS_StaticSound));
|
||||
float *pSampleData = drwav_open_file_and_read_pcm_frames_f32(filePath, &sound->channels, &sound->samplesPerSecond, &frameCount, NULL);
|
||||
if (pSampleData == NULL)
|
||||
{
|
||||
|
@ -337,19 +341,210 @@ double FAudioGMS_StaticSound_LoadWAV(char *filePath)
|
|||
/* FIXME: id re-use system */
|
||||
sound->id = device->staticSoundCount;
|
||||
|
||||
device->staticSounds = realloc(device->staticSounds, (device->staticSoundCount + 1) * sizeof(FAudioGMS_StaticSound*));
|
||||
device->staticSounds = SDL_realloc(device->staticSounds, (device->staticSoundCount + 1) * sizeof(FAudioGMS_StaticSound*));
|
||||
device->staticSounds[device->staticSoundCount] = sound;
|
||||
device->staticSoundCount += 1;
|
||||
|
||||
return (double)sound->id;
|
||||
}
|
||||
|
||||
double FAudioGMS_SoundInstance_CreateFromStaticSound(double id)
|
||||
static void FAudioGMS_INTERNAL_SoundInstance_AttachReverb(FAudioGMS_SoundInstance* instance)
|
||||
{
|
||||
FAudioGMS_StaticSound *staticSound = device->staticSounds[(uint32_t)id];
|
||||
FAudioGMS_SoundInstance *instance = malloc(sizeof(FAudioGMS_SoundInstance));
|
||||
if (!instance->reverbAttached)
|
||||
{
|
||||
/* Init reverb */
|
||||
|
||||
FAPO* reverb;
|
||||
FAudioCreateReverb(&reverb, 0);
|
||||
|
||||
FAudioEffectChain* reverbChain = SDL_malloc(sizeof(FAudioEffectChain));
|
||||
|
||||
reverbChain->EffectCount = 1;
|
||||
reverbChain->pEffectDescriptors = SDL_malloc(sizeof(FAudioEffectDescriptor));
|
||||
|
||||
FAudioEffectDescriptor* reverbDescriptor = reverbChain->pEffectDescriptors;
|
||||
|
||||
reverbDescriptor->InitialState = 1;
|
||||
reverbDescriptor->OutputChannels = device->deviceDetails.OutputFormat.Format.nChannels == 6 ? 6 : 1;
|
||||
reverbDescriptor->pEffect = reverb;
|
||||
|
||||
FAudio_CreateSubmixVoice(
|
||||
device->handle,
|
||||
&instance->reverbVoice,
|
||||
1, /* omnidirectional reverb */
|
||||
device->deviceDetails.OutputFormat.Format.nSamplesPerSec,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
reverbChain);
|
||||
|
||||
FAPOBase_Release((FAPOBase*)reverb);
|
||||
SDL_free(reverbChain->pEffectDescriptors);
|
||||
SDL_free(reverbChain);
|
||||
|
||||
FAudioFXReverbParameters* reverbParams = SDL_malloc(sizeof(FAudioFXReverbParameters));
|
||||
|
||||
reverbParams->WetDryMix = 100.0f;
|
||||
reverbParams->ReflectionsDelay = 7;
|
||||
reverbParams->ReverbDelay = 11;
|
||||
reverbParams->RearDelay = FAUDIOFX_REVERB_DEFAULT_REAR_DELAY;
|
||||
reverbParams->PositionLeft = FAUDIOFX_REVERB_DEFAULT_POSITION;
|
||||
reverbParams->PositionRight = FAUDIOFX_REVERB_DEFAULT_POSITION;
|
||||
reverbParams->PositionMatrixLeft = FAUDIOFX_REVERB_DEFAULT_POSITION_MATRIX;
|
||||
reverbParams->PositionMatrixRight = FAUDIOFX_REVERB_DEFAULT_POSITION_MATRIX;
|
||||
reverbParams->EarlyDiffusion = 15;
|
||||
reverbParams->LateDiffusion = 15;
|
||||
reverbParams->LowEQGain = 8;
|
||||
reverbParams->LowEQCutoff = 4;
|
||||
reverbParams->HighEQGain = 8;
|
||||
reverbParams->HighEQCutoff = 6;
|
||||
reverbParams->RoomFilterFreq = 5000.0f;
|
||||
reverbParams->RoomFilterMain = -10.0f;
|
||||
reverbParams->RoomFilterHF = -1.0f;
|
||||
reverbParams->ReflectionsGain = -26.0200005f;
|
||||
reverbParams->ReverbGain = 10.0f;
|
||||
reverbParams->DecayTime = 1.49000001f;
|
||||
reverbParams->Density = 100.0f;
|
||||
reverbParams->RoomSize = FAUDIOFX_REVERB_DEFAULT_ROOM_SIZE;
|
||||
|
||||
FAudioVoice_SetEffectParameters(
|
||||
instance->reverbVoice,
|
||||
0,
|
||||
reverbParams,
|
||||
sizeof(FAudioFXReverbParameters),
|
||||
0);
|
||||
|
||||
SDL_free(reverbParams);
|
||||
|
||||
/* Init reverb sends */
|
||||
|
||||
instance->reverbSends.SendCount = 2;
|
||||
instance->reverbSends.pSends = SDL_malloc(2 * sizeof(FAudioSendDescriptor));
|
||||
|
||||
instance->reverbSends.pSends[0].Flags = 0;
|
||||
instance->reverbSends.pSends[0].pOutputVoice = device->masteringVoice;
|
||||
instance->reverbSends.pSends[1].Flags = 0;
|
||||
instance->reverbSends.pSends[1].pOutputVoice = instance->reverbVoice;
|
||||
|
||||
instance->reverbAttached = 1;
|
||||
}
|
||||
|
||||
FAudioVoice_SetOutputVoices(
|
||||
instance->handle,
|
||||
&instance->reverbSends);
|
||||
}
|
||||
|
||||
static void FAudioGMS_INTERNAL_SoundInstance_SetReverb(FAudioGMS_SoundInstance *instance, float reverb)
|
||||
{
|
||||
if (!instance->reverbAttached)
|
||||
{
|
||||
FAudioGMS_INTERNAL_SoundInstance_AttachReverb(instance);
|
||||
}
|
||||
|
||||
float* outputMatrix = instance->dspSettings.pMatrixCoefficients;
|
||||
|
||||
outputMatrix[0] = reverb;
|
||||
if (instance->dspSettings.SrcChannelCount == 2)
|
||||
{
|
||||
outputMatrix[1] = reverb;
|
||||
}
|
||||
|
||||
FAudioVoice_SetOutputMatrix(
|
||||
instance->handle,
|
||||
instance->reverbVoice,
|
||||
instance->dspSettings.SrcChannelCount,
|
||||
1,
|
||||
outputMatrix,
|
||||
0);
|
||||
|
||||
instance->reverb = reverb;
|
||||
}
|
||||
|
||||
static void FAudioGMS_INTERNAL_SoundInstance_SetLowPassFilter(FAudioGMS_SoundInstance* instance, float lowPassFilter)
|
||||
{
|
||||
FAudioFilterParameters p;
|
||||
p.Type = FAudioLowPassFilter;
|
||||
p.Frequency = lowPassFilter;
|
||||
p.OneOverQ = 1.0f;
|
||||
|
||||
FAudioVoice_SetFilterParameters(instance->handle, &p, 0);
|
||||
|
||||
instance->lowPassFilter = lowPassFilter;
|
||||
}
|
||||
|
||||
static void FAudioGMS_INTERNAL_SoundInstance_SetHighPassFilter(FAudioGMS_SoundInstance* instance, float highPassFilter)
|
||||
{
|
||||
FAudioFilterParameters p;
|
||||
p.Type = FAudioHighPassFilter;
|
||||
p.Frequency = highPassFilter;
|
||||
p.OneOverQ = 1.0f;
|
||||
|
||||
FAudioVoice_SetFilterParameters(instance->handle, &p, 0);
|
||||
|
||||
instance->highPassFilter = highPassFilter;
|
||||
}
|
||||
|
||||
static void FAudioGMS_INTERNAL_SoundInstance_SetBandPassFilter(FAudioGMS_SoundInstance* instance, float bandPassFilter)
|
||||
{
|
||||
FAudioFilterParameters p;
|
||||
p.Type = FAudioBandPassFilter;
|
||||
p.Frequency = bandPassFilter;
|
||||
p.OneOverQ = 1.0f;
|
||||
|
||||
FAudioVoice_SetFilterParameters(instance->handle, &p, 0);
|
||||
|
||||
instance->bandPassFilter = bandPassFilter;
|
||||
}
|
||||
|
||||
static void FAudioGMS_INTERNAL_SoundInstance_SetPan(FAudioGMS_SoundInstance* instance, float pan)
|
||||
{
|
||||
instance->pan = pan;
|
||||
SetPanMatrixCoefficients(instance);
|
||||
|
||||
FAudioVoice_SetOutputMatrix(
|
||||
instance->handle,
|
||||
device->masteringVoice,
|
||||
instance->dspSettings.SrcChannelCount,
|
||||
instance->dspSettings.DstChannelCount,
|
||||
instance->dspSettings.pMatrixCoefficients,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
static void FAudioGMS_INTERNAL_SoundInstance_SetPitch(FAudioGMS_SoundInstance* instance, float pitch)
|
||||
{
|
||||
instance->pitch = pitch;
|
||||
|
||||
pitch -= 1.0; /* default pitch is 1.0 as per GM standard */
|
||||
pitch = SDL_max(-1.0, SDL_min(1.0, pitch));
|
||||
|
||||
FAudioSourceVoice_SetFrequencyRatio(
|
||||
instance->handle,
|
||||
SDL_powf(2.0f, pitch),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
static void FAudioGMS_INTERNAL_SoundInstance_SetVolume(FAudioGMS_SoundInstance* instance, float volume)
|
||||
{
|
||||
FAudioVoice_SetVolume(instance->handle, volume, 0);
|
||||
}
|
||||
|
||||
static FAudioGMS_SoundInstance* FAudioGMS_INTERNAL_SoundInstance_CreateFromStaticSound(
|
||||
FAudioGMS_StaticSound *staticSound,
|
||||
double pan,
|
||||
double pitch,
|
||||
double volume,
|
||||
double reverb
|
||||
) {
|
||||
FAudioGMS_SoundInstance *instance = SDL_malloc(sizeof(FAudioGMS_SoundInstance));
|
||||
|
||||
instance->handle = NULL;
|
||||
instance->parent.staticSound = staticSound;
|
||||
instance->isStatic = 1;
|
||||
instance->loop = 0;
|
||||
instance->destroyOnFinish = 0;
|
||||
|
||||
instance->format.wFormatTag = 3;
|
||||
instance->format.wBitsPerSample = 32;
|
||||
instance->format.nChannels = staticSound->channels;
|
||||
|
@ -370,8 +565,8 @@ double FAudioGMS_SoundInstance_CreateFromStaticSound(double id)
|
|||
if (instance->handle == NULL)
|
||||
{
|
||||
Log("SoundInstance failed to initialize!");
|
||||
free(instance);
|
||||
return -1;
|
||||
SDL_free(instance);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
instance->dspSettings.DopplerFactor = 1.0f;
|
||||
|
@ -379,55 +574,162 @@ double FAudioGMS_SoundInstance_CreateFromStaticSound(double id)
|
|||
instance->dspSettings.DstChannelCount = device->deviceDetails.OutputFormat.Format.nChannels;
|
||||
|
||||
uint32_t memsize = 4 * instance->dspSettings.SrcChannelCount * instance->dspSettings.DstChannelCount;
|
||||
instance->dspSettings.pMatrixCoefficients = malloc(memsize);
|
||||
memset(instance->dspSettings.pMatrixCoefficients, 0, memsize);
|
||||
instance->dspSettings.pMatrixCoefficients = SDL_malloc(memsize);
|
||||
SDL_memset(instance->dspSettings.pMatrixCoefficients, 0, memsize);
|
||||
|
||||
SetPanMatrixCoefficients(instance);
|
||||
FAudioGMS_INTERNAL_SoundInstance_SetPan(instance, pan);
|
||||
FAudioGMS_INTERNAL_SoundInstance_SetPitch(instance, pitch);
|
||||
FAudioGMS_INTERNAL_SoundInstance_SetVolume(instance, volume);
|
||||
|
||||
FAudioVoice_SetOutputVoices(
|
||||
instance->handle,
|
||||
&device->reverbSends);
|
||||
instance->reverbAttached = 0;
|
||||
instance->reverb = 0.0f;
|
||||
instance->lowPassFilter = 0.0f;
|
||||
instance->highPassFilter = 0.0f;
|
||||
instance->bandPassFilter = 0.0f;
|
||||
|
||||
if (reverb > 0.0f)
|
||||
{
|
||||
FAudioGMS_INTERNAL_SoundInstance_SetReverb(instance, reverb);
|
||||
}
|
||||
|
||||
instance->soundState = SoundState_Stopped;
|
||||
|
||||
/* FIXME: id re-use system */
|
||||
instance->id = device->staticSoundInstanceCount;
|
||||
instance->id = device->soundInstanceCount;
|
||||
|
||||
device->staticSoundInstances = realloc(device->staticSoundInstances, (device->staticSoundCount + 1) * sizeof(FAudioGMS_SoundInstance*));
|
||||
device->staticSoundInstances[device->staticSoundInstanceCount] = instance;
|
||||
device->staticSoundInstanceCount += 1;
|
||||
device->soundInstances = SDL_realloc(device->soundInstances, (device->soundInstanceCount + 1) * sizeof(FAudioGMS_SoundInstance*));
|
||||
device->soundInstances[device->soundInstanceCount] = instance;
|
||||
device->soundInstanceCount += 1;
|
||||
|
||||
return (double)instance->id;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void FAudioGMS_SoundInstance_Destroy(double id)
|
||||
static void FAudioGMS_INTERNAL_SoundInstance_Play(FAudioGMS_SoundInstance* instance)
|
||||
{
|
||||
FAudioGMS_SoundInstance *instance = device->staticSoundInstances[(uint32_t)id];
|
||||
if (instance->isStatic)
|
||||
{
|
||||
if (instance->soundState == SoundState_Playing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (instance->loop)
|
||||
{
|
||||
instance->parent.staticSound->buffer.LoopCount = FAUDIO_LOOP_INFINITE;
|
||||
instance->parent.staticSound->buffer.LoopBegin = instance->parent.staticSound->loopStart;
|
||||
instance->parent.staticSound->buffer.LoopLength = instance->parent.staticSound->loopLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
instance->parent.staticSound->buffer.LoopCount = 0;
|
||||
instance->parent.staticSound->buffer.LoopBegin = 0;
|
||||
instance->parent.staticSound->buffer.LoopLength = 0;
|
||||
}
|
||||
|
||||
FAudioSourceVoice_SubmitSourceBuffer(instance->handle, &instance->parent.staticSound->buffer, NULL);
|
||||
FAudioSourceVoice_Start(instance->handle, 0, 0);
|
||||
instance->soundState = SoundState_Playing;
|
||||
}
|
||||
}
|
||||
|
||||
void FAudioGMS_StaticSound_PlayOneOff(double staticSoundID, double pan, double pitch, double volume, double reverb)
|
||||
{
|
||||
FAudioGMS_StaticSound* staticSound = device->staticSounds[(uint32_t)staticSoundID];
|
||||
|
||||
if (staticSound != NULL)
|
||||
{
|
||||
FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_SoundInstance_CreateFromStaticSound(staticSound, pan, pitch, volume, reverb);
|
||||
instance->destroyOnFinish = 1;
|
||||
FAudioGMS_INTERNAL_SoundInstance_Play(instance);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("StaticSound_PlayOneOff: Invalid static sound ID! Did you destroy this sound?");
|
||||
}
|
||||
}
|
||||
|
||||
double FAudioGMS_StaticSound_Play(double staticSoundID, double pan, double pitch, double volume, double reverb, double loop)
|
||||
{
|
||||
FAudioGMS_StaticSound* staticSound = device->staticSounds[(uint32_t)staticSoundID];
|
||||
|
||||
if (staticSound != NULL)
|
||||
{
|
||||
FAudioGMS_SoundInstance* instance = FAudioGMS_INTERNAL_SoundInstance_CreateFromStaticSound(staticSound, pan, pitch, volume, reverb);
|
||||
instance->loop = (uint8_t)loop;
|
||||
FAudioGMS_INTERNAL_SoundInstance_Play(instance);
|
||||
return (double)instance->id;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("StaticSound_Play: Invalid static sound ID! Did you destroy this sound?");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void FAudioGMS_SoundInstance_Play(double id)
|
||||
{
|
||||
FAudioGMS_SoundInstance *instance = device->soundInstances[(uint32_t)id];
|
||||
|
||||
if (instance != NULL)
|
||||
{
|
||||
FAudioVoice_DestroyVoice(instance->handle);
|
||||
free(instance->dspSettings.pMatrixCoefficients);
|
||||
free(instance);
|
||||
device->staticSoundInstances[(uint32_t)id] = NULL;
|
||||
FAudioGMS_INTERNAL_SoundInstance_Play(instance);
|
||||
}
|
||||
}
|
||||
|
||||
void FAudioGMS_StaticSound_Destroy(double id)
|
||||
void FAudioGMS_SoundInstance_Pause(double id)
|
||||
{
|
||||
FAudioGMS_StaticSound *sound = device->staticSounds[(uint32_t)id];
|
||||
FAudioGMS_SoundInstance* instance = device->soundInstances[(uint32_t)id];
|
||||
|
||||
if (sound != NULL)
|
||||
if (instance != NULL)
|
||||
{
|
||||
free((void*)sound->buffer.pAudioData);
|
||||
free(sound);
|
||||
device->staticSounds[(uint32_t)id] = NULL;
|
||||
if (instance->isStatic)
|
||||
{
|
||||
if (instance->soundState == SoundState_Playing)
|
||||
{
|
||||
FAudioSourceVoice_Stop(instance->handle, 0, 0);
|
||||
instance->soundState = SoundState_Paused;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("SoundInstance_Pause: Invalid sound instance ID! Did you destroy this instance?");
|
||||
}
|
||||
}
|
||||
|
||||
void FAudioGMS_SoundInstance_Stop(double id)
|
||||
{
|
||||
FAudioGMS_SoundInstance* instance = device->soundInstances[(uint32_t)id];
|
||||
|
||||
if (instance != NULL)
|
||||
{
|
||||
if (instance->isStatic)
|
||||
{
|
||||
FAudioSourceVoice_ExitLoop(instance->handle, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("SoundInstance_Stop: Invalid sound instance ID! Did you destroy this instance?");
|
||||
}
|
||||
}
|
||||
|
||||
void FAudioGMS_Destroy()
|
||||
{
|
||||
FAudio_Release(device->handle);
|
||||
free(device);
|
||||
device = NULL;
|
||||
uint32_t i = 0;
|
||||
for (i = 0; i < device->staticSoundCount; i += 1)
|
||||
{
|
||||
FAudioGMS_INTERNAL_StaticSound_Destroy(device->staticSounds[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < device->soundInstanceCount; i += 1)
|
||||
{
|
||||
FAudioGMS_INTERNAL_SoundInstance_Destroy(device->soundInstances[i]);
|
||||
}
|
||||
|
||||
FAudio_Release(device->handle);
|
||||
SDL_free(device);
|
||||
device = NULL;
|
||||
|
||||
Log("FAudio cleaned up successfully!");
|
||||
}
|
||||
|
|
|
@ -27,10 +27,6 @@
|
|||
#ifndef FAUDIOGMS_H
|
||||
#define FAUDIOGMS_H
|
||||
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define FAUDIOGMSAPI __declspec(dllexport)
|
||||
#define FAUDIOGMSCALL __cdecl
|
||||
|
@ -46,11 +42,16 @@ extern "C" {
|
|||
FAUDIOGMSAPI void FAudioGMS_Init();
|
||||
FAUDIOGMSAPI void FAudioGMS_Update();
|
||||
|
||||
FAUDIOGMSAPI double FAudioGMS_StaticSound_LoadWAV(char *filePath);
|
||||
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 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_SoundInstance_CreateFromStaticSound(double id);
|
||||
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_Destroy(double id);
|
||||
FAUDIOGMSAPI void FAudioGMS_SoundInstance_DestroyWhenFinished(double id);
|
||||
FAUDIOGMSAPI void FAudioGMS_StaticSound_Destroy(double id);
|
||||
FAUDIOGMSAPI void FAudioGMS_Destroy();
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FAudioGMS", "FAudioGMS.vcxp
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FAudio", "..\lib\FAudio\visualc\FAudio.vcxproj", "{90A103EF-E403-47D4-BBBB-0F206B9FA7F2}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL2", "..\lib\SDL\VisualC\SDL\SDL.vcxproj", "{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
|
@ -53,6 +55,22 @@ Global
|
|||
{90A103EF-E403-47D4-BBBB-0F206B9FA7F2}.RelWithDebInfo|x64.Build.0 = Release|x64
|
||||
{90A103EF-E403-47D4-BBBB-0F206B9FA7F2}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
|
||||
{90A103EF-E403-47D4-BBBB-0F206B9FA7F2}.RelWithDebInfo|x86.Build.0 = Release|Win32
|
||||
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|x64.Build.0 = Debug|x64
|
||||
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Debug|x86.Build.0 = Debug|Win32
|
||||
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.MinSizeRel|x64.ActiveCfg = Debug|x64
|
||||
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.MinSizeRel|x64.Build.0 = Debug|x64
|
||||
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.MinSizeRel|x86.ActiveCfg = Debug|Win32
|
||||
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.MinSizeRel|x86.Build.0 = Debug|Win32
|
||||
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|x64.ActiveCfg = Release|x64
|
||||
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|x64.Build.0 = Release|x64
|
||||
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|x86.ActiveCfg = Release|Win32
|
||||
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.Release|x86.Build.0 = Release|Win32
|
||||
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.RelWithDebInfo|x64.ActiveCfg = Release|x64
|
||||
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.RelWithDebInfo|x64.Build.0 = Release|x64
|
||||
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.RelWithDebInfo|x86.ActiveCfg = Release|Win32
|
||||
{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}.RelWithDebInfo|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -68,10 +68,18 @@
|
|||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<LanguageStandard_C Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Default</LanguageStandard_C>
|
||||
<RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<FunctionLevelLinking Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</FunctionLevelLinking>
|
||||
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
|
||||
<SubSystem Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotSet</SubSystem>
|
||||
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">SetupAPI.lib;Version.lib;Winmm.lib;Imm32.lib;libucrt.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<ProjectReference>
|
||||
<UseLibraryDependencyInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</UseLibraryDependencyInputs>
|
||||
</ProjectReference>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||
<ClCompile>
|
||||
|
@ -83,6 +91,7 @@
|
|||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|x64'">SetupAPI.lib;Version.lib;Winmm.lib;Imm32.lib;libucrt.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
|
@ -95,6 +104,9 @@
|
|||
<ProjectReference Include="..\lib\FAudio\visualc\FAudio.vcxproj">
|
||||
<Project>{90a103ef-e403-47d4-bbbb-0f206b9fa7f2}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\lib\SDL\VisualC\SDL\SDL.vcxproj">
|
||||
<Project>{81ce8daf-ebb2-4761-8e45-b71abcca8c68}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
|
Loading…
Reference in New Issue