]> icculus.org git repositories - btb/d2x.git/blob - arch/sdl/digi.c
PocketPC fixes
[btb/d2x.git] / arch / sdl / digi.c
1 /* $Id: digi.c,v 1.12 2003-11-27 09:10:52 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 #ifdef _MSC_VER
125         ubyte   pad;            // needed for alignment
126 #endif
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 #ifdef _MSC_VER
134         short   pad2;           // needed for alignment
135 #endif
136         int     loop_start;     // The start point of the loop. -1 means no loop
137         int     loop_end;       // The end point of the loop
138         union { 
139                 struct {
140                         short           segnum;                         // Used if SOF_LINK_TO_POS field is used
141                         short           sidenum;
142                         vms_vector      position;
143                 }pos;
144                 struct {
145                         short            objnum;                         // Used if SOF_LINK_TO_OBJ field is used
146                         short            objsignature;
147                 }obj;
148         }link;
149 } sound_object;
150 #define lp_segnum link.pos.segnum
151 #define lp_sidenum link.pos.sidenum
152 #define lp_position link.pos.position
153
154 #define lo_objnum link.obj.objnum
155 #define lo_objsignature link.obj.objsignature
156
157 #define MAX_SOUND_OBJECTS 16
158 sound_object SoundObjects[MAX_SOUND_OBJECTS];
159 short next_signature=0;
160
161 //added/changed on 980905 by adb to make sfx volume work, on 990221 by adb changed F1_0 to F1_0 / 2
162 #define SOUND_MAX_VOLUME (F1_0 / 2)
163
164 int digi_volume = SOUND_MAX_VOLUME;
165 //end edit by adb
166
167 int digi_lomem = 0;
168
169 static int digi_initialised = 0;
170
171 struct sound_slot {
172  int soundno;
173  int playing;   // Is there a sample playing on this channel?
174  int looped;    // Play this sample looped?
175  fix pan;       // 0 = far left, 1 = far right
176  fix volume;    // 0 = nothing, 1 = fully on
177  //changed on 980905 by adb from char * to unsigned char * 
178  unsigned char *samples;
179  //end changes by adb
180  unsigned int length; // Length of the sample
181  unsigned int position; // Position we are at at the moment.
182 } SoundSlots[MAX_SOUND_SLOTS];
183
184 static SDL_AudioSpec WaveSpec;
185 static int digi_sounds_initialized = 0;
186
187 //added on 980905 by adb to add rotating/volume based sound kill system
188 static int digi_max_channels = 16;
189 static int next_handle = 0;
190 int SampleHandles[32];
191 void reset_sounds_on_channel(int channel);
192 //end edit by adb
193
194 void digi_reset_digi_sounds(void);
195
196 /* Audio mixing callback */
197 //changed on 980905 by adb to cleanup, add pan support and optimize mixer
198 static void audio_mixcallback(void *userdata, Uint8 *stream, int len)
199 {
200  Uint8 *streamend = stream + len;
201  struct sound_slot *sl;
202   
203  for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++)
204  {
205   if (sl->playing)
206   {
207    Uint8 *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length;
208    Uint8 *sp = stream, s;
209    signed char v;
210    fix vl, vr;
211    int x;
212
213    if ((x = sl->pan) & 0x8000)
214    {
215     vl = 0x20000 - x * 2;
216     vr = 0x10000;
217    }
218    else
219    {
220     vl = 0x10000;
221     vr = x * 2;
222    }
223    vl = fixmul(vl, (x = sl->volume));
224    vr = fixmul(vr, x);
225    while (sp < streamend) 
226    {
227     if (sldata == slend)
228     {
229      if (!sl->looped)
230      {
231       sl->playing = 0;
232       break;
233      }
234      sldata = sl->samples;
235     }
236     v = *(sldata++) - 0x80;
237     s = *sp;
238     *(sp++) = mix8[ s + fixmul(v, vl) + 0x80 ];
239     s = *sp;
240     *(sp++) = mix8[ s + fixmul(v, vr) + 0x80 ];
241    }
242    sl->position = sldata - sl->samples;
243   }
244  }
245 }
246 //end changes by adb
247
248 /* Initialise audio devices. */
249 int digi_init()
250 {
251  if (SDL_InitSubSystem(SDL_INIT_AUDIO)<0){
252     Error("SDL audio initialisation failed: %s.",SDL_GetError());
253  }
254  //added on 980905 by adb to init sound kill system
255  memset(SampleHandles, 255, sizeof(SampleHandles));
256  //end edit by adb
257
258  WaveSpec.freq = digi_sample_rate;
259 //added/changed by Sam Lantinga on 12/01/98 for new SDL version
260  WaveSpec.format = AUDIO_U8;
261  WaveSpec.channels = 2;
262 //end this section addition/change - SL
263  WaveSpec.samples = SOUND_BUFFER_SIZE;
264  WaveSpec.callback = audio_mixcallback;
265
266  if ( SDL_OpenAudio(&WaveSpec, NULL) < 0 ) {
267 //edited on 10/05/98 by Matt Mueller - should keep running, just with no sound.
268          Warning("\nError: Couldn't open audio: %s\n", SDL_GetError());
269 //killed  exit(2);
270          return 1;
271 //end edit -MM
272  }
273  SDL_PauseAudio(0);
274
275  atexit(digi_close);
276  digi_initialised = 1;
277  return 0;
278 }
279
280 /* Toggle audio */
281 void digi_reset() { }
282
283 /* Shut down audio */
284 void digi_close()
285 {
286  if (!digi_initialised) return;
287  digi_initialised = 0;
288  SDL_CloseAudio();
289 }
290
291 /* Find the sound which actually equates to a sound number */
292 int digi_xlat_sound(int soundno)
293 {
294         if ( soundno < 0 ) return -1;
295
296         if ( digi_lomem )       {
297                 soundno = AltSounds[soundno];
298                 if ( soundno == 255 ) return -1;
299         }
300         if (Sounds[soundno] == 255) return -1;
301
302         return Sounds[soundno];
303 }
304
305 static int get_free_slot()
306 {
307  int i;
308  for (i=0; i<MAX_SOUND_SLOTS; i++)
309  {
310   if (!SoundSlots[i].playing) return i;
311  }
312  return -1;
313 }
314
315 int digi_start_sound(int soundnum, fix volume, fix pan, int looping, int loop_start, int loop_end, int soundobj)
316 {
317  int ntries;
318  int slot;
319
320  if (!digi_initialised) return -1;
321
322  if (soundnum < 0) 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 = looping;
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 #if 0
390  // only use up to half the sound channels for "permanant" sounts
391  if ((SoundObjects[i].flags & SOF_PERMANANT) && (N_active_sound_objects >= max(1,digi_get_max_channels()/4)) )
392          return -1;
393 #endif
394
395  SoundSlots[slot].soundno = SoundObjects[obj].soundnum;
396  SoundSlots[slot].samples = GameSounds[SoundObjects[obj].soundnum].data;
397  SoundSlots[slot].length = GameSounds[SoundObjects[obj].soundnum].length;
398  SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume);
399  SoundSlots[slot].pan = SoundObjects[obj].pan;
400  SoundSlots[slot].position = 0;
401  SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER);
402  SoundSlots[slot].playing = 1;
403
404  SoundObjects[obj].signature = next_signature++;
405  SoundObjects[obj].handle = slot;
406
407  SoundObjects[obj].flags |= SOF_PLAYING;
408  //added on 980905 by adb to add sound kill system from original sos digi.c
409  reset_sounds_on_channel(slot);
410  //end edit by adb
411  
412  return 0;
413 }
414
415
416 // Play the given sound number.
417 // Volume is max at F1_0.
418 void digi_play_sample( int soundno, fix max_volume )
419 {
420 #ifdef NEWDEMO
421         if ( Newdemo_state == ND_STATE_RECORDING )
422                 newdemo_record_sound( soundno );
423 #endif
424         soundno = digi_xlat_sound(soundno);
425
426         if (!digi_initialised) return;
427
428         if (soundno < 0 ) return;
429
430         digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
431 }
432
433 // Play the given sound number. If the sound is already playing,
434 // restart it.
435 void digi_play_sample_once( int soundno, fix max_volume )
436 {
437         int i;
438
439 #ifdef NEWDEMO
440         if ( Newdemo_state == ND_STATE_RECORDING )
441                 newdemo_record_sound( soundno );
442 #endif
443         soundno = digi_xlat_sound(soundno);
444
445         if (!digi_initialised) return;
446
447         if (soundno < 0 ) return;
448
449         for (i=0; i < MAX_SOUND_SLOTS; i++)
450           if (SoundSlots[i].soundno == soundno)
451             SoundSlots[i].playing = 0;
452         digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
453
454 }
455
456 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) // Volume from 0-0x7fff
457 {
458         no_dups = 1;
459
460 #ifdef NEWDEMO
461         if ( Newdemo_state == ND_STATE_RECORDING )              {
462                 if ( no_dups )
463                         newdemo_record_sound_3d_once( soundno, angle, volume );
464                 else
465                         newdemo_record_sound_3d( soundno, angle, volume );
466         }
467 #endif
468         soundno = digi_xlat_sound(soundno);
469
470         if (!digi_initialised) return;
471         if (soundno < 0 ) return;
472
473         if (volume < MIN_VOLUME ) return;
474         digi_start_sound(soundno, volume, angle, 0, 0, 0, 0);
475 }
476
477 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 )
478 {         
479         vms_vector      vector_to_sound;
480         fix angle_from_ear, cosang,sinang;
481         fix distance;
482         fix path_distance;
483
484         *volume = 0;
485         *pan = 0;
486
487         max_distance = (max_distance*5)/4;              // Make all sounds travel 1.25 times as far.
488
489         //      Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
490         distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
491                 
492         if (distance < max_distance )   {
493                 int num_search_segs = f2i(max_distance/20);
494                 if ( num_search_segs < 1 ) num_search_segs = 1;
495
496                 path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
497                 if ( path_distance > -1 )       {
498                         *volume = max_volume - fixdiv(path_distance,max_distance);
499                         //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
500                         if (*volume > 0 )       {
501                                 angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
502                                 fix_sincos(angle_from_ear,&sinang,&cosang);
503                                 //mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
504                                 if (Config_channels_reversed) cosang *= -1;
505                                 *pan = (cosang + F1_0)/2;
506                         } else {
507                                 *volume = 0;
508                         }
509                 }
510         }                                                                                                                                                                         
511 }
512
513 //hack to not start object when loading level
514 int Dont_start_sound_objects = 0;
515
516 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 )
517 {
518         int i,volume,pan;
519         object * objp;
520         int soundnum;
521
522         soundnum = digi_xlat_sound(org_soundnum);
523
524         if ( max_volume < 0 ) return -1;
525 //      if ( max_volume > F1_0 ) max_volume = F1_0;
526
527         if (!digi_initialised) return -1;
528         if (soundnum < 0 ) return -1;
529         if (GameSounds[soundnum].data==NULL) {
530                 Int3();
531                 return -1;
532         }
533         if ((objnum<0)||(objnum>Highest_object_index))
534                 return -1;
535
536         if ( !forever ) {
537                 // Hack to keep sounds from building up...
538                 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
539                 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
540                 return -1;
541         }
542
543 #ifdef NEWDEMO
544         if ( Newdemo_state == ND_STATE_RECORDING )              {
545                 newdemo_record_link_sound_to_object3( org_soundnum, objnum, max_volume, max_distance, loop_start, loop_end );
546         }
547 #endif
548
549         for (i=0; i<MAX_SOUND_OBJECTS; i++ )
550                 if (SoundObjects[i].flags==0)
551                    break;
552
553         if (i==MAX_SOUND_OBJECTS) {
554                 mprintf((1, "Too many sound objects!\n" ));
555                 return -1;
556         }
557
558         SoundObjects[i].signature=next_signature++;
559         SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
560         if ( forever )
561                 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
562         SoundObjects[i].lo_objnum = objnum;
563         SoundObjects[i].lo_objsignature = Objects[objnum].signature;
564         SoundObjects[i].max_volume = max_volume;
565         SoundObjects[i].max_distance = max_distance;
566         SoundObjects[i].volume = 0;
567         SoundObjects[i].pan = 0;
568         SoundObjects[i].soundnum = soundnum;
569         SoundObjects[i].loop_start = loop_start;
570         SoundObjects[i].loop_end = loop_end;
571
572         if (Dont_start_sound_objects) {                 //started at level start
573
574                 SoundObjects[i].flags |= SOF_PERMANANT;
575                 SoundObjects[i].handle =  -1;
576         }
577         else {
578                 objp = &Objects[SoundObjects[i].lo_objnum];
579                 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
580                        &objp->pos, objp->segnum, SoundObjects[i].max_volume,
581                        &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
582
583                 //if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
584                digi_start_sound_object(i);
585
586                 // If it's a one-shot sound effect, and it can't start right away, then
587                 // just cancel it and be done with it.
588                 if ( (SoundObjects[i].handle < 0) && (!(SoundObjects[i].flags & SOF_PLAY_FOREVER)) )    {
589                         SoundObjects[i].flags = 0;
590                         return -1;
591                 }
592         }
593
594         return SoundObjects[i].signature;
595 }
596
597
598 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix  max_distance )
599 {
600         return digi_link_sound_to_object3( org_soundnum, objnum, forever, max_volume, max_distance, -1, -1 );
601 }
602
603
604 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
605 { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); }
606
607 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
608 {
609         int i, volume, pan;
610         int soundnum;
611
612         soundnum = digi_xlat_sound(org_soundnum);
613
614         if ( max_volume < 0 ) return -1;
615 //      if ( max_volume > F1_0 ) max_volume = F1_0;
616
617         if (!digi_initialised) return -1;
618         if (soundnum < 0 ) return -1;
619         if (GameSounds[soundnum].data==NULL) {
620                 Int3();
621                 return -1;
622         }
623
624         if ((segnum<0)||(segnum>Highest_segment_index))
625                 return -1;
626
627         if ( !forever ) {
628                 // Hack to keep sounds from building up...
629                 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
630                 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
631                 return -1;
632         }
633
634         for (i=0; i<MAX_SOUND_OBJECTS; i++ )
635                 if (SoundObjects[i].flags==0)
636                         break;
637         
638         if (i==MAX_SOUND_OBJECTS) {
639                 mprintf((1, "Too many sound objects!\n" ));
640                 return -1;
641         }
642
643
644         SoundObjects[i].signature=next_signature++;
645         SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
646         if ( forever )
647                 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
648         SoundObjects[i].lp_segnum = segnum;
649         SoundObjects[i].lp_sidenum = sidenum;
650         SoundObjects[i].lp_position = *pos;
651         SoundObjects[i].soundnum = soundnum;
652         SoundObjects[i].max_volume = max_volume;
653         SoundObjects[i].max_distance = max_distance;
654         SoundObjects[i].volume = 0;
655         SoundObjects[i].pan = 0;
656         SoundObjects[i].loop_start = SoundObjects[i].loop_end = -1;
657
658         if (Dont_start_sound_objects) {         //started at level start
659
660                 SoundObjects[i].flags |= SOF_PERMANANT;
661
662                 SoundObjects[i].handle =  -1;
663         }
664         else {
665
666                 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
667                                            &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
668                                            SoundObjects[i].max_volume,
669                        &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
670         
671         if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
672                 digi_start_sound_object(i);
673
674                 // If it's a one-shot sound effect, and it can't start right away, then
675                 // just cancel it and be done with it.
676                 if ( (SoundObjects[i].handle < 0) && (!(SoundObjects[i].flags & SOF_PLAY_FOREVER)) )    {
677                         SoundObjects[i].flags = 0;
678                         return -1;
679                 }
680         }
681
682         return SoundObjects[i].signature;
683 }
684
685 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
686 {
687         return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
688 }
689
690 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
691 {
692         int i,killed;
693
694         soundnum = digi_xlat_sound(soundnum);
695
696         if (!digi_initialised) return;
697
698         killed = 0;
699
700         for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
701                 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) )  {
702                         if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
703                                 if ( SoundObjects[i].flags & SOF_PLAYING )      {
704                                         SoundSlots[SoundObjects[i].handle].playing = 0;
705                                 }
706                                 SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
707                                 killed++;
708                         }
709                 }
710         }
711         // If this assert happens, it means that there were 2 sounds
712         // that got deleted. Weird, get John.
713         if ( killed > 1 )       {
714                 mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
715         }
716 }
717
718 void digi_kill_sound_linked_to_object( int objnum )
719 {
720         int i,killed;
721
722         if (!digi_initialised) return;
723
724         killed = 0;
725
726         for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
727                 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) ) {
728                         if (SoundObjects[i].lo_objnum == objnum)   {
729                                 if ( SoundObjects[i].flags & SOF_PLAYING )      {
730                                      SoundSlots[SoundObjects[i].handle].playing = 0;
731                                 }
732                                 SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
733                                 killed++;
734                         }
735                 }
736         }
737         // If this assert happens, it means that there were 2 sounds
738         // that got deleted. Weird, get John.
739         if ( killed > 1 )       {
740                 mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
741         }
742 }
743
744 void digi_sync_sounds()
745 {
746         int i;
747         int oldvolume, oldpan;
748
749         if (!digi_initialised) return;
750
751         for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
752                 if ( SoundObjects[i].flags & SOF_USED ) {
753                         oldvolume = SoundObjects[i].volume;
754                         oldpan = SoundObjects[i].pan;
755
756                         if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) )      {
757                                 // Check if its done.
758                                 if (SoundObjects[i].flags & SOF_PLAYING) {
759                                         if (!SoundSlots[SoundObjects[i].handle].playing) {
760                                                 SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
761                                                 continue;               // Go on to next sound...
762                                         }
763                                 }
764                         }                       
765                 
766                         if ( SoundObjects[i].flags & SOF_LINK_TO_POS )  {
767                                 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
768                                                                 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
769                                                                 SoundObjects[i].max_volume,
770                                 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
771
772                         } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ )   {
773                                 object * objp;
774         
775                                 objp = &Objects[SoundObjects[i].lo_objnum];
776                 
777                                 if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature))  {
778                                         // The object that this is linked to is dead, so just end this sound if it is looping.
779                                         if ( (SoundObjects[i].flags & SOF_PLAYING)  && (SoundObjects[i].flags & SOF_PLAY_FOREVER))      {
780                                              SoundSlots[SoundObjects[i].handle].playing = 0;
781                                         }
782                                         SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
783                                         continue;               // Go on to next sound...
784                                 } else {
785                                         digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
786                                         &objp->pos, objp->segnum, SoundObjects[i].max_volume,
787                                    &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
788                                 }
789                         }
790                          
791                         if (oldvolume != SoundObjects[i].volume)        {
792                                 if ( SoundObjects[i].volume < MIN_VOLUME )       {
793                                         // Sound is too far away, so stop it from playing.
794                                         if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER))  {
795                                                 SoundSlots[SoundObjects[i].handle].playing = 0;
796                                                 SoundObjects[i].flags &= ~SOF_PLAYING;          // Mark sound as not playing
797                                         }
798                                 } else {
799                                         if (!(SoundObjects[i].flags & SOF_PLAYING))     {
800                                                 digi_start_sound_object(i);
801                                         } else {
802                                                 SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0);
803                                         }
804                                 }
805                         }
806                                 
807                         if (oldpan != SoundObjects[i].pan)      {
808                                 if (SoundObjects[i].flags & SOF_PLAYING)
809                                         SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan;
810                         }
811                 }
812         }
813 }
814
815 void digi_init_sounds()
816 {
817         int i;
818
819         if (!digi_initialised) return;
820
821         digi_reset_digi_sounds();
822
823         for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
824                 if (digi_sounds_initialized) {
825                         if ( SoundObjects[i].flags & SOF_PLAYING )      {
826                                 SoundSlots[SoundObjects[i].handle].playing=0;
827                         }
828                 }
829                 SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
830         }
831         digi_sounds_initialized = 1;
832 }
833
834 //added on 980905 by adb from original source to make sfx volume work
835 void digi_set_digi_volume( int dvolume )
836 {
837         dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
838         if ( dvolume > SOUND_MAX_VOLUME )
839                 digi_volume = SOUND_MAX_VOLUME;
840         else if ( dvolume < 0 )
841                 digi_volume = 0;
842         else
843                 digi_volume = dvolume;
844
845         if ( !digi_initialised ) return;
846
847         digi_sync_sounds();
848 }
849 //end edit by adb
850
851 void digi_set_volume( int dvolume, int mvolume )
852 {
853         digi_set_digi_volume(dvolume);
854         digi_set_midi_volume(mvolume);
855 //      mprintf(( 1, "Volume: 0x%x and 0x%x\n", digi_volume, midi_volume ));
856 }
857
858 int digi_is_sound_playing(int soundno)
859 {
860         int i;
861
862         soundno = digi_xlat_sound(soundno);
863
864         for (i = 0; i < MAX_SOUND_SLOTS; i++)
865                   //changed on 980905 by adb: added SoundSlots[i].playing &&
866                   if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
867                   //end changes by adb
868                         return 1;
869         return 0;
870 }
871
872
873 void digi_pause_all() { }
874 void digi_resume_all() { }
875 void digi_stop_all() {
876        int i;
877        // ... Ano. The lack of this was causing ambient sounds to crash.
878        // fixed, added digi_stop_all 07/19/01 - bluecow
879        
880        for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
881                if ( SoundObjects[i].flags & SOF_USED ) {
882                        SoundSlots[SoundObjects[i].handle].playing = 0;
883                        SoundObjects[i].flags = 0;
884                }
885        }
886 }
887
888  //added on 980905 by adb to make sound channel setting work
889 void digi_set_max_channels(int n) { 
890         digi_max_channels       = n;
891
892         if ( digi_max_channels < 1 ) 
893                 digi_max_channels = 1;
894         if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) ) 
895                 digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS);
896
897         if ( !digi_initialised ) return;
898
899         digi_reset_digi_sounds();
900 }
901
902 int digi_get_max_channels() { 
903         return digi_max_channels; 
904 }
905 // end edit by adb
906
907 void digi_stop_sound(int channel)
908 {
909         //FIXME: Is this correct?  I dunno, it works.
910         SoundSlots[channel].playing=0;
911 }
912
913 void digi_reset_digi_sounds() {
914  int i;
915
916  for (i=0; i< MAX_SOUND_SLOTS; i++)
917   SoundSlots[i].playing=0;
918  
919  //added on 980905 by adb to reset sound kill system
920  memset(SampleHandles, 255, sizeof(SampleHandles));
921  next_handle = 0;
922  //end edit by adb
923 }
924
925
926 // MIDI stuff follows.
927 //added/killed on 11/25/98 by Matthew Mueller
928 //void digi_set_midi_volume( int mvolume ) { }
929 //void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
930 //void digi_stop_current_song()
931 //{
932 //#ifdef HMIPLAY
933 //        char buf[10];
934 //    
935 //        sprintf(buf,"s");
936 //        send_ipc(buf);
937 //#endif
938 //}
939 //end this section kill - MM