aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2014-06-29 00:47:29 -0700
committerChris Robinson <[email protected]>2014-06-29 00:47:29 -0700
commit389a2f7b4bcffa5cfbe17e8057c8541b0e442bf8 (patch)
tree238deea1698705473073b3aafd0494c08c9dd1f2
parentd19e42a723231d63da777d51a3b036683b42e702 (diff)
Store and use an ALbuffer for samples in an ALfontsound
The fontsound still maintains its own start, end, and loop offsets, so that the same buffer may be shared between multiple/all fontsounds. Ideally a single buffer should be used for all fontsounds to avoid memory fragmentation and help CPU caching, although higher quality soundfonts may need more memory than a single buffer can hold.
-rw-r--r--Alc/midi/fluidsynth.c8
-rw-r--r--OpenAL32/Include/alMidi.h2
-rw-r--r--OpenAL32/alFontsound.c27
3 files changed, 34 insertions, 3 deletions
diff --git a/Alc/midi/fluidsynth.c b/Alc/midi/fluidsynth.c
index b4788635..d10c1be8 100644
--- a/Alc/midi/fluidsynth.c
+++ b/Alc/midi/fluidsynth.c
@@ -144,7 +144,7 @@ typedef struct FSample {
ALsizei NumMods;
} FSample;
-static void FSample_Construct(FSample *self, ALfontsound *sound, ALsoundfont *sfont)
+static void FSample_Construct(FSample *self, ALfontsound *sound)
{
fluid_sample_t *sample = STATIC_CAST(fluid_sample_t, self);
memset(sample->name, 0, sizeof(sample->name));
@@ -157,7 +157,7 @@ static void FSample_Construct(FSample *self, ALfontsound *sound, ALsoundfont *sf
sample->pitchadj = sound->PitchCorrection;
sample->sampletype = getSampleType(sound->SampleType);
sample->valid = 1;
- sample->data = sfont->Samples;
+ sample->data = sound->Buffer ? sound->Buffer->data : NULL;
sample->amplitude_that_reaches_noise_floor_is_valid = 0;
sample->amplitude_that_reaches_noise_floor = 0.0;
@@ -240,7 +240,7 @@ static void FPreset_Construct(FPreset *self, ALsfpreset *preset, fluid_sfont_t *
ALsizei i;
self->NumSamples = preset->NumSounds;
for(i = 0;i < self->NumSamples;i++)
- FSample_Construct(&self->Samples[i], preset->Sounds[i], sfont);
+ FSample_Construct(&self->Samples[i], preset->Sounds[i]);
}
}
@@ -294,6 +294,8 @@ static int FPreset_noteOn(fluid_preset_t *preset, fluid_synth_t *synth, int chan
fluid_voice_t *voice;
ALsizei m;
+ if(!STATIC_CAST(fluid_sample_t, sample)->data)
+ continue;
if(!(key >= sound->MinKey && key <= sound->MaxKey && vel >= sound->MinVelocity && vel <= sound->MaxVelocity))
continue;
diff --git a/OpenAL32/Include/alMidi.h b/OpenAL32/Include/alMidi.h
index d18c165e..7fdd3f9b 100644
--- a/OpenAL32/Include/alMidi.h
+++ b/OpenAL32/Include/alMidi.h
@@ -34,6 +34,8 @@ typedef struct ALenvelope {
typedef struct ALfontsound {
RefCount ref;
+ struct ALbuffer *Buffer;
+
ALint MinKey, MaxKey;
ALint MinVelocity, MaxVelocity;
diff --git a/OpenAL32/alFontsound.c b/OpenAL32/alFontsound.c
index c4d49e92..80a7562e 100644
--- a/OpenAL32/alFontsound.c
+++ b/OpenAL32/alFontsound.c
@@ -8,6 +8,7 @@
#include "alMidi.h"
#include "alError.h"
#include "alThunk.h"
+#include "alBuffer.h"
#include "midi/base.h"
@@ -257,6 +258,10 @@ AL_API void AL_APIENTRY alGetFontsoundivSOFT(ALuint id, ALenum param, ALint *val
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
switch(param)
{
+ case AL_BUFFER:
+ values[0] = (sound->Buffer ? sound->Buffer->id : 0);
+ break;
+
case AL_MOD_LFO_TO_PITCH_SOFT:
values[0] = sound->ModLfoToPitch;
break;
@@ -510,6 +515,8 @@ static void ALfontsound_Construct(ALfontsound *self)
{
InitRef(&self->ref, 0);
+ self->Buffer = NULL;
+
self->MinKey = 0;
self->MaxKey = 127;
self->MinVelocity = 0;
@@ -587,6 +594,9 @@ void ALfontsound_Destruct(ALfontsound *self)
FreeThunkEntry(self->id);
self->id = 0;
+ if(self->Buffer)
+ DecrementRef(&self->Buffer->ref);
+ self->Buffer = NULL;
if(self->Link)
DecrementRef(&self->Link->ref);
self->Link = NULL;
@@ -602,9 +612,26 @@ void ALfontsound_Destruct(ALfontsound *self)
void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param, ALint value)
{
ALfontsound *link;
+ ALbuffer *buffer;
switch(param)
{
+ case AL_BUFFER:
+ buffer = value ? LookupBuffer(context->Device, value) : NULL;
+ if(value && !buffer)
+ SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+ else if(buffer)
+ {
+ /* Buffer must have a non-0 length, and must be mono. */
+ if(buffer->SampleLen <= 0 || buffer->FmtChannels != FmtMono)
+ SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+ }
+
+ if(buffer) IncrementRef(&buffer->ref);
+ if((buffer=ExchangePtr((XchgPtr*)&self->Buffer, buffer)) != NULL)
+ DecrementRef(&buffer->ref);
+ break;
+
case AL_MOD_LFO_TO_PITCH_SOFT:
self->ModLfoToPitch = value;
break;