]> icculus.org git repositories - taylor/freespace2.git/blob - src/sound/oal_efx.cpp
cleanup snd_init() and related:
[taylor/freespace2.git] / src / sound / oal_efx.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 #include "pstypes.h"
10 #include "oal.h"
11 #include "sound.h"
12 #include "oal_efx.h"
13
14 #include "alext.h"
15 #include "efx-presets.h"
16
17
18 // effects
19 LPALGENEFFECTS alGenEffects;
20 LPALDELETEEFFECTS alDeleteEffects;
21 LPALEFFECTI alEffecti;
22 LPALEFFECTF alEffectf;
23 LPALEFFECTFV alEffectfv;
24 LPALGETEFFECTF alGetEffectf;
25
26 // aux effect slots
27 LPALGENAUXILIARYEFFECTSLOTS alGenAuxiliaryEffectSlots;
28 LPALDELETEAUXILIARYEFFECTSLOTS alDeleteAuxiliaryEffectSlots;
29 LPALISAUXILIARYEFFECTSLOT alIsAuxiliaryEffectSlot;
30 LPALAUXILIARYEFFECTSLOTI alAuxiliaryEffectSloti;
31 LPALAUXILIARYEFFECTSLOTIV alAuxiliaryEffectSlotiv;
32 LPALAUXILIARYEFFECTSLOTF alAuxiliaryEffectSlotf;
33 LPALAUXILIARYEFFECTSLOTFV alAuxiliaryEffectSlotfv;
34
35 static uint EFX_active_environment = SND_ENV_GENERIC;
36 static EFXEAXREVERBPROPERTIES EFX_env_properties = EFX_REVERB_PRESET_GENERIC;
37 static int EFX_enabled = 0;
38
39 static ALuint AL_EFX_aux_id = 0;
40 static ALuint AL_EFX_effect_id = 0;
41
42 static int OAL_efx_inited = 0;
43
44 static const EFXEAXREVERBPROPERTIES EFX_ENV_Generic = EFX_REVERB_PRESET_GENERIC;
45 static const EFXEAXREVERBPROPERTIES EFX_ENV_PaddedCell = EFX_REVERB_PRESET_PADDEDCELL;
46 static const EFXEAXREVERBPROPERTIES EFX_ENV_Room = EFX_REVERB_PRESET_ROOM;
47 static const EFXEAXREVERBPROPERTIES EFX_ENV_BathRoom = EFX_REVERB_PRESET_BATHROOM;
48 static const EFXEAXREVERBPROPERTIES EFX_ENV_LivingRoom = EFX_REVERB_PRESET_LIVINGROOM;
49 static const EFXEAXREVERBPROPERTIES EFX_ENV_StoneRoom = EFX_REVERB_PRESET_STONEROOM;
50 static const EFXEAXREVERBPROPERTIES EFX_ENV_Auditorium = EFX_REVERB_PRESET_AUDITORIUM;
51 static const EFXEAXREVERBPROPERTIES EFX_ENV_ConcertHall = EFX_REVERB_PRESET_CONCERTHALL;
52 static const EFXEAXREVERBPROPERTIES EFX_ENV_Cave = EFX_REVERB_PRESET_CAVE;
53 static const EFXEAXREVERBPROPERTIES EFX_ENV_Arena = EFX_REVERB_PRESET_ARENA;
54 static const EFXEAXREVERBPROPERTIES EFX_ENV_Hangar = EFX_REVERB_PRESET_HANGAR;
55 static const EFXEAXREVERBPROPERTIES EFX_ENV_CarpetedHallway = EFX_REVERB_PRESET_CARPETEDHALLWAY;
56 static const EFXEAXREVERBPROPERTIES EFX_ENV_Hallway = EFX_REVERB_PRESET_HALLWAY;
57 static const EFXEAXREVERBPROPERTIES EFX_ENV_StoneCorridor = EFX_REVERB_PRESET_STONECORRIDOR;
58 static const EFXEAXREVERBPROPERTIES EFX_ENV_Alley = EFX_REVERB_PRESET_ALLEY;
59 static const EFXEAXREVERBPROPERTIES EFX_ENV_Forest = EFX_REVERB_PRESET_FOREST;
60 static const EFXEAXREVERBPROPERTIES EFX_ENV_City = EFX_REVERB_PRESET_CITY;
61 static const EFXEAXREVERBPROPERTIES EFX_ENV_Mountains = EFX_REVERB_PRESET_MOUNTAINS;
62 static const EFXEAXREVERBPROPERTIES EFX_ENV_Quarry = EFX_REVERB_PRESET_QUARRY;
63 static const EFXEAXREVERBPROPERTIES EFX_ENV_Plain = EFX_REVERB_PRESET_PLAIN;
64 static const EFXEAXREVERBPROPERTIES EFX_ENV_ParkingLot = EFX_REVERB_PRESET_PARKINGLOT;
65 static const EFXEAXREVERBPROPERTIES EFX_ENV_SewerPipe = EFX_REVERB_PRESET_SEWERPIPE;
66 static const EFXEAXREVERBPROPERTIES EFX_ENV_Underwater = EFX_REVERB_PRESET_UNDERWATER;
67 static const EFXEAXREVERBPROPERTIES EFX_ENV_Drugged = EFX_REVERB_PRESET_DRUGGED;
68 static const EFXEAXREVERBPROPERTIES EFX_ENV_Dizzy = EFX_REVERB_PRESET_DIZZY;
69 static const EFXEAXREVERBPROPERTIES EFX_ENV_Psychotic = EFX_REVERB_PRESET_PSYCHOTIC;
70
71
72 static void oal_efx_set_env_properties()
73 {
74     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_DENSITY, EFX_env_properties.flDensity);
75     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_DIFFUSION, EFX_env_properties.flDiffusion);
76     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_GAIN, EFX_env_properties.flGain);
77     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_GAINHF, EFX_env_properties.flGainHF);
78     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_GAINLF, EFX_env_properties.flGainLF);
79     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_DECAY_TIME, EFX_env_properties.flDecayTime);
80     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_DECAY_HFRATIO, EFX_env_properties.flDecayHFRatio);
81     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_DECAY_LFRATIO, EFX_env_properties.flDecayLFRatio);
82     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_REFLECTIONS_GAIN, EFX_env_properties.flReflectionsGain);
83     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_REFLECTIONS_DELAY, EFX_env_properties.flReflectionsDelay);
84     alEffectfv(AL_EFX_effect_id, AL_EAXREVERB_REFLECTIONS_PAN, EFX_env_properties.flReflectionsPan);
85     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_LATE_REVERB_GAIN, EFX_env_properties.flLateReverbGain);
86     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_LATE_REVERB_DELAY, EFX_env_properties.flLateReverbDelay);
87     alEffectfv(AL_EFX_effect_id, AL_EAXREVERB_LATE_REVERB_PAN, EFX_env_properties.flLateReverbPan);
88     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_ECHO_TIME, EFX_env_properties.flEchoTime);
89     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_ECHO_DEPTH, EFX_env_properties.flEchoDepth);
90     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_MODULATION_TIME, EFX_env_properties.flModulationTime);
91     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_MODULATION_DEPTH, EFX_env_properties.flModulationDepth);
92     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_AIR_ABSORPTION_GAINHF, EFX_env_properties.flAirAbsorptionGainHF);
93     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_HFREFERENCE, EFX_env_properties.flHFReference);
94     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_LFREFERENCE, EFX_env_properties.flLFReference);
95     alEffectf(AL_EFX_effect_id, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, EFX_env_properties.flRoomRolloffFactor);
96     alEffecti(AL_EFX_effect_id, AL_EAXREVERB_DECAY_HFLIMIT, EFX_env_properties.iDecayHFLimit);
97 }
98
99 static void oal_efx_update_env_properties()
100 {
101         alEffectf(AL_EFX_effect_id, AL_EAXREVERB_GAIN, EFX_env_properties.flGain);
102         alEffectf(AL_EFX_effect_id, AL_EAXREVERB_DECAY_TIME, EFX_env_properties.flDecayTime);
103         alEffectf(AL_EFX_effect_id, AL_EAXREVERB_DECAY_HFRATIO, EFX_env_properties.flDecayHFRatio);
104 }
105
106 static void oal_efx_set_environment(uint id)
107 {
108         uint n_id = id;
109
110         switch (n_id) {
111                 case SND_ENV_GENERIC:
112                         EFX_env_properties = EFX_ENV_Generic;
113                         break;
114
115                 case SND_ENV_PADDEDCELL:
116                         EFX_env_properties = EFX_ENV_PaddedCell;
117                         break;
118
119                 case SND_ENV_ROOM:
120                         EFX_env_properties = EFX_ENV_Room;
121                         break;
122
123                 case SND_ENV_BATHROOM:
124                         EFX_env_properties = EFX_ENV_BathRoom;
125                         break;
126
127                 case SND_ENV_LIVINGROOM:
128                         EFX_env_properties = EFX_ENV_LivingRoom;
129                         break;
130
131                 case SND_ENV_STONEROOM:
132                         EFX_env_properties = EFX_ENV_StoneRoom;
133                         break;
134
135                 case SND_ENV_AUDITORIUM:
136                         EFX_env_properties = EFX_ENV_Auditorium;
137                         break;
138
139                 case SND_ENV_CONCERTHALL:
140                         EFX_env_properties = EFX_ENV_ConcertHall;
141                         break;
142
143                 case SND_ENV_CAVE:
144                         EFX_env_properties = EFX_ENV_Cave;
145                         break;
146
147                 case SND_ENV_ARENA:
148                         EFX_env_properties = EFX_ENV_Arena;
149                         break;
150
151                 case SND_ENV_HANGAR:
152                         EFX_env_properties = EFX_ENV_Hangar;
153                         break;
154
155                 case SND_ENV_CARPETEDHALLWAY:
156                         EFX_env_properties = EFX_ENV_CarpetedHallway;
157                         break;
158
159                 case SND_ENV_HALLWAY:
160                         EFX_env_properties = EFX_ENV_Hallway;
161                         break;
162
163                 case SND_ENV_STONECORRIDOR:
164                         EFX_env_properties = EFX_ENV_StoneCorridor;
165                         break;
166
167                 case SND_ENV_ALLEY:
168                         EFX_env_properties = EFX_ENV_Alley;
169                         break;
170
171                 case SND_ENV_FOREST:
172                         EFX_env_properties = EFX_ENV_Forest;
173                         break;
174
175                 case SND_ENV_CITY:
176                         EFX_env_properties = EFX_ENV_City;
177                         break;
178
179                 case SND_ENV_MOUNTAINS:
180                         EFX_env_properties = EFX_ENV_Mountains;
181                         break;
182
183                 case SND_ENV_QUARRY:
184                         EFX_env_properties = EFX_ENV_Quarry;
185                         break;
186
187                 case SND_ENV_PLAIN:
188                         EFX_env_properties = EFX_ENV_Plain;
189                         break;
190
191                 case SND_ENV_PARKINGLOT:
192                         EFX_env_properties = EFX_ENV_ParkingLot;
193                         break;
194
195                 case SND_ENV_SEWERPIPE:
196                         EFX_env_properties = EFX_ENV_SewerPipe;
197                         break;
198
199                 case SND_ENV_UNDERWATER:
200                         EFX_env_properties = EFX_ENV_Underwater;
201                         break;
202
203                 case SND_ENV_DRUGGED:
204                         EFX_env_properties = EFX_ENV_Drugged;
205                         break;
206
207                 case SND_ENV_DIZZY:
208                         EFX_env_properties = EFX_ENV_Dizzy;
209                         break;
210
211                 case SND_ENV_PSYCHOTIC:
212                         EFX_env_properties = EFX_ENV_Psychotic;
213                         break;
214
215                 default:
216                         n_id = SND_ENV_GENERIC;
217                         EFX_env_properties = EFX_ENV_Generic;
218                         break;
219         }
220
221         EFX_active_environment = n_id;
222 }
223
224 int oal_efx_init()
225 {
226         if (OAL_efx_inited) {
227                 return 0;
228         }
229
230         // make sure we support EFX and the EAXREVERB effect
231         if ( !alcIsExtensionPresent(alcGetContextsDevice(alcGetCurrentContext()), "ALC_EXT_EFX") ) {
232                 return -1;
233         }
234
235         if ( !alGetEnumValue("AL_EFFECT_EAXREVERB") ) {
236                 return -1;
237         }
238
239         // effects
240         alGenEffects = (LPALGENEFFECTS) alGetProcAddress("alGenEffects");
241         alDeleteEffects = (LPALDELETEEFFECTS) alGetProcAddress("alDeleteEffects");
242         alEffecti = (LPALEFFECTI) alGetProcAddress("alEffecti");
243         alEffectf = (LPALEFFECTF) alGetProcAddress("alEffectf");
244         alEffectfv = (LPALEFFECTFV) alGetProcAddress("alEffectfv");
245         alGetEffectf = (LPALGETEFFECTF) alGetProcAddress("alGetEffectf");
246
247         SDL_assert_release( alGenEffects != NULL );
248         SDL_assert_release( alDeleteEffects != NULL );
249         SDL_assert_release( alEffecti != NULL );
250         SDL_assert_release( alEffectf != NULL );
251         SDL_assert_release( alEffectfv != NULL );
252         SDL_assert_release( alGetEffectf != NULL );
253
254         // aux effect slots
255         alGenAuxiliaryEffectSlots = (LPALGENAUXILIARYEFFECTSLOTS) alGetProcAddress("alGenAuxiliaryEffectSlots");
256         alDeleteAuxiliaryEffectSlots = (LPALDELETEAUXILIARYEFFECTSLOTS) alGetProcAddress("alDeleteAuxiliaryEffectSlots");
257         alIsAuxiliaryEffectSlot = (LPALISAUXILIARYEFFECTSLOT) alGetProcAddress("alIsAuxiliaryEffectSlot");
258         alAuxiliaryEffectSloti = (LPALAUXILIARYEFFECTSLOTI) alGetProcAddress("alAuxiliaryEffectSloti");
259         alAuxiliaryEffectSlotiv = (LPALAUXILIARYEFFECTSLOTIV) alGetProcAddress("alAuxiliaryEffectSlotiv");
260         alAuxiliaryEffectSlotf = (LPALAUXILIARYEFFECTSLOTF) alGetProcAddress("alAuxiliaryEffectSlotf");
261         alAuxiliaryEffectSlotfv = (LPALAUXILIARYEFFECTSLOTFV) alGetProcAddress("alAuxiliaryEffectSlotfv");
262
263         SDL_assert_release( alGenAuxiliaryEffectSlots != NULL );
264         SDL_assert_release( alDeleteAuxiliaryEffectSlots != NULL );
265         SDL_assert_release( alIsAuxiliaryEffectSlot != NULL );
266         SDL_assert_release( alAuxiliaryEffectSloti != NULL );
267         SDL_assert_release( alAuxiliaryEffectSlotiv != NULL );
268         SDL_assert_release( alAuxiliaryEffectSlotf != NULL );
269         SDL_assert_release( alAuxiliaryEffectSlotfv != NULL );
270
271
272         EFX_active_environment = SND_ENV_GENERIC;
273         EFX_env_properties = EFX_ENV_Generic;
274
275
276         alGenAuxiliaryEffectSlots(1, &AL_EFX_aux_id);
277
278         if (alGetError() != AL_NO_ERROR) {
279                 nprintf(("Sound", "SOUND ==>  EFX:  Unable to create Aux effect!\n"));
280                 return -1;
281         }
282
283         alGenEffects(1, &AL_EFX_effect_id);
284
285         if (alGetError() != AL_NO_ERROR) {
286                 nprintf(("Sound", "SOUND ==>  EFX:  Unable to create effect!\n"));
287                 return -1;
288         }
289
290         alEffecti(AL_EFX_effect_id, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB);
291
292         if (alGetError() != AL_NO_ERROR) {
293                 nprintf(("Sound", "SOUND ==>  EFX:  EAXReverb not supported!\n"));
294                 return -1;
295         }
296
297         alAuxiliaryEffectSloti(AL_EFX_aux_id, AL_EFFECTSLOT_EFFECT, AL_EFX_effect_id);
298
299         if (alGetError() != AL_NO_ERROR) {
300                 nprintf(("Sound", "SOUND ==>  EFX:  Couldn't load effect!\n"));
301                 return -1;
302         }
303
304         OAL_efx_inited = 1;
305
306         oal_efx_set_env_properties();
307
308         return 0;
309 }
310
311 int oal_efx_is_inited()
312 {
313         return OAL_efx_inited;
314 }
315
316 void oal_efx_close()
317 {
318         if ( !OAL_efx_inited ) {
319                 return;
320         }
321
322         alAuxiliaryEffectSloti(AL_EFX_aux_id, AL_EFFECTSLOT_EFFECT, AL_EFFECT_NULL);
323
324         alDeleteEffects(1, &AL_EFX_effect_id);
325         AL_EFX_effect_id = 0;
326
327         alDeleteAuxiliaryEffectSlots(1, &AL_EFX_aux_id);
328         AL_EFX_aux_id = 0;
329
330         EFX_enabled = 0;
331
332         OAL_efx_inited = 0;
333 }
334
335 void oal_efx_attach(ALuint source_id)
336 {
337         if ( !OAL_efx_inited ) {
338                 return;
339         }
340
341         // by default it's disabled
342         ALint plist[3] = { 0, 0, AL_FILTER_NULL };
343
344         if (EFX_enabled) {
345                 plist[0] = AL_EFX_aux_id;
346         }
347
348         oal_check_for_errors("oal_efx_attach() begin");
349
350         alSourceiv(source_id, AL_AUXILIARY_SEND_FILTER, plist);
351
352         oal_check_for_errors("oal_efx_attach() end");
353 }
354
355 // Get up the parameters for the current environment
356 //
357 // er: (output) hold environment parameters
358 // id: if set will get specified preset env, otherwise current env
359 //
360 // returns: 0 if successful, otherwise return -1
361 //
362 int oal_efx_get_all(EAX_REVERBPROPERTIES *er, int id)
363 {
364         if (er == NULL) {
365                 return -1;
366         }
367
368         uint active_env_save = EFX_active_environment;
369         EFXEAXREVERBPROPERTIES env_save = EFX_env_properties;
370         bool saved = false;
371
372         if ( (id >= 0) && (id != (int)EFX_active_environment) ) {
373                 saved = true;
374
375                 oal_efx_set_environment(id);
376         }
377
378         er->environment = EFX_active_environment;
379         er->fVolume = EFX_env_properties.flGain;
380         er->fDecayTime_sec = EFX_env_properties.flDecayTime;
381         er->fDamping = EFX_env_properties.flDecayHFRatio;
382
383         if (saved) {
384                 EFX_active_environment = active_env_save;
385                 EFX_env_properties = env_save;
386         }
387
388         return 0;
389 }
390
391 // Set up all the parameters for an environment
392 //
393 // id: value from the SND_ENV_* enumeration
394 // volume: volume for the environment
395 // damping: damp value for the environment
396 // decay: decay time in seconds
397 //
398 // returns: 0 if successful, otherwise return -1
399 //
400 int oal_efx_set_all(uint id, float vol, float damping, float decay)
401 {
402         if ( !OAL_efx_inited ) {
403                 return -1;
404         }
405
406         oal_check_for_errors("oal_efx_set_all() begin");
407
408         // special disabled case (NOTE: does not take immediate affect!)
409         if ( (id == SND_ENV_GENERIC) && (vol == 0.0f) && (damping == 0.0f) && (decay == 0.0f) ) {
410                 EFX_enabled = 0;
411                 return 0;
412         }
413
414         if (id != EFX_active_environment) {
415                 oal_efx_set_environment(id);
416                 oal_efx_set_env_properties();
417         }
418
419         CAP(vol, AL_EAXREVERB_MIN_GAIN, AL_EAXREVERB_MAX_GAIN);
420         CAP(decay, AL_EAXREVERB_MIN_DECAY_TIME, AL_EAXREVERB_MAX_DECAY_TIME);
421         CAP(damping, AL_EAXREVERB_MIN_DECAY_HFRATIO, AL_EAXREVERB_MAX_DECAY_HFRATIO);
422
423         EFX_env_properties.flGain = vol;
424         EFX_env_properties.flDecayTime = decay;
425         EFX_env_properties.flDecayHFRatio = damping;
426
427         oal_efx_update_env_properties();
428
429         alAuxiliaryEffectSloti(AL_EFX_aux_id, AL_EFFECTSLOT_EFFECT, AL_EFX_effect_id);
430
431         EFX_enabled = 1;
432
433         if ( oal_check_for_errors("oal_efx_set_all() end") ) {
434                 return -1;
435         }
436
437         return 0;
438 }