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