Add a new ALsoundfont object type
Includes a basic hierarchy for presets, instruments, samples, zones, generators, and modulators.
This commit is contained in:
@@ -280,6 +280,8 @@ static const ALCfunction alcFunctions[] = {
|
||||
DECL(alGetSource3i64SOFT),
|
||||
DECL(alGetSourcei64vSOFT),
|
||||
|
||||
DECL(alGenSoundfontsSOFT),
|
||||
DECL(alDeleteSoundfontsSOFT),
|
||||
DECL(alIsSoundfontSOFT),
|
||||
DECL(alMidiSoundfontSOFT),
|
||||
DECL(alMidiEventSOFT),
|
||||
|
||||
+286
-74
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "midi/base.h"
|
||||
|
||||
#include "alMidi.h"
|
||||
#include "alMain.h"
|
||||
#include "alError.h"
|
||||
#include "evtqueue.h"
|
||||
@@ -22,6 +23,100 @@
|
||||
#define SYSEX_EVENT (0xF0)
|
||||
|
||||
|
||||
void InitEvtQueue(EvtQueue *queue)
|
||||
{
|
||||
queue->events = NULL;
|
||||
queue->maxsize = 0;
|
||||
queue->size = 0;
|
||||
queue->pos = 0;
|
||||
}
|
||||
|
||||
void ResetEvtQueue(EvtQueue *queue)
|
||||
{
|
||||
ALsizei i;
|
||||
for(i = 0;i < queue->size;i++)
|
||||
{
|
||||
if(queue->events[i].event == SYSEX_EVENT)
|
||||
{
|
||||
free(queue->events[i].param.sysex.data);
|
||||
queue->events[i].param.sysex.data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
free(queue->events);
|
||||
queue->events = NULL;
|
||||
queue->maxsize = 0;
|
||||
queue->size = 0;
|
||||
queue->pos = 0;
|
||||
}
|
||||
|
||||
ALenum InsertEvtQueue(EvtQueue *queue, const MidiEvent *evt)
|
||||
{
|
||||
ALsizei pos;
|
||||
|
||||
if(queue->maxsize == queue->size)
|
||||
{
|
||||
if(queue->pos > 0)
|
||||
{
|
||||
/* Queue has some stale entries, remove them to make space for more
|
||||
* events. */
|
||||
for(pos = 0;pos < queue->pos;pos++)
|
||||
{
|
||||
if(queue->events[pos].event == SYSEX_EVENT)
|
||||
{
|
||||
free(queue->events[pos].param.sysex.data);
|
||||
queue->events[pos].param.sysex.data = NULL;
|
||||
}
|
||||
}
|
||||
memmove(&queue->events[0], &queue->events[queue->pos],
|
||||
(queue->size-queue->pos)*sizeof(queue->events[0]));
|
||||
queue->size -= queue->pos;
|
||||
queue->pos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Queue is full, double the allocated space. */
|
||||
void *temp = NULL;
|
||||
ALsizei newsize;
|
||||
|
||||
newsize = (queue->maxsize ? (queue->maxsize<<1) : 16);
|
||||
if(newsize > queue->maxsize)
|
||||
temp = realloc(queue->events, newsize * sizeof(queue->events[0]));
|
||||
if(!temp)
|
||||
return AL_OUT_OF_MEMORY;
|
||||
|
||||
queue->events = temp;
|
||||
queue->maxsize = newsize;
|
||||
}
|
||||
}
|
||||
|
||||
pos = queue->pos;
|
||||
if(queue->size > 0)
|
||||
{
|
||||
ALsizei high = queue->size - 1;
|
||||
while(pos < high)
|
||||
{
|
||||
ALsizei mid = pos + (high-pos)/2;
|
||||
if(queue->events[mid].time < evt->time)
|
||||
pos = mid + 1;
|
||||
else
|
||||
high = mid;
|
||||
}
|
||||
while(pos < queue->size && queue->events[pos].time <= evt->time)
|
||||
pos++;
|
||||
|
||||
if(pos < queue->size)
|
||||
memmove(&queue->events[pos+1], &queue->events[pos],
|
||||
(queue->size-pos)*sizeof(queue->events[0]));
|
||||
}
|
||||
|
||||
queue->events[pos] = *evt;
|
||||
queue->size++;
|
||||
|
||||
return AL_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
void MidiSynth_Construct(MidiSynth *self, ALCdevice *device)
|
||||
{
|
||||
InitEvtQueue(&self->EventQueue);
|
||||
@@ -147,95 +242,212 @@ ALenum MidiSynth_insertSysExEvent(MidiSynth *self, ALuint64 time, const ALbyte *
|
||||
}
|
||||
|
||||
|
||||
void InitEvtQueue(EvtQueue *queue)
|
||||
void ALsfzone_Construct(ALsfzone *self)
|
||||
{
|
||||
queue->events = NULL;
|
||||
queue->maxsize = 0;
|
||||
queue->size = 0;
|
||||
queue->pos = 0;
|
||||
self->Generators = NULL;
|
||||
self->NumGenerators = 0;
|
||||
self->GeneratorsMax = 0;
|
||||
|
||||
self->Modulators = NULL;
|
||||
self->NumModulators = 0;
|
||||
self->ModulatorsMax = 0;
|
||||
|
||||
self->Object = NULL;
|
||||
}
|
||||
|
||||
void ResetEvtQueue(EvtQueue *queue)
|
||||
void ALsfzone_Destruct(ALsfzone *self)
|
||||
{
|
||||
self->Object = NULL;
|
||||
|
||||
free(self->Modulators);
|
||||
self->Modulators = NULL;
|
||||
self->NumModulators = 0;
|
||||
self->ModulatorsMax = 0;
|
||||
|
||||
free(self->Generators);
|
||||
self->Generators = NULL;
|
||||
self->NumGenerators = 0;
|
||||
self->GeneratorsMax = 0;
|
||||
}
|
||||
|
||||
ALenum ALsfzone_addGenerator(ALsfzone *self, ALenum generator, ALint value)
|
||||
{
|
||||
ALsizei i;
|
||||
for(i = 0;i < queue->size;i++)
|
||||
for(i = 0;i < self->NumGenerators;i++)
|
||||
{
|
||||
if(queue->events[i].event == SYSEX_EVENT)
|
||||
if(self->Generators[i].Generator == generator)
|
||||
{
|
||||
free(queue->events[i].param.sysex.data);
|
||||
queue->events[i].param.sysex.data = NULL;
|
||||
self->Generators[i].Value = value;
|
||||
return AL_NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
free(queue->events);
|
||||
queue->events = NULL;
|
||||
queue->maxsize = 0;
|
||||
queue->size = 0;
|
||||
queue->pos = 0;
|
||||
}
|
||||
|
||||
ALenum InsertEvtQueue(EvtQueue *queue, const MidiEvent *evt)
|
||||
{
|
||||
ALsizei pos;
|
||||
|
||||
if(queue->maxsize == queue->size)
|
||||
if(self->NumGenerators == self->GeneratorsMax)
|
||||
{
|
||||
if(queue->pos > 0)
|
||||
{
|
||||
/* Queue has some stale entries, remove them to make space for more
|
||||
* events. */
|
||||
for(pos = 0;pos < queue->pos;pos++)
|
||||
{
|
||||
if(queue->events[pos].event == SYSEX_EVENT)
|
||||
{
|
||||
free(queue->events[pos].param.sysex.data);
|
||||
queue->events[pos].param.sysex.data = NULL;
|
||||
}
|
||||
}
|
||||
memmove(&queue->events[0], &queue->events[queue->pos],
|
||||
(queue->size-queue->pos)*sizeof(queue->events[0]));
|
||||
queue->size -= queue->pos;
|
||||
queue->pos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Queue is full, double the allocated space. */
|
||||
void *temp = NULL;
|
||||
ALsizei newsize;
|
||||
ALsizei newmax = 0;
|
||||
ALvoid *temp = NULL;
|
||||
|
||||
newsize = (queue->maxsize ? (queue->maxsize<<1) : 16);
|
||||
if(newsize > queue->maxsize)
|
||||
temp = realloc(queue->events, newsize * sizeof(queue->events[0]));
|
||||
if(!temp)
|
||||
return AL_OUT_OF_MEMORY;
|
||||
newmax = (self->GeneratorsMax ? self->GeneratorsMax<<1 : 1);
|
||||
if(newmax > self->GeneratorsMax)
|
||||
temp = realloc(self->Generators, newmax * sizeof(ALsfgenerator));
|
||||
if(!temp) return AL_OUT_OF_MEMORY;
|
||||
|
||||
queue->events = temp;
|
||||
queue->maxsize = newsize;
|
||||
}
|
||||
self->Generators = temp;
|
||||
self->GeneratorsMax = newmax;
|
||||
}
|
||||
|
||||
pos = queue->pos;
|
||||
if(queue->size > 0)
|
||||
{
|
||||
ALsizei high = queue->size - 1;
|
||||
while(pos < high)
|
||||
{
|
||||
ALsizei mid = pos + (high-pos)/2;
|
||||
if(queue->events[mid].time < evt->time)
|
||||
pos = mid + 1;
|
||||
else
|
||||
high = mid;
|
||||
}
|
||||
while(pos < queue->size && queue->events[pos].time <= evt->time)
|
||||
pos++;
|
||||
|
||||
if(pos < queue->size)
|
||||
memmove(&queue->events[pos+1], &queue->events[pos],
|
||||
(queue->size-pos)*sizeof(queue->events[0]));
|
||||
}
|
||||
|
||||
queue->events[pos] = *evt;
|
||||
queue->size++;
|
||||
self->Generators[self->NumGenerators].Generator = generator;
|
||||
self->Generators[self->NumGenerators].Value = value;
|
||||
self->NumGenerators++;
|
||||
|
||||
return AL_NO_ERROR;
|
||||
}
|
||||
|
||||
ALenum ALsfzone_addModulator(ALsfzone *self, ALenum sourceop, ALenum destop, ALint amount, ALenum amtsourceop, ALenum transop)
|
||||
{
|
||||
ALsizei i;
|
||||
for(i = 0;i < self->NumModulators;i++)
|
||||
{
|
||||
if(self->Modulators[i].SourceOp == sourceop && self->Modulators[i].DestOp == destop &&
|
||||
self->Modulators[i].AmountSourceOp == amtsourceop &&
|
||||
self->Modulators[i].TransformOp == transop)
|
||||
{
|
||||
self->Modulators[i].Amount = amount;
|
||||
return AL_NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if(self->NumModulators == self->ModulatorsMax)
|
||||
{
|
||||
ALsizei newmax = 0;
|
||||
ALvoid *temp = NULL;
|
||||
|
||||
newmax = (self->ModulatorsMax ? self->ModulatorsMax<<1 : 1);
|
||||
if(newmax > self->ModulatorsMax)
|
||||
temp = realloc(self->Modulators, newmax * sizeof(ALsfmodulator));
|
||||
if(!temp) return AL_OUT_OF_MEMORY;
|
||||
|
||||
self->Modulators = temp;
|
||||
self->ModulatorsMax = newmax;
|
||||
}
|
||||
|
||||
self->Modulators[self->NumModulators].SourceOp = sourceop;
|
||||
self->Modulators[self->NumModulators].DestOp = destop;
|
||||
self->Modulators[self->NumModulators].Amount = amount;
|
||||
self->Modulators[self->NumModulators].AmountSourceOp = amtsourceop;
|
||||
self->Modulators[self->NumModulators].TransformOp = transop;
|
||||
self->NumModulators++;
|
||||
|
||||
return AL_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Stores a new object pointer in the zone. Returns the old object pointer. */
|
||||
ALvoid *ALsfzone_setRefObject(ALsfzone *self, ALvoid *object)
|
||||
{
|
||||
ALvoid *oldobj = self->Object;
|
||||
self->Object = object;
|
||||
return oldobj;
|
||||
}
|
||||
|
||||
|
||||
void ALsfsample_Construct(ALsfsample *self)
|
||||
{
|
||||
self->ref = 0;
|
||||
|
||||
self->id = 0;
|
||||
}
|
||||
|
||||
void ALsfsample_Destruct(ALsfsample *self)
|
||||
{
|
||||
self->id = 0;
|
||||
}
|
||||
|
||||
|
||||
void ALsfinstrument_Construct(ALsfinstrument *self)
|
||||
{
|
||||
self->ref = 0;
|
||||
|
||||
self->Zones = NULL;
|
||||
self->NumZones = 0;
|
||||
|
||||
self->id = 0;
|
||||
}
|
||||
|
||||
void ALsfinstrument_Destruct(ALsfinstrument *self)
|
||||
{
|
||||
ALsizei i;
|
||||
|
||||
self->id = 0;
|
||||
|
||||
for(i = 0;i < self->NumZones;i++)
|
||||
{
|
||||
if(self->Zones[i].Object)
|
||||
DecrementRef(&((ALsfsample*)self->Zones[i].Object)->ref);
|
||||
ALsfzone_Destruct(&self->Zones[i]);
|
||||
}
|
||||
free(self->Zones);
|
||||
self->Zones = NULL;
|
||||
self->NumZones = 0;
|
||||
}
|
||||
|
||||
|
||||
void ALsfpreset_Construct(ALsfpreset *self)
|
||||
{
|
||||
self->ref = 0;
|
||||
|
||||
self->Zones = NULL;
|
||||
self->NumZones = 0;
|
||||
|
||||
self->id = 0;
|
||||
}
|
||||
|
||||
void ALsfpreset_Destruct(ALsfpreset *self)
|
||||
{
|
||||
ALsizei i;
|
||||
|
||||
self->id = 0;
|
||||
|
||||
for(i = 0;i < self->NumZones;i++)
|
||||
{
|
||||
if(self->Zones[i].Object)
|
||||
DecrementRef(&((ALsfinstrument*)self->Zones[i].Object)->ref);
|
||||
ALsfzone_Destruct(&self->Zones[i]);
|
||||
}
|
||||
free(self->Zones);
|
||||
self->Zones = NULL;
|
||||
self->NumZones = 0;
|
||||
}
|
||||
|
||||
|
||||
void ALsoundfont_Construct(ALsoundfont *self)
|
||||
{
|
||||
self->ref = 0;
|
||||
|
||||
self->Presets = NULL;
|
||||
self->NumPresets = 0;
|
||||
|
||||
self->SampleData = NULL;
|
||||
self->SampleDataLen = 0;
|
||||
|
||||
self->id = 0;
|
||||
}
|
||||
|
||||
void ALsoundfont_Destruct(ALsoundfont *self)
|
||||
{
|
||||
ALsizei i;
|
||||
|
||||
self->id = 0;
|
||||
|
||||
for(i = 0;i < self->NumPresets;i++)
|
||||
{
|
||||
DecrementRef(&self->Presets[i]->ref);
|
||||
self->Presets[i] = NULL;
|
||||
}
|
||||
free(self->Presets);
|
||||
self->Presets = NULL;
|
||||
self->NumPresets = 0;
|
||||
|
||||
free(self->SampleData);
|
||||
self->SampleData = NULL;
|
||||
self->SampleDataLen = 0;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
#define AL_PROGRAMCHANGE_SOFT 0x00C0
|
||||
#define AL_CHANNELPRESSURE_SOFT 0x00D0
|
||||
#define AL_PITCHBEND_SOFT 0x00E0
|
||||
typedef void (AL_APIENTRY*LPALGENSOUNDFONTSSOFT)(ALsizei n, ALuint *ids);
|
||||
typedef void (AL_APIENTRY*LPALDELETESOUNDFONTSSOFT)(ALsizei n, const ALuint *ids);
|
||||
typedef ALboolean (AL_APIENTRY*LPALISSOUNDFONTSOFT)(const char *filename);
|
||||
typedef void (AL_APIENTRY*LPALMIDISOUNDFONTSOFT)(const char *filename);
|
||||
typedef void (AL_APIENTRY*LPALMIDIEVENTSOFT)(ALuint64SOFT time, ALenum event, ALsizei channel, ALsizei param1, ALsizei param2);
|
||||
@@ -50,6 +52,8 @@ typedef void (AL_APIENTRY*LPALMIDIGAINSOFT)(ALfloat value);
|
||||
typedef ALint64SOFT (AL_APIENTRY*LPALGETINTEGER64SOFT)(ALenum pname);
|
||||
typedef void (AL_APIENTRY*LPALGETINTEGER64VSOFT)(ALenum pname, ALint64SOFT *values);
|
||||
#ifdef AL_ALEXT_PROTOTYPES
|
||||
AL_API void AL_APIENTRY alGenSoundfontsSOFT(ALsizei n, ALuint *ids);
|
||||
AL_API void AL_APIENTRY alDeleteSoundfontsSOFT(ALsizei n, const ALuint *ids);
|
||||
AL_API ALboolean AL_APIENTRY alIsSoundfontSOFT(const char *filename);
|
||||
AL_API void AL_APIENTRY alMidiSoundfontSOFT(const char *filename);
|
||||
AL_API void AL_APIENTRY alMidiEventSOFT(ALuint64SOFT time, ALenum event, ALsizei channel, ALsizei param1, ALsizei param2);
|
||||
@@ -424,6 +428,9 @@ struct ALCdevice_struct
|
||||
// Map of Filters for this device
|
||||
UIntMap FilterMap;
|
||||
|
||||
// Map of Soundfonts for this device
|
||||
UIntMap SfontMap;
|
||||
|
||||
/* MIDI synth engine */
|
||||
struct MidiSynth *Synth;
|
||||
|
||||
|
||||
@@ -8,6 +8,111 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct ALsfgenerator {
|
||||
ALenum Generator;
|
||||
ALint Value;
|
||||
} ALsfgenerator;
|
||||
|
||||
typedef struct ALsfmodulator {
|
||||
ALenum SourceOp;
|
||||
ALenum DestOp;
|
||||
ALint Amount;
|
||||
ALenum AmountSourceOp;
|
||||
ALenum TransformOp;
|
||||
} ALsfmodulator;
|
||||
|
||||
typedef struct ALsfzone {
|
||||
ALsfgenerator *Generators;
|
||||
ALsizei NumGenerators;
|
||||
ALsizei GeneratorsMax;
|
||||
|
||||
ALsfmodulator *Modulators;
|
||||
ALsizei NumModulators;
|
||||
ALsizei ModulatorsMax;
|
||||
|
||||
/* NOTE: Preset zones may have a reference to an ALsfinstrument. Instrument
|
||||
* zones may have a reference to an ALsfsample. */
|
||||
ALvoid *Object;
|
||||
} ALsfzone;
|
||||
|
||||
void ALsfzone_Construct(ALsfzone *self);
|
||||
void ALsfzone_Destruct(ALsfzone *self);
|
||||
ALenum ALsfzone_addGenerator(ALsfzone *self, ALenum generator, ALint value);
|
||||
ALenum ALsfzone_addModulator(ALsfzone *self, ALenum sourceop, ALenum destop, ALint amount, ALenum amtsourceop, ALenum transop);
|
||||
/* Stores a new object pointer in the zone. Returns the old object pointer. */
|
||||
ALvoid *ALsfzone_setRefObject(ALsfzone *self, ALvoid *object);
|
||||
|
||||
|
||||
typedef struct ALsfsample {
|
||||
volatile RefCount ref;
|
||||
|
||||
ALuint Start;
|
||||
ALuint End;
|
||||
ALuint LoopStart;
|
||||
ALuint LoopEnd;
|
||||
ALuint SampleRate;
|
||||
ALubyte PitchKey;
|
||||
ALbyte PitchCorrection;
|
||||
ALushort SampleLink;
|
||||
ALenum SampleType;
|
||||
|
||||
ALuint id;
|
||||
} ALsfsample;
|
||||
|
||||
void ALsfsample_Construct(ALsfsample *self);
|
||||
void ALsfsample_Destruct(ALsfsample *self);
|
||||
|
||||
|
||||
typedef struct ALsfinstrument {
|
||||
volatile RefCount ref;
|
||||
|
||||
ALsfzone *Zones;
|
||||
ALsizei NumZones;
|
||||
|
||||
ALuint id;
|
||||
} ALsfinstrument;
|
||||
|
||||
void ALsfinstrument_Construct(ALsfinstrument *self);
|
||||
void ALsfinstrument_Destruct(ALsfinstrument *self);
|
||||
|
||||
|
||||
typedef struct ALsfpreset {
|
||||
volatile RefCount ref;
|
||||
|
||||
ALint Program;
|
||||
ALint Bank;
|
||||
|
||||
ALsfzone *Zones;
|
||||
ALsizei NumZones;
|
||||
|
||||
ALuint id;
|
||||
} ALsfpreset;
|
||||
|
||||
void ALsfpreset_Construct(ALsfpreset *self);
|
||||
void ALsfpreset_Destruct(ALsfpreset *self);
|
||||
|
||||
|
||||
typedef struct ALsoundfont {
|
||||
volatile RefCount ref;
|
||||
|
||||
ALsfpreset **Presets;
|
||||
ALsizei NumPresets;
|
||||
|
||||
ALshort *SampleData;
|
||||
ALint SampleDataLen;
|
||||
|
||||
ALuint id;
|
||||
} ALsoundfont;
|
||||
|
||||
void ALsoundfont_Construct(ALsoundfont *self);
|
||||
void ALsoundfont_Destruct(ALsoundfont *self);
|
||||
|
||||
inline struct ALsoundfont *LookupSfont(ALCdevice *device, ALuint id)
|
||||
{ return (struct ALsoundfont*)LookupUIntMapKey(&device->SfontMap, id); }
|
||||
inline struct ALsoundfont *RemoveSfont(ALCdevice *device, ALuint id)
|
||||
{ return (struct ALsoundfont*)RemoveUIntMapKey(&device->SfontMap, id); }
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
#include <limits.h>
|
||||
|
||||
#include "alMain.h"
|
||||
#include "alMidi.h"
|
||||
#include "alError.h"
|
||||
#include "alThunk.h"
|
||||
#include "evtqueue.h"
|
||||
#include "rwlock.h"
|
||||
#include "alu.h"
|
||||
@@ -23,6 +25,97 @@ MidiSynth *SynthCreate(ALCdevice *device)
|
||||
}
|
||||
|
||||
|
||||
extern inline struct ALsoundfont *LookupSfont(ALCdevice *device, ALuint id);
|
||||
extern inline struct ALsoundfont *RemoveSfont(ALCdevice *device, ALuint id);
|
||||
|
||||
|
||||
AL_API void AL_APIENTRY alGenSoundfontsSOFT(ALsizei n, ALuint *ids)
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
ALsizei cur = 0;
|
||||
ALenum err;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
if(!(n >= 0))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
device = context->Device;
|
||||
for(cur = 0;cur < n;cur++)
|
||||
{
|
||||
ALsoundfont *sfont = calloc(1, sizeof(ALsoundfont));
|
||||
if(!sfont)
|
||||
{
|
||||
alDeleteSoundfontsSOFT(cur, ids);
|
||||
SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
|
||||
}
|
||||
ALsoundfont_Construct(sfont);
|
||||
|
||||
err = NewThunkEntry(&sfont->id);
|
||||
if(err == AL_NO_ERROR)
|
||||
err = InsertUIntMapEntry(&device->SfontMap, sfont->id, sfont);
|
||||
if(err != AL_NO_ERROR)
|
||||
{
|
||||
FreeThunkEntry(sfont->id);
|
||||
memset(sfont, 0, sizeof(ALsoundfont));
|
||||
free(sfont);
|
||||
|
||||
alDeleteSoundfontsSOFT(cur, ids);
|
||||
SET_ERROR_AND_GOTO(context, err, done);
|
||||
}
|
||||
|
||||
ids[cur] = sfont->id;
|
||||
}
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alDeleteSoundfontsSOFT(ALsizei n, const ALuint *ids)
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
ALsoundfont *sfont;
|
||||
ALsizei i;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
if(!(n >= 0))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
device = context->Device;
|
||||
for(i = 0;i < n;i++)
|
||||
{
|
||||
if(!ids[i])
|
||||
continue;
|
||||
|
||||
/* Check for valid soundfont ID */
|
||||
if((sfont=LookupSfont(device, ids[i])) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
if(sfont->ref != 0)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
|
||||
}
|
||||
|
||||
for(i = 0;i < n;i++)
|
||||
{
|
||||
if((sfont=RemoveSfont(device, ids[i])) == NULL)
|
||||
continue;
|
||||
FreeThunkEntry(sfont->id);
|
||||
|
||||
ALsoundfont_Destruct(sfont);
|
||||
|
||||
memset(sfont, 0, sizeof(*sfont));
|
||||
free(sfont);
|
||||
}
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
|
||||
AL_API ALboolean AL_APIENTRY alIsSoundfontSOFT(const char *filename)
|
||||
{
|
||||
ALCdevice *device;
|
||||
|
||||
Reference in New Issue
Block a user