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