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_WET0_PARAMS 1
556 #define APPLY_WET1_PARAMS 2
557 #define APPLY_WET2_PARAMS 3
558 #define APPLY_WET3_PARAMS 4
559 #define APPLY_DRY_PARAMS 4
560 #define APPLY_ALL_PARAMS (APPLY_WET0_PARAMS | APPLY_WET1_PARAMS | APPLY_WET2_PARAMS | APPLY_WET3_PARAMS | APPLY_DRY_PARAMS)
561 #define APPLY_ALLWET_PARAMS (APPLY_WET0_PARAMS | APPLY_WET1_PARAMS | APPLY_WET2_PARAMS | APPLY_WET3_PARAMS)
562 static void ApplyFilterParams(DSBuffer
*buf
, const EAXSOURCEPROPERTIES
*props
, int apply
)
564 /* The LFRatio properties determine how much the given level applies to low
565 * frequencies as well as high frequencies. Technically, given that the
566 * obstruction/occlusion/exclusion levels are the absolute level applied to
567 * high frequencies (relative to full-scale, according to the EAX 2.0 spec)
568 * while the HF filter gains are relative to the low, the HF gains should
569 * increase as LFRatio increases.
571 * However it seems Creative was either wrong when writing out the spec,
572 * or implemented it incorrectly, as the HF filter still applies in full
573 * regardless of the LFRatio. So to replicate the hardware behavior, we do
576 /* The interaction of ratios is pretty wierd. The typical combination of
577 * the two act as a minimal baseline, while the sum minus one is used when
578 * larger. This creates a more linear change with the individual ratios as
579 * Direct/RoomRatio goes beyond 1, but eases down as the two ratios go
582 float dryoccl
= maxF(props
->flOcclusionLFRatio
+props
->flOcclusionDirectRatio
-1.0f
,
583 props
->flOcclusionLFRatio
*props
->flOcclusionDirectRatio
) *
585 float dryocclhf
= props
->lOcclusion
*props
->flOcclusionDirectRatio
;
586 float room_mb
= props
->lRoom
+ props
->lExclusion
*props
->flExclusionLFRatio
+
587 maxF(props
->flOcclusionLFRatio
+props
->flOcclusionRoomRatio
-1.0f
,
588 props
->flOcclusionLFRatio
*props
->flOcclusionRoomRatio
) * props
->lOcclusion
;
589 float room_mbhf
= props
->lRoomHF
+ props
->lExclusion
+
590 props
->lOcclusion
*props
->flOcclusionRoomRatio
;
593 for(i
= 0;i
< EAX_MAX_FXSLOTS
;i
++)
595 const struct Send
*send
= &buf
->deferred
.send
[i
];
596 if((apply
&(1<<i
)) && buf
->filter
[1+i
])
598 /* Add the main room occlusion and exclusion properties with the
599 * sends', or take the minimum or maximum?
601 float mb
= room_mb
+ send
->lExclusion
*send
->flExclusionLFRatio
+
602 maxF(send
->flOcclusionLFRatio
+send
->flOcclusionRoomRatio
-1.0f
,
603 send
->flOcclusionLFRatio
*send
->flOcclusionRoomRatio
)*send
->lOcclusion
;
604 float mbhf
= room_mbhf
+ send
->lExclusion
+
605 send
->lOcclusion
*send
->flOcclusionRoomRatio
;
607 alFilterf(buf
->filter
[1+i
], AL_LOWPASS_GAIN
, mB_to_gain(minF(mb
, buf
->filter_mBLimit
)));
608 alFilterf(buf
->filter
[1+i
], AL_LOWPASS_GAINHF
, mB_to_gain(mbhf
));
611 /* Take the minimum, maximum, or average of the sends' direct occlusion with the main
614 dryoccl
= minF(dryoccl
,
615 maxF(send
->flOcclusionLFRatio
+send
->flOcclusionDirectRatio
-1.0f
,
616 send
->flOcclusionLFRatio
*send
->flOcclusionDirectRatio
) * send
->lOcclusion
618 dryocclhf
= minF(dryocclhf
, send
->lOcclusion
*send
->flOcclusionDirectRatio
);
620 if((apply
&APPLY_DRY_PARAMS
) && buf
->filter
[0])
622 float mb
= props
->lDirect
+ props
->lObstruction
*props
->flObstructionLFRatio
+ dryoccl
;
623 float mbhf
= props
->lDirectHF
+ props
->lObstruction
+ dryocclhf
;
625 alFilterf(buf
->filter
[0], AL_LOWPASS_GAIN
, mB_to_gain(minF(mb
, buf
->filter_mBLimit
)));
626 alFilterf(buf
->filter
[0], AL_LOWPASS_GAINHF
, mB_to_gain(mbhf
));
631 static EAXOBSTRUCTIONPROPERTIES
EAXSourceObstruction(const EAXSOURCEPROPERTIES
*props
)
633 EAXOBSTRUCTIONPROPERTIES ret
;
634 ret
.lObstruction
= props
->lObstruction
;
635 ret
.flObstructionLFRatio
= props
->flObstructionLFRatio
;
639 static EAXOCCLUSIONPROPERTIES
EAXSourceOcclusion(const EAXSOURCEPROPERTIES
*props
)
641 EAXOCCLUSIONPROPERTIES ret
;
642 ret
.lOcclusion
= props
->lOcclusion
;
643 ret
.flOcclusionLFRatio
= props
->flOcclusionLFRatio
;
644 ret
.flOcclusionRoomRatio
= props
->flOcclusionRoomRatio
;
645 ret
.flOcclusionDirectRatio
= props
->flOcclusionDirectRatio
;
649 static EAXEXCLUSIONPROPERTIES
EAXSourceExclusion(const EAXSOURCEPROPERTIES
*props
)
651 EAXEXCLUSIONPROPERTIES ret
;
652 ret
.lExclusion
= props
->lExclusion
;
653 ret
.flExclusionLFRatio
= props
->flExclusionLFRatio
;
657 static struct Send
*FindCurrentSend(DSBuffer
*buf
, const GUID
*guid
)
659 if(IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot0
))
660 return &buf
->current
.send
[0];
661 if(IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot1
))
662 return &buf
->current
.send
[1];
663 if(IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot2
))
664 return &buf
->current
.send
[2];
665 if(IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot3
))
666 return &buf
->current
.send
[3];
670 static struct Send
*FindDeferredSend(DSBuffer
*buf
, const GUID
*guid
)
672 if(IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot0
))
673 return &buf
->deferred
.send
[0];
674 if(IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot1
))
675 return &buf
->deferred
.send
[1];
676 if(IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot2
))
677 return &buf
->deferred
.send
[2];
678 if(IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot3
))
679 return &buf
->deferred
.send
[3];
683 HRESULT
EAX4Source_Query(DSBuffer
*buf
, DWORD propid
, ULONG
*pTypeSupport
)
685 if(!HAS_EXTENSION(buf
->share
, EXT_EFX
))
686 return E_PROP_ID_UNSUPPORTED
;
688 switch((propid
&~EAXSOURCE_PARAMETER_DEFERRED
))
691 case EAXSOURCE_ALLPARAMETERS
:
692 case EAXSOURCE_OBSTRUCTIONPARAMETERS
:
693 case EAXSOURCE_OCCLUSIONPARAMETERS
:
694 case EAXSOURCE_EXCLUSIONPARAMETERS
:
695 case EAXSOURCE_DIRECT
:
696 case EAXSOURCE_DIRECTHF
:
698 case EAXSOURCE_ROOMHF
:
699 case EAXSOURCE_OBSTRUCTION
:
700 case EAXSOURCE_OBSTRUCTIONLFRATIO
:
701 case EAXSOURCE_OCCLUSION
:
702 case EAXSOURCE_OCCLUSIONLFRATIO
:
703 case EAXSOURCE_OCCLUSIONROOMRATIO
:
704 case EAXSOURCE_OCCLUSIONDIRECTRATIO
:
705 case EAXSOURCE_EXCLUSION
:
706 case EAXSOURCE_EXCLUSIONLFRATIO
:
707 case EAXSOURCE_OUTSIDEVOLUMEHF
:
708 case EAXSOURCE_DOPPLERFACTOR
:
709 case EAXSOURCE_ROLLOFFFACTOR
:
710 case EAXSOURCE_ROOMROLLOFFFACTOR
:
711 case EAXSOURCE_AIRABSORPTIONFACTOR
:
712 case EAXSOURCE_FLAGS
:
713 case EAXSOURCE_SENDPARAMETERS
:
714 case EAXSOURCE_ALLSENDPARAMETERS
:
715 case EAXSOURCE_OCCLUSIONSENDPARAMETERS
:
716 case EAXSOURCE_EXCLUSIONSENDPARAMETERS
:
717 case EAXSOURCE_ACTIVEFXSLOTID
:
718 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
| KSPROPERTY_SUPPORT_SET
;
721 FIXME("Unhandled propid: 0x%08lx\n", propid
);
722 return E_PROP_ID_UNSUPPORTED
;
725 HRESULT
EAX4Source_Set(DSBuffer
*buf
, DWORD propid
, void *pPropData
, ULONG cbPropData
)
727 if(!HAS_EXTENSION(buf
->share
, EXT_EFX
))
728 return E_PROP_ID_UNSUPPORTED
;
735 case EAXSOURCE_ALLPARAMETERS
:
736 if(cbPropData
>= sizeof(EAXSOURCEPROPERTIES
))
740 const EAXSOURCEPROPERTIES
*props
;
741 } data
= { pPropData
};
742 TRACE("Parameters:\n\tDirect: %ld\n\tDirect HF: %ld\n\tRoom: %ld\n\tRoom HF: %ld\n\t"
743 "Obstruction: %ld\n\tObstruction LF Ratio: %f\n\tOcclusion: %ld\n\t"
744 "Occlusion LF Ratio: %f\n\tOcclusion Room Ratio: %f\n\t"
745 "Occlusion Direct Ratio: %f\n\tExclusion: %ld\n\tExclusion LF Ratio: %f\n\t"
746 "Outside Volume HF: %ld\n\tDoppler Factor: %f\n\tRolloff Factor: %f\n\t"
747 "Room Rolloff Factor: %f\n\tAir Absorb Factor: %f\n\tFlags: 0x%02lx\n",
748 data
.props
->lDirect
, data
.props
->lDirectHF
, data
.props
->lRoom
, data
.props
->lRoomHF
,
749 data
.props
->lObstruction
, data
.props
->flObstructionLFRatio
, data
.props
->lOcclusion
,
750 data
.props
->flOcclusionLFRatio
, data
.props
->flOcclusionRoomRatio
,
751 data
.props
->flOcclusionDirectRatio
, data
.props
->lExclusion
,
752 data
.props
->flExclusionLFRatio
, data
.props
->lOutsideVolumeHF
,
753 data
.props
->flDopplerFactor
, data
.props
->flRolloffFactor
,
754 data
.props
->flRoomRolloffFactor
, data
.props
->flAirAbsorptionFactor
,
758 buf
->deferred
.eax
= *data
.props
;
759 ApplyFilterParams(buf
, data
.props
, APPLY_ALL_PARAMS
);
761 buf
->dirty
.bit
.dry_filter
= 1;
762 buf
->dirty
.bit
.send_filters
= 1;
763 buf
->dirty
.bit
.doppler
= 1;
764 buf
->dirty
.bit
.rolloff
= 1;
765 buf
->dirty
.bit
.room_rolloff
= 1;
766 buf
->dirty
.bit
.cone_outsidevolumehf
= 1;
767 buf
->dirty
.bit
.air_absorb
= 1;
768 buf
->dirty
.bit
.flags
= 1;
771 return DSERR_INVALIDPARAM
;
772 case EAXSOURCE_OBSTRUCTIONPARAMETERS
:
773 if(cbPropData
>= sizeof(EAXOBSTRUCTIONPROPERTIES
))
777 const EAXOBSTRUCTIONPROPERTIES
*props
;
778 } data
= { pPropData
};
779 TRACE("Parameters:\n\tObstruction: %ld\n\tObstruction LF Ratio: %f\n",
780 data
.props
->lObstruction
, data
.props
->flObstructionLFRatio
);
782 buf
->deferred
.eax
.lObstruction
= data
.props
->lObstruction
;
783 buf
->deferred
.eax
.flObstructionLFRatio
= data
.props
->flObstructionLFRatio
;
784 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_DRY_PARAMS
);
786 buf
->dirty
.bit
.dry_filter
= 1;
789 return DSERR_INVALIDPARAM
;
790 case EAXSOURCE_OCCLUSIONPARAMETERS
:
791 if(cbPropData
>= sizeof(EAXOCCLUSIONPROPERTIES
))
795 const EAXOCCLUSIONPROPERTIES
*props
;
796 } data
= { pPropData
};
797 TRACE("Parameters:\n\tOcclusion: %ld\n\tOcclusion LF Ratio: %f\n\t"
798 "Occlusion Room Ratio: %f\n\tOcclusion Direct Ratio: %f\n",
799 data
.props
->lOcclusion
, data
.props
->flOcclusionLFRatio
,
800 data
.props
->flOcclusionRoomRatio
, data
.props
->flOcclusionDirectRatio
803 buf
->deferred
.eax
.lOcclusion
= data
.props
->lOcclusion
;
804 buf
->deferred
.eax
.flOcclusionLFRatio
= data
.props
->flOcclusionLFRatio
;
805 buf
->deferred
.eax
.flOcclusionRoomRatio
= data
.props
->flOcclusionRoomRatio
;
806 buf
->deferred
.eax
.flOcclusionDirectRatio
= data
.props
->flOcclusionDirectRatio
;
807 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALL_PARAMS
);
809 buf
->dirty
.bit
.dry_filter
= 1;
810 buf
->dirty
.bit
.send_filters
= 1;
813 return DSERR_INVALIDPARAM
;
814 case EAXSOURCE_EXCLUSIONPARAMETERS
:
815 if(cbPropData
>= sizeof(EAXEXCLUSIONPROPERTIES
))
819 const EAXEXCLUSIONPROPERTIES
*props
;
820 } data
= { pPropData
};
821 TRACE("Parameters:\n\tExclusion: %ld\n\tExclusion LF Ratio: %f\n",
822 data
.props
->lExclusion
, data
.props
->flExclusionLFRatio
);
824 buf
->deferred
.eax
.lExclusion
= data
.props
->lExclusion
;
825 buf
->deferred
.eax
.flExclusionLFRatio
= data
.props
->flExclusionLFRatio
;
826 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALLWET_PARAMS
);
828 buf
->dirty
.bit
.send_filters
= 1;
831 return DSERR_INVALIDPARAM
;
833 case EAXSOURCE_DIRECT
:
834 if(cbPropData
>= sizeof(long))
836 union { const void *v
; const long *l
; } data
= { pPropData
};
837 TRACE("Direct: %ld\n", *data
.l
);
839 buf
->deferred
.eax
.lDirect
= *data
.l
;
840 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_DRY_PARAMS
);
842 buf
->dirty
.bit
.dry_filter
= 1;
845 return DSERR_INVALIDPARAM
;
846 case EAXSOURCE_DIRECTHF
:
847 if(cbPropData
>= sizeof(long))
849 union { const void *v
; const long *l
; } data
= { pPropData
};
850 TRACE("Direct HF: %ld\n", *data
.l
);
852 buf
->deferred
.eax
.lDirectHF
= *data
.l
;
853 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_DRY_PARAMS
);
855 buf
->dirty
.bit
.dry_filter
= 1;
858 return DSERR_INVALIDPARAM
;
861 if(cbPropData
>= sizeof(long))
863 union { const void *v
; const long *l
; } data
= { pPropData
};
864 TRACE("Room: %ld\n", *data
.l
);
866 buf
->deferred
.eax
.lRoom
= *data
.l
;
867 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALLWET_PARAMS
);
869 buf
->dirty
.bit
.send_filters
= 1;
872 return DSERR_INVALIDPARAM
;
873 case EAXSOURCE_ROOMHF
:
874 if(cbPropData
>= sizeof(long))
876 union { const void *v
; const long *l
; } data
= { pPropData
};
877 TRACE("Room HF: %ld\n", *data
.l
);
879 buf
->deferred
.eax
.lRoomHF
= *data
.l
;
880 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALLWET_PARAMS
);
882 buf
->dirty
.bit
.send_filters
= 1;
885 return DSERR_INVALIDPARAM
;
887 case EAXSOURCE_OBSTRUCTION
:
888 if(cbPropData
>= sizeof(long))
890 union { const void *v
; const long *l
; } data
= { pPropData
};
891 TRACE("Obstruction: %ld\n", *data
.l
);
893 buf
->deferred
.eax
.lObstruction
= *data
.l
;
894 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_DRY_PARAMS
);
896 buf
->dirty
.bit
.dry_filter
= 1;
899 return DSERR_INVALIDPARAM
;
900 case EAXSOURCE_OBSTRUCTIONLFRATIO
:
901 if(cbPropData
>= sizeof(float))
903 union { const void *v
; const float *fl
; } data
= { pPropData
};
904 TRACE("Obstruction LF Ratio: %f\n", *data
.fl
);
906 buf
->deferred
.eax
.flObstructionLFRatio
= *data
.fl
;
907 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_DRY_PARAMS
);
909 buf
->dirty
.bit
.dry_filter
= 1;
912 return DSERR_INVALIDPARAM
;
914 case EAXSOURCE_OCCLUSION
:
915 if(cbPropData
>= sizeof(long))
917 union { const void *v
; const long *l
; } data
= { pPropData
};
918 TRACE("Occlusion: %ld\n", *data
.l
);
920 buf
->deferred
.eax
.lOcclusion
= *data
.l
;
921 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALL_PARAMS
);
923 buf
->dirty
.bit
.dry_filter
= 1;
924 buf
->dirty
.bit
.send_filters
= 1;
927 return DSERR_INVALIDPARAM
;
928 case EAXSOURCE_OCCLUSIONLFRATIO
:
929 if(cbPropData
>= sizeof(float))
931 union { const void *v
; const float *fl
; } data
= { pPropData
};
932 TRACE("Occlusion LF Ratio: %f\n", *data
.fl
);
934 buf
->deferred
.eax
.flOcclusionLFRatio
= *data
.fl
;
935 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALL_PARAMS
);
937 buf
->dirty
.bit
.dry_filter
= 1;
938 buf
->dirty
.bit
.send_filters
= 1;
941 return DSERR_INVALIDPARAM
;
942 case EAXSOURCE_OCCLUSIONROOMRATIO
:
943 if(cbPropData
>= sizeof(float))
945 union { const void *v
; const float *fl
; } data
= { pPropData
};
946 TRACE("Occlusion Room Ratio: %f\n", *data
.fl
);
948 buf
->deferred
.eax
.flOcclusionRoomRatio
= *data
.fl
;
949 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALLWET_PARAMS
);
951 buf
->dirty
.bit
.send_filters
= 1;
954 return DSERR_INVALIDPARAM
;
955 case EAXSOURCE_OCCLUSIONDIRECTRATIO
:
956 if(cbPropData
>= sizeof(float))
958 union { const void *v
; const float *fl
; } data
= { pPropData
};
959 TRACE("Occlusion Direct Ratio: %f\n", *data
.fl
);
961 buf
->deferred
.eax
.flOcclusionDirectRatio
= *data
.fl
;
962 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_DRY_PARAMS
);
964 buf
->dirty
.bit
.dry_filter
= 1;
967 return DSERR_INVALIDPARAM
;
969 case EAXSOURCE_EXCLUSION
:
970 if(cbPropData
>= sizeof(long))
972 union { const void *v
; const long *l
; } data
= { pPropData
};
973 TRACE("Exclusion: %ld\n", *data
.l
);
975 buf
->deferred
.eax
.lExclusion
= *data
.l
;
976 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALLWET_PARAMS
);
978 buf
->dirty
.bit
.send_filters
= 1;
981 return DSERR_INVALIDPARAM
;
982 case EAXSOURCE_EXCLUSIONLFRATIO
:
983 if(cbPropData
>= sizeof(float))
985 union { const void *v
; const float *fl
; } data
= { pPropData
};
986 TRACE("Exclusion LF Ratio: %f\n", *data
.fl
);
988 buf
->deferred
.eax
.flExclusionLFRatio
= *data
.fl
;
989 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALLWET_PARAMS
);
991 buf
->dirty
.bit
.send_filters
= 1;
994 return DSERR_INVALIDPARAM
;
996 case EAXSOURCE_OUTSIDEVOLUMEHF
:
997 if(cbPropData
>= sizeof(long))
999 union { const void *v
; const long *l
; } data
= { pPropData
};
1000 TRACE("Outisde Volume HF: %ld\n", *data
.l
);
1002 buf
->deferred
.eax
.lOutsideVolumeHF
= *data
.l
;
1004 buf
->dirty
.bit
.cone_outsidevolumehf
= 1;
1007 return DSERR_INVALIDPARAM
;
1009 case EAXSOURCE_DOPPLERFACTOR
:
1010 if(cbPropData
>= sizeof(float))
1012 union { const void *v
; const float *fl
; } data
= { pPropData
};
1013 TRACE("Doppler Factor: %f\n", *data
.fl
);
1015 buf
->deferred
.eax
.flDopplerFactor
= *data
.fl
;
1017 buf
->dirty
.bit
.doppler
= 1;
1020 return DSERR_INVALIDPARAM
;
1022 case EAXSOURCE_ROLLOFFFACTOR
:
1023 if(cbPropData
>= sizeof(float))
1025 union { const void *v
; const float *fl
; } data
= { pPropData
};
1026 TRACE("Rolloff Factor: %f\n", *data
.fl
);
1028 buf
->deferred
.eax
.flRolloffFactor
= *data
.fl
;
1030 buf
->dirty
.bit
.rolloff
= 1;
1033 return DSERR_INVALIDPARAM
;
1035 case EAXSOURCE_ROOMROLLOFFFACTOR
:
1036 if(cbPropData
>= sizeof(float))
1038 union { const void *v
; const float *fl
; } data
= { pPropData
};
1039 TRACE("Room Rolloff Factor: %f\n", *data
.fl
);
1041 buf
->deferred
.eax
.flRoomRolloffFactor
= *data
.fl
;
1043 buf
->dirty
.bit
.room_rolloff
= 1;
1046 return DSERR_INVALIDPARAM
;
1048 case EAXSOURCE_AIRABSORPTIONFACTOR
:
1049 if(cbPropData
>= sizeof(float))
1051 union { const void *v
; const float *fl
; } data
= { pPropData
};
1052 TRACE("Air Absorb Factor: %f\n", *data
.fl
);
1054 buf
->deferred
.eax
.flAirAbsorptionFactor
= *data
.fl
;
1056 buf
->dirty
.bit
.air_absorb
= 1;
1059 return DSERR_INVALIDPARAM
;
1061 case EAXSOURCE_FLAGS
:
1062 if(cbPropData
>= sizeof(DWORD
))
1064 union { const void *v
; const DWORD
*dw
; } data
= { pPropData
};
1065 TRACE("Flags: 0x%lx\n", *data
.dw
);
1067 buf
->deferred
.eax
.dwFlags
= *data
.dw
;
1069 buf
->dirty
.bit
.flags
= 1;
1072 return DSERR_INVALIDPARAM
;
1074 case EAXSOURCE_SENDPARAMETERS
:
1075 if(cbPropData
>= sizeof(EAXSOURCESENDPROPERTIES
))
1077 union { const void *v
; const EAXSOURCESENDPROPERTIES
*send
; } data
= { pPropData
};
1078 struct Send
*srcsend
[EAX_MAX_FXSLOTS
];
1079 LONG count
= cbPropData
/ sizeof(EAXSOURCESENDPROPERTIES
);
1082 if(count
> buf
->share
->num_slots
)
1084 ERR("Setting %ld sends, only %d supported\n", count
, buf
->share
->num_slots
);
1085 return DSERR_INVALIDPARAM
;
1088 for(i
= 0;i
< count
;++i
)
1090 TRACE("Send parameters:\n\tReceiving: %s\n\tSend: %ld\n\tSend HF: %ld\n",
1091 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
),
1092 data
.send
[i
].lSend
, data
.send
[i
].lSendHF
1094 srcsend
[i
] = FindDeferredSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1097 ERR("Failed to find active FXSlot target: %s\n",
1098 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1099 return DSERR_INVALIDPARAM
;
1101 wetmask
|= 1 << (srcsend
[i
]-buf
->deferred
.send
);
1104 for(i
= 0;i
< count
;++i
)
1106 srcsend
[i
]->lSend
= data
.send
[i
].lSend
;
1107 srcsend
[i
]->lSendHF
= data
.send
[i
].lSendHF
;
1109 ApplyFilterParams(buf
, &buf
->deferred
.eax
, wetmask
);
1111 buf
->dirty
.bit
.send_filters
= 1;
1114 return DSERR_INVALIDPARAM
;
1115 case EAXSOURCE_ALLSENDPARAMETERS
:
1116 if(cbPropData
>= sizeof(EAXSOURCEALLSENDPROPERTIES
))
1118 union { const void *v
; const EAXSOURCEALLSENDPROPERTIES
*send
; } data
= { pPropData
};
1119 struct Send
*srcsend
[EAX_MAX_FXSLOTS
];
1120 LONG count
= cbPropData
/ sizeof(EAXSOURCEALLSENDPROPERTIES
);
1123 if(count
> buf
->share
->num_slots
)
1125 ERR("Setting %ld sends, only %d supported\n", count
, buf
->share
->num_slots
);
1126 return DSERR_INVALIDPARAM
;
1129 for(i
= 0;i
< count
;++i
)
1131 TRACE("All send parameters:\n\tReceiving: %s\n\tSend: %ld\n\tSend HF: %ld\n\t"
1132 "Occlusion: %ld\n\tOcclusion LF Ratio: %f\n\tOcclusion Room Ratio: %f\n\t"
1133 "Occlusion Direct Ratio: %f\n\tExclusion: %ld\n\tExclusion LF Ratio: %f\n",
1134 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
),
1135 data
.send
[i
].lSend
, data
.send
[i
].lSendHF
, data
.send
[i
].lOcclusion
,
1136 data
.send
[i
].flOcclusionLFRatio
, data
.send
[i
].flOcclusionRoomRatio
,
1137 data
.send
[i
].flOcclusionDirectRatio
, data
.send
[i
].lExclusion
,
1138 data
.send
[i
].flExclusionLFRatio
1140 srcsend
[i
] = FindDeferredSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1143 ERR("Failed to find active FXSlot target: %s\n",
1144 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1145 return DSERR_INVALIDPARAM
;
1147 wetmask
|= 1 << (srcsend
[i
]-buf
->deferred
.send
);
1150 for(i
= 0;i
< count
;++i
)
1152 srcsend
[i
]->lSend
= data
.send
[i
].lSend
;
1153 srcsend
[i
]->lSendHF
= data
.send
[i
].lSendHF
;
1154 srcsend
[i
]->lOcclusion
= data
.send
[i
].lOcclusion
;
1155 srcsend
[i
]->flOcclusionLFRatio
= data
.send
[i
].flOcclusionLFRatio
;
1156 srcsend
[i
]->flOcclusionRoomRatio
= data
.send
[i
].flOcclusionRoomRatio
;
1157 srcsend
[i
]->flOcclusionDirectRatio
= data
.send
[i
].flOcclusionDirectRatio
;
1158 srcsend
[i
]->lExclusion
= data
.send
[i
].lExclusion
;
1159 srcsend
[i
]->flExclusionLFRatio
= data
.send
[i
].flExclusionLFRatio
;
1161 ApplyFilterParams(buf
, &buf
->deferred
.eax
, wetmask
|APPLY_DRY_PARAMS
);
1163 buf
->dirty
.bit
.dry_filter
= 1;
1164 buf
->dirty
.bit
.send_filters
= 1;
1167 return DSERR_INVALIDPARAM
;
1168 case EAXSOURCE_OCCLUSIONSENDPARAMETERS
:
1169 if(cbPropData
>= sizeof(EAXSOURCEOCCLUSIONSENDPROPERTIES
))
1171 union { const void *v
; const EAXSOURCEOCCLUSIONSENDPROPERTIES
*send
; } data
= { pPropData
};
1172 struct Send
*srcsend
[EAX_MAX_FXSLOTS
];
1173 LONG count
= cbPropData
/ sizeof(EAXSOURCEOCCLUSIONSENDPROPERTIES
);
1176 if(count
> buf
->share
->num_slots
)
1178 ERR("Setting %ld sends, only %d supported\n", count
, buf
->share
->num_slots
);
1179 return DSERR_INVALIDPARAM
;
1182 for(i
= 0;i
< count
;++i
)
1184 TRACE("Occlusion send parameters:\n\tReceiving: %s\n\tOcclusion: %ld\n\t"
1185 "Occlusion LF Ratio: %f\n\tOcclusion Room Ratio: %f\n\t"
1186 "Occlusion Direct Ratio: %f\n",
1187 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
), data
.send
[i
].lOcclusion
,
1188 data
.send
[i
].flOcclusionLFRatio
, data
.send
[i
].flOcclusionRoomRatio
,
1189 data
.send
[i
].flOcclusionDirectRatio
1191 srcsend
[i
] = FindDeferredSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1194 ERR("Failed to find active FXSlot target: %s\n",
1195 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1196 return DSERR_INVALIDPARAM
;
1198 wetmask
|= 1 << (srcsend
[i
]-buf
->deferred
.send
);
1201 for(i
= 0;i
< count
;++i
)
1203 srcsend
[i
]->lOcclusion
= data
.send
[i
].lOcclusion
;
1204 srcsend
[i
]->flOcclusionLFRatio
= data
.send
[i
].flOcclusionLFRatio
;
1205 srcsend
[i
]->flOcclusionRoomRatio
= data
.send
[i
].flOcclusionRoomRatio
;
1206 srcsend
[i
]->flOcclusionDirectRatio
= data
.send
[i
].flOcclusionDirectRatio
;
1208 ApplyFilterParams(buf
, &buf
->deferred
.eax
, wetmask
|APPLY_DRY_PARAMS
);
1210 buf
->dirty
.bit
.dry_filter
= 1;
1211 buf
->dirty
.bit
.send_filters
= 1;
1214 return DSERR_INVALIDPARAM
;
1215 case EAXSOURCE_EXCLUSIONSENDPARAMETERS
:
1216 if(cbPropData
>= sizeof(EAXSOURCEEXCLUSIONSENDPROPERTIES
))
1218 union { const void *v
; const EAXSOURCEEXCLUSIONSENDPROPERTIES
*send
; } data
= { pPropData
};
1219 struct Send
*srcsend
[EAX_MAX_FXSLOTS
];
1220 LONG count
= cbPropData
/ sizeof(EAXSOURCEEXCLUSIONSENDPROPERTIES
);
1223 if(count
> buf
->share
->num_slots
)
1225 ERR("Setting %ld sends, only %d supported\n", count
, buf
->share
->num_slots
);
1226 return DSERR_INVALIDPARAM
;
1229 for(i
= 0;i
< count
;++i
)
1231 TRACE("Exclusion send parameters:\n\tReceiving: %s\n\tExclusion: %ld\n\t"
1232 "Exclusion LF Ratio: %f\n",
1233 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
),
1234 data
.send
[i
].lExclusion
, data
.send
[i
].flExclusionLFRatio
1236 srcsend
[i
] = FindDeferredSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1239 ERR("Failed to find active FXSlot target: %s\n",
1240 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1241 return DSERR_INVALIDPARAM
;
1243 wetmask
|= 1 << (srcsend
[i
]-buf
->deferred
.send
);
1246 for(i
= 0;i
< count
;++i
)
1248 srcsend
[i
]->lExclusion
= data
.send
[i
].lExclusion
;
1249 srcsend
[i
]->flExclusionLFRatio
= data
.send
[i
].flExclusionLFRatio
;
1251 ApplyFilterParams(buf
, &buf
->deferred
.eax
, wetmask
);
1253 buf
->dirty
.bit
.send_filters
= 1;
1256 return DSERR_INVALIDPARAM
;
1258 case EAXSOURCE_ACTIVEFXSLOTID
:
1259 if(cbPropData
&& (cbPropData
%sizeof(GUID
)) == 0)
1261 union { const void *v
; const GUID
*guid
; } data
= { pPropData
};
1262 DWORD targets
[EAX_MAX_ACTIVE_FXSLOTS
];
1263 LONG count
= cbPropData
/ sizeof(GUID
);
1266 if(count
> buf
->share
->num_sends
)
1268 ERR("Setting %ld sends, only %d supported\n", count
, buf
->share
->num_sends
);
1269 return DSERR_INVALIDPARAM
;
1272 for(i
= 0;i
< count
;i
++)
1274 TRACE("Active FXSlot %ld: %s\n", i
, debug_fxslot(&data
.guid
[i
]));
1276 targets
[i
] = FXSLOT_TARGET_NULL
;
1277 if(IsEqualGUID(&data
.guid
[i
], &EAXPROPERTYID_EAX40_FXSlot0
))
1278 targets
[i
] = FXSLOT_TARGET_0
;
1279 else if(IsEqualGUID(&data
.guid
[i
], &EAXPROPERTYID_EAX40_FXSlot1
))
1280 targets
[i
] = FXSLOT_TARGET_1
;
1281 else if(IsEqualGUID(&data
.guid
[i
], &EAXPROPERTYID_EAX40_FXSlot2
))
1282 targets
[i
] = FXSLOT_TARGET_2
;
1283 else if(IsEqualGUID(&data
.guid
[i
], &EAXPROPERTYID_EAX40_FXSlot3
))
1284 targets
[i
] = FXSLOT_TARGET_3
;
1285 else if(IsEqualGUID(&data
.guid
[i
], &EAX_PrimaryFXSlotID
))
1286 targets
[i
] = FXSLOT_TARGET_PRIMARY
;
1287 if(targets
[i
] == FXSLOT_TARGET_NULL
&& !IsEqualGUID(&data
.guid
[i
], &EAX_NULL_GUID
))
1289 ERR("Invalid FXSlot: %s\n", debug_fxslot(&data
.guid
[i
]));
1290 return DSERR_INVALIDPARAM
;
1294 for(i
= 0;i
< count
;++i
)
1295 buf
->deferred
.fxslot_targets
[i
] = targets
[i
];
1296 buf
->dirty
.bit
.send_filters
= 1;
1299 return DSERR_INVALIDPARAM
;
1301 FIXME("Unhandled propid: 0x%08lx\n", propid
);
1302 return E_PROP_ID_UNSUPPORTED
;
1305 HRESULT
EAX4Source_Get(DSBuffer
*buf
, DWORD propid
, void *pPropData
, ULONG cbPropData
, ULONG
*pcbReturned
)
1307 if(!HAS_EXTENSION(buf
->share
, EXT_EFX
))
1308 return E_PROP_ID_UNSUPPORTED
;
1312 case EAXSOURCE_NONE
:
1316 case EAXSOURCE_ALLPARAMETERS
:
1317 GET_PROP(buf
->current
.eax
, EAXSOURCEPROPERTIES
);
1319 case EAXSOURCE_OBSTRUCTIONPARAMETERS
:
1320 GET_PROP(EAXSourceObstruction(&buf
->current
.eax
), EAXOBSTRUCTIONPROPERTIES
);
1321 case EAXSOURCE_OCCLUSIONPARAMETERS
:
1322 GET_PROP(EAXSourceOcclusion(&buf
->current
.eax
), EAXOCCLUSIONPROPERTIES
);
1323 case EAXSOURCE_EXCLUSIONPARAMETERS
:
1324 GET_PROP(EAXSourceExclusion(&buf
->current
.eax
), EAXEXCLUSIONPROPERTIES
);
1326 case EAXSOURCE_DIRECT
:
1327 GET_PROP(buf
->current
.eax
.lDirect
, long);
1328 case EAXSOURCE_DIRECTHF
:
1329 GET_PROP(buf
->current
.eax
.lDirectHF
, long);
1331 case EAXSOURCE_ROOM
:
1332 GET_PROP(buf
->current
.eax
.lRoom
, long);
1333 case EAXSOURCE_ROOMHF
:
1334 GET_PROP(buf
->current
.eax
.lRoomHF
, long);
1336 case EAXSOURCE_OBSTRUCTION
:
1337 GET_PROP(buf
->current
.eax
.lObstruction
, long);
1338 case EAXSOURCE_OBSTRUCTIONLFRATIO
:
1339 GET_PROP(buf
->current
.eax
.flObstructionLFRatio
, float);
1341 case EAXSOURCE_OCCLUSION
:
1342 GET_PROP(buf
->current
.eax
.lOcclusion
, long);
1343 case EAXSOURCE_OCCLUSIONLFRATIO
:
1344 GET_PROP(buf
->current
.eax
.flOcclusionLFRatio
, float);
1345 case EAXSOURCE_OCCLUSIONROOMRATIO
:
1346 GET_PROP(buf
->current
.eax
.flOcclusionRoomRatio
, float);
1347 case EAXSOURCE_OCCLUSIONDIRECTRATIO
:
1348 GET_PROP(buf
->current
.eax
.flOcclusionDirectRatio
, float);
1350 case EAXSOURCE_EXCLUSION
:
1351 GET_PROP(buf
->current
.eax
.lExclusion
, long);
1352 case EAXSOURCE_EXCLUSIONLFRATIO
:
1353 GET_PROP(buf
->current
.eax
.flExclusionLFRatio
, float);
1355 case EAXSOURCE_OUTSIDEVOLUMEHF
:
1356 GET_PROP(buf
->current
.eax
.lOutsideVolumeHF
, long);
1358 case EAXSOURCE_DOPPLERFACTOR
:
1359 GET_PROP(buf
->current
.eax
.flDopplerFactor
, float);
1361 case EAXSOURCE_ROLLOFFFACTOR
:
1362 GET_PROP(buf
->current
.eax
.flRolloffFactor
, float);
1363 case EAXSOURCE_ROOMROLLOFFFACTOR
:
1364 GET_PROP(buf
->current
.eax
.flRoomRolloffFactor
, float);
1366 case EAXSOURCE_AIRABSORPTIONFACTOR
:
1367 GET_PROP(buf
->current
.eax
.flAirAbsorptionFactor
, float);
1369 case EAXSOURCE_FLAGS
:
1370 GET_PROP(buf
->current
.eax
.dwFlags
, DWORD
);
1372 case EAXSOURCE_SENDPARAMETERS
:
1373 if(cbPropData
>= sizeof(EAXSOURCESENDPROPERTIES
))
1375 union { void *v
; EAXSOURCESENDPROPERTIES
*send
; } data
= { pPropData
};
1376 const struct Send
*srcsend
[EAX_MAX_FXSLOTS
];
1377 LONG count
= minI(cbPropData
/ sizeof(EAXSOURCESENDPROPERTIES
), EAX_MAX_FXSLOTS
);
1380 for(i
= 0;i
< count
;++i
)
1382 srcsend
[i
] = FindCurrentSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1385 ERR("Failed to find active FXSlot target: %s\n",
1386 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1387 return DSERR_INVALIDPARAM
;
1391 for(i
= 0;i
< count
;++i
)
1393 data
.send
[i
].lSend
= srcsend
[i
]->lSend
;
1394 data
.send
[i
].lSendHF
= srcsend
[i
]->lSendHF
;
1396 *pcbReturned
= sizeof(EAXSOURCESENDPROPERTIES
)*count
;
1399 return DSERR_INVALIDPARAM
;
1401 case EAXSOURCE_ALLSENDPARAMETERS
:
1402 if(cbPropData
>= sizeof(EAXSOURCEALLSENDPROPERTIES
))
1404 union { void *v
; EAXSOURCEALLSENDPROPERTIES
*send
; } data
= { pPropData
};
1405 const struct Send
*srcsend
[EAX_MAX_FXSLOTS
];
1406 LONG count
= minI(cbPropData
/ sizeof(EAXSOURCEALLSENDPROPERTIES
), EAX_MAX_FXSLOTS
);
1409 for(i
= 0;i
< count
;++i
)
1411 srcsend
[i
] = FindCurrentSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1414 ERR("Failed to find active FXSlot target: %s\n",
1415 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1416 return DSERR_INVALIDPARAM
;
1420 for(i
= 0;i
< count
;++i
)
1422 data
.send
[i
].lSend
= srcsend
[i
]->lSend
;
1423 data
.send
[i
].lSendHF
= srcsend
[i
]->lSendHF
;
1424 data
.send
[i
].lOcclusion
= srcsend
[i
]->lOcclusion
;
1425 data
.send
[i
].flOcclusionLFRatio
= srcsend
[i
]->flOcclusionLFRatio
;
1426 data
.send
[i
].flOcclusionRoomRatio
= srcsend
[i
]->flOcclusionRoomRatio
;
1427 data
.send
[i
].flOcclusionDirectRatio
= srcsend
[i
]->flOcclusionDirectRatio
;
1428 data
.send
[i
].lExclusion
= srcsend
[i
]->lExclusion
;
1429 data
.send
[i
].flExclusionLFRatio
= srcsend
[i
]->flExclusionLFRatio
;
1431 *pcbReturned
= sizeof(EAXSOURCEALLSENDPROPERTIES
)*count
;
1434 return DSERR_INVALIDPARAM
;
1435 case EAXSOURCE_OCCLUSIONSENDPARAMETERS
:
1436 if(cbPropData
>= sizeof(EAXSOURCEOCCLUSIONSENDPROPERTIES
))
1438 union { void *v
; EAXSOURCEOCCLUSIONSENDPROPERTIES
*send
; } data
= { pPropData
};
1439 const struct Send
*srcsend
[EAX_MAX_FXSLOTS
];
1440 LONG count
= minI(cbPropData
/ sizeof(EAXSOURCEOCCLUSIONSENDPROPERTIES
),
1444 for(i
= 0;i
< count
;++i
)
1446 srcsend
[i
] = FindCurrentSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1449 ERR("Failed to find active FXSlot target: %s\n",
1450 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1451 return DSERR_INVALIDPARAM
;
1455 for(i
= 0;i
< count
;++i
)
1457 data
.send
[i
].lOcclusion
= srcsend
[i
]->lOcclusion
;
1458 data
.send
[i
].flOcclusionLFRatio
= srcsend
[i
]->flOcclusionLFRatio
;
1459 data
.send
[i
].flOcclusionRoomRatio
= srcsend
[i
]->flOcclusionRoomRatio
;
1460 data
.send
[i
].flOcclusionDirectRatio
= srcsend
[i
]->flOcclusionDirectRatio
;
1462 *pcbReturned
= sizeof(EAXSOURCEOCCLUSIONSENDPROPERTIES
)*count
;
1465 return DSERR_INVALIDPARAM
;
1466 case EAXSOURCE_EXCLUSIONSENDPARAMETERS
:
1467 if(cbPropData
>= sizeof(EAXSOURCEEXCLUSIONSENDPROPERTIES
))
1469 union { void *v
; EAXSOURCEEXCLUSIONSENDPROPERTIES
*send
; } data
= { pPropData
};
1470 const struct Send
*srcsend
[EAX_MAX_FXSLOTS
];
1471 LONG count
= minI(cbPropData
/ sizeof(EAXSOURCEEXCLUSIONSENDPROPERTIES
),
1475 for(i
= 0;i
< count
;++i
)
1477 srcsend
[i
] = FindCurrentSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1480 ERR("Failed to find active FXSlot target: %s\n",
1481 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1482 return DSERR_INVALIDPARAM
;
1486 for(i
= 0;i
< count
;++i
)
1488 data
.send
[i
].lExclusion
= srcsend
[i
]->lExclusion
;
1489 data
.send
[i
].flExclusionLFRatio
= srcsend
[i
]->flExclusionLFRatio
;
1491 *pcbReturned
= sizeof(EAXSOURCEEXCLUSIONSENDPROPERTIES
)*count
;
1494 return DSERR_INVALIDPARAM
;
1496 case EAXSOURCE_ACTIVEFXSLOTID
:
1497 if(cbPropData
>= sizeof(GUID
))
1499 union { void *v
; GUID
*guid
; } data
= { pPropData
};
1500 LONG count
= minI(cbPropData
/ sizeof(GUID
), EAX_MAX_ACTIVE_FXSLOTS
);
1503 for(i
= 0;i
< count
;++i
)
1505 if(buf
->current
.fxslot_targets
[i
] == FXSLOT_TARGET_0
)
1506 data
.guid
[i
] = EAXPROPERTYID_EAX40_FXSlot0
;
1507 else if(buf
->current
.fxslot_targets
[i
] == FXSLOT_TARGET_1
)
1508 data
.guid
[i
] = EAXPROPERTYID_EAX40_FXSlot1
;
1509 else if(buf
->current
.fxslot_targets
[i
] == FXSLOT_TARGET_2
)
1510 data
.guid
[i
] = EAXPROPERTYID_EAX40_FXSlot2
;
1511 else if(buf
->current
.fxslot_targets
[i
] == FXSLOT_TARGET_3
)
1512 data
.guid
[i
] = EAXPROPERTYID_EAX40_FXSlot3
;
1513 else if(buf
->current
.fxslot_targets
[i
] == FXSLOT_TARGET_PRIMARY
)
1514 data
.guid
[i
] = EAX_PrimaryFXSlotID
;
1515 else /*if(buf->current.fxslot_targets[i] >= FXSLOT_TARGET_NULL)*/
1516 data
.guid
[i
] = EAX_NULL_GUID
;
1519 *pcbReturned
= sizeof(GUID
)*count
;
1522 return DSERR_INVALIDPARAM
;
1524 FIXME("Unhandled propid: 0x%08lx\n", propid
);
1525 return E_PROP_ID_UNSUPPORTED
;