1 #ifdef NEW_SOUND
2 #include <ctype.h>
3 #include <string.h>
4 #include <SDL.h>
5 #include <SDL_thread.h>
6 #include <math.h>
7 #include "sound.h"
8 #include "asc.h"
9 #include "draw_scene.h"
10 #include "elconfig.h"
11 #include "errors.h"
12 #include "init.h"
13 #include "lights.h"
14 #include "main.h"
15 #include "map.h"
16 #include "misc.h"
17 #include "multiplayer.h"
18 #include "translate.h"
19 #include "weather.h"
20 #include "2d_objects.h"
21 #include "3d_objects.h"
22 #include "spells.h"
23 #include "tiles.h"
24 #include "actors.h"
25 #include "interface.h"
26 #include "io/elpathwrapper.h"
27 #include "io/elfilewrapper.h"
28 #include "threads.h"
29 
30 #if defined _EXTRA_SOUND_DEBUG && OSX
31  #define printf LOG_ERROR
32 #endif
33 
34 #define OGG_BUFFER_SIZE (1048576)
35 #define STREAM_BUFFER_SIZE (4096 * 16)
36 #define SLEEP_TIME 300		// Time to give CPU to other processes between loops of update_streams()
37 
38 #ifdef _EXTRA_SOUND_DEBUG
39 #include <unistd.h>
40 static char last_file[50] = "";
41 static char last_func[50] = "";
42 static int last_line = 0;
43 #define	LOCK_SOUND_LIST() \
44 { \
45 	while (SDL_TryLockMutex(sound_list_mutex) != 0) \
46 	{ \
47 		printf("lock loop in %s, %s:%d - last lock: %s, %s:%d\n", __FILE__, __FUNCTION__, __LINE__, last_file, last_func, last_line); \
48 		usleep(100); \
49 	} \
50 	safe_strncpy(last_file, __FILE__, strlen(last_file)); \
51 	safe_strncpy(last_func, __FUNCTION__, strlen(last_func)); \
52 	last_line = __LINE__; \
53 }
54 #define	UNLOCK_SOUND_LIST() { CHECK_AND_UNLOCK_MUTEX(sound_list_mutex); }
55 #else // _EXTRA_SOUND_DEBUG
56 #define	LOCK_SOUND_LIST() CHECK_AND_LOCK_MUTEX(sound_list_mutex);
57 #define	UNLOCK_SOUND_LIST() CHECK_AND_UNLOCK_MUTEX(sound_list_mutex);
58 #endif // _EXTRA_SOUND_DEBUG
59 
60 #define MAX_FILENAME_LENGTH 80
61 #define MAX_BUFFERS 64
62 #define MAX_SOURCES 16
63 #define ABS_MAX_SOURCES 64				// Define an absolute maximum for the sources (the size of the array)
64 
65 #define MAX_SOUNDS 200
66 
67 #define MAX_STREAMS 7					// 1 music stream and up to 3 each for bg and crowds
68 #define STREAM_TYPE_NONE -1
69 #define STREAM_TYPE_SOUNDS 0
70 #define STREAM_TYPE_MUSIC 1
71 #define STREAM_TYPE_CROWD 2
72 #define NUM_STREAM_BUFFERS 4
73 
74 #define MAX_PLAYLIST_ENTRIES 50
75 #define MAX_PLAYLIST_FILENAME 64
76 
77 #define MAX_SOUND_FILES (MAX_SOUNDS * MAX_SOUND_VARIANTS * num_STAGES)	// The total number of files if every part of every
78 																		// variant of every sound had a different file
79 #define MAX_BACKGROUND_DEFAULTS 8			// Maximum number of global default backgrounds
80 #define MAX_MAP_BACKGROUND_DEFAULTS 4		// Maximum number of default backgrounds per map
81 #define MAX_SOUND_MAP_NAME_LENGTH 60		// Maximum length of the name of the map
82 #define MAX_SOUND_VARIANTS 10				// Maximum number of different sounds allowed for the one sound type
83 #define MAX_SOUND_MAP_BOUNDARIES 20			// Maximum number of boundary sets per map
84 #define MAX_SOUND_WALK_BOUNDARIES 40		// Maximum number of walk boundary sets per map
85 #define MAX_ITEM_SOUND_IMAGE_IDS 30			// Maximum number of image id's linked to an item sound def
86 #define MAX_SOUND_TILE_TYPES 20				// Maximum number of different tile types
87 #define MAX_SOUND_TILES 30					// Maximum number of different tiles for a tile type
88 #define MAX_SOUND_TILES_SOUNDS 5			// Maximum number of different sound types for a tile type
89 #define MAX_SERVER_SOUNDS 10				// Maximum number of server sounds - keep up to date with the snd_xxx #defs client_serv.h
90 
91 #define MAX_SOUND_MAPS 150			// This value is the maximum number of maps sounds can be defined for
92 									// (Roja has suggested 150 is safe for now)
93 #define MAX_SOUND_EFFECTS 60		// This value should equal the max special_effect_enum
94 #define MAX_SOUND_PARTICLES 20		// This value should equal the number of particle effects
95 #define MAX_SOUND_ITEMS 5			// This is the number of sounds defined for "Use item" sfx
96 
97 #define MAX_SOUND_WARNINGS 50		// The number of user defined sound warnings
98 #define MAX_SND_WARNING_STRING 256	// Max size of warning string
99 
100 typedef enum
101 {
102 	STAGE_UNUSED = -1, STAGE_INTRO, STAGE_MAIN, STAGE_OUTRO, num_STAGES, STAGE_STREAM
103 } SOUND_STAGE;
104 
105 typedef struct _source_list
106 {
107 	ALuint source;					// The physical address of this source (not the array id of source_data as that changes)
108 	struct _source_list *next;
109 	struct _source_list *last;
110 } source_list;
111 
112 typedef struct
113 {
114 	char file_path[MAX_FILENAME_LENGTH];	// Where to load the file from
115 	int sample_num;							// Sample array ID (if loaded)
116 } sound_file;
117 
118 typedef struct
119 {
120 	sound_file *part[num_STAGES];	// Pointers to the files used for each stage
121 	float gain;						// The gain of this sound (default 1.0)
122 									// The same sample may be defined under 2 sound names, with different gains.
123 } sound_variants;
124 
125 typedef struct
126 {
127 	char name[MAX_SOUND_NAME_LENGTH];
128 	sound_variants variant[MAX_SOUND_VARIANTS];
129 	int num_variants;
130 	int stereo;						// 1 is stereo, 0 is mono (default mono)
131 	float distance;					// Distance it can be heard, in meters
132 	int positional;					// 1=positional, 0=omni (default positional)
133 	int loops;						// 0=infinite, otherwise the number of loops (default 1)
134 	int fadeout_time;				// In milliseconds, only for omni sounds that loop. (default 0) -- NOT USED
135 	int echo_delay;					// The value is the echo in MS. If 0, no echo (default 0) -- NOT USED
136 	int echo_volume;				// In percent, 0 means no sound, 100 means as loud as the original sound (default 50) -- NOT USED
137 	int time_of_the_day_flags;		// Bits 0-11 set each 1/2 hour of the 6-hour day (default 0xffff)
138 	unsigned int priority;			// If there are too many sounds to be played, highest value priority get culled (default 5)
139 	int type;						// The type of sound - environmental, actor, walking etc. (default Enviro)
140 } sound_type;
141 
142 typedef struct
143 {
144 	ALuint buffer;							// If the sample is loaded, a buffer ID to play it.
145 	ALenum format;
146 	ALsizei size;							// Size of the sound data in bytes
147 	ALfloat freq;							// Frequency
148 	ALint channels;							// Number of sound channels
149 	ALint bits;								// Bits per channel per sample
150 	int length;								// Duration in milliseconds
151 	source_list *sources;					// List of sources using this sample
152 } sound_sample;
153 
154 typedef struct
155 {
156 	int sound;							// The ID of the sound type
157 	int variant;						// The variant of the sound type being played
158 	int x;
159 	int y;
160 	int loaded;							// Has this sound been loaded into a buffer
161 	int playing;						// Is this sound loaded into a source and currently playing
162 	float base_gain;					// The initial gain (before adjustments for weather and sound type volume etc)
163 	float cur_gain;						// The last actual gain. If the calculated new gain is different then do an alSourcef command
164 	unsigned int cookie;
165 	int lifetime;						// The length of time in ms the sound has existed
166 } sound_loaded;
167 
168 typedef struct
169 {
170 	ALuint source;						// A handle for the source
171 	int priority;						// Include this here for streams and to force a priority if needed
172 	int play_duration;
173 	int loaded_sound;					// Sound ID loaded into this source (Not used for streams)
174 	SOUND_STAGE current_stage;			// Set as STAGE_STREAMS for streams
175 	unsigned int cookie;
176 	int sample[num_STAGES];				// The samples currently in use by this source
177 } source_data;
178 
179 typedef struct
180 {
181 	int sound;
182 	int time_of_day_flags;		// As for sound time_of_day_flags
183 	int map_type;				// At the moment, only 0 (outside) and 1 (dungeon). Checked against the dungeon flag.
184 } background_default;
185 
186 typedef struct
187 {
188 	int x;
189 	int y;
190 	double a;					// Angle of the line between this point and the next (not used for outer bounding rect)
191 } bound_point;
192 
193 typedef struct
194 {
195 	int bg_sound;
196 	int crowd_sound;
197 	int time_of_day_flags;		// As for sound time_of_day_flags
198 	int is_default;				// There can be up to 4 defaults for any one map, with unique times of day
199 								// Coords are ignored if is_default set.
200 	bound_point p[4];			// Details of this point and its corresponding angle
201 	int int_point;				// Index of the internal point or -1 for no internal point
202 	bound_point o[2];			// Outer bounding rectangle (0 = lower left, 1 = upper right)
203 } map_sound_boundary_def;
204 
205 typedef struct
206 {
207 	int id;
208 	char file_name[256];
209 	char name[MAX_SOUND_MAP_NAME_LENGTH];		// This isn't used, it is simply helpful when editing the config
210 	map_sound_boundary_def boundaries[MAX_SOUND_MAP_BOUNDARIES];		// This is the boundaries for backgound and crowd sounds
211 	map_sound_boundary_def walk_boundaries[MAX_SOUND_WALK_BOUNDARIES];	// This is the boundaries for walking sounds (to fake 3d objects)
212 	int num_boundaries;
213 	int num_walk_boundaries;
214 	int defaults[MAX_MAP_BACKGROUND_DEFAULTS];	// ID of the default boundaries
215 	int num_defaults;
216 } map_sound_data;
217 
218 typedef struct
219 {
220 	int id;					// ID's in the config should match those of special_effect_enum
221 	int sound;
222 } effect_sound_data;
223 
224 typedef struct
225 {
226 	char file[30];			// This is the filename (without extension) for a particle
227 	int sound;
228 } particle_sound_data;
229 
230 typedef struct
231 {
232 	int image_id[MAX_ITEM_SOUND_IMAGE_IDS];
233 	int num_imageids;
234 	int sound;
235 } item_sound_data;
236 
237 typedef struct
238 {
239 	char actor_types[1024];
240 	int sound;
241 } tile_sounds;
242 
243 typedef struct
244 {
245 	int tile_type[MAX_SOUND_TILES];
246 	int num_tile_types;
247 	tile_sounds sounds[MAX_SOUND_TILES_SOUNDS];
248 	int num_sounds;
249 	int default_sound;
250 } tile_sound_data;
251 
252 typedef struct
253 {
254 	int sound;
255 	char string[MAX_SND_WARNING_STRING];
256 } sound_warnings;
257 
258 typedef struct
259 {
260 	int type;								// The type of this stream
261 	ALuint source;							// The source for this stream
262 	unsigned int cookie;					// A cookie for the source
263 	ALuint buffers[NUM_STREAM_BUFFERS];		// The stream buffers
264 	OggVorbis_File stream;					// The Ogg file handle for this stream
265 	int stream_opened;						// If try, its OK to call ov_clear()
266 	vorbis_info * info;						// The Ogg info for this file handle
267 	int fade;								// The current fade value for this stream
268 	int fade_length;						// The length of the fade in or out (number of update_stream loops)
269 	int processed;							// Processed value (temporary storage)
270 	int playing;							// Is this stream currently playing
271 	int sound;								// The sound this stream is playing				(not used for music)
272 	int variant;							// The variant of the sound playing				(not used for music)
273 	int is_default;							// Is this sound a default sound for this type	(not used for music)
274 	map_sound_boundary_def * boundary;		// This is a pointer to the boundary in use
275 } stream_data;
276 
277 typedef struct {
278 	char file_name[MAX_PLAYLIST_FILENAME];
279 	int min_x;
280 	int max_x;
281 	int min_y;
282 	int max_y;
283 	int time;
284 } playlist_entry;
285 
286 
287 int have_sound = 0;
288 int have_music = 0;
289 int no_sound = 0;
290 int sound_on = 1;
291 int music_on = 1;
292 Uint8 inited = 0;
293 
294 SDL_Thread *sound_streams_thread = NULL;
295 SDL_mutex *sound_list_mutex = NULL;
296 
297 stream_data * music_stream = NULL;
298 stream_data *streams = NULL;
299 
300 ALfloat sound_gain = 1.0f;
301 ALfloat music_gain = 1.0f;
302 ALfloat crowd_gain = 1.0f;
303 ALfloat enviro_gain = 1.0f;
304 ALfloat actor_gain = 1.0f;
305 ALfloat walking_gain = 1.0f;
306 ALfloat gamewin_gain = 1.0f;
307 ALfloat client_gain = 1.0f;
308 ALfloat warnings_gain = 1.0f;
309 
310 int used_sources = 0;						// the number of sources currently playing
311 
312 char sound_device[30] = "";					// Set up a string to store the names of the selected sound device
313 char sound_devices[1000] = "";				// Set up a string to store the names of the available sound devices
314 int max_sources = MAX_SOURCES;				// Initialise our local maximum number of sources to the default
315 int max_streams = MAX_STREAMS;				// Initialise our local maximum number of streams to the default
316 
317 int num_types = 0;							// Number of distinct sound types
318 int num_samples = 0;						// Number of actual sound files - a sound type can have > 1 sample
319 int num_sound_files = 0;					// Number of individual sound files
320 int num_sounds = 0;							// Number of sounds in the sounds_list
321 int sound_num_background_defaults = 0;		// Number of default background sounds
322 int sound_num_maps = 0;						// Number of maps we have sounds for
323 int sound_num_effects = 0;					// Number of effects we have sounds for
324 int sound_num_particles = 0;				// Number of particles we have sounds for
325 int sound_num_items = 0;					// Number of "Use item" actions we have sounds for
326 int sound_num_tile_types = 0;				// Number of tile type groups we have sounds for
327 int num_sound_warnings = 0;					// Number of string warnings
328 int have_sound_config = 0;					// true if the sound config file was found
329 static int must_restart_spell_sounds = 0;	// true if sounds have been stopped, triggeres an attempt to restart
330 
331 int snd_cur_map = -1;
332 int cur_boundary = 0;
333 
334 unsigned int next_cookie = 1;							// Each playing source is identified by a unique cookie.
335 sound_loaded *sounds_list = NULL;						// The loaded sounds
336 source_data *sound_source_data = NULL;				// The active (playing) sources
337 sound_type *sound_type_data = NULL;					// Configuration of the sound types
338 sound_sample *sound_sample_data = NULL;				// Buffer data for each sample
339 sound_file *sound_files = NULL;						// File names for each individual sound file
340 background_default *sound_background_defaults = NULL;// Default background sounds
341 														// (must have non-overlapping time of day flags)
342 int crowd_default = -1;									// Default sound for crowd effects
343 int walking_default = -1;								// Default sound for walking
344 map_sound_data *sound_map_data = NULL;				// Data for map sfx
345 effect_sound_data *sound_effect_data = NULL;			// Data for effect sfx
346 particle_sound_data *sound_particle_data = NULL;		// Data for particle sfx
347 item_sound_data *sound_item_data = NULL;				// Data for item sfx
348 tile_sound_data *sound_tile_data = NULL;				// Data for tile (walking) sfx
349 int *server_sound = NULL;								// Map of server sounds to sound def ids
350 int *sound_spell_data = NULL;							// Map of id's for spells-that-affect-you to sounds
351 sound_warnings *warnings_list = NULL;					// List of strings to monitor for warning sounds
352 int afk_snd_warning = 0;								// Whether to play a sound on receiving a message while AFK
353 
354 playlist_entry *playlist = NULL;
355 int loop_list = 1;
356 int list_pos = -1;
357 
358 
359 /*    *** Declare some local functions ****
360  * These functions shouldn't need to be accessed outside sound.c
361  */
362 
363 /* Ogg handling	*/
364 int load_ogg_file(char *file_name, OggVorbis_File *oggFile);
365 int stream_ogg_file(char *file_name, stream_data * stream, int numBuffers);
366 int stream_ogg(ALuint buffer, OggVorbis_File * inStream, vorbis_info * info);
367 /* Stream handling */
368 static char * get_stream_type(int type);
369 void play_stream(int sound, stream_data * stream, ALfloat gain);
370 int start_stream(stream_data * stream);
371 void stop_stream(stream_data * stream);
372 void reset_stream(stream_data * stream);
373 int init_sound_stream(stream_data * stream, int type, int priority);
374 void destroy_stream(stream_data * stream);
375 int add_stream(int sound, int type, int boundary);
376 int check_for_valid_stream_sound(int tx, int ty, int type);
377 void check_for_new_streams(int tx, int ty);
378 int process_stream(stream_data * stream, ALfloat gain, int * sleep);
379 int check_stream(stream_data * stream, int day_time, int tx, int ty);
380 /* Music functions */
381 void play_song(int list_pos);
382 void find_next_song(int tx, int ty, int day_time);
383 
384 /* Source functions */
385 source_data * get_available_source(int priority);
386 source_data *insert_sound_source_at_index(unsigned int index);
387 void release_source(source_data *pSource, int index);
388 int stop_sound_source_at_index(int index);
389 void set_sound_gain(source_data * pSource, int loaded_sound_num, float initial_gain);
390 /* Sample functions */
391 int ensure_sample_loaded(char * in_filename);
392 int load_samples(sound_type * pType);
393 void release_sample(int sample_num);
394 void unload_sample(int sample_num);
395 /* Individual sound functions */
396 int play_sound(int loaded_sound_num, int x, int y, float initial_gain);
397 unsigned int get_next_cookie();
398 int get_loaded_sound_num();
399 void unload_sound(int index);
400 /* General functions */
401 int get_3d_obj_walk_sound(char * filename);
402 int get_2d_obj_walk_sound(char * filename);
403 int get_boundary_walk_sound(int x_pos, int y_pos);
404 int get_tile_sound(int tile_type, char * actor_type);
405 int find_sound_from_cookie(unsigned int cookie);
406 int time_of_day_valid(int flags);
407 int sound_bounds_check(int x, int y, map_sound_boundary_def * bounds);
408 int test_bounds_angles(int x, int y, int point, map_sound_boundary_def * bounds);
409 double calculate_bounds_angle(int x, int y, int point, map_sound_boundary_def * bounds);
410 #ifdef DEBUG_MAP_SOUND
411 void print_sound_boundary_coords(const char *mapname);
412 #endif // DEBUG_MAP_SOUND
413 /* Init functions */
414 void parse_snd_devices(ALCchar * in_array, char * sound_devs);
415 static void clear_playlist(void);
416 
417 
418 /**************************
419  * SOUND OPTION FUNCTIONS *
420  **************************/
421 
turn_sound_on()422 void turn_sound_on()
423 {
424 	int i, state = 0;
425 	ALuint source, error;
426 
427 	if (!video_mode_set)
428 		return;			// Don't load the config until we have video (so we don't load before the loading screen)
429 	if (!inited)
430 		init_sound();
431 	if (!have_sound)
432 		return;
433 	LOCK_SOUND_LIST();
434 	sound_on = 1;
435 	for (i = 0; i < used_sources; i++)
436 	{
437 		source = sound_source_data[i].source;
438 		alGetSourcei(source, AL_SOURCE_STATE, &state);
439 		if (state == AL_PAUSED)
440 			alSourcePlay(source);
441 	}
442 	UNLOCK_SOUND_LIST();
443 	if ((error=alGetError()) != AL_NO_ERROR)
444 	{
445 #ifdef _EXTRA_SOUND_DEBUG
446 		printf("Error turning sound on\n");
447 #endif // _EXTRA_SOUND_DEBUG
448 	}
449 	must_restart_spell_sounds = 1;
450 }
451 
turn_sound_off()452 void turn_sound_off()
453 {
454 	int i = 0;
455 	ALuint error;
456 	if (!inited)
457 		return;
458 	if (!have_music || !music_on)
459 	{
460 		destroy_sound();
461 		return;
462 	}
463 	LOCK_SOUND_LIST();
464 	sound_on = 0;
465 	while (i < used_sources)
466 	{
467 		if (sound_source_data[i].current_stage == STAGE_STREAM)
468 		{
469 			i++;			// This source is being used by a stream and handled lower down so ignore
470 			continue;
471 		}
472 #ifdef _EXTRA_SOUND_DEBUG
473 		printf("Removing source with index %d\n", i);
474 #endif //_EXTRA_SOUND_DEBUG
475 		stop_sound_source_at_index(0);
476 		continue;
477 	}
478 	for (i = 0; i < max_streams; i++)
479 	{
480 		if (streams[i].type != STREAM_TYPE_MUSIC)
481 		{
482 			destroy_stream(&streams[i]);
483 		}
484 	}
485 	UNLOCK_SOUND_LIST();
486 	if ((error=alGetError()) != AL_NO_ERROR)
487 	{
488 #ifdef _EXTRA_SOUND_DEBUG
489 		printf("Error turning sound off\n");
490 #endif //_EXTRA_SOUND_DEBUG
491 	}
492 }
493 
turn_music_on()494 void turn_music_on()
495 {
496 	if (!video_mode_set)
497 		return;			// Don't load the config until we have video (so we don't load before the loading screen)
498 	music_on = 1;		// Set this here so if ness we will init the sound
499 	if (!inited)
500 	{
501 		init_sound();
502 	}
503 	if (!have_music)
504 		return;
505 	get_map_playlist();
506 }
507 
turn_music_off()508 void turn_music_off()
509 {
510 	if (!inited)
511 		return;
512 	if (!have_sound || !sound_on)
513 	{
514 		destroy_sound();
515 		return;
516 	}
517 	if (!have_music)
518 		return;
519 
520 	LOCK_SOUND_LIST();
521 	music_on = 0;
522 	if (sound_streams_thread != NULL)
523 	{
524 		if (music_stream)
525 		{
526 			destroy_stream(music_stream);
527 		}
528 	}
529 	UNLOCK_SOUND_LIST();
530 }
531 
toggle_sounds(int * var)532 void toggle_sounds(int *var)
533 {
534 	*var = !*var;
535 	if (!sound_on) {
536 		turn_sound_off();
537 	} else {
538 		turn_sound_on();
539 	}
540 }
541 
toggle_music(int * var)542 void toggle_music(int * var) {
543 	*var = !*var;
544 	if (!music_on) {
545 		turn_music_off();
546 	} else {
547 		turn_music_on();
548 	}
549 }
550 
disable_sound(int * var)551 void disable_sound(int *var)
552 {
553 	*var = !*var;
554 	if (no_sound) {
555 		destroy_sound();
556 		clear_sound_data();
557 		have_sound_config = 0;
558 	} else {
559 		if (sound_on)
560 			turn_sound_on();
561 		if (music_on)
562 			turn_music_on();
563 	}
564 }
565 
566 
567 /************************
568  * OGG VORBIS FUNCTIONS *
569  ************************/
570 
ogg_error(int code)571 void ogg_error(int code)
572 {
573 	switch(code)
574 	{
575 		case OV_EREAD:
576 			LOG_ERROR(snd_media_read); break;
577 		case OV_ENOTVORBIS:
578 			LOG_ERROR(snd_media_notvorbis); break;
579 		case OV_EVERSION:
580 			LOG_ERROR(snd_media_ver_mismatch); break;
581 		case OV_EBADHEADER:
582 			LOG_ERROR(snd_media_invalid_header); break;
583 		case OV_EFAULT:
584 			LOG_ERROR(snd_media_internal_error); break;
585 		case OV_EOF:
586 			LOG_ERROR(snd_media_eof); break;
587 		case OV_HOLE:
588 			LOG_ERROR(snd_media_hole); break;
589 		case OV_EINVAL:
590 			LOG_ERROR(snd_media_einval); break;
591 		case OV_EBADLINK:
592 			LOG_ERROR(snd_media_ebadlink); break;
593 		case OV_FALSE:
594 			LOG_ERROR(snd_media_false); break;
595 		case OV_ENOSEEK:
596 			LOG_ERROR(snd_media_enoseek); break;
597 		default:
598 			LOG_ERROR(snd_media_ogg_error);
599     }
600 }
601 
load_ogg_file(char * file_name,OggVorbis_File * oggFile)602 int load_ogg_file(char * file_name, OggVorbis_File *oggFile)
603 {
604 	FILE *file;
605 	int result = 0;
606 
607 	file = my_fopen(file_name, "rb");
608 
609 	if (file == NULL)
610 	{
611 		return 0;
612 	}
613 
614 #ifndef _MSC_VER		// MS's compiler breaks things with files opened from different DLL's
615 	result = ov_open(file, oggFile, NULL, 0);
616 #else // !_MSC_VER
617 	result = ov_open_callbacks(file, oggFile, NULL, 0, OV_CALLBACKS_DEFAULT);
618 #endif
619 	if (result < 0)
620 	{
621 		LOG_ERROR("Error opening ogg file: %s. Ogg error: %d\n", file_name, result);
622 		fclose(file);
623 		return 0;
624 	}
625 
626 	return 1;
627 }
628 
stream_ogg_file(char * in_filename,stream_data * stream,int numBuffers)629 int stream_ogg_file(char * in_filename, stream_data * stream, int numBuffers)
630 {
631 	int result, more_stream = 0, i;
632 	char filename[200];
633 
634 	stop_stream(stream);
635 	if (stream->stream_opened)
636 	{
637 		ov_clear(&stream->stream);
638 		stream->stream_opened = 0;
639 	}
640 
641 	// Add the datadir to the input filename and try to open it
642 	safe_strncpy(filename, datadir, sizeof(filename));
643 	safe_strcat(filename, in_filename, sizeof(filename));
644 	result = load_ogg_file(filename, &stream->stream);
645 	if (!result) {
646 		LOG_ERROR("Error loading ogg file: %s\n", filename);
647 		return -1;
648 	}
649 	stream->stream_opened = 1;
650 
651 	stream->info = ov_info(&stream->stream, -1);
652 	for (i = 0; i < numBuffers; i++)
653 	{
654 		more_stream = stream_ogg(stream->buffers[i], &stream->stream, stream->info);
655 		if (!more_stream)
656 		{
657 			LOG_ERROR("Error playing ogg file: %s\n", filename);
658 			return more_stream;		// There was an error, probably too little data to fill the buffers
659 		}
660 	}
661 
662 	alSourceQueueBuffers(stream->source, numBuffers, stream->buffers);
663 	result = start_stream(stream);
664 
665 	return result;
666 }
667 
stream_ogg(ALuint buffer,OggVorbis_File * inStream,vorbis_info * info)668 int stream_ogg(ALuint buffer, OggVorbis_File * inStream, vorbis_info * info)
669 {
670 	char data[STREAM_BUFFER_SIZE];
671 	int size = 0;
672 	int section = 0;
673 	int result = 0;
674 	int error = 0;
675 	char str[256];
676 	ALenum format;
677 
678 	// Clear any previous AL errors
679 	if ((error = alGetError()) != AL_NO_ERROR) { }
680 
681 	size = 0;
682 	while (size < STREAM_BUFFER_SIZE)
683 	{
684 #ifndef EL_BIG_ENDIAN
685         result = ov_read(inStream, data + size, STREAM_BUFFER_SIZE - size, 0, 2, 1, &section);
686 #else
687         result = ov_read(inStream, data + size, STREAM_BUFFER_SIZE - size, 1, 2, 1, &section);
688 #endif
689 		safe_snprintf(str, sizeof(str), "%d", result); //prevents optimization errors under Windows, but how/why?
690 		if (result > 0)
691 			size += result;
692 		else if (result == OV_HOLE)
693 			// OV_HOLE is informational so ignore it
694 			continue;
695 		else if(result < 0)
696 			ogg_error(result);
697 		else
698 			break;
699 	}
700 
701 	if (!size)
702 		return 0;	// The file is finished, quit trying to play
703 
704 	// Check the number of channels... always use 16-bit samples
705 	if (info->channels == 1)
706 		format = AL_FORMAT_MONO16;
707 	else
708 		format = AL_FORMAT_STEREO16;
709 
710 	alBufferData(buffer, format, data, size, info->rate);
711 
712 	if ((error = alGetError()) != AL_NO_ERROR)
713 	{
714 #ifdef _EXTRA_SOUND_DEBUG
715 		printf("stream_ogg %s: %s, buffer: %d, format: %d, size: %d, rate: %ld", my_tolower(reg_error_str), alGetString(error), buffer, format, size, info->rate);
716 #endif // _EXTRA_SOUND_DEBUG
717 	}
718 	return 1;
719 }
720 
load_ogg_into_memory(char * szPath,ALenum * inFormat,ALsizei * inSize,ALfloat * inFreq)721 ALvoid * load_ogg_into_memory(char * szPath, ALenum *inFormat, ALsizei *inSize, ALfloat *inFreq)
722 {
723 	int bitStream;
724 	int result;
725 	vorbis_info *pInfo;
726 	OggVorbis_File oggFile;
727 	ALenum format;
728 	ALsizei size;
729 	ALfloat freq;
730 	char * data;
731 
732 	// Load the file
733 	result = load_ogg_file(szPath, &oggFile);
734 	if (!result)
735 		return NULL;
736 
737 	// Get some information about the OGG file
738 	pInfo = ov_info(&oggFile, -1);
739 
740 	// Check the number of channels... always use 16-bit samples
741 	format = (pInfo->channels == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
742 
743 	// The frequency of the sampling rate
744 	freq = pInfo->rate;
745 
746 	data = malloc(OGG_BUFFER_SIZE);
747 	if (!data)
748 	{
749 		ov_clear(&oggFile);
750 		return NULL;
751 	}
752 
753 	// Reset the variables
754 	bitStream = 0;
755 	size = 0;
756 
757 	// Hope OGG_BUFFER_SIZE is large enough for this sample - 1MB should be! Anything more should be streamed.
758 	while (size < OGG_BUFFER_SIZE)
759 	{
760 #ifndef EL_BIG_ENDIAN
761 		result = ov_read(&oggFile, data + size, OGG_BUFFER_SIZE - size, 0, 2, 1, &bitStream);
762 #else
763 		result = ov_read(&oggFile, data + size, OGG_BUFFER_SIZE - size, 1, 2, 1, &bitStream);
764 #endif
765 		if (result > 0)
766 			size += result;
767 		else if (result < 0 && result != OV_HOLE)		// OV_HOLE is informational
768 			ogg_error(result);
769 		else
770 			break;
771 	}
772 
773 	ov_clear(&oggFile);
774 
775 	*inFormat = format;
776 	*inSize = size;
777 	*inFreq = freq;
778 	return data;
779 }
780 
781 
782 /**************************
783  * SOUND STREAM FUNCTIONS *
784  **************************/
785 
get_stream_type(int type)786 static char * get_stream_type(int type)
787 {
788 	return type == STREAM_TYPE_MUSIC ? "Music" :
789 		(type == STREAM_TYPE_CROWD ? "Crowd" :
790 		(type == STREAM_TYPE_SOUNDS ? "Background" : "None"));
791 }
792 
play_stream(int sound,stream_data * stream,ALfloat gain)793 void play_stream(int sound, stream_data * stream, ALfloat gain)
794 {
795 	char * file;
796 	char tmp_file_name[80];
797 
798 	// Find the filename to play
799 	if (stream->type == STREAM_TYPE_MUSIC)
800 	{
801 		if (!have_music || sound<0 || sound>=MAX_PLAYLIST_ENTRIES) return;
802 
803 		if (playlist[sound].file_name[0]!='.' && playlist[sound].file_name[0]!='/')
804 			safe_snprintf (tmp_file_name, sizeof (tmp_file_name), "./music/%s", playlist[sound].file_name);
805 		else
806 			safe_snprintf(tmp_file_name, sizeof (tmp_file_name), "%s", playlist[sound].file_name);
807 		file = tmp_file_name;
808 	}
809 	else
810 	{
811 		if (sound<0 || sound>=MAX_SOUNDS || sound_type_data[sound].num_variants <= 0) return;
812 
813 		// Choose a variant
814 		stream->variant = rand() % sound_type_data[sound].num_variants;
815 		file = sound_type_data[sound].variant[stream->variant].part[STAGE_MAIN]->file_path;
816 		if (!have_sound || sound == -1 || !strcmp(file, "")) return;
817 	}
818 
819 	// Set the gain for this stream
820 	alSourcef(stream->source, AL_GAIN, gain * (stream->type == STREAM_TYPE_MUSIC ? 1.0f : sound_type_data[sound].variant[stream->variant].gain));
821 
822 	// Load the Ogg file and start the stream
823 	if (stream_ogg_file(file, stream, NUM_STREAM_BUFFERS) < 0)
824 	{
825 		LOG_ERROR("%s:%d stream_ogg_file() returned error so not playing", __FUNCTION__, __LINE__);
826 		stream->playing = 0;
827 	}
828 	stream->sound = sound;
829 }
830 
start_stream(stream_data * stream)831 int start_stream(stream_data * stream)
832 {
833 	int state = 0, error;
834 	alGetSourcei(stream->source, AL_SOURCE_STATE, &state);
835 	if (state != AL_PLAYING) {
836 		alSourcePlay(stream->source);
837 	}
838 	stream->playing = 1;
839 	if ((error = alGetError()) != AL_NO_ERROR)
840 	{
841 		LOG_ERROR("start_stream - Error starting stream - %s: %s", my_tolower(reg_error_str), alGetString(error));
842 		stream->playing = 0;
843 		return 0;
844 	}
845 	return 1;
846 }
847 
stop_stream(stream_data * stream)848 void stop_stream(stream_data * stream)
849 {
850 	ALuint buffer;
851 	int queued = 0, state = 0, error;
852 
853 	stream->playing = 0;
854 	alGetSourcei(stream->source, AL_SOURCE_STATE, &state);
855 	if (state != AL_PAUSED)
856 		alSourceStop(stream->source);
857 	alGetSourcei(stream->source, AL_BUFFERS_PROCESSED, &stream->processed);
858 	alGetSourcei(stream->source, AL_BUFFERS_QUEUED, &queued);
859 	while ((alGetError() == AL_NO_ERROR) && (queued-- > 0))
860 	{
861 		alSourceUnqueueBuffers(stream->source, 1, &buffer);
862 	}
863 	if ((error = alGetError()) != AL_NO_ERROR)
864 	{
865 		LOG_ERROR("stop_stream - Error stopping stream - %s: %s", my_tolower(reg_error_str), alGetString(error));
866 	}
867 }
868 
reset_stream(stream_data * stream)869 void reset_stream(stream_data * stream)
870 {
871 #ifdef _EXTRA_SOUND_DEBUG
872 //	printf("Resetting stream: Type: %s, sound: %d, cookie: %d, source: %d\n", get_stream_type(stream->type), stream->sound, stream->cookie, stream->source);
873 #endif // _EXTRA_SOUND_DEBUG
874 	// Reset the data (not sources or buffers)
875 	stream->playing = 0;
876 	stream->info = NULL;
877 	stream->processed = 0;
878 	stream->sound = -1;
879 	stream->is_default = 0;
880 	stream->boundary = NULL;
881 	stream->fade = 0;
882 	stream->fade_length = 10;
883 }
884 
init_sound_stream(stream_data * stream,int type,int priority)885 int init_sound_stream(stream_data * stream, int type, int priority)
886 {
887 	source_data * source;
888 	int error;
889 
890 	alGenBuffers(NUM_STREAM_BUFFERS, stream->buffers);
891 
892 	LOCK_SOUND_LIST();
893 	source = get_available_source(priority);
894 	if (!source || !alIsSource(source->source))
895 	{
896 		UNLOCK_SOUND_LIST();
897 		return 0;
898 	}
899 	// Set some details so non-streamed functions see this source as used
900 	source->cookie = get_next_cookie();
901 	source->current_stage = STAGE_STREAM;
902 	source->loaded_sound = 0;
903 	// Make sure the data for this stream is clean
904 	reset_stream(stream);
905 	stream->type = type;
906 	stream->source = source->source;
907 	stream->cookie = source->cookie;
908 	UNLOCK_SOUND_LIST();
909 
910 	// Reset the source details
911 	alSource3f(stream->source, AL_POSITION,        0.0, 0.0, 0.0);
912 	alSource3f(stream->source, AL_VELOCITY,        0.0, 0.0, 0.0);
913 	alSource3f(stream->source, AL_DIRECTION,       0.0, 0.0, 0.0);
914 	alSourcef (stream->source, AL_ROLLOFF_FACTOR,  0.0          );
915 	alSourcei (stream->source, AL_SOURCE_RELATIVE, AL_TRUE      );
916 	alSourcef (stream->source, AL_GAIN,            0.0);
917 	alSourcei (stream->source, AL_LOOPING,         AL_FALSE);
918 	alSourceStop(stream->source);
919 	alSourcei (stream->source, AL_BUFFER,          0);		// Make sure there are no buffers attached
920 
921 	// Reset the error buffer
922 	if ((error = alGetError()) != AL_NO_ERROR)
923 	{
924 #ifdef _EXTRA_SOUND_DEBUG
925 		printf("Error initalising stream: Type: %s, %s\n", get_stream_type(type), alGetString(error));
926 #endif // _EXTRA_SOUND_DEBUG
927 	}
928 
929 	return 1;
930 }
931 
destroy_stream(stream_data * stream)932 void destroy_stream(stream_data * stream)
933 {
934 	int error, i;
935 
936 #ifdef _EXTRA_SOUND_DEBUG
937 //	printf("Destroying stream: Type: %s, sound: %d, cookie: %d, source: %d\n", get_stream_type(stream->type), stream->sound, stream->cookie, stream->source);
938 #endif // _EXTRA_SOUND_DEBUG
939 	if (stream->type == STREAM_TYPE_NONE)
940 		return;			// In theory this stream isn't initialised
941 
942 	if (stream->playing)
943 	{
944 		stop_stream(stream);
945 	}
946 	if (stream->type == STREAM_TYPE_MUSIC)
947 	{
948 		music_stream = NULL;
949 	}
950 
951 	if (stream->cookie != 0)
952 	{
953 		// Find which of our playing sources matches the handle for this stream
954 		i = find_sound_source_from_cookie(stream->cookie);
955 		if (i >= 0)
956 		{
957 			stop_sound_source_at_index(i);
958 		}
959 	}
960 	stream->source = 0;
961 	stream->cookie = 0;
962 	reset_stream(stream);
963 	for (i = 0; i < NUM_STREAM_BUFFERS; i++)
964 	{
965 		if (alIsBuffer(stream->buffers[i]))
966 			alDeleteBuffers(1, stream->buffers+i);
967 	}
968 	if (stream->stream_opened)
969 	{
970 		ov_clear(&stream->stream);
971 		stream->stream_opened = 0;
972 	}
973 	stream->type = STREAM_TYPE_NONE;
974 
975 	// Reset the error buffer
976 	if ((error = alGetError()) != AL_NO_ERROR)
977 	{
978 #ifdef _EXTRA_SOUND_DEBUG
979 		printf("Error destroying stream: Type: %s, %s\n", get_stream_type(stream->type), alGetString(error));
980 #endif // _EXTRA_SOUND_DEBUG
981 	}
982 }
983 
984 /* add_stream
985  *
986  * Processes adding a new stream if possible
987  *
988  * sound		the sound to play in the stream
989  * type			the type of stream
990  * boundary		the map boundary def being used for this stream (-1 for default sounds)
991  */
add_stream(int sound,int type,int boundary)992 int add_stream(int sound, int type, int boundary)
993 {
994 	stream_data * stream = NULL;
995 	int priority = 0, i, default_found = -1, type_count = 0;
996 
997 	if (sound == -1)
998 		return 0;
999 
1000 	// Check we aren't creating another music stream if one exists
1001 	if (type == STREAM_TYPE_MUSIC && music_stream)
1002 	{
1003 		LOG_ERROR("Sound stream error: Tried to create additional music stream. This is a bug!\n");
1004 		return 0;
1005 	}
1006 
1007 	for (i = 0; i < max_streams; i++)
1008 	{
1009 		// Check this sound isn't already being played in a stream
1010 		if (streams[i].sound == sound && streams[i].type == type)
1011 		{
1012 			return 0;
1013 		}
1014 		if (streams[i].type == type)
1015 		{
1016 			// Count the number of streams of this type (for the priority calculation)
1017 			type_count++;
1018 			// Check if there is a default stream of this type that needs to be stopped
1019 			if (streams[i].is_default)
1020 			{
1021 				default_found = i;
1022 			}
1023 		}
1024 		// Find a spot in the array
1025 		if (!stream && streams[i].type == STREAM_TYPE_NONE)
1026 		{
1027 			stream = &streams[i];
1028 		}
1029 	}
1030 	if (!stream)
1031 	{
1032 		return 0;
1033 	}
1034 	// Calculate the priority of this stream (give the first 2 streams of this type top priority and then according to sound)
1035 	if (type_count > 2)
1036 		priority = sound_type_data[sound].priority;
1037 	else
1038 		priority = 1;
1039 
1040 	// Init the stream
1041 	if (!init_sound_stream(stream, type, priority))
1042 		return 0;			// We couldn't get a source. Sad but you get that.
1043 
1044 	// Play the stream
1045 	play_stream(sound, stream, 0.0f);		// Fade the stream up
1046 	if (!stream->playing)
1047 	{
1048 		// There was an error so remove the stream and bail
1049 #ifdef _EXTRA_SOUND_DEBUG
1050 		printf("add_stream: Eek, there was an error adding this stream! sound: %d\n", sound);
1051 #endif // _EXTRA_SOUND_DEBUG
1052 		LOCK_SOUND_LIST();
1053 		if (type == STREAM_TYPE_MUSIC)
1054 			destroy_stream(stream);
1055 		UNLOCK_SOUND_LIST();
1056 		return 0;
1057 	}
1058 	stream->type = type;
1059 	stream->fade = 1;
1060 	stream->fade_length = 10;
1061 	if (boundary == -1)
1062 	{
1063 		stream->is_default = 1;
1064 		stream->boundary = NULL;
1065 	}
1066 	else
1067 	{
1068 		stream->boundary = &sound_map_data[snd_cur_map].boundaries[boundary];
1069 		stream->is_default = 0;
1070 	}
1071 #ifdef _EXTRA_SOUND_DEBUG
1072 	printf("add_stream: Started stream. Type: %s, Sound: %d, Cookie: %u, Source: %d, Fade: %d, Default: %d\n", get_stream_type(stream->type), stream->sound, stream->cookie, stream->source, stream->fade, stream->is_default);
1073 #endif // _EXTRA_SOUND_DEBUG
1074 	// If this is the music stream, set the pointer
1075 	if (type == STREAM_TYPE_MUSIC)
1076 		music_stream = stream;
1077 	// We have definitely started this stream so stop any default we found
1078 	if (default_found > -1)
1079 		streams[default_found].fade = -1;
1080 
1081 	return 1;		// Return success
1082 }
1083 
check_for_valid_stream_sound(int tx,int ty,int type)1084 int check_for_valid_stream_sound(int tx, int ty, int type)
1085 {
1086 	int i, j, snd = -1, playing, found = 0;
1087 
1088 	if (snd_cur_map > -1 && (sound_map_data[snd_cur_map].file_name[0] != '\0' || sound_map_data[snd_cur_map].id > -1) )
1089 	{
1090 		for (i = 0; i < sound_map_data[snd_cur_map].num_boundaries; i++)
1091 		{
1092 			if (i == sound_map_data[snd_cur_map].num_boundaries)
1093 				i = 0;
1094 			if (type == STREAM_TYPE_SOUNDS)
1095 			{
1096 				snd = sound_map_data[snd_cur_map].boundaries[i].bg_sound;
1097 			}
1098 			else if (type == STREAM_TYPE_CROWD)
1099 			{
1100 				snd = sound_map_data[snd_cur_map].boundaries[i].crowd_sound;
1101 			}
1102 			if (snd > -1 && sound_bounds_check(tx, ty, &sound_map_data[snd_cur_map].boundaries[i]))
1103 			{
1104 				playing = 0;
1105 				for (j = 0; j < max_streams; j++)
1106 				{
1107 					if (streams[j].sound == snd)
1108 						playing = 1;
1109 				}
1110 				if (!playing)
1111 				{
1112 #ifdef _EXTRA_SOUND_DEBUG
1113 					printf("Starting stream (%s) sound: %d, boundary: %d\n", get_stream_type(type), snd, i);
1114 #endif //_EXTRA_SOUND_DEBUG
1115 					add_stream(snd, type, i);
1116 					found = 1;
1117 				}
1118 			}
1119 		}
1120 	}
1121 	return found;
1122 }
1123 
check_for_new_streams(int tx,int ty)1124 void check_for_new_streams(int tx, int ty)
1125 {
1126 	int i, found_bg = 0, found_crowd = 0;
1127 
1128 	found_bg = check_for_valid_stream_sound(tx, ty, STREAM_TYPE_SOUNDS);
1129 	if (no_near_enhanced_actors >= 5)
1130 		found_crowd = check_for_valid_stream_sound(tx, ty, STREAM_TYPE_CROWD);
1131 
1132 	if (!found_bg && !found_crowd)
1133 	{
1134 
1135 #ifdef _EXTRA_SOUND_DEBUG
1136 //		printf("check_for_new_streams - Checking if we need a default background/crowd sound. Pos: %d, %d\n", tx, ty);
1137 #endif //_EXTRA_SOUND_DEBUG
1138 
1139 		// Check if we need a default background or default crowd sound (no other bg/crowd sounds, or they are fading out)
1140 		for (i = 0; i < max_streams; i++)
1141 		{
1142 			if (no_near_enhanced_actors < 5 || (streams[i].type == STREAM_TYPE_CROWD && streams[i].fade >= 0))
1143 				found_crowd = 1;		// We have a crowd sound already (or don't need one) so we don't need a default one
1144 			if (streams[i].type == STREAM_TYPE_SOUNDS && streams[i].fade >= 0)
1145 				found_bg = 1;		// We have a bg sound already so we don't need a default one
1146 			if (found_bg && found_crowd)
1147 				return;		// We have both so we don't need to continue
1148 		}
1149 
1150 #ifdef _EXTRA_SOUND_DEBUG
1151 //		printf("check_for_new_streams - Background found: %s, Crowd found: %s. Checking for defaults for this map\n", found_bg == 0 ? "No" : "Yes", found_crowd == 0 ? "No" : "Yes");
1152 #endif //_EXTRA_SOUND_DEBUG
1153 
1154 		// We still aren't playing a sound for one type, so check for a map based sound
1155 		if ((snd_cur_map > -1) && (sound_map_data[snd_cur_map].num_defaults > 0))
1156 		{
1157 			map_sound_data * cur_map = &sound_map_data[snd_cur_map];
1158 			for (i = 0; i < cur_map->num_defaults; i++)
1159 			{
1160 				if (!found_bg && time_of_day_valid(cur_map->boundaries[cur_map->defaults[i]].time_of_day_flags) &&
1161 					cur_map->boundaries[cur_map->defaults[i]].bg_sound > -1)
1162 				{
1163 #ifdef _EXTRA_SOUND_DEBUG
1164 //					printf("check_for_new_streams - Playing map default background sound: %d\n", cur_map->boundaries[cur_map->defaults[i]].bg_sound);
1165 #endif //_EXTRA_SOUND_DEBUG
1166 					add_stream(cur_map->boundaries[cur_map->defaults[i]].bg_sound, STREAM_TYPE_SOUNDS, -1);
1167 					found_bg = 1;
1168 				}
1169 				if (!found_crowd && time_of_day_valid(cur_map->boundaries[cur_map->defaults[i]].time_of_day_flags) &&
1170 					cur_map->boundaries[cur_map->defaults[i]].crowd_sound > -1)
1171 				{
1172 #ifdef _EXTRA_SOUND_DEBUG
1173 					printf("check_for_new_streams - Playing map default crowd sound: %d\n", cur_map->boundaries[cur_map->defaults[i]].crowd_sound);
1174 #endif //_EXTRA_SOUND_DEBUG
1175 					add_stream(cur_map->boundaries[cur_map->defaults[i]].crowd_sound, STREAM_TYPE_CROWD, -1);
1176 					found_crowd = 1;
1177 				}
1178 				if (found_bg && found_crowd)
1179 					break;
1180 			}
1181 		}
1182 
1183 		// Check if we need to find a global default background
1184 		if (!found_bg && sound_num_background_defaults > 0)
1185 		{
1186 #ifdef _EXTRA_SOUND_DEBUG
1187 //			printf("check_for_new_streams - No map defaults found, checking for global defaults\n");
1188 #endif //_EXTRA_SOUND_DEBUG
1189 			for (i = 0; i < sound_num_background_defaults; i++)
1190 			{
1191 				if (time_of_day_valid(sound_background_defaults[i].time_of_day_flags) &&
1192 					(sound_background_defaults[i].map_type == dungeon && sound_background_defaults[i].sound > -1))
1193 				{
1194 #ifdef _EXTRA_SOUND_DEBUG
1195 //					printf("check_for_new_streams - Playing default background sound: %d\n", sound_background_defaults[i].sound);
1196 #endif //_EXTRA_SOUND_DEBUG
1197 					add_stream(sound_background_defaults[i].sound, STREAM_TYPE_SOUNDS, -1);
1198 					break;
1199 				}
1200 			}
1201 		}
1202 
1203 		// If we still aren't playing a crowd sound, check for a global default
1204 		if (!found_crowd && crowd_default > -1)
1205 		{
1206 #ifdef _EXTRA_SOUND_DEBUG
1207 			printf("check_for_new_streams - Playing default crowd sound: %d\n", crowd_default);
1208 #endif //_EXTRA_SOUND_DEBUG
1209 			add_stream(crowd_default, STREAM_TYPE_CROWD, -1);
1210 		}
1211 	}
1212 }
1213 
process_stream(stream_data * stream,ALfloat gain,int * sleep)1214 int process_stream(stream_data * stream, ALfloat gain, int * sleep)
1215 {
1216 	int error, state = AL_STOPPED;	// , state2;
1217 	ALfloat new_gain = gain;
1218 	ALuint buffer;
1219 
1220 	// Check if we are starting/stopping this stream and continue the fade
1221 	if (stream->fade < 0)
1222 	{
1223 		new_gain = gain - ((float)(-stream->fade) * (gain / stream->fade_length));
1224 #ifdef _EXTRA_SOUND_DEBUG
1225 		printf("Doing stream fade - stream: %s, sound: %d, fade: %d, gain: %f\n", get_stream_type(stream->type), stream->sound, stream->fade, new_gain);
1226 #endif // _EXTRA_SOUND_DEBUG
1227 		stream->fade -= 1;
1228 	}
1229 	else if (stream->fade > 0)
1230 	{
1231 		new_gain = gain - ((float)(stream->fade_length - stream->fade) * (gain / stream->fade_length));
1232 #ifdef _EXTRA_SOUND_DEBUG
1233 		printf("Doing stream fade - stream: %s, sound: %d, fade: %d, gain: %f\n", get_stream_type(stream->type), stream->sound, stream->fade, new_gain);
1234 #endif // _EXTRA_SOUND_DEBUG
1235 		stream->fade += 1;
1236 	}
1237 
1238 	// Check if we need to dim down the sounds due to rain
1239 	if (stream->type != STREAM_TYPE_MUSIC)
1240 	{
1241 		new_gain = weather_adjust_gain(new_gain, -1);
1242 #ifdef _EXTRA_SOUND_DEBUG
1243 //		if (new_gain != gain)
1244 //			printf("Volume adjusted by fade/weather for stream %s - Original gain: %f, New gain: %f\n", get_stream_type(stream->type), gain, new_gain);
1245 #endif // _EXTRA_SOUND_DEBUG
1246 	}
1247 
1248 	alSourcef(stream->source, AL_GAIN, new_gain);
1249 	if ((error=alGetError()) != AL_NO_ERROR)
1250 	{
1251 #ifdef _EXTRA_SOUND_DEBUG
1252 		printf("process_stream - Error setting gain: %s, Stream type: %s, Source: %d\n", alGetString(error), get_stream_type(stream->type), stream->source);
1253 #endif // _EXTRA_SOUND_DEBUG
1254 	}
1255 
1256 	// Process the next portion of the stream
1257 	alGetSourcei(stream->source, AL_BUFFERS_PROCESSED, &stream->processed);
1258 	if ((error=alGetError()) != AL_NO_ERROR)
1259 	{
1260 #ifdef _EXTRA_SOUND_DEBUG
1261 		printf("process_stream - Error retrieving buffers processed value: %s, Stream type: %s, Source: %d\n", alGetString(error), get_stream_type(stream->type), stream->source);
1262 #endif // _EXTRA_SOUND_DEBUG
1263 	}
1264 	if (!stream->processed)
1265 	{
1266 		if (*sleep < SLEEP_TIME)
1267 			*sleep += (SLEEP_TIME / 100);
1268 		return 1; // Skip error checking et al
1269 	}
1270 	while (stream->processed-- > 0)
1271 	{
1272 		alSourceUnqueueBuffers(stream->source, 1, &buffer);
1273 		if ((error = alGetError()) != AL_NO_ERROR)
1274 			LOG_ERROR("process_stream - Error unqueuing buffers: %s, Stream type: %s, Source: %d", alGetString(error), get_stream_type(stream->type), stream->source);
1275 
1276 		stream->playing = stream_ogg(buffer, &stream->stream, stream->info);
1277 
1278 		if (stream->playing)
1279 		{
1280 			alSourceQueueBuffers(stream->source, 1, &buffer);
1281 			if ((error = alGetError()) != AL_NO_ERROR)
1282 				LOG_ERROR("process_stream - Error requeuing buffers: %s, Stream type: %s, Source: %d, Playing: %s", alGetString(error), get_stream_type(stream->type), stream->source, stream->playing == 0 ? "No" : "Yes");
1283 		}
1284 	}
1285 
1286 	// Check if the stream is still playing, and handle if not
1287 	alGetSourcei(stream->source, AL_SOURCE_STATE, &state);
1288 	if ((error=alGetError()) != AL_NO_ERROR)
1289 	{
1290 #ifdef _EXTRA_SOUND_DEBUG
1291 		printf("process_stream - Error retrieving state: %s, Stream type: %s, Source: %d\n", alGetString(error), get_stream_type(stream->type), stream->source);
1292 #endif // _EXTRA_SOUND_DEBUG
1293 	}
1294 	if (state != AL_PLAYING)
1295 	{
1296 		LOG_TO_CONSOLE(c_red1, snd_skip_speedup);
1297 #ifdef _EXTRA_SOUND_DEBUG
1298 		printf("process_stream - Stream Skip!! Sleep: %d\n", *sleep);
1299 #endif //_EXTRA_SOUND_DEBUG
1300 		// Let streams skip up to 10 times. If it skips more, then stop the music/sound (not the best option).
1301 		if (*sleep > (SLEEP_TIME / 10))
1302 			*sleep -= (SLEEP_TIME / 10);
1303 		else if (*sleep > 1) *sleep = 1;
1304 		else
1305 		{
1306 			LOG_TO_CONSOLE(c_red1, snd_too_slow);
1307 			LOG_ERROR(snd_too_slow);
1308 			if (stream->type == STREAM_TYPE_MUSIC)
1309 				turn_music_off();
1310 			else
1311 				turn_sound_off();
1312 			*sleep = SLEEP_TIME;
1313 			return 0;
1314 		}
1315 		alSourcePlay(stream->source);
1316 	}
1317 
1318 	// Check if the stream has finished and needs to be requeued
1319 	if (!stream->playing)
1320 	{
1321 		// Clear any remaining buffers, just in case
1322 		alSourceStop(stream->source);
1323 		alSourcei(stream->source, AL_BUFFER, 0);
1324 		if ((error=alGetError()) != AL_NO_ERROR) { }	// Clear any errors before trying to replay the stream
1325 		play_stream(stream->sound, stream, gain);
1326 	}
1327 
1328 	// Clear any OpenAL errors
1329 	if ((error=alGetError()) != AL_NO_ERROR)
1330 	{
1331 #ifdef _EXTRA_SOUND_DEBUG
1332 		printf("process_stream - OpenAL error: %s, Stream type: %s, Source: %d\n", alGetString(error), get_stream_type(stream->type), stream->source);
1333 #endif // _EXTRA_SOUND_DEBUG
1334 	}
1335 
1336 	return 1;
1337 }
1338 
check_stream(stream_data * stream,int day_time,int tx,int ty)1339 int check_stream(stream_data * stream, int day_time, int tx, int ty)
1340 {
1341 	// Check if we have finished fading this stream down and can stop it
1342 	if (stream->fade < -stream->fade_length)
1343 	{
1344 		stop_stream(stream);
1345 		// If this stream isn't the music stream then destroy it
1346 		if (stream->type != STREAM_TYPE_MUSIC)
1347 		{
1348 			LOCK_SOUND_LIST();
1349 			destroy_stream(stream);
1350 			UNLOCK_SOUND_LIST();
1351 		}
1352 		return 0;		// Stream is not continuing
1353 	}
1354 	// Check if we have finished fading this stream up and can stop the fade
1355 	else if (stream->fade > stream->fade_length)
1356 	{
1357 		stream->fade = 0;
1358 	}
1359 
1360 	// Check if we need to trigger a stop in this stream
1361 	if (stream->fade >= 0)
1362 	{
1363 		switch (stream->type)
1364 		{
1365 			case STREAM_TYPE_MUSIC:
1366 				if ((list_pos >= 0) && playlist[list_pos].file_name[0] && (tx < playlist[list_pos].min_x ||
1367 				   tx > playlist[list_pos].max_x ||
1368 				   ty < playlist[list_pos].min_y ||
1369 				   ty > playlist[list_pos].max_y ||
1370 				   (playlist[list_pos].time != 2 &&
1371 					playlist[list_pos].time != day_time)))
1372 				{
1373 					stream->fade = -1;
1374 				}
1375 				break;
1376 			case STREAM_TYPE_SOUNDS:
1377 			case STREAM_TYPE_CROWD:
1378 				if (stream->type == STREAM_TYPE_CROWD && no_near_enhanced_actors < 2)
1379 				{
1380 					// Don't stop until there are less than 2 people around so it will fade down more naturally
1381 					stream->fade = -1;
1382 				}
1383 				if (stream->is_default)
1384 				{
1385 #ifdef _EXTRA_SOUND_DEBUG
1386 //					printf("process_stream - Checking for valid %s sound. Pos: %d, %d\n", get_stream_type(stream->type), tx, ty);
1387 #endif //_EXTRA_SOUND_DEBUG
1388 					if (check_for_valid_stream_sound(tx, ty, stream->type))
1389 						stream->fade = -1;
1390 				}
1391 				else
1392 				{
1393 					if (!sound_bounds_check(tx, ty, stream->boundary))
1394 					{
1395 #ifdef _EXTRA_SOUND_DEBUG
1396 						printf("process_stream - %s sound failed bounds check. Pos: %d, %d\n", get_stream_type(stream->type), tx, ty);
1397 #endif //_EXTRA_SOUND_DEBUG
1398 						stream->fade = -1;
1399 					}
1400 				}
1401 				break;
1402 		}
1403 	}
1404 
1405 	return 1;		// Stream is continuing (but may be fading down)
1406 }
1407 
update_streams(void * dummy)1408 int update_streams(void * dummy)
1409 {
1410     int sleep, day_time, i, tx, ty;
1411 	ALfloat gain = 0.0;
1412 
1413    	sleep = SLEEP_TIME;
1414 
1415 	init_thread_log("update_streams");
1416 
1417 #ifdef _EXTRA_SOUND_DEBUG
1418 	printf("Starting streams thread\n");
1419 #endif //_EXTRA_SOUND_DEBUG
1420 	while (!exit_now && ((have_music && music_on) || (have_sound && sound_on)))
1421 	{
1422 		SDL_Delay(sleep);
1423 
1424 		day_time = (game_minute >= 30 && game_minute < 60 * 3 + 30);
1425 
1426 		LOCK_ACTORS_LISTS();
1427 		// Get our position
1428 		if (your_actor)
1429 		{
1430 			tx = your_actor->x_pos * 2;
1431 			ty = your_actor->y_pos * 2;
1432 		}
1433 		else
1434 		{
1435 			tx = 0;
1436 			ty = 0;
1437 		}
1438 		if (have_a_map && (tx > 0 || ty > 0))
1439 		{
1440 			// Check if we need to start or stop any streams
1441 			if (have_music && music_on && (!music_stream || !music_stream->playing))
1442 			{
1443 				find_next_song(tx, ty, day_time);
1444 			}
1445 			if (have_sound && sound_on)
1446 			{
1447 				check_for_new_streams(tx, ty);
1448 			}
1449 
1450 			// Handle the streams
1451 			LOCK_SOUND_LIST();
1452 			for (i = 0; i < max_streams; i++)
1453 			{
1454 				if (streams[i].playing)
1455 				{
1456 					switch (streams[i].type)
1457 					{
1458 						case STREAM_TYPE_MUSIC:
1459 							if (!have_music || !music_on)
1460 								continue;			// We aren't playing music so skip this stream
1461 							gain = music_gain;
1462 							break;
1463 						case STREAM_TYPE_SOUNDS:
1464 							if (!have_sound || !sound_on)
1465 								continue;			// We aren't playing sounds so skip this stream
1466 							gain = sound_gain * enviro_gain * sound_type_data[streams[i].sound].variant[streams[i].variant].gain;
1467 							break;
1468 						case STREAM_TYPE_CROWD:
1469 							if (!have_sound || !sound_on)
1470 								continue;			// We aren't playing sounds so skip this stream
1471 							if (distanceSq_to_near_enhanced_actors == 0)
1472 								distanceSq_to_near_enhanced_actors = 100.0f;	// Due to no actors when calc'ing
1473 // SSE optimized sqrt		gain = sound_gain * crowd_gain * sound_type_data[streams[i].sound].variant[streams[i].variant].gain
1474 // 									* fastsqrt(fastsqrt(no_near_enhanced_actors)) * invsqrt(distanceSq_to_near_enhanced_actors) * 2;
1475 							gain = sound_gain * crowd_gain * sound_type_data[streams[i].sound].variant[streams[i].variant].gain
1476 									* sqrt(sqrt(no_near_enhanced_actors)) / sqrt(distanceSq_to_near_enhanced_actors) * 2;
1477 							break;
1478 					}
1479 					if (check_stream(&streams[i], day_time, tx, ty))
1480 						process_stream(&streams[i], gain, &sleep);
1481 				}
1482 			}
1483 			UNLOCK_SOUND_LIST();
1484 		}
1485 		UNLOCK_ACTORS_LISTS();
1486 	}
1487 #ifdef _EXTRA_SOUND_DEBUG
1488 	printf("Exiting streams thread. have_music: %d, music_on: %d, have_sound: %d, sound_on: %d, exit_now: %d\n", have_music, music_on, have_sound, sound_on, exit_now);
1489 #endif //_EXTRA_SOUND_DEBUG
1490 	return 1;
1491 }
1492 
1493 
1494 
1495 
1496 /*******************
1497  * MUSIC FUNCTIONS *
1498  *******************/
1499 
get_map_playlist()1500 void get_map_playlist()
1501 {
1502 	int i=0, len;
1503 	char map_list_file_name[256];
1504 	char tmp_buf[1024];
1505 	FILE *fp;
1506 	char strLine[255];
1507 	char *tmp;
1508 	// NOTE: keep the max length in this format line in sync with
1509 	// the size of tmp_buf
1510 	static const char pl_line_fmt[] = "%d %d %d %d %d %1023s";
1511 
1512 	if(!have_music)return;
1513 
1514 	clear_playlist();
1515 
1516 	tmp = strrchr (map_file_name, '/');
1517 	if (tmp == NULL)
1518 		tmp = map_file_name;
1519 	else
1520 		tmp++;
1521 	safe_snprintf (map_list_file_name, sizeof (map_list_file_name), "music/%s", tmp);
1522 	len = strlen (map_list_file_name);
1523 	tmp = strrchr (map_list_file_name, '.');
1524 	if (tmp == NULL)
1525 		tmp = &map_list_file_name[len];
1526 	else
1527 		tmp++;
1528 	len -= strlen (tmp);
1529 	safe_snprintf (tmp, sizeof (map_list_file_name) - len, "pll");
1530 
1531 	fp=open_file_data(map_list_file_name,"r");
1532 	if (fp == NULL) return;
1533 
1534 	while(1)
1535 	{
1536 		if (fscanf (fp, pl_line_fmt, &playlist[i].min_x, &playlist[i].min_y, &playlist[i].max_x, &playlist[i].max_y, &playlist[i].time, tmp_buf) == 6)
1537 		{
1538 			// check for a comment
1539 			tmp = strstr (tmp_buf, "--");
1540 			if (tmp)
1541 			{
1542 				*tmp = '\0';
1543 				len = strlen (tmp_buf);
1544 				while (len > 0 && isspace (tmp_buf[len-1]))
1545 				{
1546 					len--;
1547 					tmp_buf[len]= '\0';
1548 				}
1549 			}
1550 			safe_strncpy (playlist[i].file_name, tmp_buf, MAX_PLAYLIST_FILENAME);
1551 			playlist[i].file_name[MAX_PLAYLIST_FILENAME-1]= '\0';
1552 			if (++i >= MAX_PLAYLIST_ENTRIES)
1553 				break;
1554 		}
1555 		if (!fgets (strLine, 100, fp)) break;
1556 	}
1557 	fclose(fp);
1558 	loop_list=1;
1559 	list_pos=-1;
1560 }
1561 
play_music(int list)1562 void play_music(int list)
1563 {
1564 	int i=0;
1565 	char list_file_name[256];
1566 	FILE *fp;
1567 	char strLine[255];
1568 
1569 	if(!have_music)return;
1570 
1571 	clear_playlist();
1572 
1573 	safe_snprintf(list_file_name, sizeof(list_file_name), "music/%d.pll", list);
1574 	fp=open_file_data(list_file_name, "r");
1575 	if(!fp)return;
1576 
1577 	while (1)
1578 	{
1579 		if (fscanf (fp, "%254s", strLine) == 1)
1580 		{
1581 			safe_strncpy(playlist[i].file_name, strLine, MAX_PLAYLIST_FILENAME);
1582 			playlist[i].min_x = 0;
1583 			playlist[i].min_y = 0;
1584 			playlist[i].max_x = 10000;
1585 			playlist[i].max_y = 10000;
1586 			playlist[i].time = 2;
1587 			if (++i > MAX_PLAYLIST_ENTRIES)
1588 				break;
1589 			if (!fgets (strLine, 100, fp))
1590 				break;
1591 		}
1592 	}
1593 	fclose(fp);
1594 	loop_list=0;
1595 	list_pos=0;
1596 	play_song(list_pos);
1597 }
1598 
display_song_name()1599 int display_song_name()
1600 {
1601 	if (!music_stream || !music_stream->playing)
1602 	{
1603 		LOG_TO_CONSOLE(c_grey1, snd_media_music_stopped);
1604 	}
1605 	else
1606 	{
1607 		char musname[100];
1608 		int t_played_min, t_played_sec, t_total_min, t_total_sec;
1609 		char *title = NULL, *artist = NULL;
1610 		int i=0;
1611 		vorbis_comment *comments;
1612 
1613 		t_played_min = (int)(ov_time_tell(&music_stream->stream) / 60);
1614 		t_played_sec = (int)ov_time_tell(&music_stream->stream) % 60;
1615 		t_total_min = (int)(ov_time_total(&music_stream->stream, -1) / 60);
1616 		t_total_sec = (int)ov_time_total(&music_stream->stream, -1) % 60;
1617 
1618 		comments = ov_comment(&music_stream->stream, -1);
1619 		if(comments == NULL)
1620 		{
1621 			safe_snprintf(musname, sizeof(musname), snd_media_ogg_info_noartist, playlist[list_pos].file_name, t_played_min, t_played_sec, t_total_min, t_total_sec);
1622 			LOG_TO_CONSOLE(c_grey1, musname);
1623 			return 1;
1624 		}
1625 		for (; i < comments->comments; ++i)
1626 		{
1627 			if ((artist == NULL) && (comments->comment_lengths[i] > 6) && (!strncasecmp(comments->user_comments[i],"artist", 6)))
1628 			{
1629 				artist = comments->user_comments[i] + 7;
1630 				if(title)
1631 					break;
1632 			}
1633 			else if ((title == NULL) && (comments->comment_lengths[i] > 6) && (!strncasecmp(comments->user_comments[i],"title", 5)))
1634 			{
1635 				title = comments->user_comments[i] + 6;
1636 				if(artist)
1637 					break;
1638 			}
1639 		}
1640 		if (artist && title)
1641 		{
1642 			safe_snprintf(musname, sizeof(musname), snd_media_ogg_info, title, artist, t_played_min, t_played_sec, t_total_min, t_total_sec);
1643 		}
1644 		else if (title)
1645 		{
1646 			safe_snprintf(musname, sizeof(musname), snd_media_ogg_info_noartist, title, t_played_min, t_played_sec, t_total_min, t_total_sec);
1647 		}
1648 		else
1649 		{
1650 			safe_snprintf(musname, sizeof(musname), snd_media_ogg_info_noartist, playlist[list_pos].file_name, t_played_min, t_played_sec, t_total_min, t_total_sec);
1651 		}
1652 		LOG_TO_CONSOLE(c_grey1, musname);
1653 	}
1654 	return 1;
1655 }
1656 
play_song(int list_pos)1657 void play_song(int list_pos)
1658 {
1659 	// Find the music stream
1660 	if (music_stream)
1661 	{
1662 		play_stream(list_pos, music_stream, 0.0f);
1663 		music_stream->fade = 1;
1664 		return;
1665 	}
1666 	// Don't have a music stream yet so create one
1667 	add_stream(list_pos, STREAM_TYPE_MUSIC, -1);
1668 }
1669 
find_next_song(int tx,int ty,int day_time)1670 void find_next_song(int tx, int ty, int day_time)
1671 {
1672 	if (playlist[list_pos+1].file_name[0])
1673 	{
1674 		list_pos++;
1675 		if (tx > playlist[list_pos].min_x &&
1676 		   tx < playlist[list_pos].max_x &&
1677 		   ty > playlist[list_pos].min_y &&
1678 		   ty < playlist[list_pos].max_y &&
1679 		   (playlist[list_pos].time == 2 ||
1680 			playlist[list_pos].time == day_time))
1681 		{
1682 			// Found a song so play it
1683 			play_song(list_pos);
1684 		}
1685 	}
1686 	else if (loop_list)
1687 		list_pos = -1;
1688 	else
1689 		get_map_playlist();
1690 }
1691 
1692 
1693 
1694 
1695 /*****************************
1696  * SOURCE HANDLING FUNCTIONS *
1697  *****************************/
add_source_to_lists(source_data * pSource)1698 static void add_source_to_lists(source_data *pSource)
1699 {
1700 	int samples[num_STAGES];
1701 	int nr_samples = 0;
1702 	int i;
1703 	source_list *new_source_id;
1704 
1705 	for (i = 0; i < num_STAGES; i++)
1706 	{
1707 		if (pSource->sample[i] > -1)
1708 			samples[nr_samples++] = pSource->sample[i];
1709 	}
1710 
1711 	if (nr_samples == 0)
1712 		return;
1713 
1714 	new_source_id = calloc(1, sizeof(source_list));
1715 	new_source_id->source = pSource->source;
1716 	new_source_id->next = NULL;
1717 	new_source_id->last = NULL;
1718 
1719 	for (i = 0; i < nr_samples; i++)
1720 	{
1721 		// Get the current list of sources for this sample
1722 		source_list *source_id = sound_sample_data[samples[i]].sources;
1723 		if (source_id)
1724 		{
1725 			// Find the end of the list and add this source to it
1726 			while (source_id->next)
1727 				source_id = source_id->next;
1728 			source_id->next = new_source_id;
1729 			new_source_id->last = source_id;
1730 		}
1731 		else
1732 		{
1733 			// Create this source as the start of the list
1734 			sound_sample_data[samples[i]].sources = new_source_id;
1735 		}
1736 	}
1737 }
1738 
remove_source_from_lists(source_data * pSource)1739 static void remove_source_from_lists(source_data *pSource)
1740 {
1741 	int i;
1742 	source_list *source_id;
1743 
1744 	for (i = 0; i < num_STAGES; i++)
1745 	{
1746 		if (pSource->sample[i] > -1)
1747 		{
1748 			for (source_id = sound_sample_data[pSource->sample[i]].sources;
1749 				source_id; source_id = source_id->next)
1750 			{
1751 				if (source_id->source == pSource->source)
1752 					break;
1753 			}
1754 
1755 			if (source_id)
1756 			{
1757 				if (source_id->next)
1758 					source_id->next->last = source_id->last;
1759 				if (source_id->last)
1760 					source_id->last->next = source_id->next;
1761 				else
1762 					sound_sample_data[pSource->sample[i]].sources = source_id->next;
1763 				free(source_id);
1764 			}
1765 		}
1766 	}
1767 }
1768 
clear_source(source_data * pSource)1769 void clear_source(source_data *pSource)
1770 {
1771 	// Reset the source
1772 	if (pSource->source > 0)
1773 	{
1774 		alSourceStop(pSource->source);
1775 		alSourcei(pSource->source, AL_BUFFER, 0);
1776 	}
1777 	// If this source is attached to samples, clear it from their list
1778 	remove_source_from_lists(pSource);
1779 	// Reset the details of this source
1780 	pSource->priority = 0;
1781 	pSource->play_duration = 0;
1782 	pSource->current_stage = STAGE_UNUSED;
1783 	pSource->loaded_sound = -1;
1784 	pSource->cookie = 0;
1785 	pSource->sample[STAGE_INTRO] = -1;
1786 	pSource->sample[STAGE_MAIN] = -1;
1787 	pSource->sample[STAGE_OUTRO] = -1;
1788 }
1789 
get_available_source(int priority)1790 source_data * get_available_source(int priority)
1791 {
1792 	source_data * pSource;
1793 	int i;
1794 
1795 	if (used_sources == max_sources)
1796 		return NULL;
1797 
1798 	// Search for an available source. The sources are ordered by decreasing play priority
1799 	for (pSource = sound_source_data, i = 0; i < max_sources - 1; ++i, ++pSource)
1800 	{
1801 		if (pSource->loaded_sound < 0 && pSource->current_stage != STAGE_STREAM)
1802 		{
1803 #ifdef _EXTRA_SOUND_DEBUG
1804 			printf("Found available source at index %d/%d, Source: %d\n", i, used_sources, pSource->source);
1805 #endif //_EXTRA_SOUND_DEBUG
1806 			pSource->priority = priority;
1807 			used_sources++;
1808 			return pSource;
1809 		}
1810 		else if (priority <= pSource->priority)
1811 		{
1812 #ifdef _EXTRA_SOUND_DEBUG
1813 			printf("Inserting new source at index %d/%d", i, used_sources);
1814 #endif //_EXTRA_SOUND_DEBUG
1815 			pSource = insert_sound_source_at_index(i);
1816 #ifdef _EXTRA_SOUND_DEBUG
1817 			printf(", Source: %d\n", pSource->source);
1818 #endif //_EXTRA_SOUND_DEBUG
1819 			pSource->priority = priority;
1820 			used_sources++;
1821 			return pSource;
1822 		}
1823 	}
1824 
1825 	// All sources are used by higher-priority sounds
1826 	return NULL;
1827 }
1828 
1829 // This takes a copy the first unused source object (or last one in the list if all used),
1830 // moves all objects after #index along one place, and inserts the copied object at #index;
1831 // It is ensured the source at #index is stopped with no buffers queued
insert_sound_source_at_index(unsigned int index)1832 source_data *insert_sound_source_at_index(unsigned int index)
1833 {
1834 	int i;
1835 	source_data tempSource;
1836 	// Take a copy of the source about to be overwritten
1837 	tempSource = sound_source_data[min2i(used_sources, max_sources - 1)];
1838 	// Ensure it is stopped and ready
1839 	clear_source(&tempSource);
1840 
1841 	// Shunt source objects down a place
1842 	for (i = min2i(used_sources, max_sources - 1); i > index; --i)
1843 	{
1844 		sound_source_data[i] = sound_source_data[i - 1];
1845 	}
1846 
1847 	// Now insert our stored object at #index
1848 	sound_source_data[index] = tempSource;
1849 
1850 	// Return a pointer to this new source
1851 	return &sound_source_data[index];
1852 }
1853 
release_source(source_data * pSource,int index)1854 void release_source(source_data *pSource, int index)
1855 {
1856 	source_data sourceTemp;
1857 
1858 	// Check we have the index for this source
1859 	if (index == -1)
1860 		for (index = 0; &sound_source_data[index] != pSource; index++) {}
1861 	// Reset the data for this source
1862 	clear_source(pSource);
1863 	// We can't lose a source handle - copy this...
1864 	sourceTemp = *pSource;
1865 	//...shift all the next sources up a place, overwriting the stopped source...
1866 	memmove(pSource, pSource+1, sizeof(source_data) * (used_sources - (index + 1)));
1867 	//...and put the saved object back in after them
1868 	sound_source_data[used_sources - 1] = sourceTemp;
1869 	// Note that one less source is playing!
1870 	--used_sources;
1871 }
1872 
1873 // This stops the source for sound_source_data[index]. Because this array will change, the index
1874 // associated with a source will change, so this function should only be called if the index is
1875 // known for certain.
stop_sound_source_at_index(int index)1876 int stop_sound_source_at_index(int index)
1877 {
1878 	ALuint error = AL_NO_ERROR;
1879 	source_data *pSource;
1880 
1881 	if (index < 0 || index >= used_sources)
1882 	{
1883 #ifdef _EXTRA_SOUND_DEBUG
1884 		printf("Trying to unload invalid source! Index: %d, Num Sources: %d\n", index, used_sources);
1885 #endif //_EXTRA_SOUND_DEBUG
1886 		return 0;
1887 	}
1888 
1889 	// This should not happen
1890 	if (index >= max_sources)
1891 	{
1892 		LOG_ERROR("Trying to unload invalid source! Index: %d, Num Sources: %d, Max Sources: %d\n", index, used_sources, max_sources);
1893 		return 0;
1894 	}
1895 
1896 	pSource = &sound_source_data[index];
1897 
1898 	// Error if source is invalid (lost)
1899 	if (!alIsSource(sound_source_data[index].source))
1900 	{
1901    		LOG_ERROR("Attempting to stop invalid sound source %d with index %d", (int)pSource->source, index);
1902 	}
1903 
1904 	release_source(pSource, index);
1905 
1906 	// Clear any errors so as to not confuse other error handlers
1907 	if ((error=alGetError()) != AL_NO_ERROR)
1908 	{
1909 #ifdef _EXTRA_SOUND_DEBUG
1910 		printf("Error '%s' stopping sound source with index: %d/%d.\n", alGetString(error), index, used_sources + 1);
1911 #endif //_EXTRA_SOUND_DEBUG
1912 	}
1913 
1914 	return 1;
1915 }
1916 
1917 // Find the index of the source associated with this cookie.
1918 // Note that this result must not be stored, but used immediately;
find_sound_source_from_cookie(unsigned int cookie)1919 int find_sound_source_from_cookie(unsigned int cookie)
1920 {
1921 	int n;
1922 	source_data *pSource;
1923 
1924 	if (!cookie)
1925 		return -1;
1926 
1927 	for (n = 0, pSource = sound_source_data; n < used_sources; ++n, ++pSource)
1928 	{
1929 		if (pSource->cookie == cookie)
1930 			return n;
1931 	}
1932 
1933 	return -1;
1934 }
1935 
sound_source_set_gain(unsigned long int cookie,float gain)1936 void sound_source_set_gain(unsigned long int cookie, float gain)
1937 {
1938 	int n;
1939 	source_data *pSource;
1940 
1941 	// Source handle of 0 is a null source
1942 	if (!have_sound || !cookie)
1943 		return;
1944 
1945 	// Find which of our playing sources matches the handle passed
1946 	LOCK_SOUND_LIST();
1947 	n = find_sound_source_from_cookie(cookie);
1948 	if (n > 0)
1949 	{
1950 		pSource = &sound_source_data[n];
1951 		set_sound_gain(pSource, pSource->loaded_sound, gain);
1952 	}
1953 	UNLOCK_SOUND_LIST();
1954 	return;
1955 }
1956 
set_sound_gain(source_data * pSource,int loaded_sound_num,float new_gain)1957 void set_sound_gain(source_data * pSource, int loaded_sound_num, float new_gain)
1958 {
1959 	float type_gain = 1.0f;
1960 	int error;
1961 	sound_type * this_snd = &sound_type_data[sounds_list[loaded_sound_num].sound];
1962 	sound_variants * this_variant = &this_snd->variant[sounds_list[loaded_sound_num].variant];
1963 	// Check what type this sound is and match it to the "type gain"
1964 	switch (this_snd->type)
1965 	{
1966 		case SOUNDS_CROWD:
1967 			type_gain = crowd_gain;
1968 			break;
1969 		case SOUNDS_CLIENT:
1970 			type_gain = client_gain;
1971 			break;
1972 		case SOUNDS_WALKING:
1973 			type_gain = walking_gain;
1974 			break;
1975 		case SOUNDS_ACTOR:
1976 			type_gain = actor_gain;
1977 			break;
1978 		case SOUNDS_MAP:
1979 			type_gain = enviro_gain;
1980 			break;
1981 		case SOUNDS_ENVIRO:
1982 			type_gain = enviro_gain;
1983 			break;
1984 		case SOUNDS_GAMEWIN:
1985 			type_gain = gamewin_gain;
1986 			break;
1987 		case SOUNDS_WARNINGS:
1988 			type_gain = warnings_gain;
1989 			break;
1990 	}
1991 	// Check if we need to update the base gain for this sound
1992 	if (new_gain != sounds_list[loaded_sound_num].base_gain)
1993 		sounds_list[loaded_sound_num].base_gain = new_gain;
1994 
1995 	// Check if we need to dim down the sounds due to rain
1996 	if (this_snd->type != SOUNDS_CLIENT && this_snd->type != SOUNDS_GAMEWIN && this_snd->type != SOUNDS_WARNINGS && this_snd->type != SOUNDS_ENVIRO)
1997 		new_gain = weather_adjust_gain(new_gain, pSource->cookie);
1998 
1999 	// Check if we need to update the overall gain for this source
2000 	if (sound_gain * type_gain * this_variant->gain * new_gain != sounds_list[loaded_sound_num].cur_gain)
2001 	{
2002 		sounds_list[loaded_sound_num].cur_gain = sound_gain * type_gain * this_variant->gain * new_gain;
2003 		alSourcef(pSource->source, AL_GAIN, sounds_list[loaded_sound_num].cur_gain);
2004 	}
2005 	if ((error=alGetError()) != AL_NO_ERROR)
2006 	{
2007 #ifdef _EXTRA_SOUND_DEBUG
2008 		printf("Error setting sound gain: %f, sound: %d, error: %s\n", new_gain, loaded_sound_num, alGetString(error));
2009 #endif //_EXTRA_SOUND_DEBUG
2010 	}
2011 	return;
2012 }
2013 
2014 
2015 
2016 
2017 /*******************************
2018  * SAMPLE PROCESSING FUNCTIONS *
2019  *******************************/
2020 
2021 /* If the sample given by the filename is not currently loaded, create a
2022  * buffer and load it from the path given.
2023  * Returns the sample number for success or -1 on failure.
2024  *
2025  * This function is likely to be very expensive as it initially traverses the types array
2026  * checking if the sample is loaded, then checks for a space in the buffer array, and
2027  * if it still hasn't found a spot, traverses the buffer and source arrays looking for a
2028  * buffer that isn't currently being played by a source!
2029  */
ensure_sample_loaded(char * in_filename)2030 int ensure_sample_loaded(char * in_filename)
2031 {
2032 	int i, j, k, l, sample_num, error;
2033 	ALvoid *data;
2034 	ALsizei datasize;
2035 	ALuint *pBuffer;
2036 	sound_sample *pSample;
2037 	char filename[200];				// This is for the full path to the file
2038 
2039 	// Check if this sample is already loaded and if so, return the sample ID
2040 	for (i = 0; i < MAX_SOUND_FILES; i++)
2041 	{
2042 		if (!strcasecmp(sound_files[i].file_path, in_filename) && sound_files[i].sample_num > -1)
2043 		{
2044 #ifdef _EXTRA_SOUND_DEBUG
2045 			printf("Found this sample already loaded: %s, sound file: %d, sample num: %d\n", in_filename, i, sound_files[i].sample_num);
2046 #endif //_EXTRA_SOUND_DEBUG
2047 			return sound_files[i].sample_num;
2048 		}
2049 	}
2050 
2051 	// Sample isn't loaded so find a space in the array
2052 	sample_num = -1;
2053 	for (i = 0; i < MAX_BUFFERS; i++)
2054 	{
2055 		// Check if this sample is free (no buffer exists)
2056 		if (sound_sample_data[i].buffer == 0 || !alIsBuffer(sound_sample_data[i].buffer))
2057 		{
2058 			sample_num = i;
2059 #ifdef _EXTRA_SOUND_DEBUG
2060 			printf("Found a spot for this sample: %s, sample %d\n", in_filename, i);
2061 #endif //_EXTRA_SOUND_DEBUG
2062 			break;
2063 		}
2064 	}
2065 
2066 	if (sample_num == -1)
2067 	{
2068 		// Don't have a spot yet so check for any inactive samples (not loaded into a source)
2069 		// -- This part will be expensive!! Let's hope we don't get here often --
2070 		int found;
2071 #ifdef _EXTRA_SOUND_DEBUG
2072 		char tmp[1000] = "";
2073 		snprintf(tmp, sizeof(tmp), "Eek! Didn't want to get here. Sample (%s) is apparently not loaded and there is no space for it!", in_filename);
2074 		LOG_TO_CONSOLE(c_red1, tmp);
2075 		printf("Eek, nowhere for the sample: %s\n", in_filename);
2076 #endif //_EXTRA_SOUND_DEBUG
2077 		for (i = 0; i < MAX_BUFFERS; i++)
2078 		{
2079 			found = 0;
2080 			for (j = 0; j < used_sources; j++)
2081 			{
2082 				for (k = 0; k < sound_type_data[sounds_list[sound_source_data[j].loaded_sound].sound].num_variants; k++)
2083 				{
2084 					for (l = STAGE_INTRO; l <= STAGE_OUTRO; l++)
2085 					{
2086 						// Check if this sample is loaded into a source atm
2087 						if (sound_type_data[sounds_list[sound_source_data[j].loaded_sound].sound].variant[k].part[l] &&
2088 							sound_type_data[sounds_list[sound_source_data[j].loaded_sound].sound].variant[k].part[l]->sample_num == i)
2089 						{
2090 							found = 1;
2091 							break;
2092 						}
2093 					}
2094 					if (found)
2095 						break;	// No need to keep looking
2096 				}
2097 				if (found)
2098 					break;	// No need to keep looking
2099 			}
2100 			if (!found)
2101 			{
2102 				// This is an unused sample
2103 				unload_sample(i);
2104 				sample_num = i;
2105 #ifdef _EXTRA_SOUND_DEBUG
2106 				printf("Found unused sample slot: %d\n", i);
2107 #endif //_EXTRA_SOUND_DEBUG
2108 				break;
2109 			}
2110 		}
2111 		if (sample_num == -1)
2112 		{
2113 			// We didn't find an available sample slot so error and bail
2114 #ifdef _EXTRA_SOUND_DEBUG
2115 			LOG_ERROR("Error: Too many samples loaded. Unable to load sample: %s, num samples: %d\n", in_filename, num_samples);
2116 #endif //_EXTRA_SOUND_DEBUG
2117 			return -1;
2118 		}
2119 	}
2120 
2121 #ifdef _EXTRA_SOUND_DEBUG
2122 	printf("Got sample num: %d, Attemping to load sound: File: %s\n", sample_num, in_filename);
2123 #endif //_EXTRA_SOUND_DEBUG
2124 
2125 	num_samples++;
2126 	pSample = &sound_sample_data[sample_num];
2127 
2128 	// Add the data dir to the front of the input filename
2129 	safe_strncpy(filename, datadir, sizeof(filename));
2130 	safe_strcat(filename, in_filename, sizeof(filename));
2131 
2132 	// Load the file into memory
2133 	data = load_ogg_into_memory(filename, &pSample->format, &datasize, &pSample->freq);
2134 	if (!data)
2135 	{
2136 		// Couldn't load the file, so release this sample num
2137 		num_samples--;
2138 		// We have already dumped an error message so just return
2139 		return -1;
2140 	}
2141 
2142 #ifdef _EXTRA_SOUND_DEBUG
2143 	printf("Result: File: %s, Format: %d, Size: %d, Freq: %f\n", filename, (int)pSample->format, (int)datasize, (float)pSample->freq);
2144 #endif //_EXTRA_SOUND_DEBUG
2145 
2146 	// Create a buffer for the sample
2147 	pBuffer = &pSample->buffer;
2148 	alGenBuffers(1, pBuffer);
2149 	if ((error=alGetError()) != AL_NO_ERROR)
2150 	{
2151 		// Couldn't generate a buffer
2152 		LOG_ERROR("Error generating buffer: %s", alGetString(error));
2153 #ifdef _EXTRA_SOUND_DEBUG
2154 		printf("Error generating buffer: %s\n", alGetString(error));
2155 #endif //_EXTRA_SOUND_DEBUG
2156 		*pBuffer = 0;
2157 		// Get rid of the temporary data
2158 		free(data);
2159 		return -1;
2160 	}
2161 
2162 	// Send this data to the buffer
2163 	alBufferData(*pBuffer, pSample->format, data, datasize, pSample->freq);
2164 	if ((error=alGetError()) != AL_NO_ERROR)
2165 	{
2166 		LOG_ERROR("Error loading buffer: %s", alGetString(error));
2167 #ifdef _EXTRA_SOUND_DEBUG
2168 		printf("Error loading buffer: %s\n", alGetString(error));
2169 #endif //_EXTRA_SOUND_DEBUG
2170 		alDeleteBuffers(1, pBuffer);
2171 		// Get rid of the temporary data
2172 		free(data);
2173 		return -1;
2174 	}
2175 
2176 	alGetBufferi(*pBuffer, AL_BITS, &pSample->bits);
2177 	alGetBufferi(*pBuffer, AL_CHANNELS, &pSample->channels);
2178 	alGetBufferi(*pBuffer, AL_SIZE, &pSample->size);
2179 
2180 	pSample->length = (pSample->size * 1000) / ((pSample->bits >> 3) * pSample->channels * pSample->freq);
2181 
2182 	// Get rid of the temporary data
2183 	free(data);
2184 
2185 	if ((error=alGetError()) != AL_NO_ERROR)
2186 	{
2187 #ifdef _EXTRA_SOUND_DEBUG
2188 		printf("Error in ensure_sample_loaded: %s, Filename: %s\n", alGetString(error), filename);
2189 #endif //_EXTRA_SOUND_DEBUG
2190 	}
2191 	return sample_num;
2192 }
2193 
load_samples(sound_type * pType)2194 int load_samples(sound_type * pType)
2195 {
2196 	int i, j;
2197 	// Choose a variant
2198 	j = rand() % pType->num_variants;
2199 	// Check we can load all samples used by this type
2200 	for (i = 0; i < num_STAGES; ++i)
2201 	{
2202 		if (pType->variant[j].part[i] && pType->variant[j].part[i]->sample_num < 0 && strcasecmp(pType->variant[j].part[i]->file_path, ""))
2203 		{
2204 			pType->variant[j].part[i]->sample_num = ensure_sample_loaded(pType->variant[j].part[i]->file_path);
2205 			if (pType->variant[j].part[i]->sample_num < 0)
2206 			{
2207 #ifdef _EXTRA_SOUND_DEBUG
2208 				printf("Error: problem loading sample: %s\n", pType->variant[j].part[i]->file_path);
2209 #endif //_EXTRA_SOUND_DEBUG
2210 				return -1;
2211 			}
2212 		}
2213 	}
2214 	return j;		// Return the variant we chose
2215 }
2216 
release_sample(int sample_num)2217 void release_sample(int sample_num)
2218 {
2219 	sound_sample * pSample;
2220 
2221 	// Check we have a valid sample_num
2222 	if (sample_num < 0 || sample_num >= MAX_BUFFERS)
2223 		return;
2224 
2225 	pSample = &sound_sample_data[sample_num];
2226 
2227 	// Release the buffer used by this sample
2228 	if (alIsBuffer(pSample->buffer))
2229 		alDeleteBuffers(1, &pSample->buffer);
2230 	// Reset the array element
2231 	pSample->buffer = 0;
2232 	pSample->format = 0;
2233 	pSample->size = 0;
2234 	pSample->freq = 0;
2235 	pSample->channels = 0;
2236 	pSample->bits = 0;
2237 	pSample->length = 0;
2238 }
2239 
unload_sample(int sample_num)2240 void unload_sample(int sample_num)
2241 {
2242 	int i, j, k;
2243 
2244 	// Check we have a valid sample_num
2245 	if (sample_num < 0 || sample_num >= MAX_BUFFERS)
2246 		return;
2247 
2248 	// Find the places this sample is listed and reset them
2249 	for (i = 0; i < num_types; i++)
2250 	{
2251 		for (j = 0; j < sound_type_data[i].num_variants; j++)
2252 		{
2253 			for (k = 0; k < num_STAGES; k++)
2254 			{
2255 				if (sound_type_data[i].variant[j].part[k] && sound_type_data[i].variant[j].part[k]->sample_num == sample_num)
2256 				{
2257 					sound_type_data[i].variant[j].part[k]->sample_num = -1;
2258 				}
2259 			}
2260 		}
2261 	}
2262 	// Release the buffer used by this sample and reset the array element
2263 	release_sample(sample_num);
2264 }
2265 
2266 
2267 
2268 
2269 /*****************************************
2270  * INDIVIDUAL SOUND PROCESSING FUNCTIONS *
2271  *****************************************/
2272 
add_server_sound(int type,int x,int y,int gain)2273 unsigned int add_server_sound(int type, int x, int y, int gain)
2274 {
2275 	int snd = -1;
2276 	// Find the sound for this server sound type
2277 	snd = server_sound[type];
2278 	if (snd > -1)
2279 	{
2280 #ifdef _EXTRA_SOUND_DEBUG
2281 		printf("Adding server sound: %d\n", type);
2282 #endif //_EXTRA_SOUND_DEBUG
2283 		return add_sound_object_gain(snd, x, y, 0, gain);
2284 	}
2285 	else
2286 	{
2287 		LOG_ERROR("Unable to find server sound: %i", type);
2288 		return 0;
2289 	}
2290 }
2291 
2292 // Wrapper function for adding walking sounds.
add_walking_sound(int type,int x,int y,int me,float scale)2293 unsigned int add_walking_sound(int type, int x, int y, int me, float scale)
2294 {
2295 	return add_sound_object_gain(type, x, y, me, scale);
2296 }
2297 
2298 /* Wrapper function for adding map based particle sounds
2299  *
2300  * Due to only a subset of sound information being programmed into the map data, sounds
2301  * are triggered by the addition of each particle system. This causes problems for fires,
2302  * fountains, waterfalls and anything that is made of multiple particle systems.
2303  *
2304  * To fix this, this function checks for any existing sounds in a similar location before
2305  * loading this one.
2306  */
add_map_sound(int type,int x,int y)2307 unsigned int add_map_sound(int type, int x, int y)
2308 {
2309 	int i;
2310 	const int buffer = 5;
2311 	// Check if there is another sound within +/-5 (buffer) tiles around this position
2312 	for (i = 0; i < MAX_BUFFERS * 2; i++)
2313 	{
2314 		if (x >= sounds_list[i].x - buffer
2315 			&& x <= sounds_list[i].x + buffer
2316 			&& y >= sounds_list[i].y - buffer
2317 			&& y <= sounds_list[i].y + buffer
2318 			&& type == sounds_list[i].sound)
2319 		{
2320 			// There is a sound of this type already within this space so ignore this one
2321 			return 0;
2322 		}
2323 	}
2324 	return add_sound_object_gain(type, x, y, 0, 1.0f);
2325 }
2326 
2327 // Wrapper for regular particle sounds (non-map based) to avoid the location check
add_particle_sound(int type,int x,int y)2328 unsigned int add_particle_sound(int type, int x, int y)
2329 {
2330 	return add_sound_object_gain(type, x, y, 0, 1.0f);
2331 }
2332 
2333 // Add a wrapper for under-the-influence-of-spell sounds
add_spell_sound(int spell)2334 unsigned int add_spell_sound(int spell)
2335 {
2336 	if (spell >= 0 && spell < NUM_ACTIVE_SPELLS && sound_spell_data[spell] > -1)
2337 	{
2338 		// Add the sound
2339 		return add_sound_object_gain(sound_spell_data[spell], 0, 0, 1, 1.0f);
2340 	}
2341 	return 0;
2342 }
2343 
add_death_sound(actor * act)2344 unsigned int add_death_sound(actor * act)
2345 {
2346 	int snd;
2347 	// Check the type of this actor has a death sound (only used for enhanced actors as simple
2348 	// actors are triggered though the cal animation)
2349 	if (!act)
2350 		return 0;
2351 	snd = actors_defs[act->actor_type].cal_frames[cal_actor_die1_frame].sound;
2352 	if (snd > -1)
2353 	{
2354 		return add_sound_object_gain(snd, act->x_pos, act->y_pos, act == your_actor ? 1 : 0, 1.0f);
2355 	}
2356 	return 0;
2357 }
2358 
add_battlecry_sound(actor * act)2359 unsigned int add_battlecry_sound(actor * act)
2360 {
2361 	// Maybe play a battlecry sound
2362 	if (act && rand() % 3 == 2)			// 1 chance in 3 to play
2363 	{
2364 		return add_sound_object_gain(actors_defs[act->actor_type].battlecry.sound,
2365 										act->x_pos * 2,
2366 										act->x_pos * 2,
2367 										act == your_actor ? 1 : 0,
2368 										actors_defs[act->actor_type].battlecry.scale
2369 									);
2370 	}
2371 	return 0;
2372 }
2373 
add_sound_object(int type,int x,int y,int me)2374 unsigned int add_sound_object(int type, int x, int y, int me)
2375 {
2376 	return add_sound_object_gain(type, x, y, me, 1.0f);
2377 }
2378 
add_sound_object_gain(int type,int x,int y,int me,float initial_gain)2379 unsigned int add_sound_object_gain(int type, int x, int y, int me, float initial_gain)
2380 {
2381 	int tx, ty, distanceSq, sound_num, cookie;
2382 	sound_type *pNewType;
2383 	float maxDistanceSq = 0.0f;
2384 
2385 /*	Torg: Checks for sound enabled etc have been removed as we should load sounds even if currently
2386 	disabled, as they may be enabled within the duration of this sound (eg. rain and map sounds). We just
2387 	won't play them yet.
2388 */
2389 
2390 	// Check if we have a sound config, and thus if its worth doing anything
2391 	if (num_types < 1)
2392 		return 0;
2393 
2394 	// Get our position
2395 	if (your_actor)
2396 	{
2397 		tx = your_actor->x_pos * 2;
2398 		ty = your_actor->y_pos * 2;
2399 	}
2400 	else
2401 	{
2402 		tx = 0;
2403 		ty = 0;
2404 	}
2405 #ifdef _EXTRA_SOUND_DEBUG
2406 	printf("Trying to add sound: %d (%s) at %d, %d. Position: %d, %d, Gain: %f\n", type, type > -1 ? sound_type_data[type].name : "not defined", x, y, tx, ty, initial_gain);
2407 #endif //_EXTRA_SOUND_DEBUG
2408 	if (type == -1)			// Invalid sound, ignore
2409 		return 0;
2410 
2411 	if (me)
2412 	{
2413 		// Override the x & y values to use the camera (listener) position because its me
2414 		x = tx;
2415 		y = ty;
2416 	}
2417 
2418 	// Check it's a valid type, get pType as a pointer to the type data
2419 	if (type >= MAX_SOUNDS || type >= num_types || type < 0)
2420 	{
2421 		LOG_ERROR("%s: %i", snd_invalid_number, type);
2422 #ifdef _EXTRA_SOUND_DEBUG
2423 		printf("Apparently an invalid type: %d\n", type);
2424 #endif //_EXTRA_SOUND_DEBUG
2425 		return 0;
2426 	}
2427 	pNewType = &sound_type_data[type];
2428 
2429 	// Check if this sound is played at this time of day
2430 	if (!time_of_day_valid(pNewType->time_of_the_day_flags))
2431 	{
2432 #ifdef _EXTRA_SOUND_DEBUG
2433 		printf("Not playing this sound at this time of the day: Flags: 0x%x, Time: %d\n", pNewType->time_of_the_day_flags, game_minute);
2434 #endif //_EXTRA_SOUND_DEBUG
2435 		return 0;
2436 	}
2437 
2438 	// Check this sound doesn't already exist in the sounds list and just isn't loaded
2439 /*	for (i = 0; i < MAX_BUFFERS * 2; i++)
2440 	{
2441 		if (sounds_list[i].sound == type && sounds_list[i].x == x && sounds_list[i].y == y && sounds_list)
2442 			return 0;		// This sound already exists so let update_sound handle it
2443 	}
2444 */
2445 	// Find a spot in the sounds list for this sound
2446 	sound_num = get_loaded_sound_num();
2447 	if (sound_num == -1)
2448 	{
2449 		// Check if we should bother erroring - an overflow of sounds when sound is disabled we can ignore
2450 		if (have_sound && sound_on)
2451 		{
2452 #ifdef _EXTRA_SOUND_DEBUG
2453 			printf("Error: Too many sounds loaded!! n00b! Not playing this sound: %d (%s)\n", type, pNewType->name);
2454 #endif //_EXTRA_SOUND_DEBUG
2455 			LOG_ERROR("Error: Too many sounds loaded. Not playing this sound: %d (%s)\n", type, pNewType->name);
2456 		}
2457 		return 0;
2458 	}
2459 
2460 	// We got this far so add this sound to the list and assign it a cookie
2461 	LOCK_SOUND_LIST();
2462 
2463 	sounds_list[sound_num].sound = type;
2464 	sounds_list[sound_num].variant = -1;		// Haven't chosen a variant yet - that's done by load_samples()
2465 	sounds_list[sound_num].x = x;
2466 	sounds_list[sound_num].y = y;
2467 	sounds_list[sound_num].loaded = 0;
2468 	sounds_list[sound_num].playing = 0;
2469 	sounds_list[sound_num].base_gain = initial_gain;
2470 	sounds_list[sound_num].cur_gain = -1.0f;		// Make sure we set the gain when we first play the sound
2471 	cookie = get_next_cookie();
2472 	sounds_list[sound_num].cookie = cookie;
2473 	num_sounds++;
2474 
2475 	// Check if we should try to load the samples (sound is enabled)
2476 	if (inited && have_sound && sound_on)
2477 	{
2478 		// Load all samples used by this type
2479 		sounds_list[sound_num].variant = load_samples(pNewType);
2480 		if (sounds_list[sound_num].variant < 0)
2481 		{
2482 			// Unable to load all the samples. We have already errored so mark it as not loaded and bail.
2483 			sounds_list[sound_num].loaded = 0;
2484 			UNLOCK_SOUND_LIST();
2485 			return cookie;
2486 		}
2487 		sounds_list[sound_num].loaded = 1;
2488 
2489 		// Check if we are playing this sound now (and need to load it into a source)
2490 		distanceSq = (tx - x) * (tx - x) + (ty - y) * (ty - y);
2491 		maxDistanceSq = pNewType->distance * pNewType->distance;
2492 
2493 		if (!pNewType->positional || (distanceSq <= maxDistanceSq))
2494 		{
2495 			if (!play_sound(sound_num, x, y, initial_gain))
2496 			{
2497 #ifdef _EXTRA_SOUND_DEBUG
2498 				printf("There was an error so not playing this sound: %d, Cookie: %d\n", type, cookie);
2499 #endif //_EXTRA_SOUND_DEBUG
2500 			}
2501 		}
2502 #ifdef _EXTRA_SOUND_DEBUG
2503 		else
2504 		{
2505 			printf("Not playing this sound as we are out of range! maxDistanceSq: %d, distanceSq: %d. Loaded as: %d, Cookie: %d\n", (int)maxDistanceSq, distanceSq, sound_num, cookie);
2506 		}
2507 #endif //_EXTRA_SOUND_DEBUG
2508 	}
2509 #ifdef _EXTRA_SOUND_DEBUG
2510 	else
2511 	{
2512 		// Sound isn't enabled so bail now. When sound is enabled, these sounds (if applicable) will be
2513 		// loaded and played then
2514 		printf("Not playing this sound as sound isn't enabled yet. Inited: %d, Have sound: %d, Sound on: %d, Cookie: %d\n", inited, have_sound, sound_on, cookie);
2515 	}
2516 #endif //_EXTRA_SOUND_DEBUG
2517 
2518 	// We have added the sound to the list so return the cookie
2519 	UNLOCK_SOUND_LIST();
2520 	return cookie;
2521 }
2522 
play_sound(int sound_num,int x,int y,float initial_gain)2523 int play_sound(int sound_num, int x, int y, float initial_gain)
2524 {
2525 	int loops, error;
2526 #ifdef _EXTRA_SOUND_DEBUG
2527 	int err = 0;
2528 #endif // _EXTRA_SOUND_DEBUG
2529 	ALuint buffer = 0;
2530 	SOUND_STAGE stage;
2531 	ALfloat sourcePos[] = {x, y, 0.0};
2532 	ALfloat sourceVel[] = {0.0, 0.0, 0.0};
2533 	source_data * pSource;
2534 	sound_variants * pVariant;
2535 	sound_type * pNewType = &sound_type_data[sounds_list[sound_num].sound];
2536 
2537 	// Check if we have a sound device and its worth continuing
2538 	if (!inited)
2539 		return 0;
2540 
2541 #ifdef _EXTRA_SOUND_DEBUG
2542 	printf("Playing this sound: %d, Sound num: %d, Cookie: %d\n", sounds_list[sound_num].sound, sound_num, sounds_list[sound_num].cookie);
2543 #endif //_EXTRA_SOUND_DEBUG
2544 
2545 	// Check if we need to load the samples into buffers
2546 	if (!sounds_list[sound_num].loaded)
2547 	{
2548 		sounds_list[sound_num].variant = load_samples(pNewType);
2549 		if (sounds_list[sound_num].variant < 0)
2550 		{
2551 			return 0;
2552 		}
2553 		sounds_list[sound_num].loaded = 1;
2554 	}
2555 	pVariant = &pNewType->variant[sounds_list[sound_num].variant];
2556 
2557 	pSource = get_available_source(pNewType->priority);
2558 	if (!pSource)
2559 	{
2560 #ifdef _EXTRA_SOUND_DEBUG
2561 		printf("Sound overflow: %s, %d\n", pNewType->name, max_sources);
2562 #endif //_EXTRA_SOUND_DEBUG
2563 		LOG_ERROR("%s: %d sources allocated", snd_sound_overflow, max_sources);
2564 		return 0;
2565 	}
2566 
2567 	// Check if we have an intro. We already quit if the sound doesn't have a main.
2568 	stage = !pVariant->part[STAGE_INTRO] || pVariant->part[STAGE_INTRO]->sample_num < 0 ? STAGE_MAIN : STAGE_INTRO;
2569 
2570 	// Initialise the source data to the first sample to be played for this sound
2571 	pSource->play_duration = 0;
2572 	pSource->loaded_sound = sound_num;
2573 	pSource->current_stage = stage;
2574 
2575 	alSourcef(pSource->source, AL_PITCH, 1.0f);
2576 	set_sound_gain(pSource, sound_num, initial_gain);
2577 	alSourcefv(pSource->source, AL_VELOCITY, sourceVel);
2578 	alSourcefv(pSource->source, AL_POSITION, sourcePos);
2579 	if ((error=alGetError()) != AL_NO_ERROR)
2580 	{
2581 #ifdef _EXTRA_SOUND_DEBUG
2582 		printf("Error with alSourcef calls: %s. Name: %s. Source: %d: %s\n", snd_source_error, pNewType->name, pSource->source, alGetString(error));
2583 #endif //_EXTRA_SOUND_DEBUG
2584 	}
2585 
2586 #ifdef _EXTRA_SOUND_DEBUG
2587 	if (!alIsSource(pSource->source))
2588 	{
2589 		printf("Source corruption! %d, %d, %d\n", pSource->source, sounds_list[sound_num].sound, sounds_list[sound_num].cookie);
2590 		release_source(pSource, -1);
2591 		return 0;
2592 	}
2593 	else
2594 	{
2595 		int tmp = 0;
2596 		alGetSourcei(pSource->source, AL_SOURCE_TYPE, &tmp);
2597 		if ((error=alGetError()) != AL_NO_ERROR)
2598 		{
2599 			printf("Error getting source status! %s, %d, %d, %d\n", alGetString(error), pSource->source, sounds_list[sound_num].sound, sounds_list[sound_num].cookie);
2600 		}
2601 		else if (tmp == AL_STATIC)
2602 		{
2603 			printf("Found a static source! This isn't meant to exist! %d, %d\n", pSource->source, sounds_list[sound_num].sound);
2604 		}
2605 	}
2606 #endif //_EXTRA_SOUND_DEBUG
2607 
2608 	// Ensure the source is ready for queueing (attach a NULL buffer to reset it)
2609 	alSourcei(pSource->source, AL_BUFFER, 0);
2610 #ifdef _EXTRA_SOUND_DEBUG
2611 	if ((error=alGetError()) != AL_NO_ERROR)
2612 	{
2613 		printf("Error resetting source! %d, %d\n", pSource->source, sounds_list[sound_num].sound);
2614 	}
2615 #endif //_EXTRA_SOUND_DEBUG
2616 
2617 	for (; stage < num_STAGES; ++stage)
2618 	{
2619 		// Get the buffer to be queued.
2620 		if (!pVariant->part[stage] || pVariant->part[stage]->sample_num < 0)
2621 			continue;
2622 		buffer = sound_sample_data[pVariant->part[stage]->sample_num].buffer;
2623 		pSource->sample[stage] = pVariant->part[stage]->sample_num;
2624 #ifdef _EXTRA_SOUND_DEBUG
2625 		printf("Stage: %d, Buffer address: %d\n", stage, buffer);
2626 #endif //_EXTRA_SOUND_DEBUG
2627 
2628 		// If there are a finite number of loops for main sample, queue them all here
2629 		if (stage == STAGE_MAIN)
2630 		{
2631 			if (pNewType->loops > 0)
2632 			{
2633 				for (loops = 0; loops < pNewType->loops; ++loops)
2634 				{
2635 					alSourceQueueBuffers(pSource->source, 1, &buffer);
2636 #ifdef _EXTRA_SOUND_DEBUG
2637 					if ((error=alGetError()) != AL_NO_ERROR)
2638 					{
2639 						printf("Error with sample alSourceQueueBuffers: %s, Name: %s. Source: %d, Loops: %d/%d\n", alGetString(error), pNewType->name, pSource->source, loops, pNewType->loops);
2640 						err = 1;
2641 					}
2642 #endif //_EXTRA_SOUND_DEBUG
2643 				}
2644 			}
2645 			else
2646 			{
2647 				alSourceQueueBuffers(pSource->source, 1, &buffer);
2648 #ifdef _EXTRA_SOUND_DEBUG
2649 				if ((error=alGetError()) != AL_NO_ERROR)
2650 				{
2651 					printf("Error with looped sample alSourceQueueBuffers: %s, Name: %s. Source: %d\n", alGetString(error), pNewType->name, pSource->source);
2652 					err = 1;
2653 				}
2654 #endif //_EXTRA_SOUND_DEBUG
2655 				// Dont queue an outro that will never get played!
2656 				break;
2657 			}
2658 		}
2659 		else
2660 		{
2661 			alSourceQueueBuffers(pSource->source, 1, &buffer);
2662 #ifdef _EXTRA_SOUND_DEBUG
2663 			if ((error=alGetError()) != AL_NO_ERROR)
2664 			{
2665 				printf("Error with intro/outro sample alSourceQueueBuffers: %s, Name: %s. Source: %d\n", alGetString(error), pNewType->name, pSource->source);
2666 				err = 1;
2667 			}
2668 #endif //_EXTRA_SOUND_DEBUG
2669 		}
2670 	}
2671 	add_source_to_lists(pSource);
2672 #ifdef _EXTRA_SOUND_DEBUG
2673 	if (err != 0)
2674 	{
2675 #else //_EXTRA_SOUND_DEBUG
2676 	if ((error=alGetError()) != AL_NO_ERROR)
2677 	{
2678 		LOG_ERROR("Error with alSourceQueueBuffers: %s, Name: %s. Source: %d\n", alGetString(error), pNewType->name, pSource->source);
2679 #endif //_EXTRA_SOUND_DEBUG
2680 		release_source(pSource, -1);
2681 		return 0;
2682 	}
2683 
2684 	if (!pNewType->positional)
2685 	{
2686 		alSourcei(pSource->source, AL_SOURCE_RELATIVE, AL_TRUE);
2687 	}
2688 	else
2689 	{
2690 		alSourcei(pSource->source, AL_SOURCE_RELATIVE, AL_FALSE);
2691 		alSourcef(pSource->source, AL_REFERENCE_DISTANCE , 10.0f);
2692 		alSourcef(pSource->source, AL_ROLLOFF_FACTOR , 4.0f);
2693 	}
2694 	if ((pVariant->part[STAGE_INTRO] && pVariant->part[STAGE_INTRO]->sample_num < 0 && pNewType->loops == 0) ||
2695 		(!pVariant->part[STAGE_INTRO] && pNewType->loops == 0))
2696 		// 0 is infinite looping
2697 		alSourcei(pSource->source,AL_LOOPING,AL_TRUE);
2698 	else
2699 		alSourcei(pSource->source,AL_LOOPING,AL_FALSE);
2700 
2701 	alSourcePlay(pSource->source);
2702 	sounds_list[sound_num].playing = 1;
2703 
2704 	pSource->cookie = sounds_list[sound_num].cookie;
2705 
2706 	// Check and clear any AL error
2707 	if ((error=alGetError()) != AL_NO_ERROR)
2708 	{
2709 #ifdef _EXTRA_SOUND_DEBUG
2710 		printf("Error setting source properties/playing source: %s, Name: %s. Source: %d, Cookie: %d\n", alGetString(error), pNewType->name, pSource->source, sounds_list[sound_num].cookie);
2711 #endif // _EXTRA_SOUND_DEBUG
2712 	}
2713 
2714 #ifdef _EXTRA_SOUND_DEBUG
2715 	printf("Playing %d sources\n", used_sources);
2716 #endif // _EXTRA_SOUND_DEBUG
2717 
2718 	return 1;	// Return success
2719 }
2720 
2721 unsigned int get_next_cookie()
2722 {
2723 	unsigned int cookie = next_cookie;
2724 
2725 	// If next_cookie wraps around back to 0 then address this.
2726 	if (++next_cookie == 0) ++next_cookie;
2727 
2728 	return cookie;
2729 }
2730 
2731 int get_loaded_sound_num()
2732 {
2733 	int i;
2734 	// Loop through the array looking for an unused spot (sound = -1 && cookie = 0)
2735 	for (i = 0; i < MAX_BUFFERS * 2; i++)
2736 	{
2737 		if (sounds_list[i].sound == -1 && sounds_list[i].cookie == 0)
2738 		{
2739 			return i;
2740 		}
2741 	}
2742 	return -1;
2743 }
2744 
2745 // This is passed a cookie, and searches for a sound and source (if ness) with this cookie
2746 void stop_sound(unsigned long int cookie)
2747 {
2748 	int n, m;
2749 
2750 	// Cookie of 0 is an invalid sound handle
2751 	if (!cookie)
2752 		return;
2753 
2754 	// Find which sound matches this cookie
2755 	n = find_sound_from_cookie(cookie);
2756 #ifdef _EXTRA_SOUND_DEBUG
2757 	printf("Removing cookie: %ld, Sound number: %d\n", cookie, n);
2758 #endif //_EXTRA_SOUND_DEBUG
2759 	if (n >= 0)
2760 	{
2761 #ifdef _EXTRA_SOUND_DEBUG
2762 		printf("Stopping cookie %ld with sound index %d. It is currently %splaying.\n", cookie, n, sounds_list[n].playing ? "" : "not ");
2763 #endif //_EXTRA_SOUND_DEBUG
2764 		if (sounds_list[n].playing)
2765 		{
2766 			// Find which of our playing sources matches the handle passed
2767 			LOCK_SOUND_LIST();
2768 			m = find_sound_source_from_cookie(cookie);
2769 			if (m >= 0)
2770 			{
2771 				stop_sound_source_at_index(m);
2772 			}
2773 #ifdef _EXTRA_SOUND_DEBUG
2774 			else
2775 			{
2776 				printf("ERROR! Unable to find source for cookie %ld with sound index %d. It is meant to be currently playing.\n", cookie, n);
2777 			}
2778 #endif //_EXTRA_SOUND_DEBUG
2779 			UNLOCK_SOUND_LIST();
2780 		}
2781 		sounds_list[n].playing = 0;
2782 		unload_sound(n);
2783 	}
2784 }
2785 
2786 void stop_sound_at_location(int x, int y)
2787 {
2788 	int i = 0;
2789 
2790 	// Search for a sound at the given location
2791 	for (i = 0; i < MAX_BUFFERS * 2; i++)
2792 	{
2793 		if (sounds_list[i].x == x && sounds_list[i].y == y)
2794 		{
2795 			stop_sound(sounds_list[i].cookie);
2796 		}
2797 	}
2798 }
2799 
2800 // Kill all the not playing and looping sounds. Useful when we change maps, etc.
2801 void stop_all_sounds()
2802 {
2803 	int i;
2804 	ALuint error;
2805 
2806 	if (!inited) return;
2807 
2808 	LOCK_SOUND_LIST();
2809 
2810 #ifdef _EXTRA_SOUND_DEBUG
2811 	printf("Stopping all individual sounds\n");
2812 #endif //_EXTRA_SOUND_DEBUG
2813 	for (i = 0; i < MAX_BUFFERS * 2; i++)
2814 	{
2815 		// Check if this is a loaded sound that isn't going to finish by itself (not playing or loops)
2816 		if (sounds_list[i].cookie != 0 && (!sounds_list[i].playing || sound_type_data[sounds_list[i].sound].loops == 0))
2817 		{
2818 #ifdef _EXTRA_SOUND_DEBUG
2819 			printf("Stopping sound %d (%s), cookie: %d, used_sources: %d\n", i, sound_type_data[sounds_list[i].sound].name, sounds_list[i].cookie, used_sources);
2820 #endif //_EXTRA_SOUND_DEBUG
2821 			stop_sound(sounds_list[i].cookie);
2822 		}
2823 	}
2824 
2825 	for (i = 0; i < max_streams; i++)
2826 	{
2827 		// Fade the music stream down (we can use it again after the map change) but destroy any other streams
2828 		if (streams[i].type == STREAM_TYPE_MUSIC)
2829 			streams[i].fade = -1;
2830 		else
2831 		{
2832 #ifdef _EXTRA_SOUND_DEBUG
2833 			printf("Stopping %s stream source: %d\n", get_stream_type(streams[i].type), streams[i].source);
2834 #endif //_EXTRA_SOUND_DEBUG
2835 			destroy_stream(&streams[i]);
2836 		}
2837 	}
2838 
2839 	UNLOCK_SOUND_LIST();
2840 
2841 	if ((error=alGetError()) != AL_NO_ERROR)
2842 	{
2843 #ifdef _EXTRA_SOUND_DEBUG
2844 		printf("Error killing all sounds\n");
2845 #endif //_EXTRA_SOUND_DEBUG
2846 	}
2847 
2848 	must_restart_spell_sounds = 1;
2849 }
2850 
2851 void unload_sound(int index)
2852 {
2853 	// Reset this sound
2854 	sounds_list[index].sound = -1;
2855 	sounds_list[index].x = -1;
2856 	sounds_list[index].y = -1;
2857 	sounds_list[index].playing = 0;
2858 	sounds_list[index].loaded = 0;
2859 	sounds_list[index].cookie = 0;
2860 	sounds_list[index].lifetime = 0;
2861 	num_sounds--;
2862 }
2863 
2864 // -- Update the sound system --
2865 // We update our listener position and any sounds being played, as well as
2866 // rebuilding the list of active sources, as some may have become inactive
2867 // due to the sound ending or being out of range, or some may be back in
2868 // range and need to be played. We also adjust volumes if ness.
2869 void update_sound(int ms)
2870 {
2871 	int i = 0, error = AL_NO_ERROR;
2872 	source_data *pSource;
2873 #ifdef USE_ALGETSOURCEI_AL_BUFFER
2874 	sound_sample *pSample;
2875 	ALuint deadBuffer;
2876 	ALint numProcessed, buffer;
2877 #endif
2878 	sound_type *pSoundType;
2879 	sound_variants *pVariant;
2880 	ALint state;
2881 
2882 	int source;
2883 	int x, y, distanceSq, maxDistSq;
2884 	int relative;
2885 	int tx = 0, ty = 0;
2886 	ALfloat sourcePos[3] = {0.0f, 0.0f, 0.0f};
2887 	ALfloat listenerPos[3] = {0.0f, 0.0f, 0.0f};
2888 	ALfloat listenerVel[3] = {0.0f, 0.0f, 0.0f};
2889 	ALfloat listenerOri[6] = {0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f};
2890 #ifdef _EXTRA_SOUND_DEBUG
2891 	int j;
2892 #endif // _EXTRA_SOUND_DEBUG
2893 	int l;
2894 
2895 	// Check if we have a sound config, and thus if its worth doing anything (or sound is disabled)
2896 	if (num_types < 1 || no_sound)
2897 		return;
2898 
2899 	LOCK_ACTORS_LISTS();
2900 	// Check if we have our actor
2901 	if (your_actor)
2902 	{
2903 		// Set our position and the listener variables
2904 		tx = your_actor->x_pos * 2;
2905 		ty = your_actor->y_pos * 2;
2906 		listenerPos[0] = tx;
2907 		listenerPos[1] = ty;
2908 		if (your_actor->z_rot > 0 && your_actor->z_rot < 180) {
2909 			listenerOri[0] = 1;
2910 		} else if (your_actor->z_rot > 180 && your_actor->z_rot < 360) {
2911 			listenerOri[0] = -1;
2912 		} else {
2913 			listenerOri[0] = 0;
2914 		}
2915 		if (your_actor->z_rot > 315 || your_actor->z_rot < 90) {
2916 			listenerOri[1] = 1;
2917 		} else if (your_actor->z_rot > 135 && your_actor->z_rot < 225) {
2918 			listenerOri[1] = -1;
2919 		} else {
2920 			listenerOri[1] = 0;
2921 		}
2922 		// a map change or sound-off will have stopped spell sounds,
2923 		// now we have our actor, we can re-enable the spell sounds
2924 		if (must_restart_spell_sounds && !disconnected)
2925 		{
2926 			restart_active_spell_sounds();
2927 			must_restart_spell_sounds = 0;
2928 		}
2929 	}
2930 
2931 	// Start to process the sounds
2932 	LOCK_SOUND_LIST();
2933 
2934 	// Check the sounds_list for anything to be loaded/played
2935 	for (i = 0; i < MAX_BUFFERS * 2; i++)
2936 	{
2937 		// If this sound is "live"
2938 		if (sounds_list[i].sound > -1)
2939 		{
2940 			pSoundType = &sound_type_data[sounds_list[i].sound];
2941 			// Update the length of time this sound has been alive
2942 			sounds_list[i].lifetime += ms;
2943 			// Check for any non-looping sounds in the sounds_list that aren't being played that have passed their time
2944 			if (sounds_list[i].lifetime >= 1000 && !sounds_list[i].playing && pSoundType->loops != 0)
2945 			{
2946 #ifdef _EXTRA_SOUND_DEBUG
2947 				printf("Sound (%d) timed out: %d (%s), Cookie: %d, Lifetime: %d\n", i, sounds_list[i].sound, pSoundType->name, sounds_list[i].cookie, sounds_list[i].lifetime);
2948 #endif //_EXTRA_SOUND_DEBUG
2949 				stop_sound(sounds_list[i].cookie);
2950 				continue;
2951 			}
2952 			// Check for any sounds that aren't being played and check if they need to be because
2953 			// sound has now been enabled or they have come back into range
2954 			x = sounds_list[i].x;
2955 			y = sounds_list[i].y;
2956 			if (inited && !sounds_list[i].playing && x > -1 && y > -1 && sounds_list[i].sound > -1)
2957 			{
2958 				distanceSq = (tx - x) * (tx - x) + (ty - y) * (ty - y);
2959 				maxDistSq = pSoundType->distance * pSoundType->distance;
2960 				if (sound_on && (distanceSq < maxDistSq))
2961 				{
2962 					// This sound is back in range so load it into a source and play it
2963 #ifdef _EXTRA_SOUND_DEBUG
2964 					printf("Sound now in-range: %d (%s), Distance squared: %d, Max: %d\n", sounds_list[i].sound, pSoundType->name, distanceSq, maxDistSq);
2965 #endif //_EXTRA_SOUND_DEBUG
2966 					sounds_list[i].cur_gain = -1.0f;	// Make sure we recalculate this sound's volume
2967 					if (!play_sound(i, x, y, sounds_list[i].base_gain))
2968 					{
2969 #ifdef _EXTRA_SOUND_DEBUG
2970 						printf("Error restarting sound!!\n");
2971 #endif //_EXTRA_SOUND_DEBUG
2972 					}
2973 				}
2974 			}
2975 		}
2976 	}
2977 
2978 	// Check if we have a sound device and its worth continuing
2979 	if (!inited)
2980 	{
2981 		UNLOCK_SOUND_LIST();
2982 		UNLOCK_ACTORS_LISTS();
2983 		return;
2984 	}
2985 
2986 	// Update the position of the listener
2987 	alListenerfv(AL_POSITION, listenerPos);
2988 	alListenerfv(AL_VELOCITY, listenerVel);
2989 	alListenerfv(AL_ORIENTATION, listenerOri);
2990 
2991 	// Check if we have any sounds playing currently (this includes streams so is sometimes a little redundant)
2992 	if (!used_sources)
2993 	{
2994 		UNLOCK_SOUND_LIST();
2995 		UNLOCK_ACTORS_LISTS();
2996 		return;
2997 	}
2998 
2999 #ifdef _EXTRA_SOUND_DEBUG
3000 	j = 0;
3001 #endif // _EXTRA_SOUND_DEBUG
3002 	// Now, update the position of actor (animation) sounds
3003 	for (i = 0; i < max_actors; i++)
3004 	{
3005 		if (!actors_list[i] || !actors_list[i]->cur_anim_sound_cookie)
3006 			continue;
3007 
3008 		source = find_sound_source_from_cookie(actors_list[i]->cur_anim_sound_cookie);
3009 		if (source < 0)
3010 			continue;
3011 
3012 		// Check if this is the correct tile type, or if we need to play another sound
3013 		if (actors_list[i]->moving && !actors_list[i]->fighting)
3014 		{
3015 			UNLOCK_SOUND_LIST();
3016 			handle_walking_sound(actors_list[i], actors_list[i]->cur_anim.sound);
3017 			LOCK_SOUND_LIST();
3018 		}
3019 		if (actors_list[i]->actor_id == yourself)
3020 		{
3021 			// If this is you, use the same position as the listener
3022 			sourcePos[0] = tx;
3023 			sourcePos[1] = ty;
3024 		}
3025 		else
3026 		{
3027 			sourcePos[0] = actors_list[i]->x_pos * 2;
3028 			sourcePos[1] = actors_list[i]->y_pos * 2;
3029 		}
3030 		sourcePos[2] = 0.0f;
3031 		alSourcefv(sound_source_data[source].source, AL_POSITION, sourcePos);
3032 	}
3033 
3034 	UNLOCK_ACTORS_LISTS();
3035 
3036 	// Finally, update all the sources
3037 	i = 0;
3038 #ifdef _EXTRA_SOUND_DEBUG
3039 	j = 0;
3040 #endif // _EXTRA_SOUND_DEBUG
3041 
3042 	while (i < used_sources)
3043 	{
3044 		pSource = &sound_source_data[i];
3045 #ifdef _EXTRA_SOUND_DEBUG
3046 		j++;
3047 		if (j > max_sources)
3048 		{
3049 			LOG_ERROR("update_sound race condition!! i = %d, used_sources = %d\n", i, used_sources);
3050 			printf("update_sound race condition!! i = %d, used_sources = %d\n", i, used_sources);
3051 			break;
3052 		}
3053 #endif // _EXTRA_SOUND_DEBUG
3054 
3055 		// Check if this is a source we should ignore (streams)
3056 		if (pSource->current_stage == STAGE_STREAM)
3057 		{
3058 			pSource->play_duration += ms;
3059 			++i;
3060 			++pSource;
3061 			continue;
3062 		}
3063 
3064 		// Check for invalid sources -- This test should be redundant!
3065 		if (pSource->cookie == 0 || pSource->loaded_sound < 0 || sounds_list[pSource->loaded_sound].sound < 0 || pSource->current_stage == STAGE_UNUSED)
3066 		{
3067 #ifdef _EXTRA_SOUND_DEBUG
3068 			printf("Removing dud sound %d. Cookie: %d, Source Num: %d, Source: %d. Current stage: %d\n", pSource->loaded_sound, pSource->cookie, i, pSource->source, pSource->current_stage);
3069 #endif //_EXTRA_SOUND_DEBUG
3070 			if (pSource->loaded_sound >= 0)
3071 				unload_sound(pSource->loaded_sound);
3072 			stop_sound_source_at_index(i);
3073 			continue;
3074 		}
3075 
3076 		// Update the gain for this source if nessessary
3077 		set_sound_gain(pSource, pSource->loaded_sound, sounds_list[pSource->loaded_sound].base_gain);
3078 
3079 		pSoundType = &sound_type_data[sounds_list[pSource->loaded_sound].sound];
3080 		pVariant = &pSoundType->variant[sounds_list[pSource->loaded_sound].variant];
3081 #ifdef USE_ALGETSOURCEI_AL_BUFFER
3082 		pSample = &sound_sample_data[pVariant->part[pSource->current_stage]->sample_num];
3083 #endif
3084 
3085 		// Is this source still playing?
3086 		alGetSourcei(pSource->source, AL_SOURCE_STATE, &state);
3087 		if (state == AL_STOPPED)
3088 		{
3089 #ifdef _EXTRA_SOUND_DEBUG
3090 //			printf("'%s' has stopped after sample '%s'\n", pSoundType->name, pVariant->part[pSource->current_stage]->file_path);
3091 #endif //_EXTRA_SOUND_DEBUG
3092 			// Flag the sound as finished
3093 			pSource->current_stage = num_STAGES;
3094 		}
3095 		else
3096 		{
3097 			//	TBD - Fix properly
3098 			//	Newer versions of openal do not suppport using alGetSourcei() in this way.
3099 			//	Older versions appear to have always returned (buffer == pSample->buffer) so fall to the else block.
3100 			//	Newer versions always return buffer == 0 so the if block is always called, resulting in most sounds never playing.
3101 			//	The else catches completed sounds anyway so just force the older behavour for now.
3102 			//	The links below cover the openal library change and suggested way to achieve the same behavout ... TDB....
3103 			//	https://github.com/kcat/openal-soft/issues/126
3104 			//	https://github.com/kcat/openal-soft/commit/5c859af24ea44dabbbb31631309bb08a858a523e
3105 #ifdef USE_ALGETSOURCEI_AL_BUFFER // exclude block
3106 			// Find which buffer is playing
3107 			alGetSourcei(pSource->source, AL_BUFFER, &buffer);
3108 			if (buffer != pSample->buffer)
3109 			{
3110 				// The source has moved on to the next queued sample
3111 #ifdef _EXTRA_SOUND_DEBUG
3112 				printf("Cookie: %d, Loaded sound: %d, sound: %d, '%s' - sample '%s' has ended...", pSource->cookie, pSource->loaded_sound, sounds_list[pSource->loaded_sound].sound, pSoundType->name, pVariant->part[pSource->current_stage]->file_path);
3113 				k = 0;
3114 #endif //_EXTRA_SOUND_DEBUG
3115 				while (++pSource->current_stage <= num_STAGES)
3116 				{
3117 #ifdef _EXTRA_SOUND_DEBUG
3118 					k++;
3119 					if (k > num_STAGES)
3120 					{
3121 						LOG_ERROR("update_sound race condition!! cur stage = %d, num_stages = %d\n", pSource->current_stage, num_STAGES);
3122 						printf("update_sound race condition!! cur stage = %d, num_stages = %d\n", pSource->current_stage, num_STAGES);
3123 						pSource->current_stage = num_STAGES;
3124 						break;
3125 					}
3126 #endif // _EXTRA_SOUND_DEBUG
3127 					if (!pVariant->part[pSource->current_stage] || pVariant->part[pSource->current_stage]->sample_num < 0)
3128 					{
3129 						// No more samples to play
3130 #ifdef _EXTRA_SOUND_DEBUG
3131 						printf("no more samples for this type!\n");
3132 #endif //_EXTRA_SOUND_DEBUG
3133 						pSource->current_stage = num_STAGES;
3134 						break;
3135 					}
3136 					pSample = &sound_sample_data[pVariant->part[pSource->current_stage]->sample_num];
3137 					// Found the currently-playing buffer
3138 
3139 					if (pSample->buffer == buffer)
3140 					{
3141 #ifdef _EXTRA_SOUND_DEBUG
3142 						printf("next sample is '%s'\n", pVariant->part[pSource->current_stage]->file_path);
3143 #endif //_EXTRA_SOUND_DEBUG
3144 						if (pSource->current_stage == STAGE_MAIN && pSoundType->loops == 0)
3145 						{
3146 							// We've progressed to the main sample which loops infinitely.
3147 #ifdef _EXTRA_SOUND_DEBUG
3148 							l = 0;
3149 #endif // _EXTRA_SOUND_DEBUG
3150 							do
3151 							{
3152 #ifdef _EXTRA_SOUND_DEBUG
3153 								l++;
3154 								if (l > 10)
3155 								{
3156 									LOG_ERROR("update_sound race condition!! cur buffer = %d, k = %d\n", numProcessed, l);
3157 									printf("update_sound race condition!! cur buffer = %d, k = %d\n", numProcessed, l);
3158 									break;
3159 								}
3160 #endif // _EXTRA_SOUND_DEBUG
3161 								// We only unqueue buffers explicitly here so that there's only the
3162 								// MAIN sample queued for the looping. Normally we just set a zero
3163 								// buffer to the source which automatically unqueues any buffers
3164 								alGetSourcei(pSource->source, AL_BUFFERS_PROCESSED, &numProcessed);
3165 								if (numProcessed-- > 0)
3166 									alSourceUnqueueBuffers(pSource->source, 1, &deadBuffer);
3167 							}
3168 							while (numProcessed > 0);
3169 
3170 							alSourcei(pSource->source, AL_LOOPING, AL_TRUE);
3171 							if ((error=alGetError()) != AL_NO_ERROR)
3172 							{
3173 								LOG_ERROR("update_sound error: %s", alGetString(error));
3174 							}
3175 						}
3176 						break;
3177 					}
3178 				}
3179 			}
3180 			else
3181 #endif // end USE_ALGETSOURCEI_AL_BUFFER exclude block
3182 			{
3183 				if (pSoundType->loops != 0)
3184 				{
3185 					// Check if something odd happened and this source wasn't stopped when the sample finished (lifetime > sum of sample lengths)
3186 					int lifetime = 0;
3187 					for (l = 0; l <= pSource->current_stage; l++)
3188 						if (pVariant->part[l])
3189 							lifetime += sound_sample_data[pVariant->part[l]->sample_num].length;
3190 					if (sounds_list[pSource->loaded_sound].lifetime > lifetime)
3191 					{
3192 #ifdef _EXTRA_SOUND_DEBUG
3193 						printf("This sound has passed its lifetime (%d ms)! It should have been stopped!: %d (%s). Playing: %d, lifetime: %d, cookie: %d\n",
3194 							   lifetime, sounds_list[pSource->loaded_sound].sound, pSoundType->name, sounds_list[pSource->loaded_sound].playing,
3195 							   sounds_list[pSource->loaded_sound].lifetime, sounds_list[pSource->loaded_sound].cookie);
3196 #endif //_EXTRA_SOUND_DEBUG
3197 						unload_sound(pSource->loaded_sound);
3198 						stop_sound_source_at_index(i);
3199 						continue;
3200 					}
3201 				}
3202 			}
3203 		}
3204 
3205 		// Check if we need to remove this sound because its finished
3206 		// If the state is num_STAGES then the sound has ended (or gone wrong)
3207 		if (pSource->current_stage == num_STAGES)
3208 		{
3209 #ifdef _EXTRA_SOUND_DEBUG
3210 			printf("Removing finished sound %d (%s) at cookie %d, source index %d, source %d, loaded_sound: %d\n", sounds_list[pSource->loaded_sound].sound, pSoundType->name, pSource->cookie, i, pSource->source, pSource->loaded_sound);
3211 #endif //_EXTRA_SOUND_DEBUG
3212 			unload_sound(pSource->loaded_sound);
3213 			stop_sound_source_at_index(i);
3214 			continue;
3215 		}
3216 
3217 		// Check if this source is out of range, or back in range (an error!)
3218 		alGetSourcei(pSource->source, AL_SOURCE_RELATIVE, &relative);
3219 		if (relative != AL_TRUE)
3220 		{
3221 			alGetSourcei(pSource->source, AL_SOURCE_STATE, &state);
3222 			alGetSourcefv(pSource->source, AL_POSITION, sourcePos);
3223 			x = sourcePos[0]; y = sourcePos[1];
3224 			distanceSq = (tx - x) * (tx - x) + (ty - y) * (ty - y);
3225 			maxDistSq = pSoundType->distance * pSoundType->distance;
3226 
3227 			if ((state == AL_PLAYING) && (distanceSq > maxDistSq))
3228 			{
3229 #ifdef _EXTRA_SOUND_DEBUG
3230 				printf("Pausing sound: %d (%s), Distance squared: %d, Max: %d\n", i, pSoundType->name, distanceSq, maxDistSq);
3231 #endif //_EXTRA_SOUND_DEBUG
3232 				// Free up this source
3233 				sounds_list[pSource->loaded_sound].playing = 0;
3234 				stop_sound_source_at_index(i);
3235 				continue;
3236 			}
3237 			else if (sound_on && (state == AL_PAUSED) && (distanceSq < maxDistSq))
3238 			{
3239 				LOG_ERROR("Sound error: We found a wasted source. Sound %d (%s) was loaded into a source and paused!!\n", i, pSoundType->name);
3240 				alSourcePlay(pSource->source);
3241 				sounds_list[pSource->loaded_sound].playing = 1;
3242 			}
3243 			if ((error=alGetError()) != AL_NO_ERROR)
3244 		    {
3245 				LOG_ERROR("update_sound %s: %s", my_tolower(reg_error_str), alGetString(error));
3246 		    }
3247 		}
3248 		pSource->play_duration += ms;
3249 		++i;
3250 		++pSource;
3251 	}
3252 
3253 	UNLOCK_SOUND_LIST();
3254 
3255 	if ((error=alGetError()) != AL_NO_ERROR)
3256 	{
3257 #ifdef _EXTRA_SOUND_DEBUG
3258 		printf("Error updating sound: %s\n", alGetString(error));
3259 #endif //_EXTRA_SOUND_DEBUG
3260 	}
3261 }
3262 
3263 
3264 /*********************
3265  * GENERAL FUNCTIONS *
3266  *********************/
3267 
3268 
3269 void handle_walking_sound(actor * pActor, int def_snd)
3270 {
3271 	float x, y;
3272 	int snd, cur_sound;
3273 
3274 	if (pActor->cur_anim.sound_scale > 0.0f)
3275 	{
3276 		// This creature is large enough for a walking sound so look for one
3277 		x = pActor->x_pos;
3278 		y = pActor->y_pos;
3279 
3280 		// Start with the sound from the animation
3281 		snd = def_snd;
3282 
3283 /*		Unfortunatly these functions aren't ready for release.
3284 		They need help to be accurate, possibly from the under_mouse or get_intersect type code.
3285 		Alternatively a check for objects around the actor and then checking the size and rotation
3286 		of each object to determine if the actor is standing on it might work.
3287 
3288 		// Check for a 3d object we have a sound for
3289 		snd = get_3d_obj_walk_sound(get_3dobject_at_location(x, y));
3290 
3291 		// Check if we need to look for a 2d obj, and look if necessary
3292 		if (snd == -1)
3293 			snd = get_2d_obj_walk_sound(get_2dobject_at_location(x, y));
3294 */
3295 
3296 		// If we still don't have a sound, check for a defined area (the same as map boundary areas).
3297 		// NOTE: This code can and should be removed when the above functions are fixed.
3298 		if (snd == -1)
3299 			snd = get_boundary_walk_sound((int)(x * 2), (int)(y * 2));
3300 
3301 		// Finally, check if we need to look for a tile, and look if necessary
3302 		if (snd == -1)
3303 			snd = get_tile_sound(get_tile_type((int)(x * 2), (int)(y * 2)), actors_defs[pActor->actor_type].actor_name);
3304 
3305 #ifdef _EXTRA_SOUND_DEBUG
3306 //		printf("Actor: %s, Pos: %f, %f, Found sound: %d, Scale: %f\n", pActor->actor_name, pActor->x_pos, pActor->y_pos, snd, actors_defs[pActor->actor_type].walk_snd_scale);
3307 #endif // _EXTRA_SOUND_DEBUG
3308 
3309 		if (snd == -1)
3310 			// Still no sound, so fall back on the global default
3311 			snd = walking_default;
3312 
3313 		// Check for something to do
3314 		if (snd > -1)
3315 		{
3316 			// Check if we have a sound and it is different to the current one
3317 			cur_sound = find_sound_from_cookie(pActor->cur_anim_sound_cookie);
3318 			if (cur_sound >= 0 && sounds_list[cur_sound].sound != snd && sound_type_data[sounds_list[cur_sound].sound].type == SOUNDS_WALKING)
3319 			{
3320 				// It is valid and different so remove the current sound before we add the new one
3321 				stop_sound(pActor->cur_anim_sound_cookie);
3322 			}
3323 			if (cur_sound < 0 || sounds_list[cur_sound].sound != snd)
3324 			{
3325 				// Add the new sound
3326 				pActor->cur_anim_sound_cookie = add_walking_sound(	snd,
3327 																	2 * pActor->x_pos,
3328 																	2 * pActor->y_pos,
3329 																	pActor->actor_id == yourself ? 1 : 0,
3330 																	pActor->cur_anim.sound_scale
3331 																);
3332 			}
3333 		}
3334 	}
3335 }
3336 
3337 int get_boundary_walk_sound(int tx, int ty)
3338 {
3339 	int i, snd = -1;
3340 
3341 	if (snd_cur_map > -1 && (sound_map_data[snd_cur_map].file_name[0] != '\0' || sound_map_data[snd_cur_map].id > -1) )
3342 	{
3343 		for (i = 0; i < sound_map_data[snd_cur_map].num_walk_boundaries; i++)
3344 		{
3345 			if (i == sound_map_data[snd_cur_map].num_walk_boundaries)
3346 				i = 0;
3347 			snd = sound_map_data[snd_cur_map].walk_boundaries[i].bg_sound;
3348 			if (snd > -1 && sound_bounds_check(tx, ty, &sound_map_data[snd_cur_map].walk_boundaries[i]))
3349 			{
3350 				return snd;
3351 			}
3352 		}
3353 	}
3354 	return -1;
3355 }
3356 
3357 int get_3d_obj_walk_sound(char * filename)
3358 {
3359 	if (!strcasecmp(filename, ""))
3360 		return -1;
3361 #ifdef _EXTRA_SOUND_DEBUG
3362 	printf("Searching for the sound for 3D object: %s\n", filename);
3363 #endif //_EXTRA_SOUND_DEBUG
3364 	return -1;
3365 }
3366 
3367 int get_2d_obj_walk_sound(char * filename)
3368 {
3369 	if (!strcasecmp(filename, ""))
3370 		return -1;
3371 #ifdef _EXTRA_SOUND_DEBUG
3372 	printf("Searching for the sound for 2D object: %s\n", filename);
3373 #endif //_EXTRA_SOUND_DEBUG
3374 	return -1;
3375 }
3376 
3377 int get_tile_sound(int tile_type, char * actor_type)
3378 {
3379 	int i, j, k;
3380 
3381 	// Check for unknown/invalid tile type
3382 	if (tile_type == -1)
3383 		return -1;
3384 
3385 	for (i = 0; i < MAX_SOUND_TILE_TYPES; i++)
3386 	{
3387 		for (j = 0; j < sound_tile_data[i].num_tile_types; j++)
3388 		{
3389 			if (sound_tile_data[i].tile_type[j] == tile_type)
3390 			{
3391 				// Found a matching tile type so find the actor type
3392 				for (k = 0; k < sound_tile_data[i].num_sounds; k++)
3393 				{
3394 					if (get_string_occurance(actor_type, sound_tile_data[i].sounds[k].actor_types, strlen(actor_type), 0) > -1)
3395 					{
3396 						// Return the sound
3397 						return sound_tile_data[i].sounds[k].sound;
3398 					}
3399 				}
3400 				// Didn't find a sound, so return a default if it exists
3401 				return sound_tile_data[i].default_sound;
3402 			}
3403 		}
3404 	}
3405 	// If we got here, we don't have a sound for this tile type
3406 	return -1;
3407 }
3408 
3409 
3410 void setup_map_sounds (const char * mapname)
3411 {
3412 	int i;
3413 #ifdef DEBUG_MAP_SOUND
3414 	char str[100];
3415 	safe_snprintf(str, sizeof(str), "Map file name: %s", mapname);
3416 	LOG_TO_CONSOLE(c_red1, str);
3417 #endif // DEBUG_MAP_SOUND
3418 	// Find the index for this map in our data
3419 	snd_cur_map = -1;
3420 	for (i = 0; i < sound_num_maps; i++)
3421 	{
3422 		if (strcmp (sound_map_data[i].file_name, mapname) == 0 || get_cur_map(mapname) == sound_map_data[i].id)
3423 		{
3424 			snd_cur_map = i;
3425 #ifdef DEBUG_MAP_SOUND
3426 			safe_snprintf(str, sizeof(str), "Snd config map name: %s", sound_map_data[i].name);
3427 			LOG_TO_CONSOLE(c_red1, str);
3428 			print_sound_boundary_coords(mapname);
3429 #endif // DEBUG_MAP_SOUND
3430 			return;
3431 		}
3432 	}
3433 }
3434 
3435 // Find the index of the sound associated with this cookie.
3436 int find_sound_from_cookie(unsigned int cookie)
3437 {
3438 	int n;
3439 
3440 	if (!cookie || cookie == 0)
3441 		return -1;
3442 
3443 	for (n = 0; n < MAX_BUFFERS * 2; n++)
3444 	{
3445 		if (sounds_list[n].cookie == cookie)
3446 			return n;
3447 	}
3448 
3449 	return -1;
3450 }
3451 
3452 int get_index_for_sound_type_name(const char *name)
3453 {
3454 	int i;
3455 	for(i = 0; i < num_types; ++i)
3456 	{
3457 		if (strcasecmp(sound_type_data[i].name, name) == 0)
3458 			return i;
3459 	}
3460 	return -1;
3461 }
3462 
3463 // Look for a particle sound def matching the input filename
3464 // (minus the directory ./particles/ and extension .part)
3465 int get_sound_index_for_particle_file_name(const char *name)
3466 {
3467 	char my_name[MAX_FILENAME_LENGTH];
3468 	int i;
3469 	safe_strncpy(my_name, name+12, sizeof(my_name));
3470 	my_name[strlen(my_name) - 5] = '\0';
3471 	for(i = 0; i < sound_num_particles; ++i)
3472 	{
3473 		if (strcasecmp(sound_particle_data[i].file, my_name) == 0)
3474 			return sound_particle_data[i].sound;
3475 	}
3476 	return -1;
3477 }
3478 
3479 // Looks for a sound effect def matching the input special effect
3480 int get_sound_index_for_sfx(int sfx)
3481 {
3482 	int i;
3483 	for(i = 0; i < sound_num_effects; ++i)
3484 	{
3485 		if (sound_effect_data[i].id == sfx)
3486 			return sound_effect_data[i].sound;
3487 	}
3488 	return -1;
3489 }
3490 
3491 int get_index_for_inv_usewith_item_sound(int use_image_id, int with_image_id)
3492 {
3493 	char name[MAX_SOUND_NAME_LENGTH];
3494 
3495 #ifdef _EXTRA_SOUND_DEBUG
3496 	printf("Searching for the sound for: %d on %d\n", use_image_id, with_image_id);
3497 #endif //_EXTRA_SOUND_DEBUG
3498 	snprintf(name, sizeof(name), "%d on %d", use_image_id, with_image_id);
3499 	return get_index_for_sound_type_name(name);
3500 }
3501 
3502 int get_index_for_inv_use_item_sound(int image_id)
3503 {
3504 	int i, j;
3505 #ifdef _EXTRA_SOUND_DEBUG
3506 	printf("Searching for the sound for image ID: %d\n", image_id);
3507 #endif //_EXTRA_SOUND_DEBUG
3508 	for (i = 0; i < sound_num_items; ++i)
3509 	{
3510 		for (j = 0; j < sound_item_data[i].num_imageids; j++)
3511 		{
3512 			if (sound_item_data[i].image_id[j] == image_id)
3513 				return sound_item_data[i].sound;
3514 		}
3515 	}
3516 	return -1;
3517 }
3518 
3519 int check_sound_loops(unsigned int cookie)
3520 {
3521 	int snd = find_sound_from_cookie(cookie);
3522 	if (snd > -1 && sound_type_data[sounds_list[snd].sound].loops == 0)
3523 		return 1;
3524 	return 0;
3525 }
3526 
3527 void check_sound_alerts(const Uint8* text, size_t len, Uint8 channel)
3528 {
3529 	int i;
3530 	for (i = 0; i < num_sound_warnings; i++)
3531 	{
3532 		if (safe_strcasestr((char *)text, len, warnings_list[i].string, strlen(warnings_list[i].string)))
3533 		{
3534 			add_sound_object_gain(warnings_list[i].sound, 0, 0, 1, 1.0f);
3535 			return;		// Only play one sound
3536 		}
3537 	}
3538 	return;
3539 }
3540 
3541 // Compare the input flags to the current time and return true if they match
3542 int time_of_day_valid(int flags)
3543 {
3544 	return flags & (1 << (game_minute / 30));
3545 }
3546 
3547 /* sound_bounds_check
3548  *
3549  * Check if input point (x, y) is within the input boundary
3550  *
3551  * Initially test to see if the point given is within the outer boundary given by the extreme of the coords. If
3552  * it is, then continue with the more complex test of each boundary line.
3553  *
3554  * We will do this by checking the angle of the line created between each of the 4 points of the boundaries and
3555  * comparing that angle to the line created by each point and our test point.
3556  *
3557  */
3558 int sound_bounds_check(int x, int y, map_sound_boundary_def * bounds)
3559 {
3560 	int pX, pY, npX, npY;
3561 	int i, j, result;
3562 
3563 	// Initially check if we are on or inside the outermost box
3564 	if (x < bounds->o[0].x || y < bounds->o[0].y || x > bounds->o[1].x || y > bounds->o[1].y)
3565 		return 0;	// We are outside the outer rectangle so can't be inside the polygon
3566 
3567 	// Check if we have only 2 points (rectangle) and are therefore don't need to do anything more
3568 	if (bounds->p[2].x == -1 || bounds->p[2].y == -1 || bounds->p[3].x == -1 || bounds->p[3].y == -1)
3569 		return 1;
3570 
3571 	// Check if we are inside the 4 lines of the polygon
3572 	for (i = 0; i < 4; i++)
3573 	{
3574 		j = i + 1;
3575 		if (j == 4) j = 0;	// Wrap the next point var around to 0
3576 		pX = bounds->p[i].x;
3577 		pY = bounds->p[i].y;
3578 		npX = bounds->p[j].x;
3579 		npY = bounds->p[j].y;
3580 
3581 		/* Psuedo-code to explain this block of nastiness
3582 
3583 		If (this is not an internal point, OR
3584 			(if the x coord of our test point is within the x bounds of the line with p <= np AND
3585 				((the y coord is within the line with p <= np AND the point is within the y bounds of the line (bottom left quadrant)) OR
3586 				 (the y coord is within the line with p > np AND the point is within the y bounds of the line (top left quadrant))
3587 			) OR
3588 			(if the x coord is within the x bounds of the line with p > np AND
3589 				((the y coord is within the line with p <= np AND the point is within the y bounds of the line (bottom right quadrant)) OR
3590 				 (the y coord is within the line with p > np AND the the point is within the y bounds of the line (top right quadrant))
3591 			)
3592 		) ...then we need to test the angle otherwise we can ignore this point
3593 		*/
3594 		if (bounds->int_point != i ||
3595 			(pX <= npX && x >= pX && x <= pX &&
3596 				((pY <= npY && y >= pY && y <= pY) ||
3597 				 (pY >  npY && y <= pY && y >= pY))
3598 			) ||
3599 			(pX > npX && x <= pX && x >= pX &&
3600 				((pY <= npY && y >= pY && y <= pY) ||
3601 				 (pY >  npY && y <= pY && y >= pY))
3602 			)
3603 		)
3604 		{
3605 			result = test_bounds_angles(x, y, i, bounds);
3606 			if (result == 0) return 0;
3607 		}
3608 	}
3609 
3610 	// This point is inside the 4 lines
3611 	return 1;
3612 }
3613 
3614 int test_bounds_angles(int x, int y, int point, map_sound_boundary_def * bounds)
3615 {
3616 	double a = calculate_bounds_angle(x, y, point, bounds);
3617 
3618 	// If our angle for the test point is greater than the angle of the boundary line, then the point is outside
3619 	if (a > bounds->p[point].a)
3620 		return 0;
3621 	return 1;
3622 }
3623 
3624 /* This function is the complex one!
3625  *
3626  * If you notice the pattern for the subsitutions below, it is because we are rotating the 0 degree angle around
3627  * the axis to keep it on the outside of the polygon. We need to do this because if our test line crosses from
3628  * > 2pi to < 2pi it will give a false positive.
3629  *
3630  * For point 0 the "illegal zone" is straight down, for point 1 horizontally left, for point 2 straight up, and
3631  * for point 3 horizontally right.
3632  *
3633  * This is why point 0 (or A in my diagrams) is the bottom left as nothing should cross it there, and so on for
3634  * the other points around the polygon. Each "illegal zone" should be pointing outside almost all permutations of
3635  * a polygon.
3636  *
3637  * If none of this makes sense then grab one of my drawings and if it still doesn't then ask. Grab me and ask.
3638  *  - Torg -
3639  *
3640  * Inputs:
3641  * 		x				The x coord of our test point
3642  * 		y				The y coord of our test point
3643  * 		point			The ID of the boundary point we are calculating from
3644  *		bounds			The boundary we are calculating this point of
3645  */
3646 double calculate_bounds_angle(int x, int y, int point, map_sound_boundary_def * bounds)
3647 {
3648 	int A = 0,
3649 		B = 0,
3650 		C = 0,
3651 		D = 0;
3652 	double pi = 3.1415;
3653 	double ra = pi / 2;		// ra = Right angle... meh
3654 	double a;
3655 
3656 	//  Set up the subsitutions for the actual equation. (This is such a waste of space. Grrr)
3657 	switch (point)
3658 	{
3659 		case 0:
3660 			// Check the angle of the line from the bottom left corner to our test point (point0 -> pointT)
3661 			A = bounds->p[0].y;
3662 			B = y;
3663 			C = bounds->p[0].x;
3664 			D = x;
3665 			break;
3666 		case 1:
3667 			// Check the angle of the line from the top left corner to our test point (point1 -> pointT)
3668 			A = bounds->p[1].x;
3669 			B = x;
3670 			C = y;
3671 			D = bounds->p[1].y;
3672 			break;
3673 		case 2:
3674 			// Check the angle of the line from the top right corner to our test point (point2 -> pointT)
3675 			A = y;
3676 			B = bounds->p[2].y;
3677 			C = x;
3678 			D = bounds->p[2].x;
3679 			break;
3680 		case 3:
3681 			// Check the angle of the line from the bottom right corner to our test point (point3 -> pointT)
3682 			A = x;
3683 			B = bounds->p[3].x;
3684 			C = bounds->p[3].y;
3685 			D = y;
3686 			break;
3687 	}
3688 	// If the line aligns to an axis, arctan has no value, so we need to check for this and use 90 degrees (pi / 2)
3689 	// Otherwise calculate the angle and adjust the negative
3690 	if (A == B && C < D) a = ra;			// If axis 1 is aligned and the coord on axis 2 of the first point is less
3691 	else if (A == B && C > D) a = -ra;		// If axis 1 is aligned and the coord on axis 2 of the first point is greater
3692 	else a = atan2((D - C), (A - B));		// If we aren't on the axis, find the angle
3693 	if (D < C) a += pi * 2;					// If the second point is below the axis (-pi) then boost the angle to the positive (2pi)
3694 											// This gives us a proper range from 0 to 2pi counter clockwise around the polygon
3695 
3696 	return a;
3697 }
3698 
3699 #ifdef DEBUG_MAP_SOUND
3700 // Print the sound area boundaries onto the tab-map (called from interface.c)
3701 //
3702 // It is a known bug that this _does not_ scale to the map selected. The scale will stay the same as your currently loaded map!
3703 //
3704 void print_sound_boundaries(const char *mapname)
3705 {
3706 	int i, i_max, j, id = -1, scale = 6, num_def = 0;
3707 	char buf[256];
3708 	map_sound_boundary_def *bounds;
3709 	bound_point p[4];
3710 
3711 	// Check if this map matches an array id
3712 	for (i = 0; i < MAX_SOUND_MAPS; i++) {
3713 		if (strcmp (sound_map_data[i].file_name, mapname) == 0 || get_cur_map(mapname) == sound_map_data[i].id ) {
3714 			id = i;
3715 			break;
3716 		}
3717 	}
3718 	if (id == -1) return;	// Didn't find the map in our array so bail
3719 
3720 	// count default boundary sounds - they do not have points
3721 	for (i=0; i<sound_map_data[id].num_boundaries; i++)
3722 		if (sound_map_data[id].boundaries[i].is_default)
3723 			num_def++;
3724 
3725 	glEnable (GL_TEXTURE_2D);
3726 	glColor3f (1.0f, 1.0f, 1.0f);
3727 	safe_snprintf(buf, sizeof(buf), "Map File Name: %s, Array ID: %d\nMap Name: %s\nNum Bound: %d (%d def), Num Walk: %d", mapname, id, sound_map_data[id].name,
3728 				  sound_map_data[id].num_boundaries, num_def, sound_map_data[id].num_walk_boundaries);
3729 	draw_string_zoomed_width_font(main_map_screen_x_left, main_map_screen_y_bottom/10, (unsigned char*)buf, main_map_screen_x_right-main_map_screen_x_left,3,UI_FONT, get_global_scale());
3730 	glDisable(GL_TEXTURE_2D);
3731 	glBegin(GL_LINES);
3732 	// Draw boundaries for this map
3733 	for (j = 0; j < 2; j++) {
3734 		if (j == 0) {
3735 			i_max = sound_map_data[id].num_walk_boundaries;
3736 		} else {
3737 			i_max = sound_map_data[id].num_boundaries;
3738 		}
3739 		for (i = 0; i < i_max; i++) {
3740 			if (j == 0) {
3741 				bounds = &sound_map_data[id].walk_boundaries[i];
3742 				glColor3f (0.0f, 0.0f, 1.0f);
3743 			} else {
3744 				bounds = &sound_map_data[id].boundaries[i];
3745 				if (bounds->is_default)
3746 					continue;
3747 				glColor3f (1.0f, 0.0f, 0.0f);
3748 			}
3749 			if (bounds->p[2].x == -1 || bounds->p[2].y == -1 || bounds->p[3].x == -1 || bounds->p[3].y == -1)
3750 			{
3751 				p[0].x = main_map_screen_x_left + (main_map_screen_x_right - main_map_screen_x_left) * bounds->p[0].x / (tile_map_size_x * scale);
3752 				p[1].x = main_map_screen_x_left + (main_map_screen_x_right - main_map_screen_x_left) * bounds->p[1].x / (tile_map_size_x * scale);
3753 				p[2].x = main_map_screen_x_left + (main_map_screen_x_right - main_map_screen_x_left) * bounds->p[1].x / (tile_map_size_x * scale);
3754 				p[3].x = main_map_screen_x_left + (main_map_screen_x_right - main_map_screen_x_left) * bounds->p[0].x / (tile_map_size_x * scale);
3755 				p[0].y = main_map_screen_y_bottom - (main_map_screen_y_bottom - main_map_screen_y_top) * bounds->p[0].y / (tile_map_size_y * scale);
3756 				p[1].y = main_map_screen_y_bottom - (main_map_screen_y_bottom - main_map_screen_y_top) * bounds->p[0].y / (tile_map_size_y * scale);
3757 				p[2].y = main_map_screen_y_bottom - (main_map_screen_y_bottom - main_map_screen_y_top) * bounds->p[1].y / (tile_map_size_y * scale);
3758 				p[3].y = main_map_screen_y_bottom - (main_map_screen_y_bottom - main_map_screen_y_top) * bounds->p[1].y / (tile_map_size_y * scale);
3759 			}
3760 			else
3761 			{
3762 				p[0].x = main_map_screen_x_left + (main_map_screen_x_right - main_map_screen_x_left) * bounds->p[0].x / (tile_map_size_x * scale);
3763 				p[1].x = main_map_screen_x_left + (main_map_screen_x_right - main_map_screen_x_left) * bounds->p[1].x / (tile_map_size_x * scale);
3764 				p[2].x = main_map_screen_x_left + (main_map_screen_x_right - main_map_screen_x_left) * bounds->p[2].x / (tile_map_size_x * scale);
3765 				p[3].x = main_map_screen_x_left + (main_map_screen_x_right - main_map_screen_x_left) * bounds->p[3].x / (tile_map_size_x * scale);
3766 				p[0].y = main_map_screen_y_bottom - (main_map_screen_y_bottom - main_map_screen_y_top) * bounds->p[0].y / (tile_map_size_y * scale);
3767 				p[1].y = main_map_screen_y_bottom - (main_map_screen_y_bottom - main_map_screen_y_top) * bounds->p[1].y / (tile_map_size_y * scale);
3768 				p[2].y = main_map_screen_y_bottom - (main_map_screen_y_bottom - main_map_screen_y_top) * bounds->p[2].y / (tile_map_size_y * scale);
3769 				p[3].y = main_map_screen_y_bottom - (main_map_screen_y_bottom - main_map_screen_y_top) * bounds->p[3].y / (tile_map_size_y * scale);
3770 			}
3771 
3772 			glVertex2i(p[0].x, p[0].y);
3773 			glVertex2i(p[1].x, p[1].y);
3774 
3775 			glVertex2i(p[1].x, p[1].y);
3776 			glVertex2i(p[2].x, p[2].y);
3777 
3778 			glVertex2i(p[2].x, p[2].y);
3779 			glVertex2i(p[3].x, p[3].y);
3780 
3781 			glVertex2i(p[3].x, p[3].y);
3782 			glVertex2i(p[0].x, p[0].y);
3783 		}
3784 	}
3785 	glEnd();
3786 }
3787 
3788 // Prints the sound boundary coords for the input map to stdout
3789 void print_sound_boundary_coords(const char *mapname)
3790 {
3791 	int i, i_max, j, id = -1;
3792 	map_sound_boundary_def *bounds;
3793 
3794 	// Check if this map matches an array id
3795 	for (i = 0; i < MAX_SOUND_MAPS; i++) {
3796 		if (strcmp (sound_map_data[i].file_name, mapname) == 0 || get_cur_map(mapname) == sound_map_data[i].id ) {
3797 			id = i;
3798 			break;
3799 		}
3800 	}
3801 	if (id == -1) return;	// Didn't find the map in our array so bail
3802 
3803 	printf("Map File Name: %s, Array ID: %d, Map Name: %s, ", mapname, id, sound_map_data[id].name);
3804 	// Print boundaries for this map
3805 	for (j = 0; j < 2; j++) {
3806 		if (j == 0) {
3807 			i_max = sound_map_data[id].num_walk_boundaries;
3808 			printf("Num Walk Boundaries: %d\n", i_max);
3809 		} else {
3810 			i_max = sound_map_data[id].num_boundaries;
3811 			printf("Num Boundaries: %d\n", i_max);
3812 		}
3813 		for (i = 0; i < i_max; i++) {
3814 			if (j == 0) {
3815 				bounds = &sound_map_data[id].walk_boundaries[i];
3816 			} else {
3817 				bounds = &sound_map_data[id].boundaries[i];
3818 			}
3819 			printf("Outer - 1: %d, %d; 2: %d, %d\n", bounds->o[0].x, bounds->o[0].y, bounds->o[1].x, bounds->o[1].y);
3820 			printf("Points - 1: %d, %d; 2: %d, %d; 3: %d, %d; 4: %d, %d\n", bounds->p[0].x, bounds->p[0].y, bounds->p[1].x, bounds->p[1].y
3821 				   															, bounds->p[2].x, bounds->p[2].y, bounds->p[3].x, bounds->p[3].y);
3822 		}
3823 	}
3824 }
3825 #endif // DEBUG_MAP_SOUND
3826 
3827 
3828 
3829 /******************
3830  * INIT FUNCTIONS *
3831  ******************/
3832 
3833 void clear_variant(sound_variants *pVariant)
3834 {
3835 	int i;
3836 	for (i = 0; i < num_STAGES; i++)
3837 	{
3838 		pVariant->part[i] = NULL;
3839 	}
3840 	pVariant->gain = 1.0f;
3841 }
3842 
3843 void clear_sound_type(int type)
3844 {
3845 	int i;
3846 	sound_type * sound;
3847 
3848 	if (type < 0 || type > MAX_SOUNDS)
3849 		return;
3850 
3851 	sound = &sound_type_data[type];
3852 
3853 	sound->name[0] = '\0';
3854 	for (i = 0; i < MAX_SOUND_VARIANTS; i++)
3855 	{
3856 		clear_variant(&sound->variant[i]);
3857 	}
3858 	sound->num_variants = 0;
3859 	sound->stereo = 0;
3860 	sound->distance = 100.0f;
3861 	sound->positional = 1;
3862 	sound->loops = 1;
3863 	sound->fadeout_time = 0;
3864 	sound->echo_delay = 0;
3865 	sound->echo_volume = 50;
3866 	sound->time_of_the_day_flags = 0xffff;
3867 	sound->priority = 5;
3868 	sound->type = SOUNDS_ENVIRO;
3869 }
3870 
3871 void clear_boundary_data(map_sound_boundary_def * pBoundary)
3872 {
3873 	int i;
3874 
3875 	pBoundary->bg_sound = -1;
3876 	pBoundary->crowd_sound = -1;
3877 	pBoundary->time_of_day_flags = 0xffff;
3878 	pBoundary->is_default = 0;
3879 	for (i = 0; i < 4; i++)
3880 	{
3881 		pBoundary->p[i].x = -1;
3882 		pBoundary->p[i].y = -1;
3883 		pBoundary->p[i].a = -1;
3884 	}
3885 	pBoundary->o[0].x = -1;
3886 	pBoundary->o[0].y = -1;
3887 	pBoundary->o[1].x = -1;
3888 	pBoundary->o[1].y = -1;
3889 	pBoundary->int_point = -1;
3890 }
3891 
3892 void clear_sound_data()
3893 {
3894 	int i, j;
3895 
3896 	for (i = 0; i < MAX_BUFFERS * 2; i++)
3897 	{
3898 		sounds_list[i].sound = -1;
3899 		sounds_list[i].x = -1;
3900 		sounds_list[i].y = -1;
3901 		sounds_list[i].cookie = 0;
3902 		sounds_list[i].loaded = 0;
3903 		sounds_list[i].playing = 0;
3904 		sounds_list[i].base_gain = 0.0f;
3905 		sounds_list[i].cur_gain = 0.0f;
3906 	}
3907 	for (i = 0; i < MAX_STREAMS; i++)
3908 	{
3909 		destroy_stream(&streams[i]);
3910 	}
3911 	for (i = 0; i < MAX_SOUNDS; i++)
3912 	{
3913 		clear_sound_type(i);
3914 	}
3915 	for (i = 0; i < MAX_BUFFERS; i++)
3916 	{
3917 		unload_sample(i);
3918 	}
3919 	for (i = 0; i < MAX_BACKGROUND_DEFAULTS; i++)
3920 	{
3921 		sound_background_defaults[i].time_of_day_flags = 0xffff;
3922 		sound_background_defaults[i].map_type = 0;
3923 		sound_background_defaults[i].sound = -1;
3924 	}
3925 	crowd_default = -1;
3926 	walking_default = -1;
3927 	for (i = 0; i < MAX_SOUND_MAPS; i++)
3928 	{
3929 		sound_map_data[i].id = -1;
3930 		sound_map_data[i].file_name[0] = '\0';
3931 		sound_map_data[i].name[0] = '\0';
3932 		sound_map_data[i].num_boundaries = 0;
3933 		for (j = 0; j < MAX_SOUND_MAP_BOUNDARIES; j++)
3934 		{
3935 			clear_boundary_data(&sound_map_data[i].boundaries[j]);
3936 		}
3937 		sound_map_data[i].num_walk_boundaries = 0;
3938 		for (j = 0; j < MAX_SOUND_WALK_BOUNDARIES; j++)
3939 		{
3940 			clear_boundary_data(&sound_map_data[i].walk_boundaries[j]);
3941 		}
3942 		sound_map_data[i].num_defaults = 0;
3943 		for (j = 0; j < MAX_MAP_BACKGROUND_DEFAULTS; j++)
3944 		{
3945 			sound_map_data[i].defaults[j] = 0;
3946 		}
3947 	}
3948 	for (i = 0; i < MAX_SOUND_EFFECTS; i++)
3949 	{
3950 		sound_effect_data[i].id = 0;
3951 		sound_effect_data[i].sound = -1;
3952 	}
3953 	for (i = 0; i < MAX_SOUND_PARTICLES; i++)
3954 	{
3955 		sound_particle_data[i].file[0] = '\0';
3956 		sound_particle_data[i].sound = -1;
3957 	}
3958 	for (i = 0; i < MAX_SOUND_ITEMS; i++)
3959 	{
3960 		for (j = 0; j < MAX_ITEM_SOUND_IMAGE_IDS; j++)
3961 		{
3962 			sound_item_data[i].image_id[j] = -1;
3963 		}
3964 		sound_item_data[i].num_imageids = 0;
3965 		sound_item_data[i].sound = -1;
3966 	}
3967 	for (i = 0; i < MAX_SOUND_TILE_TYPES; i++)
3968 	{
3969 		for (j = 0; j < MAX_SOUND_TILES; j++)
3970 		{
3971 			sound_tile_data[i].tile_type[j] = -1;
3972 		}
3973 		sound_tile_data[i].num_tile_types = 0;
3974 		for (j = 0; j < MAX_SOUND_TILES_SOUNDS; j++)
3975 		{
3976 			sound_tile_data[i].sounds[j].actor_types[0] = '\0';
3977 			sound_tile_data[i].sounds[j].sound = -1;
3978 		}
3979 		sound_tile_data[i].num_sounds = 0;
3980 		sound_tile_data[i].default_sound = -1;
3981 	}
3982 	for (i = 0; i < MAX_SERVER_SOUNDS; i++)
3983 	{
3984 		server_sound[i] = -1;
3985 	}
3986 	for (i = 0; i < NUM_ACTIVE_SPELLS; i++)
3987 	{
3988 		sound_spell_data[i] = -1;
3989 	}
3990 	for (i = 0; i < MAX_SOUND_WARNINGS; i++)
3991 	{
3992 		warnings_list[i].sound = -1;
3993 		warnings_list[i].string[0] = '\0';
3994 	}
3995 	for (i = 0; i < MAX_SOUND_FILES; i++)
3996 	{
3997 		sound_files[i].file_path[0] = '\0';
3998 		sound_files[i].sample_num = -1;
3999 	}
4000 
4001 	num_types = 0;
4002 	num_samples = 0;
4003 	sound_num_background_defaults = 0;
4004 	sound_num_maps = 0;
4005 	sound_num_effects = 0;
4006 	sound_num_particles = 0;
4007 	sound_num_items = 0;
4008 	sound_num_tile_types = 0;
4009 	num_sound_warnings = 0;
4010 	num_sound_files = 0;
4011 }
4012 
4013 /* done once at start up to create the sound list mutex */
4014 void initial_sound_init(void)
4015 {
4016 	size_t i, j, k;
4017 	sound_list_mutex = SDL_CreateMutex();
4018 	if (!sound_list_mutex)
4019 	{
4020 		LOG_ERROR("Fatal error, unable to create sound list mutex: %s\n", SDL_GetError());
4021 		SDL_Quit();
4022 		exit(1);
4023 	}
4024 
4025 	/* create arrays and do minimum initisation - memsetting to zero is not good enough.
4026 	 * These arrays were previous static and so valgrind could not determine if there were
4027 	 * memory access errors, this way we can work through them.  How it worked before is
4028 	 * unknown.  TO DO: Need to dedupe this code with clear_sound_data()....
4029 	 */
4030 
4031 	streams = (stream_data *)malloc(sizeof(stream_data) * MAX_STREAMS);
4032 	for (i=0; i<MAX_STREAMS; i++)
4033 	{
4034 		streams[i].type = STREAM_TYPE_NONE;
4035 		streams[i].sound = -1;
4036 		streams[i].source = 0;
4037 		streams[i].cookie = 0;
4038 		memset(&streams[i].buffers, 0, sizeof(ALuint) * NUM_STREAM_BUFFERS);
4039 		memset(&streams[i].stream, 0, sizeof(OggVorbis_File));
4040 		streams[i].stream_opened = 0;
4041 		streams[i].fade_length = 10;
4042 		streams[i].boundary = NULL;
4043 		streams[i].info = NULL;
4044 		streams[i].fade = streams[i].processed = streams[i].playing = streams[i].variant = streams[i].is_default = 0;
4045 	}
4046 
4047 	sounds_list = (sound_loaded *)malloc(sizeof(sound_loaded) * MAX_BUFFERS * 2);
4048 	for (i=0; i<MAX_BUFFERS * 2; i++)
4049 	{
4050 		sounds_list[i].sound = sounds_list[i].variant = sounds_list[i].x = sounds_list[i].y = -1;
4051 		sounds_list[i].loaded = sounds_list[i].playing = sounds_list[i].lifetime = 0;
4052 		sounds_list[i].base_gain = sounds_list[i].cur_gain = 0.0f;
4053 		sounds_list[i].cookie = 0;
4054 	}
4055 
4056 	sound_source_data = (source_data*)malloc(sizeof(source_data) * ABS_MAX_SOURCES);
4057 	for (i=0; i<ABS_MAX_SOURCES; i++)
4058 	{
4059 		source_data* p = &sound_source_data[i];
4060 		p->source = 0;
4061 		p->priority = p->play_duration = 0;
4062 		p->current_stage = STAGE_UNUSED;
4063 		p->loaded_sound = -1;
4064 		p->cookie = 0;
4065 		for (j=0; j<num_STAGES; j++)
4066 			p->sample[j] = -1;
4067 	}
4068 
4069 	sound_type_data = (sound_type*)malloc(sizeof(sound_type) * MAX_SOUNDS);
4070 	for (i=0; i<MAX_SOUNDS; i++)
4071 	{
4072 		sound_type* p = &sound_type_data[i];
4073 		p->name[0] = '\0';
4074 		p->num_variants = p->stereo = p->fadeout_time = p->echo_delay = 0;
4075 		p->echo_volume = 50;
4076 		p->distance = 100.0f;
4077 		p->time_of_the_day_flags = 0xffff;
4078 		p->type = SOUNDS_NONE;
4079 		p->positional = p->loops = 1;
4080 		p->priority = p->loops = 50;
4081 		for (j=0; j<MAX_SOUND_VARIANTS; j++)
4082 		{
4083 			for (k=0; k<num_STAGES; k++)
4084 				p->variant[j].part[k] = NULL;
4085 			p->variant[j].gain = 0.0f;
4086 		}
4087 	}
4088 
4089 	sound_sample_data = (sound_sample*)malloc(sizeof(sound_sample) * MAX_BUFFERS);
4090 	for (i=0; i<MAX_BUFFERS; i++)
4091 	{
4092 		sound_sample* p = &sound_sample_data[i];
4093 		p->sources = NULL;
4094 		p->buffer = 0;
4095 		p->format = 0;
4096 		p->size = 0;
4097 		p->freq = 0.0;
4098 		p->channels = p->bits = 0;
4099 		p->length = 0;
4100 	}
4101 
4102 	// as clear_sound_data()
4103 	sound_files = (sound_file*)malloc(sizeof(sound_file) * MAX_SOUND_FILES);
4104 	for (i=0; i<MAX_SOUND_FILES; i++)
4105 	{
4106 		sound_files[i].file_path[0] = '\0';
4107 		sound_files[i].sample_num = -1;
4108 	}
4109 
4110 	sound_background_defaults = (background_default*)malloc(sizeof(background_default) * MAX_BACKGROUND_DEFAULTS);
4111 	for (i=0; i<MAX_BACKGROUND_DEFAULTS; i++)
4112 	{
4113 		sound_background_defaults[i].time_of_day_flags = 0xffff;
4114 		sound_background_defaults[i].map_type = 0;
4115 		sound_background_defaults[i].sound = -1;
4116 	}
4117 
4118 	sound_map_data = (map_sound_data*)malloc(sizeof(map_sound_data) * MAX_SOUND_MAPS);
4119 	for (i=0; i<MAX_SOUND_MAPS; i++)
4120 	{
4121 		sound_map_data[i].num_boundaries = sound_map_data[i].num_defaults = sound_map_data[i].num_walk_boundaries = 0;
4122 		sound_map_data[i].id = -1;
4123 		sound_map_data[i].file_name[0] = '\0';
4124 	}
4125 
4126 	// as clear_sound_data()
4127 	sound_effect_data = (effect_sound_data*)malloc(sizeof(effect_sound_data) * MAX_SOUND_EFFECTS);
4128 	for (i=0; i<MAX_SOUND_EFFECTS; i++)
4129 	{
4130 		sound_effect_data[i].id = 0;
4131 		sound_effect_data[i].sound = -1;
4132 	}
4133 
4134 	// as clear_sound_data()
4135 	sound_particle_data = (particle_sound_data*)malloc(sizeof(particle_sound_data) * MAX_SOUND_PARTICLES);
4136 	for (i=0; i<MAX_SOUND_PARTICLES; i++)
4137 	{
4138 		sound_particle_data[i].file[0] = '\0';
4139 		sound_particle_data[i].sound = -1;
4140 	}
4141 
4142 	// as clear_sound_data()
4143 	sound_item_data = (item_sound_data*)malloc(sizeof(item_sound_data) * MAX_SOUND_ITEMS);
4144 	for (i=0; i<MAX_SOUND_ITEMS; i++)
4145 	{
4146 		for (j = 0; j < MAX_ITEM_SOUND_IMAGE_IDS; j++)
4147 			sound_item_data[i].image_id[j] = -1;
4148 		sound_item_data[i].num_imageids = 0;
4149 		sound_item_data[i].sound = -1;
4150 	}
4151 
4152 	// as clear_sound_data()
4153 	sound_tile_data = (tile_sound_data*)malloc(sizeof(tile_sound_data) * MAX_SOUND_TILE_TYPES);
4154 	for (i=0; i<MAX_SOUND_TILE_TYPES; i++)
4155 	{
4156 		for (j = 0; j < MAX_SOUND_TILES; j++)
4157 		{
4158 			sound_tile_data[i].tile_type[j] = -1;
4159 		}
4160 		sound_tile_data[i].num_tile_types = 0;
4161 		for (j = 0; j < MAX_SOUND_TILES_SOUNDS; j++)
4162 		{
4163 			sound_tile_data[i].sounds[j].actor_types[0] = '\0';
4164 			sound_tile_data[i].sounds[j].sound = -1;
4165 		}
4166 		sound_tile_data[i].num_sounds = 0;
4167 		sound_tile_data[i].default_sound = -1;
4168 	}
4169 
4170 	// as clear_sound_data()
4171 	server_sound = (int*)malloc(sizeof(int) * MAX_SERVER_SOUNDS);
4172 	for (i=0; i<MAX_SERVER_SOUNDS; i++)
4173 		server_sound[i] = -1;
4174 
4175 	// as clear_sound_data()
4176 	sound_spell_data = (int*)malloc(sizeof(int) * NUM_ACTIVE_SPELLS);
4177 	for (i=0; i<NUM_ACTIVE_SPELLS; i++)
4178 		sound_spell_data[i] = -1;
4179 
4180 	// as clear_sound_data()
4181 	warnings_list = (sound_warnings*)malloc(sizeof(sound_warnings) * MAX_SOUND_WARNINGS);
4182 	for (i = 0; i < MAX_SOUND_WARNINGS; i++)
4183 	{
4184 		warnings_list[i].sound = -1;
4185 		warnings_list[i].string[0] = '\0';
4186 	}
4187 
4188 	// NOT as clear_sound_data()
4189 	playlist = (playlist_entry*)malloc(sizeof(playlist_entry) * MAX_PLAYLIST_ENTRIES);
4190 	clear_playlist();
4191 
4192 	// as clear_sound_data()
4193 	num_types = 0;
4194 	num_samples = 0;
4195 	sound_num_background_defaults = 0;
4196 	sound_num_maps = 0;
4197 	sound_num_effects = 0;
4198 	sound_num_particles = 0;
4199 	sound_num_items = 0;
4200 	sound_num_tile_types = 0;
4201 	num_sound_warnings = 0;
4202 	num_sound_files = 0;
4203 
4204 	return;
4205 }
4206 
4207 static void clear_playlist(void)
4208 {
4209 	size_t i;
4210 	for (i=0; i<MAX_PLAYLIST_ENTRIES; i++)
4211 	{
4212 		playlist[i].file_name[0] = '\0';
4213 		playlist[i].min_x = playlist[i].max_x = playlist[i].min_y = playlist[i].max_y = playlist[i].time = 0;
4214 	}
4215 }
4216 
4217 /* done once at exit to delete the sound list mutex */
4218 void final_sound_exit(void)
4219 {
4220 	SDL_DestroyMutex(sound_list_mutex);
4221 	sound_list_mutex = NULL;
4222 	free(streams); streams = NULL;
4223 	free(sounds_list); sounds_list = NULL;
4224 	free(sound_source_data); sound_source_data = NULL;
4225 	free(sound_type_data); sound_type_data = NULL;
4226 	free(sound_sample_data); sound_sample_data = NULL;
4227 	free(sound_files); sound_files = NULL;
4228 	free(sound_background_defaults); sound_background_defaults = NULL;
4229 	free(sound_map_data); sound_map_data = NULL;
4230 	free(sound_effect_data); sound_effect_data = NULL;
4231 	free(sound_particle_data); sound_particle_data = NULL;
4232 	free(sound_item_data); sound_item_data = NULL;
4233 	free(sound_tile_data); sound_tile_data = NULL;
4234 	free(server_sound); server_sound = NULL;
4235 	free(sound_spell_data); sound_spell_data = NULL;
4236 	free(warnings_list); warnings_list = NULL;
4237 	free(playlist); playlist = NULL;
4238 }
4239 
4240 void init_sound()
4241 {
4242 	ALCcontext *context;
4243 	ALCdevice *device;
4244 	ALfloat listenerPos[3] = {0.0f, 0.0f, 0.0f};
4245 	ALfloat listenerVel[3] = {0.0f, 0.0f, 0.0f};
4246 	ALfloat listenerOri[6] = {0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f};
4247 	ALCchar *device_list;
4248 	int error;
4249 	int i;
4250 
4251 	// If we don't have sound/music then bail so we don't grab the soundcard.
4252 	if (inited || no_sound || (!sound_on && !music_on))
4253 		return;
4254 
4255 	// Begin by setting all data to a known state
4256 	if (have_sound)
4257 		destroy_sound();
4258 
4259 	// Initialise OpenAL
4260 
4261 	// Get a list of the available devices (not used yet)
4262 	if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") != AL_TRUE)
4263 	{
4264 		LOG_WARNING("ALC_ENUMERATION_EXT not found. Retrieving list of sound devices may fail.");
4265 	}
4266 	device_list = (char*) alcGetString(NULL, ALC_DEVICE_SPECIFIER);
4267 	parse_snd_devices(device_list, sound_devices);
4268 	LOG_INFO("Sound devices detected: %s\n", sound_devices);
4269 
4270 	// If you want to use a specific device, use, for example:
4271 	// device = alcOpenDevice((ALCchar*) "DirectSound3D")
4272 	// NULL makes it use the default device
4273 	LOG_INFO("Soundcard device attempted: %s", sound_device);
4274 	device = alcOpenDevice((ALCchar*) sound_device);
4275 	if ((error = alcGetError(device)) != AL_NO_ERROR || !device)
4276 	{
4277 		if (strcmp(sound_device, "")) {
4278 			// Try the default device
4279 			device = alcOpenDevice(NULL);
4280 		}
4281 		if ((error = alcGetError(device)) != AL_NO_ERROR || !device)
4282 		{
4283 			char str[256];
4284 			safe_snprintf(str, sizeof(str), "alcOpenDevice(): %s: %s\n", snd_init_error, alcGetString(device, error));
4285 			LOG_TO_CONSOLE(c_red1, str);
4286 			LOG_ERROR(str);
4287 			have_sound = have_music = 0;
4288 			return;
4289 		} else {
4290 			LOG_ERROR("Soundcard device specified (%s) failed. Using default device: %s", sound_device, alcGetString(device, ALC_DEVICE_SPECIFIER));
4291 		}
4292 	} else {
4293 		LOG_INFO("Soundcard device in-use: %s", alcGetString(device, ALC_DEVICE_SPECIFIER));
4294 	}
4295 
4296 	context = alcCreateContext( device, NULL );
4297 	alcMakeContextCurrent( context );
4298 	if ((error = alcGetError(device)) != AL_NO_ERROR || !context)
4299 	{
4300 		char str[256];
4301 		safe_snprintf(str, sizeof(str), "context: %s: %s\n", snd_init_error, alcGetString(device, error));
4302 		LOG_TO_CONSOLE(c_red1, str);
4303 		LOG_ERROR(str);
4304 		have_sound = have_music = 0;
4305 		return;
4306 	}
4307 
4308 	// Setup the listener
4309 	alListenerfv(AL_POSITION, listenerPos);
4310 #ifdef _EXTRA_SOUND_DEBUG							// Debugging for Florian
4311 	if ((error = alGetError()) != AL_NO_ERROR)
4312 	{
4313 		LOG_DEBUG_VERBOSE("%s: Error setting up listener position - %s\n", snd_init_error, alGetString(error));
4314 	}
4315 #endif // _EXTRA_SOUND_DEBUG
4316 	alListenerfv(AL_VELOCITY, listenerVel);
4317 #ifdef _EXTRA_SOUND_DEBUG
4318 	if ((error = alGetError()) != AL_NO_ERROR)
4319 	{
4320 		LOG_DEBUG_VERBOSE("%s: Error setting up listener velocity - %s\n", snd_init_error, alGetString(error));
4321 	}
4322 #endif // _EXTRA_SOUND_DEBUG
4323 	alListenerfv(AL_ORIENTATION, listenerOri);
4324 #ifdef _EXTRA_SOUND_DEBUG
4325 	if ((error = alGetError()) != AL_NO_ERROR)
4326 	{
4327 		LOG_DEBUG_VERBOSE("%s: Error setting up listener orientation - %s\n", snd_init_error, alGetString(error));
4328 	}
4329 #endif // _EXTRA_SOUND_DEBUG
4330 
4331 	if ((error = alGetError()) != AL_NO_ERROR)
4332 	{
4333 		char str[256];
4334 		safe_snprintf(str, sizeof(str), "%s: Error setting up listener - %s\n", snd_init_error, alGetString(error));
4335 		LOG_ERROR(str);
4336 	}
4337 
4338 	// Start with our max and see how many sources we can allocate
4339 	max_sources = ABS_MAX_SOURCES;
4340 
4341 	// Initialise sources
4342 	LOCK_SOUND_LIST();
4343 
4344 	// Init source data
4345 	for (i = 0; i < max_sources; i++)
4346 	{
4347 		clear_source(&sound_source_data[i]);
4348 	}
4349 
4350 	// Generate our sources
4351 	for (i = 0; i < max_sources; i++)
4352 	{
4353 		alGenSources(1, &sound_source_data[i].source);
4354 		if ((error = alGetError()) != AL_NO_ERROR)
4355 		{
4356 			// Assume this is the limit of sources available
4357 			max_sources = i;
4358 			// Limit the available streams based on the number of sources (a stream takes twice the resources)
4359 			if (max_sources <= 16)
4360 				max_streams = 4;		// This only allows a music stream, a crowd stream and 2 backgrounds...
4361 										// but it takes effectively 8 sources of <= 16
4362 			if (max_sources == 0)
4363 			{
4364 				// We don't have any sources so error and disable sound
4365 				char str[256];
4366 				safe_snprintf(str, sizeof(str), "alGenSources(): %s: %s - %s\n", snd_init_error, snd_source_error, alGetString(error));
4367 				LOG_TO_CONSOLE(c_red1, str);
4368 				LOG_ERROR(str);
4369 				have_sound = have_music = 0;
4370 				UNLOCK_SOUND_LIST();
4371 				return;
4372 			}
4373 			break;
4374 		}
4375 	}
4376 	UNLOCK_SOUND_LIST();
4377 #ifdef _EXTRA_SOUND_DEBUG
4378 	LOG_DEBUG_VERBOSE("Generated and using %d sources\n", max_sources);
4379 #endif // _EXTRA_SOUND_DEBUG
4380 
4381 	have_sound = 1;
4382 	have_music = 1;
4383 
4384 	// Initialise streams thread
4385 	if (sound_streams_thread == NULL) {
4386 		sound_streams_thread = SDL_CreateThread(update_streams, "SoundThread", 0);
4387 	}
4388 
4389 	if (num_types == 0)
4390 	{
4391 		// We have no sounds defined so assume the config isn't loaded
4392 		// As it isn't already loaded, assume the default config location
4393 		load_sound_config_data(SOUND_CONFIG_PATH);
4394 	}
4395 
4396 	inited = 1;
4397 
4398 	// Reset the error buffer
4399 	if ((error = alGetError()) != AL_NO_ERROR)
4400 	{
4401 		LOG_DEBUG_VERBOSE("%s: %s", snd_init_error, alGetString(error));
4402 	}
4403 }
4404 
4405 void destroy_sound()
4406 {
4407 	int i, error;
4408 	ALCcontext *context;
4409 	ALCdevice *device = NULL;
4410 	if (!inited){
4411 		return;
4412 	}
4413 	inited = have_sound = have_music = 0;
4414 
4415 	if (sound_streams_thread != NULL)
4416 	{
4417 		SDL_WaitThread(sound_streams_thread, NULL);
4418 		sound_streams_thread = NULL;
4419 	}
4420 	LOCK_SOUND_LIST();
4421 	for (i = 0; i < MAX_STREAMS; i++)
4422 	{
4423 		destroy_stream(&streams[i]);
4424 	}
4425 	// Remove physical elements (sources and buffers)
4426 	for (i = 0; i < ABS_MAX_SOURCES; i++)
4427 	{
4428 		if (alIsSource(sound_source_data[i].source) == AL_TRUE)
4429 		{
4430 			alSourceStopv(1, &sound_source_data[i].source);
4431 			alDeleteSources(1, &sound_source_data[i].source);
4432 		}
4433 		sound_source_data[i].source = 0;
4434 	}
4435 	used_sources = 0;
4436 	for (i = 0; i < MAX_BUFFERS; i++)
4437 	{
4438 		unload_sample(i);
4439 	}
4440 	for (i = 0; i < MAX_BUFFERS * 2; i++)
4441 	{
4442 		if (no_sound) {
4443 			unload_sound(i);
4444 		} else {
4445 			// Flag all sounds as unloaded, but don't remove them
4446 			sounds_list[i].playing = 0;
4447 			sounds_list[i].loaded = 0;
4448 		}
4449 	}
4450 	UNLOCK_SOUND_LIST();
4451 
4452 	context = alcGetCurrentContext();
4453 	if (context != NULL)
4454 	{
4455 		device = alcGetContextsDevice(context);
4456 #ifndef LINUX
4457 		alcMakeContextCurrent(NULL);
4458 #endif // LINUX
4459 		alcDestroyContext(context);
4460 		if (device != NULL)
4461 		{
4462 			alcCloseDevice(device);
4463 			device = NULL;
4464 		}
4465 	}
4466 
4467 	if (device != NULL && (error = alcGetError(device)) != AL_NO_ERROR)
4468 	{
4469 		char str[256];
4470 		safe_snprintf(str, sizeof(str), "%s: %s\n", snd_init_error, alcGetString(device, error));
4471 		LOG_TO_CONSOLE(c_red1, str);
4472 		LOG_ERROR(str);
4473 	}
4474 }
4475 
4476 
4477 // This function is to convert the \0 delimiter used by OpenAL into a comma so we can use
4478 // the device list as an everyday C "string" (original string terminated by \0\0).
4479 // For now the existance of a comma in a device name is irrelevent.
4480 void parse_snd_devices(ALCchar * in_array, char * sound_devs)
4481 {
4482 	int i = 0;
4483 	while (in_array[i] != '\0' || in_array[i+1] != '\0') {
4484 		if (in_array[i] == '\0') {
4485 			sound_devs[i] = ',';
4486 		} else {
4487 			sound_devs[i] = in_array[i];
4488 		}
4489 		i++;
4490 	}
4491 	sound_devs[i] = '\0';
4492 }
4493 
4494 /********************
4495  * CONFIG FUNCTIONS *
4496  ********************/
4497 
4498 // Returns -1 if the string is already in the list, 0 on error, 1 on success or -2 if there are no more list slots
4499 int add_to_sound_warnings_list(const char * text)
4500 {
4501 	int i, snd;
4502 	char left[256];
4503 	char right[256];
4504 	int t, tp;
4505 
4506 	if (text[0] == '\0' || text[0] == '#')
4507 		return 1;		// Nothing to do so return success
4508 
4509 	// Extract the sound name (left) and string (right) from the input text
4510 	safe_strncpy (left, text, sizeof(left));
4511 	for (t = 0; ; t++)
4512 	{
4513 		if (left[t] == '\0')
4514 		{
4515 			LOG_ERROR("Invalid sound warning declared: %s. Expected format 'sound = string'.", text);
4516 			return 0;
4517 		}
4518 		if (left[t] == '=')
4519 		{
4520 			left[t] = '\0';
4521 			for (tp = t - 1; tp >= 0 && isspace(left[tp]); tp--)
4522 			{
4523 				left[tp] = '\0';
4524 			}
4525 			for (tp = t + 1; left[tp] != '\0' && !(left[tp]&0x80) && isspace(left[tp]); tp++) ;
4526 			safe_strncpy (right, &left[tp], sizeof(right));
4527 			break;
4528 		}
4529 	}
4530 
4531 	// See if this string is already in the list
4532 	for (i = 0; i < MAX_SOUND_WARNINGS; i++)
4533 	{
4534 		if (warnings_list[i].sound >= 0)
4535 		{
4536 			if (!strcasecmp(warnings_list[i].string, right))
4537 				return -1; // Already in the list
4538 		}
4539 	}
4540 
4541 	snd = get_index_for_sound_type_name(left);
4542 	if (snd > -1)
4543 	{
4544 		// We have a valid sound so find a free spot
4545 		for (i = 0; i < MAX_SOUND_WARNINGS; i++)
4546 		{
4547 			if (warnings_list[i].sound < 0)
4548 			{
4549 				// Excellent, a free spot
4550 				warnings_list[i].sound = snd;
4551 				safe_strncpy(warnings_list[i].string, right, MAX_SND_WARNING_STRING);
4552 				num_sound_warnings++;
4553 				return 1;
4554 			}
4555 		}
4556 		LOG_ERROR("Sound warning list is full. %d warnings loaded.", num_sound_warnings);
4557 		return -2;		// If we are here, it means the warnings list is full
4558 	}
4559 
4560 	LOG_ERROR("Sound not found for sound warning: %s", text);
4561 	return 0;		// The sound wasn't found
4562 }
4563 
4564 // Blatently stolen from the text filter code (filter.c)
4565 void load_sound_warnings_list(const char *filename)
4566 {
4567 	int f_size;
4568 	FILE * f = NULL;
4569 	char * sound_warnings_list_mem;
4570 	int istart, iend;
4571 	char string[128];
4572 
4573 	f = open_file_config (filename, "rb");
4574 	if (f == NULL) return;
4575 
4576 	// Ok, allocate memory for it and read it in
4577 	fseek(f, 0, SEEK_END);
4578 	f_size = ftell(f);
4579 	if (f_size <= 0)
4580 	{
4581 		fclose(f);
4582 		return;
4583 	}
4584 
4585 	sound_warnings_list_mem = (char *) calloc (f_size, 1);
4586 	fseek(f, 0, SEEK_SET);
4587 	if (fread(sound_warnings_list_mem, 1, f_size, f) != f_size)
4588 	{
4589 		LOG_ERROR("%s() read failed for file [%s]\n", __FUNCTION__, filename);
4590 		free(sound_warnings_list_mem);
4591 		fclose(f);
4592 		return;
4593 	}
4594 	fclose(f);
4595 
4596 	istart = 0;
4597 	while (istart < f_size)
4598 	{
4599 		// Find end of the line
4600 		for (iend = istart; iend < f_size; iend++)
4601 		{
4602 			if (sound_warnings_list_mem[iend] == '\n' || sound_warnings_list_mem[iend] == '\r')
4603 				break;
4604 		}
4605 
4606 		// Copy the line and process it
4607 		if (iend > istart)
4608 		{
4609 			safe_strncpy2(string, sound_warnings_list_mem+istart, sizeof(string), iend - istart);
4610 			if (add_to_sound_warnings_list(string) == -2)		// -1 == already exists, -2 == list full
4611 			{
4612 				free(sound_warnings_list_mem);
4613 				return; // Sound warnings list full
4614 			}
4615 		}
4616 
4617 		// Move to next line
4618 		istart = iend + 1;
4619 	}
4620 
4621 	free(sound_warnings_list_mem);
4622 }
4623 
4624 
4625 
4626 void parse_server_sounds()
4627 {
4628 	int i;
4629 	// Parse the list of sounds according to client_serv.h and map them to our sound defs
4630 	//
4631 	// NOTE: This must be kept up-to-date with client_serv.h for it to be any use!!
4632 	for (i = 0; i < MAX_SERVER_SOUNDS; i++)
4633 	{
4634 		switch(i)
4635 		{
4636 			case snd_rain:
4637 				server_sound[snd_rain] = get_index_for_sound_type_name("Rain");
4638 				break;
4639 			case snd_tele_in:
4640 				server_sound[snd_tele_in] = get_index_for_sound_type_name("Teleport_in");
4641 				break;
4642 			case snd_tele_out:
4643 				server_sound[snd_tele_out] = get_index_for_sound_type_name("Teleport_out");
4644 				break;
4645 			case snd_teleprtr:
4646 				server_sound[snd_teleprtr] = get_index_for_sound_type_name("Teleporter");
4647 				break;
4648 			case snd_thndr_1:
4649 				server_sound[snd_thndr_1] = get_index_for_sound_type_name("Thunder1");
4650 				break;
4651 			case snd_thndr_2:
4652 				server_sound[snd_thndr_2] = get_index_for_sound_type_name("Thunder2");
4653 				break;
4654 			case snd_thndr_3:
4655 				server_sound[snd_thndr_3] = get_index_for_sound_type_name("Thunder3");
4656 				break;
4657 			case snd_thndr_4:
4658 				server_sound[snd_thndr_4] = get_index_for_sound_type_name("Thunder4");
4659 				break;
4660 			case snd_thndr_5:
4661 				server_sound[snd_thndr_5] = get_index_for_sound_type_name("Thunder5");
4662 				break;
4663 			case snd_fire:
4664 				server_sound[snd_fire] = get_index_for_sound_type_name("FireBig");
4665 				break;
4666 		}
4667 	}
4668 }
4669 
4670 sound_file * init_sound_file(const char * content)
4671 {
4672 	int i;
4673 
4674 	// Check if this file is already in our list of sound files
4675 	for (i = 0; i < num_sound_files; i++)
4676 	{
4677 		if (!strcasecmp(sound_files[i].file_path, content)) {
4678 			return &sound_files[i];
4679 		}
4680 	}
4681 	// Not found so check we have space to add it to the list
4682 	if (num_sound_files >= MAX_SOUND_FILES)
4683 	{
4684 		// Big problem! No more room to load sound files
4685 		return NULL;
4686 	}
4687 	// Everything is ok so load it
4688 	safe_strncpy(sound_files[i].file_path, content, MAX_FILENAME_LENGTH);
4689 	num_sound_files++;
4690 	return &sound_files[i];
4691 }
4692 
4693 sound_file * load_sound_part(sound_file *pPart, SOUND_STAGE stage, const char * content)
4694 {
4695 	char filename[200];
4696 	char stage_name[6];
4697 
4698 	safe_strncpy(stage_name, (stage == STAGE_INTRO ? "Intro" : (stage == STAGE_MAIN ? "Main" : "Outro")), sizeof(stage_name));
4699 
4700 	if (!pPart || !strcasecmp(pPart->file_path, ""))
4701 	{
4702 		safe_strncpy(filename, datadir, sizeof(filename));
4703 		safe_strcat(filename, content, sizeof(filename));
4704 		if (file_exists(filename))
4705 		{
4706 			pPart = init_sound_file(content);
4707 			if (pPart)
4708 			{
4709 				return pPart;
4710 			}
4711 			LOG_ERROR("%s: Too many sound files loaded!", snd_config_error);
4712 		}
4713 		else
4714 		{
4715 			LOG_ERROR("%s: %s stage file does not exist! %s", snd_config_error, stage_name, content);
4716 		}
4717 	}
4718 	else
4719 	{
4720 		LOG_ERROR("%s: %s stage file already set!", snd_config_error, stage_name);
4721 		return pPart;
4722 	}
4723 	return NULL;
4724 }
4725 
4726 void parse_sound_variant(const xmlNode *inNode, sound_type *inType)
4727 {
4728 	char content[50];
4729 	float fVal = 0.0f;
4730 	sound_variants * pData;
4731 	const xmlNode *attributeNode;
4732 
4733 	if (inType->num_variants >= MAX_SOUND_VARIANTS)
4734 	{
4735 		LOG_ERROR("%s: Too many sound variants defined for this sound type: %s", snd_config_error, inType->name);
4736 		return;
4737 	}
4738 
4739 	pData = &inType->variant[inType->num_variants++];
4740 	attributeNode = inNode->xmlChildrenNode;
4741 	while (attributeNode != NULL)
4742 	{
4743 		if (attributeNode->type == XML_ELEMENT_NODE)
4744 		{
4745 			get_string_value(content, sizeof(content), attributeNode);
4746 			if (!xmlStrcmp (attributeNode->name, (xmlChar*)"intro_sound"))
4747 			{
4748 				pData->part[STAGE_INTRO] = load_sound_part(pData->part[STAGE_INTRO], STAGE_INTRO, content);
4749 			}
4750 			else if (!xmlStrcmp (attributeNode->name, (xmlChar*)"main_sound"))
4751 			{
4752 				pData->part[STAGE_MAIN] = load_sound_part(pData->part[STAGE_MAIN], STAGE_MAIN, content);
4753 				if (!pData->part[STAGE_MAIN])
4754 				{
4755 					// We don't have a main stage file, therefore this variant is invalid!
4756 					LOG_ERROR("%s: We do not have a main stage file so this variant for sound type '%s' is disabled", snd_config_error, inType->name);
4757 					clear_variant(pData);
4758 					inType->num_variants--;
4759 					return;
4760 				}
4761 			}
4762 			else if (!xmlStrcmp (attributeNode->name, (xmlChar*)"outro_sound"))
4763 			{
4764 				pData->part[STAGE_OUTRO] = load_sound_part(pData->part[STAGE_OUTRO], STAGE_OUTRO, content);
4765 			}
4766 			else if (!xmlStrcmp (attributeNode->name, (xmlChar*)"gain"))
4767 			{
4768 				fVal = (float)atof((char *)content);
4769 				if (fVal > 0.0f)
4770 					pData->gain = fVal;
4771 				else
4772 				{
4773 					LOG_ERROR("%s: Invalid gain = %s in '%s'", snd_config_error, content, inType->name);
4774 				}
4775 			}
4776 		}
4777 		else if (attributeNode->type == XML_ENTITY_REF_NODE)
4778 		{
4779 			LOG_ERROR("%s: Include not allowed in variant sound def", snd_config_error);
4780 		}
4781 		attributeNode = attributeNode->next;
4782 	}
4783 	// Check this variant has the required Main stage
4784 	if (!pData->part[STAGE_MAIN])
4785 	{
4786 		LOG_ERROR("%s: Main stage not defined! A sound variant for this type is disabled: %s", snd_config_error, inType->name);
4787 		clear_variant(pData);
4788 		inType->num_variants--;
4789 	}
4790 	return;
4791 }
4792 
4793 void parse_sound_object(const xmlNode *inNode)
4794 {
4795 	const xmlNode *attributeNode = NULL;
4796 
4797 	char content[50];
4798 	int iVal = 0;
4799 	float fVal = 0.0f;
4800 	xmlChar *sVal = NULL;
4801 
4802 	sound_type *pData = NULL;
4803 
4804 	if (num_types >= MAX_SOUNDS)
4805 	{
4806 		LOG_ERROR("%s: Maximum number of sounds (%d) reached!", snd_config_error, MAX_SOUNDS);
4807 		return;
4808 	}
4809 
4810 	pData = &sound_type_data[num_types++];
4811 
4812 	sVal = xmlGetProp((xmlNode *)inNode, (const xmlChar*)"name");
4813 	if (!sVal)
4814 	{
4815 		LOG_ERROR("%s: sound has no name", snd_config_error);
4816 	}
4817 	else
4818 	{
4819 		safe_strncpy(pData->name, (const char*)sVal, sizeof(pData->name));
4820 		xmlFree(sVal);
4821 
4822 		attributeNode = inNode->xmlChildrenNode;
4823 		while (attributeNode != NULL)
4824 		{
4825 			if (attributeNode->type == XML_ELEMENT_NODE)
4826 			{
4827 				get_string_value(content, sizeof(content), attributeNode);
4828 				if (!xmlStrcmp (attributeNode->name, (xmlChar*)"variant"))
4829 				{
4830 					parse_sound_variant(attributeNode, pData);
4831 				}
4832 				else if (!xmlStrcmp (attributeNode->name, (xmlChar*)"stereo"))
4833 				{
4834 					iVal = atoi((char *)content);
4835 					if (iVal == 0 || iVal == 1)
4836 						pData->stereo = iVal;
4837 					else
4838 					{
4839 						LOG_ERROR("%s: stereo = %d in '%s'", snd_config_error, iVal, pData->name);
4840 					}
4841 				}
4842 				else if (!xmlStrcmp (attributeNode->name, (xmlChar*)"distance"))
4843 				{
4844 					fVal = (float)atof((char *)content);
4845 					if (fVal > 0.0f)
4846 						pData->distance = fVal;
4847 					else
4848 					{
4849 						LOG_ERROR("%s: distance = %f in '%s'", snd_config_error, fVal, pData->name);
4850 					}
4851 				}
4852 				else if (!xmlStrcmp (attributeNode->name, (xmlChar*)"positional"))
4853 				{
4854 					iVal = atoi((char *)content);
4855 					if (iVal == 0 || iVal == 1)
4856 						pData->positional = iVal;
4857 					else
4858 					{
4859 						LOG_ERROR("%s: positional = %d in '%s'", snd_config_error, iVal, pData->name);
4860 					}
4861 				}
4862 				else if (!xmlStrcmp (attributeNode->name, (xmlChar*)"loops"))
4863 				{
4864 					iVal = atoi((char *)content);
4865 					if (iVal >= 0)
4866 						pData->loops = iVal;
4867 					else
4868 					{
4869 						LOG_ERROR("%s: loops = %d in '%s'", snd_config_error, iVal, pData->name);
4870 					}
4871 				}
4872 				else if (!xmlStrcmp (attributeNode->name, (xmlChar*)"fadeout_time"))
4873 				{
4874 					iVal = atoi((char *)content);
4875 					if (iVal >= 0)
4876 						pData->fadeout_time = iVal;
4877 					else
4878 					{
4879 						LOG_ERROR("%s: fadeout_time = %d in '%s'", snd_config_error, iVal, pData->name);
4880 					}
4881 				}
4882 				else if (!xmlStrcmp (attributeNode->name, (xmlChar*)"echo_delay"))
4883 				{
4884 					iVal = atoi((char *)content);
4885 					if (iVal >= 0)
4886 						pData->echo_delay = iVal;
4887 					else
4888 					{
4889 						LOG_ERROR("%s: echo_delay = %d in '%s'", snd_config_error, iVal, pData->name);
4890 					}
4891 				}
4892 				else if (!xmlStrcmp (attributeNode->name, (xmlChar*)"echo_volume"))
4893 				{
4894 					iVal = atoi((char *)content);
4895 					if (iVal >= 0)
4896 						pData->echo_volume = iVal;
4897 					else
4898 					{
4899 						LOG_ERROR("%s: echo_volume = %d in '%s'", snd_config_error, iVal, pData->name);
4900 					}
4901 				}
4902 				else if (!xmlStrcmp (attributeNode->name, (xmlChar*)"time_of_day_flags"))
4903 				{
4904 					sscanf((char *)content, "%x", &iVal);
4905 					if (iVal >= 0 && iVal <= 0xffff)
4906 						pData->time_of_the_day_flags = iVal;
4907 					else
4908 					{
4909 						LOG_ERROR("%s: time_of_the_day_flags = 0x%x in '%s'", snd_config_error, iVal, pData->name);
4910 					}
4911 				}
4912 				else if (!xmlStrcmp (attributeNode->name, (xmlChar*)"priority"))
4913 				{
4914 					iVal = atoi((char *)content);
4915 					if (iVal >= 0)
4916 						pData->priority = iVal;
4917 					else
4918 					{
4919 						LOG_ERROR("%s: priority = %d in '%s'", snd_config_error, iVal, pData->name);
4920 					}
4921 				}
4922 				else if (!xmlStrcmp (attributeNode->name, (xmlChar*)"type"))
4923 				{
4924 					iVal = SOUNDS_NONE;
4925 					if (!strcasecmp((char *)content, "environmental")) {
4926 						iVal = SOUNDS_ENVIRO;
4927 					} else if (!strcasecmp((char *)content, "actor")) {
4928 						iVal = SOUNDS_ACTOR;
4929 					} else if (!strcasecmp((char *)content, "walking")) {
4930 						iVal = SOUNDS_WALKING;
4931 					} else if (!strcasecmp((char *)content, "map")) {
4932 						iVal = SOUNDS_MAP;
4933 					} else if (!strcasecmp((char *)content, "crowd")) {
4934 						iVal = SOUNDS_CROWD;
4935 					} else if (!strcasecmp((char *)content, "client")) {
4936 						iVal = SOUNDS_CLIENT;
4937 					} else if (!strcasecmp((char *)content, "gamewin")) {
4938 						iVal = SOUNDS_GAMEWIN;
4939 					} else if (!strcasecmp((char *)content, "warnings")) {
4940 						iVal = SOUNDS_WARNINGS;
4941 					} else {
4942 						LOG_ERROR("%s: Unknown type '%s' for sound '%s'", snd_config_error, content, pData->name);
4943 					}
4944 					if (iVal != SOUNDS_NONE)
4945 						pData->type = iVal;
4946 				}
4947 				else
4948 				{
4949 					LOG_ERROR("%s: Unknown attribute '%s' for sound '%s'", snd_config_error, attributeNode->name, pData->name);
4950 				}
4951 			}
4952 			else if (attributeNode->type == XML_ENTITY_REF_NODE)
4953 			{
4954 				LOG_ERROR("%s: Include not allowed in sound def", snd_config_error);
4955 			}
4956 			attributeNode = attributeNode->next;
4957 		}
4958 	}
4959 	// Check this type has at least one variant
4960 	if (pData->num_variants < 1)
4961 	{
4962 		LOG_ERROR("%s: No sound variants defined! This sound type is disabled: %s", snd_config_error, pData->name);
4963 		clear_sound_type(num_types);
4964 		num_types--;
4965 	}
4966 }
4967 
4968 void store_boundary_coords(char *coordinates, int * x, int * y)
4969 {
4970 	int i = 0, j = 0, element = 0;
4971 	char tmp[5] = "";
4972 
4973 	while (i != strlen(coordinates))
4974 	{
4975 		if (coordinates[i] != ',' && j < 5 && i != strlen(coordinates))
4976 		{
4977 			tmp[j] = coordinates[i];
4978 			j++;
4979 		}
4980 		else
4981 		{
4982 			if (element == 0)
4983 			{
4984 				*x = atoi(tmp);
4985 				for (j = 0; j < 5; j++)
4986 				{
4987 					tmp[j] = '\0';
4988 				}
4989 				j = 0;
4990 				element++;
4991 			}
4992 			else break;
4993 		}
4994 		i++;
4995 	}
4996 	if (element == 1)
4997 	{
4998 		*y = atoi(tmp);
4999 	}
5000 	else
5001 	{
5002 		LOG_ERROR("%s: Error parsing coordinates", snd_config_error);
5003 	}
5004 	return;
5005 }
5006 
5007 int validate_boundary(map_sound_boundary_def * bounds, char * map_name)
5008 {
5009 	int i;
5010 	double a;
5011 
5012 	// Check if this is a default
5013 	if (bounds->is_default)
5014 	{
5015 		// Check if we have any points
5016 		if (bounds->p[0].x != -1 || bounds->p[0].y != -1 || bounds->p[1].x != -1 || bounds->p[1].y != -1
5017 			|| bounds->p[2].x != -1 || bounds->p[2].y != -1 || bounds->p[3].x != -1 || bounds->p[3].y != -1)
5018 		{
5019 			LOG_ERROR("Warning: Points defined for default boundary. Points will be ignored.\n");
5020 		}
5021 		return 1;		// Points are ignored for defaults
5022 	}
5023 
5024 	// Check we have details for at least 2 points
5025 	if (bounds->p[0].x == -1 || bounds->p[0].y == -1 || bounds->p[1].x == -1 || bounds->p[1].y == -1)
5026 	{
5027 		LOG_ERROR("%s: Point missing for boundary in map '%s'. Non-default boundaries must contain 2 or 4 points.", snd_config_error, map_name);
5028 		return 0;
5029 	}
5030 
5031 	// Calculate the outer box
5032 	bounds->o[0].x = bounds->p[0].x;
5033 	bounds->o[0].y = bounds->p[0].y;
5034 	bounds->o[1].x = bounds->p[0].x;
5035 	bounds->o[1].y = bounds->p[0].y;
5036 	for (i = 0; i < 4; i++)
5037 	{
5038 		if (bounds->p[i].x > -1 && bounds->p[i].y > -1)
5039 		{
5040 			// Check if this point's x or y is greater than the current max or less than the current min and update
5041 			if (bounds->p[i].x < bounds->o[0].x)
5042 				bounds->o[0].x = bounds->p[i].x;
5043 			if (bounds->p[i].y < bounds->o[0].y)
5044 				bounds->o[0].y = bounds->p[i].y;
5045 			if (bounds->p[i].x > bounds->o[1].x)
5046 				bounds->o[1].x = bounds->p[i].x;
5047 			if (bounds->p[i].y > bounds->o[1].y)
5048 				bounds->o[1].y = bounds->p[i].y;
5049 		}
5050 	}
5051 
5052 	// We have the outer box now so if we have only 2 points then we can bail
5053 	if (bounds->p[2].x == -1 && bounds->p[2].y == -1 && bounds->p[3].x == -1 && bounds->p[3].y == -1)
5054 	{
5055 		return 1;
5056 	}
5057 	else if (bounds->p[2].x == -1 || bounds->p[2].y == -1 || bounds->p[3].x == -1 || bounds->p[3].y == -1)
5058 	{
5059 		LOG_ERROR("%s: Point missing for boundary in map '%s'. Non-default boundaries must contain 2 or 4 points.", snd_config_error, map_name);
5060 		return 0;
5061 	}
5062 
5063 	// Check if our 4 points are actually equal to the bounding box rectangle
5064 	if (bounds->p[0].x == bounds->o[0].x && bounds->p[0].y == bounds->o[0].y &&
5065 		bounds->p[1].x == bounds->o[0].x && bounds->p[1].y == bounds->o[1].y &&
5066 		bounds->p[2].x == bounds->o[1].x && bounds->p[2].y == bounds->o[1].y &&
5067 		bounds->p[3].x == bounds->o[1].x && bounds->p[3].y == bounds->o[0].y)
5068 	{
5069 		// This is the bounding box so remove points 1 and 2 as the corners and blank the others
5070 		// to symbolise using the bounding box check only
5071 		bounds->p[1].x = bounds->p[2].x;
5072 		bounds->p[1].y = bounds->p[2].y;
5073 		bounds->p[2].x = -1;
5074 		bounds->p[2].y = -1;
5075 		bounds->p[3].x = -1;
5076 		bounds->p[3].y = -1;
5077 		// Nothing left to do
5078 		return 1;
5079 	}
5080 
5081 	// Find the angle of the line from the top left corner to the top right (point1 -> point2)
5082 	bounds->p[0].a = calculate_bounds_angle(bounds->p[1].x, bounds->p[1].y, 0, bounds);
5083 
5084 	// Find the angle of the line from the top right corner to the bottom right (point2 -> point3)
5085 	bounds->p[1].a = calculate_bounds_angle(bounds->p[2].x, bounds->p[2].y, 1, bounds);
5086 
5087 	// Find the angle of the line from the bottom right corner to the bottom left (point3 -> point4)
5088 	bounds->p[2].a = calculate_bounds_angle(bounds->p[3].x, bounds->p[3].y, 2, bounds);
5089 
5090 	// Find the angle of the line from the bottom left corner to the top left (point4 -> point1)
5091 	bounds->p[3].a = calculate_bounds_angle(bounds->p[0].x, bounds->p[0].y, 3, bounds);
5092 
5093 
5094 	// Check the angle of the line from the bottom left corner to the top right (point4 -> point2)
5095 	a = calculate_bounds_angle(bounds->p[1].x, bounds->p[1].y, 3, bounds);
5096 	if (bounds->p[3].a < a) bounds->int_point = 0;
5097 
5098 	// Check the angle of the line from the top left corner to the bottom right (point1 -> point3)
5099 	a = calculate_bounds_angle(bounds->p[2].x, bounds->p[2].y, 0, bounds);
5100 	if (bounds->p[0].a < a) bounds->int_point = 1;
5101 
5102 	// Check the angle of the line from the top right corner to the bottom left (point2 -> point4)
5103 	a = calculate_bounds_angle(bounds->p[3].x, bounds->p[3].y, 1, bounds);
5104 	if (bounds->p[1].a < a) bounds->int_point = 2;
5105 
5106 	// Check the angle of the line from the bottom right corner to the top left (point3 -> point1)
5107 	a = calculate_bounds_angle(bounds->p[0].x, bounds->p[0].y, 2, bounds);
5108 	if (bounds->p[2].a < a) bounds->int_point = 3;
5109 
5110 	return 1;
5111 }
5112 
5113 void parse_map_sound(const xmlNode *inNode)
5114 {
5115 	const xmlNode *boundaryNode = NULL;
5116 	const xmlNode *attributeNode = NULL;
5117 
5118 	xmlChar *sVal = NULL;
5119 	char content[50];
5120 
5121 	int iVal;
5122 
5123 	map_sound_data *pMap = NULL;
5124 	map_sound_boundary_def *pMapBoundary = NULL;
5125 
5126 	if (sound_num_maps >= MAX_SOUND_MAPS)
5127 	{
5128 		LOG_ERROR("%s: Maximum number of maps reached!", snd_config_error);
5129 		return;
5130 	}
5131 	pMap = &sound_map_data[sound_num_maps++];
5132 
5133 	sVal = xmlGetProp((xmlNode*)inNode,(const xmlChar*)"file_name");
5134 	if (!sVal)
5135 	{
5136 		pMap->file_name[0] = '\0';
5137 	}
5138 	else
5139 	{
5140 		safe_strncpy(pMap->file_name, (const char*)sVal, sizeof(pMap->file_name));
5141 		xmlFree(sVal);
5142 	}
5143 
5144 	sVal = xmlGetProp((xmlNode*)inNode,(const xmlChar*)"id");
5145 	if (!sVal)
5146 	{
5147 		pMap->id = -1;
5148 	}
5149 	else
5150 	{
5151 		pMap->id = atoi((const char*)sVal);
5152 		xmlFree(sVal);
5153 	}
5154 
5155 	if (pMap->file_name[0] == '\0' && pMap->id == -1)
5156 	{
5157 			LOG_ERROR("%s: map has no file_name or id", snd_config_error);
5158 	}
5159 	else
5160 	{
5161 		sVal = xmlGetProp((xmlNode*)inNode, (const xmlChar*)"name");
5162 		if (sVal)
5163 		{
5164 			safe_strncpy(pMap->name, (const char*)sVal, sizeof(pMap->name));
5165 			xmlFree(sVal);
5166 		}
5167 
5168 		for (boundaryNode = inNode->children; boundaryNode; boundaryNode = boundaryNode->next)
5169 		{
5170 			if (boundaryNode->type == XML_ELEMENT_NODE)
5171 			{
5172 				if(!xmlStrcasecmp(boundaryNode->name, (xmlChar*)"boundary_def"))
5173 				{
5174 					// Process this set of boundaries
5175 					if (pMap->num_boundaries++ < MAX_SOUND_MAP_BOUNDARIES)
5176 					{
5177 						pMapBoundary = &pMap->boundaries[pMap->num_boundaries - 1];
5178 
5179 						for (attributeNode = boundaryNode->children; attributeNode; attributeNode = attributeNode->next)
5180 						{
5181 							get_string_value(content, sizeof(content), attributeNode);
5182 							if (!xmlStrcasecmp(attributeNode->name, (xmlChar*)"background"))
5183 							{
5184 								// Find the type of background sound for this set of boundaries
5185 								pMapBoundary->bg_sound = get_index_for_sound_type_name(content);
5186 								if (pMapBoundary->bg_sound == -1)
5187 								{
5188 									LOG_ERROR("%s: background sound not found for map boundary type '%s' in map '%s'", snd_config_error,content, pMap->name);
5189 								}
5190 							}
5191 							else if (!xmlStrcasecmp(attributeNode->name, (xmlChar*)"crowd"))
5192 							{
5193 								// Find the type of crowd sound for this set of boundaries
5194 								pMapBoundary->crowd_sound = get_index_for_sound_type_name(content);
5195 								if (pMapBoundary->crowd_sound == -1)
5196 								{
5197 									LOG_ERROR("%s: crowd sound not found for map boundary type '%s' in map '%s'", snd_config_error, content, pMap->name);
5198 								}
5199 							}
5200 							else if (!xmlStrcasecmp(attributeNode->name, (xmlChar*)"time_of_day_flags"))
5201 							{
5202 								// Find the type of crowd sound for this set of boundaries
5203 								sscanf((char *)content, "%x", &iVal);
5204 								if (iVal >= 0 && iVal <= 0xffff)
5205 									pMapBoundary->time_of_day_flags = iVal;
5206 								else
5207 								{
5208 									LOG_ERROR("%s: time_of_day flags (%s) invalid for map boundary in map '%s'", snd_config_error, content, pMap->name);
5209 								}
5210 							}
5211 							else if (!xmlStrcasecmp(attributeNode->name, (xmlChar*)"is_default"))
5212 							{
5213 								// Find the type of crowd sound for this set of boundaries
5214 								iVal = atoi(content);
5215 								if (iVal == 0 || iVal == 1)
5216 								{
5217 									pMapBoundary->is_default = iVal;
5218 									if (pMap->num_defaults < MAX_MAP_BACKGROUND_DEFAULTS)
5219 									{
5220 										pMap->num_defaults++;
5221 										pMap->defaults[pMap->num_defaults] = pMap->num_boundaries;
5222 									}
5223 									else
5224 									{
5225 										LOG_ERROR("%s: Maximum defaults reached for map '%s'", snd_config_error, pMap->name);
5226 									}
5227 								}
5228 								else
5229 								{
5230 									LOG_ERROR("%s: is_default setting (%s) invalid for map boundary in map '%s'", snd_config_error, content, pMap->name);
5231 								}
5232 							}
5233 							else if (!xmlStrcasecmp(attributeNode->name, (xmlChar*)"point1"))
5234 							{
5235 								// Parse the coordinates
5236 								store_boundary_coords(content, &pMapBoundary->p[0].x, &pMapBoundary->p[0].y);
5237 							}
5238 							else if (!xmlStrcasecmp(attributeNode->name, (xmlChar*)"point2"))
5239 							{
5240 								// Parse the coordinates
5241 								store_boundary_coords(content, &pMapBoundary->p[1].x, &pMapBoundary->p[1].y);
5242 							}
5243 							else if (!xmlStrcasecmp(attributeNode->name, (xmlChar*)"point3"))
5244 							{
5245 								// Parse the coordinates
5246 								store_boundary_coords(content, &pMapBoundary->p[2].x, &pMapBoundary->p[2].y);
5247 							}
5248 							else if (!xmlStrcasecmp(attributeNode->name, (xmlChar*)"point4"))
5249 							{
5250 								// Parse the coordinates
5251 								store_boundary_coords(content, &pMapBoundary->p[3].x, &pMapBoundary->p[3].y);
5252 							}
5253 						}
5254 						// Validate the boundary
5255 						if (!validate_boundary(pMapBoundary, pMap->name))
5256 						{
5257 							// This one is invalid so remove it (we have already errored)
5258 							clear_boundary_data(pMapBoundary);
5259 							pMap->num_boundaries--;
5260 						}
5261 					}
5262 					else
5263 					{
5264 						LOG_ERROR("%s: reached max boundaries for map '%s'", snd_config_error, pMap->name);
5265 					}
5266 				}
5267 // This block is a temporary fix for detecting 2d and 3d objects. It can be removed once the other functionality is coded.
5268 				else if(!xmlStrcasecmp(boundaryNode->name, (xmlChar*)"walk_boundary_def"))
5269 				{
5270 					// Process this set of boundaries
5271 					if (pMap->num_walk_boundaries++ < MAX_SOUND_WALK_BOUNDARIES)
5272 					{
5273 						pMapBoundary = &pMap->walk_boundaries[pMap->num_walk_boundaries - 1];
5274 
5275 						for (attributeNode = boundaryNode->children; attributeNode; attributeNode = attributeNode->next)
5276 						{
5277 							get_string_value(content, sizeof(content), attributeNode);
5278 							if (!xmlStrcasecmp(attributeNode->name, (xmlChar*)"sound"))
5279 							{
5280 								// Find the sound for this set of boundaries
5281 								pMapBoundary->bg_sound = get_index_for_sound_type_name(content);
5282 								if (pMapBoundary->bg_sound == -1)
5283 								{
5284 									LOG_ERROR("%s: sound not found for walk boundary type '%s' in map '%s'", snd_config_error, content, pMap->name);
5285 								}
5286 							}
5287 							else if (!xmlStrcasecmp(attributeNode->name, (xmlChar*)"time_of_day_flags"))
5288 							{
5289 								// Find the type of time of day flags for this set of boundaries
5290 								sscanf((char *)content, "%x", &iVal);
5291 								if (iVal >= 0 && iVal <= 0xffff)
5292 									pMapBoundary->time_of_day_flags = iVal;
5293 								else
5294 								{
5295 									LOG_ERROR("%s: time_of_day flags (%s) invalid for walk boundary in map '%s'", snd_config_error, content, pMap->name);
5296 								}
5297 							}
5298 							else if (!xmlStrcasecmp(attributeNode->name, (xmlChar*)"point1"))
5299 							{
5300 								// Parse the coordinates
5301 								store_boundary_coords(content, &pMapBoundary->p[0].x, &pMapBoundary->p[0].y);
5302 							}
5303 							else if (!xmlStrcasecmp(attributeNode->name, (xmlChar*)"point2"))
5304 							{
5305 								// Parse the coordinates
5306 								store_boundary_coords(content, &pMapBoundary->p[1].x, &pMapBoundary->p[1].y);
5307 							}
5308 							else if (!xmlStrcasecmp(attributeNode->name, (xmlChar*)"point3"))
5309 							{
5310 								// Parse the coordinates
5311 								store_boundary_coords(content, &pMapBoundary->p[2].x, &pMapBoundary->p[2].y);
5312 							}
5313 							else if (!xmlStrcasecmp(attributeNode->name, (xmlChar*)"point4"))
5314 							{
5315 								// Parse the coordinates
5316 								store_boundary_coords(content, &pMapBoundary->p[3].x, &pMapBoundary->p[3].y);
5317 							}
5318 						}
5319 						// Validate the boundary
5320 						if (!validate_boundary(pMapBoundary, pMap->name))
5321 						{
5322 							// This one is invalid so remove it (we have already errored)
5323 							clear_boundary_data(pMapBoundary);
5324 							pMap->num_walk_boundaries--;
5325 						}
5326 					}
5327 					else
5328 					{
5329 						LOG_ERROR("%s: reached max walk boundaries for map '%s'", snd_config_error, pMap->name);
5330 					}
5331 				}
5332 // This block ^^ is a temporary fix for detecting 2d and 3d objects. It can be removed once the other functionality is coded.
5333 				else
5334 				{
5335 					LOG_ERROR("%s: Boundary definition expected. Found: %s", snd_config_error, boundaryNode->name);
5336 				}
5337 			}
5338 			else if (boundaryNode->type == XML_ENTITY_REF_NODE)
5339 			{
5340 				LOG_ERROR("%s: Include not allowed in map sound def", snd_config_error);
5341 			}
5342 		}
5343 	}
5344 }
5345 
5346 void parse_effect_sound(const xmlNode *inNode)
5347 {
5348 	const xmlNode *attributeNode = NULL;
5349 	effect_sound_data *pEffect = NULL;
5350 	char sound[MAX_SOUND_NAME_LENGTH] = "";
5351 
5352 	if (inNode->type == XML_ELEMENT_NODE)
5353 	{
5354 		if (sound_num_effects >= MAX_SOUND_EFFECTS)
5355 		{
5356 			LOG_ERROR("%s: Maximum number of effects reached!", snd_config_error);
5357 			return;
5358 		}
5359 		pEffect = &sound_effect_data[sound_num_effects++];
5360 
5361 		for (attributeNode = inNode->children; attributeNode; attributeNode = attributeNode->next)
5362 		{
5363 			if(!xmlStrcasecmp(attributeNode->name, (xmlChar*)"id"))
5364 			{
5365 				pEffect->id = get_float_value(attributeNode);
5366 			}
5367 			else if(!xmlStrcasecmp(attributeNode->name, (xmlChar*)"sound"))
5368 			{
5369 				get_string_value(sound, sizeof(sound), attributeNode);
5370 				pEffect->sound = get_index_for_sound_type_name(sound);
5371 				if (pEffect->sound == -1)
5372 				{
5373 					LOG_ERROR("%s: Unknown sound %s for effect %d", snd_config_error, sound, pEffect->id);
5374 				}
5375 			}
5376 		}
5377 	}
5378 	else if (inNode->type == XML_ENTITY_REF_NODE)
5379 	{
5380 		LOG_ERROR("%s: Include not allowed in effect sound def", snd_config_error);
5381 	}
5382 }
5383 
5384 void parse_particle_sound(const xmlNode *inNode)
5385 {
5386 	const xmlNode *attributeNode = NULL;
5387 	particle_sound_data *pParticle = NULL;
5388 	char sound[MAX_SOUND_NAME_LENGTH] = "";
5389 
5390 	if (inNode->type == XML_ELEMENT_NODE)
5391 	{
5392 		if (sound_num_particles >= MAX_SOUND_PARTICLES)
5393 		{
5394 			LOG_ERROR("%s: Maximum number of particles reached!", snd_config_error);
5395 			return;
5396 		}
5397 		pParticle = &sound_particle_data[sound_num_particles++];
5398 
5399 		for (attributeNode = inNode->children; attributeNode; attributeNode = attributeNode->next)
5400 		{
5401 			if(!xmlStrcasecmp(attributeNode->name, (xmlChar*)"file"))
5402 			{
5403 				get_string_value(pParticle->file, sizeof(pParticle->file), attributeNode);
5404 			}
5405 			else if(!xmlStrcasecmp(attributeNode->name, (xmlChar*)"sound"))
5406 			{
5407 				get_string_value(sound, sizeof(sound), attributeNode);
5408 				pParticle->sound = get_index_for_sound_type_name(sound);
5409 				if (pParticle->sound == -1)
5410 				{
5411 					LOG_ERROR("%s: Unknown sound %s for particle %s", snd_config_error, sound, pParticle->file);
5412 				}
5413 			}
5414 		}
5415 	}
5416 	else if (inNode->type == XML_ENTITY_REF_NODE)
5417 	{
5418 		LOG_ERROR("%s: Include not allowed in particle sound def", snd_config_error);
5419 	}
5420 }
5421 
5422 int check_for_valid_background_details(background_default * test)
5423 {
5424 	int err, i;
5425 	err = 0;
5426 	// Check this has a valid sound
5427 	if (test->sound < 0) return -1;
5428 	// Check this time_of_day_flag and map_type don't conflict with an existing default background
5429 	for (i = 0; i < sound_num_background_defaults - 1; i++)
5430 	{
5431 		if ((sound_background_defaults[i].time_of_day_flags & test->time_of_day_flags) > 0 &&
5432 			sound_background_defaults[i].map_type == test->map_type)
5433 		{
5434 			// Conflict
5435 			err = -1;
5436 			break;
5437 		}
5438 	}
5439 	return err;
5440 }
5441 
5442 void parse_background_defaults(const xmlNode *inNode)
5443 {
5444 	const xmlNode *attributeNode = NULL;
5445 	background_default *pBackgroundDefault = NULL;
5446 	char content[MAX_SOUND_NAME_LENGTH] = "";
5447 
5448 	int iVal = 0;
5449 
5450 	if (inNode->type == XML_ELEMENT_NODE)
5451 	{
5452 		if (sound_num_background_defaults >= MAX_BACKGROUND_DEFAULTS)
5453 		{
5454 			LOG_ERROR("%s: Maximum number of background defaults reached!", snd_config_error);
5455 			return;
5456 		}
5457 		pBackgroundDefault = &sound_background_defaults[sound_num_background_defaults++];
5458 
5459 		for (attributeNode = inNode->children; attributeNode; attributeNode = attributeNode->next)
5460 		{
5461 			get_string_value(content, sizeof(content), attributeNode);
5462 			if(!xmlStrcasecmp(attributeNode->name, (xmlChar*)"time_of_day_flags"))
5463 			{
5464 				sscanf((char *)content, "%x", &iVal);
5465 				if (iVal >= 0 && iVal <= 0xffff)
5466 					pBackgroundDefault->time_of_day_flags = iVal;
5467 				else
5468 				{
5469 					LOG_ERROR("%s: time_of_the_day_flags = 0x%x in background default", snd_config_error, iVal);
5470 				}
5471 			}
5472 			else if(!xmlStrcasecmp(attributeNode->name, (xmlChar*)"map_type"))
5473 			{
5474 				iVal = atoi((char *)content);
5475 				if(iVal >= 0)
5476 					pBackgroundDefault->map_type = iVal;
5477 				else
5478 				{
5479 					LOG_ERROR("%s: Unknown map_type %s in background default", snd_config_error, content);
5480 				}
5481 			}
5482 			else if(!xmlStrcasecmp(attributeNode->name, (xmlChar*)"sound"))
5483 			{
5484 				pBackgroundDefault->sound = get_index_for_sound_type_name(content);
5485 				if (pBackgroundDefault->sound == -1)
5486 				{
5487 					LOG_ERROR("%s: Unknown sound %s in background default", snd_config_error, content);
5488 				}
5489 			}
5490 		}
5491 		if (check_for_valid_background_details(pBackgroundDefault))
5492 		{
5493 			LOG_ERROR("%s: invalid/conflicting background defaults found!", snd_config_error);
5494 			// This background is invalid so reset it to the defaults (and reuse it if there are any others)
5495 			pBackgroundDefault->time_of_day_flags = 0xffff;
5496 			pBackgroundDefault->map_type = 0;
5497 			pBackgroundDefault->sound = -1;
5498 			sound_num_background_defaults--;
5499 		}
5500 	}
5501 	else if (inNode->type == XML_ENTITY_REF_NODE)
5502 	{
5503 		LOG_ERROR("%s: Include not allowed in defaults sound def", snd_config_error);
5504 	}
5505 }
5506 
5507 void parse_sound_defaults(const xmlNode *inNode)
5508 {
5509 	const xmlNode *attributeNode = NULL;
5510 	char sound[MAX_SOUND_NAME_LENGTH] = "";
5511 
5512 	if (inNode->type == XML_ELEMENT_NODE)
5513 	{
5514 		for (attributeNode = inNode->children; attributeNode; attributeNode = attributeNode->next)
5515 		{
5516 			if(!xmlStrcasecmp(attributeNode->name, (xmlChar*)"background"))
5517 			{
5518 				parse_background_defaults(attributeNode);
5519 			}
5520 			else if(!xmlStrcasecmp(attributeNode->name, (xmlChar*)"crowd"))
5521 			{
5522 				get_string_value(sound, sizeof(sound), attributeNode);
5523 				crowd_default = get_index_for_sound_type_name(sound);
5524 				if (crowd_default == -1)
5525 				{
5526 					LOG_ERROR("%s: Unknown sound %s for crowd default", snd_config_error, sound);
5527 				}
5528 			}
5529 			else if(!xmlStrcasecmp(attributeNode->name, (xmlChar*)"walking"))
5530 			{
5531 				get_string_value(sound, sizeof(sound), attributeNode);
5532 				walking_default = get_index_for_sound_type_name(sound);
5533 				if (walking_default == -1)
5534 				{
5535 					LOG_ERROR("%s: Unknown sound %s for crowd default", snd_config_error, sound);
5536 				}
5537 			}
5538 		}
5539 	}
5540 	else if (inNode->type == XML_ENTITY_REF_NODE)
5541 	{
5542 		LOG_ERROR("%s: Include not allowed in defaults sound def", snd_config_error);
5543 	}
5544 }
5545 
5546 void parse_item_image_ids(char * content, item_sound_data * pItem)
5547 {
5548 	int i, j;
5549 	char temp[5] = "";
5550 
5551 	i = 0;
5552 	j = -1;
5553 	while (i < strlen(content))
5554 	{
5555 		if (content[i] == ',')
5556 		{
5557 			if (pItem->num_imageids < MAX_ITEM_SOUND_IMAGE_IDS)
5558 			{
5559 				pItem->image_id[pItem->num_imageids++] = atoi(temp);
5560 				j = -1;
5561 			}
5562 			else
5563 			{
5564 				LOG_ERROR("%s: Too many image ids defined for item sound: %s", snd_config_error, content);
5565 				return;		// Avoid any more errors
5566 			}
5567 		}
5568 		else
5569 		{
5570 			j++;
5571 			if (j < 5)
5572 				temp[j] = content[i];
5573 			else
5574 			{
5575 				LOG_ERROR("%s: Invalid image id defined for item sound: %s...", snd_config_error, temp);
5576 				j = -1;
5577 			}
5578 		}
5579 		i++;
5580 	}
5581 	// Add anything remaining as a last image id
5582 	if (pItem->num_imageids < MAX_ITEM_SOUND_IMAGE_IDS)
5583 	{
5584 		pItem->image_id[pItem->num_imageids++] = atoi(temp);
5585 	}
5586 	else
5587 	{
5588 		LOG_ERROR("%s: Too many image ids defined for item sound: %s", snd_config_error, content);
5589 	}
5590 	return;
5591 }
5592 
5593 void parse_item_sound(const xmlNode *inNode)
5594 {
5595 	const xmlNode *attributeNode = NULL;
5596 	char content[100] = "";
5597 	item_sound_data * pItem;
5598 
5599 	if (inNode->type == XML_ELEMENT_NODE)
5600 	{
5601 		if (sound_num_items < MAX_SOUND_ITEMS)
5602 		{
5603 			pItem = &sound_item_data[sound_num_items++];
5604 
5605 			for (attributeNode = inNode->children; attributeNode; attributeNode = attributeNode->next)
5606 			{
5607 				get_string_value(content, sizeof(content), attributeNode);
5608 				if(!xmlStrcasecmp(attributeNode->name, (xmlChar*)"image_ids"))
5609 				{
5610 					parse_item_image_ids(content, pItem);
5611 				}
5612 				else if(!xmlStrcasecmp(attributeNode->name, (xmlChar*)"sound"))
5613 				{
5614 					pItem->sound = get_index_for_sound_type_name(content);
5615 					if (pItem->sound == -1)
5616 					{
5617 						LOG_ERROR("%s: Unknown sound %s for item sound", snd_config_error, content);
5618 					}
5619 				}
5620 			}
5621 		}
5622 		else
5623 		{
5624 			LOG_ERROR("%s: Too many item sounds defined.", snd_config_error);
5625 		}
5626 	}
5627 	else if (inNode->type == XML_ENTITY_REF_NODE)
5628 	{
5629 		LOG_ERROR("%s: Include not allowed in item sound def", snd_config_error);
5630 	}
5631 }
5632 
5633 void parse_tile_types(char * content, tile_sound_data * pTileType)
5634 {
5635 	int i, j;
5636 	char temp[5] = "";
5637 
5638 	i = 0;
5639 	j = -1;
5640 	while (i < strlen(content))
5641 	{
5642 		if (content[i] == ',')
5643 		{
5644 			if (pTileType->num_tile_types < MAX_SOUND_TILES)
5645 			{
5646 				pTileType->tile_type[pTileType->num_tile_types++] = atoi(temp);
5647 				j = -1;
5648 			}
5649 			else
5650 			{
5651 				LOG_ERROR("%s: Too many tile types defined for tile type sound: %s, max: %d", snd_config_error, content, MAX_SOUND_TILES);
5652 				return;		// Avoid any more errors
5653 			}
5654 		}
5655 		else
5656 		{
5657 			j++;
5658 			if (j < 5)
5659 				temp[j] = content[i];
5660 			else
5661 			{
5662 				LOG_ERROR("%s: Invalid tile type defined for tile type sound: %s...", snd_config_error, temp);
5663 				j = -1;
5664 			}
5665 		}
5666 		i++;
5667 	}
5668 	// Add anything remaining as a last tile type
5669 	if (pTileType->num_tile_types < MAX_SOUND_TILES)
5670 	{
5671 		pTileType->tile_type[pTileType->num_tile_types++] = atoi(temp);
5672 	}
5673 	else
5674 	{
5675 		LOG_ERROR("%s: Too many tile types defined for tile type sound: %s, max: %d", snd_config_error, content, MAX_SOUND_TILES);
5676 	}
5677 	return;
5678 }
5679 
5680 void parse_tile_type_sound(const xmlNode *inNode)
5681 {
5682 	const xmlNode *attributeNode = NULL;
5683 	char content[1024] = "";
5684 	tile_sound_data * pTileType;
5685 
5686 	if (inNode->type == XML_ELEMENT_NODE)
5687 	{
5688 		if (sound_num_tile_types < MAX_SOUND_TILE_TYPES)
5689 		{
5690 			pTileType = &sound_tile_data[sound_num_tile_types++];
5691 
5692 			for (attributeNode = inNode->children; attributeNode; attributeNode = attributeNode->next)
5693 			{
5694 				get_string_value(content, sizeof(content), attributeNode);
5695 				if (!xmlStrcasecmp(attributeNode->name, (xmlChar*)"tiles"))
5696 				{
5697 					parse_tile_types(content, pTileType);
5698 				}
5699 				else if (!xmlStrcasecmp(attributeNode->name, (xmlChar*)"actor_types"))
5700 				{
5701 					safe_strncpy(pTileType->sounds[pTileType->num_sounds].actor_types, content, sizeof(pTileType->sounds[pTileType->num_sounds].actor_types));
5702 					safe_strncpy(content, get_string_property(attributeNode, "sound"), sizeof(content));
5703 					pTileType->sounds[pTileType->num_sounds].sound = get_index_for_sound_type_name(content);
5704 					if (pTileType->sounds[pTileType->num_sounds].sound == -1)
5705 					{
5706 						LOG_ERROR("%s: Unknown sound %s for tile type sound", snd_config_error, content);
5707 					}
5708 					// Increment the actor_types count
5709 					pTileType->num_sounds++;
5710 				}
5711 				else if (!xmlStrcasecmp(attributeNode->name, (xmlChar*)"default"))
5712 				{
5713 					pTileType->default_sound = get_index_for_sound_type_name(content);
5714 					if (pTileType->default_sound == -1)
5715 					{
5716 						LOG_ERROR("%s: Unknown default sound %s for tile type sound", snd_config_error, content);
5717 					}
5718 				}
5719 			}
5720 		}
5721 		else
5722 		{
5723 			LOG_ERROR("%s: Too many tile type sounds defined.", snd_config_error);
5724 		}
5725 	}
5726 	else if (inNode->type == XML_ENTITY_REF_NODE)
5727 	{
5728 		LOG_ERROR("%s: Include not allowed in tile type sound def", snd_config_error);
5729 	}
5730 }
5731 
5732 void parse_spell_sound(const xmlNode *inNode)
5733 {
5734 	char content[100] = "";
5735 	int i = -1;
5736 
5737 	if (inNode->type == XML_ELEMENT_NODE)
5738 	{
5739 		get_string_value(content, sizeof(content), inNode);
5740 		if (!xmlStrcasecmp(inNode->name, (xmlChar*)"spell_effect"))
5741 		{
5742 			i = get_int_property(inNode, "id");
5743 			if (i >= 0 && i < NUM_ACTIVE_SPELLS)
5744 			{
5745 				sound_spell_data[i] = get_index_for_sound_type_name(content);
5746 				if (sound_spell_data[i] == -1)
5747 				{
5748 					LOG_ERROR("%s: Unknown sound %s for spell effect sound", snd_config_error, content);
5749 				}
5750 			}
5751 			else
5752 			{
5753 				LOG_ERROR("%s: Unknown spell effect ID %d for spell effect sound", snd_config_error, i);
5754 			}
5755 		}
5756 	}
5757 	else if (inNode->type == XML_ENTITY_REF_NODE)
5758 	{
5759 		LOG_ERROR("%s: Include not allowed in spell effect sound def", snd_config_error);
5760 	}
5761 }
5762 
5763 int parse_sound_defs(const xmlNode *node)
5764 {
5765 	const xmlNode *def;
5766 	int ok = 1;
5767 
5768 	for (def = node->children; def; def = def->next)
5769 	{
5770 		if (def->type == XML_ELEMENT_NODE)
5771 		{
5772 			if (xmlStrcasecmp (def->name, (xmlChar*)"sound") == 0)
5773 			{
5774 				parse_sound_object(def);
5775 			}
5776 			else if (xmlStrcasecmp (def->name, (xmlChar*)"defaults") == 0)
5777 			{
5778 				parse_sound_defaults(def);
5779 			}
5780 			else if (xmlStrcasecmp (def->name, (xmlChar*)"map") == 0)
5781 			{
5782 				parse_map_sound(def);
5783 			}
5784 			else if (xmlStrcasecmp (def->name, (xmlChar*)"effect") == 0)
5785 			{
5786 				parse_effect_sound(def);
5787 			}
5788 			else if (xmlStrcasecmp (def->name, (xmlChar*)"particle") == 0)
5789 			{
5790 				parse_particle_sound(def);
5791 			}
5792 			else if (xmlStrcasecmp (def->name, (xmlChar*)"item") == 0)
5793 			{
5794 				parse_item_sound(def);
5795 			}
5796 			else if (xmlStrcasecmp (def->name, (xmlChar*)"tile_type") == 0)
5797 			{
5798 				parse_tile_type_sound(def);
5799 			}
5800 			else if (xmlStrcasecmp (def->name, (xmlChar*)"spell_effect") == 0)
5801 			{
5802 				parse_spell_sound(def);
5803 			}
5804 			else
5805 			{
5806 				LOG_ERROR("%s: Unknown element found: %s", snd_config_error, def->name);
5807 				ok = 0;
5808 			}
5809 		}
5810 		else if (def->type == XML_ENTITY_REF_NODE)
5811 		{
5812 			ok &= parse_sound_defs (def->children);
5813 		}
5814 	}
5815 
5816 	return ok;
5817 }
5818 
5819 void load_sound_config_data (const char *file)
5820 {
5821 	xmlDoc *doc;
5822 	const xmlNode *root = NULL;
5823 
5824 	if (no_sound)
5825 		return;
5826 
5827 	if (!el_file_exists(file))
5828 		return;
5829 
5830 	if ((doc = xmlReadFile(file, NULL, XML_PARSE_NOENT)) == NULL)
5831 	{
5832 		char str[200];
5833 		safe_snprintf(str, sizeof(str), snd_config_open_err_str, file);
5834 		LOG_ERROR(str);
5835 		LOG_TO_CONSOLE(c_red1,str);
5836 	}
5837 	// Can we find a root element
5838 	else if ((root = xmlDocGetRootElement(doc))==NULL)
5839 	{
5840 		LOG_ERROR("%s: No XML root element found in '%s'", snd_config_error, file);
5841 	}
5842 	// Is the root the right type?
5843 	else if ( xmlStrcmp( root->name, (xmlChar*)"sound_config" ) )
5844 	{
5845 		LOG_ERROR("%s: Invalid root element '%s' in '%s'", snd_config_error, root->name, file);
5846 	}
5847 	// We've found our expected root, now parse the children
5848 	else
5849 	{
5850 		have_sound_config = 1;
5851 		clear_sound_data();
5852 		parse_sound_defs(root);
5853 		parse_server_sounds();
5854 		load_sound_warnings_list(SOUND_WARNINGS_PATH);
5855 	}
5856 
5857 	xmlFreeDoc(doc);
5858 #ifdef DEBUG
5859 	print_sound_types();
5860 #endif // DEBUG
5861 
5862 }
5863 
5864 /***********************
5865  * DEBUGGING FUNCTIONS *
5866  ***********************/
5867 
5868 #ifdef DEBUG
5869 void print_sound_types()
5870 {
5871 	int i, j;
5872 	sound_type *pData = NULL;
5873 	map_sound_data *pMap = NULL;
5874 	map_sound_boundary_def *pMapBoundary = NULL;
5875 	effect_sound_data *pEffect = NULL;
5876 	particle_sound_data *pParticle = NULL;
5877 	item_sound_data *pItem = NULL;
5878 	tile_sound_data *pTileType = NULL;
5879 
5880 	printf("\nSOUND TYPE DATA\n===============\n");
5881 	printf("There are %d sound types (max %d):\n", num_types, MAX_SOUNDS);
5882 	for (i = 0; i < num_types; ++i)
5883 	{
5884 		pData = &sound_type_data[i];
5885 		printf("Sound type '%s' #%d:\n"			, pData->name, i);
5886 		for (j = 0; j < pData->num_variants; ++j)
5887 		{
5888 			printf("\tVariant %d/%d:\n"				, j, pData->num_variants);
5889 			printf("\t\tIntro sample = '%s'\n"		, (pData->variant[j].part[STAGE_INTRO] ? pData->variant[j].part[STAGE_INTRO]->file_path : "(none)"));
5890 			printf("\t\tMain sample = '%s'\n"		, (pData->variant[j].part[STAGE_MAIN] ? pData->variant[j].part[STAGE_MAIN]->file_path : "(none)"));
5891 			printf("\t\tOutro sample = '%s'\n"		, (pData->variant[j].part[STAGE_OUTRO] ? pData->variant[j].part[STAGE_OUTRO]->file_path : "(none)"));
5892 			printf("\t\tGain = %f\n"				, pData->variant[j].gain);
5893 		}
5894 		printf("\tStereo = %d\n"				, pData->stereo);
5895 		printf("\tDistance = %f\n"				, pData->distance);
5896 		printf("\tPositional = %d\n"			, pData->positional);
5897 		printf("\tLoops = %d\n"					, pData->loops);
5898 		printf("\tFadeout time = %dms\n"		, pData->fadeout_time);
5899 		printf("\tEcho delay = %dms\n"			, pData->echo_delay);
5900 		printf("\tEcho volume = %d%%\n"			, pData->echo_volume);
5901 		printf("\tTime of day flags = 0x%x\n"	, pData->time_of_the_day_flags);
5902 		printf("\tPriority = %d\n"				, pData->priority);
5903 		printf("\tType = %d\n\n"				, pData->type);
5904 	}
5905 
5906 	printf("\nMAP SOUND DATA\n===============\n");
5907 	printf("There are %d map sounds:\n"		, sound_num_maps);
5908 	for (i = 0; i < sound_num_maps; ++i)
5909 	{
5910 		pMap = &sound_map_data[i];
5911 		printf("Map id: %d\n"				, pMap->id);
5912 		printf("Map name: %s\n"				, pMap->name);
5913 		printf("Num boundaries: %d\n"		, pMap->num_boundaries);
5914 		for (j = 0; j < pMap->num_boundaries; ++j)
5915 		{
5916 			pMapBoundary = &pMap->boundaries[j];
5917 			printf("Boundary num: %d\n"			, j);
5918 			printf("\tBackground sound: %d\n"	, pMapBoundary->bg_sound);
5919 			printf("\tCrowd sound: %d\n"		, pMapBoundary->crowd_sound);
5920 			printf("\tTime of day flags: 0x%x\n", pMapBoundary->time_of_day_flags);
5921 			printf("\tDefault: %s\n"			, pMapBoundary->is_default == 0 ? "No" : "Yes");
5922 			printf("\tX1, Y1, A1: (%d, %d, %f), X2, Y2, A2: (%d, %d, %f), X3, Y3, A3: (%d, %d, %f), X4, Y4, A4: (%d, %d, %f)\n",
5923 				pMapBoundary->p[0].x, pMapBoundary->p[0].y, pMapBoundary->p[0].a,
5924 				pMapBoundary->p[1].x, pMapBoundary->p[1].y, pMapBoundary->p[1].a,
5925 				pMapBoundary->p[2].x, pMapBoundary->p[2].y, pMapBoundary->p[2].a,
5926 				pMapBoundary->p[3].x, pMapBoundary->p[3].y, pMapBoundary->p[3].a);
5927 			printf("\tOuter box - X1, Y1, A1: (%d, %d, %f); X2, Y2, A1: (%d, %d, %f)\n",
5928 				pMapBoundary->o[0].x, pMapBoundary->o[0].y, pMapBoundary->o[0].a,
5929 				pMapBoundary->o[1].x, pMapBoundary->o[1].y, pMapBoundary->o[1].a);
5930 			printf("\tInternal point: %d\n"		, pMapBoundary->int_point);
5931 		}
5932 		printf("\n");
5933 		printf("Num walk boundaries: %d\n"		, pMap->num_walk_boundaries);
5934 		for (j = 0; j < pMap->num_walk_boundaries; ++j)
5935 		{
5936 			pMapBoundary = &pMap->walk_boundaries[j];
5937 			printf("Walk boundary num: %d\n"	, j);
5938 			printf("\tWalk sound: %d\n"			, pMapBoundary->bg_sound);
5939 			printf("\tTime of day flags: 0x%x\n", pMapBoundary->time_of_day_flags);
5940 			printf("\tX1, Y1, A1: (%d, %d, %f), X2, Y2, A2: (%d, %d, %f), X3, Y3, A3: (%d, %d, %f), X4, Y4, A4: (%d, %d, %f)\n",
5941 				pMapBoundary->p[0].x, pMapBoundary->p[0].y, pMapBoundary->p[0].a,
5942 				pMapBoundary->p[1].x, pMapBoundary->p[1].y, pMapBoundary->p[1].a,
5943 				pMapBoundary->p[2].x, pMapBoundary->p[2].y, pMapBoundary->p[2].a,
5944 				pMapBoundary->p[3].x, pMapBoundary->p[3].y, pMapBoundary->p[3].a);
5945 			printf("\tOuter box - X1, Y1, A1: (%d, %d, %f); X2, Y2, A1: (%d, %d, %f)\n",
5946 				pMapBoundary->o[0].x, pMapBoundary->o[0].y, pMapBoundary->o[0].a,
5947 				pMapBoundary->o[1].x, pMapBoundary->o[1].y, pMapBoundary->o[1].a);
5948 			printf("\tInternal point: %d\n"		, pMapBoundary->int_point);
5949 		}
5950 		printf("\n");
5951 	}
5952 
5953 	printf("\nEFFECT SOUND DATA\n===============\n");
5954 	printf("There are %d effect sounds:\n", sound_num_effects);
5955 	for (i = 0; i < sound_num_effects; ++i)
5956 	{
5957 		pEffect = &sound_effect_data[i];
5958 		printf("Effect ID: %d\n"		, pEffect->id);
5959 		printf("Sound: %d\n"			, pEffect->sound);
5960 	}
5961 
5962 	printf("\nPARTICLE SOUND DATA\n===============\n");
5963 	printf("There are %d particle sounds:\n", sound_num_particles);
5964 	for (i = 0; i < sound_num_particles; ++i)
5965 	{
5966 		pParticle = &sound_particle_data[i];
5967 		printf("Particle file: %s\n"	, pParticle->file);
5968 		printf("Sound: %d\n"			, pParticle->sound);
5969 	}
5970 
5971 	printf("\nITEM SOUND DATA\n===============\n");
5972 	printf("There are %d item sounds:\n", sound_num_items);
5973 	for (i = 0; i < sound_num_items; ++i)
5974 	{
5975 		pItem = &sound_item_data[i];
5976 		printf("Sound: %d\n"				, pItem->sound);
5977 		printf("Image ID's (%d total):\n"	, pItem->num_imageids);
5978 		for (j = 0; j < pItem->num_imageids; ++j)
5979 		{
5980 			printf("%d, "					, pItem->image_id[j]);
5981 		}
5982 		printf("\n");
5983 	}
5984 
5985 	printf("\nTILE (WALKING) SOUND DATA\n===============\n");
5986 	printf("There are %d tile type sounds:\n", sound_num_tile_types);
5987 	for (i = 0; i < sound_num_tile_types; ++i)
5988 	{
5989 		pTileType = &sound_tile_data[i];
5990 		printf("Tile: %d\n"							, i);
5991 		printf("\tDefault sound: %d\n"				, pTileType->default_sound);
5992 		printf("\tTile types (%d total):\n\t\t"		, pTileType->num_tile_types);
5993 		for (j = 0; j < pTileType->num_tile_types; ++j)
5994 		{
5995 			printf("%d, "							, pTileType->tile_type[j]);
5996 		}
5997 		printf("\n\tNum sounds: %d\n"				, pTileType->num_sounds);
5998 		for (j = 0; j < pTileType->num_sounds; ++j)
5999 		{
6000 			printf("\t\tSound: %d\n"				, pTileType->sounds[j].sound);
6001 			printf("\t\tActor types: %s\n"			, pTileType->sounds[j].actor_types);
6002 		}
6003 	}
6004 
6005 	printf("\nSPELL EFFECT SOUND DATA\n===============\n");
6006 	printf("There are %d spell effects:\n", NUM_ACTIVE_SPELLS);
6007 	for (i = 0; i <NUM_ACTIVE_SPELLS; ++i)
6008 	{
6009 		printf("Spell Effect Sound: %d = %d\n", i, sound_spell_data[i]);
6010 	}
6011 
6012 	printf("\nSERVER SOUNDS\n===============\n");
6013 	printf("There are %d server sounds:\n", MAX_SERVER_SOUNDS);
6014 	for (i = 0; i <MAX_SERVER_SOUNDS; ++i)
6015 	{
6016 		printf("Server Sound: %d = %d\n", i, server_sound[i]);
6017 	}
6018 
6019 	printf("\nTEXT WARNING SOUNDS\n===============\n");
6020 	printf("There are %d/%d text warning sounds:\n", num_sound_warnings, MAX_SOUND_WARNINGS);
6021 	for (i = 0; i < num_sound_warnings; ++i)
6022 	{
6023 		printf("Text Warning: %d\n", i);
6024 		printf("\tText: %s\n", warnings_list[i].string);
6025 		printf("\tSound: %d\n", warnings_list[i].sound);
6026 	}
6027 }
6028 
6029 void print_sound_samples()
6030 {
6031 	int i;
6032 	sound_sample *pData=NULL;
6033 	printf("\nSOUND SAMPLE DATA\n===============\n");
6034 	printf("There are %d sound samples loaded (max %d):\n", num_samples, MAX_BUFFERS);
6035 	printf("(skipped sample numbers are buffers that have been used and released)\n");
6036 
6037 	for (i = 0; i < MAX_BUFFERS; ++i)
6038 	{
6039 		pData = &sound_sample_data[i];
6040 		if (alIsBuffer(pData->buffer))
6041 		{
6042 			printf("Sample %d:\n"			, i);
6043 			printf("\tBuffer ID = %d\n"		, pData->buffer);
6044 			printf("\tSize = %d\n"			, pData->size);
6045 			printf("\tFrequency = %f\n"		, pData->freq);
6046 			printf("\tChannels = %d\n"		, pData->channels);
6047 			printf("\tBits = %d\n"			, pData->bits);
6048 			printf("\tLength = %dms\n\n"	, pData->length);
6049 		}
6050 	}
6051 }
6052 
6053 void print_sounds_list()
6054 {
6055 	int i;
6056 	sound_loaded *pData = NULL;
6057 	printf("\nLOADED SOUND DATA\n===============\n");
6058 	printf("There are %d loaded sounds (max %d):\n", num_sounds, MAX_BUFFERS * 2);
6059 
6060 	for (i = 0; i < num_sounds; ++i)
6061 	{
6062 		pData = &sounds_list[i];
6063 		printf("Loaded sound #%d:\n"			, i);
6064 		printf("\tSound type %d : '%s'\n"		, pData->sound, sound_type_data[pData->sound].name);
6065 		printf("\tX = %d\n"						, pData->x);
6066 		printf("\tY = %d\n"						, pData->y);
6067 		printf("\tPlaying = %s\n"				, pData->playing == 0 ? "No" : "Yes");
6068 		printf("\tBase gain = %f\n"				, pData->base_gain);
6069 		printf("\tCurrent (final) gain = %f\n"	, pData->cur_gain);
6070 		printf("\tSamples are loaded: %s\n"		, pData->loaded == 0 ? "No" : "Yes");
6071 	}
6072 }
6073 
6074 void print_sound_sources()
6075 {
6076 	int i;
6077 	source_data *pData = NULL;
6078 	printf("\nSOUND SOURCE DATA\n===============\n");
6079 	printf("There are %d sound sources (max %d):\n", used_sources, max_sources);
6080 
6081 	for (i = 0; i < used_sources; ++i)
6082 	{
6083 		pData = &sound_source_data[i];
6084 		printf("Source #%d:\n"				, i);
6085 		printf("\tLoaded sound num = %d\n"	, pData->loaded_sound);
6086 		printf("\tSound type = %d : '%s'\n"	, sounds_list[pData->loaded_sound].sound
6087 											, sound_type_data[sounds_list[pData->loaded_sound].sound].name);
6088 		printf("\tPlay duration = %dms\n"	, pData->play_duration);
6089 		printf("\tSource ID = %d\n"			, pData->source);
6090 	}
6091 }
6092 
6093 void print_sound_streams()
6094 {
6095 	int i;
6096 	stream_data *pData = NULL;
6097 	printf("\nSOUND STREAM DATA\n===============\n");
6098 	printf("There are %d sound streams:\n", max_streams);
6099 
6100 	for (i = 0; i < max_streams; ++i)
6101 	{
6102 		pData = &streams[i];
6103 		printf("Stream #%d:\n"				, i);
6104 		printf("\tType = %s\n"				, get_stream_type(pData->type));
6105 		printf("\tSound = %d : '%s'\n"		, pData->sound
6106 											, pData->type != STREAM_TYPE_MUSIC ? sound_type_data[pData->sound].name : playlist[pData->sound].file_name);
6107 		printf("\tSource ID = %d\n"			, pData->source);
6108 		printf("\tCookie = %u\n"			, pData->cookie);
6109 		printf("\tPlaying = %s\n"			, pData->playing == 1 ? "Yes" : "No");
6110 		printf("\tDefault = %s\n"			, pData->is_default == 1 ? "Yes" : "No");
6111 		printf("\tCurrent fade = %d\n"		, pData->fade);
6112 		printf("\tFade length = %d\n"		, pData->fade_length);
6113 		printf("\tProcessed = %d\n"			, pData->processed);
6114 	}
6115 }
6116 
6117 #endif //_DEBUG
6118 #endif // !NEW_SOUND
6119