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