Allow "deleting" the default soundfont
The ID remains valid and the soundfont will be reloaded as needed, but this provides a way for the application to clear up the soundfont memory.
This commit is contained in:
parent
bb54743425
commit
540a99e71f
49
Alc/ALc.c
49
Alc/ALc.c
@ -1950,54 +1950,7 @@ static ALCvoid FreeDevice(ALCdevice *device)
|
||||
}
|
||||
|
||||
if(device->DefaultSfont)
|
||||
{
|
||||
ALsoundfont *sfont = device->DefaultSfont;
|
||||
ALsfpreset **presets;
|
||||
ALsizei num_presets;
|
||||
ALsizei i;
|
||||
|
||||
presets = ExchangePtr((XchgPtr*)&sfont->Presets, NULL);
|
||||
num_presets = ExchangeInt(&sfont->NumPresets, 0);
|
||||
|
||||
for(i = 0;i < num_presets;i++)
|
||||
{
|
||||
ALsfpreset *preset = presets[i];
|
||||
ALfontsound **sounds;
|
||||
ALsizei num_sounds;
|
||||
ALboolean deleting;
|
||||
ALsizei j;
|
||||
|
||||
sounds = ExchangePtr((XchgPtr*)&preset->Sounds, NULL);
|
||||
num_sounds = ExchangeInt(&preset->NumSounds, 0);
|
||||
DeletePreset(preset, device);
|
||||
preset = NULL;
|
||||
|
||||
for(j = 0;j < num_sounds;j++)
|
||||
DecrementRef(&sounds[j]->ref);
|
||||
/* Some fontsounds may not be immediately deletable because they're
|
||||
* linked to another fontsound. When those fontsounds are deleted
|
||||
* they should become deletable, so use a loop until all fontsounds
|
||||
* are deleted. */
|
||||
do {
|
||||
deleting = AL_FALSE;
|
||||
for(j = 0;j < num_sounds;j++)
|
||||
{
|
||||
if(sounds[j] && sounds[j]->ref == 0)
|
||||
{
|
||||
deleting = AL_TRUE;
|
||||
RemoveFontsound(device, sounds[j]->id);
|
||||
ALfontsound_Destruct(sounds[j]);
|
||||
free(sounds[j]);
|
||||
sounds[j] = NULL;
|
||||
}
|
||||
}
|
||||
} while(deleting);
|
||||
free(sounds);
|
||||
}
|
||||
|
||||
ALsoundfont_Destruct(sfont);
|
||||
free(sfont);
|
||||
}
|
||||
MidiSynth_deleteSoundfont(device, device->DefaultSfont);
|
||||
device->DefaultSfont = NULL;
|
||||
|
||||
if(device->BufferMap.size > 0)
|
||||
|
@ -188,6 +188,55 @@ ALsoundfont *MidiSynth_getDefSoundfont(ALCcontext *context)
|
||||
return device->DefaultSfont;
|
||||
}
|
||||
|
||||
void MidiSynth_deleteSoundfont(ALCdevice *device, ALsoundfont *sfont)
|
||||
{
|
||||
ALsfpreset **presets;
|
||||
ALsizei num_presets;
|
||||
ALsizei i;
|
||||
|
||||
presets = ExchangePtr((XchgPtr*)&sfont->Presets, NULL);
|
||||
num_presets = ExchangeInt(&sfont->NumPresets, 0);
|
||||
|
||||
for(i = 0;i < num_presets;i++)
|
||||
{
|
||||
ALsfpreset *preset = presets[i];
|
||||
ALfontsound **sounds;
|
||||
ALsizei num_sounds;
|
||||
ALboolean deleting;
|
||||
ALsizei j;
|
||||
|
||||
sounds = ExchangePtr((XchgPtr*)&preset->Sounds, NULL);
|
||||
num_sounds = ExchangeInt(&preset->NumSounds, 0);
|
||||
DeletePreset(preset, device);
|
||||
preset = NULL;
|
||||
|
||||
for(j = 0;j < num_sounds;j++)
|
||||
DecrementRef(&sounds[j]->ref);
|
||||
/* Some fontsounds may not be immediately deletable because they're
|
||||
* linked to another fontsound. When those fontsounds are deleted
|
||||
* they should become deletable, so use a loop until all fontsounds
|
||||
* are deleted. */
|
||||
do {
|
||||
deleting = AL_FALSE;
|
||||
for(j = 0;j < num_sounds;j++)
|
||||
{
|
||||
if(sounds[j] && sounds[j]->ref == 0)
|
||||
{
|
||||
deleting = AL_TRUE;
|
||||
RemoveFontsound(device, sounds[j]->id);
|
||||
ALfontsound_Destruct(sounds[j]);
|
||||
free(sounds[j]);
|
||||
sounds[j] = NULL;
|
||||
}
|
||||
}
|
||||
} while(deleting);
|
||||
free(sounds);
|
||||
}
|
||||
|
||||
ALsoundfont_Destruct(sfont);
|
||||
free(sfont);
|
||||
}
|
||||
|
||||
ALenum MidiSynth_selectSoundfonts(MidiSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids)
|
||||
{
|
||||
ALCdevice *device = context->Device;
|
||||
|
@ -53,6 +53,7 @@ typedef struct MidiSynth {
|
||||
void MidiSynth_Construct(MidiSynth *self, ALCdevice *device);
|
||||
void MidiSynth_Destruct(MidiSynth *self);
|
||||
struct ALsoundfont *MidiSynth_getDefSoundfont(ALCcontext *context);
|
||||
void MidiSynth_deleteSoundfont(ALCdevice *device, struct ALsoundfont *sfont);
|
||||
ALenum MidiSynth_selectSoundfonts(MidiSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids);
|
||||
inline void MidiSynth_setGain(MidiSynth *self, ALfloat gain) { self->Gain = gain; }
|
||||
inline ALfloat MidiSynth_getGain(const MidiSynth *self) { return self->Gain; }
|
||||
|
@ -76,11 +76,13 @@ AL_API ALvoid AL_APIENTRY alDeleteSoundfontsSOFT(ALsizei n, const ALuint *ids)
|
||||
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)
|
||||
if(ids[i] == 0)
|
||||
{
|
||||
if(!(sfont=device->DefaultSfont))
|
||||
continue;
|
||||
}
|
||||
else if((sfont=LookupSfont(device, ids[i])) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
if(sfont->Mapped != AL_FALSE || sfont->ref != 0)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
|
||||
@ -88,7 +90,17 @@ AL_API ALvoid AL_APIENTRY alDeleteSoundfontsSOFT(ALsizei n, const ALuint *ids)
|
||||
|
||||
for(i = 0;i < n;i++)
|
||||
{
|
||||
if((sfont=RemoveSfont(device, ids[i])) == NULL)
|
||||
if(ids[i] == 0)
|
||||
{
|
||||
MidiSynth *synth = device->Synth;
|
||||
WriteLock(&synth->Lock);
|
||||
if(device->DefaultSfont != NULL)
|
||||
MidiSynth_deleteSoundfont(device, device->DefaultSfont);
|
||||
device->DefaultSfont = NULL;
|
||||
WriteUnlock(&synth->Lock);
|
||||
continue;
|
||||
}
|
||||
else if((sfont=RemoveSfont(device, ids[i])) == NULL)
|
||||
continue;
|
||||
|
||||
ALsoundfont_Destruct(sfont);
|
||||
|
Loading…
x
Reference in New Issue
Block a user