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