diff options
-rw-r--r-- | Alc/ALc.c | 2 | ||||
-rw-r--r-- | Alc/midi/sf2load.c | 53 | ||||
-rw-r--r-- | OpenAL32/Include/alMain.h | 41 | ||||
-rw-r--r-- | OpenAL32/Include/alMidi.h | 10 | ||||
-rw-r--r-- | OpenAL32/alFontsound.c | 185 |
5 files changed, 287 insertions, 4 deletions
@@ -303,6 +303,8 @@ static const ALCfunction alcFunctions[] = { DECL(alFontsound2iSOFT), DECL(alFontsoundivSOFT), DECL(alGetFontsoundivSOFT), + DECL(alFontsoundModulatoriSOFT), + DECL(alGetFontsoundModulatorivSOFT), DECL(alMidiSoundfontSOFT), DECL(alMidiSoundfontvSOFT), DECL(alMidiEventSOFT), diff --git a/Alc/midi/sf2load.c b/Alc/midi/sf2load.c index 2f6d3324..a56a701c 100644 --- a/Alc/midi/sf2load.c +++ b/Alc/midi/sf2load.c @@ -714,6 +714,27 @@ static ALboolean checkZone(const GenModList *zone, const PresetHeader *preset, c return AL_TRUE; } +static ALenum getModSrcInput(int type) +{ + if(type == 0) return AL_ONE_SOFT; + if(type == 2) return AL_NOTEON_VELOCITY_SOFT; + if(type == 3) return AL_NOTEON_KEY_SOFT; + if(type == 10) return AL_AFTERTOUCH_SOFT; + if(type == 13) return AL_CHANNELPRESSURE_SOFT; + if(type == 14) return AL_PITCHBEND_SOFT; + if(type == 16) return AL_PITCHBEND_SENSITIVITY_SOFT; + if((type&0x80)) + { + type ^= 0x80; + if(type > 0 && type < 120 && !(type == 6 || (type >= 32 && type <= 63) || + (type >= 98 && type <= 101))) + return type; + type ^= 0x80; + } + ERR("Unhandled modulator source input: 0x%02x\n", type); + return AL_NONE; +} + static void fillZone(ALfontsound *sound, ALCcontext *context, const GenModList *zone) { static const ALenum Gen2Param[60] = { @@ -782,7 +803,37 @@ static void fillZone(ALfontsound *sound, ALCcontext *context, const GenModList * if(zone->mods) { - /* FIXME: Handle modulators */ + ALsizei i; + for(i = 0;i < zone->mods_size;i++) + { + ALenum src0in = getModSrcInput(zone->mods[i].mSrcOp&0xFF); + ALenum src0form = (zone->mods[i].mSrcOp&0xFC00); + ALenum src1in = getModSrcInput(zone->mods[i].mAmtSrcOp&0xFF); + ALenum src1form = (zone->mods[i].mAmtSrcOp&0xFC00); + ALenum trans = zone->mods[i].mTransOp; + ALenum dst = (zone->mods[i].mDstOp < 60) ? Gen2Param[zone->mods[i].mDstOp] : 0; + if(!dst) + ERR("Unhandled modulator destination: %d\n", zone->mods[i].mDstOp); + if((src0form&0xF000)) + ERR("Unhandled modulator source form: 0x%04x\n", src0form); + if((src1form&0xF000)) + ERR("Unhandled modulator source form: 0x%04x\n", src1form); + if(!(trans == 0 || trans == 2)) + ERR("Unhandled modulator transform: %d\n", trans); + if(src0in && !(src0form&0xF000) && src1in && !(src1form&0xF000) && + (trans == 0 || trans == 2) && dst) + { + ALfontsound_setModStagei(sound, context, i, AL_SOURCE0_INPUT_SOFT, src0in); + ALfontsound_setModStagei(sound, context, i, AL_SOURCE0_TYPE_SOFT, (zone->mods[i].mSrcOp&0x300)); + ALfontsound_setModStagei(sound, context, i, AL_SOURCE0_FORM_SOFT, src0form); + ALfontsound_setModStagei(sound, context, i, AL_SOURCE1_INPUT_SOFT, src1in); + ALfontsound_setModStagei(sound, context, i, AL_SOURCE1_TYPE_SOFT, (zone->mods[i].mAmtSrcOp&0x300)); + ALfontsound_setModStagei(sound, context, i, AL_SOURCE1_FORM_SOFT, src1form); + ALfontsound_setModStagei(sound, context, i, AL_AMOUNT_SOFT, zone->mods[i].mAmount); + ALfontsound_setModStagei(sound, context, i, AL_TRANSFORM_OP_SOFT, trans); + ALfontsound_setModStagei(sound, context, i, AL_DESTINATION_SOFT, dst); + } + } } gen = zone->gens; diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index cf843919..43f0cfcd 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -39,6 +39,43 @@ #define AL_PRESETS_SOFT 0x9992 #define AL_FONTSOUNDS_SIZE_SOFT 0x9991 #define AL_FONTSOUNDS_SOFT 0x9990 + +#define AL_SOURCE0_INPUT_SOFT 0x998F +#define AL_SOURCE0_TYPE_SOFT 0x998E +#define AL_SOURCE0_FORM_SOFT 0x998D +#define AL_SOURCE1_INPUT_SOFT 0x998C +#define AL_SOURCE1_TYPE_SOFT 0x998B +#define AL_SOURCE1_FORM_SOFT 0x998A +#define AL_AMOUNT_SOFT 0x9989 +#define AL_TRANSFORM_OP_SOFT 0x9988 +#define AL_DESTINATION_SOFT 0x9987 + +/* Sounce Input */ +#define AL_ONE_SOFT 0x0080 +#define AL_NOTEON_VELOCITY_SOFT 0x0082 +#define AL_NOTEON_KEY_SOFT 0x0083 +/* aftertouch */ +/* channelpressure */ +/* pitchbend */ +#define AL_PITCHBEND_SENSITIVITY_SOFT 0x0090 +/* 0...127 CC */ + +/* Source Type */ +#define AL_UNORM_SOFT 0x0000 +#define AL_SNORM_SOFT 0x0100 +#define AL_UNORM_REV_SOFT 0x0200 +#define AL_SNORM_REV_SOFT 0x0300 + +/* Source Form */ +#define AL_LINEAR_SOFT 0x0000 +#define AL_CONCAVE_SOFT 0x0400 +#define AL_CONVEX_SOFT 0x0800 +#define AL_SWITCH_SOFT 0x0C00 + +/* Transform op */ +/* linear */ +#define AL_ABSOLUTE_SOFT 0x0002 + #define AL_SAMPLE_START_SOFT 0x2000 #define AL_SAMPLE_END_SOFT 0x2001 #define AL_SAMPLE_LOOP_START_SOFT 0x2002 @@ -119,6 +156,8 @@ typedef void (AL_APIENTRY*LPALFONTSOUNDISOFT)(ALuint id, ALenum param, ALint val typedef void (AL_APIENTRY*LPALFONTSOUND2ISOFT)(ALuint id, ALenum param, ALint value1, ALint value2); typedef void (AL_APIENTRY*LPALFONTSOUNDIVSOFT)(ALuint id, ALenum param, const ALint *values); typedef void (AL_APIENTRY*LPALGETFONTSOUNDIVSOFT)(ALuint id, ALenum param, ALint *values); +typedef void (AL_APIENTRY*LPALFONTSOUNDMOFULATORISOFT)(ALuint id, ALsizei stage, ALenum param, ALint value); +typedef void (AL_APIENTRY*LPALGETFONTSOUNDMODULATORIVSOFT)(ALuint id, ALsizei stage, ALenum param, ALint *values); typedef void (AL_APIENTRY*LPALMIDISOUNDFONTSOFT)(ALuint id); typedef void (AL_APIENTRY*LPALMIDISOUNDFONTVSOFT)(ALsizei count, const ALuint *ids); typedef void (AL_APIENTRY*LPALMIDIEVENTSOFT)(ALuint64SOFT time, ALenum event, ALsizei channel, ALsizei param1, ALsizei param2); @@ -156,6 +195,8 @@ AL_API void AL_APIENTRY alFontsoundiSOFT(ALuint id, ALenum param, ALint value); AL_API void AL_APIENTRY alFontsound2iSOFT(ALuint id, ALenum param, ALint value1, ALint value2); AL_API void AL_APIENTRY alFontsoundivSOFT(ALuint id, ALenum param, const ALint *values); AL_API void AL_APIENTRY alGetFontsoundivSOFT(ALuint id, ALenum param, ALint *values); +AL_API void AL_APIENTRY alFontsoundModulatoriSOFT(ALuint id, ALsizei stage, ALenum param, ALint value); +AL_API void AL_APIENTRY alGetFontsoundModulatorivSOFT(ALuint id, ALsizei stage, ALenum param, ALint *values); AL_API void AL_APIENTRY alMidiSoundfontSOFT(ALuint id); AL_API void AL_APIENTRY alMidiSoundfontvSOFT(ALsizei count, const ALuint *ids); diff --git a/OpenAL32/Include/alMidi.h b/OpenAL32/Include/alMidi.h index 25bed250..b24f43a0 100644 --- a/OpenAL32/Include/alMidi.h +++ b/OpenAL32/Include/alMidi.h @@ -9,11 +9,14 @@ extern "C" { #endif typedef struct ALsfmodulator { - ALenum SourceOp; - ALenum DestOp; + struct { + ALenum Input; + ALenum Type; + ALenum Form; + } Source[2]; ALint Amount; - ALenum AmountSourceOp; ALenum TransformOp; + ALenum Dest; } ALsfmodulator; @@ -96,6 +99,7 @@ typedef struct ALfontsound { void ALfontsound_Destruct(ALfontsound *self); 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); diff --git a/OpenAL32/alFontsound.c b/OpenAL32/alFontsound.c index 3c47822c..9c2f4bf9 100644 --- a/OpenAL32/alFontsound.c +++ b/OpenAL32/alFontsound.c @@ -18,6 +18,9 @@ extern inline struct ALfontsound *RemoveFontsound(ALCdevice *device, ALuint id); static void ALfontsound_Construct(ALfontsound *self); void ALfontsound_Destruct(ALfontsound *self); void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param, ALint value); +static ALsfmodulator *ALfontsound_getModStage(ALfontsound *self, ALsizei stage); +void ALfontsound_setModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint value); +static void ALfontsound_getModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint *values); AL_API void AL_APIENTRY alGenFontsoundsSOFT(ALsizei n, ALuint *ids) @@ -439,6 +442,42 @@ done: ALCcontext_DecRef(context); } +AL_API void AL_APIENTRY alFontsoundModulatoriSOFT(ALuint id, ALsizei stage, ALenum param, ALint value) +{ + ALCdevice *device; + ALCcontext *context; + ALfontsound *sound; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if(!(sound=LookupFontsound(device, id))) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + ALfontsound_setModStagei(sound, context, stage, param, value); + +done: + ALCcontext_DecRef(context); +} + +AL_API void AL_APIENTRY alGetFontsoundModulatorivSOFT(ALuint id, ALsizei stage, ALenum param, ALint *values) +{ + ALCdevice *device; + ALCcontext *context; + ALfontsound *sound; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if(!(sound=LookupFontsound(device, id))) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + ALfontsound_getModStagei(sound, context, stage, param, values); + +done: + ALCcontext_DecRef(context); +} + ALfontsound *NewFontsound(ALCcontext *context) { @@ -766,6 +805,152 @@ void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param, } } +static ALsfmodulator *ALfontsound_getModStage(ALfontsound *self, ALsizei stage) +{ + ALsfmodulator *ret = LookupModulator(self, stage); + if(!ret) + { + static const ALsfmodulator moddef = { + { { AL_ONE_SOFT, AL_UNORM_SOFT, AL_LINEAR_SOFT }, + { AL_ONE_SOFT, AL_UNORM_SOFT, AL_LINEAR_SOFT } + }, + 0, + AL_LINEAR_SOFT, + AL_NONE + }; + ret = malloc(sizeof(*ret)); + InsertUIntMapEntry(&self->ModulatorMap, stage, ret); + *ret = moddef; + } + return ret; +} + +void ALfontsound_setModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint value) +{ + ALint srcidx = 0; + + if(self->ref != 0) + SET_ERROR_AND_RETURN(context, AL_INVALID_OPERATION); + switch(param) + { + case AL_SOURCE1_INPUT_SOFT: + srcidx++; + /* fall-through */ + case AL_SOURCE0_INPUT_SOFT: + if(!(value == AL_ONE_SOFT || value == AL_NOTEON_VELOCITY_SOFT || + value == AL_NOTEON_KEY_SOFT || value == AL_AFTERTOUCH_SOFT || + value == AL_CHANNELPRESSURE_SOFT || value == AL_PITCHBEND_SOFT || + value == AL_PITCHBEND_SENSITIVITY_SOFT || + (value > 0 && value < 120 && !(value == 6 || (value >= 32 && value <= 63) || + (value >= 98 && value <= 101)) + ) + )) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + ALfontsound_getModStage(self, stage)->Source[srcidx].Input = value; + break; + + case AL_SOURCE1_TYPE_SOFT: + srcidx++; + /* fall-through */ + case AL_SOURCE0_TYPE_SOFT: + if(!(value == AL_UNORM_SOFT || value == AL_SNORM_SOFT || + value == AL_UNORM_REV_SOFT || value == AL_SNORM_REV_SOFT)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + ALfontsound_getModStage(self, stage)->Source[srcidx].Type = value; + break; + + case AL_SOURCE1_FORM_SOFT: + srcidx++; + /* fall-through */ + case AL_SOURCE0_FORM_SOFT: + if(!(value == AL_LINEAR_SOFT || value == AL_CONVEX_SOFT || + value == AL_CONCAVE_SOFT || value == AL_SWITCH_SOFT)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + ALfontsound_getModStage(self, stage)->Source[srcidx].Form = value; + break; + + case AL_AMOUNT_SOFT: + ALfontsound_getModStage(self, stage)->Amount = value; + break; + + case AL_TRANSFORM_OP_SOFT: + if(!(value == AL_LINEAR_SOFT || value == AL_ABSOLUTE_SOFT)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + ALfontsound_getModStage(self, stage)->TransformOp = value; + break; + + case AL_DESTINATION_SOFT: + if(!(value == AL_MOD_LFO_TO_PITCH_SOFT || value == AL_VIBRATO_LFO_TO_PITCH_SOFT || + value == AL_MOD_ENV_TO_PITCH_SOFT || value == AL_FILTER_CUTOFF_SOFT || + value == AL_FILTER_RESONANCE_SOFT || value == AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT || + value == AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT || value == AL_MOD_LFO_TO_VOLUME_SOFT || + value == AL_CHORUS_SEND_SOFT || value == AL_REVERB_SEND_SOFT || value == AL_PAN_SOFT || + value == AL_MOD_LFO_DELAY_SOFT || value == AL_MOD_LFO_FREQUENCY_SOFT || + value == AL_VIBRATO_LFO_DELAY_SOFT || value == AL_VIBRATO_LFO_FREQUENCY_SOFT || + value == AL_MOD_ENV_DELAYTIME_SOFT || value == AL_MOD_ENV_ATTACKTIME_SOFT || + value == AL_MOD_ENV_HOLDTIME_SOFT || value == AL_MOD_ENV_DECAYTIME_SOFT || + value == AL_MOD_ENV_SUSTAINVOLUME_SOFT || value == AL_MOD_ENV_RELEASETIME_SOFT || + value == AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT || value == AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT || + value == AL_VOLUME_ENV_DELAYTIME_SOFT || value == AL_VOLUME_ENV_ATTACKTIME_SOFT || + value == AL_VOLUME_ENV_HOLDTIME_SOFT || value == AL_VOLUME_ENV_DECAYTIME_SOFT || + value == AL_VOLUME_ENV_SUSTAINVOLUME_SOFT || value == AL_VOLUME_ENV_RELEASETIME_SOFT || + value == AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT || value == AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT || + value == AL_ATTENUATION_SOFT || value == AL_TUNING_COARSE_SOFT || + value == AL_TUNING_FINE_SOFT || value == AL_TUNING_SCALE_SOFT)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + ALfontsound_getModStage(self, stage)->Dest = value; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} + +static void ALfontsound_getModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint *values) +{ + ALsfmodulator *mod = LookupModulator(self, stage); + ALint srcidx = 0; + + switch(param) + { + case AL_SOURCE1_INPUT_SOFT: + srcidx++; + /* fall-through */ + case AL_SOURCE0_INPUT_SOFT: + values[0] = mod ? mod->Source[srcidx].Input : AL_ONE_SOFT; + break; + + case AL_SOURCE1_TYPE_SOFT: + srcidx++; + /* fall-through */ + case AL_SOURCE0_TYPE_SOFT: + values[0] = mod ? mod->Source[srcidx].Type : AL_UNORM_SOFT; + break; + + case AL_SOURCE1_FORM_SOFT: + srcidx++; + /* fall-through */ + case AL_SOURCE0_FORM_SOFT: + values[0] = mod ? mod->Source[srcidx].Form : AL_LINEAR_SOFT; + break; + + case AL_AMOUNT_SOFT: + values[0] = mod ? mod->Amount : 0; + break; + + case AL_TRANSFORM_OP_SOFT: + values[0] = mod ? mod->TransformOp : AL_LINEAR_SOFT; + break; + + case AL_DESTINATION_SOFT: + values[0] = mod ? mod->Dest : AL_NONE; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} + /* ReleaseALFontsounds * |