mirror of
https://github.com/love2d/megasource.git
synced 2026-08-19 20:20:11 +02:00
Update OpenAL-Soft to 1.17.
This commit is contained in:
@@ -1,172 +0,0 @@
|
||||
#ifndef ALMIDI_H
|
||||
#define ALMIDI_H
|
||||
|
||||
#include "alMain.h"
|
||||
#include "atomic.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct ALsfmodulator {
|
||||
struct {
|
||||
ALenum Input;
|
||||
ALenum Type;
|
||||
ALenum Form;
|
||||
} Source[2];
|
||||
ALint Amount;
|
||||
ALenum TransformOp;
|
||||
ALenum Dest;
|
||||
} ALsfmodulator;
|
||||
|
||||
typedef struct ALenvelope {
|
||||
ALint DelayTime;
|
||||
ALint AttackTime;
|
||||
ALint HoldTime;
|
||||
ALint DecayTime;
|
||||
ALint SustainAttn;
|
||||
ALint ReleaseTime;
|
||||
ALint KeyToHoldTime;
|
||||
ALint KeyToDecayTime;
|
||||
} ALenvelope;
|
||||
|
||||
|
||||
typedef struct ALfontsound {
|
||||
RefCount ref;
|
||||
|
||||
struct ALbuffer *Buffer;
|
||||
|
||||
ALint MinKey, MaxKey;
|
||||
ALint MinVelocity, MaxVelocity;
|
||||
|
||||
ALint ModLfoToPitch;
|
||||
ALint VibratoLfoToPitch;
|
||||
ALint ModEnvToPitch;
|
||||
|
||||
ALint FilterCutoff;
|
||||
ALint FilterQ;
|
||||
ALint ModLfoToFilterCutoff;
|
||||
ALint ModEnvToFilterCutoff;
|
||||
ALint ModLfoToVolume;
|
||||
|
||||
ALint ChorusSend;
|
||||
ALint ReverbSend;
|
||||
|
||||
ALint Pan;
|
||||
|
||||
struct {
|
||||
ALint Delay;
|
||||
ALint Frequency;
|
||||
} ModLfo;
|
||||
struct {
|
||||
ALint Delay;
|
||||
ALint Frequency;
|
||||
} VibratoLfo;
|
||||
|
||||
ALenvelope ModEnv;
|
||||
ALenvelope VolEnv;
|
||||
|
||||
ALint Attenuation;
|
||||
|
||||
ALint CoarseTuning;
|
||||
ALint FineTuning;
|
||||
|
||||
ALenum LoopMode;
|
||||
|
||||
ALint TuningScale;
|
||||
|
||||
ALint ExclusiveClass;
|
||||
|
||||
ALuint Start;
|
||||
ALuint End;
|
||||
ALuint LoopStart;
|
||||
ALuint LoopEnd;
|
||||
ALuint SampleRate;
|
||||
ALubyte PitchKey;
|
||||
ALbyte PitchCorrection;
|
||||
ALenum SampleType;
|
||||
struct ALfontsound *Link;
|
||||
|
||||
/* NOTE: Each map entry contains *four* (4) ALsfmodulator objects. */
|
||||
UIntMap ModulatorMap;
|
||||
|
||||
ALuint id;
|
||||
} ALfontsound;
|
||||
|
||||
void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param, ALint value);
|
||||
void ALfontsound_setModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint value);
|
||||
|
||||
ALfontsound *NewFontsound(ALCcontext *context);
|
||||
void DeleteFontsound(ALCdevice *device, ALfontsound *sound);
|
||||
|
||||
inline struct ALfontsound *LookupFontsound(ALCdevice *device, ALuint id)
|
||||
{ return (struct ALfontsound*)LookupUIntMapKey(&device->FontsoundMap, id); }
|
||||
inline struct ALfontsound *RemoveFontsound(ALCdevice *device, ALuint id)
|
||||
{ return (struct ALfontsound*)RemoveUIntMapKey(&device->FontsoundMap, id); }
|
||||
|
||||
void ReleaseALFontsounds(ALCdevice *device);
|
||||
|
||||
|
||||
typedef struct ALsfpreset {
|
||||
RefCount ref;
|
||||
|
||||
ALint Preset; /* a.k.a. MIDI program number */
|
||||
ALint Bank; /* MIDI bank 0...127, or percussion (bank 128) */
|
||||
|
||||
ALfontsound **Sounds;
|
||||
ALsizei NumSounds;
|
||||
|
||||
ALuint id;
|
||||
} ALsfpreset;
|
||||
|
||||
ALsfpreset *NewPreset(ALCcontext *context);
|
||||
void DeletePreset(ALCdevice *device, ALsfpreset *preset);
|
||||
|
||||
inline struct ALsfpreset *LookupPreset(ALCdevice *device, ALuint id)
|
||||
{ return (struct ALsfpreset*)LookupUIntMapKey(&device->PresetMap, id); }
|
||||
inline struct ALsfpreset *RemovePreset(ALCdevice *device, ALuint id)
|
||||
{ return (struct ALsfpreset*)RemoveUIntMapKey(&device->PresetMap, id); }
|
||||
|
||||
void ReleaseALPresets(ALCdevice *device);
|
||||
|
||||
|
||||
typedef struct ALsoundfont {
|
||||
RefCount ref;
|
||||
|
||||
ALsfpreset **Presets;
|
||||
ALsizei NumPresets;
|
||||
|
||||
RWLock Lock;
|
||||
|
||||
ALuint id;
|
||||
} ALsoundfont;
|
||||
|
||||
ALsoundfont *ALsoundfont_getDefSoundfont(ALCcontext *context);
|
||||
void ALsoundfont_deleteSoundfont(ALsoundfont *self, ALCdevice *device);
|
||||
|
||||
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); }
|
||||
|
||||
void ReleaseALSoundfonts(ALCdevice *device);
|
||||
|
||||
|
||||
inline ALboolean IsValidCtrlInput(int cc)
|
||||
{
|
||||
/* These correspond to MIDI functions, not real controller values. */
|
||||
if(cc == 0 || cc == 6 || cc == 32 || cc == 38 || (cc >= 98 && cc <= 101) || cc >= 120)
|
||||
return AL_FALSE;
|
||||
/* These are the LSB components of CC0...CC31, which are automatically used when
|
||||
* reading the MSB controller value. */
|
||||
if(cc >= 32 && cc <= 63)
|
||||
return AL_FALSE;
|
||||
/* All the rest are okay! */
|
||||
return AL_TRUE;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ALMIDI_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,217 +0,0 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "alMain.h"
|
||||
#include "alMidi.h"
|
||||
#include "alError.h"
|
||||
#include "alThunk.h"
|
||||
#include "evtqueue.h"
|
||||
#include "rwlock.h"
|
||||
#include "alu.h"
|
||||
|
||||
#include "midi/base.h"
|
||||
|
||||
|
||||
MidiSynth *SynthCreate(ALCdevice *device)
|
||||
{
|
||||
MidiSynth *synth = NULL;
|
||||
if(!synth) synth = SSynth_create(device);
|
||||
if(!synth) synth = FSynth_create(device);
|
||||
if(!synth) synth = DSynth_create(device);
|
||||
return synth;
|
||||
}
|
||||
|
||||
|
||||
AL_API void AL_APIENTRY alMidiSoundfontSOFT(ALuint id)
|
||||
{
|
||||
alMidiSoundfontvSOFT(1, &id);
|
||||
}
|
||||
|
||||
AL_API void AL_APIENTRY alMidiSoundfontvSOFT(ALsizei count, const ALuint *ids)
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
MidiSynth *synth;
|
||||
ALenum err;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
if(count < 0)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
device = context->Device;
|
||||
synth = device->Synth;
|
||||
|
||||
WriteLock(&synth->Lock);
|
||||
if(synth->State == AL_PLAYING || synth->State == AL_PAUSED)
|
||||
alSetError(context, AL_INVALID_OPERATION);
|
||||
else
|
||||
{
|
||||
err = V(synth,selectSoundfonts)(context, count, ids);
|
||||
if(err != AL_NO_ERROR)
|
||||
alSetError(context, err);
|
||||
}
|
||||
WriteUnlock(&synth->Lock);
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
|
||||
AL_API void AL_APIENTRY alMidiEventSOFT(ALuint64SOFT time, ALenum event, ALsizei channel, ALsizei param1, ALsizei param2)
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
ALenum err;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
if(!(event == AL_NOTEOFF_SOFT || event == AL_NOTEON_SOFT ||
|
||||
event == AL_KEYPRESSURE_SOFT || event == AL_CONTROLLERCHANGE_SOFT ||
|
||||
event == AL_PROGRAMCHANGE_SOFT || event == AL_CHANNELPRESSURE_SOFT ||
|
||||
event == AL_PITCHBEND_SOFT))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
if(!(channel >= 0 && channel <= 15))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
if(!(param1 >= 0 && param1 <= 127))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
if(!(param2 >= 0 && param2 <= 127))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
device = context->Device;
|
||||
ALCdevice_Lock(device);
|
||||
err = MidiSynth_insertEvent(device->Synth, time, event|channel, param1, param2);
|
||||
ALCdevice_Unlock(device);
|
||||
if(err != AL_NO_ERROR)
|
||||
alSetError(context, err);
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
AL_API void AL_APIENTRY alMidiSysExSOFT(ALuint64SOFT time, const ALbyte *data, ALsizei size)
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
ALenum err;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
if(!data || size < 0)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
device = context->Device;
|
||||
ALCdevice_Lock(device);
|
||||
err = MidiSynth_insertSysExEvent(device->Synth, time, data, size);
|
||||
ALCdevice_Unlock(device);
|
||||
if(err != AL_NO_ERROR)
|
||||
alSetError(context, err);
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
AL_API void AL_APIENTRY alMidiPlaySOFT(void)
|
||||
{
|
||||
ALCcontext *context;
|
||||
MidiSynth *synth;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
synth = context->Device->Synth;
|
||||
WriteLock(&synth->Lock);
|
||||
MidiSynth_setState(synth, AL_PLAYING);
|
||||
WriteUnlock(&synth->Lock);
|
||||
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
AL_API void AL_APIENTRY alMidiPauseSOFT(void)
|
||||
{
|
||||
ALCcontext *context;
|
||||
MidiSynth *synth;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
synth = context->Device->Synth;
|
||||
WriteLock(&synth->Lock);
|
||||
MidiSynth_setState(synth, AL_PAUSED);
|
||||
WriteUnlock(&synth->Lock);
|
||||
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
AL_API void AL_APIENTRY alMidiStopSOFT(void)
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
MidiSynth *synth;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
synth = device->Synth;
|
||||
|
||||
WriteLock(&synth->Lock);
|
||||
MidiSynth_setState(synth, AL_STOPPED);
|
||||
|
||||
ALCdevice_Lock(device);
|
||||
V0(synth,stop)();
|
||||
ALCdevice_Unlock(device);
|
||||
WriteUnlock(&synth->Lock);
|
||||
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
AL_API void AL_APIENTRY alMidiResetSOFT(void)
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
MidiSynth *synth;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
synth = device->Synth;
|
||||
|
||||
WriteLock(&synth->Lock);
|
||||
MidiSynth_setState(synth, AL_INITIAL);
|
||||
|
||||
ALCdevice_Lock(device);
|
||||
V0(synth,reset)();
|
||||
ALCdevice_Unlock(device);
|
||||
WriteUnlock(&synth->Lock);
|
||||
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
|
||||
AL_API void AL_APIENTRY alMidiGainSOFT(ALfloat value)
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
if(!(value >= 0.0f && isfinite(value)))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
device = context->Device;
|
||||
V(device->Synth,setGain)(value);
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
@@ -1,339 +0,0 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "alMain.h"
|
||||
#include "alMidi.h"
|
||||
#include "alError.h"
|
||||
#include "alThunk.h"
|
||||
|
||||
#include "midi/base.h"
|
||||
|
||||
|
||||
extern inline struct ALsfpreset *LookupPreset(ALCdevice *device, ALuint id);
|
||||
extern inline struct ALsfpreset *RemovePreset(ALCdevice *device, ALuint id);
|
||||
|
||||
static void ALsfpreset_Construct(ALsfpreset *self);
|
||||
static void ALsfpreset_Destruct(ALsfpreset *self);
|
||||
|
||||
|
||||
AL_API void AL_APIENTRY alGenPresetsSOFT(ALsizei n, ALuint *ids)
|
||||
{
|
||||
ALCcontext *context;
|
||||
ALsizei cur = 0;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
if(!(n >= 0))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
for(cur = 0;cur < n;cur++)
|
||||
{
|
||||
ALsfpreset *preset = NewPreset(context);
|
||||
if(!preset)
|
||||
{
|
||||
alDeletePresetsSOFT(cur, ids);
|
||||
break;
|
||||
}
|
||||
|
||||
ids[cur] = preset->id;
|
||||
}
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alDeletePresetsSOFT(ALsizei n, const ALuint *ids)
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
ALsfpreset *preset;
|
||||
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++)
|
||||
{
|
||||
/* Check for valid ID */
|
||||
if((preset=LookupPreset(device, ids[i])) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
if(ReadRef(&preset->ref) != 0)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
|
||||
}
|
||||
|
||||
for(i = 0;i < n;i++)
|
||||
{
|
||||
if((preset=LookupPreset(device, ids[i])) != NULL)
|
||||
DeletePreset(device, preset);
|
||||
}
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
AL_API ALboolean AL_APIENTRY alIsPresetSOFT(ALuint id)
|
||||
{
|
||||
ALCcontext *context;
|
||||
ALboolean ret;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return AL_FALSE;
|
||||
|
||||
ret = LookupPreset(context->Device, id) ? AL_TRUE : AL_FALSE;
|
||||
|
||||
ALCcontext_DecRef(context);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AL_API void AL_APIENTRY alPresetiSOFT(ALuint id, ALenum param, ALint value)
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
ALsfpreset *preset;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
if((preset=LookupPreset(device, id)) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
if(ReadRef(&preset->ref) != 0)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
|
||||
switch(param)
|
||||
{
|
||||
case AL_MIDI_PRESET_SOFT:
|
||||
if(!(value >= 0 && value <= 127))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
preset->Preset = value;
|
||||
break;
|
||||
|
||||
case AL_MIDI_BANK_SOFT:
|
||||
if(!(value >= 0 && value <= 128))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
preset->Bank = value;
|
||||
break;
|
||||
|
||||
default:
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
}
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
AL_API void AL_APIENTRY alPresetivSOFT(ALuint id, ALenum param, const ALint *values)
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
ALsfpreset *preset;
|
||||
|
||||
switch(param)
|
||||
{
|
||||
case AL_MIDI_PRESET_SOFT:
|
||||
case AL_MIDI_BANK_SOFT:
|
||||
alPresetiSOFT(id, param, values[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
if((preset=LookupPreset(device, id)) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
if(ReadRef(&preset->ref) != 0)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
|
||||
switch(param)
|
||||
{
|
||||
default:
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
}
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
AL_API void AL_APIENTRY alGetPresetivSOFT(ALuint id, ALenum param, ALint *values)
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
ALsfpreset *preset;
|
||||
ALsizei i;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
if((preset=LookupPreset(device, id)) == NULL)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
switch(param)
|
||||
{
|
||||
case AL_MIDI_PRESET_SOFT:
|
||||
values[0] = preset->Preset;
|
||||
break;
|
||||
|
||||
case AL_MIDI_BANK_SOFT:
|
||||
values[0] = preset->Bank;
|
||||
break;
|
||||
|
||||
case AL_FONTSOUNDS_SIZE_SOFT:
|
||||
values[0] = preset->NumSounds;
|
||||
break;
|
||||
|
||||
case AL_FONTSOUNDS_SOFT:
|
||||
for(i = 0;i < preset->NumSounds;i++)
|
||||
values[i] = preset->Sounds[i]->id;
|
||||
break;
|
||||
|
||||
default:
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
}
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
AL_API void AL_APIENTRY alPresetFontsoundsSOFT(ALuint id, ALsizei count, const ALuint *fsids)
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
ALsfpreset *preset;
|
||||
ALfontsound **sounds;
|
||||
ALsizei i;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
if(!(preset=LookupPreset(device, id)))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
if(count < 0)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
if(ReadRef(&preset->ref) != 0)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
|
||||
|
||||
if(count == 0)
|
||||
sounds = NULL;
|
||||
else
|
||||
{
|
||||
sounds = calloc(count, sizeof(sounds[0]));
|
||||
if(!sounds)
|
||||
SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
|
||||
|
||||
for(i = 0;i < count;i++)
|
||||
{
|
||||
if(!(sounds[i]=LookupFontsound(device, fsids[i])))
|
||||
{
|
||||
free(sounds);
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0;i < count;i++)
|
||||
IncrementRef(&sounds[i]->ref);
|
||||
|
||||
sounds = ExchangePtr((XchgPtr*)&preset->Sounds, sounds);
|
||||
count = ExchangeInt(&preset->NumSounds, count);
|
||||
|
||||
for(i = 0;i < count;i++)
|
||||
DecrementRef(&sounds[i]->ref);
|
||||
free(sounds);
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
|
||||
ALsfpreset *NewPreset(ALCcontext *context)
|
||||
{
|
||||
ALCdevice *device = context->Device;
|
||||
ALsfpreset *preset;
|
||||
ALenum err;
|
||||
|
||||
preset = calloc(1, sizeof(*preset));
|
||||
if(!preset)
|
||||
SET_ERROR_AND_RETURN_VALUE(context, AL_OUT_OF_MEMORY, NULL);
|
||||
ALsfpreset_Construct(preset);
|
||||
|
||||
err = NewThunkEntry(&preset->id);
|
||||
if(err == AL_NO_ERROR)
|
||||
err = InsertUIntMapEntry(&device->PresetMap, preset->id, preset);
|
||||
if(err != AL_NO_ERROR)
|
||||
{
|
||||
ALsfpreset_Destruct(preset);
|
||||
memset(preset, 0, sizeof(*preset));
|
||||
free(preset);
|
||||
|
||||
SET_ERROR_AND_RETURN_VALUE(context, err, NULL);
|
||||
}
|
||||
|
||||
return preset;
|
||||
}
|
||||
|
||||
void DeletePreset(ALCdevice *device, ALsfpreset *preset)
|
||||
{
|
||||
RemovePreset(device, preset->id);
|
||||
|
||||
ALsfpreset_Destruct(preset);
|
||||
memset(preset, 0, sizeof(*preset));
|
||||
free(preset);
|
||||
}
|
||||
|
||||
|
||||
static void ALsfpreset_Construct(ALsfpreset *self)
|
||||
{
|
||||
InitRef(&self->ref, 0);
|
||||
|
||||
self->Preset = 0;
|
||||
self->Bank = 0;
|
||||
|
||||
self->Sounds = NULL;
|
||||
self->NumSounds = 0;
|
||||
|
||||
self->id = 0;
|
||||
}
|
||||
|
||||
static void ALsfpreset_Destruct(ALsfpreset *self)
|
||||
{
|
||||
ALsizei i;
|
||||
|
||||
FreeThunkEntry(self->id);
|
||||
self->id = 0;
|
||||
|
||||
for(i = 0;i < self->NumSounds;i++)
|
||||
DecrementRef(&self->Sounds[i]->ref);
|
||||
free(self->Sounds);
|
||||
self->Sounds = NULL;
|
||||
self->NumSounds = 0;
|
||||
}
|
||||
|
||||
|
||||
/* ReleaseALPresets
|
||||
*
|
||||
* Called to destroy any presets that still exist on the device
|
||||
*/
|
||||
void ReleaseALPresets(ALCdevice *device)
|
||||
{
|
||||
ALsizei i;
|
||||
for(i = 0;i < device->PresetMap.size;i++)
|
||||
{
|
||||
ALsfpreset *temp = device->PresetMap.array[i].value;
|
||||
device->PresetMap.array[i].value = NULL;
|
||||
|
||||
ALsfpreset_Destruct(temp);
|
||||
|
||||
memset(temp, 0, sizeof(*temp));
|
||||
free(temp);
|
||||
}
|
||||
}
|
||||
@@ -1,454 +0,0 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "alMain.h"
|
||||
#include "alMidi.h"
|
||||
#include "alThunk.h"
|
||||
#include "alError.h"
|
||||
#include <alBuffer.h>
|
||||
|
||||
#include "midi/base.h"
|
||||
|
||||
|
||||
extern inline struct ALsoundfont *LookupSfont(ALCdevice *device, ALuint id);
|
||||
extern inline struct ALsoundfont *RemoveSfont(ALCdevice *device, ALuint id);
|
||||
|
||||
static void ALsoundfont_Construct(ALsoundfont *self);
|
||||
static void ALsoundfont_Destruct(ALsoundfont *self);
|
||||
void ALsoundfont_deleteSoundfont(ALsoundfont *self, ALCdevice *device);
|
||||
ALsoundfont *ALsoundfont_getDefSoundfont(ALCcontext *context);
|
||||
static size_t ALsoundfont_read(ALvoid *buf, size_t bytes, ALvoid *ptr);
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
ALsoundfont_Destruct(sfont);
|
||||
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++)
|
||||
{
|
||||
/* Check for valid soundfont ID */
|
||||
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(ReadRef(&sfont->ref) != 0)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
|
||||
}
|
||||
|
||||
for(i = 0;i < n;i++)
|
||||
{
|
||||
if(ids[i] == 0)
|
||||
{
|
||||
MidiSynth *synth = device->Synth;
|
||||
WriteLock(&synth->Lock);
|
||||
if(device->DefaultSfont != NULL)
|
||||
ALsoundfont_deleteSoundfont(device->DefaultSfont, device);
|
||||
device->DefaultSfont = NULL;
|
||||
WriteUnlock(&synth->Lock);
|
||||
continue;
|
||||
}
|
||||
else if((sfont=RemoveSfont(device, ids[i])) == NULL)
|
||||
continue;
|
||||
|
||||
ALsoundfont_Destruct(sfont);
|
||||
|
||||
memset(sfont, 0, sizeof(*sfont));
|
||||
free(sfont);
|
||||
}
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
AL_API ALboolean AL_APIENTRY alIsSoundfontSOFT(ALuint id)
|
||||
{
|
||||
ALCcontext *context;
|
||||
ALboolean ret;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return AL_FALSE;
|
||||
|
||||
ret = ((!id || LookupSfont(context->Device, id)) ?
|
||||
AL_TRUE : AL_FALSE);
|
||||
|
||||
ALCcontext_DecRef(context);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
AL_API void AL_APIENTRY alGetSoundfontivSOFT(ALuint id, ALenum param, ALint *values)
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
ALsoundfont *sfont;
|
||||
ALsizei i;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
if(id == 0)
|
||||
sfont = ALsoundfont_getDefSoundfont(context);
|
||||
else if(!(sfont=LookupSfont(device, id)))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
switch(param)
|
||||
{
|
||||
case AL_PRESETS_SIZE_SOFT:
|
||||
values[0] = sfont->NumPresets;
|
||||
break;
|
||||
|
||||
case AL_PRESETS_SOFT:
|
||||
for(i = 0;i < sfont->NumPresets;i++)
|
||||
values[i] = sfont->Presets[i]->id;
|
||||
break;
|
||||
|
||||
default:
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
}
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
AL_API void AL_APIENTRY alSoundfontPresetsSOFT(ALuint id, ALsizei count, const ALuint *pids)
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
ALsoundfont *sfont;
|
||||
ALsfpreset **presets;
|
||||
ALsizei i;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
if(id == 0)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
|
||||
if(!(sfont=LookupSfont(device, id)))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
if(count < 0)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
WriteLock(&sfont->Lock);
|
||||
if(ReadRef(&sfont->ref) != 0)
|
||||
{
|
||||
WriteUnlock(&sfont->Lock);
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
|
||||
}
|
||||
|
||||
if(count == 0)
|
||||
presets = NULL;
|
||||
else
|
||||
{
|
||||
presets = calloc(count, sizeof(presets[0]));
|
||||
if(!presets)
|
||||
{
|
||||
WriteUnlock(&sfont->Lock);
|
||||
SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
|
||||
}
|
||||
|
||||
for(i = 0;i < count;i++)
|
||||
{
|
||||
if(!(presets[i]=LookupPreset(device, pids[i])))
|
||||
{
|
||||
free(presets);
|
||||
WriteUnlock(&sfont->Lock);
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0;i < count;i++)
|
||||
IncrementRef(&presets[i]->ref);
|
||||
|
||||
presets = ExchangePtr((XchgPtr*)&sfont->Presets, presets);
|
||||
count = ExchangeInt(&sfont->NumPresets, count);
|
||||
WriteUnlock(&sfont->Lock);
|
||||
|
||||
for(i = 0;i < count;i++)
|
||||
DecrementRef(&presets[i]->ref);
|
||||
free(presets);
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
|
||||
AL_API void AL_APIENTRY alLoadSoundfontSOFT(ALuint id, size_t(*cb)(ALvoid*,size_t,ALvoid*), ALvoid *user)
|
||||
{
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
ALsoundfont *sfont;
|
||||
Reader reader;
|
||||
|
||||
context = GetContextRef();
|
||||
if(!context) return;
|
||||
|
||||
device = context->Device;
|
||||
if(id == 0)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
|
||||
if(!(sfont=LookupSfont(device, id)))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
|
||||
|
||||
WriteLock(&sfont->Lock);
|
||||
if(ReadRef(&sfont->ref) != 0)
|
||||
{
|
||||
WriteUnlock(&sfont->Lock);
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
|
||||
}
|
||||
if(sfont->NumPresets > 0)
|
||||
{
|
||||
WriteUnlock(&sfont->Lock);
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
|
||||
}
|
||||
|
||||
reader.cb = cb;
|
||||
reader.ptr = user;
|
||||
reader.error = 0;
|
||||
loadSf2(&reader, sfont, context);
|
||||
WriteUnlock(&sfont->Lock);
|
||||
|
||||
done:
|
||||
ALCcontext_DecRef(context);
|
||||
}
|
||||
|
||||
|
||||
static void ALsoundfont_Construct(ALsoundfont *self)
|
||||
{
|
||||
InitRef(&self->ref, 0);
|
||||
|
||||
self->Presets = NULL;
|
||||
self->NumPresets = 0;
|
||||
|
||||
RWLockInit(&self->Lock);
|
||||
|
||||
self->id = 0;
|
||||
}
|
||||
|
||||
static void ALsoundfont_Destruct(ALsoundfont *self)
|
||||
{
|
||||
ALsizei i;
|
||||
|
||||
FreeThunkEntry(self->id);
|
||||
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;
|
||||
}
|
||||
|
||||
ALsoundfont *ALsoundfont_getDefSoundfont(ALCcontext *context)
|
||||
{
|
||||
ALCdevice *device = context->Device;
|
||||
al_string fname = AL_STRING_INIT_STATIC();
|
||||
const char *namelist;
|
||||
|
||||
if(device->DefaultSfont)
|
||||
return device->DefaultSfont;
|
||||
|
||||
device->DefaultSfont = calloc(1, sizeof(device->DefaultSfont[0]));
|
||||
ALsoundfont_Construct(device->DefaultSfont);
|
||||
|
||||
namelist = getenv("ALSOFT_SOUNDFONT");
|
||||
if(!namelist || !namelist[0])
|
||||
ConfigValueStr("midi", "soundfont", &namelist);
|
||||
while(namelist && namelist[0])
|
||||
{
|
||||
const char *next, *end;
|
||||
FILE *f;
|
||||
|
||||
while(*namelist && (isspace(*namelist) || *namelist == ','))
|
||||
namelist++;
|
||||
if(!*namelist)
|
||||
break;
|
||||
next = strchr(namelist, ',');
|
||||
end = next ? next++ : (namelist+strlen(namelist));
|
||||
while(--end != namelist && isspace(*end)) {
|
||||
}
|
||||
if(end == namelist)
|
||||
continue;
|
||||
al_string_append_range(&fname, namelist, end+1);
|
||||
namelist = next;
|
||||
|
||||
f = OpenDataFile(al_string_get_cstr(fname), "openal/soundfonts");
|
||||
if(f == NULL)
|
||||
ERR("Failed to open %s\n", al_string_get_cstr(fname));
|
||||
else
|
||||
{
|
||||
Reader reader;
|
||||
reader.cb = ALsoundfont_read;
|
||||
reader.ptr = f;
|
||||
reader.error = 0;
|
||||
TRACE("Loading %s\n", al_string_get_cstr(fname));
|
||||
loadSf2(&reader, device->DefaultSfont, context);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
al_string_clear(&fname);
|
||||
}
|
||||
AL_STRING_DEINIT(fname);
|
||||
|
||||
return device->DefaultSfont;
|
||||
}
|
||||
|
||||
void ALsoundfont_deleteSoundfont(ALsoundfont *self, ALCdevice *device)
|
||||
{
|
||||
ALsfpreset **presets;
|
||||
ALsizei num_presets;
|
||||
VECTOR(ALbuffer*) buffers;
|
||||
ALsizei i;
|
||||
|
||||
VECTOR_INIT(buffers);
|
||||
presets = ExchangePtr((XchgPtr*)&self->Presets, NULL);
|
||||
num_presets = ExchangeInt(&self->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(device, preset);
|
||||
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] && ReadRef(&sounds[j]->ref) == 0)
|
||||
{
|
||||
deleting = AL_TRUE;
|
||||
if(sounds[j]->Buffer)
|
||||
{
|
||||
ALbuffer *buffer = sounds[j]->Buffer;
|
||||
ALbuffer **iter;
|
||||
|
||||
#define MATCH_BUFFER(_i) (buffer == *(_i))
|
||||
VECTOR_FIND_IF(iter, ALbuffer*, buffers, MATCH_BUFFER);
|
||||
if(iter == VECTOR_ITER_END(buffers))
|
||||
VECTOR_PUSH_BACK(buffers, buffer);
|
||||
#undef MATCH_BUFFER
|
||||
}
|
||||
DeleteFontsound(device, sounds[j]);
|
||||
sounds[j] = NULL;
|
||||
}
|
||||
}
|
||||
} while(deleting);
|
||||
free(sounds);
|
||||
}
|
||||
|
||||
ALsoundfont_Destruct(self);
|
||||
free(self);
|
||||
|
||||
#define DELETE_BUFFER(iter) do { \
|
||||
assert(ReadRef(&(*(iter))->ref) == 0); \
|
||||
DeleteBuffer(device, *(iter)); \
|
||||
} while(0)
|
||||
VECTOR_FOR_EACH(ALbuffer*, buffers, DELETE_BUFFER);
|
||||
VECTOR_DEINIT(buffers);
|
||||
#undef DELETE_BUFFER
|
||||
}
|
||||
|
||||
|
||||
static size_t ALsoundfont_read(ALvoid *buf, size_t bytes, ALvoid *ptr)
|
||||
{
|
||||
return fread(buf, 1, bytes, (FILE*)ptr);
|
||||
}
|
||||
|
||||
|
||||
/* ReleaseALSoundfonts
|
||||
*
|
||||
* Called to destroy any soundfonts that still exist on the device
|
||||
*/
|
||||
void ReleaseALSoundfonts(ALCdevice *device)
|
||||
{
|
||||
ALsizei i;
|
||||
for(i = 0;i < device->SfontMap.size;i++)
|
||||
{
|
||||
ALsoundfont *temp = device->SfontMap.array[i].value;
|
||||
device->SfontMap.array[i].value = NULL;
|
||||
|
||||
ALsoundfont_Destruct(temp);
|
||||
|
||||
memset(temp, 0, sizeof(*temp));
|
||||
free(temp);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user