]> icculus.org git repositories - taylor/freespace2.git/blob - src/gamesnd/gamesnd.cpp
Freespace 1 support
[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 void gamesnd_preload_common_sounds()
209 {
210         int             i;
211         game_snd        *gs;
212
213         for ( i = 0; i < MAX_GAME_SOUNDS; i++ ) {
214                 gs = &Snds[i];
215                 if ( gs->filename[0] != 0 && stricmp(gs->filename, NOX("none.wav")) ) {
216                         if ( gs->preload ) {
217                                 gs->id = snd_load(gs);
218                         }
219                 }
220                 game_busy();            // Animate loading cursor... does nothing if loading screen not active.
221         }
222 }
223
224 // -------------------------------------------------------------------------------------------------
225 // gamesnd_load_gameplay_sounds()
226 //
227 // Load the ingame sounds into memory
228 //
229 void gamesnd_load_gameplay_sounds()
230 {
231         int             i;
232         game_snd        *gs;
233
234         for ( i = 0; i < MAX_GAME_SOUNDS; i++ ) {
235                 gs = &Snds[i];
236                 if ( gs->filename[0] != 0 && stricmp(gs->filename, NOX("none.wav")) ) {
237                         gs->id = snd_load(gs);
238                 }
239         }
240 }
241
242 // -------------------------------------------------------------------------------------------------
243 // gamesnd_unload_gameplay_sounds()
244 //
245 // Unload the ingame sounds from memory
246 //
247 void gamesnd_unload_gameplay_sounds()
248 {
249         int             i;
250         game_snd        *gs;
251
252         for ( i = 0; i < MAX_GAME_SOUNDS; i++ ) {
253                 gs = &Snds[i];
254                 if ( gs->id != -1 ) {
255                         snd_unload( gs->id );
256                         gs->id = -1;
257                 }
258         }       
259 }
260
261 // -------------------------------------------------------------------------------------------------
262 // gamesnd_load_interface_sounds()
263 //
264 // Load the interface sounds into memory
265 //
266 void gamesnd_load_interface_sounds()
267 {
268         int             i;
269         game_snd        *gs;
270
271         for ( i = 0; i < MAX_INTERFACE_SOUNDS; i++ ) {
272                 gs = &Snds_iface[i];
273                 if ( gs->filename[0] != 0 && stricmp(gs->filename, NOX("none.wav")) ) {
274                         gs->id = snd_load(gs);
275                 }
276         }
277 }
278
279 // -------------------------------------------------------------------------------------------------
280 // gamesnd_unload_interface_sounds()
281 //
282 // Unload the interface sounds from memory
283 //
284 void gamesnd_unload_interface_sounds()
285 {
286         int             i;
287         game_snd        *gs;
288
289         for ( i = 0; i < MAX_INTERFACE_SOUNDS; i++ ) {
290                 gs = &Snds_iface[i];
291                 if ( gs->id != -1 ) {
292                         snd_unload( gs->id );
293                         gs->id = -1;
294                         gs->id_sig = -1;
295                 }
296         }
297 }
298
299 // -------------------------------------------------------------------------------------------------
300 // gamesnd_parse_line()
301 //
302 // Parse a sound effect line
303 //
304 void gamesnd_parse_line(game_snd *gs, char *tag)
305 {
306         int is_3d;
307
308         required_string(tag);
309         stuff_int(&gs->sig);
310         stuff_string(gs->filename, F_NAME, ",");
311         if ( !stricmp(gs->filename,NOX("empty")) ) {
312                 gs->filename[0] = 0;
313                 advance_to_eoln(NULL);
314                 return;
315         }
316         Mp++;
317         stuff_int(&gs->preload);
318         stuff_float(&gs->default_volume);
319         stuff_int(&is_3d);
320         if ( is_3d ) {
321                 gs->flags |= GAME_SND_USE_DS3D;
322                 stuff_int(&gs->min);
323                 stuff_int(&gs->max);
324         }
325         advance_to_eoln(NULL);
326 }
327
328 // -------------------------------------------------------------------------------------------------
329 // gamesnd_parse_soundstbl() will parse the sounds.tbl file, and load the specified sounds.
330 //
331 //
332 void gamesnd_parse_soundstbl()
333 {
334         int             rval;
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         if ((rval = setjmp(parse_abort)) != 0) {
344                 Error(LOCATION, "Unable to parse sounds.tbl!  Code = %i.\n", rval);
345         }
346         else {
347                 read_file_text("sounds.tbl");
348                 reset_parse();          
349         }
350
351         // Parse the gameplay sounds section
352         required_string("#Game Sounds Start");
353         while (required_string_either("#Game Sounds End","$Name:")) {
354                 Assert( num_game_sounds < MAX_GAME_SOUNDS);
355                 gamesnd_parse_line( &Snds[num_game_sounds], "$Name:" );
356                 num_game_sounds++;
357         }
358         required_string("#Game Sounds End");
359
360         // Parse the interface sounds section
361         required_string("#Interface Sounds Start");
362         while (required_string_either("#Interface Sounds End","$Name:")) {
363                 Assert( num_iface_sounds < MAX_INTERFACE_SOUNDS);
364                 gamesnd_parse_line(&Snds_iface[num_iface_sounds], "$Name:");
365                 num_iface_sounds++;
366         }
367         required_string("#Interface Sounds End");
368
369 #ifndef MAKE_FS1
370         // parse flyby sound section    
371         required_string("#Flyby Sounds Start");
372
373         // read 2 terran sounds
374         gamesnd_parse_line(&Snds_flyby[SPECIES_TERRAN][0], "$Terran:");
375         gamesnd_parse_line(&Snds_flyby[SPECIES_TERRAN][1], "$Terran:");
376
377         // 2 vasudan sounds
378         gamesnd_parse_line(&Snds_flyby[SPECIES_VASUDAN][0], "$Vasudan:");
379         gamesnd_parse_line(&Snds_flyby[SPECIES_VASUDAN][1], "$Vasudan:");
380
381         gamesnd_parse_line(&Snds_flyby[SPECIES_SHIVAN][0], "$Shivan:");
382         gamesnd_parse_line(&Snds_flyby[SPECIES_SHIVAN][1], "$Shivan:");
383         
384         required_string("#Flyby Sounds End");
385 #endif
386
387         // close localization
388         lcl_ext_close();
389 }
390
391
392 // -------------------------------------------------------------------------------------------------
393 // gamesnd_init_struct()
394 //
395 void gamesnd_init_struct(game_snd *gs)
396 {
397         gs->filename[0] = 0;
398         gs->id = -1;
399         gs->id_sig = -1;
400 //      gs->is_3d = 0;
401 //      gs->use_ds3d = 0;
402         gs->flags = 0;
403 }
404
405 // -------------------------------------------------------------------------------------------------
406 // gamesnd_init_sounds() will initialize the Snds[] and Snds_iface[] arrays
407 //
408 void gamesnd_init_sounds()
409 {
410         int             i;
411
412         // init the gameplay sounds
413         for ( i = 0; i < MAX_GAME_SOUNDS; i++ ) {
414                 gamesnd_init_struct(&Snds[i]);
415         }
416
417         // init the interface sounds
418         for ( i = 0; i < MAX_INTERFACE_SOUNDS; i++ ) {
419                 gamesnd_init_struct(&Snds_iface[i]);
420                 Snds_iface_handle[i] = -1;
421         }
422 }
423
424 // callback function for the UI code to call when the mouse first goes over a button.
425 void common_play_highlight_sound()
426 {
427         gamesnd_play_iface(SND_USER_OVER);
428 }
429
430 void gamesnd_play_error_beep()
431 {
432         gamesnd_play_iface(SND_GENERAL_FAIL);
433 }
434