1 /*
2  * $Source: /cvs/cvsroot/d2x/arch/dos/digi.c,v $
3  * $Revision: 1.3 $
4  * $Author: bradleyb $
5  * $Date: 2001/10/25 08:25:33 $
6  *
7  * DOS digital audio support
8  *
9  * $Log: digi.c,v $
10  * Revision 1.3  2001/10/25 08:25:33  bradleyb
11  * Finished moving stuff to arch/blah.  I know, it's ugly, but It'll be easier to sync with d1x.
12  *
13  * Revision 1.3  2001/01/31 14:04:45  bradleyb
14  * Fix compiler warnings
15  *
16  * Revision 1.2  2001/01/29 13:53:28  bradleyb
17  * Fixed build, minor fixes
18  *
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include <conf.h>
23 #endif
24 
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 
29 #include "pstypes.h"
30 #include "error.h"
31 #include "mono.h"
32 #include "fix.h"
33 #include "vecmat.h"
34 #include "gr.h" // needed for piggy.h
35 #include "piggy.h"
36 #include "digi.h"
37 #include "sounds.h"
38 #include "wall.h"
39 #include "newdemo.h"
40 #include "kconfig.h"
41 
42 int digi_sample_rate=11025;
43 int digi_timer_rate                                     = 9943;                 // rate for the timer to go off to handle the driver system (120 Hz)
44 
45 //edited 05/17/99 Matt Mueller - added ifndef NO_ASM
46 //added on 980905 by adb to add inline fixmul for mixer on i386
47 #ifndef NO_ASM
48 #ifdef __i386__
49 #define do_fixmul(x,y)				\
50 ({						\
51 	int _ax, _dx;				\
52 	asm("imull %2\n\tshrdl %3,%1,%0"	\
53 	    : "=a"(_ax), "=d"(_dx)		\
54 	    : "rm"(y), "i"(16), "0"(x));	\
55 	_ax;					\
56 })
fixmul(fix x,fix y)57 extern inline fix fixmul(fix x, fix y) { return do_fixmul(x,y); }
58 #endif
59 #endif
60 //end edit by adb
61 //end edit -MM
62 
63 //changed on 980905 by adb to increase number of concurrent sounds
64 #define MAX_SOUND_SLOTS 32
65 //end changes by adb
66 #define SOUND_BUFFER_SIZE 512
67 
68 #define MIN_VOLUME 10
69 
70 /* This table is used to add two sound values together and pin
71  * the value to avoid overflow.  (used with permission from ARDI)
72  * DPH: Taken from SDL/src/SDL_mixer.c.
73  */
74 static const unsigned char mix8[] =
75 {
76   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
88   0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
89   0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
90   0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
91   0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
92   0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
93   0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
94   0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
95   0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B,
96   0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
97   0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
98   0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
99   0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
100   0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
101   0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,
102   0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
103   0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
104   0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
105   0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
106   0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4,
107   0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
108   0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
109   0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
110   0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xFF,
111   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
112   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
113   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
114   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
115   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
116   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
117   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
118   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
119   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
120   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
121   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
122   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
123 };
124 
125 #define SOF_USED			1		// Set if this sample is used
126 #define SOF_PLAYING			2		// Set if this sample is playing on a channel
127 #define SOF_LINK_TO_OBJ		4		// Sound is linked to a moving object. If object dies, then finishes play and quits.
128 #define SOF_LINK_TO_POS		8		// Sound is linked to segment, pos
129 #define SOF_PLAY_FOREVER	16		// Play forever (or until level is stopped), otherwise plays once
130 
131 typedef struct sound_object {
132 	short		signature;		// A unique signature to this sound
133 	ubyte		flags;			// Used to tell if this slot is used and/or currently playing, and how long.
134 	fix		max_volume;		// Max volume that this sound is playing at
135 	fix		max_distance;	        // The max distance that this sound can be heard at...
136 	int		volume;			// Volume that this sound is playing at
137 	int 		pan;			// Pan value that this sound is playing at
138 	int		handle; 		// What handle this sound is playing on.  Valid only if SOF_PLAYING is set.
139 	short		soundnum;		// The sound number that is playing
140 	union {
141 		struct {
142 			short		segnum; 			// Used if SOF_LINK_TO_POS field is used
143 			short		sidenum;
144 			vms_vector	position;
145 		}pos;
146 		struct {
147 			short		 objnum;			 // Used if SOF_LINK_TO_OBJ field is used
148 			short		 objsignature;
149 		}obj;
150 	}link;
151 } sound_object;
152 #define lp_segnum link.pos.segnum
153 #define lp_sidenum link.pos.sidenum
154 #define lp_position link.pos.position
155 
156 #define lo_objnum link.obj.objnum
157 #define lo_objsignature link.obj.objsignature
158 
159 #define MAX_SOUND_OBJECTS 16
160 sound_object SoundObjects[MAX_SOUND_OBJECTS];
161 short next_signature=0;
162 
163 //added/changed on 980905 by adb to make sfx volume work, on 990221 by adb changed F1_0 to F1_0 / 2
164 #define SOUND_MAX_VOLUME (F1_0 / 2)
165 
166 int digi_volume = SOUND_MAX_VOLUME;
167 //end edit by adb
168 
169 int digi_lomem = 0;
170 
171 static int digi_initialised = 0;
172 
173 struct sound_slot {
174  int soundno;
175  int playing;   // Is there a sample playing on this channel?
176  int looped;    // Play this sample looped?
177  fix pan;       // 0 = far left, 1 = far right
178  fix volume;    // 0 = nothing, 1 = fully on
179  //changed on 980905 by adb from char * to unsigned char *
180  unsigned char *samples;
181  //end changes by adb
182  unsigned int length; // Length of the sample
183  unsigned int position; // Position we are at at the moment.
184 } SoundSlots[MAX_SOUND_SLOTS];
185 
186 static int digi_sounds_initialized = 0;
187 
188 //added on 980905 by adb to add rotating/volume based sound kill system
189 static int digi_max_channels = 16;
190 static int next_handle = 0;
191 int SampleHandles[32];
192 void reset_sounds_on_channel(int channel);
193 //end edit by adb
194 
195 void digi_reset_digi_sounds(void);
196 
197 /* Audio mixing callback */
198 //changed on 980905 by adb to cleanup, add pan support and optimize mixer
audio_mixcallback(void * userdata,unsigned char * stream,int len)199 static void audio_mixcallback(void *userdata, unsigned char *stream, int len)
200 {
201  unsigned char *streamend = stream + len;
202  struct sound_slot *sl;
203 
204  for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++)
205  {
206   if (sl->playing)
207   {
208    unsigned char *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length;
209    unsigned char *sp = stream;
210    signed char v;
211    fix vl, vr;
212    int x;
213 
214    if ((x = sl->pan) & 0x8000)
215    {
216     vl = 0x20000 - x * 2;
217     vr = 0x10000;
218    }
219    else
220    {
221     vl = 0x10000;
222     vr = x * 2;
223    }
224    vl = fixmul(vl, (x = sl->volume));
225    vr = fixmul(vr, x);
226    while (sp < streamend)
227    {
228     if (sldata == slend)
229     {
230      if (!sl->looped)
231      {
232       sl->playing = 0;
233       break;
234      }
235      sldata = sl->samples;
236     }
237     v = *(sldata++) - 0x80;
238     *(sp++) = mix8[ *sp + fixmul(v, vl) + 0x80 ];
239     *(sp++) = mix8[ *sp + fixmul(v, vr) + 0x80 ];
240    }
241    sl->position = sldata - sl->samples;
242   }
243  }
244 }
245 //end changes by adb
246 
247 /* Initialise audio devices. */
digi_init()248 int digi_init()
249 {
250     /* this is just here now to stop gcc from complaining about
251      * audio_mixcallback being declared static and not used...
252      */
253     if (0) audio_mixcallback(NULL,NULL,0);
254 
255  return 1;
256 }
257 
258 /* Toggle audio */
digi_reset()259 void digi_reset() { }
260 
261 /* Shut down audio */
digi_close()262 void digi_close()
263 {
264  if (!digi_initialised) return;
265  digi_initialised = 0;
266 }
267 
268 /* Find the sound which actually equates to a sound number */
digi_xlat_sound(int soundno)269 int digi_xlat_sound(int soundno)
270 {
271 	if ( soundno < 0 ) return -1;
272 
273 	if ( digi_lomem )	{
274 		soundno = AltSounds[soundno];
275 		if ( soundno == 255 ) return -1;
276 	}
277 	return Sounds[soundno];
278 }
279 
get_free_slot()280 static int get_free_slot()
281 {
282  int i;
283  for (i=0; i<MAX_SOUND_SLOTS; i++)
284  {
285   if (!SoundSlots[i].playing) return i;
286  }
287  return -1;
288 }
289 
digi_start_sound(int soundnum,fix volume,fix pan,int unknown1,int unknown2,int unknown3,int unknown4)290 int digi_start_sound(int soundnum, fix volume, fix pan, int unknown1, int unknown2, int unknown3, int unknown4)
291 {
292  int ntries;
293  int slot;
294 
295  if (!digi_initialised) return -1;
296 
297  //added on 980905 by adb from original source to add sound kill system
298  // play at most digi_max_channel samples, if possible kill sample with low volume
299  ntries = 0;
300 
301 TryNextChannel:
302  if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing)  )
303  {
304   if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries<digi_max_channels) )
305   {
306    //mprintf(( 0, "Not stopping loud sound %d.\n", next_handle ));
307    next_handle++;
308    if ( next_handle >= digi_max_channels )
309     next_handle = 0;
310    ntries++;
311    goto TryNextChannel;
312   }
313   //mprintf(( 0, "[SS:%d]", next_handle ));
314   SoundSlots[SampleHandles[next_handle]].playing = 0;
315   SampleHandles[next_handle] = -1;
316  }
317  //end edit by adb
318 
319  slot = get_free_slot();
320  if (slot<0) return -1;
321 
322  SoundSlots[slot].soundno = soundnum;
323  SoundSlots[slot].samples = GameSounds[soundnum].data;
324  SoundSlots[slot].length = GameSounds[soundnum].length;
325  SoundSlots[slot].volume = fixmul(digi_volume, volume);
326  SoundSlots[slot].pan = pan;
327  SoundSlots[slot].position = 0;
328  SoundSlots[slot].looped = 0;
329  SoundSlots[slot].playing = 1;
330 
331  //added on 980905 by adb to add sound kill system from original sos digi.c
332  reset_sounds_on_channel(slot);
333  SampleHandles[next_handle] = slot;
334  next_handle++;
335  if ( next_handle >= digi_max_channels )
336   next_handle = 0;
337  //end edit by adb
338 
339  return slot;
340 }
341 
342  //added on 980905 by adb to add sound kill system from original sos digi.c
reset_sounds_on_channel(int channel)343 void reset_sounds_on_channel( int channel )
344 {
345  int i;
346 
347  for (i=0; i<digi_max_channels; i++)
348   if (SampleHandles[i] == channel)
349    SampleHandles[i] = -1;
350 }
351 //end edit by adb
352 
digi_start_sound_object(int obj)353 int digi_start_sound_object(int obj)
354 {
355  int slot;
356 
357  if (!digi_initialised) return -1;
358  slot = get_free_slot();
359 
360  if (slot<0) return -1;
361 
362 
363  SoundSlots[slot].soundno = SoundObjects[obj].soundnum;
364  SoundSlots[slot].samples = GameSounds[SoundObjects[obj].soundnum].data;
365  SoundSlots[slot].length = GameSounds[SoundObjects[obj].soundnum].length;
366  SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume);
367  SoundSlots[slot].pan = SoundObjects[obj].pan;
368  SoundSlots[slot].position = 0;
369  SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER);
370  SoundSlots[slot].playing = 1;
371 
372  SoundObjects[obj].signature = next_signature++;
373  SoundObjects[obj].handle = slot;
374 
375  SoundObjects[obj].flags |= SOF_PLAYING;
376  //added on 980905 by adb to add sound kill system from original sos digi.c
377  reset_sounds_on_channel(slot);
378  //end edit by adb
379 
380  return 0;
381 }
382 
383 
384 // Play the given sound number.
385 // Volume is max at F1_0.
digi_play_sample(int soundno,fix max_volume)386 void digi_play_sample( int soundno, fix max_volume )
387 {
388 #ifdef NEWDEMO
389 	if ( Newdemo_state == ND_STATE_RECORDING )
390 		newdemo_record_sound( soundno );
391 #endif
392 	soundno = digi_xlat_sound(soundno);
393 
394 	if (!digi_initialised) return;
395 
396 	if (soundno < 0 ) return;
397 
398 	digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
399 }
400 
401 // Play the given sound number. If the sound is already playing,
402 // restart it.
digi_play_sample_once(int soundno,fix max_volume)403 void digi_play_sample_once( int soundno, fix max_volume )
404 {
405 	int i;
406 
407 #ifdef NEWDEMO
408 	if ( Newdemo_state == ND_STATE_RECORDING )
409 		newdemo_record_sound( soundno );
410 #endif
411 	soundno = digi_xlat_sound(soundno);
412 
413 	if (!digi_initialised) return;
414 
415 	if (soundno < 0 ) return;
416 
417         for (i=0; i < MAX_SOUND_SLOTS; i++)
418           if (SoundSlots[i].soundno == soundno)
419             SoundSlots[i].playing = 0;
420 	digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
421 
422 }
423 
digi_play_sample_3d(int soundno,int angle,int volume,int no_dups)424 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) // Volume from 0-0x7fff
425 {
426 	no_dups = 1;
427 
428 #ifdef NEWDEMO
429 	if ( Newdemo_state == ND_STATE_RECORDING )		{
430 		if ( no_dups )
431 			newdemo_record_sound_3d_once( soundno, angle, volume );
432 		else
433 			newdemo_record_sound_3d( soundno, angle, volume );
434 	}
435 #endif
436 	soundno = digi_xlat_sound(soundno);
437 
438 	if (!digi_initialised) return;
439 	if (soundno < 0 ) return;
440 
441 	if (volume < MIN_VOLUME ) return;
442 	digi_start_sound(soundno, volume, angle, 0, 0, 0, 0);
443 }
444 
digi_get_sound_loc(vms_matrix * listener,vms_vector * listener_pos,int listener_seg,vms_vector * sound_pos,int sound_seg,fix max_volume,int * volume,int * pan,fix max_distance)445 void digi_get_sound_loc( vms_matrix * listener, vms_vector * listener_pos, int listener_seg, vms_vector * sound_pos, int sound_seg, fix max_volume, int *volume, int *pan, fix max_distance )
446 {
447 	vms_vector	vector_to_sound;
448 	fix angle_from_ear, cosang,sinang;
449 	fix distance;
450 	fix path_distance;
451 
452 	*volume = 0;
453 	*pan = 0;
454 
455 	max_distance = (max_distance*5)/4;		// Make all sounds travel 1.25 times as far.
456 
457 	//	Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
458 	distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
459 
460 	if (distance < max_distance )	{
461 		int num_search_segs = f2i(max_distance/20);
462 		if ( num_search_segs < 1 ) num_search_segs = 1;
463 
464 		path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
465 		if ( path_distance > -1 )	{
466 			*volume = max_volume - fixdiv(path_distance,max_distance);
467 			//mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
468 			if (*volume > 0 )	{
469 				angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
470 				fix_sincos(angle_from_ear,&sinang,&cosang);
471 				//mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
472 				if (Config_channels_reversed) cosang *= -1;
473 				*pan = (cosang + F1_0)/2;
474 			} else {
475 				*volume = 0;
476 			}
477 		}
478 	}
479 }
480 
digi_link_sound_to_object2(int org_soundnum,short objnum,int forever,fix max_volume,fix max_distance)481 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix  max_distance )
482 {
483 	int i,volume,pan;
484 	object * objp;
485 	int soundnum;
486 
487 	soundnum = digi_xlat_sound(org_soundnum);
488 
489 	if ( max_volume < 0 ) return -1;
490 //	if ( max_volume > F1_0 ) max_volume = F1_0;
491 
492 	if (!digi_initialised) return -1;
493 	if (soundnum < 0 ) return -1;
494 	if (GameSounds[soundnum].data==NULL) {
495 		Int3();
496 		return -1;
497 	}
498 	if ((objnum<0)||(objnum>Highest_object_index))
499 		return -1;
500 
501 	if ( !forever )	{
502 		// Hack to keep sounds from building up...
503 		digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
504 		digi_play_sample_3d( org_soundnum, pan, volume, 0 );
505 		return -1;
506 	}
507 
508        	for (i=0; i<MAX_SOUND_OBJECTS; i++ )
509         	if (SoundObjects[i].flags==0)
510 	           break;
511 
512 	if (i==MAX_SOUND_OBJECTS) {
513 		mprintf((1, "Too many sound objects!\n" ));
514 		return -1;
515 	}
516 
517 	SoundObjects[i].signature=next_signature++;
518 	SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
519 	if ( forever )
520 		SoundObjects[i].flags |= SOF_PLAY_FOREVER;
521 	SoundObjects[i].lo_objnum = objnum;
522 	SoundObjects[i].lo_objsignature = Objects[objnum].signature;
523 	SoundObjects[i].max_volume = max_volume;
524 	SoundObjects[i].max_distance = max_distance;
525 	SoundObjects[i].volume = 0;
526 	SoundObjects[i].pan = 0;
527 	SoundObjects[i].soundnum = soundnum;
528 
529 	objp = &Objects[SoundObjects[i].lo_objnum];
530 	digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
531                        &objp->pos, objp->segnum, SoundObjects[i].max_volume,
532                        &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
533 
534 	if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
535 	       digi_start_sound_object(i);
536 
537 	return SoundObjects[i].signature;
538 }
539 
digi_link_sound_to_object(int soundnum,short objnum,int forever,fix max_volume)540 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
541 { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); }
542 
digi_link_sound_to_pos2(int org_soundnum,short segnum,short sidenum,vms_vector * pos,int forever,fix max_volume,fix max_distance)543 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
544 {
545 	int i, volume, pan;
546 	int soundnum;
547 
548 	soundnum = digi_xlat_sound(org_soundnum);
549 
550 	if ( max_volume < 0 ) return -1;
551 //	if ( max_volume > F1_0 ) max_volume = F1_0;
552 
553 	if (!digi_initialised) return -1;
554 	if (soundnum < 0 ) return -1;
555 	if (GameSounds[soundnum].data==NULL) {
556 		Int3();
557 		return -1;
558 	}
559 
560 	if ((segnum<0)||(segnum>Highest_segment_index))
561 		return -1;
562 
563 	if ( !forever )	{
564 		// Hack to keep sounds from building up...
565 		digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
566 		digi_play_sample_3d( org_soundnum, pan, volume, 0 );
567 		return -1;
568 	}
569 
570 	for (i=0; i<MAX_SOUND_OBJECTS; i++ )
571 		if (SoundObjects[i].flags==0)
572 			break;
573 
574 	if (i==MAX_SOUND_OBJECTS) {
575 		mprintf((1, "Too many sound objects!\n" ));
576 		return -1;
577 	}
578 
579 
580 	SoundObjects[i].signature=next_signature++;
581 	SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
582 	if ( forever )
583 		SoundObjects[i].flags |= SOF_PLAY_FOREVER;
584 	SoundObjects[i].lp_segnum = segnum;
585 	SoundObjects[i].lp_sidenum = sidenum;
586 	SoundObjects[i].lp_position = *pos;
587 	SoundObjects[i].soundnum = soundnum;
588 	SoundObjects[i].max_volume = max_volume;
589 	SoundObjects[i].max_distance = max_distance;
590 	SoundObjects[i].volume = 0;
591 	SoundObjects[i].pan = 0;
592 	digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
593 					   &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
594 					   SoundObjects[i].max_volume,
595                        &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
596 
597 	if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
598 		digi_start_sound_object(i);
599 
600 	return SoundObjects[i].signature;
601 }
602 
digi_link_sound_to_pos(int soundnum,short segnum,short sidenum,vms_vector * pos,int forever,fix max_volume)603 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
604 {
605 	return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
606 }
607 
digi_kill_sound_linked_to_segment(int segnum,int sidenum,int soundnum)608 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
609 {
610 	int i,killed;
611 
612 	soundnum = digi_xlat_sound(soundnum);
613 
614 	if (!digi_initialised) return;
615 
616 	killed = 0;
617 
618 	for (i=0; i<MAX_SOUND_OBJECTS; i++ )	{
619 		if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) )	{
620 			if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
621 				if ( SoundObjects[i].flags & SOF_PLAYING )	{
622 				        SoundSlots[SoundObjects[i].handle].playing = 0;
623 				}
624 				SoundObjects[i].flags = 0;	// Mark as dead, so some other sound can use this sound
625 				killed++;
626 			}
627 		}
628 	}
629 	// If this assert happens, it means that there were 2 sounds
630 	// that got deleted. Weird, get John.
631 	if ( killed > 1 )	{
632 		mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
633 	}
634 }
635 
digi_kill_sound_linked_to_object(int objnum)636 void digi_kill_sound_linked_to_object( int objnum )
637 {
638 	int i,killed;
639 
640 	if (!digi_initialised) return;
641 
642 	killed = 0;
643 
644 	for (i=0; i<MAX_SOUND_OBJECTS; i++ )	{
645 		if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) )	{
646 			if (SoundObjects[i].lo_objnum == objnum)   {
647 				if ( SoundObjects[i].flags & SOF_PLAYING )	{
648                                      SoundSlots[SoundObjects[i].handle].playing = 0;
649 				}
650 				SoundObjects[i].flags = 0;	// Mark as dead, so some other sound can use this sound
651 				killed++;
652 			}
653 		}
654 	}
655 	// If this assert happens, it means that there were 2 sounds
656 	// that got deleted. Weird, get John.
657 	if ( killed > 1 )	{
658 		mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
659 	}
660 }
661 
digi_sync_sounds()662 void digi_sync_sounds()
663 {
664 	int i;
665 	int oldvolume, oldpan;
666 
667 	if (!digi_initialised) return;
668 
669 	for (i=0; i<MAX_SOUND_OBJECTS; i++ )	{
670 		if ( SoundObjects[i].flags & SOF_USED )	{
671 			oldvolume = SoundObjects[i].volume;
672 			oldpan = SoundObjects[i].pan;
673 
674 			if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) )	{
675 			 	// Check if its done.
676 				if (SoundObjects[i].flags & SOF_PLAYING) {
677 					if (!SoundSlots[SoundObjects[i].handle].playing) {
678 						SoundObjects[i].flags = 0;	// Mark as dead, so some other sound can use this sound
679 						continue;		// Go on to next sound...
680 					}
681 				}
682 			}
683 
684 			if ( SoundObjects[i].flags & SOF_LINK_TO_POS )	{
685 				digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
686 								&SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
687 								SoundObjects[i].max_volume,
688                                 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
689 
690 			} else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ )	{
691 				object * objp;
692 
693 				objp = &Objects[SoundObjects[i].lo_objnum];
694 
695 				if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature))  {
696 					// The object that this is linked to is dead, so just end this sound if it is looping.
697 					if ( (SoundObjects[i].flags & SOF_PLAYING)  && (SoundObjects[i].flags & SOF_PLAY_FOREVER))	{
698 					     SoundSlots[SoundObjects[i].handle].playing = 0;
699 					}
700 					SoundObjects[i].flags = 0;	// Mark as dead, so some other sound can use this sound
701 					continue;		// Go on to next sound...
702 				} else {
703 					digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
704 	                                &objp->pos, objp->segnum, SoundObjects[i].max_volume,
705                                    &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
706 				}
707 			}
708 
709 			if (oldvolume != SoundObjects[i].volume) 	{
710 				if ( SoundObjects[i].volume < MIN_VOLUME )	 {
711 					// Sound is too far away, so stop it from playing.
712 					if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER))	{
713                                         	SoundSlots[SoundObjects[i].handle].playing = 0;
714 						SoundObjects[i].flags &= ~SOF_PLAYING;		// Mark sound as not playing
715 					}
716 				} else {
717 					if (!(SoundObjects[i].flags & SOF_PLAYING))	{
718 						digi_start_sound_object(i);
719 					} else {
720 					        SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0);
721 					}
722 				}
723 			}
724 
725 			if (oldpan != SoundObjects[i].pan) 	{
726 				if (SoundObjects[i].flags & SOF_PLAYING)
727                                         SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan;
728 			}
729 		}
730 	}
731 }
732 
digi_init_sounds()733 void digi_init_sounds()
734 {
735 	int i;
736 
737 	if (!digi_initialised) return;
738 
739 	digi_reset_digi_sounds();
740 
741 	for (i=0; i<MAX_SOUND_OBJECTS; i++ )	{
742 		if (digi_sounds_initialized) {
743 			if ( SoundObjects[i].flags & SOF_PLAYING )	{
744 			        SoundSlots[SoundObjects[i].handle].playing=0;
745 			}
746 		}
747 		SoundObjects[i].flags = 0;	// Mark as dead, so some other sound can use this sound
748 	}
749 	digi_sounds_initialized = 1;
750 }
751 
752 //added on 980905 by adb from original source to make sfx volume work
digi_set_digi_volume(int dvolume)753 void digi_set_digi_volume( int dvolume )
754 {
755 	dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
756 	if ( dvolume > SOUND_MAX_VOLUME )
757 		digi_volume = SOUND_MAX_VOLUME;
758 	else if ( dvolume < 0 )
759 		digi_volume = 0;
760 	else
761 		digi_volume = dvolume;
762 
763 	if ( !digi_initialised ) return;
764 
765 	digi_sync_sounds();
766 }
767 //end edit by adb
768 
digi_set_volume(int dvolume,int mvolume)769 void digi_set_volume( int dvolume, int mvolume ) { }
770 
digi_is_sound_playing(int soundno)771 int digi_is_sound_playing(int soundno)
772 {
773 	int i;
774 
775 	soundno = digi_xlat_sound(soundno);
776 
777 	for (i = 0; i < MAX_SOUND_SLOTS; i++)
778 		  //changed on 980905 by adb: added SoundSlots[i].playing &&
779 		  if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
780 		  //end changes by adb
781 			return 1;
782 	return 0;
783 }
784 
785 
digi_pause_all()786 void digi_pause_all() { }
digi_resume_all()787 void digi_resume_all() { }
digi_stop_all()788 void digi_stop_all() { }
789 
790  //added on 980905 by adb to make sound channel setting work
digi_set_max_channels(int n)791 void digi_set_max_channels(int n) {
792 	digi_max_channels	= n;
793 
794 	if ( digi_max_channels < 1 )
795 		digi_max_channels = 1;
796 	if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) )
797 		digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS);
798 
799 	if ( !digi_initialised ) return;
800 
801 	digi_reset_digi_sounds();
802 }
803 
digi_get_max_channels()804 int digi_get_max_channels() {
805 	return digi_max_channels;
806 }
807 // end edit by adb
808 
digi_reset_digi_sounds()809 void digi_reset_digi_sounds() {
810  int i;
811 
812  for (i=0; i< MAX_SOUND_SLOTS; i++)
813   SoundSlots[i].playing=0;
814 
815  //added on 980905 by adb to reset sound kill system
816  memset(SampleHandles, 255, sizeof(SampleHandles));
817  next_handle = 0;
818  //end edit by adb
819 }
820 
821 
822 // MIDI stuff follows.
823 //added/killed on 11/25/98 by Matthew Mueller
824 //void digi_set_midi_volume( int mvolume ) { }
825 //void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
826 //void digi_stop_current_song()
827 //{
828 //#ifdef HMIPLAY
829 //        char buf[10];
830 //
831 //        sprintf(buf,"s");
832 //        send_ipc(buf);
833 //#endif
834 //}
835 //end this section kill - MM
836