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