]> icculus.org git repositories - taylor/freespace2.git/blob - src/gamesnd/gamesnd.cpp
fix incorrect FS2 demo ifdef
[taylor/freespace2.git] / src / gamesnd / gamesnd.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 /*
10  * $Logfile: /Freespace2/code/Gamesnd/GameSnd.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Routines to keep track of which sound files go where
16  *
17  * $Log$
18  * Revision 1.4  2003/05/25 02:30:42  taylor
19  * Freespace 1 support
20  *
21  * Revision 1.3  2002/06/09 04:41:17  relnev
22  * added copyright header
23  *
24  * Revision 1.2  2002/05/03 13:34:33  theoddone33
25  * More stuff compiles
26  *
27  * Revision 1.1.1.1  2002/05/03 03:28:09  root
28  * Initial import.
29  *
30  * 
31  * 6     7/01/99 11:44a Dave
32  * Updated object sound system to allow multiple obj sounds per ship.
33  * Added hit-by-beam sound. Added killed by beam sound.
34  * 
35  * 5     6/25/99 3:08p Dave
36  * Multiple flyby sounds.
37  * 
38  * 4     5/23/99 8:11p Alanl
39  * Added support for EAX
40  * 
41  * 3     10/23/98 3:51p Dave
42  * Full support for tstrings.tbl and foreign languages. All that remains
43  * is to make it active in Fred.
44  * 
45  * 2     10/07/98 10:52a Dave
46  * Initial checkin.
47  * 
48  * 1     10/07/98 10:48a Dave
49  * 
50  * 39    5/05/98 4:49p Lawrance
51  * Put in code to authenticate A3D, improve A3D support
52  * 
53  * 38    4/25/98 1:25p Lawrance
54  * Make function for playing generic error beep
55  * 
56  * 37    4/18/98 9:12p Lawrance
57  * Added Aureal support.
58  * 
59  * 36    3/29/98 12:56a Lawrance
60  * preload the warp in and explosions sounds before a mission.
61  * 
62  * 35    3/25/98 6:10p Lawrance
63  * Work on DirectSound3D
64  * 
65  * 34    2/22/98 2:48p John
66  * More String Externalization Classification
67  * 
68  * 33    1/17/98 12:33p John
69  * Made the game_busy function be called a constant amount of times per
70  * level load, making the bar prediction easier.
71  * 
72  * 32    1/17/98 12:14p John
73  * Added loading... bar to freespace.
74  * 
75  * 31    1/11/98 11:14p Lawrance
76  * Preload sounds that we expect will get played.
77  * 
78  * 30    12/24/97 8:54p Lawrance
79  * Integrating new popup code
80  * 
81  * 29    12/19/97 3:44p Mike
82  * Fix parse code.  Would improperly read a number through a comma.  Lots
83  * of ships.tbl problems.
84  * 
85  * 28    12/01/97 5:25p Hoffoss
86  * Routed interface sound playing through a special function that will
87  * only allow one instance of the sound to play at a time, avoiding
88  * over-mixing problems.
89  * 
90  * 27    11/20/97 1:06a Lawrance
91  * Add Master_voice_volume, make voices play back at correctly scaled
92  * volumes
93  * 
94  * 26    10/17/97 1:36p Lawrance
95  * load/unload interface sounds
96  * 
97  * 25    10/14/97 11:35p Lawrance
98  * change snd_load parameters
99  * 
100  * 24    7/05/97 1:46p Lawrance
101  * improve robustness of gameplay and interface sound loading/unloading
102  * 
103  * 23    6/09/97 11:50p Lawrance
104  * integrating DirectSound3D
105  * 
106  * 22    6/08/97 5:59p Lawrance
107  * flag sounds as 3D
108  * 
109  * 21    6/05/97 11:25a Lawrance
110  * use sound signatures to ensure correct sound is loaded
111  * 
112  * 20    6/05/97 1:07a Lawrance
113  * changes to support sound interface
114  * 
115  * 19    6/04/97 1:18p Lawrance
116  * added hooks for shield impacts
117  * 
118  * 18    6/02/97 1:50p Lawrance
119  * supporting new format of sounds in table
120  * 
121  * 17    5/14/97 9:54a Lawrance
122  * supporting mission-specific briefing music
123  * 
124  * 16    5/08/97 1:56p Lawrance
125  * supporting ship-specific engine sounds
126  * 
127  * 15    5/06/97 9:36a Lawrance
128  * added support for min and max distances for 3d sounds
129  * 
130  * 14    4/23/97 5:19p Lawrance
131  * split up misc sounds into: gamewide, ingame, and interface
132  * 
133  * 13    4/20/97 11:48a Lawrance
134  * added array of filenames for misc sounds.  Will be useful if we want to
135  * unload then re-load sounds
136  * 
137  * 12    4/20/97 11:19a Lawrance
138  * sndman_ interface obsolete.  Using snd_ functions to load, play, and
139  * manage static sound fx
140  * 
141  * 11    4/18/97 4:31p Mike
142  * Add support for default volume levels.
143  * 
144  * 10    3/20/97 11:04a Lawrance
145  * using incorrect constant when loading music filenames
146  * 
147  * 9     3/19/97 5:53p Lawrance
148  * integrating new Misc_sounds[] array (replaces old Game_sounds
149  * structure)
150  * 
151  * 8     3/17/97 3:47p Mike
152  * Homing missile lock sound.
153  * More on AI ships firing missiles.
154  * 
155  * 7     3/10/97 8:54a Lawrance
156  * added gamesnd_init_looping_sounds()
157  * 
158  * 6     2/28/97 8:41a Lawrance
159  * added afterburner engage and burn sounds
160  * 
161  * 5     2/14/97 12:37a Lawrance
162  * added hooks to play docking/undocking sounds
163  * 
164  * 4     2/13/97 12:03p Lawrance
165  * hooked in throttle sounds
166  * 
167  * 3     2/05/97 10:35a Lawrance
168  * supporting spooled music at menus, briefings, credits etc.
169  * 
170  * 2     1/20/97 7:58p John
171  * Fixed some link errors with testcode.
172  * 
173  * 1     1/20/97 7:08p John
174  *
175  * $NoKeywords: $
176  */
177
178 #include "pstypes.h"
179 #include "gamesnd.h"
180 #include "sound.h"
181 #include "parselo.h"
182 #include "localize.h"
183
184 // Global array that holds data about the gameplay sound effects.
185 game_snd Snds[MAX_GAME_SOUNDS];
186
187 // Global array that holds data about the interface sound effects.
188 game_snd Snds_iface[MAX_INTERFACE_SOUNDS];
189 int Snds_iface_handle[MAX_INTERFACE_SOUNDS];
190
191 // flyby sounds - 2 for each species (fighter and bomber flybys)
192 game_snd Snds_flyby[MAX_SPECIES_NAMES][2];
193
194
195 void gamesnd_play_iface(int n)
196 {
197         if (Snds_iface_handle[n] >= 0)
198                 snd_stop(Snds_iface_handle[n]);
199
200         Snds_iface_handle[n] = snd_play(&Snds_iface[n]);
201 }
202
203 // load in sounds that we expect will get played
204 //
205 // The method currently used is to load all those sounds that have the hardware flag
206 // set.  This works well since we don't want to try and load hardware sounds in on the
207 // fly (too slow).
208 extern "C"
209 void gamesnd_preload_common_sounds()
210 {
211         int             i;
212         game_snd        *gs;
213
214         for ( i = 0; i < MAX_GAME_SOUNDS; i++ ) {
215                 gs = &Snds[i];
216                 if ( gs->filename[0] != 0 && SDL_strcasecmp(gs->filename, NOX("none.wav")) ) {
217                         if ( gs->preload ) {
218                                 gs->id = snd_load(gs);
219                         }
220                 }
221                 game_busy();            // Animate loading cursor... does nothing if loading screen not active.
222         }
223 }
224
225 // -------------------------------------------------------------------------------------------------
226 // gamesnd_load_gameplay_sounds()
227 //
228 // Load the ingame sounds into memory
229 //
230 void gamesnd_load_gameplay_sounds()
231 {
232         int             i;
233         game_snd        *gs;
234
235         for ( i = 0; i < MAX_GAME_SOUNDS; i++ ) {
236                 gs = &Snds[i];
237                 if ( gs->filename[0] != 0 && SDL_strcasecmp(gs->filename, NOX("none.wav")) ) {
238                         gs->id = snd_load(gs);
239                 }
240         }
241 }
242
243 // -------------------------------------------------------------------------------------------------
244 // gamesnd_unload_gameplay_sounds()
245 //
246 // Unload the ingame sounds from memory
247 //
248 void gamesnd_unload_gameplay_sounds()
249 {
250         int             i;
251         game_snd        *gs;
252
253         for ( i = 0; i < MAX_GAME_SOUNDS; i++ ) {
254                 gs = &Snds[i];
255                 if ( gs->id != -1 ) {
256                         snd_unload( gs->id );
257                         gs->id = -1;
258                 }
259         }       
260 }
261
262 // -------------------------------------------------------------------------------------------------
263 // gamesnd_load_interface_sounds()
264 //
265 // Load the interface sounds into memory
266 //
267 void gamesnd_load_interface_sounds()
268 {
269         int             i;
270         game_snd        *gs;
271
272         for ( i = 0; i < MAX_INTERFACE_SOUNDS; i++ ) {
273                 gs = &Snds_iface[i];
274                 if ( gs->filename[0] != 0 && SDL_strcasecmp(gs->filename, NOX("none.wav")) ) {
275                         gs->id = snd_load(gs);
276                 }
277         }
278 }
279
280 // -------------------------------------------------------------------------------------------------
281 // gamesnd_unload_interface_sounds()
282 //
283 // Unload the interface sounds from memory
284 //
285 void gamesnd_unload_interface_sounds()
286 {
287         int             i;
288         game_snd        *gs;
289
290         for ( i = 0; i < MAX_INTERFACE_SOUNDS; i++ ) {
291                 gs = &Snds_iface[i];
292                 if ( gs->id != -1 ) {
293                         snd_unload( gs->id );
294                         gs->id = -1;
295                         gs->id_sig = -1;
296                 }
297         }
298 }
299
300 // -------------------------------------------------------------------------------------------------
301 // gamesnd_parse_line()
302 //
303 // Parse a sound effect line
304 //
305 void gamesnd_parse_line(game_snd *gs, const char *tag)
306 {
307         int is_3d;
308
309         required_string(tag);
310         stuff_int(&gs->sig);
311         stuff_string(gs->filename, F_NAME, ",");
312         if ( !SDL_strcasecmp(gs->filename,NOX("empty")) ) {
313                 gs->filename[0] = 0;
314                 advance_to_eoln(NULL);
315                 return;
316         }
317         Mp++;
318         stuff_int(&gs->preload);
319         stuff_float(&gs->default_volume);
320         stuff_int(&is_3d);
321         if ( is_3d ) {
322                 gs->flags |= GAME_SND_USE_3D;
323                 stuff_int(&gs->min);
324                 stuff_int(&gs->max);
325         }
326         advance_to_eoln(NULL);
327 }
328
329 // -------------------------------------------------------------------------------------------------
330 // gamesnd_parse_soundstbl() will parse the sounds.tbl file, and load the specified sounds.
331 //
332 //
333 void gamesnd_parse_soundstbl()
334 {
335         int             num_game_sounds = 0;
336         int             num_iface_sounds = 0;
337
338         // open localization
339         lcl_ext_open();
340
341         gamesnd_init_sounds();
342
343         try {
344                 read_file_text("sounds.tbl");
345                 reset_parse();          
346
347                 // Parse the gameplay sounds section
348                 required_string("#Game Sounds Start");
349                 while (required_string_either("#Game Sounds End","$Name:")) {
350                         SDL_assert( num_game_sounds < MAX_GAME_SOUNDS);
351                         gamesnd_parse_line( &Snds[num_game_sounds], "$Name:" );
352                         num_game_sounds++;
353                 }
354                 required_string("#Game Sounds End");
355
356                 // Parse the interface sounds section
357                 required_string("#Interface Sounds Start");
358                 while (required_string_either("#Interface Sounds End","$Name:")) {
359                         SDL_assert( num_iface_sounds < MAX_INTERFACE_SOUNDS);
360                         gamesnd_parse_line(&Snds_iface[num_iface_sounds], "$Name:");
361                         num_iface_sounds++;
362                 }
363                 required_string("#Interface Sounds End");
364
365 #ifndef MAKE_FS1
366                 // parse flyby sound section
367                 required_string("#Flyby Sounds Start");
368
369                 // read 2 terran sounds
370                 gamesnd_parse_line(&Snds_flyby[SPECIES_TERRAN][0], "$Terran:");
371                 gamesnd_parse_line(&Snds_flyby[SPECIES_TERRAN][1], "$Terran:");
372
373                 // 2 vasudan sounds
374                 gamesnd_parse_line(&Snds_flyby[SPECIES_VASUDAN][0], "$Vasudan:");
375                 gamesnd_parse_line(&Snds_flyby[SPECIES_VASUDAN][1], "$Vasudan:");
376
377                 gamesnd_parse_line(&Snds_flyby[SPECIES_SHIVAN][0], "$Shivan:");
378                 gamesnd_parse_line(&Snds_flyby[SPECIES_SHIVAN][1], "$Shivan:");
379
380                 required_string("#Flyby Sounds End");
381 #endif
382         } catch (parse_error_t rval) {
383                 Error(LOCATION, "Unable to parse sounds.tbl!  Code = %i.\n", (int)rval);
384         }
385
386         // close localization
387         lcl_ext_close();
388 }
389
390
391 // -------------------------------------------------------------------------------------------------
392 // gamesnd_init_struct()
393 //
394 void gamesnd_init_struct(game_snd *gs)
395 {
396         gs->filename[0] = 0;
397         gs->id = -1;
398         gs->id_sig = -1;
399 //      gs->is_3d = 0;
400 //      gs->use_ds3d = 0;
401         gs->flags = 0;
402 }
403
404 // -------------------------------------------------------------------------------------------------
405 // gamesnd_init_sounds() will initialize the Snds[] and Snds_iface[] arrays
406 //
407 void gamesnd_init_sounds()
408 {
409         int             i;
410
411         // init the gameplay sounds
412         for ( i = 0; i < MAX_GAME_SOUNDS; i++ ) {
413                 gamesnd_init_struct(&Snds[i]);
414         }
415
416         // init the interface sounds
417         for ( i = 0; i < MAX_INTERFACE_SOUNDS; i++ ) {
418                 gamesnd_init_struct(&Snds_iface[i]);
419                 Snds_iface_handle[i] = -1;
420         }
421 }
422
423 // callback function for the UI code to call when the mouse first goes over a button.
424 void common_play_highlight_sound()
425 {
426         gamesnd_play_iface(SND_USER_OVER);
427 }
428
429 void gamesnd_play_error_beep()
430 {
431         gamesnd_play_iface(SND_GENERAL_FAIL);
432 }
433