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