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