Add missing file
[dsound-openal.git] / reverb.c
blob9b990777a1424e32ecdc0b9e027aa9021d69dd83
1 /* EAX reverb 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(ALuint effect, const EAXREVERBPROPERTIES *props)
31 /* FIXME: Need to validate property values... Ignore? Clamp? Error? */
32 alEffectf(effect, AL_EAXREVERB_DENSITY,
33 clampF(powf(props->flEnvironmentSize, 3.0f) / 16.0f, 0.0f, 1.0f)
35 alEffectf(effect, AL_EAXREVERB_DIFFUSION, props->flEnvironmentDiffusion);
37 alEffectf(effect, AL_EAXREVERB_GAIN, mB_to_gain((float)props->lRoom));
38 alEffectf(effect, AL_EAXREVERB_GAINHF, mB_to_gain((float)props->lRoomHF));
39 alEffectf(effect, AL_EAXREVERB_GAINLF, mB_to_gain((float)props->lRoomLF));
41 alEffectf(effect, AL_EAXREVERB_DECAY_TIME, props->flDecayTime);
42 alEffectf(effect, AL_EAXREVERB_DECAY_HFRATIO, props->flDecayHFRatio);
43 alEffectf(effect, AL_EAXREVERB_DECAY_LFRATIO, props->flDecayLFRatio);
45 /* NOTE: Imprecision can cause some converted volume levels to land outside
46 * EFX's gain limits (e.g. EAX's +1000mB volume limit gets converted to
47 * 3.162something, while EFX defines the limit as 3.16; close enough for
48 * practical uses, but still technically an error).
50 alEffectf(effect, AL_EAXREVERB_REFLECTIONS_GAIN,
51 clampF(mB_to_gain((float)props->lReflections), AL_EAXREVERB_MIN_REFLECTIONS_GAIN,
52 AL_EAXREVERB_MAX_REFLECTIONS_GAIN)
54 alEffectf(effect, AL_EAXREVERB_REFLECTIONS_DELAY, props->flReflectionsDelay);
55 alEffectfv(effect, AL_EAXREVERB_REFLECTIONS_PAN, &props->vReflectionsPan.x);
57 alEffectf(effect, AL_EAXREVERB_LATE_REVERB_GAIN,
58 clampF(mB_to_gain((float)props->lReverb), AL_EAXREVERB_MIN_LATE_REVERB_GAIN,
59 AL_EAXREVERB_MAX_LATE_REVERB_GAIN)
61 alEffectf(effect, AL_EAXREVERB_LATE_REVERB_DELAY, props->flReverbDelay);
62 alEffectfv(effect, AL_EAXREVERB_LATE_REVERB_PAN, &props->vReverbPan.x);
64 alEffectf(effect, AL_EAXREVERB_ECHO_TIME, props->flEchoTime);
65 alEffectf(effect, AL_EAXREVERB_ECHO_DEPTH, props->flEchoDepth);
67 alEffectf(effect, AL_EAXREVERB_MODULATION_TIME, props->flModulationTime);
68 alEffectf(effect, AL_EAXREVERB_MODULATION_DEPTH, props->flModulationDepth);
70 alEffectf(effect, AL_EAXREVERB_AIR_ABSORPTION_GAINHF,
71 clampF(mB_to_gain(props->flAirAbsorptionHF), AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF,
72 AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF)
75 alEffectf(effect, AL_EAXREVERB_HFREFERENCE, props->flHFReference);
76 alEffectf(effect, AL_EAXREVERB_LFREFERENCE, props->flLFReference);
78 alEffectf(effect, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, props->flRoomRolloffFactor);
80 alEffecti(effect, AL_EAXREVERB_DECAY_HFLIMIT,
81 (props->dwFlags&EAX30LISTENERFLAGS_DECAYHFLIMIT) ?
82 AL_TRUE : AL_FALSE);
84 checkALError();
87 static void RescaleEnvSize(EAXREVERBPROPERTIES *props, float newsize)
89 float scale = newsize / props->flEnvironmentSize;
91 props->flEnvironmentSize = newsize;
93 if((props->dwFlags&EAX30LISTENERFLAGS_DECAYTIMESCALE))
95 props->flDecayTime *= scale;
96 props->flDecayTime = clampF(props->flDecayTime, 0.1f, 20.0f);
98 if((props->dwFlags&EAX30LISTENERFLAGS_REFLECTIONSSCALE))
100 props->lReflections -= gain_to_mB(scale);
101 props->lReflections = clampI(props->lReflections, -10000, 1000);
103 if((props->dwFlags&EAX30LISTENERFLAGS_REFLECTIONSDELAYSCALE))
105 props->flReflectionsDelay *= scale;
106 props->flReflectionsDelay = clampF(props->flReflectionsDelay, 0.0f, 0.3f);
108 if((props->dwFlags&EAX30LISTENERFLAGS_REVERBSCALE))
110 LONG diff = gain_to_mB(scale);
111 /* This is scaled by an extra 1/3rd if decay time isn't also scaled, to
112 * account for the (lack of) change on the send's initial decay.
114 if(!(props->dwFlags&EAX30LISTENERFLAGS_DECAYTIMESCALE))
115 diff = diff * 3 / 2;
116 props->lReverb -= diff;
117 props->lReverb = clampI(props->lReverb, -10000, 2000);
119 if((props->dwFlags&EAX30LISTENERFLAGS_REVERBDELAYSCALE))
121 props->flReverbDelay *= scale;
122 props->flReverbDelay = clampF(props->flReverbDelay, 0.0f, 0.1f);
124 if((props->dwFlags&EAX30LISTENERFLAGS_ECHOTIMESCALE))
126 props->flEchoTime *= scale;
127 props->flEchoTime = clampF(props->flEchoTime, 0.075f, 0.25f);
129 if((props->dwFlags&EAX30LISTENERFLAGS_MODTIMESCALE))
131 props->flModulationTime *= scale;
132 props->flModulationTime = clampF(props->flModulationTime, 0.04f, 4.0f);
137 HRESULT EAXReverb_Set(DSPrimary *prim, LONG idx, DWORD propid, void *pPropData, ULONG cbPropData)
139 switch(propid)
141 case EAXREVERB_NONE: /* not setting any property, just applying */
142 return DS_OK;
144 case EAXREVERB_ALLPARAMETERS:
145 if(cbPropData >= sizeof(EAXREVERBPROPERTIES))
147 union {
148 const void *v;
149 const EAXREVERBPROPERTIES *props;
150 } data = { pPropData };
151 TRACE("Parameters:\n\tEnvironment: %lu\n\tEnvSize: %f\n\tEnvDiffusion: %f\n\t"
152 "Room: %ld\n\tRoom HF: %ld\n\tRoom LF: %ld\n\tDecay Time: %f\n\t"
153 "Decay HF Ratio: %f\n\tDecay LF Ratio: %f\n\tReflections: %ld\n\t"
154 "Reflections Delay: %f\n\tReflections Pan: { %f, %f, %f }\n\tReverb: %ld\n\t"
155 "Reverb Delay: %f\n\tReverb Pan: { %f, %f, %f }\n\tEcho Time: %f\n\t"
156 "Echo Depth: %f\n\tMod Time: %f\n\tMod Depth: %f\n\tAir Absorption: %f\n\t"
157 "HF Reference: %f\n\tLF Reference: %f\n\tRoom Rolloff: %f\n\tFlags: 0x%02lx\n",
158 data.props->dwEnvironment, data.props->flEnvironmentSize,
159 data.props->flEnvironmentDiffusion, data.props->lRoom, data.props->lRoomHF,
160 data.props->lRoomLF, data.props->flDecayTime, data.props->flDecayHFRatio,
161 data.props->flDecayLFRatio, data.props->lReflections,
162 data.props->flReflectionsDelay, data.props->vReflectionsPan.x,
163 data.props->vReflectionsPan.y, data.props->vReflectionsPan.z, data.props->lReverb,
164 data.props->flReverbDelay, data.props->vReverbPan.x, data.props->vReverbPan.y,
165 data.props->vReverbPan.z, data.props->flEchoTime, data.props->flEchoDepth,
166 data.props->flModulationTime, data.props->flModulationDepth,
167 data.props->flAirAbsorptionHF, data.props->flHFReference,
168 data.props->flLFReference, data.props->flRoomRolloffFactor, data.props->dwFlags
171 ApplyReverbParams(prim->effect[idx], data.props);
172 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
173 return DS_OK;
175 return DSERR_INVALIDPARAM;
177 case EAXREVERB_ENVIRONMENT:
178 if(cbPropData >= sizeof(DWORD))
180 union { const void *v; const DWORD *dw; } data = { pPropData };
181 TRACE("Environment: %lu\n", *data.dw);
182 if(*data.dw < EAX_ENVIRONMENT_UNDEFINED)
184 prim->deferred.fxslot[idx].fx.reverb = EnvironmentDefaults[*data.dw];
185 ApplyReverbParams(prim->effect[idx], &EnvironmentDefaults[*data.dw]);
186 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
187 return DS_OK;
190 return DSERR_INVALIDPARAM;
192 case EAXREVERB_ENVIRONMENTSIZE:
193 if(cbPropData >= sizeof(float))
195 union { const void *v; const float *fl; } data = { pPropData };
196 TRACE("Environment Size: %f\n", *data.fl);
198 RescaleEnvSize(&prim->deferred.fxslot[idx].fx.reverb, clampF(*data.fl, 1.0f, 100.0f));
199 ApplyReverbParams(prim->effect[idx], &prim->deferred.fxslot[idx].fx.reverb);
201 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
202 return DS_OK;
204 return DSERR_INVALIDPARAM;
205 case EAXREVERB_ENVIRONMENTDIFFUSION:
206 if(cbPropData >= sizeof(float))
208 union { const void *v; const float *fl; } data = { pPropData };
209 TRACE("Environment Diffusion: %f\n", *data.fl);
211 prim->deferred.fxslot[idx].fx.reverb.flEnvironmentDiffusion = *data.fl;
212 alEffectf(prim->effect[idx], AL_EAXREVERB_DIFFUSION,
213 prim->deferred.fxslot[idx].fx.reverb.flEnvironmentDiffusion);
214 checkALError();
216 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
217 return DS_OK;
219 return DSERR_INVALIDPARAM;
221 case EAXREVERB_ROOM:
222 if(cbPropData >= sizeof(long))
224 union { const void *v; const long *l; } data = { pPropData };
225 TRACE("Room: %ld\n", *data.l);
227 prim->deferred.fxslot[idx].fx.reverb.lRoom = *data.l;
228 alEffectf(prim->effect[idx], AL_EAXREVERB_GAIN,
229 mB_to_gain((float)prim->deferred.fxslot[idx].fx.reverb.lRoom));
230 checkALError();
232 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
233 return DS_OK;
235 return DSERR_INVALIDPARAM;
236 case EAXREVERB_ROOMHF:
237 if(cbPropData >= sizeof(long))
239 union { const void *v; const long *l; } data = { pPropData };
240 TRACE("Room HF: %ld\n", *data.l);
242 prim->deferred.fxslot[idx].fx.reverb.lRoomHF = *data.l;
243 alEffectf(prim->effect[idx], AL_EAXREVERB_GAINHF,
244 mB_to_gain((float)prim->deferred.fxslot[idx].fx.reverb.lRoomHF));
245 checkALError();
247 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
248 return DS_OK;
250 return DSERR_INVALIDPARAM;
251 case EAXREVERB_ROOMLF:
252 if(cbPropData >= sizeof(long))
254 union { const void *v; const long *l; } data = { pPropData };
255 TRACE("Room LF: %ld\n", *data.l);
257 prim->deferred.fxslot[idx].fx.reverb.lRoomLF = *data.l;
258 alEffectf(prim->effect[idx], AL_EAXREVERB_GAINLF,
259 mB_to_gain((float)prim->deferred.fxslot[idx].fx.reverb.lRoomLF));
260 checkALError();
262 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
263 return DS_OK;
265 return DSERR_INVALIDPARAM;
267 case EAXREVERB_DECAYTIME:
268 if(cbPropData >= sizeof(float))
270 union { const void *v; const float *fl; } data = { pPropData };
271 TRACE("Decay Time: %f\n", *data.fl);
273 prim->deferred.fxslot[idx].fx.reverb.flDecayTime = *data.fl;
274 alEffectf(prim->effect[idx], AL_EAXREVERB_DECAY_TIME,
275 prim->deferred.fxslot[idx].fx.reverb.flDecayTime);
276 checkALError();
278 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
279 return DS_OK;
281 return DSERR_INVALIDPARAM;
282 case EAXREVERB_DECAYHFRATIO:
283 if(cbPropData >= sizeof(float))
285 union { const void *v; const float *fl; } data = { pPropData };
286 TRACE("Decay HF Ratio: %f\n", *data.fl);
288 prim->deferred.fxslot[idx].fx.reverb.flDecayHFRatio = *data.fl;
289 alEffectf(prim->effect[idx], AL_EAXREVERB_DECAY_HFRATIO,
290 prim->deferred.fxslot[idx].fx.reverb.flDecayHFRatio);
291 checkALError();
293 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
294 return DS_OK;
296 return DSERR_INVALIDPARAM;
297 case EAXREVERB_DECAYLFRATIO:
298 if(cbPropData >= sizeof(float))
300 union { const void *v; const float *fl; } data = { pPropData };
301 TRACE("Decay LF Ratio: %f\n", *data.fl);
303 prim->deferred.fxslot[idx].fx.reverb.flDecayLFRatio = *data.fl;
304 alEffectf(prim->effect[idx], AL_EAXREVERB_DECAY_LFRATIO,
305 prim->deferred.fxslot[idx].fx.reverb.flDecayLFRatio);
306 checkALError();
308 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
309 return DS_OK;
311 return DSERR_INVALIDPARAM;
313 case EAXREVERB_REFLECTIONS:
314 if(cbPropData >= sizeof(long))
316 union { const void *v; const long *l; } data = { pPropData };
317 TRACE("Reflections: %ld\n", *data.l);
319 prim->deferred.fxslot[idx].fx.reverb.lReflections = *data.l;
320 alEffectf(prim->effect[idx], AL_EAXREVERB_REFLECTIONS_GAIN,
321 mB_to_gain((float)prim->deferred.fxslot[idx].fx.reverb.lReflections));
322 checkALError();
324 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
325 return DS_OK;
327 return DSERR_INVALIDPARAM;
328 case EAXREVERB_REFLECTIONSDELAY:
329 if(cbPropData >= sizeof(float))
331 union { const void *v; const float *fl; } data = { pPropData };
332 TRACE("Reflections Delay: %f\n", *data.fl);
334 prim->deferred.fxslot[idx].fx.reverb.flReflectionsDelay = *data.fl;
335 alEffectf(prim->effect[idx], AL_EAXREVERB_REFLECTIONS_DELAY,
336 prim->deferred.fxslot[idx].fx.reverb.flReflectionsDelay);
337 checkALError();
339 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
340 return DS_OK;
342 return DSERR_INVALIDPARAM;
343 case EAXREVERB_REFLECTIONSPAN:
344 if(cbPropData >= sizeof(EAXVECTOR))
346 union { const void *v; const EAXVECTOR *vec; } data = { pPropData };
347 TRACE("Reflections Pan: { %f, %f, %f }\n", data.vec->x, data.vec->y, data.vec->z);
349 prim->deferred.fxslot[idx].fx.reverb.vReflectionsPan = *data.vec;
350 alEffectfv(prim->effect[idx], AL_EAXREVERB_REFLECTIONS_PAN,
351 &prim->deferred.fxslot[idx].fx.reverb.vReflectionsPan.x);
352 checkALError();
354 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
355 return DS_OK;
357 return DSERR_INVALIDPARAM;
359 case EAXREVERB_REVERB:
360 if(cbPropData >= sizeof(long))
362 union { const void *v; const long *l; } data = { pPropData };
363 TRACE("Reverb: %ld\n", *data.l);
365 prim->deferred.fxslot[idx].fx.reverb.lReverb = *data.l;
366 alEffectf(prim->effect[idx], AL_EAXREVERB_LATE_REVERB_GAIN,
367 mB_to_gain((float)prim->deferred.fxslot[idx].fx.reverb.lReverb));
368 checkALError();
370 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
371 return DS_OK;
373 return DSERR_INVALIDPARAM;
374 case EAXREVERB_REVERBDELAY:
375 if(cbPropData >= sizeof(float))
377 union { const void *v; const float *fl; } data = { pPropData };
378 TRACE("Reverb Delay: %f\n", *data.fl);
380 prim->deferred.fxslot[idx].fx.reverb.flReverbDelay = *data.fl;
381 alEffectf(prim->effect[idx], AL_EAXREVERB_LATE_REVERB_DELAY,
382 prim->deferred.fxslot[idx].fx.reverb.flReverbDelay);
383 checkALError();
385 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
386 return DS_OK;
388 return DSERR_INVALIDPARAM;
389 case EAXREVERB_REVERBPAN:
390 if(cbPropData >= sizeof(EAXVECTOR))
392 union { const void *v; const EAXVECTOR *vec; } data = { pPropData };
393 TRACE("Reverb Pan: { %f, %f, %f }\n", data.vec->x, data.vec->y, data.vec->z);
395 prim->deferred.fxslot[idx].fx.reverb.vReverbPan = *data.vec;
396 alEffectfv(prim->effect[idx], AL_EAXREVERB_LATE_REVERB_PAN,
397 &prim->deferred.fxslot[idx].fx.reverb.vReverbPan.x);
398 checkALError();
400 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
401 return DS_OK;
403 return DSERR_INVALIDPARAM;
405 case EAXREVERB_ECHOTIME:
406 if(cbPropData >= sizeof(float))
408 union { const void *v; const float *fl; } data = { pPropData };
409 TRACE("Echo Time: %f\n", *data.fl);
411 prim->deferred.fxslot[idx].fx.reverb.flEchoTime = *data.fl;
412 alEffectf(prim->effect[idx], AL_EAXREVERB_ECHO_TIME,
413 prim->deferred.fxslot[idx].fx.reverb.flEchoTime);
414 checkALError();
416 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
417 return DS_OK;
419 return DSERR_INVALIDPARAM;
420 case EAXREVERB_ECHODEPTH:
421 if(cbPropData >= sizeof(float))
423 union { const void *v; const float *fl; } data = { pPropData };
424 TRACE("Echo Depth: %f\n", *data.fl);
426 prim->deferred.fxslot[idx].fx.reverb.flEchoDepth = *data.fl;
427 alEffectf(prim->effect[idx], AL_EAXREVERB_ECHO_DEPTH,
428 prim->deferred.fxslot[idx].fx.reverb.flEchoDepth);
429 checkALError();
431 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
432 return DS_OK;
434 return DSERR_INVALIDPARAM;
436 case EAXREVERB_MODULATIONTIME:
437 if(cbPropData >= sizeof(float))
439 union { const void *v; const float *fl; } data = { pPropData };
440 TRACE("Modulation Time: %f\n", *data.fl);
442 prim->deferred.fxslot[idx].fx.reverb.flModulationTime = *data.fl;
443 alEffectf(prim->effect[idx], AL_EAXREVERB_MODULATION_TIME,
444 prim->deferred.fxslot[idx].fx.reverb.flModulationTime);
445 checkALError();
447 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
448 return DS_OK;
450 return DSERR_INVALIDPARAM;
451 case EAXREVERB_MODULATIONDEPTH:
452 if(cbPropData >= sizeof(float))
454 union { const void *v; const float *fl; } data = { pPropData };
455 TRACE("Modulation Depth: %f\n", *data.fl);
457 prim->deferred.fxslot[idx].fx.reverb.flModulationDepth = *data.fl;
458 alEffectf(prim->effect[idx], AL_EAXREVERB_MODULATION_DEPTH,
459 prim->deferred.fxslot[idx].fx.reverb.flModulationDepth);
460 checkALError();
462 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
463 return DS_OK;
465 return DSERR_INVALIDPARAM;
467 case EAXREVERB_AIRABSORPTIONHF:
468 if(cbPropData >= sizeof(float))
470 union { const void *v; const float *fl; } data = { pPropData };
471 TRACE("Air Absorption HF: %f\n", *data.fl);
473 prim->deferred.fxslot[idx].fx.reverb.flAirAbsorptionHF = *data.fl;
474 alEffectf(prim->effect[idx], AL_EAXREVERB_AIR_ABSORPTION_GAINHF,
475 mB_to_gain(prim->deferred.fxslot[idx].fx.reverb.flAirAbsorptionHF));
476 checkALError();
478 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
479 return DS_OK;
481 return DSERR_INVALIDPARAM;
483 case EAXREVERB_HFREFERENCE:
484 if(cbPropData >= sizeof(float))
486 union { const void *v; const float *fl; } data = { pPropData };
487 TRACE("HF Reference: %f\n", *data.fl);
489 prim->deferred.fxslot[idx].fx.reverb.flHFReference = *data.fl;
490 alEffectf(prim->effect[idx], AL_EAXREVERB_HFREFERENCE,
491 prim->deferred.fxslot[idx].fx.reverb.flHFReference);
492 checkALError();
494 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
495 return DS_OK;
497 return DSERR_INVALIDPARAM;
498 case EAXREVERB_LFREFERENCE:
499 if(cbPropData >= sizeof(float))
501 union { const void *v; const float *fl; } data = { pPropData };
502 TRACE("LF Reference: %f\n", *data.fl);
504 prim->deferred.fxslot[idx].fx.reverb.flLFReference = *data.fl;
505 alEffectf(prim->effect[idx], AL_EAXREVERB_LFREFERENCE,
506 prim->deferred.fxslot[idx].fx.reverb.flLFReference);
507 checkALError();
509 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
510 return DS_OK;
512 return DSERR_INVALIDPARAM;
514 case EAXREVERB_ROOMROLLOFFFACTOR:
515 if(cbPropData >= sizeof(float))
517 union { const void *v; const float *fl; } data = { pPropData };
518 TRACE("Room Rolloff Factor: %f\n", *data.fl);
520 prim->deferred.fxslot[idx].fx.reverb.flRoomRolloffFactor = *data.fl;
521 alEffectf(prim->effect[idx], AL_EAXREVERB_ROOM_ROLLOFF_FACTOR,
522 prim->deferred.fxslot[idx].fx.reverb.flRoomRolloffFactor);
523 checkALError();
525 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
526 return DS_OK;
528 return DSERR_INVALIDPARAM;
530 case EAXREVERB_FLAGS:
531 if(cbPropData >= sizeof(DWORD))
533 union { const void *v; const DWORD *dw; } data = { pPropData };
534 TRACE("Flags: %lu\n", *data.dw);
536 prim->deferred.fxslot[idx].fx.reverb.dwFlags = *data.dw;
537 alEffecti(prim->effect[idx], AL_EAXREVERB_DECAY_HFLIMIT,
538 (prim->deferred.fxslot[idx].fx.reverb.dwFlags&EAX30LISTENERFLAGS_DECAYHFLIMIT) ?
539 AL_TRUE : AL_FALSE
541 checkALError();
543 FXSLOT_SET_DIRTY(prim->dirty.bit, idx, FXSLOT_EFFECT_BIT);
544 return DS_OK;
546 return DSERR_INVALIDPARAM;
548 FIXME("Unhandled propid: 0x%08lx\n", propid);
549 return E_PROP_ID_UNSUPPORTED;
552 #define GET_PROP(src, T) do { \
553 if(cbPropData >= sizeof(T)) \
555 union { void *v; T *props; } data = { pPropData }; \
556 *data.props = src; \
557 *pcbReturned = sizeof(T); \
558 return DS_OK; \
560 return DSERR_INVALIDPARAM; \
561 } while(0)
563 HRESULT EAXReverb_Get(DSPrimary *prim, DWORD idx, DWORD propid, void *pPropData, ULONG cbPropData, ULONG *pcbReturned)
565 switch(propid)
567 case EAXREVERB_NONE:
568 *pcbReturned = 0;
569 return DS_OK;
571 case EAXREVERB_ALLPARAMETERS:
572 GET_PROP(prim->current.fxslot[idx].fx.reverb, EAXREVERBPROPERTIES);
574 case EAXREVERB_ENVIRONMENT:
575 GET_PROP(prim->current.fxslot[idx].fx.reverb.dwEnvironment, DWORD);
577 case EAXREVERB_ENVIRONMENTSIZE:
578 GET_PROP(prim->current.fxslot[idx].fx.reverb.flEnvironmentSize, float);
579 case EAXREVERB_ENVIRONMENTDIFFUSION:
580 GET_PROP(prim->current.fxslot[idx].fx.reverb.flEnvironmentDiffusion, float);
582 case EAXREVERB_ROOM:
583 GET_PROP(prim->current.fxslot[idx].fx.reverb.lRoom, long);
584 case EAXREVERB_ROOMHF:
585 GET_PROP(prim->current.fxslot[idx].fx.reverb.lRoomHF, long);
586 case EAXREVERB_ROOMLF:
587 GET_PROP(prim->current.fxslot[idx].fx.reverb.lRoomLF, long);
589 case EAXREVERB_DECAYTIME:
590 GET_PROP(prim->current.fxslot[idx].fx.reverb.flDecayTime, float);
591 case EAXREVERB_DECAYHFRATIO:
592 GET_PROP(prim->current.fxslot[idx].fx.reverb.flDecayHFRatio, float);
593 case EAXREVERB_DECAYLFRATIO:
594 GET_PROP(prim->current.fxslot[idx].fx.reverb.flDecayLFRatio, float);
596 case EAXREVERB_REFLECTIONS:
597 GET_PROP(prim->current.fxslot[idx].fx.reverb.lReflections, long);
598 case EAXREVERB_REFLECTIONSDELAY:
599 GET_PROP(prim->current.fxslot[idx].fx.reverb.flReflectionsDelay, float);
600 case EAXREVERB_REFLECTIONSPAN:
601 GET_PROP(prim->current.fxslot[idx].fx.reverb.vReflectionsPan, EAXVECTOR);
603 case EAXREVERB_REVERB:
604 GET_PROP(prim->current.fxslot[idx].fx.reverb.lReverb, long);
605 case EAXREVERB_REVERBDELAY:
606 GET_PROP(prim->current.fxslot[idx].fx.reverb.flReverbDelay, float);
607 case EAXREVERB_REVERBPAN:
608 GET_PROP(prim->current.fxslot[idx].fx.reverb.vReverbPan, EAXVECTOR);
610 case EAXREVERB_ECHOTIME:
611 GET_PROP(prim->current.fxslot[idx].fx.reverb.flEchoTime, float);
612 case EAXREVERB_ECHODEPTH:
613 GET_PROP(prim->current.fxslot[idx].fx.reverb.flEchoDepth, float);
615 case EAXREVERB_MODULATIONTIME:
616 GET_PROP(prim->current.fxslot[idx].fx.reverb.flModulationTime, float);
617 case EAXREVERB_MODULATIONDEPTH:
618 GET_PROP(prim->current.fxslot[idx].fx.reverb.flModulationDepth, float);
620 case EAXREVERB_AIRABSORPTIONHF:
621 GET_PROP(prim->current.fxslot[idx].fx.reverb.flAirAbsorptionHF, float);
623 case EAXREVERB_HFREFERENCE:
624 GET_PROP(prim->current.fxslot[idx].fx.reverb.flHFReference, float);
625 case EAXREVERB_LFREFERENCE:
626 GET_PROP(prim->current.fxslot[idx].fx.reverb.flLFReference, float);
628 case EAXREVERB_ROOMROLLOFFFACTOR:
629 GET_PROP(prim->current.fxslot[idx].fx.reverb.flRoomRolloffFactor, float);
631 case EAXREVERB_FLAGS:
632 GET_PROP(prim->current.fxslot[idx].fx.reverb.dwFlags, DWORD);
634 FIXME("Unhandled propid: 0x%08lx\n", propid);
635 return E_PROP_ID_UNSUPPORTED;