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