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
))
107 prim_slot
= prim
->auxslot
[0];
108 else if(IsEqualGUID(&data
.props
->guidPrimaryFXSlotID
, &EAXPROPERTYID_EAX40_FXSlot1
))
109 prim_slot
= prim
->auxslot
[1];
110 else if(IsEqualGUID(&data
.props
->guidPrimaryFXSlotID
, &EAXPROPERTYID_EAX40_FXSlot2
))
111 prim_slot
= prim
->auxslot
[2];
112 else if(IsEqualGUID(&data
.props
->guidPrimaryFXSlotID
, &EAXPROPERTYID_EAX40_FXSlot3
))
113 prim_slot
= prim
->auxslot
[3];
114 if(prim_slot
== 0 && !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_slot
= prim_slot
;
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
))
157 prim_slot
= prim
->auxslot
[0];
158 else if(IsEqualGUID(data
.guid
, &EAXPROPERTYID_EAX40_FXSlot1
))
159 prim_slot
= prim
->auxslot
[1];
160 else if(IsEqualGUID(data
.guid
, &EAXPROPERTYID_EAX40_FXSlot2
))
161 prim_slot
= prim
->auxslot
[2];
162 else if(IsEqualGUID(data
.guid
, &EAXPROPERTYID_EAX40_FXSlot3
))
163 prim_slot
= prim
->auxslot
[3];
164 if(prim_slot
== 0 && !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_slot
= prim_slot
;
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_DRY_PARAMS 4
558 #define APPLY_ALL_PARAMS (APPLY_WET0_PARAMS | APPLY_WET1_PARAMS | APPLY_DRY_PARAMS)
559 #define APPLY_ALLWET_PARAMS (APPLY_WET0_PARAMS | APPLY_WET1_PARAMS)
560 static void ApplyFilterParams(DSBuffer
*buf
, const EAXSOURCEPROPERTIES
*props
, int apply
)
562 /* The LFRatio properties determine how much the given level applies to low
563 * frequencies as well as high frequencies. Technically, given that the
564 * obstruction/occlusion/exclusion levels are the absolute level applied to
565 * high frequencies (relative to full-scale, according to the EAX 2.0 spec)
566 * while the HF filter gains are relative to the low, the HF gains should
567 * increase as LFRatio increases.
569 * However it seems Creative was either wrong when writing out the spec,
570 * or implemented it incorrectly, as the HF filter still applies in full
571 * regardless of the LFRatio. So to replicate the hardware behavior, we do
574 /* The interaction of ratios is pretty wierd. The typical combination of
575 * the two act as a minimal baseline, while the sum minus one is used when
576 * larger. This creates a more linear change with the individual ratios as
577 * Direct/RoomRatio goes beyond 1, but eases down as the two ratios go
580 float dryoccl
= maxF(props
->flOcclusionLFRatio
+props
->flOcclusionDirectRatio
-1.0f
,
581 props
->flOcclusionLFRatio
*props
->flOcclusionDirectRatio
) *
583 float dryocclhf
= props
->lOcclusion
*props
->flOcclusionDirectRatio
;
584 float room_mb
= props
->lRoom
+ props
->lExclusion
*props
->flExclusionLFRatio
+
585 maxF(props
->flOcclusionLFRatio
+props
->flOcclusionRoomRatio
-1.0f
,
586 props
->flOcclusionLFRatio
*props
->flOcclusionRoomRatio
) * props
->lOcclusion
;
587 float room_mbhf
= props
->lRoomHF
+ props
->lExclusion
+
588 props
->lOcclusion
*props
->flOcclusionRoomRatio
;
591 for(i
= 0;i
< EAX_MAX_ACTIVE_FXSLOTS
;i
++)
593 const struct Send
*send
= &buf
->deferred
.send
[i
];
594 if((apply
&(1<<i
)) && buf
->filter
[1+i
])
596 /* Add the main room occlusion and exclusion properties with the
597 * sends', or take the minimum or maximum?
599 float mb
= room_mb
+ send
->lExclusion
*send
->flExclusionLFRatio
+
600 maxF(send
->flOcclusionLFRatio
+send
->flOcclusionRoomRatio
-1.0f
,
601 send
->flOcclusionLFRatio
*send
->flOcclusionRoomRatio
)*send
->lOcclusion
;
602 float mbhf
= room_mbhf
+ send
->lExclusion
+
603 send
->lOcclusion
*send
->flOcclusionRoomRatio
;
605 alFilterf(buf
->filter
[1+i
], AL_LOWPASS_GAIN
, mB_to_gain(minF(mb
, buf
->filter_mBLimit
)));
606 alFilterf(buf
->filter
[1+i
], AL_LOWPASS_GAINHF
, mB_to_gain(mbhf
));
609 /* Take the minimum, maximum, or average of the sends' direct occlusion with the main
612 dryoccl
= minF(dryoccl
,
613 maxF(send
->flOcclusionLFRatio
+send
->flOcclusionDirectRatio
-1.0f
,
614 send
->flOcclusionLFRatio
*send
->flOcclusionDirectRatio
) * send
->lOcclusion
616 dryocclhf
= minF(dryocclhf
, send
->lOcclusion
*send
->flOcclusionDirectRatio
);
618 if((apply
&APPLY_DRY_PARAMS
) && buf
->filter
[0])
620 float mb
= props
->lDirect
+ props
->lObstruction
*props
->flObstructionLFRatio
+ dryoccl
;
621 float mbhf
= props
->lDirectHF
+ props
->lObstruction
+ dryocclhf
;
623 alFilterf(buf
->filter
[0], AL_LOWPASS_GAIN
, mB_to_gain(minF(mb
, buf
->filter_mBLimit
)));
624 alFilterf(buf
->filter
[0], AL_LOWPASS_GAINHF
, mB_to_gain(mbhf
));
629 static EAXOBSTRUCTIONPROPERTIES
EAXSourceObstruction(const EAXSOURCEPROPERTIES
*props
)
631 EAXOBSTRUCTIONPROPERTIES ret
;
632 ret
.lObstruction
= props
->lObstruction
;
633 ret
.flObstructionLFRatio
= props
->flObstructionLFRatio
;
637 static EAXOCCLUSIONPROPERTIES
EAXSourceOcclusion(const EAXSOURCEPROPERTIES
*props
)
639 EAXOCCLUSIONPROPERTIES ret
;
640 ret
.lOcclusion
= props
->lOcclusion
;
641 ret
.flOcclusionLFRatio
= props
->flOcclusionLFRatio
;
642 ret
.flOcclusionRoomRatio
= props
->flOcclusionRoomRatio
;
643 ret
.flOcclusionDirectRatio
= props
->flOcclusionDirectRatio
;
647 static EAXEXCLUSIONPROPERTIES
EAXSourceExclusion(const EAXSOURCEPROPERTIES
*props
)
649 EAXEXCLUSIONPROPERTIES ret
;
650 ret
.lExclusion
= props
->lExclusion
;
651 ret
.flExclusionLFRatio
= props
->flExclusionLFRatio
;
655 static struct Send
*FindCurrentSend(DSBuffer
*buf
, const GUID
*guid
)
658 for(i
= 0;i
< EAX_MAX_ACTIVE_FXSLOTS
;i
++)
660 DWORD target
= buf
->current
.fxslot_targets
[i
];
661 if((target
== FXSLOT_TARGET_0
&& IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot0
)) ||
662 (target
== FXSLOT_TARGET_1
&& IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot1
)) ||
663 (target
== FXSLOT_TARGET_2
&& IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot2
)) ||
664 (target
== FXSLOT_TARGET_3
&& IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot3
)) ||
665 (target
== FXSLOT_TARGET_PRIMARY
&& IsEqualGUID(guid
, &EAX_PrimaryFXSlotID
)) ||
666 (target
== FXSLOT_TARGET_NULL
&& IsEqualGUID(guid
, &EAX_NULL_GUID
)))
667 return &buf
->current
.send
[i
];
672 static struct Send
*FindDeferredSend(DSBuffer
*buf
, const GUID
*guid
)
675 for(i
= 0;i
< EAX_MAX_ACTIVE_FXSLOTS
;i
++)
677 DWORD target
= buf
->deferred
.fxslot_targets
[i
];
678 if((target
== FXSLOT_TARGET_0
&& IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot0
)) ||
679 (target
== FXSLOT_TARGET_1
&& IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot1
)) ||
680 (target
== FXSLOT_TARGET_2
&& IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot2
)) ||
681 (target
== FXSLOT_TARGET_3
&& IsEqualGUID(guid
, &EAXPROPERTYID_EAX40_FXSlot3
)) ||
682 (target
== FXSLOT_TARGET_PRIMARY
&& IsEqualGUID(guid
, &EAX_PrimaryFXSlotID
)) ||
683 (target
== FXSLOT_TARGET_NULL
&& IsEqualGUID(guid
, &EAX_NULL_GUID
)))
684 return &buf
->deferred
.send
[i
];
689 HRESULT
EAX4Source_Query(DSBuffer
*buf
, DWORD propid
, ULONG
*pTypeSupport
)
691 if(!HAS_EXTENSION(buf
->share
, EXT_EFX
))
692 return E_PROP_ID_UNSUPPORTED
;
694 switch((propid
&~EAXSOURCE_PARAMETER_DEFERRED
))
697 case EAXSOURCE_ALLPARAMETERS
:
698 case EAXSOURCE_OBSTRUCTIONPARAMETERS
:
699 case EAXSOURCE_OCCLUSIONPARAMETERS
:
700 case EAXSOURCE_EXCLUSIONPARAMETERS
:
701 case EAXSOURCE_DIRECT
:
702 case EAXSOURCE_DIRECTHF
:
704 case EAXSOURCE_ROOMHF
:
705 case EAXSOURCE_OBSTRUCTION
:
706 case EAXSOURCE_OBSTRUCTIONLFRATIO
:
707 case EAXSOURCE_OCCLUSION
:
708 case EAXSOURCE_OCCLUSIONLFRATIO
:
709 case EAXSOURCE_OCCLUSIONROOMRATIO
:
710 case EAXSOURCE_OCCLUSIONDIRECTRATIO
:
711 case EAXSOURCE_EXCLUSION
:
712 case EAXSOURCE_EXCLUSIONLFRATIO
:
713 case EAXSOURCE_OUTSIDEVOLUMEHF
:
714 case EAXSOURCE_DOPPLERFACTOR
:
715 case EAXSOURCE_ROLLOFFFACTOR
:
716 case EAXSOURCE_ROOMROLLOFFFACTOR
:
717 case EAXSOURCE_AIRABSORPTIONFACTOR
:
718 case EAXSOURCE_FLAGS
:
719 case EAXSOURCE_SENDPARAMETERS
:
720 case EAXSOURCE_ALLSENDPARAMETERS
:
721 case EAXSOURCE_OCCLUSIONSENDPARAMETERS
:
722 case EAXSOURCE_EXCLUSIONSENDPARAMETERS
:
723 case EAXSOURCE_ACTIVEFXSLOTID
:
724 *pTypeSupport
= KSPROPERTY_SUPPORT_GET
| KSPROPERTY_SUPPORT_SET
;
727 FIXME("Unhandled propid: 0x%08lx\n", propid
);
728 return E_PROP_ID_UNSUPPORTED
;
731 HRESULT
EAX4Source_Set(DSBuffer
*buf
, DWORD propid
, void *pPropData
, ULONG cbPropData
)
733 if(!HAS_EXTENSION(buf
->share
, EXT_EFX
))
734 return E_PROP_ID_UNSUPPORTED
;
741 case EAXSOURCE_ALLPARAMETERS
:
742 if(cbPropData
>= sizeof(EAXSOURCEPROPERTIES
))
746 const EAXSOURCEPROPERTIES
*props
;
747 } data
= { pPropData
};
748 TRACE("Parameters:\n\tDirect: %ld\n\tDirect HF: %ld\n\tRoom: %ld\n\tRoom HF: %ld\n\t"
749 "Obstruction: %ld\n\tObstruction LF Ratio: %f\n\tOcclusion: %ld\n\t"
750 "Occlusion LF Ratio: %f\n\tOcclusion Room Ratio: %f\n\t"
751 "Occlusion Direct Ratio: %f\n\tExclusion: %ld\n\tExclusion LF Ratio: %f\n\t"
752 "Outside Volume HF: %ld\n\tDoppler Factor: %f\n\tRolloff Factor: %f\n\t"
753 "Room Rolloff Factor: %f\n\tAir Absorb Factor: %f\n\tFlags: 0x%02lx\n",
754 data
.props
->lDirect
, data
.props
->lDirectHF
, data
.props
->lRoom
, data
.props
->lRoomHF
,
755 data
.props
->lObstruction
, data
.props
->flObstructionLFRatio
, data
.props
->lOcclusion
,
756 data
.props
->flOcclusionLFRatio
, data
.props
->flOcclusionRoomRatio
,
757 data
.props
->flOcclusionDirectRatio
, data
.props
->lExclusion
,
758 data
.props
->flExclusionLFRatio
, data
.props
->lOutsideVolumeHF
,
759 data
.props
->flDopplerFactor
, data
.props
->flRolloffFactor
,
760 data
.props
->flRoomRolloffFactor
, data
.props
->flAirAbsorptionFactor
,
764 buf
->deferred
.eax
= *data
.props
;
765 ApplyFilterParams(buf
, data
.props
, APPLY_ALL_PARAMS
);
767 buf
->dirty
.bit
.dry_filter
= 1;
768 buf
->dirty
.bit
.send_filter
= (1<<buf
->share
->num_sends
) - 1;
769 buf
->dirty
.bit
.doppler
= 1;
770 buf
->dirty
.bit
.rolloff
= 1;
771 buf
->dirty
.bit
.room_rolloff
= 1;
772 buf
->dirty
.bit
.cone_outsidevolumehf
= 1;
773 buf
->dirty
.bit
.air_absorb
= 1;
774 buf
->dirty
.bit
.flags
= 1;
777 return DSERR_INVALIDPARAM
;
778 case EAXSOURCE_OBSTRUCTIONPARAMETERS
:
779 if(cbPropData
>= sizeof(EAXOBSTRUCTIONPROPERTIES
))
783 const EAXOBSTRUCTIONPROPERTIES
*props
;
784 } data
= { pPropData
};
785 TRACE("Parameters:\n\tObstruction: %ld\n\tObstruction LF Ratio: %f\n",
786 data
.props
->lObstruction
, data
.props
->flObstructionLFRatio
);
788 buf
->deferred
.eax
.lObstruction
= data
.props
->lObstruction
;
789 buf
->deferred
.eax
.flObstructionLFRatio
= data
.props
->flObstructionLFRatio
;
790 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_DRY_PARAMS
);
792 buf
->dirty
.bit
.dry_filter
= 1;
795 return DSERR_INVALIDPARAM
;
796 case EAXSOURCE_OCCLUSIONPARAMETERS
:
797 if(cbPropData
>= sizeof(EAXOCCLUSIONPROPERTIES
))
801 const EAXOCCLUSIONPROPERTIES
*props
;
802 } data
= { pPropData
};
803 TRACE("Parameters:\n\tOcclusion: %ld\n\tOcclusion LF Ratio: %f\n\t"
804 "Occlusion Room Ratio: %f\n\tOcclusion Direct Ratio: %f\n",
805 data
.props
->lOcclusion
, data
.props
->flOcclusionLFRatio
,
806 data
.props
->flOcclusionRoomRatio
, data
.props
->flOcclusionDirectRatio
809 buf
->deferred
.eax
.lOcclusion
= data
.props
->lOcclusion
;
810 buf
->deferred
.eax
.flOcclusionLFRatio
= data
.props
->flOcclusionLFRatio
;
811 buf
->deferred
.eax
.flOcclusionRoomRatio
= data
.props
->flOcclusionRoomRatio
;
812 buf
->deferred
.eax
.flOcclusionDirectRatio
= data
.props
->flOcclusionDirectRatio
;
813 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALL_PARAMS
);
815 buf
->dirty
.bit
.dry_filter
= 1;
816 buf
->dirty
.bit
.send_filter
= (1<<buf
->share
->num_sends
) - 1;
819 return DSERR_INVALIDPARAM
;
820 case EAXSOURCE_EXCLUSIONPARAMETERS
:
821 if(cbPropData
>= sizeof(EAXEXCLUSIONPROPERTIES
))
825 const EAXEXCLUSIONPROPERTIES
*props
;
826 } data
= { pPropData
};
827 TRACE("Parameters:\n\tExclusion: %ld\n\tExclusion LF Ratio: %f\n",
828 data
.props
->lExclusion
, data
.props
->flExclusionLFRatio
);
830 buf
->deferred
.eax
.lExclusion
= data
.props
->lExclusion
;
831 buf
->deferred
.eax
.flExclusionLFRatio
= data
.props
->flExclusionLFRatio
;
832 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALLWET_PARAMS
);
834 buf
->dirty
.bit
.send_filter
= (1<<buf
->share
->num_sends
) - 1;
837 return DSERR_INVALIDPARAM
;
839 case EAXSOURCE_DIRECT
:
840 if(cbPropData
>= sizeof(long))
842 union { const void *v
; const long *l
; } data
= { pPropData
};
843 TRACE("Direct: %ld\n", *data
.l
);
845 buf
->deferred
.eax
.lDirect
= *data
.l
;
846 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_DRY_PARAMS
);
848 buf
->dirty
.bit
.dry_filter
= 1;
851 return DSERR_INVALIDPARAM
;
852 case EAXSOURCE_DIRECTHF
:
853 if(cbPropData
>= sizeof(long))
855 union { const void *v
; const long *l
; } data
= { pPropData
};
856 TRACE("Direct HF: %ld\n", *data
.l
);
858 buf
->deferred
.eax
.lDirectHF
= *data
.l
;
859 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_DRY_PARAMS
);
861 buf
->dirty
.bit
.dry_filter
= 1;
864 return DSERR_INVALIDPARAM
;
867 if(cbPropData
>= sizeof(long))
869 union { const void *v
; const long *l
; } data
= { pPropData
};
870 TRACE("Room: %ld\n", *data
.l
);
872 buf
->deferred
.eax
.lRoom
= *data
.l
;
873 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALLWET_PARAMS
);
875 buf
->dirty
.bit
.send_filter
= (1<<buf
->share
->num_sends
) - 1;
878 return DSERR_INVALIDPARAM
;
879 case EAXSOURCE_ROOMHF
:
880 if(cbPropData
>= sizeof(long))
882 union { const void *v
; const long *l
; } data
= { pPropData
};
883 TRACE("Room HF: %ld\n", *data
.l
);
885 buf
->deferred
.eax
.lRoomHF
= *data
.l
;
886 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALLWET_PARAMS
);
888 buf
->dirty
.bit
.send_filter
= (1<<buf
->share
->num_sends
) - 1;
891 return DSERR_INVALIDPARAM
;
893 case EAXSOURCE_OBSTRUCTION
:
894 if(cbPropData
>= sizeof(long))
896 union { const void *v
; const long *l
; } data
= { pPropData
};
897 TRACE("Obstruction: %ld\n", *data
.l
);
899 buf
->deferred
.eax
.lObstruction
= *data
.l
;
900 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_DRY_PARAMS
);
902 buf
->dirty
.bit
.dry_filter
= 1;
905 return DSERR_INVALIDPARAM
;
906 case EAXSOURCE_OBSTRUCTIONLFRATIO
:
907 if(cbPropData
>= sizeof(float))
909 union { const void *v
; const float *fl
; } data
= { pPropData
};
910 TRACE("Obstruction LF Ratio: %f\n", *data
.fl
);
912 buf
->deferred
.eax
.flObstructionLFRatio
= *data
.fl
;
913 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_DRY_PARAMS
);
915 buf
->dirty
.bit
.dry_filter
= 1;
918 return DSERR_INVALIDPARAM
;
920 case EAXSOURCE_OCCLUSION
:
921 if(cbPropData
>= sizeof(long))
923 union { const void *v
; const long *l
; } data
= { pPropData
};
924 TRACE("Occlusion: %ld\n", *data
.l
);
926 buf
->deferred
.eax
.lOcclusion
= *data
.l
;
927 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALL_PARAMS
);
929 buf
->dirty
.bit
.dry_filter
= 1;
930 buf
->dirty
.bit
.send_filter
= (1<<buf
->share
->num_sends
) - 1;
933 return DSERR_INVALIDPARAM
;
934 case EAXSOURCE_OCCLUSIONLFRATIO
:
935 if(cbPropData
>= sizeof(float))
937 union { const void *v
; const float *fl
; } data
= { pPropData
};
938 TRACE("Occlusion LF Ratio: %f\n", *data
.fl
);
940 buf
->deferred
.eax
.flOcclusionLFRatio
= *data
.fl
;
941 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALL_PARAMS
);
943 buf
->dirty
.bit
.dry_filter
= 1;
944 buf
->dirty
.bit
.send_filter
= (1<<buf
->share
->num_sends
) - 1;
947 return DSERR_INVALIDPARAM
;
948 case EAXSOURCE_OCCLUSIONROOMRATIO
:
949 if(cbPropData
>= sizeof(float))
951 union { const void *v
; const float *fl
; } data
= { pPropData
};
952 TRACE("Occlusion Room Ratio: %f\n", *data
.fl
);
954 buf
->deferred
.eax
.flOcclusionRoomRatio
= *data
.fl
;
955 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALLWET_PARAMS
);
957 buf
->dirty
.bit
.send_filter
= (1<<buf
->share
->num_sends
) - 1;
960 return DSERR_INVALIDPARAM
;
961 case EAXSOURCE_OCCLUSIONDIRECTRATIO
:
962 if(cbPropData
>= sizeof(float))
964 union { const void *v
; const float *fl
; } data
= { pPropData
};
965 TRACE("Occlusion Direct Ratio: %f\n", *data
.fl
);
967 buf
->deferred
.eax
.flOcclusionDirectRatio
= *data
.fl
;
968 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_DRY_PARAMS
);
970 buf
->dirty
.bit
.dry_filter
= 1;
973 return DSERR_INVALIDPARAM
;
975 case EAXSOURCE_EXCLUSION
:
976 if(cbPropData
>= sizeof(long))
978 union { const void *v
; const long *l
; } data
= { pPropData
};
979 TRACE("Exclusion: %ld\n", *data
.l
);
981 buf
->deferred
.eax
.lExclusion
= *data
.l
;
982 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALLWET_PARAMS
);
984 buf
->dirty
.bit
.send_filter
= (1<<buf
->share
->num_sends
) - 1;
987 return DSERR_INVALIDPARAM
;
988 case EAXSOURCE_EXCLUSIONLFRATIO
:
989 if(cbPropData
>= sizeof(float))
991 union { const void *v
; const float *fl
; } data
= { pPropData
};
992 TRACE("Exclusion LF Ratio: %f\n", *data
.fl
);
994 buf
->deferred
.eax
.flExclusionLFRatio
= *data
.fl
;
995 ApplyFilterParams(buf
, &buf
->deferred
.eax
, APPLY_ALLWET_PARAMS
);
997 buf
->dirty
.bit
.send_filter
= (1<<buf
->share
->num_sends
) - 1;
1000 return DSERR_INVALIDPARAM
;
1002 case EAXSOURCE_OUTSIDEVOLUMEHF
:
1003 if(cbPropData
>= sizeof(long))
1005 union { const void *v
; const long *l
; } data
= { pPropData
};
1006 TRACE("Outisde Volume HF: %ld\n", *data
.l
);
1008 buf
->deferred
.eax
.lOutsideVolumeHF
= *data
.l
;
1010 buf
->dirty
.bit
.cone_outsidevolumehf
= 1;
1013 return DSERR_INVALIDPARAM
;
1015 case EAXSOURCE_DOPPLERFACTOR
:
1016 if(cbPropData
>= sizeof(float))
1018 union { const void *v
; const float *fl
; } data
= { pPropData
};
1019 TRACE("Doppler Factor: %f\n", *data
.fl
);
1021 buf
->deferred
.eax
.flDopplerFactor
= *data
.fl
;
1023 buf
->dirty
.bit
.doppler
= 1;
1026 return DSERR_INVALIDPARAM
;
1028 case EAXSOURCE_ROLLOFFFACTOR
:
1029 if(cbPropData
>= sizeof(float))
1031 union { const void *v
; const float *fl
; } data
= { pPropData
};
1032 TRACE("Rolloff Factor: %f\n", *data
.fl
);
1034 buf
->deferred
.eax
.flRolloffFactor
= *data
.fl
;
1036 buf
->dirty
.bit
.rolloff
= 1;
1039 return DSERR_INVALIDPARAM
;
1041 case EAXSOURCE_ROOMROLLOFFFACTOR
:
1042 if(cbPropData
>= sizeof(float))
1044 union { const void *v
; const float *fl
; } data
= { pPropData
};
1045 TRACE("Room Rolloff Factor: %f\n", *data
.fl
);
1047 buf
->deferred
.eax
.flRoomRolloffFactor
= *data
.fl
;
1049 buf
->dirty
.bit
.room_rolloff
= 1;
1052 return DSERR_INVALIDPARAM
;
1054 case EAXSOURCE_AIRABSORPTIONFACTOR
:
1055 if(cbPropData
>= sizeof(float))
1057 union { const void *v
; const float *fl
; } data
= { pPropData
};
1058 TRACE("Air Absorb Factor: %f\n", *data
.fl
);
1060 buf
->deferred
.eax
.flAirAbsorptionFactor
= *data
.fl
;
1062 buf
->dirty
.bit
.air_absorb
= 1;
1065 return DSERR_INVALIDPARAM
;
1067 case EAXSOURCE_FLAGS
:
1068 if(cbPropData
>= sizeof(DWORD
))
1070 union { const void *v
; const DWORD
*dw
; } data
= { pPropData
};
1071 TRACE("Flags: 0x%lx\n", *data
.dw
);
1073 buf
->deferred
.eax
.dwFlags
= *data
.dw
;
1075 buf
->dirty
.bit
.flags
= 1;
1078 return DSERR_INVALIDPARAM
;
1080 case EAXSOURCE_SENDPARAMETERS
:
1081 if(cbPropData
>= sizeof(EAXSOURCESENDPROPERTIES
))
1083 union { const void *v
; const EAXSOURCESENDPROPERTIES
*send
; } data
= { pPropData
};
1084 struct Send
*srcsend
[EAX_MAX_ACTIVE_FXSLOTS
];
1085 LONG count
= cbPropData
/ sizeof(EAXSOURCESENDPROPERTIES
);
1088 if(count
> buf
->share
->num_sends
)
1090 ERR("Setting %ld sends, only %d supported\n", count
, buf
->share
->num_sends
);
1091 return DSERR_INVALIDPARAM
;
1094 for(i
= 0;i
< count
;++i
)
1096 TRACE("Send parameters:\n\tReceiving: %s\n\tSend: %ld\n\tSend HF: %ld\n",
1097 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
),
1098 data
.send
[i
].lSend
, data
.send
[i
].lSendHF
1100 srcsend
[i
] = FindDeferredSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1103 ERR("Failed to find active FXSlot target: %s\n",
1104 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1105 return DSERR_INVALIDPARAM
;
1107 wetmask
|= 1 << (srcsend
[i
]-buf
->deferred
.send
);
1110 for(i
= 0;i
< count
;++i
)
1112 srcsend
[i
]->lSend
= data
.send
[i
].lSend
;
1113 srcsend
[i
]->lSendHF
= data
.send
[i
].lSendHF
;
1115 ApplyFilterParams(buf
, &buf
->deferred
.eax
, wetmask
);
1117 buf
->dirty
.bit
.send_filter
|= wetmask
;
1120 return DSERR_INVALIDPARAM
;
1121 case EAXSOURCE_ALLSENDPARAMETERS
:
1122 if(cbPropData
>= sizeof(EAXSOURCEALLSENDPROPERTIES
))
1124 union { const void *v
; const EAXSOURCEALLSENDPROPERTIES
*send
; } data
= { pPropData
};
1125 struct Send
*srcsend
[EAX_MAX_ACTIVE_FXSLOTS
];
1126 LONG count
= cbPropData
/ sizeof(EAXSOURCEALLSENDPROPERTIES
);
1129 if(count
> buf
->share
->num_sends
)
1131 ERR("Setting %ld sends, only %d supported\n", count
, buf
->share
->num_sends
);
1132 return DSERR_INVALIDPARAM
;
1135 for(i
= 0;i
< count
;++i
)
1137 TRACE("All send parameters:\n\tReceiving: %s\n\tSend: %ld\n\tSend HF: %ld\n\t"
1138 "Occlusion: %ld\n\tOcclusion LF Ratio: %f\n\tOcclusion Room Ratio: %f\n\t"
1139 "Occlusion Direct Ratio: %f\n\tExclusion: %ld\n\tExclusion LF Ratio: %f\n",
1140 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
),
1141 data
.send
[i
].lSend
, data
.send
[i
].lSendHF
, data
.send
[i
].lOcclusion
,
1142 data
.send
[i
].flOcclusionLFRatio
, data
.send
[i
].flOcclusionRoomRatio
,
1143 data
.send
[i
].flOcclusionDirectRatio
, data
.send
[i
].lExclusion
,
1144 data
.send
[i
].flExclusionLFRatio
1146 srcsend
[i
] = FindDeferredSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1149 ERR("Failed to find active FXSlot target: %s\n",
1150 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1151 return DSERR_INVALIDPARAM
;
1153 wetmask
|= 1 << (srcsend
[i
]-buf
->deferred
.send
);
1156 for(i
= 0;i
< count
;++i
)
1158 srcsend
[i
]->lSend
= data
.send
[i
].lSend
;
1159 srcsend
[i
]->lSendHF
= data
.send
[i
].lSendHF
;
1160 srcsend
[i
]->lOcclusion
= data
.send
[i
].lOcclusion
;
1161 srcsend
[i
]->flOcclusionLFRatio
= data
.send
[i
].flOcclusionLFRatio
;
1162 srcsend
[i
]->flOcclusionRoomRatio
= data
.send
[i
].flOcclusionRoomRatio
;
1163 srcsend
[i
]->flOcclusionDirectRatio
= data
.send
[i
].flOcclusionDirectRatio
;
1164 srcsend
[i
]->lExclusion
= data
.send
[i
].lExclusion
;
1165 srcsend
[i
]->flExclusionLFRatio
= data
.send
[i
].flExclusionLFRatio
;
1167 ApplyFilterParams(buf
, &buf
->deferred
.eax
, wetmask
|APPLY_DRY_PARAMS
);
1169 buf
->dirty
.bit
.dry_filter
= 1;
1170 buf
->dirty
.bit
.send_filter
|= wetmask
;
1173 return DSERR_INVALIDPARAM
;
1174 case EAXSOURCE_OCCLUSIONSENDPARAMETERS
:
1175 if(cbPropData
>= sizeof(EAXSOURCEOCCLUSIONSENDPROPERTIES
))
1177 union { const void *v
; const EAXSOURCEOCCLUSIONSENDPROPERTIES
*send
; } data
= { pPropData
};
1178 struct Send
*srcsend
[EAX_MAX_ACTIVE_FXSLOTS
];
1179 LONG count
= cbPropData
/ sizeof(EAXSOURCEOCCLUSIONSENDPROPERTIES
);
1182 if(count
> buf
->share
->num_sends
)
1184 ERR("Setting %ld sends, only %d supported\n", count
, buf
->share
->num_sends
);
1185 return DSERR_INVALIDPARAM
;
1188 for(i
= 0;i
< count
;++i
)
1190 TRACE("Occlusion send parameters:\n\tReceiving: %s\n\tOcclusion: %ld\n\t"
1191 "Occlusion LF Ratio: %f\n\tOcclusion Room Ratio: %f\n\t"
1192 "Occlusion Direct Ratio: %f\n",
1193 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
), data
.send
[i
].lOcclusion
,
1194 data
.send
[i
].flOcclusionLFRatio
, data
.send
[i
].flOcclusionRoomRatio
,
1195 data
.send
[i
].flOcclusionDirectRatio
1197 srcsend
[i
] = FindDeferredSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1200 ERR("Failed to find active FXSlot target: %s\n",
1201 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1202 return DSERR_INVALIDPARAM
;
1204 wetmask
|= 1 << (srcsend
[i
]-buf
->deferred
.send
);
1207 for(i
= 0;i
< count
;++i
)
1209 srcsend
[i
]->lOcclusion
= data
.send
[i
].lOcclusion
;
1210 srcsend
[i
]->flOcclusionLFRatio
= data
.send
[i
].flOcclusionLFRatio
;
1211 srcsend
[i
]->flOcclusionRoomRatio
= data
.send
[i
].flOcclusionRoomRatio
;
1212 srcsend
[i
]->flOcclusionDirectRatio
= data
.send
[i
].flOcclusionDirectRatio
;
1214 ApplyFilterParams(buf
, &buf
->deferred
.eax
, wetmask
|APPLY_DRY_PARAMS
);
1216 buf
->dirty
.bit
.dry_filter
= 1;
1217 buf
->dirty
.bit
.send_filter
|= wetmask
;
1220 return DSERR_INVALIDPARAM
;
1221 case EAXSOURCE_EXCLUSIONSENDPARAMETERS
:
1222 if(cbPropData
>= sizeof(EAXSOURCEEXCLUSIONSENDPROPERTIES
))
1224 union { const void *v
; const EAXSOURCEEXCLUSIONSENDPROPERTIES
*send
; } data
= { pPropData
};
1225 struct Send
*srcsend
[EAX_MAX_ACTIVE_FXSLOTS
];
1226 LONG count
= cbPropData
/ sizeof(EAXSOURCEEXCLUSIONSENDPROPERTIES
);
1229 if(count
> buf
->share
->num_sends
)
1231 ERR("Setting %ld sends, only %d supported\n", count
, buf
->share
->num_sends
);
1232 return DSERR_INVALIDPARAM
;
1235 for(i
= 0;i
< count
;++i
)
1237 TRACE("Exclusion send parameters:\n\tReceiving: %s\n\tExclusion: %ld\n\t"
1238 "Exclusion LF Ratio: %f\n",
1239 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
),
1240 data
.send
[i
].lExclusion
, data
.send
[i
].flExclusionLFRatio
1242 srcsend
[i
] = FindDeferredSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1245 ERR("Failed to find active FXSlot target: %s\n",
1246 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1247 return DSERR_INVALIDPARAM
;
1249 wetmask
|= 1 << (srcsend
[i
]-buf
->deferred
.send
);
1252 for(i
= 0;i
< count
;++i
)
1254 srcsend
[i
]->lExclusion
= data
.send
[i
].lExclusion
;
1255 srcsend
[i
]->flExclusionLFRatio
= data
.send
[i
].flExclusionLFRatio
;
1257 ApplyFilterParams(buf
, &buf
->deferred
.eax
, wetmask
);
1259 buf
->dirty
.bit
.send_filter
|= wetmask
;
1262 return DSERR_INVALIDPARAM
;
1264 case EAXSOURCE_ACTIVEFXSLOTID
:
1265 if(cbPropData
&& (cbPropData
%sizeof(GUID
)) == 0)
1267 union { const void *v
; const GUID
*guid
; } data
= { pPropData
};
1268 DWORD targets
[EAX_MAX_ACTIVE_FXSLOTS
];
1269 LONG count
= cbPropData
/ sizeof(GUID
);
1272 if(count
> buf
->share
->num_sends
)
1274 ERR("Setting %ld sends, only %d supported\n", count
, buf
->share
->num_sends
);
1275 return DSERR_INVALIDPARAM
;
1278 for(i
= 0;i
< count
;i
++)
1280 TRACE("Active FXSlot %ld: %s\n", i
, debug_fxslot(&data
.guid
[i
]));
1282 targets
[i
] = FXSLOT_TARGET_NULL
;
1283 if(IsEqualGUID(&data
.guid
[i
], &EAXPROPERTYID_EAX40_FXSlot0
))
1284 targets
[i
] = FXSLOT_TARGET_0
;
1285 else if(IsEqualGUID(&data
.guid
[i
], &EAXPROPERTYID_EAX40_FXSlot1
))
1286 targets
[i
] = FXSLOT_TARGET_1
;
1287 else if(IsEqualGUID(&data
.guid
[i
], &EAXPROPERTYID_EAX40_FXSlot2
))
1288 targets
[i
] = FXSLOT_TARGET_2
;
1289 else if(IsEqualGUID(&data
.guid
[i
], &EAXPROPERTYID_EAX40_FXSlot3
))
1290 targets
[i
] = FXSLOT_TARGET_3
;
1291 else if(IsEqualGUID(&data
.guid
[i
], &EAX_PrimaryFXSlotID
))
1292 targets
[i
] = FXSLOT_TARGET_PRIMARY
;
1293 if(targets
[i
] == FXSLOT_TARGET_NULL
&& !IsEqualGUID(&data
.guid
[i
], &EAX_NULL_GUID
))
1295 ERR("Invalid FXSlot: %s\n", debug_fxslot(&data
.guid
[i
]));
1296 return DSERR_INVALIDPARAM
;
1300 for(i
= 0;i
< count
;++i
)
1301 buf
->deferred
.fxslot_targets
[i
] = targets
[i
];
1302 buf
->dirty
.bit
.send_filter
|= (1<<count
) - 1;
1305 return DSERR_INVALIDPARAM
;
1307 FIXME("Unhandled propid: 0x%08lx\n", propid
);
1308 return E_PROP_ID_UNSUPPORTED
;
1311 HRESULT
EAX4Source_Get(DSBuffer
*buf
, DWORD propid
, void *pPropData
, ULONG cbPropData
, ULONG
*pcbReturned
)
1313 if(!HAS_EXTENSION(buf
->share
, EXT_EFX
))
1314 return E_PROP_ID_UNSUPPORTED
;
1318 case EAXSOURCE_NONE
:
1322 case EAXSOURCE_ALLPARAMETERS
:
1323 GET_PROP(buf
->current
.eax
, EAXSOURCEPROPERTIES
);
1325 case EAXSOURCE_OBSTRUCTIONPARAMETERS
:
1326 GET_PROP(EAXSourceObstruction(&buf
->current
.eax
), EAXOBSTRUCTIONPROPERTIES
);
1327 case EAXSOURCE_OCCLUSIONPARAMETERS
:
1328 GET_PROP(EAXSourceOcclusion(&buf
->current
.eax
), EAXOCCLUSIONPROPERTIES
);
1329 case EAXSOURCE_EXCLUSIONPARAMETERS
:
1330 GET_PROP(EAXSourceExclusion(&buf
->current
.eax
), EAXEXCLUSIONPROPERTIES
);
1332 case EAXSOURCE_DIRECT
:
1333 GET_PROP(buf
->current
.eax
.lDirect
, long);
1334 case EAXSOURCE_DIRECTHF
:
1335 GET_PROP(buf
->current
.eax
.lDirectHF
, long);
1337 case EAXSOURCE_ROOM
:
1338 GET_PROP(buf
->current
.eax
.lRoom
, long);
1339 case EAXSOURCE_ROOMHF
:
1340 GET_PROP(buf
->current
.eax
.lRoomHF
, long);
1342 case EAXSOURCE_OBSTRUCTION
:
1343 GET_PROP(buf
->current
.eax
.lObstruction
, long);
1344 case EAXSOURCE_OBSTRUCTIONLFRATIO
:
1345 GET_PROP(buf
->current
.eax
.flObstructionLFRatio
, float);
1347 case EAXSOURCE_OCCLUSION
:
1348 GET_PROP(buf
->current
.eax
.lOcclusion
, long);
1349 case EAXSOURCE_OCCLUSIONLFRATIO
:
1350 GET_PROP(buf
->current
.eax
.flOcclusionLFRatio
, float);
1351 case EAXSOURCE_OCCLUSIONROOMRATIO
:
1352 GET_PROP(buf
->current
.eax
.flOcclusionRoomRatio
, float);
1353 case EAXSOURCE_OCCLUSIONDIRECTRATIO
:
1354 GET_PROP(buf
->current
.eax
.flOcclusionDirectRatio
, float);
1356 case EAXSOURCE_EXCLUSION
:
1357 GET_PROP(buf
->current
.eax
.lExclusion
, long);
1358 case EAXSOURCE_EXCLUSIONLFRATIO
:
1359 GET_PROP(buf
->current
.eax
.flExclusionLFRatio
, float);
1361 case EAXSOURCE_OUTSIDEVOLUMEHF
:
1362 GET_PROP(buf
->current
.eax
.lOutsideVolumeHF
, long);
1364 case EAXSOURCE_DOPPLERFACTOR
:
1365 GET_PROP(buf
->current
.eax
.flDopplerFactor
, float);
1367 case EAXSOURCE_ROLLOFFFACTOR
:
1368 GET_PROP(buf
->current
.eax
.flRolloffFactor
, float);
1369 case EAXSOURCE_ROOMROLLOFFFACTOR
:
1370 GET_PROP(buf
->current
.eax
.flRoomRolloffFactor
, float);
1372 case EAXSOURCE_AIRABSORPTIONFACTOR
:
1373 GET_PROP(buf
->current
.eax
.flAirAbsorptionFactor
, float);
1375 case EAXSOURCE_FLAGS
:
1376 GET_PROP(buf
->current
.eax
.dwFlags
, DWORD
);
1378 case EAXSOURCE_SENDPARAMETERS
:
1379 if(cbPropData
>= sizeof(EAXSOURCESENDPROPERTIES
))
1381 union { void *v
; EAXSOURCESENDPROPERTIES
*send
; } data
= { pPropData
};
1382 const struct Send
*srcsend
[EAX_MAX_ACTIVE_FXSLOTS
];
1383 LONG count
= minI(cbPropData
/ sizeof(EAXSOURCESENDPROPERTIES
),
1384 EAX_MAX_ACTIVE_FXSLOTS
);
1387 for(i
= 0;i
< count
;++i
)
1389 srcsend
[i
] = FindCurrentSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1392 ERR("Failed to find active FXSlot target: %s\n",
1393 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1394 return DSERR_INVALIDPARAM
;
1398 for(i
= 0;i
< count
;++i
)
1400 data
.send
[i
].lSend
= srcsend
[i
]->lSend
;
1401 data
.send
[i
].lSendHF
= srcsend
[i
]->lSendHF
;
1403 *pcbReturned
= sizeof(EAXSOURCESENDPROPERTIES
)*count
;
1406 return DSERR_INVALIDPARAM
;
1408 case EAXSOURCE_ALLSENDPARAMETERS
:
1409 if(cbPropData
>= sizeof(EAXSOURCEALLSENDPROPERTIES
))
1411 union { void *v
; EAXSOURCEALLSENDPROPERTIES
*send
; } data
= { pPropData
};
1412 const struct Send
*srcsend
[EAX_MAX_ACTIVE_FXSLOTS
];
1413 LONG count
= minI(cbPropData
/ sizeof(EAXSOURCEALLSENDPROPERTIES
),
1414 EAX_MAX_ACTIVE_FXSLOTS
);
1417 for(i
= 0;i
< count
;++i
)
1419 srcsend
[i
] = FindCurrentSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1422 ERR("Failed to find active FXSlot target: %s\n",
1423 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1424 return DSERR_INVALIDPARAM
;
1428 for(i
= 0;i
< count
;++i
)
1430 data
.send
[i
].lSend
= srcsend
[i
]->lSend
;
1431 data
.send
[i
].lSendHF
= srcsend
[i
]->lSendHF
;
1432 data
.send
[i
].lOcclusion
= srcsend
[i
]->lOcclusion
;
1433 data
.send
[i
].flOcclusionLFRatio
= srcsend
[i
]->flOcclusionLFRatio
;
1434 data
.send
[i
].flOcclusionRoomRatio
= srcsend
[i
]->flOcclusionRoomRatio
;
1435 data
.send
[i
].flOcclusionDirectRatio
= srcsend
[i
]->flOcclusionDirectRatio
;
1436 data
.send
[i
].lExclusion
= srcsend
[i
]->lExclusion
;
1437 data
.send
[i
].flExclusionLFRatio
= srcsend
[i
]->flExclusionLFRatio
;
1439 *pcbReturned
= sizeof(EAXSOURCEALLSENDPROPERTIES
)*count
;
1442 return DSERR_INVALIDPARAM
;
1443 case EAXSOURCE_OCCLUSIONSENDPARAMETERS
:
1444 if(cbPropData
>= sizeof(EAXSOURCEOCCLUSIONSENDPROPERTIES
))
1446 union { void *v
; EAXSOURCEOCCLUSIONSENDPROPERTIES
*send
; } data
= { pPropData
};
1447 const struct Send
*srcsend
[EAX_MAX_ACTIVE_FXSLOTS
];
1448 LONG count
= minI(cbPropData
/ sizeof(EAXSOURCEOCCLUSIONSENDPROPERTIES
),
1449 EAX_MAX_ACTIVE_FXSLOTS
);
1452 for(i
= 0;i
< count
;++i
)
1454 srcsend
[i
] = FindCurrentSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1457 ERR("Failed to find active FXSlot target: %s\n",
1458 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1459 return DSERR_INVALIDPARAM
;
1463 for(i
= 0;i
< count
;++i
)
1465 data
.send
[i
].lOcclusion
= srcsend
[i
]->lOcclusion
;
1466 data
.send
[i
].flOcclusionLFRatio
= srcsend
[i
]->flOcclusionLFRatio
;
1467 data
.send
[i
].flOcclusionRoomRatio
= srcsend
[i
]->flOcclusionRoomRatio
;
1468 data
.send
[i
].flOcclusionDirectRatio
= srcsend
[i
]->flOcclusionDirectRatio
;
1470 *pcbReturned
= sizeof(EAXSOURCEOCCLUSIONSENDPROPERTIES
)*count
;
1473 return DSERR_INVALIDPARAM
;
1474 case EAXSOURCE_EXCLUSIONSENDPARAMETERS
:
1475 if(cbPropData
>= sizeof(EAXSOURCEEXCLUSIONSENDPROPERTIES
))
1477 union { void *v
; EAXSOURCEEXCLUSIONSENDPROPERTIES
*send
; } data
= { pPropData
};
1478 const struct Send
*srcsend
[EAX_MAX_ACTIVE_FXSLOTS
];
1479 LONG count
= minI(cbPropData
/ sizeof(EAXSOURCEEXCLUSIONSENDPROPERTIES
),
1480 EAX_MAX_ACTIVE_FXSLOTS
);
1483 for(i
= 0;i
< count
;++i
)
1485 srcsend
[i
] = FindCurrentSend(buf
, &data
.send
[i
].guidReceivingFXSlotID
);
1488 ERR("Failed to find active FXSlot target: %s\n",
1489 debug_fxslot(&data
.send
[i
].guidReceivingFXSlotID
));
1490 return DSERR_INVALIDPARAM
;
1494 for(i
= 0;i
< count
;++i
)
1496 data
.send
[i
].lExclusion
= srcsend
[i
]->lExclusion
;
1497 data
.send
[i
].flExclusionLFRatio
= srcsend
[i
]->flExclusionLFRatio
;
1499 *pcbReturned
= sizeof(EAXSOURCEEXCLUSIONSENDPROPERTIES
)*count
;
1502 return DSERR_INVALIDPARAM
;
1504 case EAXSOURCE_ACTIVEFXSLOTID
:
1505 if(cbPropData
>= sizeof(GUID
))
1507 union { void *v
; GUID
*guid
; } data
= { pPropData
};
1508 LONG count
= minI(cbPropData
/ sizeof(GUID
), EAX_MAX_ACTIVE_FXSLOTS
);
1511 for(i
= 0;i
< count
;++i
)
1513 if(buf
->current
.fxslot_targets
[i
] == FXSLOT_TARGET_0
)
1514 data
.guid
[i
] = EAXPROPERTYID_EAX40_FXSlot0
;
1515 else if(buf
->current
.fxslot_targets
[i
] == FXSLOT_TARGET_1
)
1516 data
.guid
[i
] = EAXPROPERTYID_EAX40_FXSlot1
;
1517 else if(buf
->current
.fxslot_targets
[i
] == FXSLOT_TARGET_2
)
1518 data
.guid
[i
] = EAXPROPERTYID_EAX40_FXSlot2
;
1519 else if(buf
->current
.fxslot_targets
[i
] == FXSLOT_TARGET_3
)
1520 data
.guid
[i
] = EAXPROPERTYID_EAX40_FXSlot3
;
1521 else if(buf
->current
.fxslot_targets
[i
] == FXSLOT_TARGET_PRIMARY
)
1522 data
.guid
[i
] = EAX_PrimaryFXSlotID
;
1523 else /*if(buf->current.fxslot_targets[i] >= FXSLOT_TARGET_NULL)*/
1524 data
.guid
[i
] = EAX_NULL_GUID
;
1527 *pcbReturned
= sizeof(GUID
)*count
;
1530 return DSERR_INVALIDPARAM
;
1532 FIXME("Unhandled propid: 0x%08lx\n", propid
);
1533 return E_PROP_ID_UNSUPPORTED
;