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