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