1 /* DirectSound EAX interface
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "dsound_private.h"
26 #include "eax-presets.h"
29 static const char *debug_fxslot(const GUID
*guid
)
31 #define HANDLE_ID(id) if(IsEqualGUID(guid, &(id))) return #id
32 HANDLE_ID(EAX_NULL_GUID
);
33 HANDLE_ID(EAX_PrimaryFXSlotID
);
34 HANDLE_ID(EAXPROPERTYID_EAX40_FXSlot0
);
35 HANDLE_ID(EAXPROPERTYID_EAX40_FXSlot1
);
36 HANDLE_ID(EAXPROPERTYID_EAX40_FXSlot2
);
37 HANDLE_ID(EAXPROPERTYID_EAX40_FXSlot3
);
39 return debugstr_guid(guid
);
42 static const char *debug_fxguid(const GUID
*guid
)
44 #define HANDLE_ID(id) if(IsEqualGUID(guid, &(id))) return #id
45 HANDLE_ID(EAX_NULL_GUID
);
46 HANDLE_ID(EAX_REVERB_EFFECT
);
47 HANDLE_ID(EAX_AGCCOMPRESSOR_EFFECT
);
48 HANDLE_ID(EAX_AUTOWAH_EFFECT
);
49 HANDLE_ID(EAX_CHORUS_EFFECT
);
50 HANDLE_ID(EAX_DISTORTION_EFFECT
);
51 HANDLE_ID(EAX_ECHO_EFFECT
);
52 HANDLE_ID(EAX_EQUALIZER_EFFECT
);
53 HANDLE_ID(EAX_FLANGER_EFFECT
);
54 HANDLE_ID(EAX_FREQUENCYSHIFTER_EFFECT
);
55 HANDLE_ID(EAX_VOCALMORPHER_EFFECT
);
56 HANDLE_ID(EAX_PITCHSHIFTER_EFFECT
);
57 HANDLE_ID(EAX_RINGMODULATOR_EFFECT
);
59 return debugstr_guid(guid
);
63 HRESULT
EAX4Context_Query(DSPrimary
*prim
, DWORD propid
, ULONG
*pTypeSupport
)
65 if(!HAS_EXTENSION(prim
->share
, EXT_EFX
))
66 return E_PROP_ID_UNSUPPORTED
;
68 switch((propid
&~EAXCONTEXT_PARAMETER_DEFERRED
))
71 case EAXCONTEXT_ALLPARAMETERS
:
72 case EAXCONTEXT_PRIMARYFXSLOTID
:
73 case EAXCONTEXT_DISTANCEFACTOR
:
74 case EAXCONTEXT_AIRABSORPTIONHF
:
75 case EAXCONTEXT_HFREFERENCE
:
76 case EAXCONTEXT_LASTERROR
:
77 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
| KSPROPERTY_SUPPORT_SET
;
80 FIXME("Unhandled propid: 0x%08lx\n", propid
);
81 return E_PROP_ID_UNSUPPORTED
;
84 HRESULT
EAX4Context_Set(DSPrimary
*prim
, DWORD propid
, void *pPropData
, ULONG cbPropData
)
86 if(!HAS_EXTENSION(prim
->share
, EXT_EFX
))
87 return E_PROP_ID_UNSUPPORTED
;
91 case EAXCONTEXT_NONE
: /* not setting any property, just applying */
94 case EAXCONTEXT_ALLPARAMETERS
:
95 if(cbPropData
>= sizeof(EAXCONTEXTPROPERTIES
))
97 union { void *v
; const EAXCONTEXTPROPERTIES
*props
; } data
= { pPropData
};
99 TRACE("Parameters:\n\tPrimary FXSlot: %s\n\tDistance Factor: %f\n\t"
100 "Air Absorption: %f\n\tHF Reference: %f\n",
101 debug_fxslot(&data
.props
->guidPrimaryFXSlotID
), data
.props
->flDistanceFactor
,
102 data
.props
->flAirAbsorptionHF
, data
.props
->flHFReference
106 if(IsEqualGUID(&data
.props
->guidPrimaryFXSlotID
, &EAXPROPERTYID_EAX40_FXSlot0
))
108 else if(IsEqualGUID(&data
.props
->guidPrimaryFXSlotID
, &EAXPROPERTYID_EAX40_FXSlot1
))
110 else if(IsEqualGUID(&data
.props
->guidPrimaryFXSlotID
, &EAXPROPERTYID_EAX40_FXSlot2
))
112 else if(IsEqualGUID(&data
.props
->guidPrimaryFXSlotID
, &EAXPROPERTYID_EAX40_FXSlot3
))
114 if(prim_idx
== -1 && !IsEqualGUID(&data
.props
->guidPrimaryFXSlotID
, &EAX_NULL_GUID
))
116 ERR("Unexpected primary FXSlot: %s\n",
117 debug_fxslot(&data
.props
->guidPrimaryFXSlotID
));
118 return DSERR_INVALIDPARAM
;
120 if(!(data
.props
->flDistanceFactor
>= DS3D_MINDISTANCEFACTOR
&&
121 data
.props
->flDistanceFactor
<= DS3D_MAXDISTANCEFACTOR
))
123 ERR("Unexpected distance factor: %f\n", data
.props
->flDistanceFactor
);
124 return DSERR_INVALIDPARAM
;
126 if(!(data
.props
->flAirAbsorptionHF
<= 0.0f
&& data
.props
->flAirAbsorptionHF
>= -100.0f
))
128 ERR("Unexpected air absorption: %f\n", data
.props
->flAirAbsorptionHF
);
129 return DSERR_INVALIDPARAM
;
131 if(!(data
.props
->flHFReference
>= 1000.0f
&& data
.props
->flHFReference
<= 20000.0f
))
133 ERR("Unexpected HF reference: %f\n", data
.props
->flAirAbsorptionHF
);
134 return DSERR_INVALIDPARAM
;
137 prim
->deferred
.ctx
= *data
.props
;
138 prim
->primary_idx
= prim_idx
;
140 prim
->dirty
.bit
.prim_slotid
= 1;
141 prim
->dirty
.bit
.distancefactor2
= 1;
142 prim
->dirty
.bit
.air_absorbhf
= 1;
143 prim
->dirty
.bit
.hfreference
= 1;
146 return DSERR_INVALIDPARAM
;
148 case EAXCONTEXT_PRIMARYFXSLOTID
:
149 if(cbPropData
>= sizeof(GUID
))
151 union { void *v
; const GUID
*guid
; } data
= { pPropData
};
153 TRACE("Primary FXSlot: %s\n", debug_fxslot(data
.guid
));
156 if(IsEqualGUID(data
.guid
, &EAXPROPERTYID_EAX40_FXSlot0
))
158 else if(IsEqualGUID(data
.guid
, &EAXPROPERTYID_EAX40_FXSlot1
))
160 else if(IsEqualGUID(data
.guid
, &EAXPROPERTYID_EAX40_FXSlot2
))
162 else if(IsEqualGUID(data
.guid
, &EAXPROPERTYID_EAX40_FXSlot3
))
164 if(prim_idx
== -1 && !IsEqualGUID(data
.guid
, &EAX_NULL_GUID
))
166 ERR("Unexpected primary FXSlot: %s\n", debug_fxslot(data
.guid
));
167 return DSERR_INVALIDPARAM
;
170 prim
->deferred
.ctx
.guidPrimaryFXSlotID
= *data
.guid
;
171 prim
->primary_idx
= prim_idx
;
173 prim
->dirty
.bit
.prim_slotid
= 1;
176 return DSERR_INVALIDPARAM
;
178 case EAXCONTEXT_DISTANCEFACTOR
:
179 if(cbPropData
>= sizeof(float))
181 union { void *v
; const float *fl
; } data
= { pPropData
};
182 TRACE("Distance Factor: %f\n", *data
.fl
);
184 if(!(*data
.fl
>= DS3D_MINDISTANCEFACTOR
&& *data
.fl
<= DS3D_MAXDISTANCEFACTOR
))
186 ERR("Unexpected distance factor: %f\n", *data
.fl
);
187 return DSERR_INVALIDPARAM
;
190 prim
->deferred
.ctx
.flDistanceFactor
= *data
.fl
;
192 prim
->dirty
.bit
.distancefactor2
= 1;
195 return DSERR_INVALIDPARAM
;
197 case EAXCONTEXT_AIRABSORPTIONHF
:
198 if(cbPropData
>= sizeof(float))
200 union { void *v
; const float *fl
; } data
= { pPropData
};
201 TRACE("Air Absorption: %f\n", *data
.fl
);
203 if(!(*data
.fl
<= 0.0f
&& *data
.fl
>= -100.0f
))
205 ERR("Unexpected air absorption: %f\n", *data
.fl
);
206 return DSERR_INVALIDPARAM
;
209 prim
->deferred
.ctx
.flAirAbsorptionHF
= *data
.fl
;
211 prim
->dirty
.bit
.air_absorbhf
= 1;
214 return DSERR_INVALIDPARAM
;
216 case EAXCONTEXT_HFREFERENCE
:
217 if(cbPropData
>= sizeof(float))
219 union { void *v
; const float *fl
; } data
= { pPropData
};
220 TRACE("HF Reference: %f\n", *data
.fl
);
222 if(!(*data
.fl
>= 1000.0f
&& *data
.fl
<= 20000.0f
))
224 ERR("Unexpected HF reference: %f\n", *data
.fl
);
225 return DSERR_INVALIDPARAM
;
228 prim
->deferred
.ctx
.flHFReference
= *data
.fl
;
230 prim
->dirty
.bit
.hfreference
= 1;
233 return DSERR_INVALIDPARAM
;
235 case EAXCONTEXT_LASTERROR
:
236 if(cbPropData
>= sizeof(long))
238 union { void *v
; const long *l
; } data
= { pPropData
};
239 TRACE("Last Error: %ld\n", *data
.l
);
241 prim
->eax_error
= *data
.l
;
245 return DSERR_INVALIDPARAM
;
247 FIXME("Unhandled propid: 0x%08lx\n", propid
);
248 return E_PROP_ID_UNSUPPORTED
;
251 #define GET_PROP(src, T) do { \
252 if(cbPropData >= sizeof(T)) \
254 union { void *v; T *props; } data = { pPropData }; \
256 *pcbReturned = sizeof(T); \
259 return DSERR_INVALIDPARAM; \
262 HRESULT
EAX4Context_Get(DSPrimary
*prim
, DWORD propid
, void *pPropData
, ULONG cbPropData
, ULONG
*pcbReturned
)
264 if(!HAS_EXTENSION(prim
->share
, EXT_EFX
))
265 return E_PROP_ID_UNSUPPORTED
;
269 case EAXCONTEXT_NONE
:
273 case EAXCONTEXT_ALLPARAMETERS
:
274 GET_PROP(prim
->current
.ctx
, EAXCONTEXTPROPERTIES
);
275 case EAXCONTEXT_PRIMARYFXSLOTID
:
276 GET_PROP(prim
->current
.ctx
.guidPrimaryFXSlotID
, GUID
);
277 case EAXCONTEXT_DISTANCEFACTOR
:
278 GET_PROP(prim
->current
.ctx
.flDistanceFactor
, float);
279 case EAXCONTEXT_AIRABSORPTIONHF
:
280 GET_PROP(prim
->current
.ctx
.flAirAbsorptionHF
, float);
281 case EAXCONTEXT_HFREFERENCE
:
282 GET_PROP(prim
->current
.ctx
.flHFReference
, float);
284 case EAXCONTEXT_LASTERROR
:
285 GET_PROP(InterlockedExchange(&prim
->eax_error
, EAX_OK
), long);
287 FIXME("Unhandled propid: 0x%08lx\n", propid
);
288 return E_PROP_ID_UNSUPPORTED
;
292 HRESULT
EAX4Slot_Query(DSPrimary
*prim
, LONG idx
, DWORD propid
, ULONG
*pTypeSupport
)
294 if(prim
->auxslot
[idx
] == 0)
295 return E_PROP_ID_UNSUPPORTED
;
297 if((propid
&~EAXFXSLOT_PARAMETER_DEFERRED
) < EAXFXSLOT_NONE
)
299 if(prim
->current
.fxslot
[idx
].effect_type
== FXSLOT_EFFECT_REVERB
)
301 if((propid
&~EAXFXSLOT_PARAMETER_DEFERRED
) <= EAXREVERB_FLAGS
)
303 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
| KSPROPERTY_SUPPORT_SET
;
306 FIXME("Unhandled reverb propid: 0x%08lx\n", propid
);
308 else if(prim
->current
.fxslot
[idx
].effect_type
== FXSLOT_EFFECT_CHORUS
)
310 if((propid
&~EAXFXSLOT_PARAMETER_DEFERRED
) <= EAXCHORUS_DELAY
)
312 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
| KSPROPERTY_SUPPORT_SET
;
315 FIXME("Unhandled chorus propid: 0x%08lx\n", propid
);
317 else /*if(prim->current.fxslot[idx].effect_type == FXSLOT_EFFECT_NULL)*/
319 FIXME("Unhandled null effect propid: 0x%08lx\n", propid
);
321 return DSERR_INVALIDPARAM
;
323 switch((propid
&~EAXFXSLOT_PARAMETER_DEFERRED
))
326 case EAXFXSLOT_ALLPARAMETERS
:
327 case EAXFXSLOT_LOADEFFECT
:
328 case EAXFXSLOT_VOLUME
:
330 case EAXFXSLOT_FLAGS
:
331 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
| KSPROPERTY_SUPPORT_SET
;
334 FIXME("Unhandled propid: 0x%08lx\n", propid
);
335 return E_PROP_ID_UNSUPPORTED
;
339 HRESULT
EAX4Slot_Set(DSPrimary
*prim
, LONG idx
, DWORD propid
, void *pPropData
, ULONG cbPropData
)
341 if(prim
->auxslot
[idx
] == 0)
342 return E_PROP_ID_UNSUPPORTED
;
344 if(propid
< EAXFXSLOT_NONE
)
346 if(prim
->deferred
.fxslot
[idx
].effect_type
== FXSLOT_EFFECT_REVERB
)
347 return EAXReverb_Set(prim
, idx
, propid
, pPropData
, cbPropData
);
348 if(prim
->deferred
.fxslot
[idx
].effect_type
== FXSLOT_EFFECT_CHORUS
)
349 return EAXChorus_Set(prim
, idx
, propid
, pPropData
, cbPropData
);
351 ERR("Unexpected null effect propid 0x%08lx\n", propid
);
352 return E_PROP_ID_UNSUPPORTED
;
356 case EAXFXSLOT_NONE
: /* not setting any property, just applying */
359 case EAXFXSLOT_ALLPARAMETERS
:
360 if(cbPropData
>= sizeof(EAXFXSLOTPROPERTIES
))
362 union { const void *v
; const EAXFXSLOTPROPERTIES
*props
; } data
= { pPropData
};
364 TRACE("Parameters:\n\tLoad Effect: %s\n\tVolume: %ld\n\tLock: %ld\n\tFlags: 0x%lx\n",
365 debug_fxguid(&data
.props
->guidLoadEffect
), data
.props
->lVolume
, data
.props
->lLock
,
369 effect_type
= FXSLOT_EFFECT_NULL
;
370 if(IsEqualGUID(&data
.props
->guidLoadEffect
, &EAX_REVERB_EFFECT
))
371 effect_type
= FXSLOT_EFFECT_REVERB
;
372 else if(IsEqualGUID(&data
.props
->guidLoadEffect
, &EAX_CHORUS_EFFECT
))
373 effect_type
= FXSLOT_EFFECT_CHORUS
;
374 else if(!IsEqualGUID(&data
.props
->guidLoadEffect
, &EAX_NULL_GUID
))
376 ERR("Unhandled effect: %s\n", debug_fxguid(&data
.props
->guidLoadEffect
));
377 return DSERR_INVALIDPARAM
;
380 if(data
.props
->lLock
== EAXFXSLOT_LOCKED
&&
381 prim
->deferred
.fxslot
[idx
].props
.lLock
== EAXFXSLOT_LOCKED
&&
382 prim
->deferred
.fxslot
[idx
].effect_type
!= effect_type
)
384 ERR("Attempting to change effect type for locked FXSlot\n");
385 return DSERR_INVALIDCALL
;
388 if(prim
->deferred
.fxslot
[idx
].effect_type
!= effect_type
)
391 alEffecti(prim
->effect
[idx
], AL_EFFECT_TYPE
,
392 (effect_type
== FXSLOT_EFFECT_REVERB
) ? AL_EFFECT_EAXREVERB
:
393 (effect_type
== FXSLOT_EFFECT_CHORUS
) ? AL_EFFECT_CHORUS
:
396 if(alGetError() != AL_NO_ERROR
)
398 ERR("Failed to set effect type %lu\n", effect_type
);
399 return DSERR_INVALIDPARAM
;
402 prim
->deferred
.fxslot
[idx
].effect_type
= effect_type
;
403 memset(&prim
->deferred
.fxslot
[idx
].fx
, 0, sizeof(prim
->deferred
.fxslot
[idx
].fx
));
404 if(effect_type
== FXSLOT_EFFECT_REVERB
)
405 prim
->deferred
.fxslot
[idx
].fx
.reverb
= EnvironmentDefaults
[EAX_ENVIRONMENT_GENERIC
];
406 else if(effect_type
== FXSLOT_EFFECT_CHORUS
)
408 const EAXCHORUSPROPERTIES chorus_def
= CHORUS_PRESET_DEFAULT
;
409 prim
->deferred
.fxslot
[idx
].fx
.chorus
= chorus_def
;
412 FXSLOT_SET_DIRTY(prim
->dirty
.bit
, idx
, FXSLOT_EFFECT_BIT
);
414 prim
->deferred
.fxslot
[idx
].props
= *data
.props
;
416 FXSLOT_SET_DIRTY(prim
->dirty
.bit
, idx
, FXSLOT_VOL_BIT
);
417 FXSLOT_SET_DIRTY(prim
->dirty
.bit
, idx
, FXSLOT_LOCK_BIT
);
418 FXSLOT_SET_DIRTY(prim
->dirty
.bit
, idx
, FXSLOT_FLAGS_BIT
);
421 return DSERR_INVALIDPARAM
;
423 case EAXFXSLOT_LOADEFFECT
:
424 if(cbPropData
>= sizeof(GUID
))
426 union { const void *v
; const GUID
*guid
; } data
= { pPropData
};
428 TRACE("Load Effect: %s\n", debug_fxguid(data
.guid
));
430 effect_type
= FXSLOT_EFFECT_NULL
;
431 if(IsEqualGUID(data
.guid
, &EAX_REVERB_EFFECT
))
432 effect_type
= FXSLOT_EFFECT_REVERB
;
433 else if(IsEqualGUID(data
.guid
, &EAX_CHORUS_EFFECT
))
434 effect_type
= FXSLOT_EFFECT_CHORUS
;
435 else if(!IsEqualGUID(data
.guid
, &EAX_NULL_GUID
))
437 ERR("Unhandled effect: %s\n", debug_fxguid(data
.guid
));
438 return DSERR_INVALIDPARAM
;
441 if(prim
->deferred
.fxslot
[idx
].props
.lLock
== EAXFXSLOT_LOCKED
)
443 ERR("Attempting to change effect type for locked FXSlot\n");
444 return DSERR_INVALIDCALL
;
448 alEffecti(prim
->effect
[idx
], AL_EFFECT_TYPE
,
449 (effect_type
== FXSLOT_EFFECT_REVERB
) ? AL_EFFECT_EAXREVERB
:
450 (effect_type
== FXSLOT_EFFECT_CHORUS
) ? AL_EFFECT_CHORUS
:
453 if(alGetError() != AL_NO_ERROR
)
455 ERR("Failed to set effect type %lu\n", effect_type
);
456 return DSERR_INVALIDPARAM
;
459 prim
->deferred
.fxslot
[idx
].effect_type
= effect_type
;
460 memset(&prim
->deferred
.fxslot
[idx
].fx
, 0, sizeof(prim
->deferred
.fxslot
[idx
].fx
));
461 if(effect_type
== FXSLOT_EFFECT_REVERB
)
462 prim
->deferred
.fxslot
[idx
].fx
.reverb
= EnvironmentDefaults
[EAX_ENVIRONMENT_GENERIC
];
463 else if(effect_type
== FXSLOT_EFFECT_CHORUS
)
465 const EAXCHORUSPROPERTIES chorus_def
= CHORUS_PRESET_DEFAULT
;
466 prim
->deferred
.fxslot
[idx
].fx
.chorus
= chorus_def
;
468 prim
->deferred
.fxslot
[idx
].props
.guidLoadEffect
= *data
.guid
;
470 FXSLOT_SET_DIRTY(prim
->dirty
.bit
, idx
, FXSLOT_EFFECT_BIT
);
473 return DSERR_INVALIDPARAM
;
475 case EAXFXSLOT_VOLUME
:
476 if(cbPropData
>= sizeof(long))
478 union { const void *v
; const long *l
; } data
= { pPropData
};
479 TRACE("Volume: %ld\n", *data
.l
);
481 prim
->deferred
.fxslot
[idx
].props
.lVolume
= *data
.l
;
483 FXSLOT_SET_DIRTY(prim
->dirty
.bit
, idx
, FXSLOT_VOL_BIT
);
486 return DSERR_INVALIDPARAM
;
489 if(cbPropData
>= sizeof(long))
491 union { const void *v
; const long *l
; } data
= { pPropData
};
492 TRACE("Lock: %ld\n", *data
.l
);
494 prim
->deferred
.fxslot
[idx
].props
.lLock
= *data
.l
;
496 FXSLOT_SET_DIRTY(prim
->dirty
.bit
, idx
, FXSLOT_LOCK_BIT
);
499 return DSERR_INVALIDPARAM
;
501 case EAXFXSLOT_FLAGS
:
502 if(cbPropData
>= sizeof(DWORD
))
504 union { const void *v
; const DWORD
*dw
; } data
= { pPropData
};
505 TRACE("Flags: 0x%lx\n", *data
.dw
);
507 prim
->deferred
.fxslot
[idx
].props
.dwFlags
= *data
.dw
;
509 FXSLOT_SET_DIRTY(prim
->dirty
.bit
, idx
, FXSLOT_FLAGS_BIT
);
512 return DSERR_INVALIDPARAM
;
514 FIXME("Unhandled propid: 0x%08lx\n", propid
);
515 return E_PROP_ID_UNSUPPORTED
;
518 HRESULT
EAX4Slot_Get(DSPrimary
*prim
, LONG idx
, DWORD propid
, void *pPropData
, ULONG cbPropData
, ULONG
*pcbReturned
)
520 if(prim
->auxslot
[idx
] == 0)
521 return E_PROP_ID_UNSUPPORTED
;
523 if(propid
< EAXFXSLOT_NONE
)
525 if(prim
->deferred
.fxslot
[idx
].effect_type
== FXSLOT_EFFECT_REVERB
)
526 return EAXReverb_Get(prim
, idx
, propid
, pPropData
, cbPropData
, pcbReturned
);
527 if(prim
->deferred
.fxslot
[idx
].effect_type
== FXSLOT_EFFECT_CHORUS
)
528 return EAXChorus_Get(prim
, idx
, propid
, pPropData
, cbPropData
, pcbReturned
);
530 ERR("Unexpected null effect propid 0x%08lx\n", propid
);
531 return E_PROP_ID_UNSUPPORTED
;
539 case EAXFXSLOT_ALLPARAMETERS
:
540 GET_PROP(prim
->current
.fxslot
[idx
].props
, EAXFXSLOTPROPERTIES
);
541 case EAXFXSLOT_LOADEFFECT
:
542 GET_PROP(prim
->current
.fxslot
[idx
].props
.guidLoadEffect
, GUID
);
543 case EAXFXSLOT_VOLUME
:
544 GET_PROP(prim
->current
.fxslot
[idx
].props
.lVolume
, long);
546 GET_PROP(prim
->current
.fxslot
[idx
].props
.lLock
, long);
547 case EAXFXSLOT_FLAGS
:
548 GET_PROP(prim
->current
.fxslot
[idx
].props
.dwFlags
, DWORD
);
550 FIXME("Unhandled propid: 0x%08lx\n", propid
);
551 return E_PROP_ID_UNSUPPORTED
;
555 #define APPLY_DRY_PARAMS (1<<EAX_MAX_FXSLOTS)
556 #define APPLY_ALLWET_PARAMS (APPLY_DRY_PARAMS-1)
557 #define APPLY_ALL_PARAMS (APPLY_DRY_PARAMS | APPLY_ALLWET_PARAMS)
558 static void ApplyFilterParams(DSBuffer
*buf
, const EAXSOURCEPROPERTIES
*props
, int apply
)
560 /* The LFRatio properties determine how much the given level applies to low
561 * frequencies as well as high frequencies. Technically, given that the
562 * obstruction/occlusion/exclusion levels are the absolute level applied to
563 * high frequencies (relative to full-scale, according to the EAX 2.0 spec)
564 * while the HF filter gains are relative to the low, the HF gains should
565 * increase as LFRatio increases.
567 * However it seems Creative was either wrong when writing out the spec,
568 * or implemented it incorrectly, as the HF filter still applies in full
569 * regardless of the LFRatio. So to replicate the hardware behavior, we do
572 /* The interaction of ratios is pretty wierd. The typical combination of
573 * the two act as a minimal baseline, while the sum minus one is used when
574 * larger. This creates a more linear change with the individual ratios as
575 * Direct/RoomRatio goes beyond 1, but eases down as the two ratios go
578 float dryoccl
= maxF(props
->flOcclusionLFRatio
+props
->flOcclusionDirectRatio
-1.0f
,
579 props
->flOcclusionLFRatio
*props
->flOcclusionDirectRatio
) *
581 float dryocclhf
= props
->lOcclusion
*props
->flOcclusionDirectRatio
;
582 float room_mb
= props
->lRoom
+ props
->lExclusion
*props
->flExclusionLFRatio
+
583 maxF(props
->flOcclusionLFRatio
+props
->flOcclusionRoomRatio
-1.0f
,
584 props
->flOcclusionLFRatio
*props
->flOcclusionRoomRatio
) * props
->lOcclusion
;
585 float room_mbhf
= props
->lRoomHF
+ props
->lExclusion
+
586 props
->lOcclusion
*props
->flOcclusionRoomRatio
;
589 for(i
= 0;i
< EAX_MAX_FXSLOTS
;i
++)
591 const struct Send
*send
= &buf
->deferred
.send
[i
];
592 if((apply
&(1<<i
)) && buf
->filter
[1+i
])
594 /* Add the main room occlusion and exclusion properties with the
595 * sends', or take the minimum or maximum?
597 float mb
= room_mb
+ send
->lExclusion
*send
->flExclusionLFRatio
+
598 maxF(send
->flOcclusionLFRatio
+send
->flOcclusionRoomRatio
-1.0f
,
599 send
->flOcclusionLFRatio
*send
->flOcclusionRoomRatio
)*send
->lOcclusion
;
600 float mbhf
= room_mbhf
+ send
->lExclusion
+
601 send
->lOcclusion
*send
->flOcclusionRoomRatio
;
603 alFilterf(buf
->filter
[1+i
], AL_LOWPASS_GAIN
, mB_to_gain(minF(mb
, buf
->filter_mBLimit
)));
604 alFilterf(buf
->filter
[1+i
], AL_LOWPASS_GAINHF
, mB_to_gain(mbhf
));
607 /* Take the minimum, maximum, or average of the sends' direct occlusion with the main
610 dryoccl
= minF(dryoccl
,
611 maxF(send
->flOcclusionLFRatio
+send
->flOcclusionDirectRatio
-1.0f
,
612 send
->flOcclusionLFRatio
*send
->flOcclusionDirectRatio
) * send
->lOcclusion
614 dryocclhf
= minF(dryocclhf
, send
->lOcclusion
*send
->flOcclusionDirectRatio
);
616 if((apply
&APPLY_DRY_PARAMS
) && buf
->filter
[0])
618 float mb
= props
->lDirect
+ props
->lObstruction
*props
->flObstructionLFRatio
+ dryoccl
;
619 float mbhf
= props
->lDirectHF
+ props
->lObstruction
+ dryocclhf
;
621 alFilterf(buf
->filter
[0], AL_LOWPASS_GAIN
, mB_to_gain(minF(mb
, buf
->filter_mBLimit
)));
622 alFilterf(buf
->filter
[0], AL_LOWPASS_GAINHF
, mB_to_gain(mbhf
));
627 static EAXOBSTRUCTIONPROPERTIES
EAXSourceObstruction(const EAXSOURCEPROPERTIES
*props
)
629 EAXOBSTRUCTIONPROPERTIES ret
;
630 ret
.lObstruction
= props
->lObstruction
;
631 ret
.flObstructionLFRatio
= props
->flObstructionLFRatio
;
635 static EAXOCCLUSIONPROPERTIES
EAXSourceOcclusion(const EAXSOURCEPROPERTIES
*props
)
637 EAXOCCLUSIONPROPERTIES ret
;
638 ret
.lOcclusion
= props
->lOcclusion
;
639 ret
.flOcclusionLFRatio
= props
->flOcclusionLFRatio
;
640 ret
.flOcclusionRoomRatio
= props
->flOcclusionRoomRatio
;
641 ret
.flOcclusionDirectRatio
= props
->flOcclusionDirectRatio
;
645 static EAXEXCLUSIONPROPERTIES
EAXSourceExclusion(const EAXSOURCEPROPERTIES
*props
)
647 EAXEXCLUSIONPROPERTIES ret
;
648 ret
.lExclusion
= props
->lExclusion
;
649 ret
.flExclusionLFRatio
= props
->flExclusionLFRatio
;
653 static struct Send
*FindCurrentSend(DSBuffer
*buf
, const GUID
*guid
)
655 if(IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot0
))
656 return &buf
->current
.send
[0];
657 if(IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot1
))
658 return &buf
->current
.send
[1];
659 if(IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot2
))
660 return &buf
->current
.send
[2];
661 if(IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot3
))
662 return &buf
->current
.send
[3];
666 static struct Send
*FindDeferredSend(DSBuffer
*buf
, const GUID
*guid
)
668 if(IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot0
))
669 return &buf
->deferred
.send
[0];
670 if(IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot1
))
671 return &buf
->deferred
.send
[1];
672 if(IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot2
))
673 return &buf
->deferred
.send
[2];
674 if(IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot3
))
675 return &buf
->deferred
.send
[3];
679 HRESULT
EAX4Source_Query(DSBuffer
*buf
, DWORD propid
, ULONG
*pTypeSupport
)
681 if(!HAS_EXTENSION(buf
->share
, EXT_EFX
))
682 return E_PROP_ID_UNSUPPORTED
;
684 switch((propid
&~EAXSOURCE_PARAMETER_DEFERRED
))
687 case EAXSOURCE_ALLPARAMETERS
:
688 case EAXSOURCE_OBSTRUCTIONPARAMETERS
:
689 case EAXSOURCE_OCCLUSIONPARAMETERS
:
690 case EAXSOURCE_EXCLUSIONPARAMETERS
:
691 case EAXSOURCE_DIRECT
:
692 case EAXSOURCE_DIRECTHF
:
694 case EAXSOURCE_ROOMHF
:
695 case EAXSOURCE_OBSTRUCTION
:
696 case EAXSOURCE_OBSTRUCTIONLFRATIO
:
697 case EAXSOURCE_OCCLUSION
:
698 case EAXSOURCE_OCCLUSIONLFRATIO
:
699 case EAXSOURCE_OCCLUSIONROOMRATIO
:
700 case EAXSOURCE_OCCLUSIONDIRECTRATIO
:
701 case EAXSOURCE_EXCLUSION
:
702 case EAXSOURCE_EXCLUSIONLFRATIO
:
703 case EAXSOURCE_OUTSIDEVOLUMEHF
:
704 case EAXSOURCE_DOPPLERFACTOR
:
705 case EAXSOURCE_ROLLOFFFACTOR
:
706 case EAXSOURCE_ROOMROLLOFFFACTOR
:
707 case EAXSOURCE_AIRABSORPTIONFACTOR
:
708 case EAXSOURCE_FLAGS
:
709 case EAXSOURCE_SENDPARAMETERS
:
710 case EAXSOURCE_ALLSENDPARAMETERS
:
711 case EAXSOURCE_OCCLUSIONSENDPARAMETERS
:
712 case EAXSOURCE_EXCLUSIONSENDPARAMETERS
:
713 case EAXSOURCE_ACTIVEFXSLOTID
:
714 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
| KSPROPERTY_SUPPORT_SET
;
717 FIXME("Unhandled propid: 0x%08lx\n", propid
);
718 return E_PROP_ID_UNSUPPORTED
;
721 HRESULT
EAX4Source_Set(DSBuffer
*buf
, DWORD propid
, void *pPropData
, ULONG cbPropData
)
723 if(!HAS_EXTENSION(buf
->share
, EXT_EFX
))
724 return E_PROP_ID_UNSUPPORTED
;
731 case EAXSOURCE_ALLPARAMETERS
:
732 if(cbPropData
>= sizeof(EAXSOURCEPROPERTIES
))
736 const EAXSOURCEPROPERTIES
*props
;
737 } data
= { pPropData
};
738 TRACE("Parameters:\n\tDirect: %ld\n\tDirect HF: %ld\n\tRoom: %ld\n\tRoom HF: %ld\n\t"
739 "Obstruction: %ld\n\tObstruction LF Ratio: %f\n\tOcclusion: %ld\n\t"
740 "Occlusion LF Ratio: %f\n\tOcclusion Room Ratio: %f\n\t"
741 "Occlusion Direct Ratio: %f\n\tExclusion: %ld\n\tExclusion LF Ratio: %f\n\t"
742 "Outside Volume HF: %ld\n\tDoppler Factor: %f\n\tRolloff Factor: %f\n\t"
743 "Room Rolloff Factor: %f\n\tAir Absorb Factor: %f\n\tFlags: 0x%02lx\n",
744 data
.props
->lDirect
, data
.props
->lDirectHF
, data
.props
->lRoom
, data
.props
->lRoomHF
,
745 data
.props
->lObstruction
, data
.props
->flObstructionLFRatio
, data
.props
->lOcclusion
,
746 data
.props
->flOcclusionLFRatio
, data
.props
->flOcclusionRoomRatio
,
747 data
.props
->flOcclusionDirectRatio
, data
.props
->lExclusion
,
748 data
.props
->flExclusionLFRatio
, data
.props
->lOutsideVolumeHF
,
749 data
.props
->flDopplerFactor
, data
.props
->flRolloffFactor
,
750 data
.props
->flRoomRolloffFactor
, data
.props
->flAirAbsorptionFactor
,
754 buf
->deferred
.eax
= *data
.props
;
755 ApplyFilterParams(buf
, data
.props
, APPLY_ALL_PARAMS
);
757 buf
->dirty
.bit
.dry_filter
= 1;
758 buf
->dirty
.bit
.send_filters
= 1;
759 buf
->dirty
.bit
.doppler
= 1;
760 buf
->dirty
.bit
.rolloff
= 1;
761 buf
->dirty
.bit
.room_rolloff
= 1;
762 buf
->dirty
.bit
.cone_outsidevolumehf
= 1;
763 buf
->dirty
.bit
.air_absorb
= 1;
764 buf
->dirty
.bit
.flags
= 1;
767 return DSERR_INVALIDPARAM
;
768 case EAXSOURCE_OBSTRUCTIONPARAMETERS
:
769 if(cbPropData
>= sizeof(EAXOBSTRUCTIONPROPERTIES
))
773 const EAXOBSTRUCTIONPROPERTIES
*props
;
774 } data
= { pPropData
};
775 TRACE("Parameters:\n\tObstruction: %ld\n\tObstruction LF Ratio: %f\n",
776 data
.props
->lObstruction
, data
.props
->flObstructionLFRatio
);
778 buf
->deferred
.eax
.lObstruction
= data
.props
->lObstruction
;
779 buf
->deferred
.eax
.flObstructionLFRatio
= data
.props
->flObstructionLFRatio
;
780 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_DRY_PARAMS
);
782 buf
->dirty
.bit
.dry_filter
= 1;
785 return DSERR_INVALIDPARAM
;
786 case EAXSOURCE_OCCLUSIONPARAMETERS
:
787 if(cbPropData
>= sizeof(EAXOCCLUSIONPROPERTIES
))
791 const EAXOCCLUSIONPROPERTIES
*props
;
792 } data
= { pPropData
};
793 TRACE("Parameters:\n\tOcclusion: %ld\n\tOcclusion LF Ratio: %f\n\t"
794 "Occlusion Room Ratio: %f\n\tOcclusion Direct Ratio: %f\n",
795 data
.props
->lOcclusion
, data
.props
->flOcclusionLFRatio
,
796 data
.props
->flOcclusionRoomRatio
, data
.props
->flOcclusionDirectRatio
799 buf
->deferred
.eax
.lOcclusion
= data
.props
->lOcclusion
;
800 buf
->deferred
.eax
.flOcclusionLFRatio
= data
.props
->flOcclusionLFRatio
;
801 buf
->deferred
.eax
.flOcclusionRoomRatio
= data
.props
->flOcclusionRoomRatio
;
802 buf
->deferred
.eax
.flOcclusionDirectRatio
= data
.props
->flOcclusionDirectRatio
;
803 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALL_PARAMS
);
805 buf
->dirty
.bit
.dry_filter
= 1;
806 buf
->dirty
.bit
.send_filters
= 1;
809 return DSERR_INVALIDPARAM
;
810 case EAXSOURCE_EXCLUSIONPARAMETERS
:
811 if(cbPropData
>= sizeof(EAXEXCLUSIONPROPERTIES
))
815 const EAXEXCLUSIONPROPERTIES
*props
;
816 } data
= { pPropData
};
817 TRACE("Parameters:\n\tExclusion: %ld\n\tExclusion LF Ratio: %f\n",
818 data
.props
->lExclusion
, data
.props
->flExclusionLFRatio
);
820 buf
->deferred
.eax
.lExclusion
= data
.props
->lExclusion
;
821 buf
->deferred
.eax
.flExclusionLFRatio
= data
.props
->flExclusionLFRatio
;
822 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALLWET_PARAMS
);
824 buf
->dirty
.bit
.send_filters
= 1;
827 return DSERR_INVALIDPARAM
;
829 case EAXSOURCE_DIRECT
:
830 if(cbPropData
>= sizeof(long))
832 union { const void *v
; const long *l
; } data
= { pPropData
};
833 TRACE("Direct: %ld\n", *data
.l
);
835 buf
->deferred
.eax
.lDirect
= *data
.l
;
836 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_DRY_PARAMS
);
838 buf
->dirty
.bit
.dry_filter
= 1;
841 return DSERR_INVALIDPARAM
;
842 case EAXSOURCE_DIRECTHF
:
843 if(cbPropData
>= sizeof(long))
845 union { const void *v
; const long *l
; } data
= { pPropData
};
846 TRACE("Direct HF: %ld\n", *data
.l
);
848 buf
->deferred
.eax
.lDirectHF
= *data
.l
;
849 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_DRY_PARAMS
);
851 buf
->dirty
.bit
.dry_filter
= 1;
854 return DSERR_INVALIDPARAM
;
857 if(cbPropData
>= sizeof(long))
859 union { const void *v
; const long *l
; } data
= { pPropData
};
860 TRACE("Room: %ld\n", *data
.l
);
862 buf
->deferred
.eax
.lRoom
= *data
.l
;
863 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALLWET_PARAMS
);
865 buf
->dirty
.bit
.send_filters
= 1;
868 return DSERR_INVALIDPARAM
;
869 case EAXSOURCE_ROOMHF
:
870 if(cbPropData
>= sizeof(long))
872 union { const void *v
; const long *l
; } data
= { pPropData
};
873 TRACE("Room HF: %ld\n", *data
.l
);
875 buf
->deferred
.eax
.lRoomHF
= *data
.l
;
876 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALLWET_PARAMS
);
878 buf
->dirty
.bit
.send_filters
= 1;
881 return DSERR_INVALIDPARAM
;
883 case EAXSOURCE_OBSTRUCTION
:
884 if(cbPropData
>= sizeof(long))
886 union { const void *v
; const long *l
; } data
= { pPropData
};
887 TRACE("Obstruction: %ld\n", *data
.l
);
889 buf
->deferred
.eax
.lObstruction
= *data
.l
;
890 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_DRY_PARAMS
);
892 buf
->dirty
.bit
.dry_filter
= 1;
895 return DSERR_INVALIDPARAM
;
896 case EAXSOURCE_OBSTRUCTIONLFRATIO
:
897 if(cbPropData
>= sizeof(float))
899 union { const void *v
; const float *fl
; } data
= { pPropData
};
900 TRACE("Obstruction LF Ratio: %f\n", *data
.fl
);
902 buf
->deferred
.eax
.flObstructionLFRatio
= *data
.fl
;
903 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_DRY_PARAMS
);
905 buf
->dirty
.bit
.dry_filter
= 1;
908 return DSERR_INVALIDPARAM
;
910 case EAXSOURCE_OCCLUSION
:
911 if(cbPropData
>= sizeof(long))
913 union { const void *v
; const long *l
; } data
= { pPropData
};
914 TRACE("Occlusion: %ld\n", *data
.l
);
916 buf
->deferred
.eax
.lOcclusion
= *data
.l
;
917 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALL_PARAMS
);
919 buf
->dirty
.bit
.dry_filter
= 1;
920 buf
->dirty
.bit
.send_filters
= 1;
923 return DSERR_INVALIDPARAM
;
924 case EAXSOURCE_OCCLUSIONLFRATIO
:
925 if(cbPropData
>= sizeof(float))
927 union { const void *v
; const float *fl
; } data
= { pPropData
};
928 TRACE("Occlusion LF Ratio: %f\n", *data
.fl
);
930 buf
->deferred
.eax
.flOcclusionLFRatio
= *data
.fl
;
931 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALL_PARAMS
);
933 buf
->dirty
.bit
.dry_filter
= 1;
934 buf
->dirty
.bit
.send_filters
= 1;
937 return DSERR_INVALIDPARAM
;
938 case EAXSOURCE_OCCLUSIONROOMRATIO
:
939 if(cbPropData
>= sizeof(float))
941 union { const void *v
; const float *fl
; } data
= { pPropData
};
942 TRACE("Occlusion Room Ratio: %f\n", *data
.fl
);
944 buf
->deferred
.eax
.flOcclusionRoomRatio
= *data
.fl
;
945 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALLWET_PARAMS
);
947 buf
->dirty
.bit
.send_filters
= 1;
950 return DSERR_INVALIDPARAM
;
951 case EAXSOURCE_OCCLUSIONDIRECTRATIO
:
952 if(cbPropData
>= sizeof(float))
954 union { const void *v
; const float *fl
; } data
= { pPropData
};
955 TRACE("Occlusion Direct Ratio: %f\n", *data
.fl
);
957 buf
->deferred
.eax
.flOcclusionDirectRatio
= *data
.fl
;
958 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_DRY_PARAMS
);
960 buf
->dirty
.bit
.dry_filter
= 1;
963 return DSERR_INVALIDPARAM
;
965 case EAXSOURCE_EXCLUSION
:
966 if(cbPropData
>= sizeof(long))
968 union { const void *v
; const long *l
; } data
= { pPropData
};
969 TRACE("Exclusion: %ld\n", *data
.l
);
971 buf
->deferred
.eax
.lExclusion
= *data
.l
;
972 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALLWET_PARAMS
);
974 buf
->dirty
.bit
.send_filters
= 1;
977 return DSERR_INVALIDPARAM
;
978 case EAXSOURCE_EXCLUSIONLFRATIO
:
979 if(cbPropData
>= sizeof(float))
981 union { const void *v
; const float *fl
; } data
= { pPropData
};
982 TRACE("Exclusion LF Ratio: %f\n", *data
.fl
);
984 buf
->deferred
.eax
.flExclusionLFRatio
= *data
.fl
;
985 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALLWET_PARAMS
);
987 buf
->dirty
.bit
.send_filters
= 1;
990 return DSERR_INVALIDPARAM
;
992 case EAXSOURCE_OUTSIDEVOLUMEHF
:
993 if(cbPropData
>= sizeof(long))
995 union { const void *v
; const long *l
; } data
= { pPropData
};
996 TRACE("Outisde Volume HF: %ld\n", *data
.l
);
998 buf
->deferred
.eax
.lOutsideVolumeHF
= *data
.l
;
1000 buf
->dirty
.bit
.cone_outsidevolumehf
= 1;
1003 return DSERR_INVALIDPARAM
;
1005 case EAXSOURCE_DOPPLERFACTOR
:
1006 if(cbPropData
>= sizeof(float))
1008 union { const void *v
; const float *fl
; } data
= { pPropData
};
1009 TRACE("Doppler Factor: %f\n", *data
.fl
);
1011 buf
->deferred
.eax
.flDopplerFactor
= *data
.fl
;
1013 buf
->dirty
.bit
.doppler
= 1;
1016 return DSERR_INVALIDPARAM
;
1018 case EAXSOURCE_ROLLOFFFACTOR
:
1019 if(cbPropData
>= sizeof(float))
1021 union { const void *v
; const float *fl
; } data
= { pPropData
};
1022 TRACE("Rolloff Factor: %f\n", *data
.fl
);
1024 buf
->deferred
.eax
.flRolloffFactor
= *data
.fl
;
1026 buf
->dirty
.bit
.rolloff
= 1;
1029 return DSERR_INVALIDPARAM
;
1031 case EAXSOURCE_ROOMROLLOFFFACTOR
:
1032 if(cbPropData
>= sizeof(float))
1034 union { const void *v
; const float *fl
; } data
= { pPropData
};
1035 TRACE("Room Rolloff Factor: %f\n", *data
.fl
);
1037 buf
->deferred
.eax
.flRoomRolloffFactor
= *data
.fl
;
1039 buf
->dirty
.bit
.room_rolloff
= 1;
1042 return DSERR_INVALIDPARAM
;
1044 case EAXSOURCE_AIRABSORPTIONFACTOR
:
1045 if(cbPropData
>= sizeof(float))
1047 union { const void *v
; const float *fl
; } data
= { pPropData
};
1048 TRACE("Air Absorb Factor: %f\n", *data
.fl
);
1050 buf
->deferred
.eax
.flAirAbsorptionFactor
= *data
.fl
;
1052 buf
->dirty
.bit
.air_absorb
= 1;
1055 return DSERR_INVALIDPARAM
;
1057 case EAXSOURCE_FLAGS
:
1058 if(cbPropData
>= sizeof(DWORD
))
1060 union { const void *v
; const DWORD
*dw
; } data
= { pPropData
};
1061 TRACE("Flags: 0x%lx\n", *data
.dw
);
1063 buf
->deferred
.eax
.dwFlags
= *data
.dw
;
1065 buf
->dirty
.bit
.flags
= 1;
1068 return DSERR_INVALIDPARAM
;
1070 case EAXSOURCE_SENDPARAMETERS
:
1071 if(cbPropData
>= sizeof(EAXSOURCESENDPROPERTIES
))
1073 union { const void *v
; const EAXSOURCESENDPROPERTIES
*send
; } data
= { pPropData
};
1074 struct Send
*srcsend
[EAX_MAX_FXSLOTS
];
1075 LONG count
= cbPropData
/ sizeof(EAXSOURCESENDPROPERTIES
);
1078 if(count
> buf
->share
->num_slots
)
1080 ERR("Setting %ld sends, only %d supported\n", count
, buf
->share
->num_slots
);
1081 return DSERR_INVALIDPARAM
;
1084 for(i
= 0;i
< count
;++i
)
1086 TRACE("Send parameters:\n\tReceiving: %s\n\tSend: %ld\n\tSend HF: %ld\n",
1087 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
),
1088 data
.send
[i
].lSend
, data
.send
[i
].lSendHF
1090 srcsend
[i
] = FindDeferredSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1093 ERR("Failed to find active FXSlot target: %s\n",
1094 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1095 return DSERR_INVALIDPARAM
;
1097 wetmask
|= 1 << (srcsend
[i
]-buf
->deferred
.send
);
1100 for(i
= 0;i
< count
;++i
)
1102 srcsend
[i
]->lSend
= data
.send
[i
].lSend
;
1103 srcsend
[i
]->lSendHF
= data
.send
[i
].lSendHF
;
1105 ApplyFilterParams(buf
, &buf
->deferred
.eax
, wetmask
);
1107 buf
->dirty
.bit
.send_filters
= 1;
1110 return DSERR_INVALIDPARAM
;
1111 case EAXSOURCE_ALLSENDPARAMETERS
:
1112 if(cbPropData
>= sizeof(EAXSOURCEALLSENDPROPERTIES
))
1114 union { const void *v
; const EAXSOURCEALLSENDPROPERTIES
*send
; } data
= { pPropData
};
1115 struct Send
*srcsend
[EAX_MAX_FXSLOTS
];
1116 LONG count
= cbPropData
/ sizeof(EAXSOURCEALLSENDPROPERTIES
);
1119 if(count
> buf
->share
->num_slots
)
1121 ERR("Setting %ld sends, only %d supported\n", count
, buf
->share
->num_slots
);
1122 return DSERR_INVALIDPARAM
;
1125 for(i
= 0;i
< count
;++i
)
1127 TRACE("All send parameters:\n\tReceiving: %s\n\tSend: %ld\n\tSend HF: %ld\n\t"
1128 "Occlusion: %ld\n\tOcclusion LF Ratio: %f\n\tOcclusion Room Ratio: %f\n\t"
1129 "Occlusion Direct Ratio: %f\n\tExclusion: %ld\n\tExclusion LF Ratio: %f\n",
1130 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
),
1131 data
.send
[i
].lSend
, data
.send
[i
].lSendHF
, data
.send
[i
].lOcclusion
,
1132 data
.send
[i
].flOcclusionLFRatio
, data
.send
[i
].flOcclusionRoomRatio
,
1133 data
.send
[i
].flOcclusionDirectRatio
, data
.send
[i
].lExclusion
,
1134 data
.send
[i
].flExclusionLFRatio
1136 srcsend
[i
] = FindDeferredSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1139 ERR("Failed to find active FXSlot target: %s\n",
1140 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1141 return DSERR_INVALIDPARAM
;
1143 wetmask
|= 1 << (srcsend
[i
]-buf
->deferred
.send
);
1146 for(i
= 0;i
< count
;++i
)
1148 srcsend
[i
]->lSend
= data
.send
[i
].lSend
;
1149 srcsend
[i
]->lSendHF
= data
.send
[i
].lSendHF
;
1150 srcsend
[i
]->lOcclusion
= data
.send
[i
].lOcclusion
;
1151 srcsend
[i
]->flOcclusionLFRatio
= data
.send
[i
].flOcclusionLFRatio
;
1152 srcsend
[i
]->flOcclusionRoomRatio
= data
.send
[i
].flOcclusionRoomRatio
;
1153 srcsend
[i
]->flOcclusionDirectRatio
= data
.send
[i
].flOcclusionDirectRatio
;
1154 srcsend
[i
]->lExclusion
= data
.send
[i
].lExclusion
;
1155 srcsend
[i
]->flExclusionLFRatio
= data
.send
[i
].flExclusionLFRatio
;
1157 ApplyFilterParams(buf
, &buf
->deferred
.eax
, wetmask
|APPLY_DRY_PARAMS
);
1159 buf
->dirty
.bit
.dry_filter
= 1;
1160 buf
->dirty
.bit
.send_filters
= 1;
1163 return DSERR_INVALIDPARAM
;
1164 case EAXSOURCE_OCCLUSIONSENDPARAMETERS
:
1165 if(cbPropData
>= sizeof(EAXSOURCEOCCLUSIONSENDPROPERTIES
))
1167 union { const void *v
; const EAXSOURCEOCCLUSIONSENDPROPERTIES
*send
; } data
= { pPropData
};
1168 struct Send
*srcsend
[EAX_MAX_FXSLOTS
];
1169 LONG count
= cbPropData
/ sizeof(EAXSOURCEOCCLUSIONSENDPROPERTIES
);
1172 if(count
> buf
->share
->num_slots
)
1174 ERR("Setting %ld sends, only %d supported\n", count
, buf
->share
->num_slots
);
1175 return DSERR_INVALIDPARAM
;
1178 for(i
= 0;i
< count
;++i
)
1180 TRACE("Occlusion send parameters:\n\tReceiving: %s\n\tOcclusion: %ld\n\t"
1181 "Occlusion LF Ratio: %f\n\tOcclusion Room Ratio: %f\n\t"
1182 "Occlusion Direct Ratio: %f\n",
1183 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
), data
.send
[i
].lOcclusion
,
1184 data
.send
[i
].flOcclusionLFRatio
, data
.send
[i
].flOcclusionRoomRatio
,
1185 data
.send
[i
].flOcclusionDirectRatio
1187 srcsend
[i
] = FindDeferredSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1190 ERR("Failed to find active FXSlot target: %s\n",
1191 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1192 return DSERR_INVALIDPARAM
;
1194 wetmask
|= 1 << (srcsend
[i
]-buf
->deferred
.send
);
1197 for(i
= 0;i
< count
;++i
)
1199 srcsend
[i
]->lOcclusion
= data
.send
[i
].lOcclusion
;
1200 srcsend
[i
]->flOcclusionLFRatio
= data
.send
[i
].flOcclusionLFRatio
;
1201 srcsend
[i
]->flOcclusionRoomRatio
= data
.send
[i
].flOcclusionRoomRatio
;
1202 srcsend
[i
]->flOcclusionDirectRatio
= data
.send
[i
].flOcclusionDirectRatio
;
1204 ApplyFilterParams(buf
, &buf
->deferred
.eax
, wetmask
|APPLY_DRY_PARAMS
);
1206 buf
->dirty
.bit
.dry_filter
= 1;
1207 buf
->dirty
.bit
.send_filters
= 1;
1210 return DSERR_INVALIDPARAM
;
1211 case EAXSOURCE_EXCLUSIONSENDPARAMETERS
:
1212 if(cbPropData
>= sizeof(EAXSOURCEEXCLUSIONSENDPROPERTIES
))
1214 union { const void *v
; const EAXSOURCEEXCLUSIONSENDPROPERTIES
*send
; } data
= { pPropData
};
1215 struct Send
*srcsend
[EAX_MAX_FXSLOTS
];
1216 LONG count
= cbPropData
/ sizeof(EAXSOURCEEXCLUSIONSENDPROPERTIES
);
1219 if(count
> buf
->share
->num_slots
)
1221 ERR("Setting %ld sends, only %d supported\n", count
, buf
->share
->num_slots
);
1222 return DSERR_INVALIDPARAM
;
1225 for(i
= 0;i
< count
;++i
)
1227 TRACE("Exclusion send parameters:\n\tReceiving: %s\n\tExclusion: %ld\n\t"
1228 "Exclusion LF Ratio: %f\n",
1229 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
),
1230 data
.send
[i
].lExclusion
, data
.send
[i
].flExclusionLFRatio
1232 srcsend
[i
] = FindDeferredSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1235 ERR("Failed to find active FXSlot target: %s\n",
1236 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1237 return DSERR_INVALIDPARAM
;
1239 wetmask
|= 1 << (srcsend
[i
]-buf
->deferred
.send
);
1242 for(i
= 0;i
< count
;++i
)
1244 srcsend
[i
]->lExclusion
= data
.send
[i
].lExclusion
;
1245 srcsend
[i
]->flExclusionLFRatio
= data
.send
[i
].flExclusionLFRatio
;
1247 ApplyFilterParams(buf
, &buf
->deferred
.eax
, wetmask
);
1249 buf
->dirty
.bit
.send_filters
= 1;
1252 return DSERR_INVALIDPARAM
;
1254 case EAXSOURCE_ACTIVEFXSLOTID
:
1255 if(cbPropData
&& (cbPropData
%sizeof(GUID
)) == 0)
1257 union { const void *v
; const GUID
*guid
; } data
= { pPropData
};
1258 DWORD targets
[EAX_MAX_ACTIVE_FXSLOTS
];
1259 LONG count
= cbPropData
/ sizeof(GUID
);
1262 if(count
> buf
->share
->num_sends
)
1264 ERR("Setting %ld sends, only %d supported\n", count
, buf
->share
->num_sends
);
1265 return DSERR_INVALIDPARAM
;
1268 for(i
= 0;i
< count
;i
++)
1270 TRACE("Active FXSlot %ld: %s\n", i
, debug_fxslot(&data
.guid
[i
]));
1272 targets
[i
] = FXSLOT_TARGET_NULL
;
1273 if(IsEqualGUID(&data
.guid
[i
], &EAXPROPERTYID_EAX40_FXSlot0
))
1274 targets
[i
] = FXSLOT_TARGET_0
;
1275 else if(IsEqualGUID(&data
.guid
[i
], &EAXPROPERTYID_EAX40_FXSlot1
))
1276 targets
[i
] = FXSLOT_TARGET_1
;
1277 else if(IsEqualGUID(&data
.guid
[i
], &EAXPROPERTYID_EAX40_FXSlot2
))
1278 targets
[i
] = FXSLOT_TARGET_2
;
1279 else if(IsEqualGUID(&data
.guid
[i
], &EAXPROPERTYID_EAX40_FXSlot3
))
1280 targets
[i
] = FXSLOT_TARGET_3
;
1281 else if(IsEqualGUID(&data
.guid
[i
], &EAX_PrimaryFXSlotID
))
1282 targets
[i
] = FXSLOT_TARGET_PRIMARY
;
1283 if(targets
[i
] == FXSLOT_TARGET_NULL
&& !IsEqualGUID(&data
.guid
[i
], &EAX_NULL_GUID
))
1285 ERR("Invalid FXSlot: %s\n", debug_fxslot(&data
.guid
[i
]));
1286 return DSERR_INVALIDPARAM
;
1290 for(i
= 0;i
< count
;++i
)
1291 buf
->deferred
.fxslot_targets
[i
] = targets
[i
];
1292 buf
->dirty
.bit
.send_filters
= 1;
1295 return DSERR_INVALIDPARAM
;
1297 FIXME("Unhandled propid: 0x%08lx\n", propid
);
1298 return E_PROP_ID_UNSUPPORTED
;
1301 HRESULT
EAX4Source_Get(DSBuffer
*buf
, DWORD propid
, void *pPropData
, ULONG cbPropData
, ULONG
*pcbReturned
)
1303 if(!HAS_EXTENSION(buf
->share
, EXT_EFX
))
1304 return E_PROP_ID_UNSUPPORTED
;
1308 case EAXSOURCE_NONE
:
1312 case EAXSOURCE_ALLPARAMETERS
:
1313 GET_PROP(buf
->current
.eax
, EAXSOURCEPROPERTIES
);
1315 case EAXSOURCE_OBSTRUCTIONPARAMETERS
:
1316 GET_PROP(EAXSourceObstruction(&buf
->current
.eax
), EAXOBSTRUCTIONPROPERTIES
);
1317 case EAXSOURCE_OCCLUSIONPARAMETERS
:
1318 GET_PROP(EAXSourceOcclusion(&buf
->current
.eax
), EAXOCCLUSIONPROPERTIES
);
1319 case EAXSOURCE_EXCLUSIONPARAMETERS
:
1320 GET_PROP(EAXSourceExclusion(&buf
->current
.eax
), EAXEXCLUSIONPROPERTIES
);
1322 case EAXSOURCE_DIRECT
:
1323 GET_PROP(buf
->current
.eax
.lDirect
, long);
1324 case EAXSOURCE_DIRECTHF
:
1325 GET_PROP(buf
->current
.eax
.lDirectHF
, long);
1327 case EAXSOURCE_ROOM
:
1328 GET_PROP(buf
->current
.eax
.lRoom
, long);
1329 case EAXSOURCE_ROOMHF
:
1330 GET_PROP(buf
->current
.eax
.lRoomHF
, long);
1332 case EAXSOURCE_OBSTRUCTION
:
1333 GET_PROP(buf
->current
.eax
.lObstruction
, long);
1334 case EAXSOURCE_OBSTRUCTIONLFRATIO
:
1335 GET_PROP(buf
->current
.eax
.flObstructionLFRatio
, float);
1337 case EAXSOURCE_OCCLUSION
:
1338 GET_PROP(buf
->current
.eax
.lOcclusion
, long);
1339 case EAXSOURCE_OCCLUSIONLFRATIO
:
1340 GET_PROP(buf
->current
.eax
.flOcclusionLFRatio
, float);
1341 case EAXSOURCE_OCCLUSIONROOMRATIO
:
1342 GET_PROP(buf
->current
.eax
.flOcclusionRoomRatio
, float);
1343 case EAXSOURCE_OCCLUSIONDIRECTRATIO
:
1344 GET_PROP(buf
->current
.eax
.flOcclusionDirectRatio
, float);
1346 case EAXSOURCE_EXCLUSION
:
1347 GET_PROP(buf
->current
.eax
.lExclusion
, long);
1348 case EAXSOURCE_EXCLUSIONLFRATIO
:
1349 GET_PROP(buf
->current
.eax
.flExclusionLFRatio
, float);
1351 case EAXSOURCE_OUTSIDEVOLUMEHF
:
1352 GET_PROP(buf
->current
.eax
.lOutsideVolumeHF
, long);
1354 case EAXSOURCE_DOPPLERFACTOR
:
1355 GET_PROP(buf
->current
.eax
.flDopplerFactor
, float);
1357 case EAXSOURCE_ROLLOFFFACTOR
:
1358 GET_PROP(buf
->current
.eax
.flRolloffFactor
, float);
1359 case EAXSOURCE_ROOMROLLOFFFACTOR
:
1360 GET_PROP(buf
->current
.eax
.flRoomRolloffFactor
, float);
1362 case EAXSOURCE_AIRABSORPTIONFACTOR
:
1363 GET_PROP(buf
->current
.eax
.flAirAbsorptionFactor
, float);
1365 case EAXSOURCE_FLAGS
:
1366 GET_PROP(buf
->current
.eax
.dwFlags
, DWORD
);
1368 case EAXSOURCE_SENDPARAMETERS
:
1369 if(cbPropData
>= sizeof(EAXSOURCESENDPROPERTIES
))
1371 union { void *v
; EAXSOURCESENDPROPERTIES
*send
; } data
= { pPropData
};
1372 const struct Send
*srcsend
[EAX_MAX_FXSLOTS
];
1373 LONG count
= minI(cbPropData
/ sizeof(EAXSOURCESENDPROPERTIES
), EAX_MAX_FXSLOTS
);
1376 for(i
= 0;i
< count
;++i
)
1378 srcsend
[i
] = FindCurrentSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1381 ERR("Failed to find active FXSlot target: %s\n",
1382 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1383 return DSERR_INVALIDPARAM
;
1387 for(i
= 0;i
< count
;++i
)
1389 data
.send
[i
].lSend
= srcsend
[i
]->lSend
;
1390 data
.send
[i
].lSendHF
= srcsend
[i
]->lSendHF
;
1392 *pcbReturned
= sizeof(EAXSOURCESENDPROPERTIES
)*count
;
1395 return DSERR_INVALIDPARAM
;
1397 case EAXSOURCE_ALLSENDPARAMETERS
:
1398 if(cbPropData
>= sizeof(EAXSOURCEALLSENDPROPERTIES
))
1400 union { void *v
; EAXSOURCEALLSENDPROPERTIES
*send
; } data
= { pPropData
};
1401 const struct Send
*srcsend
[EAX_MAX_FXSLOTS
];
1402 LONG count
= minI(cbPropData
/ sizeof(EAXSOURCEALLSENDPROPERTIES
), EAX_MAX_FXSLOTS
);
1405 for(i
= 0;i
< count
;++i
)
1407 srcsend
[i
] = FindCurrentSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1410 ERR("Failed to find active FXSlot target: %s\n",
1411 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1412 return DSERR_INVALIDPARAM
;
1416 for(i
= 0;i
< count
;++i
)
1418 data
.send
[i
].lSend
= srcsend
[i
]->lSend
;
1419 data
.send
[i
].lSendHF
= srcsend
[i
]->lSendHF
;
1420 data
.send
[i
].lOcclusion
= srcsend
[i
]->lOcclusion
;
1421 data
.send
[i
].flOcclusionLFRatio
= srcsend
[i
]->flOcclusionLFRatio
;
1422 data
.send
[i
].flOcclusionRoomRatio
= srcsend
[i
]->flOcclusionRoomRatio
;
1423 data
.send
[i
].flOcclusionDirectRatio
= srcsend
[i
]->flOcclusionDirectRatio
;
1424 data
.send
[i
].lExclusion
= srcsend
[i
]->lExclusion
;
1425 data
.send
[i
].flExclusionLFRatio
= srcsend
[i
]->flExclusionLFRatio
;
1427 *pcbReturned
= sizeof(EAXSOURCEALLSENDPROPERTIES
)*count
;
1430 return DSERR_INVALIDPARAM
;
1431 case EAXSOURCE_OCCLUSIONSENDPARAMETERS
:
1432 if(cbPropData
>= sizeof(EAXSOURCEOCCLUSIONSENDPROPERTIES
))
1434 union { void *v
; EAXSOURCEOCCLUSIONSENDPROPERTIES
*send
; } data
= { pPropData
};
1435 const struct Send
*srcsend
[EAX_MAX_FXSLOTS
];
1436 LONG count
= minI(cbPropData
/ sizeof(EAXSOURCEOCCLUSIONSENDPROPERTIES
),
1440 for(i
= 0;i
< count
;++i
)
1442 srcsend
[i
] = FindCurrentSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1445 ERR("Failed to find active FXSlot target: %s\n",
1446 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1447 return DSERR_INVALIDPARAM
;
1451 for(i
= 0;i
< count
;++i
)
1453 data
.send
[i
].lOcclusion
= srcsend
[i
]->lOcclusion
;
1454 data
.send
[i
].flOcclusionLFRatio
= srcsend
[i
]->flOcclusionLFRatio
;
1455 data
.send
[i
].flOcclusionRoomRatio
= srcsend
[i
]->flOcclusionRoomRatio
;
1456 data
.send
[i
].flOcclusionDirectRatio
= srcsend
[i
]->flOcclusionDirectRatio
;
1458 *pcbReturned
= sizeof(EAXSOURCEOCCLUSIONSENDPROPERTIES
)*count
;
1461 return DSERR_INVALIDPARAM
;
1462 case EAXSOURCE_EXCLUSIONSENDPARAMETERS
:
1463 if(cbPropData
>= sizeof(EAXSOURCEEXCLUSIONSENDPROPERTIES
))
1465 union { void *v
; EAXSOURCEEXCLUSIONSENDPROPERTIES
*send
; } data
= { pPropData
};
1466 const struct Send
*srcsend
[EAX_MAX_FXSLOTS
];
1467 LONG count
= minI(cbPropData
/ sizeof(EAXSOURCEEXCLUSIONSENDPROPERTIES
),
1471 for(i
= 0;i
< count
;++i
)
1473 srcsend
[i
] = FindCurrentSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1476 ERR("Failed to find active FXSlot target: %s\n",
1477 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1478 return DSERR_INVALIDPARAM
;
1482 for(i
= 0;i
< count
;++i
)
1484 data
.send
[i
].lExclusion
= srcsend
[i
]->lExclusion
;
1485 data
.send
[i
].flExclusionLFRatio
= srcsend
[i
]->flExclusionLFRatio
;
1487 *pcbReturned
= sizeof(EAXSOURCEEXCLUSIONSENDPROPERTIES
)*count
;
1490 return DSERR_INVALIDPARAM
;
1492 case EAXSOURCE_ACTIVEFXSLOTID
:
1493 if(cbPropData
>= sizeof(GUID
))
1495 union { void *v
; GUID
*guid
; } data
= { pPropData
};
1496 LONG count
= minI(cbPropData
/ sizeof(GUID
), EAX_MAX_ACTIVE_FXSLOTS
);
1499 for(i
= 0;i
< count
;++i
)
1501 if(buf
->current
.fxslot_targets
[i
] == FXSLOT_TARGET_0
)
1502 data
.guid
[i
] = EAXPROPERTYID_EAX40_FXSlot0
;
1503 else if(buf
->current
.fxslot_targets
[i
] == FXSLOT_TARGET_1
)
1504 data
.guid
[i
] = EAXPROPERTYID_EAX40_FXSlot1
;
1505 else if(buf
->current
.fxslot_targets
[i
] == FXSLOT_TARGET_2
)
1506 data
.guid
[i
] = EAXPROPERTYID_EAX40_FXSlot2
;
1507 else if(buf
->current
.fxslot_targets
[i
] == FXSLOT_TARGET_3
)
1508 data
.guid
[i
] = EAXPROPERTYID_EAX40_FXSlot3
;
1509 else if(buf
->current
.fxslot_targets
[i
] == FXSLOT_TARGET_PRIMARY
)
1510 data
.guid
[i
] = EAX_PrimaryFXSlotID
;
1511 else /*if(buf->current.fxslot_targets[i] >= FXSLOT_TARGET_NULL)*/
1512 data
.guid
[i
] = EAX_NULL_GUID
;
1515 *pcbReturned
= sizeof(GUID
)*count
;
1518 return DSERR_INVALIDPARAM
;
1520 FIXME("Unhandled propid: 0x%08lx\n", propid
);
1521 return E_PROP_ID_UNSUPPORTED
;