Report more correct DirectSoundPrivate device info
[dsound-openal.git] / eax.c
blobfd9a7116d7781f452737d4f92dd6ff6beef5a595
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
18 #define CONST_VTABLE
19 #include <stdarg.h>
20 #include <string.h>
22 #include "windows.h"
23 #include "dsound.h"
25 #include "dsound_private.h"
26 #include "eax-presets.h"
29 static void ApplyReverbParams(DS8Primary *prim, const EAX30LISTENERPROPERTIES *props)
31 /* FIXME: Need to validate property values... Ignore? Clamp? Error? */
32 prim->deferred.eax = *props;
33 alEffectf(prim->effect, AL_EAXREVERB_DENSITY,
34 clampF(powf(props->flEnvironmentSize, 3.0f) / 16.0f, 0.0f, 1.0f)
36 alEffectf(prim->effect, AL_EAXREVERB_DIFFUSION, props->flEnvironmentDiffusion);
38 alEffectf(prim->effect, AL_EAXREVERB_GAIN, mB_to_gain(props->lRoom));
39 alEffectf(prim->effect, AL_EAXREVERB_GAINHF, mB_to_gain(props->lRoomHF));
40 alEffectf(prim->effect, AL_EAXREVERB_GAINLF, mB_to_gain(props->lRoomLF));
42 alEffectf(prim->effect, AL_EAXREVERB_DECAY_TIME, props->flDecayTime);
43 alEffectf(prim->effect, AL_EAXREVERB_DECAY_HFRATIO, props->flDecayHFRatio);
44 alEffectf(prim->effect, AL_EAXREVERB_DECAY_LFRATIO, props->flDecayLFRatio);
46 /* NOTE: Imprecision can cause some converted volume levels to land outside
47 * EFX's gain limits (e.g. EAX's +1000mB volume limit gets converted to
48 * 3.162something, while EFX defines the limit as 3.16; close enough for
49 * practical uses, but still technically an error).
51 alEffectf(prim->effect, AL_EAXREVERB_REFLECTIONS_GAIN,
52 clampF(mB_to_gain(props->lReflections), AL_EAXREVERB_MIN_REFLECTIONS_GAIN,
53 AL_EAXREVERB_MAX_REFLECTIONS_GAIN)
55 alEffectf(prim->effect, AL_EAXREVERB_REFLECTIONS_DELAY, props->flReflectionsDelay);
56 alEffectfv(prim->effect, AL_EAXREVERB_REFLECTIONS_PAN, &props->vReflectionsPan.x);
58 alEffectf(prim->effect, AL_EAXREVERB_LATE_REVERB_GAIN,
59 clampF(mB_to_gain(props->lReverb), AL_EAXREVERB_MIN_LATE_REVERB_GAIN,
60 AL_EAXREVERB_MAX_LATE_REVERB_GAIN)
62 alEffectf(prim->effect, AL_EAXREVERB_LATE_REVERB_DELAY, props->flReverbDelay);
63 alEffectfv(prim->effect, AL_EAXREVERB_LATE_REVERB_PAN, &props->vReverbPan.x);
65 alEffectf(prim->effect, AL_EAXREVERB_ECHO_TIME, props->flEchoTime);
66 alEffectf(prim->effect, AL_EAXREVERB_ECHO_DEPTH, props->flEchoDepth);
68 alEffectf(prim->effect, AL_EAXREVERB_MODULATION_TIME, props->flModulationTime);
69 alEffectf(prim->effect, AL_EAXREVERB_MODULATION_DEPTH, props->flModulationDepth);
71 alEffectf(prim->effect, AL_EAXREVERB_AIR_ABSORPTION_GAINHF,
72 clampF(mB_to_gain(props->flAirAbsorptionHF), AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF,
73 AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF)
76 alEffectf(prim->effect, AL_EAXREVERB_HFREFERENCE, props->flHFReference);
77 alEffectf(prim->effect, AL_EAXREVERB_LFREFERENCE, props->flLFReference);
79 alEffectf(prim->effect, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, props->flRoomRolloffFactor);
81 alEffecti(prim->effect, AL_EAXREVERB_DECAY_HFLIMIT,
82 (props->dwFlags&EAX30LISTENERFLAGS_DECAYHFLIMIT) ?
83 AL_TRUE : AL_FALSE);
85 checkALError();
87 prim->dirty.bit.effect = 1;
90 static inline float minF(float a, float b)
91 { return (a <= b) ? a : b; }
92 static inline float maxF(float a, float b)
93 { return (a >= b) ? a : b; }
95 #define APPLY_DRY_PARAMS 1
96 #define APPLY_WET_PARAMS 2
97 static void ApplyFilterParams(DS8Buffer *buf, const EAX30BUFFERPROPERTIES *props, int apply)
99 /* The LFRatio properties determine how much the given level applies to low
100 * frequencies as well as high frequencies. Technically, given that the
101 * obstruction/occlusion/exclusion levels are the absolute level applied to
102 * high frequencies (relative to full-scale, according to the EAX 2.0 spec)
103 * while the HF filter gains are relative to the low, the HF gains should
104 * increase as LFRatio increases.
106 * However it seems Creative was either wrong when writing out the spec,
107 * or implemented it incorrectly, as the HF filter still applies in full
108 * regardless of the LFRatio. So to replicate the hardware behavior, we do
109 * the same here.
112 if((apply&APPLY_DRY_PARAMS))
114 float mb = props->lDirect + props->lObstruction*props->flObstructionLFRatio;
115 float mbhf = props->lDirectHF + props->lObstruction;
116 /* The interaction of ratios is pretty wierd. The typical combination
117 * of the two act as a minimal baseline, while the sum minus one is
118 * used when larger. This creates a more linear change with the
119 * individual ratios as DirectRatio goes beyond 1, but eases down as
120 * the two ratios go toward 0.
122 mb += maxF(props->flOcclusionLFRatio+props->flOcclusionDirectRatio-1.0f,
123 props->flOcclusionLFRatio*props->flOcclusionDirectRatio) * props->lOcclusion;
124 mbhf += props->lOcclusion * props->flOcclusionDirectRatio;
126 alFilterf(buf->filter[0], AL_LOWPASS_GAIN, minF(mB_to_gain(mb), 1.0f));
127 alFilterf(buf->filter[0], AL_LOWPASS_GAINHF, mB_to_gain(mbhf));
129 if((apply&APPLY_WET_PARAMS))
131 float mb = props->lRoom + props->lExclusion*props->flExclusionLFRatio;
132 float mbhf = props->lRoomHF + props->lExclusion;
133 mb += maxF(props->flOcclusionLFRatio+props->flOcclusionRoomRatio-1.0f,
134 props->flOcclusionLFRatio*props->flOcclusionRoomRatio) * props->lOcclusion;
135 mbhf += props->lOcclusion * props->flOcclusionRoomRatio;
137 alFilterf(buf->filter[1], AL_LOWPASS_GAIN, minF(mB_to_gain(mb), 1.0f));
138 alFilterf(buf->filter[1], AL_LOWPASS_GAINHF, mB_to_gain(mbhf));
140 checkALError();
144 static void RescaleEnvSize(EAX30LISTENERPROPERTIES *props, float newsize)
146 float scale = newsize / props->flEnvironmentSize;
148 props->flEnvironmentSize = newsize;
150 if((props->dwFlags&EAX30LISTENERFLAGS_DECAYTIMESCALE))
152 props->flDecayTime *= scale;
153 props->flDecayTime = clampF(props->flDecayTime, 0.1f, 20.0f);
155 if((props->dwFlags&EAX30LISTENERFLAGS_REFLECTIONSSCALE))
157 props->lReflections -= gain_to_mB(scale);
158 props->lReflections = clampI(props->lReflections, -10000, 1000);
160 if((props->dwFlags&EAX30LISTENERFLAGS_REFLECTIONSDELAYSCALE))
162 props->flReflectionsDelay *= scale;
163 props->flReflectionsDelay = clampF(props->flReflectionsDelay, 0.0f, 0.3f);
165 if((props->dwFlags&EAX30LISTENERFLAGS_REVERBSCALE))
167 LONG diff = gain_to_mB(scale);
168 /* This is scaled by an extra 1/3rd if decay time isn't also scaled, to
169 * account for the (lack of) change on the send's initial decay.
171 if(!(props->dwFlags&EAX30LISTENERFLAGS_DECAYTIMESCALE))
172 diff = diff * 3 / 2;
173 props->lReverb -= diff;
174 props->lReverb = clampI(props->lReverb, -10000, 2000);
176 if((props->dwFlags&EAX30LISTENERFLAGS_REVERBDELAYSCALE))
178 props->flReverbDelay *= scale;
179 props->flReverbDelay = clampF(props->flReverbDelay, 0.0f, 0.1f);
181 if((props->dwFlags&EAX30LISTENERFLAGS_ECHOTIMESCALE))
183 props->flEchoTime *= scale;
184 props->flEchoTime = clampF(props->flEchoTime, 0.075f, 0.25f);
186 if((props->dwFlags&EAX30LISTENERFLAGS_MODTIMESCALE))
188 props->flModulationTime *= scale;
189 props->flModulationTime = clampF(props->flModulationTime, 0.04f, 4.0f);
194 /*******************
195 * EAX 3 stuff
196 ******************/
198 static EAXOBSTRUCTIONPROPERTIES EAX3BufferObstruction(const EAX30BUFFERPROPERTIES *props)
200 EAXOBSTRUCTIONPROPERTIES ret;
201 ret.lObstruction = props->lObstruction;
202 ret.flObstructionLFRatio = props->flObstructionLFRatio;
203 return ret;
206 static EAXOCCLUSIONPROPERTIES EAX3BufferOcclusion(const EAX30BUFFERPROPERTIES *props)
208 EAXOCCLUSIONPROPERTIES ret;
209 ret.lOcclusion = props->lOcclusion;
210 ret.flOcclusionLFRatio = props->flOcclusionLFRatio;
211 ret.flOcclusionRoomRatio = props->flOcclusionRoomRatio;
212 ret.flOcclusionDirectRatio = props->flOcclusionDirectRatio;
213 return ret;
216 static EAXEXCLUSIONPROPERTIES EAX3BufferExclusion(const EAX30BUFFERPROPERTIES *props)
218 EAXEXCLUSIONPROPERTIES ret;
219 ret.lExclusion = props->lExclusion;
220 ret.flExclusionLFRatio = props->flExclusionLFRatio;
221 return ret;
224 HRESULT EAX3_Query(DS8Primary *prim, DWORD propid, ULONG *pTypeSupport)
226 if(prim->effect == 0)
227 return E_PROP_ID_UNSUPPORTED;
229 switch(propid)
231 case DSPROPERTY_EAX30LISTENER_NONE:
232 case DSPROPERTY_EAX30LISTENER_ALLPARAMETERS:
233 case DSPROPERTY_EAX30LISTENER_ENVIRONMENT:
234 case DSPROPERTY_EAX30LISTENER_ENVIRONMENTSIZE:
235 case DSPROPERTY_EAX30LISTENER_ENVIRONMENTDIFFUSION:
236 case DSPROPERTY_EAX30LISTENER_ROOM:
237 case DSPROPERTY_EAX30LISTENER_ROOMHF:
238 case DSPROPERTY_EAX30LISTENER_ROOMLF:
239 case DSPROPERTY_EAX30LISTENER_DECAYTIME:
240 case DSPROPERTY_EAX30LISTENER_DECAYHFRATIO:
241 case DSPROPERTY_EAX30LISTENER_DECAYLFRATIO:
242 case DSPROPERTY_EAX30LISTENER_REFLECTIONS:
243 case DSPROPERTY_EAX30LISTENER_REFLECTIONSDELAY:
244 case DSPROPERTY_EAX30LISTENER_REFLECTIONSPAN:
245 case DSPROPERTY_EAX30LISTENER_REVERB:
246 case DSPROPERTY_EAX30LISTENER_REVERBDELAY:
247 case DSPROPERTY_EAX30LISTENER_REVERBPAN:
248 case DSPROPERTY_EAX30LISTENER_ECHOTIME:
249 case DSPROPERTY_EAX30LISTENER_ECHODEPTH:
250 case DSPROPERTY_EAX30LISTENER_MODULATIONTIME:
251 case DSPROPERTY_EAX30LISTENER_MODULATIONDEPTH:
252 case DSPROPERTY_EAX30LISTENER_AIRABSORPTIONHF:
253 case DSPROPERTY_EAX30LISTENER_HFREFERENCE:
254 case DSPROPERTY_EAX30LISTENER_LFREFERENCE:
255 case DSPROPERTY_EAX30LISTENER_ROOMROLLOFFFACTOR:
256 case DSPROPERTY_EAX30LISTENER_FLAGS:
257 *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
258 return DS_OK;
260 default:
261 FIXME("Unhandled propid: 0x%08lx\n", propid);
263 return E_PROP_ID_UNSUPPORTED;
266 HRESULT EAX3_Set(DS8Primary *prim, DWORD propid, void *pPropData, ULONG cbPropData)
268 HRESULT hr;
270 if(prim->effect == 0)
271 return E_PROP_ID_UNSUPPORTED;
273 hr = DSERR_INVALIDPARAM;
274 switch(propid)
276 case DSPROPERTY_EAX30LISTENER_NONE: /* not setting any property, just applying */
277 hr = DS_OK;
278 break;
280 case DSPROPERTY_EAX30LISTENER_ALLPARAMETERS:
281 if(cbPropData >= sizeof(EAX30LISTENERPROPERTIES))
283 union {
284 const void *v;
285 const EAX30LISTENERPROPERTIES *props;
286 } data = { pPropData };
287 TRACE("Parameters:\n\tEnvironment: %lu\n\tEnvSize: %f\n\tEnvDiffusion: %f\n\t"
288 "Room: %ld\n\tRoom HF: %ld\n\tRoom LF: %ld\n\tDecay Time: %f\n\t"
289 "Decay HF Ratio: %f\n\tDecay LF Ratio: %f\n\tReflections: %ld\n\t"
290 "Reflections Delay: %f\n\tReflections Pan: { %f, %f, %f }\n\tReverb: %ld\n\t"
291 "Reverb Delay: %f\n\tReverb Pan: { %f, %f, %f }\n\tEcho Time: %f\n\t"
292 "Echo Depth: %f\n\tMod Time: %f\n\tMod Depth: %f\n\tAir Absorption: %f\n\t"
293 "HF Reference: %f\n\tLF Reference: %f\n\tRoom Rolloff: %f\n\tFlags: 0x%02lx\n",
294 data.props->dwEnvironment, data.props->flEnvironmentSize,
295 data.props->flEnvironmentDiffusion, data.props->lRoom, data.props->lRoomHF,
296 data.props->lRoomLF, data.props->flDecayTime, data.props->flDecayHFRatio,
297 data.props->flDecayLFRatio, data.props->lReflections,
298 data.props->flReflectionsDelay, data.props->vReflectionsPan.x,
299 data.props->vReflectionsPan.y, data.props->vReflectionsPan.z, data.props->lReverb,
300 data.props->flReverbDelay, data.props->vReverbPan.x, data.props->vReverbPan.y,
301 data.props->vReverbPan.z, data.props->flEchoTime, data.props->flEchoDepth,
302 data.props->flModulationTime, data.props->flModulationDepth,
303 data.props->flAirAbsorptionHF, data.props->flHFReference,
304 data.props->flLFReference, data.props->flRoomRolloffFactor, data.props->dwFlags
307 ApplyReverbParams(prim, data.props);
308 hr = DS_OK;
310 break;
312 case DSPROPERTY_EAX30LISTENER_ENVIRONMENT:
313 if(cbPropData >= sizeof(DWORD))
315 union { const void *v; const DWORD *dw; } data = { pPropData };
316 TRACE("Environment: %lu\n", *data.dw);
317 if(*data.dw < EAX_ENVIRONMENT_UNDEFINED)
319 ApplyReverbParams(prim, &EnvironmentDefaults[*data.dw]);
320 hr = DS_OK;
323 break;
325 case DSPROPERTY_EAX30LISTENER_ENVIRONMENTSIZE:
326 if(cbPropData >= sizeof(float))
328 union { const void *v; const float *fl; } data = { pPropData };
329 TRACE("Environment Size: %f\n", *data.fl);
331 RescaleEnvSize(&prim->deferred.eax, clampF(*data.fl, 1.0f, 100.0f));
333 ApplyReverbParams(prim, &prim->deferred.eax);
334 hr = DS_OK;
336 break;
337 case DSPROPERTY_EAX30LISTENER_ENVIRONMENTDIFFUSION:
338 if(cbPropData >= sizeof(float))
340 union { const void *v; const float *fl; } data = { pPropData };
341 TRACE("Environment Diffusion: %f\n", *data.fl);
343 prim->deferred.eax.flEnvironmentDiffusion = *data.fl;
344 alEffectf(prim->effect, AL_EAXREVERB_DIFFUSION,
345 prim->deferred.eax.flEnvironmentDiffusion);
346 checkALError();
348 prim->dirty.bit.effect = 1;
349 hr = DS_OK;
351 break;
353 case DSPROPERTY_EAX30LISTENER_ROOM:
354 if(cbPropData >= sizeof(long))
356 union { const void *v; const long *l; } data = { pPropData };
357 TRACE("Room: %ld\n", *data.l);
359 prim->deferred.eax.lRoom = *data.l;
360 alEffectf(prim->effect, AL_EAXREVERB_GAIN,
361 mB_to_gain(prim->deferred.eax.lRoom));
362 checkALError();
364 prim->dirty.bit.effect = 1;
365 hr = DS_OK;
367 break;
368 case DSPROPERTY_EAX30LISTENER_ROOMHF:
369 if(cbPropData >= sizeof(long))
371 union { const void *v; const long *l; } data = { pPropData };
372 TRACE("Room HF: %ld\n", *data.l);
374 prim->deferred.eax.lRoomHF = *data.l;
375 alEffectf(prim->effect, AL_EAXREVERB_GAINHF,
376 mB_to_gain(prim->deferred.eax.lRoomHF));
377 checkALError();
379 prim->dirty.bit.effect = 1;
380 hr = DS_OK;
382 break;
383 case DSPROPERTY_EAX30LISTENER_ROOMLF:
384 if(cbPropData >= sizeof(long))
386 union { const void *v; const long *l; } data = { pPropData };
387 TRACE("Room LF: %ld\n", *data.l);
389 prim->deferred.eax.lRoomLF = *data.l;
390 alEffectf(prim->effect, AL_EAXREVERB_GAINLF,
391 mB_to_gain(prim->deferred.eax.lRoomLF));
392 checkALError();
394 prim->dirty.bit.effect = 1;
395 hr = DS_OK;
397 break;
399 case DSPROPERTY_EAX30LISTENER_DECAYTIME:
400 if(cbPropData >= sizeof(float))
402 union { const void *v; const float *fl; } data = { pPropData };
403 TRACE("Decay Time: %f\n", *data.fl);
405 prim->deferred.eax.flDecayTime = *data.fl;
406 alEffectf(prim->effect, AL_EAXREVERB_DECAY_TIME,
407 prim->deferred.eax.flDecayTime);
408 checkALError();
410 prim->dirty.bit.effect = 1;
411 hr = DS_OK;
413 break;
414 case DSPROPERTY_EAX30LISTENER_DECAYHFRATIO:
415 if(cbPropData >= sizeof(float))
417 union { const void *v; const float *fl; } data = { pPropData };
418 TRACE("Decay HF Ratio: %f\n", *data.fl);
420 prim->deferred.eax.flDecayHFRatio = *data.fl;
421 alEffectf(prim->effect, AL_EAXREVERB_DECAY_HFRATIO,
422 prim->deferred.eax.flDecayHFRatio);
423 checkALError();
425 prim->dirty.bit.effect = 1;
426 hr = DS_OK;
428 break;
429 case DSPROPERTY_EAX30LISTENER_DECAYLFRATIO:
430 if(cbPropData >= sizeof(float))
432 union { const void *v; const float *fl; } data = { pPropData };
433 TRACE("Decay LF Ratio: %f\n", *data.fl);
435 prim->deferred.eax.flDecayLFRatio = *data.fl;
436 alEffectf(prim->effect, AL_EAXREVERB_DECAY_LFRATIO,
437 prim->deferred.eax.flDecayLFRatio);
438 checkALError();
440 prim->dirty.bit.effect = 1;
441 hr = DS_OK;
443 break;
445 case DSPROPERTY_EAX30LISTENER_REFLECTIONS:
446 if(cbPropData >= sizeof(long))
448 union { const void *v; const long *l; } data = { pPropData };
449 TRACE("Reflections: %ld\n", *data.l);
451 prim->deferred.eax.lReflections = *data.l;
452 alEffectf(prim->effect, AL_EAXREVERB_REFLECTIONS_GAIN,
453 mB_to_gain(prim->deferred.eax.lReflections));
454 checkALError();
456 prim->dirty.bit.effect = 1;
457 hr = DS_OK;
459 break;
460 case DSPROPERTY_EAX30LISTENER_REFLECTIONSDELAY:
461 if(cbPropData >= sizeof(float))
463 union { const void *v; const float *fl; } data = { pPropData };
464 TRACE("Reflections Delay: %f\n", *data.fl);
466 prim->deferred.eax.flReflectionsDelay = *data.fl;
467 alEffectf(prim->effect, AL_EAXREVERB_REFLECTIONS_DELAY,
468 prim->deferred.eax.flReflectionsDelay);
469 checkALError();
471 prim->dirty.bit.effect = 1;
472 hr = DS_OK;
474 break;
475 case DSPROPERTY_EAX30LISTENER_REFLECTIONSPAN:
476 if(cbPropData >= sizeof(EAXVECTOR))
478 union { const void *v; const EAXVECTOR *vec; } data = { pPropData };
479 TRACE("Reflections Pan: { %f, %f, %f }\n", data.vec->x, data.vec->y, data.vec->z);
481 prim->deferred.eax.vReflectionsPan = *data.vec;
482 alEffectfv(prim->effect, AL_EAXREVERB_REFLECTIONS_PAN,
483 &prim->deferred.eax.vReflectionsPan.x);
484 checkALError();
486 prim->dirty.bit.effect = 1;
487 hr = DS_OK;
489 break;
491 case DSPROPERTY_EAX30LISTENER_REVERB:
492 if(cbPropData >= sizeof(long))
494 union { const void *v; const long *l; } data = { pPropData };
495 TRACE("Reverb: %ld\n", *data.l);
497 prim->deferred.eax.lReverb = *data.l;
498 alEffectf(prim->effect, AL_EAXREVERB_LATE_REVERB_GAIN,
499 mB_to_gain(prim->deferred.eax.lReverb));
500 checkALError();
502 prim->dirty.bit.effect = 1;
503 hr = DS_OK;
505 break;
506 case DSPROPERTY_EAX30LISTENER_REVERBDELAY:
507 if(cbPropData >= sizeof(float))
509 union { const void *v; const float *fl; } data = { pPropData };
510 TRACE("Reverb Delay: %f\n", *data.fl);
512 prim->deferred.eax.flReverbDelay = *data.fl;
513 alEffectf(prim->effect, AL_EAXREVERB_LATE_REVERB_DELAY,
514 prim->deferred.eax.flReverbDelay);
515 checkALError();
517 prim->dirty.bit.effect = 1;
518 hr = DS_OK;
520 break;
521 case DSPROPERTY_EAX30LISTENER_REVERBPAN:
522 if(cbPropData >= sizeof(EAXVECTOR))
524 union { const void *v; const EAXVECTOR *vec; } data = { pPropData };
525 TRACE("Reverb Pan: { %f, %f, %f }\n", data.vec->x, data.vec->y, data.vec->z);
527 prim->deferred.eax.vReverbPan = *data.vec;
528 alEffectfv(prim->effect, AL_EAXREVERB_LATE_REVERB_PAN,
529 &prim->deferred.eax.vReverbPan.x);
530 checkALError();
532 prim->dirty.bit.effect = 1;
533 hr = DS_OK;
535 break;
537 case DSPROPERTY_EAX30LISTENER_ECHOTIME:
538 if(cbPropData >= sizeof(float))
540 union { const void *v; const float *fl; } data = { pPropData };
541 TRACE("Echo Time: %f\n", *data.fl);
543 prim->deferred.eax.flEchoTime = *data.fl;
544 alEffectf(prim->effect, AL_EAXREVERB_ECHO_TIME,
545 prim->deferred.eax.flEchoTime);
546 checkALError();
548 prim->dirty.bit.effect = 1;
549 hr = DS_OK;
551 break;
552 case DSPROPERTY_EAX30LISTENER_ECHODEPTH:
553 if(cbPropData >= sizeof(float))
555 union { const void *v; const float *fl; } data = { pPropData };
556 TRACE("Echo Depth: %f\n", *data.fl);
558 prim->deferred.eax.flEchoDepth = *data.fl;
559 alEffectf(prim->effect, AL_EAXREVERB_ECHO_DEPTH,
560 prim->deferred.eax.flEchoDepth);
561 checkALError();
563 prim->dirty.bit.effect = 1;
564 hr = DS_OK;
566 break;
568 case DSPROPERTY_EAX30LISTENER_MODULATIONTIME:
569 if(cbPropData >= sizeof(float))
571 union { const void *v; const float *fl; } data = { pPropData };
572 TRACE("Modulation Time: %f\n", *data.fl);
574 prim->deferred.eax.flModulationTime = *data.fl;
575 alEffectf(prim->effect, AL_EAXREVERB_MODULATION_TIME,
576 prim->deferred.eax.flModulationTime);
577 checkALError();
579 prim->dirty.bit.effect = 1;
580 hr = DS_OK;
582 break;
583 case DSPROPERTY_EAX30LISTENER_MODULATIONDEPTH:
584 if(cbPropData >= sizeof(float))
586 union { const void *v; const float *fl; } data = { pPropData };
587 TRACE("Modulation Depth: %f\n", *data.fl);
589 prim->deferred.eax.flModulationDepth = *data.fl;
590 alEffectf(prim->effect, AL_EAXREVERB_MODULATION_DEPTH,
591 prim->deferred.eax.flModulationDepth);
592 checkALError();
594 prim->dirty.bit.effect = 1;
595 hr = DS_OK;
597 break;
599 case DSPROPERTY_EAX30LISTENER_AIRABSORPTIONHF:
600 if(cbPropData >= sizeof(float))
602 union { const void *v; const float *fl; } data = { pPropData };
603 TRACE("Air Absorption HF: %f\n", *data.fl);
605 prim->deferred.eax.flAirAbsorptionHF = *data.fl;
606 alEffectf(prim->effect, AL_EAXREVERB_AIR_ABSORPTION_GAINHF,
607 mB_to_gain(prim->deferred.eax.flAirAbsorptionHF));
608 checkALError();
610 prim->dirty.bit.effect = 1;
611 hr = DS_OK;
613 break;
615 case DSPROPERTY_EAX30LISTENER_HFREFERENCE:
616 if(cbPropData >= sizeof(float))
618 union { const void *v; const float *fl; } data = { pPropData };
619 TRACE("HF Reference: %f\n", *data.fl);
621 prim->deferred.eax.flHFReference = *data.fl;
622 alEffectf(prim->effect, AL_EAXREVERB_HFREFERENCE,
623 prim->deferred.eax.flHFReference);
624 checkALError();
626 prim->dirty.bit.effect = 1;
627 hr = DS_OK;
629 break;
630 case DSPROPERTY_EAX30LISTENER_LFREFERENCE:
631 if(cbPropData >= sizeof(float))
633 union { const void *v; const float *fl; } data = { pPropData };
634 TRACE("LF Reference: %f\n", *data.fl);
636 prim->deferred.eax.flLFReference = *data.fl;
637 alEffectf(prim->effect, AL_EAXREVERB_LFREFERENCE,
638 prim->deferred.eax.flLFReference);
639 checkALError();
641 prim->dirty.bit.effect = 1;
642 hr = DS_OK;
644 break;
646 case DSPROPERTY_EAX30LISTENER_ROOMROLLOFFFACTOR:
647 if(cbPropData >= sizeof(float))
649 union { const void *v; const float *fl; } data = { pPropData };
650 TRACE("Room Rolloff Factor: %f\n", *data.fl);
652 prim->deferred.eax.flRoomRolloffFactor = *data.fl;
653 alEffectf(prim->effect, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR,
654 prim->deferred.eax.flRoomRolloffFactor);
655 checkALError();
657 prim->dirty.bit.effect = 1;
658 hr = DS_OK;
660 break;
662 case DSPROPERTY_EAX30LISTENER_FLAGS:
663 if(cbPropData >= sizeof(DWORD))
665 union { const void *v; const DWORD *dw; } data = { pPropData };
666 TRACE("Flags: %lu\n", *data.dw);
668 prim->deferred.eax.dwFlags = *data.dw;
669 alEffecti(prim->effect, AL_EAXREVERB_DECAY_HFLIMIT,
670 (prim->deferred.eax.dwFlags&EAX30LISTENERFLAGS_DECAYHFLIMIT) ?
671 AL_TRUE : AL_FALSE);
672 checkALError();
674 prim->dirty.bit.effect = 1;
675 hr = DS_OK;
677 break;
679 default:
680 hr = E_PROP_ID_UNSUPPORTED;
681 FIXME("Unhandled propid: 0x%08lx\n", propid);
682 break;
685 return hr;
688 HRESULT EAX3_Get(DS8Primary *prim, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned)
690 HRESULT hr;
692 if(prim->effect == 0)
693 return E_PROP_ID_UNSUPPORTED;
695 #define GET_PROP(src, T) do { \
696 if(cbPropData >= sizeof(T)) \
698 union { void *v; T *props; } data = { pPropData }; \
699 *data.props = src; \
700 *pcbReturned = sizeof(T); \
701 hr = DS_OK; \
703 } while(0)
704 hr = DSERR_INVALIDPARAM;
705 switch(propid)
707 case DSPROPERTY_EAX30LISTENER_NONE:
708 *pcbReturned = 0;
709 hr = DS_OK;
710 break;
712 case DSPROPERTY_EAX30LISTENER_ALLPARAMETERS:
713 GET_PROP(prim->deferred.eax, EAX30LISTENERPROPERTIES);
714 break;
716 case DSPROPERTY_EAX30LISTENER_ENVIRONMENT:
717 GET_PROP(prim->deferred.eax.dwEnvironment, DWORD);
718 break;
720 case DSPROPERTY_EAX30LISTENER_ENVIRONMENTSIZE:
721 GET_PROP(prim->deferred.eax.flEnvironmentSize, float);
722 break;
723 case DSPROPERTY_EAX30LISTENER_ENVIRONMENTDIFFUSION:
724 GET_PROP(prim->deferred.eax.flEnvironmentDiffusion, float);
725 break;
727 case DSPROPERTY_EAX30LISTENER_ROOM:
728 GET_PROP(prim->deferred.eax.lRoom, long);
729 break;
730 case DSPROPERTY_EAX30LISTENER_ROOMHF:
731 GET_PROP(prim->deferred.eax.lRoomHF, long);
732 break;
733 case DSPROPERTY_EAX30LISTENER_ROOMLF:
734 GET_PROP(prim->deferred.eax.lRoomLF, long);
735 break;
737 case DSPROPERTY_EAX30LISTENER_DECAYTIME:
738 GET_PROP(prim->deferred.eax.flDecayTime, float);
739 break;
740 case DSPROPERTY_EAX30LISTENER_DECAYHFRATIO:
741 GET_PROP(prim->deferred.eax.flDecayHFRatio, float);
742 break;
743 case DSPROPERTY_EAX30LISTENER_DECAYLFRATIO:
744 GET_PROP(prim->deferred.eax.flDecayLFRatio, float);
745 break;
747 case DSPROPERTY_EAX30LISTENER_REFLECTIONS:
748 GET_PROP(prim->deferred.eax.lReflections, long);
749 break;
750 case DSPROPERTY_EAX30LISTENER_REFLECTIONSDELAY:
751 GET_PROP(prim->deferred.eax.flReflectionsDelay, float);
752 break;
753 case DSPROPERTY_EAX30LISTENER_REFLECTIONSPAN:
754 GET_PROP(prim->deferred.eax.vReflectionsPan, EAXVECTOR);
755 break;
757 case DSPROPERTY_EAX30LISTENER_REVERB:
758 GET_PROP(prim->deferred.eax.lReverb, long);
759 break;
760 case DSPROPERTY_EAX30LISTENER_REVERBDELAY:
761 GET_PROP(prim->deferred.eax.flReverbDelay, float);
762 break;
763 case DSPROPERTY_EAX30LISTENER_REVERBPAN:
764 GET_PROP(prim->deferred.eax.vReverbPan, EAXVECTOR);
765 break;
767 case DSPROPERTY_EAX30LISTENER_ECHOTIME:
768 GET_PROP(prim->deferred.eax.flEchoTime, float);
769 break;
770 case DSPROPERTY_EAX30LISTENER_ECHODEPTH:
771 GET_PROP(prim->deferred.eax.flEchoDepth, float);
772 break;
774 case DSPROPERTY_EAX30LISTENER_MODULATIONTIME:
775 GET_PROP(prim->deferred.eax.flModulationTime, float);
776 break;
777 case DSPROPERTY_EAX30LISTENER_MODULATIONDEPTH:
778 GET_PROP(prim->deferred.eax.flModulationDepth, float);
779 break;
781 case DSPROPERTY_EAX30LISTENER_AIRABSORPTIONHF:
782 GET_PROP(prim->deferred.eax.flAirAbsorptionHF, float);
783 break;
785 case DSPROPERTY_EAX30LISTENER_HFREFERENCE:
786 GET_PROP(prim->deferred.eax.flHFReference, float);
787 break;
788 case DSPROPERTY_EAX30LISTENER_LFREFERENCE:
789 GET_PROP(prim->deferred.eax.flLFReference, float);
790 break;
792 case DSPROPERTY_EAX30LISTENER_ROOMROLLOFFFACTOR:
793 GET_PROP(prim->deferred.eax.flRoomRolloffFactor, float);
794 break;
796 case DSPROPERTY_EAX30LISTENER_FLAGS:
797 GET_PROP(prim->deferred.eax.dwFlags, DWORD);
798 break;
800 default:
801 hr = E_PROP_ID_UNSUPPORTED;
802 FIXME("Unhandled propid: 0x%08lx\n", propid);
803 break;
805 #undef GET_PROP
807 return hr;
811 HRESULT EAX3Buffer_Query(DS8Buffer *buf, DWORD propid, ULONG *pTypeSupport)
813 if(buf->filter[0] == 0)
814 return E_PROP_ID_UNSUPPORTED;
816 switch(propid)
818 case DSPROPERTY_EAX30BUFFER_NONE:
819 case DSPROPERTY_EAX30BUFFER_ALLPARAMETERS:
820 case DSPROPERTY_EAX30BUFFER_OBSTRUCTIONPARAMETERS:
821 case DSPROPERTY_EAX30BUFFER_OCCLUSIONPARAMETERS:
822 case DSPROPERTY_EAX30BUFFER_EXCLUSIONPARAMETERS:
823 case DSPROPERTY_EAX30BUFFER_DIRECT:
824 case DSPROPERTY_EAX30BUFFER_DIRECTHF:
825 case DSPROPERTY_EAX30BUFFER_ROOM:
826 case DSPROPERTY_EAX30BUFFER_ROOMHF:
827 case DSPROPERTY_EAX30BUFFER_OBSTRUCTION:
828 case DSPROPERTY_EAX30BUFFER_OBSTRUCTIONLFRATIO:
829 case DSPROPERTY_EAX30BUFFER_OCCLUSION:
830 case DSPROPERTY_EAX30BUFFER_OCCLUSIONLFRATIO:
831 case DSPROPERTY_EAX30BUFFER_OCCLUSIONROOMRATIO:
832 case DSPROPERTY_EAX30BUFFER_OCCLUSIONDIRECTRATIO:
833 case DSPROPERTY_EAX30BUFFER_EXCLUSION:
834 case DSPROPERTY_EAX30BUFFER_EXCLUSIONLFRATIO:
835 case DSPROPERTY_EAX30BUFFER_OUTSIDEVOLUMEHF:
836 case DSPROPERTY_EAX30BUFFER_DOPPLERFACTOR:
837 case DSPROPERTY_EAX30BUFFER_ROLLOFFFACTOR:
838 case DSPROPERTY_EAX30BUFFER_ROOMROLLOFFFACTOR:
839 case DSPROPERTY_EAX30BUFFER_AIRABSORPTIONFACTOR:
840 case DSPROPERTY_EAX30BUFFER_FLAGS:
841 *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
842 return DS_OK;
844 default:
845 FIXME("Unhandled propid: 0x%08lx\n", propid);
847 return E_PROP_ID_UNSUPPORTED;
851 HRESULT EAX3Buffer_Set(DS8Buffer *buf, DWORD propid, void *pPropData, ULONG cbPropData)
853 HRESULT hr;
855 if(buf->filter[0] == 0)
856 return E_PROP_ID_UNSUPPORTED;
858 hr = DSERR_INVALIDPARAM;
859 switch(propid)
861 case DSPROPERTY_EAX30BUFFER_NONE: /* not setting any property, just applying */
862 hr = DS_OK;
863 break;
865 case DSPROPERTY_EAX30BUFFER_ALLPARAMETERS:
866 if(cbPropData >= sizeof(EAX30BUFFERPROPERTIES))
868 union {
869 const void *v;
870 const EAX30BUFFERPROPERTIES *props;
871 } data = { pPropData };
872 TRACE("Parameters:\n\tDirect: %ld\n\tDirect HF: %ld\n\tRoom: %ld\n\tRoom HF: %ld\n\t"
873 "Obstruction: %ld\n\tObstruction LF Ratio: %f\n\tOcclusion: %ld\n\t"
874 "Occlusion LF Ratio: %f\n\tOcclusion Room Ratio: %f\n\t"
875 "Occlusion Direct Ratio: %f\n\tExclusion: %ld\n\tExclusion LF Ratio: %f\n\t"
876 "Outside Volume HF: %ld\n\tDoppler Factor: %f\n\tRolloff Factor: %f\n\t"
877 "Room Rolloff Factor: %f\n\tAir Absorb Factor: %f\n\tFlags: 0x%02lx\n",
878 data.props->lDirect, data.props->lDirectHF, data.props->lRoom, data.props->lRoomHF,
879 data.props->lObstruction, data.props->flObstructionLFRatio, data.props->lOcclusion,
880 data.props->flOcclusionLFRatio, data.props->flOcclusionRoomRatio,
881 data.props->flOcclusionDirectRatio, data.props->lExclusion,
882 data.props->flExclusionLFRatio, data.props->lOutsideVolumeHF,
883 data.props->flDopplerFactor, data.props->flRolloffFactor,
884 data.props->flRoomRolloffFactor, data.props->flAirAbsorptionFactor,
885 data.props->dwFlags
888 buf->deferred.eax = *data.props;
889 ApplyFilterParams(buf, data.props, APPLY_DRY_PARAMS|APPLY_WET_PARAMS);
891 buf->dirty.bit.dry_filter = 1;
892 buf->dirty.bit.wet_filter = 1;
893 buf->dirty.bit.room_rolloff = 1;
894 buf->dirty.bit.cone_outsidevolumehf = 1;
895 buf->dirty.bit.air_absorb = 1;
896 buf->dirty.bit.flags = 1;
897 hr = DS_OK;
899 break;
900 case DSPROPERTY_EAX30BUFFER_OBSTRUCTIONPARAMETERS:
901 if(cbPropData >= sizeof(EAXOBSTRUCTIONPROPERTIES))
903 union {
904 const void *v;
905 const EAXOBSTRUCTIONPROPERTIES *props;
906 } data = { pPropData };
907 TRACE("Parameters:\n\tObstruction: %ld\n\tObstruction LF Ratio: %f\n",
908 data.props->lObstruction, data.props->flObstructionLFRatio);
910 buf->deferred.eax.lObstruction = data.props->lObstruction;
911 buf->deferred.eax.flObstructionLFRatio = data.props->flObstructionLFRatio;
912 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_DRY_PARAMS);
914 buf->dirty.bit.dry_filter = 1;
915 hr = DS_OK;
917 break;
918 case DSPROPERTY_EAX30BUFFER_OCCLUSIONPARAMETERS:
919 if(cbPropData >= sizeof(EAXOCCLUSIONPROPERTIES))
921 union {
922 const void *v;
923 const EAXOCCLUSIONPROPERTIES *props;
924 } data = { pPropData };
925 TRACE("Parameters:\n\tOcclusion: %ld\n\tOcclusion LF Ratio: %f\n\t"
926 "Occlusion Room Ratio: %f\n\tOcclusion Direct Ratio: %f\n",
927 data.props->lOcclusion, data.props->flOcclusionLFRatio,
928 data.props->flOcclusionRoomRatio, data.props->flOcclusionDirectRatio
931 buf->deferred.eax.lOcclusion = data.props->lOcclusion;
932 buf->deferred.eax.flOcclusionLFRatio = data.props->flOcclusionLFRatio;
933 buf->deferred.eax.flOcclusionRoomRatio = data.props->flOcclusionRoomRatio;
934 buf->deferred.eax.flOcclusionDirectRatio = data.props->flOcclusionDirectRatio;
935 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_DRY_PARAMS|APPLY_WET_PARAMS);
937 buf->dirty.bit.dry_filter = 1;
938 buf->dirty.bit.wet_filter = 1;
939 hr = DS_OK;
941 break;
942 case DSPROPERTY_EAX30BUFFER_EXCLUSIONPARAMETERS:
943 if(cbPropData >= sizeof(EAXEXCLUSIONPROPERTIES))
945 union {
946 const void *v;
947 const EAXEXCLUSIONPROPERTIES *props;
948 } data = { pPropData };
949 TRACE("Parameters:\n\tExclusion: %ld\n\tExclusion LF Ratio: %f\n",
950 data.props->lExclusion, data.props->flExclusionLFRatio);
952 buf->deferred.eax.lExclusion = data.props->lExclusion;
953 buf->deferred.eax.flExclusionLFRatio = data.props->flExclusionLFRatio;
954 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_WET_PARAMS);
956 buf->dirty.bit.wet_filter = 1;
957 hr = DS_OK;
959 break;
961 case DSPROPERTY_EAX30BUFFER_DIRECT:
962 if(cbPropData >= sizeof(long))
964 union { const void *v; const long *l; } data = { pPropData };
965 TRACE("Direct: %ld\n", *data.l);
967 buf->deferred.eax.lDirect = *data.l;
968 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_DRY_PARAMS);
970 buf->dirty.bit.dry_filter = 1;
971 hr = DS_OK;
973 break;
974 case DSPROPERTY_EAX30BUFFER_DIRECTHF:
975 if(cbPropData >= sizeof(long))
977 union { const void *v; const long *l; } data = { pPropData };
978 TRACE("Direct HF: %ld\n", *data.l);
980 buf->deferred.eax.lDirectHF = *data.l;
981 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_DRY_PARAMS);
983 buf->dirty.bit.dry_filter = 1;
984 hr = DS_OK;
986 break;
988 case DSPROPERTY_EAX30BUFFER_ROOM:
989 if(cbPropData >= sizeof(long))
991 union { const void *v; const long *l; } data = { pPropData };
992 TRACE("Room: %ld\n", *data.l);
994 buf->deferred.eax.lRoom = *data.l;
995 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_WET_PARAMS);
997 buf->dirty.bit.wet_filter = 1;
998 hr = DS_OK;
1000 break;
1001 case DSPROPERTY_EAX30BUFFER_ROOMHF:
1002 if(cbPropData >= sizeof(long))
1004 union { const void *v; const long *l; } data = { pPropData };
1005 TRACE("Room HF: %ld\n", *data.l);
1007 buf->deferred.eax.lRoomHF = *data.l;
1008 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_WET_PARAMS);
1010 buf->dirty.bit.wet_filter = 1;
1011 hr = DS_OK;
1013 break;
1015 case DSPROPERTY_EAX30BUFFER_OBSTRUCTION:
1016 if(cbPropData >= sizeof(long))
1018 union { const void *v; const long *l; } data = { pPropData };
1019 TRACE("Obstruction: %ld\n", *data.l);
1021 buf->deferred.eax.lObstruction = *data.l;
1022 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_DRY_PARAMS);
1024 buf->dirty.bit.dry_filter = 1;
1025 hr = DS_OK;
1027 break;
1028 case DSPROPERTY_EAX30BUFFER_OBSTRUCTIONLFRATIO:
1029 if(cbPropData >= sizeof(float))
1031 union { const void *v; const float *fl; } data = { pPropData };
1032 TRACE("Obstruction LF Ratio: %f\n", *data.fl);
1034 buf->deferred.eax.flObstructionLFRatio = *data.fl;
1035 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_DRY_PARAMS);
1037 buf->dirty.bit.dry_filter = 1;
1038 hr = DS_OK;
1040 break;
1042 case DSPROPERTY_EAX30BUFFER_OCCLUSION:
1043 if(cbPropData >= sizeof(long))
1045 union { const void *v; const long *l; } data = { pPropData };
1046 TRACE("Occlusion: %ld\n", *data.l);
1048 buf->deferred.eax.lOcclusion = *data.l;
1049 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_DRY_PARAMS|APPLY_WET_PARAMS);
1051 buf->dirty.bit.dry_filter = 1;
1052 buf->dirty.bit.wet_filter = 1;
1053 hr = DS_OK;
1055 break;
1056 case DSPROPERTY_EAX30BUFFER_OCCLUSIONLFRATIO:
1057 if(cbPropData >= sizeof(float))
1059 union { const void *v; const float *fl; } data = { pPropData };
1060 TRACE("Occlusion LF Ratio: %f\n", *data.fl);
1062 buf->deferred.eax.flOcclusionLFRatio = *data.fl;
1063 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_DRY_PARAMS|APPLY_WET_PARAMS);
1065 buf->dirty.bit.dry_filter = 1;
1066 buf->dirty.bit.wet_filter = 1;
1067 hr = DS_OK;
1069 break;
1070 case DSPROPERTY_EAX30BUFFER_OCCLUSIONROOMRATIO:
1071 if(cbPropData >= sizeof(float))
1073 union { const void *v; const float *fl; } data = { pPropData };
1074 TRACE("Occlusion Room Ratio: %f\n", *data.fl);
1076 buf->deferred.eax.flOcclusionRoomRatio = *data.fl;
1077 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_WET_PARAMS);
1079 buf->dirty.bit.wet_filter = 1;
1080 hr = DS_OK;
1082 break;
1083 case DSPROPERTY_EAX30BUFFER_OCCLUSIONDIRECTRATIO:
1084 if(cbPropData >= sizeof(float))
1086 union { const void *v; const float *fl; } data = { pPropData };
1087 TRACE("Occlusion Direct Ratio: %f\n", *data.fl);
1089 buf->deferred.eax.flOcclusionDirectRatio = *data.fl;
1090 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_DRY_PARAMS);
1092 buf->dirty.bit.dry_filter = 1;
1093 hr = DS_OK;
1095 break;
1097 case DSPROPERTY_EAX30BUFFER_EXCLUSION:
1098 if(cbPropData >= sizeof(long))
1100 union { const void *v; const long *l; } data = { pPropData };
1101 TRACE("Exclusion: %ld\n", *data.l);
1103 buf->deferred.eax.lExclusion = *data.l;
1104 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_WET_PARAMS);
1106 buf->dirty.bit.wet_filter = 1;
1107 hr = DS_OK;
1109 break;
1110 case DSPROPERTY_EAX30BUFFER_EXCLUSIONLFRATIO:
1111 if(cbPropData >= sizeof(float))
1113 union { const void *v; const float *fl; } data = { pPropData };
1114 TRACE("Exclusion LF Ratio: %f\n", *data.fl);
1116 buf->deferred.eax.flExclusionLFRatio = *data.fl;
1117 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_WET_PARAMS);
1119 buf->dirty.bit.wet_filter = 1;
1120 hr = DS_OK;
1122 break;
1124 case DSPROPERTY_EAX30BUFFER_OUTSIDEVOLUMEHF:
1125 if(cbPropData >= sizeof(long))
1127 union { const void *v; const long *l; } data = { pPropData };
1128 TRACE("Outisde Volume HF: %ld\n", *data.l);
1130 buf->deferred.eax.lOutsideVolumeHF = *data.l;
1132 buf->dirty.bit.cone_outsidevolumehf = 1;
1133 hr = DS_OK;
1135 break;
1137 case DSPROPERTY_EAX30BUFFER_DOPPLERFACTOR:
1138 if(cbPropData >= sizeof(float))
1140 union { const void *v; const float *fl; } data = { pPropData };
1141 TRACE("Doppler Factor: %f\n", *data.fl);
1143 buf->deferred.eax.flDopplerFactor = *data.fl;
1145 buf->dirty.bit.doppler = 1;
1146 hr = DS_OK;
1148 break;
1150 case DSPROPERTY_EAX30BUFFER_ROLLOFFFACTOR:
1151 if(cbPropData >= sizeof(float))
1153 union { const void *v; const float *fl; } data = { pPropData };
1154 TRACE("Rolloff Factor: %f\n", *data.fl);
1156 buf->deferred.eax.flRolloffFactor = *data.fl;
1158 buf->dirty.bit.rolloff = 1;
1159 hr = DS_OK;
1161 break;
1163 case DSPROPERTY_EAX30BUFFER_ROOMROLLOFFFACTOR:
1164 if(cbPropData >= sizeof(float))
1166 union { const void *v; const float *fl; } data = { pPropData };
1167 TRACE("Room Rolloff Factor: %f\n", *data.fl);
1169 buf->deferred.eax.flRoomRolloffFactor = *data.fl;
1171 buf->dirty.bit.room_rolloff = 1;
1172 hr = DS_OK;
1174 break;
1176 case DSPROPERTY_EAX30BUFFER_AIRABSORPTIONFACTOR:
1177 if(cbPropData >= sizeof(float))
1179 union { const void *v; const float *fl; } data = { pPropData };
1180 TRACE("Air Absorb Factor: %f\n", *data.fl);
1182 buf->deferred.eax.flAirAbsorptionFactor = *data.fl;
1184 buf->dirty.bit.air_absorb = 1;
1185 hr = DS_OK;
1187 break;
1189 case DSPROPERTY_EAX30BUFFER_FLAGS:
1190 if(cbPropData >= sizeof(DWORD))
1192 union { const void *v; const DWORD *dw; } data = { pPropData };
1193 TRACE("Flags: 0x%lx\n", *data.dw);
1195 buf->deferred.eax.dwFlags = *data.dw;
1197 buf->dirty.bit.flags = 1;
1198 hr = DS_OK;
1200 break;
1202 default:
1203 hr = E_PROP_ID_UNSUPPORTED;
1204 FIXME("Unhandled propid: 0x%08lx\n", propid);
1205 break;
1208 return hr;
1211 HRESULT EAX3Buffer_Get(DS8Buffer *buf, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned)
1213 HRESULT hr;
1215 if(buf->filter[0] == 0)
1216 return E_PROP_ID_UNSUPPORTED;
1218 #define GET_PROP(src, T) do { \
1219 if(cbPropData >= sizeof(T)) \
1221 union { void *v; T *props; } data = { pPropData }; \
1222 *data.props = src; \
1223 *pcbReturned = sizeof(T); \
1224 hr = DS_OK; \
1226 } while(0)
1227 hr = DSERR_INVALIDPARAM;
1228 switch(propid)
1230 case DSPROPERTY_EAX30BUFFER_NONE:
1231 *pcbReturned = 0;
1232 hr = DS_OK;
1233 break;
1235 case DSPROPERTY_EAX30BUFFER_ALLPARAMETERS:
1236 GET_PROP(buf->current.eax, EAX30BUFFERPROPERTIES);
1237 break;
1238 case DSPROPERTY_EAX30BUFFER_OBSTRUCTIONPARAMETERS:
1239 GET_PROP(EAX3BufferObstruction(&buf->current.eax), EAXOBSTRUCTIONPROPERTIES);
1240 break;
1241 case DSPROPERTY_EAX30BUFFER_OCCLUSIONPARAMETERS:
1242 GET_PROP(EAX3BufferOcclusion(&buf->current.eax), EAXOCCLUSIONPROPERTIES);
1243 break;
1244 case DSPROPERTY_EAX30BUFFER_EXCLUSIONPARAMETERS:
1245 GET_PROP(EAX3BufferExclusion(&buf->current.eax), EAXEXCLUSIONPROPERTIES);
1246 break;
1248 case DSPROPERTY_EAX30BUFFER_DIRECT:
1249 GET_PROP(buf->current.eax.lDirect, long);
1250 break;
1251 case DSPROPERTY_EAX30BUFFER_DIRECTHF:
1252 GET_PROP(buf->current.eax.lDirectHF, long);
1253 break;
1255 case DSPROPERTY_EAX30BUFFER_ROOM:
1256 GET_PROP(buf->current.eax.lRoom, long);
1257 break;
1258 case DSPROPERTY_EAX30BUFFER_ROOMHF:
1259 GET_PROP(buf->current.eax.lRoomHF, long);
1260 break;
1262 case DSPROPERTY_EAX30BUFFER_OBSTRUCTION:
1263 GET_PROP(buf->current.eax.lObstruction, long);
1264 break;
1265 case DSPROPERTY_EAX30BUFFER_OBSTRUCTIONLFRATIO:
1266 GET_PROP(buf->current.eax.flObstructionLFRatio, float);
1267 break;
1269 case DSPROPERTY_EAX30BUFFER_OCCLUSION:
1270 GET_PROP(buf->current.eax.lOcclusion, long);
1271 break;
1272 case DSPROPERTY_EAX30BUFFER_OCCLUSIONLFRATIO:
1273 GET_PROP(buf->current.eax.flOcclusionLFRatio, float);
1274 break;
1275 case DSPROPERTY_EAX30BUFFER_OCCLUSIONROOMRATIO:
1276 GET_PROP(buf->current.eax.flOcclusionRoomRatio, float);
1277 break;
1278 case DSPROPERTY_EAX30BUFFER_OCCLUSIONDIRECTRATIO:
1279 GET_PROP(buf->current.eax.flOcclusionDirectRatio, float);
1280 break;
1282 case DSPROPERTY_EAX30BUFFER_EXCLUSION:
1283 GET_PROP(buf->current.eax.lExclusion, long);
1284 break;
1285 case DSPROPERTY_EAX30BUFFER_EXCLUSIONLFRATIO:
1286 GET_PROP(buf->current.eax.flExclusionLFRatio, float);
1287 break;
1289 case DSPROPERTY_EAX30BUFFER_OUTSIDEVOLUMEHF:
1290 GET_PROP(buf->current.eax.lOutsideVolumeHF, long);
1291 break;
1293 case DSPROPERTY_EAX30BUFFER_DOPPLERFACTOR:
1294 GET_PROP(buf->current.eax.flDopplerFactor, float);
1295 break;
1297 case DSPROPERTY_EAX30BUFFER_ROLLOFFFACTOR:
1298 GET_PROP(buf->current.eax.flRolloffFactor, float);
1299 break;
1300 case DSPROPERTY_EAX30BUFFER_ROOMROLLOFFFACTOR:
1301 GET_PROP(buf->current.eax.flRoomRolloffFactor, float);
1302 break;
1304 case DSPROPERTY_EAX30BUFFER_AIRABSORPTIONFACTOR:
1305 GET_PROP(buf->current.eax.flAirAbsorptionFactor, float);
1306 break;
1308 case DSPROPERTY_EAX30BUFFER_FLAGS:
1309 GET_PROP(buf->current.eax.dwFlags, DWORD);
1310 break;
1312 default:
1313 hr = E_PROP_ID_UNSUPPORTED;
1314 FIXME("Unhandled propid: 0x%08lx\n", propid);
1315 break;
1317 #undef GET_PROP
1319 return hr;
1323 /*******************
1324 * EAX 2 stuff
1325 ******************/
1327 #define EAX2LISTENERFLAGS_MASK (EAX20LISTENERFLAGS_DECAYTIMESCALE | \
1328 EAX20LISTENERFLAGS_REFLECTIONSSCALE | \
1329 EAX20LISTENERFLAGS_REFLECTIONSDELAYSCALE | \
1330 EAX20LISTENERFLAGS_REVERBSCALE | \
1331 EAX20LISTENERFLAGS_REVERBDELAYSCALE | \
1332 EAX20LISTENERFLAGS_DECAYHFLIMIT)
1334 static EAX20LISTENERPROPERTIES EAX3To2(const EAX30LISTENERPROPERTIES *props)
1336 EAX20LISTENERPROPERTIES ret;
1337 ret.lRoom = props->lRoom;
1338 ret.lRoomHF = props->lRoomHF;
1339 ret.flRoomRolloffFactor = props->flRoomRolloffFactor;
1340 ret.flDecayTime = props->flDecayTime;
1341 ret.flDecayHFRatio = props->flDecayHFRatio;
1342 ret.lReflections = props->lReflections;
1343 ret.flReflectionsDelay = props->flReflectionsDelay;
1344 ret.lReverb = props->lReverb;
1345 ret.flReverbDelay = props->flReverbDelay;
1346 ret.dwEnvironment = props->dwEnvironment;
1347 ret.flEnvironmentSize = props->flEnvironmentSize;
1348 ret.flEnvironmentDiffusion = props->flEnvironmentDiffusion;
1349 ret.flAirAbsorptionHF = props->flAirAbsorptionHF;
1350 ret.dwFlags = props->dwFlags & EAX2LISTENERFLAGS_MASK;
1351 return ret;
1354 static EAX20BUFFERPROPERTIES EAXBuffer3To2(const EAX30BUFFERPROPERTIES *props)
1356 EAX20BUFFERPROPERTIES ret;
1357 ret.lDirect = props->lDirect;
1358 ret.lDirectHF = props->lDirectHF;
1359 ret.lRoom = props->lRoom;
1360 ret.lRoomHF = props->lRoomHF;
1361 ret.flRoomRolloffFactor = props->flRoomRolloffFactor;
1362 ret.lObstruction = props->lObstruction;
1363 ret.flObstructionLFRatio = props->flObstructionLFRatio;
1364 ret.lOcclusion = props->lOcclusion;
1365 ret.flOcclusionLFRatio = props->flOcclusionLFRatio;
1366 ret.flOcclusionRoomRatio = props->flOcclusionRoomRatio;
1367 ret.lOutsideVolumeHF = props->lOutsideVolumeHF;
1368 ret.flAirAbsorptionFactor = props->flAirAbsorptionFactor;
1369 ret.dwFlags = props->dwFlags;
1370 return ret;
1374 HRESULT EAX2_Query(DS8Primary *prim, DWORD propid, ULONG *pTypeSupport)
1376 if(prim->effect == 0)
1377 return E_PROP_ID_UNSUPPORTED;
1379 switch(propid)
1381 case DSPROPERTY_EAX20LISTENER_NONE:
1382 case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS:
1383 case DSPROPERTY_EAX20LISTENER_ROOM:
1384 case DSPROPERTY_EAX20LISTENER_ROOMHF:
1385 case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR:
1386 case DSPROPERTY_EAX20LISTENER_DECAYTIME:
1387 case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO:
1388 case DSPROPERTY_EAX20LISTENER_REFLECTIONS:
1389 case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY:
1390 case DSPROPERTY_EAX20LISTENER_REVERB:
1391 case DSPROPERTY_EAX20LISTENER_REVERBDELAY:
1392 case DSPROPERTY_EAX20LISTENER_ENVIRONMENT:
1393 case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE:
1394 case DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION:
1395 case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF:
1396 case DSPROPERTY_EAX20LISTENER_FLAGS:
1397 *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
1398 return DS_OK;
1400 default:
1401 FIXME("Unhandled propid: 0x%08lx\n", propid);
1403 return E_PROP_ID_UNSUPPORTED;
1406 HRESULT EAX2_Set(DS8Primary *prim, DWORD propid, void *pPropData, ULONG cbPropData)
1408 HRESULT hr;
1410 if(prim->effect == 0)
1411 return E_PROP_ID_UNSUPPORTED;
1413 hr = DSERR_INVALIDPARAM;
1414 switch(propid)
1416 case DSPROPERTY_EAX20LISTENER_NONE: /* not setting any property, just applying */
1417 hr = DS_OK;
1418 break;
1420 case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS:
1421 if(cbPropData >= sizeof(EAX20LISTENERPROPERTIES))
1423 union {
1424 const void *v;
1425 const EAX20LISTENERPROPERTIES *props;
1426 } data = { pPropData };
1427 EAX30LISTENERPROPERTIES props3 = REVERB_PRESET_GENERIC;
1428 TRACE("Parameters:\n\tEnvironment: %lu\n\tEnvSize: %f\n\tEnvDiffusion: %f\n\t"
1429 "Room: %ld\n\tRoom HF: %ld\n\tDecay Time: %f\n\tDecay HF Ratio: %f\n\t"
1430 "Reflections: %ld\n\tReflections Delay: %f\n\tReverb: %ld\n\tReverb Delay: %f\n\t"
1431 "Air Absorption: %f\n\tRoom Rolloff: %f\n\tFlags: 0x%02lx\n",
1432 data.props->dwEnvironment, data.props->flEnvironmentSize,
1433 data.props->flEnvironmentDiffusion, data.props->lRoom, data.props->lRoomHF,
1434 data.props->flDecayTime, data.props->flDecayHFRatio, data.props->lReflections,
1435 data.props->flReflectionsDelay, data.props->lReverb, data.props->flReverbDelay,
1436 data.props->flAirAbsorptionHF, data.props->flRoomRolloffFactor, data.props->dwFlags
1439 if(data.props->dwEnvironment < EAX_ENVIRONMENT_UNDEFINED)
1441 props3 = EnvironmentDefaults[data.props->dwEnvironment];
1442 props3.dwEnvironment = data.props->dwEnvironment;
1444 props3.flEnvironmentSize = data.props->flEnvironmentSize;
1445 props3.flEnvironmentDiffusion = data.props->flEnvironmentDiffusion;
1446 props3.lRoom = data.props->lRoom;
1447 props3.lRoomHF = data.props->lRoomHF;
1448 props3.flDecayTime = data.props->flDecayTime;
1449 props3.flDecayHFRatio = data.props->flDecayHFRatio;
1450 props3.lReflections = data.props->lReflections;
1451 props3.flReflectionsDelay = data.props->flReflectionsDelay;
1452 props3.lReverb = data.props->lReverb;
1453 props3.flReverbDelay = data.props->flReverbDelay;
1454 props3.flAirAbsorptionHF = data.props->flAirAbsorptionHF;
1455 props3.flRoomRolloffFactor = data.props->flRoomRolloffFactor;
1456 props3.dwFlags = data.props->dwFlags;
1458 ApplyReverbParams(prim, &props3);
1459 hr = DS_OK;
1461 break;
1463 case DSPROPERTY_EAX20LISTENER_ROOM:
1464 if(cbPropData >= sizeof(long))
1466 union { const void *v; const long *l; } data = { pPropData };
1467 TRACE("Room: %ld\n", *data.l);
1469 prim->deferred.eax.lRoom = *data.l;
1470 alEffectf(prim->effect, AL_EAXREVERB_GAIN,
1471 mB_to_gain(prim->deferred.eax.lRoom));
1472 checkALError();
1474 prim->dirty.bit.effect = 1;
1475 hr = DS_OK;
1477 break;
1478 case DSPROPERTY_EAX20LISTENER_ROOMHF:
1479 if(cbPropData >= sizeof(long))
1481 union { const void *v; const long *l; } data = { pPropData };
1482 TRACE("Room HF: %ld\n", *data.l);
1484 prim->deferred.eax.lRoomHF = *data.l;
1485 alEffectf(prim->effect, AL_EAXREVERB_GAINHF,
1486 mB_to_gain(prim->deferred.eax.lRoomHF));
1487 checkALError();
1489 prim->dirty.bit.effect = 1;
1490 hr = DS_OK;
1492 break;
1494 case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR:
1495 if(cbPropData >= sizeof(float))
1497 union { const void *v; const float *fl; } data = { pPropData };
1498 TRACE("Room Rolloff Factor: %f\n", *data.fl);
1500 prim->deferred.eax.flRoomRolloffFactor = *data.fl;
1501 alEffectf(prim->effect, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR,
1502 prim->deferred.eax.flRoomRolloffFactor);
1503 checkALError();
1505 prim->dirty.bit.effect = 1;
1506 hr = DS_OK;
1508 break;
1510 case DSPROPERTY_EAX20LISTENER_DECAYTIME:
1511 if(cbPropData >= sizeof(float))
1513 union { const void *v; const float *fl; } data = { pPropData };
1514 TRACE("Decay Time: %f\n", *data.fl);
1516 prim->deferred.eax.flDecayTime = *data.fl;
1517 alEffectf(prim->effect, AL_EAXREVERB_DECAY_TIME,
1518 prim->deferred.eax.flDecayTime);
1519 checkALError();
1521 prim->dirty.bit.effect = 1;
1522 hr = DS_OK;
1524 break;
1525 case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO:
1526 if(cbPropData >= sizeof(float))
1528 union { const void *v; const float *fl; } data = { pPropData };
1529 TRACE("Decay HF Ratio: %f\n", *data.fl);
1531 prim->deferred.eax.flDecayHFRatio = *data.fl;
1532 alEffectf(prim->effect, AL_EAXREVERB_DECAY_HFRATIO,
1533 prim->deferred.eax.flDecayHFRatio);
1534 checkALError();
1536 prim->dirty.bit.effect = 1;
1537 hr = DS_OK;
1539 break;
1541 case DSPROPERTY_EAX20LISTENER_REFLECTIONS:
1542 if(cbPropData >= sizeof(long))
1544 union { const void *v; const long *l; } data = { pPropData };
1545 TRACE("Reflections: %ld\n", *data.l);
1547 prim->deferred.eax.lReflections = *data.l;
1548 alEffectf(prim->effect, AL_EAXREVERB_REFLECTIONS_GAIN,
1549 mB_to_gain(prim->deferred.eax.lReflections));
1550 checkALError();
1552 prim->dirty.bit.effect = 1;
1553 hr = DS_OK;
1555 break;
1556 case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY:
1557 if(cbPropData >= sizeof(float))
1559 union { const void *v; const float *fl; } data = { pPropData };
1560 TRACE("Reflections Delay: %f\n", *data.fl);
1562 prim->deferred.eax.flReflectionsDelay = *data.fl;
1563 alEffectf(prim->effect, AL_EAXREVERB_REFLECTIONS_DELAY,
1564 prim->deferred.eax.flReflectionsDelay);
1565 checkALError();
1567 prim->dirty.bit.effect = 1;
1568 hr = DS_OK;
1570 break;
1572 case DSPROPERTY_EAX20LISTENER_REVERB:
1573 if(cbPropData >= sizeof(long))
1575 union { const void *v; const long *l; } data = { pPropData };
1576 TRACE("Reverb: %ld\n", *data.l);
1578 prim->deferred.eax.lReverb = *data.l;
1579 alEffectf(prim->effect, AL_EAXREVERB_LATE_REVERB_GAIN,
1580 mB_to_gain(prim->deferred.eax.lReverb));
1581 checkALError();
1583 prim->dirty.bit.effect = 1;
1584 hr = DS_OK;
1586 break;
1587 case DSPROPERTY_EAX20LISTENER_REVERBDELAY:
1588 if(cbPropData >= sizeof(float))
1590 union { const void *v; const float *fl; } data = { pPropData };
1591 TRACE("Reverb Delay: %f\n", *data.fl);
1593 prim->deferred.eax.flReverbDelay = *data.fl;
1594 alEffectf(prim->effect, AL_EAXREVERB_LATE_REVERB_DELAY,
1595 prim->deferred.eax.flReverbDelay);
1596 checkALError();
1598 prim->dirty.bit.effect = 1;
1599 hr = DS_OK;
1601 break;
1603 case DSPROPERTY_EAX20LISTENER_ENVIRONMENT:
1604 if(cbPropData >= sizeof(DWORD))
1606 union { const void *v; const DWORD *dw; } data = { pPropData };
1607 TRACE("Environment: %lu\n", *data.dw);
1608 if(*data.dw < EAX_ENVIRONMENT_UNDEFINED)
1610 ApplyReverbParams(prim, &EnvironmentDefaults[*data.dw]);
1611 hr = DS_OK;
1614 break;
1616 case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE:
1617 if(cbPropData >= sizeof(float))
1619 union { const void *v; const float *fl; } data = { pPropData };
1620 TRACE("Environment Size: %f\n", *data.fl);
1622 RescaleEnvSize(&prim->deferred.eax, clampF(*data.fl, 1.0f, 100.0f));
1624 ApplyReverbParams(prim, &prim->deferred.eax);
1625 hr = DS_OK;
1627 break;
1628 case DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION:
1629 if(cbPropData >= sizeof(float))
1631 union { const void *v; const float *fl; } data = { pPropData };
1632 TRACE("Environment Diffusion: %f\n", *data.fl);
1634 prim->deferred.eax.flEnvironmentDiffusion = *data.fl;
1635 alEffectf(prim->effect, AL_EAXREVERB_DIFFUSION,
1636 prim->deferred.eax.flEnvironmentDiffusion);
1637 checkALError();
1639 prim->dirty.bit.effect = 1;
1640 hr = DS_OK;
1642 break;
1644 case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF:
1645 if(cbPropData >= sizeof(float))
1647 union { const void *v; const float *fl; } data = { pPropData };
1648 TRACE("Air Absorption HF: %f\n", *data.fl);
1650 prim->deferred.eax.flAirAbsorptionHF = *data.fl;
1651 alEffectf(prim->effect, AL_EAXREVERB_AIR_ABSORPTION_GAINHF,
1652 mB_to_gain(prim->deferred.eax.flAirAbsorptionHF));
1653 checkALError();
1655 prim->dirty.bit.effect = 1;
1656 hr = DS_OK;
1658 break;
1660 case DSPROPERTY_EAX20LISTENER_FLAGS:
1661 if(cbPropData >= sizeof(DWORD))
1663 union { const void *v; const DWORD *dw; } data = { pPropData };
1664 TRACE("Flags: %lu\n", *data.dw);
1666 prim->deferred.eax.dwFlags = *data.dw;
1667 alEffecti(prim->effect, AL_EAXREVERB_DECAY_HFLIMIT,
1668 (prim->deferred.eax.dwFlags&EAX30LISTENERFLAGS_DECAYHFLIMIT) ?
1669 AL_TRUE : AL_FALSE);
1670 checkALError();
1672 prim->dirty.bit.effect = 1;
1673 hr = DS_OK;
1675 break;
1677 default:
1678 hr = E_PROP_ID_UNSUPPORTED;
1679 FIXME("Unhandled propid: 0x%08lx\n", propid);
1680 break;
1683 return hr;
1686 HRESULT EAX2_Get(DS8Primary *prim, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned)
1688 HRESULT hr;
1690 if(prim->effect == 0)
1691 return E_PROP_ID_UNSUPPORTED;
1693 #define GET_PROP(src, T) do { \
1694 if(cbPropData >= sizeof(T)) \
1696 union { void *v; T *props; } data = { pPropData }; \
1697 *data.props = src; \
1698 *pcbReturned = sizeof(T); \
1699 hr = DS_OK; \
1701 } while(0)
1702 hr = DSERR_INVALIDPARAM;
1703 switch(propid)
1705 case DSPROPERTY_EAX20LISTENER_NONE:
1706 *pcbReturned = 0;
1707 hr = DS_OK;
1708 break;
1710 case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS:
1711 GET_PROP(EAX3To2(&prim->deferred.eax), EAX20LISTENERPROPERTIES);
1712 break;
1714 case DSPROPERTY_EAX20LISTENER_ROOM:
1715 GET_PROP(prim->deferred.eax.lRoom, long);
1716 break;
1717 case DSPROPERTY_EAX20LISTENER_ROOMHF:
1718 GET_PROP(prim->deferred.eax.lRoomHF, long);
1719 break;
1721 case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR:
1722 GET_PROP(prim->deferred.eax.flRoomRolloffFactor, float);
1723 break;
1725 case DSPROPERTY_EAX20LISTENER_DECAYTIME:
1726 GET_PROP(prim->deferred.eax.flDecayTime, float);
1727 break;
1728 case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO:
1729 GET_PROP(prim->deferred.eax.flDecayHFRatio, float);
1730 break;
1732 case DSPROPERTY_EAX20LISTENER_REFLECTIONS:
1733 GET_PROP(prim->deferred.eax.lReflections, long);
1734 break;
1735 case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY:
1736 GET_PROP(prim->deferred.eax.flReflectionsDelay, float);
1737 break;
1739 case DSPROPERTY_EAX20LISTENER_REVERB:
1740 GET_PROP(prim->deferred.eax.lReverb, long);
1741 break;
1742 case DSPROPERTY_EAX20LISTENER_REVERBDELAY:
1743 GET_PROP(prim->deferred.eax.flReverbDelay, float);
1744 break;
1746 case DSPROPERTY_EAX20LISTENER_ENVIRONMENT:
1747 GET_PROP(prim->deferred.eax.dwEnvironment, DWORD);
1748 break;
1750 case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE:
1751 GET_PROP(prim->deferred.eax.flEnvironmentSize, float);
1752 break;
1753 case DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION:
1754 GET_PROP(prim->deferred.eax.flEnvironmentDiffusion, float);
1755 break;
1757 case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF:
1758 GET_PROP(prim->deferred.eax.flAirAbsorptionHF, float);
1759 break;
1761 case DSPROPERTY_EAX20LISTENER_FLAGS:
1762 GET_PROP(prim->deferred.eax.dwFlags&EAX2LISTENERFLAGS_MASK, DWORD);
1763 break;
1765 default:
1766 hr = E_PROP_ID_UNSUPPORTED;
1767 FIXME("Unhandled listener propid: 0x%08lx\n", propid);
1768 break;
1770 #undef GET_PROP
1772 return hr;
1776 HRESULT EAX2Buffer_Query(DS8Buffer *buf, DWORD propid, ULONG *pTypeSupport)
1778 if(buf->filter[0] == 0)
1779 return E_PROP_ID_UNSUPPORTED;
1781 switch(propid)
1783 case DSPROPERTY_EAX20BUFFER_NONE:
1784 case DSPROPERTY_EAX20BUFFER_ALLPARAMETERS:
1785 case DSPROPERTY_EAX20BUFFER_DIRECT:
1786 case DSPROPERTY_EAX20BUFFER_DIRECTHF:
1787 case DSPROPERTY_EAX20BUFFER_ROOM:
1788 case DSPROPERTY_EAX20BUFFER_ROOMHF:
1789 case DSPROPERTY_EAX20BUFFER_ROOMROLLOFFFACTOR:
1790 case DSPROPERTY_EAX20BUFFER_OBSTRUCTION:
1791 case DSPROPERTY_EAX20BUFFER_OBSTRUCTIONLFRATIO:
1792 case DSPROPERTY_EAX20BUFFER_OCCLUSION:
1793 case DSPROPERTY_EAX20BUFFER_OCCLUSIONLFRATIO:
1794 case DSPROPERTY_EAX20BUFFER_OCCLUSIONROOMRATIO:
1795 case DSPROPERTY_EAX20BUFFER_OUTSIDEVOLUMEHF:
1796 case DSPROPERTY_EAX20BUFFER_AIRABSORPTIONFACTOR:
1797 case DSPROPERTY_EAX20BUFFER_FLAGS:
1798 *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
1799 return DS_OK;
1801 default:
1802 FIXME("Unhandled propid: 0x%08lx\n", propid);
1804 return E_PROP_ID_UNSUPPORTED;
1807 HRESULT EAX2Buffer_Set(DS8Buffer *buf, DWORD propid, void *pPropData, ULONG cbPropData)
1809 HRESULT hr;
1811 if(buf->filter[0] == 0)
1812 return E_PROP_ID_UNSUPPORTED;
1814 hr = DSERR_INVALIDPARAM;
1815 switch(propid)
1817 case DSPROPERTY_EAX20BUFFER_NONE: /* not setting any property, just applying */
1818 hr = DS_OK;
1819 break;
1821 case DSPROPERTY_EAX20BUFFER_ALLPARAMETERS:
1822 if(cbPropData >= sizeof(EAX20BUFFERPROPERTIES))
1824 union {
1825 const void *v;
1826 const EAX20BUFFERPROPERTIES *props;
1827 } data = { pPropData };
1828 TRACE("Parameters:\n\tDirect: %ld\n\tDirect HF: %ld\n\tRoom: %ld\n\tRoom HF: %ld\n\t"
1829 "Room Rolloff Factor: %f\n\tObstruction: %ld\n\tObstruction LF Ratio: %f\n\t"
1830 "Occlusion: %ld\n\tOcclusion LF Ratio: %f\n\tOcclusion Room Ratio: %f\n\t"
1831 "Outside Volume HF: %ld\n\tAir Absorb Factor: %f\n\tFlags: 0x%02lx\n",
1832 data.props->lDirect, data.props->lDirectHF, data.props->lRoom, data.props->lRoomHF,
1833 data.props->flRoomRolloffFactor, data.props->lObstruction,
1834 data.props->flObstructionLFRatio, data.props->lOcclusion,
1835 data.props->flOcclusionLFRatio, data.props->flOcclusionRoomRatio,
1836 data.props->lOutsideVolumeHF, data.props->flAirAbsorptionFactor,
1837 data.props->dwFlags
1840 buf->deferred.eax.lDirect = data.props->lDirect;
1841 buf->deferred.eax.lDirectHF = data.props->lDirectHF;
1842 buf->deferred.eax.lRoom = data.props->lRoom;
1843 buf->deferred.eax.lRoomHF = data.props->lRoomHF;
1844 buf->deferred.eax.flRoomRolloffFactor = data.props->flRoomRolloffFactor;
1845 buf->deferred.eax.lObstruction = data.props->lObstruction;
1846 buf->deferred.eax.flObstructionLFRatio = data.props->flObstructionLFRatio;
1847 buf->deferred.eax.lOcclusion = data.props->lOcclusion;
1848 buf->deferred.eax.flOcclusionLFRatio = data.props->flOcclusionLFRatio;
1849 buf->deferred.eax.flOcclusionRoomRatio = data.props->flOcclusionRoomRatio;
1850 buf->deferred.eax.lOutsideVolumeHF = data.props->lOutsideVolumeHF;
1851 buf->deferred.eax.flAirAbsorptionFactor = data.props->flAirAbsorptionFactor;
1852 buf->deferred.eax.dwFlags = data.props->dwFlags;
1853 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_DRY_PARAMS|APPLY_WET_PARAMS);
1855 buf->dirty.bit.dry_filter = 1;
1856 buf->dirty.bit.wet_filter = 1;
1857 buf->dirty.bit.room_rolloff = 1;
1858 buf->dirty.bit.cone_outsidevolumehf = 1;
1859 buf->dirty.bit.air_absorb = 1;
1860 buf->dirty.bit.flags = 1;
1861 hr = DS_OK;
1863 break;
1865 case DSPROPERTY_EAX20BUFFER_DIRECT:
1866 if(cbPropData >= sizeof(long))
1868 union { const void *v; const long *l; } data = { pPropData };
1869 TRACE("Direct: %ld\n", *data.l);
1871 buf->deferred.eax.lDirect = *data.l;
1872 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_DRY_PARAMS);
1874 buf->dirty.bit.dry_filter = 1;
1875 hr = DS_OK;
1877 break;
1878 case DSPROPERTY_EAX20BUFFER_DIRECTHF:
1879 if(cbPropData >= sizeof(long))
1881 union { const void *v; const long *l; } data = { pPropData };
1882 TRACE("Direct HF: %ld\n", *data.l);
1884 buf->deferred.eax.lDirectHF = *data.l;
1885 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_DRY_PARAMS);
1887 buf->dirty.bit.dry_filter = 1;
1888 hr = DS_OK;
1890 break;
1892 case DSPROPERTY_EAX20BUFFER_ROOM:
1893 if(cbPropData >= sizeof(long))
1895 union { const void *v; const long *l; } data = { pPropData };
1896 TRACE("Room: %ld\n", *data.l);
1898 buf->deferred.eax.lRoom = *data.l;
1899 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_WET_PARAMS);
1901 buf->dirty.bit.wet_filter = 1;
1902 hr = DS_OK;
1904 break;
1905 case DSPROPERTY_EAX20BUFFER_ROOMHF:
1906 if(cbPropData >= sizeof(long))
1908 union { const void *v; const long *l; } data = { pPropData };
1909 TRACE("Room HF: %ld\n", *data.l);
1911 buf->deferred.eax.lRoomHF = *data.l;
1912 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_WET_PARAMS);
1914 buf->dirty.bit.wet_filter = 1;
1915 hr = DS_OK;
1917 break;
1919 case DSPROPERTY_EAX20BUFFER_ROOMROLLOFFFACTOR:
1920 if(cbPropData >= sizeof(float))
1922 union { const void *v; const float *fl; } data = { pPropData };
1923 TRACE("Room Rolloff Factor: %f\n", *data.fl);
1925 buf->deferred.eax.flRoomRolloffFactor = *data.fl;
1927 buf->dirty.bit.room_rolloff = 1;
1928 hr = DS_OK;
1930 break;
1932 case DSPROPERTY_EAX20BUFFER_OBSTRUCTION:
1933 if(cbPropData >= sizeof(long))
1935 union { const void *v; const long *l; } data = { pPropData };
1936 TRACE("Obstruction: %ld\n", *data.l);
1938 buf->deferred.eax.lObstruction = *data.l;
1939 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_DRY_PARAMS);
1941 buf->dirty.bit.dry_filter = 1;
1942 hr = DS_OK;
1944 break;
1945 case DSPROPERTY_EAX20BUFFER_OBSTRUCTIONLFRATIO:
1946 if(cbPropData >= sizeof(float))
1948 union { const void *v; const float *fl; } data = { pPropData };
1949 TRACE("Obstruction LF Ratio: %f\n", *data.fl);
1951 buf->deferred.eax.flObstructionLFRatio = *data.fl;
1952 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_DRY_PARAMS);
1954 buf->dirty.bit.dry_filter = 1;
1955 hr = DS_OK;
1957 break;
1959 case DSPROPERTY_EAX20BUFFER_OCCLUSION:
1960 if(cbPropData >= sizeof(long))
1962 union { const void *v; const long *l; } data = { pPropData };
1963 TRACE("Occlusion: %ld\n", *data.l);
1965 buf->deferred.eax.lOcclusion = *data.l;
1966 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_DRY_PARAMS|APPLY_WET_PARAMS);
1968 buf->dirty.bit.dry_filter = 1;
1969 buf->dirty.bit.wet_filter = 1;
1970 hr = DS_OK;
1972 break;
1973 case DSPROPERTY_EAX20BUFFER_OCCLUSIONLFRATIO:
1974 if(cbPropData >= sizeof(float))
1976 union { const void *v; const float *fl; } data = { pPropData };
1977 TRACE("Occlusion LF Ratio: %f\n", *data.fl);
1979 buf->deferred.eax.flOcclusionLFRatio = *data.fl;
1980 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_DRY_PARAMS|APPLY_WET_PARAMS);
1982 buf->dirty.bit.dry_filter = 1;
1983 buf->dirty.bit.wet_filter = 1;
1984 hr = DS_OK;
1986 break;
1987 case DSPROPERTY_EAX20BUFFER_OCCLUSIONROOMRATIO:
1988 if(cbPropData >= sizeof(float))
1990 union { const void *v; const float *fl; } data = { pPropData };
1991 TRACE("Occlusion Room Ratio: %f\n", *data.fl);
1993 buf->deferred.eax.flOcclusionRoomRatio = *data.fl;
1994 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_WET_PARAMS);
1996 buf->dirty.bit.wet_filter = 1;
1997 hr = DS_OK;
1999 break;
2001 case DSPROPERTY_EAX20BUFFER_OUTSIDEVOLUMEHF:
2002 if(cbPropData >= sizeof(long))
2004 union { const void *v; const long *l; } data = { pPropData };
2005 TRACE("Outisde Volume HF: %ld\n", *data.l);
2007 buf->deferred.eax.lOutsideVolumeHF = *data.l;
2009 buf->dirty.bit.cone_outsidevolumehf = 1;
2010 hr = DS_OK;
2012 break;
2014 case DSPROPERTY_EAX20BUFFER_AIRABSORPTIONFACTOR:
2015 if(cbPropData >= sizeof(float))
2017 union { const void *v; const float *fl; } data = { pPropData };
2018 TRACE("Air Absorb Factor: %f\n", *data.fl);
2020 buf->deferred.eax.flAirAbsorptionFactor = *data.fl;
2022 buf->dirty.bit.air_absorb = 1;
2023 hr = DS_OK;
2025 break;
2027 case DSPROPERTY_EAX20BUFFER_FLAGS:
2028 if(cbPropData >= sizeof(DWORD))
2030 union { const void *v; const DWORD *dw; } data = { pPropData };
2031 TRACE("Flags: 0x%lx\n", *data.dw);
2033 buf->deferred.eax.dwFlags = *data.dw;
2035 buf->dirty.bit.flags = 1;
2036 hr = DS_OK;
2038 break;
2040 default:
2041 hr = E_PROP_ID_UNSUPPORTED;
2042 FIXME("Unhandled propid: 0x%08lx\n", propid);
2043 break;
2046 return hr;
2049 HRESULT EAX2Buffer_Get(DS8Buffer *buf, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned)
2051 HRESULT hr;
2053 if(buf->filter[0] == 0)
2054 return E_PROP_ID_UNSUPPORTED;
2056 #define GET_PROP(src, T) do { \
2057 if(cbPropData >= sizeof(T)) \
2059 union { void *v; T *props; } data = { pPropData }; \
2060 *data.props = src; \
2061 *pcbReturned = sizeof(T); \
2062 hr = DS_OK; \
2064 } while(0)
2065 hr = DSERR_INVALIDPARAM;
2066 switch(propid)
2068 case DSPROPERTY_EAX20BUFFER_NONE:
2069 *pcbReturned = 0;
2070 hr = DS_OK;
2071 break;
2073 case DSPROPERTY_EAX20BUFFER_ALLPARAMETERS:
2074 GET_PROP(EAXBuffer3To2(&buf->current.eax), EAX20BUFFERPROPERTIES);
2075 break;
2077 case DSPROPERTY_EAX20BUFFER_DIRECT:
2078 GET_PROP(buf->current.eax.lDirect, long);
2079 break;
2080 case DSPROPERTY_EAX20BUFFER_DIRECTHF:
2081 GET_PROP(buf->current.eax.lDirectHF, long);
2082 break;
2084 case DSPROPERTY_EAX20BUFFER_ROOM:
2085 GET_PROP(buf->current.eax.lRoom, long);
2086 break;
2087 case DSPROPERTY_EAX20BUFFER_ROOMHF:
2088 GET_PROP(buf->current.eax.lRoomHF, long);
2089 break;
2091 case DSPROPERTY_EAX20BUFFER_ROOMROLLOFFFACTOR:
2092 GET_PROP(buf->current.eax.flRoomRolloffFactor, float);
2093 break;
2095 case DSPROPERTY_EAX20BUFFER_OBSTRUCTION:
2096 GET_PROP(buf->current.eax.lObstruction, long);
2097 break;
2098 case DSPROPERTY_EAX20BUFFER_OBSTRUCTIONLFRATIO:
2099 GET_PROP(buf->current.eax.flObstructionLFRatio, float);
2100 break;
2102 case DSPROPERTY_EAX20BUFFER_OCCLUSION:
2103 GET_PROP(buf->current.eax.lOcclusion, long);
2104 break;
2105 case DSPROPERTY_EAX20BUFFER_OCCLUSIONLFRATIO:
2106 GET_PROP(buf->current.eax.flOcclusionLFRatio, float);
2107 break;
2108 case DSPROPERTY_EAX20BUFFER_OCCLUSIONROOMRATIO:
2109 GET_PROP(buf->current.eax.flOcclusionRoomRatio, float);
2110 break;
2112 case DSPROPERTY_EAX20BUFFER_OUTSIDEVOLUMEHF:
2113 GET_PROP(buf->current.eax.lOutsideVolumeHF, long);
2114 break;
2116 case DSPROPERTY_EAX20BUFFER_AIRABSORPTIONFACTOR:
2117 GET_PROP(buf->current.eax.flAirAbsorptionFactor, float);
2118 break;
2120 case DSPROPERTY_EAX20BUFFER_FLAGS:
2121 GET_PROP(buf->current.eax.dwFlags, DWORD);
2122 break;
2124 default:
2125 hr = E_PROP_ID_UNSUPPORTED;
2126 FIXME("Unhandled propid: 0x%08lx\n", propid);
2127 break;
2129 #undef GET_PROP
2131 return hr;
2135 /*******************
2136 * EAX 1 stuff
2137 ******************/
2139 HRESULT EAX1_Query(DS8Primary *prim, DWORD propid, ULONG *pTypeSupport)
2141 if(prim->effect == 0)
2142 return E_PROP_ID_UNSUPPORTED;
2144 switch(propid)
2146 case DSPROPERTY_EAX10LISTENER_ALL:
2147 case DSPROPERTY_EAX10LISTENER_ENVIRONMENT:
2148 case DSPROPERTY_EAX10LISTENER_VOLUME:
2149 case DSPROPERTY_EAX10LISTENER_DECAYTIME:
2150 case DSPROPERTY_EAX10LISTENER_DAMPING:
2151 *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
2152 return DS_OK;
2154 default:
2155 FIXME("Unhandled propid: 0x%08lx\n", propid);
2157 return E_PROP_ID_UNSUPPORTED;
2160 HRESULT EAX1_Set(DS8Primary *prim, DWORD propid, void *pPropData, ULONG cbPropData)
2162 static const float eax1_env_volume[EAX_ENVIRONMENT_UNDEFINED] = {
2163 0.5f, 0.25f, 0.417f, 0.653f, 0.208f, 0.5f, 0.403f, 0.5f, 0.5f,
2164 0.361f, 0.5f, 0.153f, 0.361f, 0.444f, 0.25f, 0.111f, 0.111f,
2165 0.194f, 1.0f, 0.097f, 0.208f, 0.652f, 1.0f, 0.875f, 0.139f, 0.486f
2167 static const float eax1_env_dampening[EAX_ENVIRONMENT_UNDEFINED] = {
2168 0.5f, 0.0f, 0.666f, 0.166f, 0.0f, 0.888f, 0.5f, 0.5f, 1.304f,
2169 0.332f, 0.3f, 2.0f, 0.0f, 0.638f, 0.776f, 0.472f, 0.224f, 0.472f,
2170 0.5f, 0.224f, 1.5f, 0.25f, 0.0f, 1.388f, 0.666f, 0.806f
2172 HRESULT hr;
2174 if(prim->effect == 0)
2175 return E_PROP_ID_UNSUPPORTED;
2177 hr = DSERR_INVALIDPARAM;
2178 switch(propid)
2180 case DSPROPERTY_EAX10LISTENER_ALL:
2181 if(cbPropData >= sizeof(EAX10LISTENERPROPERTIES))
2183 union {
2184 const void *v;
2185 const EAX10LISTENERPROPERTIES *props;
2186 } data = { pPropData };
2187 TRACE("Parameters:\n\tEnvironment: %lu\n\tVolume: %f\n\tDecay Time: %f\n\t"
2188 "Damping: %f\n", data.props->dwEnvironment, data.props->fVolume,
2189 data.props->fDecayTime, data.props->fDamping
2192 if(data.props->dwEnvironment < EAX_ENVIRONMENT_UNDEFINED)
2194 /* NOTE: I'm not quite sure how to handle the volume. It's
2195 * important to deal with since it can have a notable impact on
2196 * the output levels, but given the default EAX1 environment
2197 * volumes, they don't align with the gain/room volume for
2198 * EAX2+ environments. Presuming the default volumes are
2199 * correct, it's possible the reverb implementation was
2200 * different and relied on different gains to get the intended
2201 * output levels.
2203 * Rather than just blindly applying the volume, we take the
2204 * difference from the EAX1 environment's default volume and
2205 * apply that as an offset to the EAX2 environment's volume.
2207 EAX30LISTENERPROPERTIES env = EnvironmentDefaults[data.props->dwEnvironment];
2208 long db_vol = clampI(
2209 gain_to_mB(data.props->fVolume / eax1_env_volume[data.props->dwEnvironment]),
2210 -10000, 10000
2212 env.lRoom = clampI(env.lRoom + db_vol, -10000, 0);
2213 env.flDecayTime = data.props->fDecayTime;
2214 prim->deferred.eax1_volume = data.props->fVolume;
2215 prim->deferred.eax1_dampening = data.props->fDamping;
2216 ApplyReverbParams(prim, &env);
2217 hr = DS_OK;
2220 break;
2222 case DSPROPERTY_EAX10LISTENER_ENVIRONMENT:
2223 if(cbPropData >= sizeof(DWORD))
2225 union { const void *v; const DWORD *dw; } data = { pPropData };
2226 TRACE("Environment: %lu\n", *data.dw);
2228 if(*data.dw < EAX_ENVIRONMENT_UNDEFINED)
2230 prim->deferred.eax1_volume = eax1_env_volume[*data.dw];
2231 prim->deferred.eax1_dampening = eax1_env_dampening[*data.dw];
2232 ApplyReverbParams(prim, &EnvironmentDefaults[*data.dw]);
2233 hr = DS_OK;
2236 break;
2238 case DSPROPERTY_EAX10LISTENER_VOLUME:
2239 if(cbPropData >= sizeof(float))
2241 union { const void *v; const float *fl; } data = { pPropData };
2242 long db_vol = clampI(
2243 gain_to_mB(*data.fl / eax1_env_volume[prim->deferred.eax.dwEnvironment]),
2244 -10000, 10000
2246 long room_vol = clampI(
2247 EnvironmentDefaults[prim->deferred.eax.dwEnvironment].lRoom + db_vol,
2248 -10000, 0
2250 TRACE("Volume: %f\n", *data.fl);
2252 prim->deferred.eax.lRoom = room_vol;
2253 prim->deferred.eax1_volume = *data.fl;
2254 alEffectf(prim->effect, AL_EAXREVERB_GAIN, mB_to_gain(room_vol));
2255 checkALError();
2257 prim->dirty.bit.effect = 1;
2258 hr = DS_OK;
2260 break;
2261 case DSPROPERTY_EAX10LISTENER_DECAYTIME:
2262 if(cbPropData >= sizeof(float))
2264 union { const void *v; const float *fl; } data = { pPropData };
2265 TRACE("Decay Time: %f\n", *data.fl);
2267 prim->deferred.eax.flDecayTime = *data.fl;
2268 alEffectf(prim->effect, AL_EAXREVERB_DECAY_TIME,
2269 prim->deferred.eax.flDecayTime);
2270 checkALError();
2272 prim->dirty.bit.effect = 1;
2273 hr = DS_OK;
2275 break;
2276 case DSPROPERTY_EAX10LISTENER_DAMPING:
2277 if(cbPropData >= sizeof(float))
2279 union { const void *v; const float *fl; } data = { pPropData };
2280 TRACE("Damping: %f\n", *data.fl);
2282 prim->deferred.eax1_dampening = *data.fl;
2284 hr = DS_OK;
2286 break;
2288 default:
2289 hr = E_PROP_ID_UNSUPPORTED;
2290 FIXME("Unhandled propid: 0x%08lx\n", propid);
2291 break;
2294 return hr;
2297 HRESULT EAX1_Get(DS8Primary *prim, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned)
2299 HRESULT hr;
2301 if(prim->effect == 0)
2302 return E_PROP_ID_UNSUPPORTED;
2304 hr = DSERR_INVALIDPARAM;
2305 switch(propid)
2307 case DSPROPERTY_EAX10LISTENER_ALL:
2308 if(cbPropData >= sizeof(EAX10LISTENERPROPERTIES))
2310 union {
2311 void *v;
2312 EAX10LISTENERPROPERTIES *props;
2313 } data = { pPropData };
2315 data.props->dwEnvironment = prim->deferred.eax.dwEnvironment;
2316 data.props->fVolume = prim->deferred.eax1_volume;
2317 data.props->fDecayTime = prim->deferred.eax.flDecayTime;
2318 data.props->fDamping = prim->deferred.eax1_dampening;
2320 *pcbReturned = sizeof(EAX10LISTENERPROPERTIES);
2321 hr = DS_OK;
2323 break;
2325 case DSPROPERTY_EAX10LISTENER_ENVIRONMENT:
2326 if(cbPropData >= sizeof(DWORD))
2328 union { void *v; DWORD *dw; } data = { pPropData };
2330 *data.dw = prim->deferred.eax.dwEnvironment;
2332 *pcbReturned = sizeof(DWORD);
2333 hr = DS_OK;
2335 break;
2337 case DSPROPERTY_EAX10LISTENER_VOLUME:
2338 if(cbPropData >= sizeof(float))
2340 union { void *v; float *fl; } data = { pPropData };
2342 *data.fl = prim->deferred.eax1_volume;
2344 *pcbReturned = sizeof(float);
2345 hr = DS_OK;
2347 break;
2349 case DSPROPERTY_EAX10LISTENER_DECAYTIME:
2350 if(cbPropData >= sizeof(float))
2352 union { void *v; float *fl; } data = { pPropData };
2354 *data.fl = prim->deferred.eax.flDecayTime;
2356 *pcbReturned = sizeof(float);
2357 hr = DS_OK;
2359 break;
2361 case DSPROPERTY_EAX10LISTENER_DAMPING:
2362 if(cbPropData >= sizeof(float))
2364 union { void *v; float *fl; } data = { pPropData };
2366 *data.fl = prim->deferred.eax1_dampening;
2368 *pcbReturned = sizeof(float);
2369 hr = DS_OK;
2371 break;
2373 default:
2374 hr = E_PROP_ID_UNSUPPORTED;
2375 FIXME("Unhandled propid: 0x%08lx\n", propid);
2376 break;
2379 return hr;
2383 HRESULT EAX1Buffer_Query(DS8Buffer *buf, DWORD propid, ULONG *pTypeSupport)
2385 if(buf->filter[0] == 0)
2386 return E_PROP_ID_UNSUPPORTED;
2388 switch(propid)
2390 case DSPROPERTY_EAX10BUFFER_ALL:
2391 case DSPROPERTY_EAX10BUFFER_REVERBMIX:
2392 *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
2393 return DS_OK;
2395 default:
2396 FIXME("Unhandled propid: 0x%08lx\n", propid);
2398 return E_PROP_ID_UNSUPPORTED;
2401 HRESULT EAX1Buffer_Set(DS8Buffer *buf, DWORD propid, void *pPropData, ULONG cbPropData)
2403 HRESULT hr;
2405 if(buf->filter[0] == 0)
2406 return E_PROP_ID_UNSUPPORTED;
2408 hr = DSERR_INVALIDPARAM;
2409 switch(propid)
2411 /* NOTE: DSPROPERTY_EAX10BUFFER_ALL is for EAX10BUFFERPROPERTIES, however
2412 * that struct just contains the single ReverbMix float property.
2414 case DSPROPERTY_EAX10BUFFER_ALL:
2415 case DSPROPERTY_EAX10BUFFER_REVERBMIX:
2416 if(cbPropData >= sizeof(float))
2418 union { const void *v; const float *fl; } data = { pPropData };
2419 TRACE("Reverb Mix: %f\n", *data.fl);
2421 buf->deferred.eax.lRoom = gain_to_mB(*data.fl);
2422 buf->deferred.eax1_reverbmix = *data.fl;
2423 ApplyFilterParams(buf, &buf->deferred.eax, APPLY_WET_PARAMS);
2425 buf->dirty.bit.wet_filter = 1;
2426 hr = DS_OK;
2428 break;
2430 default:
2431 hr = E_PROP_ID_UNSUPPORTED;
2432 FIXME("Unhandled propid: 0x%08lx\n", propid);
2433 break;
2436 return hr;
2439 HRESULT EAX1Buffer_Get(DS8Buffer *buf, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned)
2441 HRESULT hr;
2443 if(buf->filter[0] == 0)
2444 return E_PROP_ID_UNSUPPORTED;
2446 hr = DSERR_INVALIDPARAM;
2447 switch(propid)
2449 case DSPROPERTY_EAX10BUFFER_ALL:
2450 case DSPROPERTY_EAX10BUFFER_REVERBMIX:
2451 if(cbPropData >= sizeof(float))
2453 union { void *v; float *fl; } data = { pPropData };
2455 *data.fl = buf->current.eax1_reverbmix;
2456 *pcbReturned = sizeof(float);
2457 hr = DS_OK;
2459 break;
2461 default:
2462 hr = E_PROP_ID_UNSUPPORTED;
2463 FIXME("Unhandled propid: 0x%08lx\n", propid);
2464 break;
2467 return hr;