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