fix crash on non-existent sounds (i.e. shareware data)
[btb/d2x.git] / arch / sdl / digi.c
1 /* $Id: digi.c,v 1.7 2003-02-24 06:16:17 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         if (Sounds[soundno] == 255) return -1;
292
293         return Sounds[soundno];
294 }
295
296 static int get_free_slot()
297 {
298  int i;
299  for (i=0; i<MAX_SOUND_SLOTS; i++)
300  {
301   if (!SoundSlots[i].playing) return i;
302  }
303  return -1;
304 }
305
306 int digi_start_sound(int soundnum, fix volume, fix pan, int looping, int loop_start, int loop_end, int soundobj)
307 {
308  int ntries;
309  int slot;
310
311  if (!digi_initialised) return -1;
312
313  if (soundnum < 0) return -1;
314
315  //added on 980905 by adb from original source to add sound kill system
316  // play at most digi_max_channel samples, if possible kill sample with low volume
317  ntries = 0;
318
319 TryNextChannel:
320  if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing)  )
321  {
322   if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries<digi_max_channels) )
323   {
324    //mprintf(( 0, "Not stopping loud sound %d.\n", next_handle ));
325    next_handle++;
326    if ( next_handle >= digi_max_channels )
327     next_handle = 0;
328    ntries++;
329    goto TryNextChannel;
330   }
331   //mprintf(( 0, "[SS:%d]", next_handle ));
332   SoundSlots[SampleHandles[next_handle]].playing = 0;
333   SampleHandles[next_handle] = -1;
334  }
335  //end edit by adb
336
337  slot = get_free_slot();
338  if (slot<0) return -1;
339
340  SoundSlots[slot].soundno = soundnum;
341  SoundSlots[slot].samples = GameSounds[soundnum].data;
342  SoundSlots[slot].length = GameSounds[soundnum].length;
343  SoundSlots[slot].volume = fixmul(digi_volume, volume);
344  SoundSlots[slot].pan = pan;
345  SoundSlots[slot].position = 0;
346  SoundSlots[slot].looped = looping;
347  SoundSlots[slot].playing = 1;
348
349  //added on 980905 by adb to add sound kill system from original sos digi.c
350  reset_sounds_on_channel(slot);
351  SampleHandles[next_handle] = slot;
352  next_handle++;
353  if ( next_handle >= digi_max_channels )
354   next_handle = 0;
355  //end edit by adb
356
357  return slot;
358 }
359
360  //added on 980905 by adb to add sound kill system from original sos digi.c
361 void reset_sounds_on_channel( int channel )
362 {
363  int i;
364
365  for (i=0; i<digi_max_channels; i++)
366   if (SampleHandles[i] == channel)
367    SampleHandles[i] = -1;
368 }
369 //end edit by adb
370
371 int digi_start_sound_object(int obj)
372 {
373  int slot;
374
375  if (!digi_initialised) return -1;
376  slot = get_free_slot();
377
378  if (slot<0) return -1;
379
380
381  SoundSlots[slot].soundno = SoundObjects[obj].soundnum;
382  SoundSlots[slot].samples = GameSounds[SoundObjects[obj].soundnum].data;
383  SoundSlots[slot].length = GameSounds[SoundObjects[obj].soundnum].length;
384  SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume);
385  SoundSlots[slot].pan = SoundObjects[obj].pan;
386  SoundSlots[slot].position = 0;
387  SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER);
388  SoundSlots[slot].playing = 1;
389
390  SoundObjects[obj].signature = next_signature++;
391  SoundObjects[obj].handle = slot;
392
393  SoundObjects[obj].flags |= SOF_PLAYING;
394  //added on 980905 by adb to add sound kill system from original sos digi.c
395  reset_sounds_on_channel(slot);
396  //end edit by adb
397  
398  return 0;
399 }
400
401
402 // Play the given sound number.
403 // Volume is max at F1_0.
404 void digi_play_sample( int soundno, fix max_volume )
405 {
406 #ifdef NEWDEMO
407         if ( Newdemo_state == ND_STATE_RECORDING )
408                 newdemo_record_sound( soundno );
409 #endif
410         soundno = digi_xlat_sound(soundno);
411
412         if (!digi_initialised) return;
413
414         if (soundno < 0 ) return;
415
416         digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
417 }
418
419 // Play the given sound number. If the sound is already playing,
420 // restart it.
421 void digi_play_sample_once( int soundno, fix max_volume )
422 {
423         int i;
424
425 #ifdef NEWDEMO
426         if ( Newdemo_state == ND_STATE_RECORDING )
427                 newdemo_record_sound( soundno );
428 #endif
429         soundno = digi_xlat_sound(soundno);
430
431         if (!digi_initialised) return;
432
433         if (soundno < 0 ) return;
434
435         for (i=0; i < MAX_SOUND_SLOTS; i++)
436           if (SoundSlots[i].soundno == soundno)
437             SoundSlots[i].playing = 0;
438         digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
439
440 }
441
442 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) // Volume from 0-0x7fff
443 {
444         no_dups = 1;
445
446 #ifdef NEWDEMO
447         if ( Newdemo_state == ND_STATE_RECORDING )              {
448                 if ( no_dups )
449                         newdemo_record_sound_3d_once( soundno, angle, volume );
450                 else
451                         newdemo_record_sound_3d( soundno, angle, volume );
452         }
453 #endif
454         soundno = digi_xlat_sound(soundno);
455
456         if (!digi_initialised) return;
457         if (soundno < 0 ) return;
458
459         if (volume < MIN_VOLUME ) return;
460         digi_start_sound(soundno, volume, angle, 0, 0, 0, 0);
461 }
462
463 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 )
464 {         
465         vms_vector      vector_to_sound;
466         fix angle_from_ear, cosang,sinang;
467         fix distance;
468         fix path_distance;
469
470         *volume = 0;
471         *pan = 0;
472
473         max_distance = (max_distance*5)/4;              // Make all sounds travel 1.25 times as far.
474
475         //      Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
476         distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
477                 
478         if (distance < max_distance )   {
479                 int num_search_segs = f2i(max_distance/20);
480                 if ( num_search_segs < 1 ) num_search_segs = 1;
481
482                 path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
483                 if ( path_distance > -1 )       {
484                         *volume = max_volume - fixdiv(path_distance,max_distance);
485                         //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
486                         if (*volume > 0 )       {
487                                 angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
488                                 fix_sincos(angle_from_ear,&sinang,&cosang);
489                                 //mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
490                                 if (Config_channels_reversed) cosang *= -1;
491                                 *pan = (cosang + F1_0)/2;
492                         } else {
493                                 *volume = 0;
494                         }
495                 }
496         }                                                                                                                                                                         
497 }
498
499 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix  max_distance )
500 {
501         int i,volume,pan;
502         object * objp;
503         int soundnum;
504
505         soundnum = digi_xlat_sound(org_soundnum);
506
507         if ( max_volume < 0 ) return -1;
508 //      if ( max_volume > F1_0 ) max_volume = F1_0;
509
510         if (!digi_initialised) return -1;
511         if (soundnum < 0 ) return -1;
512         if (GameSounds[soundnum].data==NULL) {
513                 Int3();
514                 return -1;
515         }
516         if ((objnum<0)||(objnum>Highest_object_index))
517                 return -1;
518
519         if ( !forever ) {
520                 // Hack to keep sounds from building up...
521                 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
522                 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
523                 return -1;
524         }
525
526         for (i=0; i<MAX_SOUND_OBJECTS; i++ )
527                 if (SoundObjects[i].flags==0)
528                    break;
529
530         if (i==MAX_SOUND_OBJECTS) {
531                 mprintf((1, "Too many sound objects!\n" ));
532                 return -1;
533         }
534
535         SoundObjects[i].signature=next_signature++;
536         SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
537         if ( forever )
538                 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
539         SoundObjects[i].lo_objnum = objnum;
540         SoundObjects[i].lo_objsignature = Objects[objnum].signature;
541         SoundObjects[i].max_volume = max_volume;
542         SoundObjects[i].max_distance = max_distance;
543         SoundObjects[i].volume = 0;
544         SoundObjects[i].pan = 0;
545         SoundObjects[i].soundnum = soundnum;
546
547         objp = &Objects[SoundObjects[i].lo_objnum];
548         digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
549                        &objp->pos, objp->segnum, SoundObjects[i].max_volume,
550                        &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
551
552         if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
553                digi_start_sound_object(i);
554
555         return SoundObjects[i].signature;
556 }
557
558 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
559 { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); }
560
561 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
562 {
563         int i, volume, pan;
564         int soundnum;
565
566         soundnum = digi_xlat_sound(org_soundnum);
567
568         if ( max_volume < 0 ) return -1;
569 //      if ( max_volume > F1_0 ) max_volume = F1_0;
570
571         if (!digi_initialised) return -1;
572         if (soundnum < 0 ) return -1;
573         if (GameSounds[soundnum].data==NULL) {
574                 Int3();
575                 return -1;
576         }
577
578         if ((segnum<0)||(segnum>Highest_segment_index))
579                 return -1;
580
581         if ( !forever ) {
582                 // Hack to keep sounds from building up...
583                 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
584                 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
585                 return -1;
586         }
587
588         for (i=0; i<MAX_SOUND_OBJECTS; i++ )
589                 if (SoundObjects[i].flags==0)
590                         break;
591         
592         if (i==MAX_SOUND_OBJECTS) {
593                 mprintf((1, "Too many sound objects!\n" ));
594                 return -1;
595         }
596
597
598         SoundObjects[i].signature=next_signature++;
599         SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
600         if ( forever )
601                 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
602         SoundObjects[i].lp_segnum = segnum;
603         SoundObjects[i].lp_sidenum = sidenum;
604         SoundObjects[i].lp_position = *pos;
605         SoundObjects[i].soundnum = soundnum;
606         SoundObjects[i].max_volume = max_volume;
607         SoundObjects[i].max_distance = max_distance;
608         SoundObjects[i].volume = 0;
609         SoundObjects[i].pan = 0;
610         digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
611                                            &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
612                                            SoundObjects[i].max_volume,
613                        &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
614         
615         if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
616                 digi_start_sound_object(i);
617
618         return SoundObjects[i].signature;
619 }
620
621 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
622 {
623         return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
624 }
625
626 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
627 {
628         int i,killed;
629
630         soundnum = digi_xlat_sound(soundnum);
631
632         if (!digi_initialised) return;
633
634         killed = 0;
635
636         for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
637                 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) )  {
638                         if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
639                                 if ( SoundObjects[i].flags & SOF_PLAYING )      {
640                                         SoundSlots[SoundObjects[i].handle].playing = 0;
641                                 }
642                                 SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
643                                 killed++;
644                         }
645                 }
646         }
647         // If this assert happens, it means that there were 2 sounds
648         // that got deleted. Weird, get John.
649         if ( killed > 1 )       {
650                 mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
651         }
652 }
653
654 void digi_kill_sound_linked_to_object( int objnum )
655 {
656         int i,killed;
657
658         if (!digi_initialised) return;
659
660         killed = 0;
661
662         for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
663                 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) ) {
664                         if (SoundObjects[i].lo_objnum == objnum)   {
665                                 if ( SoundObjects[i].flags & SOF_PLAYING )      {
666                                      SoundSlots[SoundObjects[i].handle].playing = 0;
667                                 }
668                                 SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
669                                 killed++;
670                         }
671                 }
672         }
673         // If this assert happens, it means that there were 2 sounds
674         // that got deleted. Weird, get John.
675         if ( killed > 1 )       {
676                 mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
677         }
678 }
679
680 void digi_sync_sounds()
681 {
682         int i;
683         int oldvolume, oldpan;
684
685         if (!digi_initialised) return;
686
687         for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
688                 if ( SoundObjects[i].flags & SOF_USED ) {
689                         oldvolume = SoundObjects[i].volume;
690                         oldpan = SoundObjects[i].pan;
691
692                         if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) )      {
693                                 // Check if its done.
694                                 if (SoundObjects[i].flags & SOF_PLAYING) {
695                                         if (!SoundSlots[SoundObjects[i].handle].playing) {
696                                                 SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
697                                                 continue;               // Go on to next sound...
698                                         }
699                                 }
700                         }                       
701                 
702                         if ( SoundObjects[i].flags & SOF_LINK_TO_POS )  {
703                                 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
704                                                                 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
705                                                                 SoundObjects[i].max_volume,
706                                 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
707
708                         } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ )   {
709                                 object * objp;
710         
711                                 objp = &Objects[SoundObjects[i].lo_objnum];
712                 
713                                 if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature))  {
714                                         // The object that this is linked to is dead, so just end this sound if it is looping.
715                                         if ( (SoundObjects[i].flags & SOF_PLAYING)  && (SoundObjects[i].flags & SOF_PLAY_FOREVER))      {
716                                              SoundSlots[SoundObjects[i].handle].playing = 0;
717                                         }
718                                         SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
719                                         continue;               // Go on to next sound...
720                                 } else {
721                                         digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
722                                         &objp->pos, objp->segnum, SoundObjects[i].max_volume,
723                                    &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
724                                 }
725                         }
726                          
727                         if (oldvolume != SoundObjects[i].volume)        {
728                                 if ( SoundObjects[i].volume < MIN_VOLUME )       {
729                                         // Sound is too far away, so stop it from playing.
730                                         if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER))  {
731                                                 SoundSlots[SoundObjects[i].handle].playing = 0;
732                                                 SoundObjects[i].flags &= ~SOF_PLAYING;          // Mark sound as not playing
733                                         }
734                                 } else {
735                                         if (!(SoundObjects[i].flags & SOF_PLAYING))     {
736                                                 digi_start_sound_object(i);
737                                         } else {
738                                                 SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0);
739                                         }
740                                 }
741                         }
742                                 
743                         if (oldpan != SoundObjects[i].pan)      {
744                                 if (SoundObjects[i].flags & SOF_PLAYING)
745                                         SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan;
746                         }
747                 }
748         }
749 }
750
751 void digi_init_sounds()
752 {
753         int i;
754
755         if (!digi_initialised) return;
756
757         digi_reset_digi_sounds();
758
759         for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
760                 if (digi_sounds_initialized) {
761                         if ( SoundObjects[i].flags & SOF_PLAYING )      {
762                                 SoundSlots[SoundObjects[i].handle].playing=0;
763                         }
764                 }
765                 SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
766         }
767         digi_sounds_initialized = 1;
768 }
769
770 //added on 980905 by adb from original source to make sfx volume work
771 void digi_set_digi_volume( int dvolume )
772 {
773         dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
774         if ( dvolume > SOUND_MAX_VOLUME )
775                 digi_volume = SOUND_MAX_VOLUME;
776         else if ( dvolume < 0 )
777                 digi_volume = 0;
778         else
779                 digi_volume = dvolume;
780
781         if ( !digi_initialised ) return;
782
783         digi_sync_sounds();
784 }
785 //end edit by adb
786
787 void digi_set_volume( int dvolume, int mvolume )
788 {
789         digi_set_digi_volume(dvolume);
790         digi_set_midi_volume(mvolume);
791 //      mprintf(( 1, "Volume: 0x%x and 0x%x\n", digi_volume, midi_volume ));
792 }
793
794 int digi_is_sound_playing(int soundno)
795 {
796         int i;
797
798         soundno = digi_xlat_sound(soundno);
799
800         for (i = 0; i < MAX_SOUND_SLOTS; i++)
801                   //changed on 980905 by adb: added SoundSlots[i].playing &&
802                   if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
803                   //end changes by adb
804                         return 1;
805         return 0;
806 }
807
808
809 void digi_pause_all() { }
810 void digi_resume_all() { }
811 void digi_stop_all() {
812        int i;
813        // ... Ano. The lack of this was causing ambient sounds to crash.
814        // fixed, added digi_stop_all 07/19/01 - bluecow
815        
816        for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
817                if ( SoundObjects[i].flags & SOF_USED ) {
818                        SoundSlots[SoundObjects[i].handle].playing = 0;
819                        SoundObjects[i].flags = 0;
820                }
821        }
822 }
823
824  //added on 980905 by adb to make sound channel setting work
825 void digi_set_max_channels(int n) { 
826         digi_max_channels       = n;
827
828         if ( digi_max_channels < 1 ) 
829                 digi_max_channels = 1;
830         if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) ) 
831                 digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS);
832
833         if ( !digi_initialised ) return;
834
835         digi_reset_digi_sounds();
836 }
837
838 int digi_get_max_channels() { 
839         return digi_max_channels; 
840 }
841 // end edit by adb
842
843 void digi_stop_sound(int channel)
844 {
845         //FIXME: Is this correct?  I dunno, it works.
846         SoundSlots[channel].playing=0;
847 }
848
849 void digi_reset_digi_sounds() {
850  int i;
851
852  for (i=0; i< MAX_SOUND_SLOTS; i++)
853   SoundSlots[i].playing=0;
854  
855  //added on 980905 by adb to reset sound kill system
856  memset(SampleHandles, 255, sizeof(SampleHandles));
857  next_handle = 0;
858  //end edit by adb
859 }
860
861
862 // MIDI stuff follows.
863 //added/killed on 11/25/98 by Matthew Mueller
864 //void digi_set_midi_volume( int mvolume ) { }
865 //void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
866 //void digi_stop_current_song()
867 //{
868 //#ifdef HMIPLAY
869 //        char buf[10];
870 //    
871 //        sprintf(buf,"s");
872 //        send_ipc(buf);
873 //#endif
874 //}
875 //end this section kill - MM