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