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