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