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