]> icculus.org git repositories - btb/d2x.git/blob - arch/linux/alsadigi.c
get rid of warnings (now compiles with -Werror on SunOS)
[btb/d2x.git] / arch / linux / alsadigi.c
1 /* $Id: alsadigi.c,v 1.2 2003-03-13 00:20:21 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 <sys/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 void *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++) = mix8[ *sp + fixmul(v, vr) + 0x80 ];
230    }
231    sl->position = sldata - sl->samples;
232   }
233  }
234 }
235 //end changes by adb
236
237 void *mixer_thread(void *data) {
238 // int i=0;
239  ubyte buffer[512];
240  /* Allow ourselves to be asynchronously cancelled */
241  pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
242  while (1) {
243 //   printf("i=%d\n",i++);
244    memset(buffer, 0x80, 512);
245    LOCK();
246    audio_mixcallback(NULL,buffer,512);
247    UNLOCK();
248    snd_pcm_write(snd_devhandle, buffer, 512);
249  } 
250  return 0;
251 }
252
253
254 /* Initialise audio devices. */
255 int digi_init()
256 {
257  int card=0, device=0, err;
258  snd_pcm_format_t format;
259  snd_pcm_playback_params_t params;
260  pthread_attr_t attr;
261  pthread_mutexattr_t mutexattr;
262
263  //added on 980905 by adb to init sound kill system
264  memset(SampleHandles, 255, sizeof(SampleHandles));
265  //end edit by adb
266
267  /* Open the ALSA sound device */
268  if ((err = snd_pcm_open(&snd_devhandle, card, device, 
269      SND_PCM_OPEN_PLAYBACK)) < 0) {  
270      fprintf(stderr, "open failed: %s\n", snd_strerror( err ));  
271      return -1; 
272  } 
273
274  memset(&format, 0, sizeof(format));
275  format.format = SND_PCM_SFMT_U8;
276  format.rate = 11025;
277  format.channels = 2;
278  if ((err = snd_pcm_playback_format(snd_devhandle, &format)) < 0) { 
279     fprintf(stderr, "format setup failed: %s\n", snd_strerror( err ));
280     snd_pcm_close( snd_devhandle ); 
281     return -1; 
282  } 
283
284  memset(&params, 0, sizeof(params));
285  params.fragment_size=512;
286  params.fragments_max=2;
287  params.fragments_room=1;
288  if ((err = snd_pcm_playback_params(snd_devhandle, &params)) < 0) { 
289     fprintf(stderr, "params setup failed: %s\n", snd_strerror( err ));
290     snd_pcm_close( snd_devhandle ); 
291     return -1; 
292  }
293
294  /* Start the mixer thread */
295
296  /* We really should check the results of these */
297  pthread_mutexattr_init(&mutexattr);
298  pthread_mutex_init(&mutex,&mutexattr);
299  pthread_mutexattr_destroy(&mutexattr);
300  
301  if (pthread_attr_init(&attr) != 0) {
302   fprintf(stderr, "failed to init attr\n");
303   snd_pcm_close( snd_devhandle ); 
304   return -1;
305  }
306
307  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
308
309  pthread_create(&thread_id,&attr,mixer_thread,NULL);
310  pthread_attr_destroy(&attr);
311
312  atexit(digi_close);
313  digi_initialised = 1;
314  return 0;
315 }
316
317 /* Toggle audio */
318 void digi_reset() { }
319
320 /* Shut down audio */
321 void digi_close()
322 {
323  if (!digi_initialised) return;
324  digi_initialised = 0;
325  snd_pcm_close(snd_devhandle);
326  pthread_mutex_destroy(&mutex);
327  pthread_cancel(thread_id);
328 }
329
330 /* Find the sound which actually equates to a sound number */
331 int digi_xlat_sound(int soundno)
332 {
333         if ( soundno < 0 ) return -1;
334
335         if ( digi_lomem )       {
336                 soundno = AltSounds[soundno];
337                 if ( soundno == 255 ) return -1;
338         }
339         return Sounds[soundno];
340 }
341
342 static int get_free_slot()
343 {
344  int i;
345  for (i=0; i<MAX_SOUND_SLOTS; i++)
346  {
347   if (!SoundSlots[i].playing) return i;
348  }
349  return -1;
350 }
351
352 int digi_start_sound(int soundnum, fix volume, fix pan)
353 {
354  int ntries;
355  int slot;
356
357  if (!digi_initialised) return -1;
358  LOCK();
359  //added on 980905 by adb from original source to add sound kill system
360  // play at most digi_max_channel samples, if possible kill sample with low volume
361  ntries = 0;
362
363 TryNextChannel:
364  if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing)  )
365  {
366   if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries<digi_max_channels) )
367   {
368    //mprintf(( 0, "Not stopping loud sound %d.\n", next_handle ));
369    next_handle++;
370    if ( next_handle >= digi_max_channels )
371     next_handle = 0;
372    ntries++;
373    goto TryNextChannel;
374   }
375   //mprintf(( 0, "[SS:%d]", next_handle ));
376   SoundSlots[SampleHandles[next_handle]].playing = 0;
377   SampleHandles[next_handle] = -1;
378  }
379  //end edit by adb
380
381  slot = get_free_slot();
382  if (slot<0) return -1;
383
384  SoundSlots[slot].soundno = soundnum;
385  SoundSlots[slot].samples = GameSounds[soundnum].data;
386  SoundSlots[slot].length = GameSounds[soundnum].length;
387  SoundSlots[slot].volume = fixmul(digi_volume, volume);
388  SoundSlots[slot].pan = pan;
389  SoundSlots[slot].position = 0;
390  SoundSlots[slot].looped = 0;
391  SoundSlots[slot].playing = 1;
392
393  //added on 980905 by adb to add sound kill system from original sos digi.c
394  reset_sounds_on_channel(slot);
395  SampleHandles[next_handle] = slot;
396  next_handle++;
397  if ( next_handle >= digi_max_channels )
398   next_handle = 0;
399  //end edit by adb
400  UNLOCK();
401  return slot;
402 }
403
404  //added on 980905 by adb to add sound kill system from original sos digi.c
405 void reset_sounds_on_channel( int channel )
406 {
407  int i;
408
409  for (i=0; i<digi_max_channels; i++)
410   if (SampleHandles[i] == channel)
411    SampleHandles[i] = -1;
412 }
413 //end edit by adb
414
415 int digi_start_sound_object(int obj)
416 {
417  int slot;
418
419  if (!digi_initialised) return -1;
420  LOCK();
421  slot = get_free_slot();
422
423  if (slot<0) { UNLOCK(); return -1; }
424
425
426  SoundSlots[slot].soundno = SoundObjects[obj].soundnum;
427  SoundSlots[slot].samples = GameSounds[SoundObjects[obj].soundnum].data;
428  SoundSlots[slot].length = GameSounds[SoundObjects[obj].soundnum].length;
429  SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume);
430  SoundSlots[slot].pan = SoundObjects[obj].pan;
431  SoundSlots[slot].position = 0;
432  SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER);
433  SoundSlots[slot].playing = 1;
434
435  SoundObjects[obj].signature = next_signature++;
436  SoundObjects[obj].handle = slot;
437
438  SoundObjects[obj].flags |= SOF_PLAYING;
439  //added on 980905 by adb to add sound kill system from original sos digi.c
440  reset_sounds_on_channel(slot);
441  //end edit by adb
442  
443  UNLOCK();
444  return 0;
445 }
446
447
448 // Play the given sound number.
449 // Volume is max at F1_0.
450 void digi_play_sample( int soundno, fix max_volume )
451 {
452 #ifdef NEWDEMO
453         if ( Newdemo_state == ND_STATE_RECORDING )
454                 newdemo_record_sound( soundno );
455 #endif
456         soundno = digi_xlat_sound(soundno);
457
458         if (!digi_initialised) return;
459
460         if (soundno < 0 ) return;
461
462         digi_start_sound(soundno, max_volume, F0_5);
463 }
464
465 // Play the given sound number. If the sound is already playing,
466 // restart it.
467 void digi_play_sample_once( int soundno, fix max_volume )
468 {
469         int i;
470
471 #ifdef NEWDEMO
472         if ( Newdemo_state == ND_STATE_RECORDING )
473                 newdemo_record_sound( soundno );
474 #endif
475         soundno = digi_xlat_sound(soundno);
476
477         if (!digi_initialised) return;
478
479         if (soundno < 0 ) return;
480
481         LOCK();
482         for (i=0; i < MAX_SOUND_SLOTS; i++)
483           if (SoundSlots[i].soundno == soundno)
484             SoundSlots[i].playing = 0;
485         UNLOCK();
486         digi_start_sound(soundno, max_volume, F0_5);
487
488 }
489
490 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) // Volume from 0-0x7fff
491 {
492         no_dups = 1;
493
494 #ifdef NEWDEMO
495         if ( Newdemo_state == ND_STATE_RECORDING )              {
496                 if ( no_dups )
497                         newdemo_record_sound_3d_once( soundno, angle, volume );
498                 else
499                         newdemo_record_sound_3d( soundno, angle, volume );
500         }
501 #endif
502         soundno = digi_xlat_sound(soundno);
503
504         if (!digi_initialised) return;
505         if (soundno < 0 ) return;
506
507         if (volume < MIN_VOLUME ) return;
508         digi_start_sound(soundno, volume, angle);
509 }
510
511 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 )
512 {         
513         vms_vector      vector_to_sound;
514         fix angle_from_ear, cosang,sinang;
515         fix distance;
516         fix path_distance;
517
518         *volume = 0;
519         *pan = 0;
520
521         max_distance = (max_distance*5)/4;              // Make all sounds travel 1.25 times as far.
522
523         //      Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
524         distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
525                 
526         if (distance < max_distance )   {
527                 int num_search_segs = f2i(max_distance/20);
528                 if ( num_search_segs < 1 ) num_search_segs = 1;
529
530                 path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
531                 if ( path_distance > -1 )       {
532                         *volume = max_volume - fixdiv(path_distance,max_distance);
533                         //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
534                         if (*volume > 0 )       {
535                                 angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
536                                 fix_sincos(angle_from_ear,&sinang,&cosang);
537                                 //mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
538                                 if (Config_channels_reversed) cosang *= -1;
539                                 *pan = (cosang + F1_0)/2;
540                         } else {
541                                 *volume = 0;
542                         }
543                 }
544         }                                                                                                                                                                         
545 }
546
547 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix  max_distance )
548 {
549         int i,volume,pan;
550         object * objp;
551         int soundnum;
552
553         soundnum = digi_xlat_sound(org_soundnum);
554
555         if ( max_volume < 0 ) return -1;
556 //      if ( max_volume > F1_0 ) max_volume = F1_0;
557
558         if (!digi_initialised) return -1;
559         if (soundnum < 0 ) return -1;
560         if (GameSounds[soundnum].data==NULL) {
561                 Int3();
562                 return -1;
563         }
564         if ((objnum<0)||(objnum>Highest_object_index))
565                 return -1;
566
567         if ( !forever ) {
568                 // Hack to keep sounds from building up...
569                 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
570                 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
571                 return -1;
572         }
573
574         for (i=0; i<MAX_SOUND_OBJECTS; i++ )
575                 if (SoundObjects[i].flags==0)
576                    break;
577
578         if (i==MAX_SOUND_OBJECTS) {
579                 mprintf((1, "Too many sound objects!\n" ));
580                 return -1;
581         }
582
583         SoundObjects[i].signature=next_signature++;
584         SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
585         if ( forever )
586                 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
587         SoundObjects[i].lo_objnum = objnum;
588         SoundObjects[i].lo_objsignature = Objects[objnum].signature;
589         SoundObjects[i].max_volume = max_volume;
590         SoundObjects[i].max_distance = max_distance;
591         SoundObjects[i].volume = 0;
592         SoundObjects[i].pan = 0;
593         SoundObjects[i].soundnum = soundnum;
594
595         objp = &Objects[SoundObjects[i].lo_objnum];
596         digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
597                        &objp->pos, objp->segnum, SoundObjects[i].max_volume,
598                        &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
599
600         if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
601                digi_start_sound_object(i);
602
603         return SoundObjects[i].signature;
604 }
605
606 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
607 { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); }
608
609 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
610 {
611         int i, volume, pan;
612         int soundnum;
613
614         soundnum = digi_xlat_sound(org_soundnum);
615
616         if ( max_volume < 0 ) return -1;
617 //      if ( max_volume > F1_0 ) max_volume = F1_0;
618
619         if (!digi_initialised) return -1;
620         if (soundnum < 0 ) return -1;
621         if (GameSounds[soundnum].data==NULL) {
622                 Int3();
623                 return -1;
624         }
625
626         if ((segnum<0)||(segnum>Highest_segment_index))
627                 return -1;
628
629         if ( !forever ) {
630                 // Hack to keep sounds from building up...
631                 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
632                 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
633                 return -1;
634         }
635
636         for (i=0; i<MAX_SOUND_OBJECTS; i++ )
637                 if (SoundObjects[i].flags==0)
638                         break;
639         
640         if (i==MAX_SOUND_OBJECTS) {
641                 mprintf((1, "Too many sound objects!\n" ));
642                 return -1;
643         }
644
645
646         SoundObjects[i].signature=next_signature++;
647         SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
648         if ( forever )
649                 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
650         SoundObjects[i].lp_segnum = segnum;
651         SoundObjects[i].lp_sidenum = sidenum;
652         SoundObjects[i].lp_position = *pos;
653         SoundObjects[i].soundnum = soundnum;
654         SoundObjects[i].max_volume = max_volume;
655         SoundObjects[i].max_distance = max_distance;
656         SoundObjects[i].volume = 0;
657         SoundObjects[i].pan = 0;
658         digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
659                                            &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
660                                            SoundObjects[i].max_volume,
661                        &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
662         
663         if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
664                 digi_start_sound_object(i);
665
666         return SoundObjects[i].signature;
667 }
668
669 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
670 {
671         return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
672 }
673
674 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
675 {
676         int i,killed;
677
678         soundnum = digi_xlat_sound(soundnum);
679
680         if (!digi_initialised) return;
681
682         killed = 0;
683
684         for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
685                 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) )  {
686                         if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
687                                 if ( SoundObjects[i].flags & SOF_PLAYING )      {
688                                         LOCK();
689                                         SoundSlots[SoundObjects[i].handle].playing = 0;
690                                         UNLOCK();
691                                 }
692                                 SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
693                                 killed++;
694                         }
695                 }
696         }
697         // If this assert happens, it means that there were 2 sounds
698         // that got deleted. Weird, get John.
699         if ( killed > 1 )       {
700                 mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
701         }
702 }
703
704 void digi_kill_sound_linked_to_object( int objnum )
705 {
706         int i,killed;
707
708         if (!digi_initialised) return;
709
710         killed = 0;
711
712         for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
713                 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) ) {
714                         if (SoundObjects[i].lo_objnum == objnum)   {
715                                 if ( SoundObjects[i].flags & SOF_PLAYING )      {
716                                      LOCK();
717                                      SoundSlots[SoundObjects[i].handle].playing = 0;
718                                      UNLOCK();
719                                 }
720                                 SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
721                                 killed++;
722                         }
723                 }
724         }
725         // If this assert happens, it means that there were 2 sounds
726         // that got deleted. Weird, get John.
727         if ( killed > 1 )       {
728                 mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
729         }
730 }
731
732 void digi_sync_sounds()
733 {
734         int i;
735         int oldvolume, oldpan;
736
737         if (!digi_initialised) return;
738
739         for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
740                 if ( SoundObjects[i].flags & SOF_USED ) {
741                         oldvolume = SoundObjects[i].volume;
742                         oldpan = SoundObjects[i].pan;
743
744                         if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) )      {
745                                 // Check if its done.
746                                 if (SoundObjects[i].flags & SOF_PLAYING) {
747                                         LOCK();
748                                         if (!SoundSlots[SoundObjects[i].handle].playing) {
749                                                 UNLOCK();
750                                                 SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
751                                                 continue;               // Go on to next sound...
752                                         }
753                                         UNLOCK();
754                                 }
755                         }                       
756                 
757                         if ( SoundObjects[i].flags & SOF_LINK_TO_POS )  {
758                                 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
759                                                                 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
760                                                                 SoundObjects[i].max_volume,
761                                 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
762
763                         } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ )   {
764                                 object * objp;
765         
766                                 objp = &Objects[SoundObjects[i].lo_objnum];
767                 
768                                 if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature))  {
769                                         // The object that this is linked to is dead, so just end this sound if it is looping.
770                                         if ( (SoundObjects[i].flags & SOF_PLAYING)  && (SoundObjects[i].flags & SOF_PLAY_FOREVER))      {
771                                              LOCK();
772                                              SoundSlots[SoundObjects[i].handle].playing = 0;
773                                              UNLOCK();
774                                         }
775                                         SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
776                                         continue;               // Go on to next sound...
777                                 } else {
778                                         digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
779                                         &objp->pos, objp->segnum, SoundObjects[i].max_volume,
780                                    &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
781                                 }
782                         }
783                          
784                         if (oldvolume != SoundObjects[i].volume)        {
785                                 if ( SoundObjects[i].volume < MIN_VOLUME )       {
786                                         // Sound is too far away, so stop it from playing.
787                                         if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER))  {
788                                                 LOCK();
789                                                 SoundSlots[SoundObjects[i].handle].playing = 0;
790                                                 UNLOCK();
791                                                 SoundObjects[i].flags &= ~SOF_PLAYING;          // Mark sound as not playing
792                                         }
793                                 } else {
794                                         if (!(SoundObjects[i].flags & SOF_PLAYING))     {
795                                                 digi_start_sound_object(i);
796                                         } else {
797                                                 LOCK();
798                                                 SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0);
799                                                 UNLOCK();
800                                         }
801                                 }
802                         }
803                                 
804                         if (oldpan != SoundObjects[i].pan)      {
805                                 if (SoundObjects[i].flags & SOF_PLAYING) {
806                                         LOCK();
807                                         SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan;
808                                         UNLOCK();
809                                 }
810                         }
811                 }
812         }
813 }
814
815 void digi_init_sounds()
816 {
817         int i;
818
819         if (!digi_initialised) return;
820
821         digi_reset_digi_sounds();
822
823         for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
824                 if (digi_sounds_initialized) {
825                         if ( SoundObjects[i].flags & SOF_PLAYING )      {
826                                 LOCK();
827                                 SoundSlots[SoundObjects[i].handle].playing=0;
828                                 UNLOCK();
829                         }
830                 }
831                 SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
832         }
833         digi_sounds_initialized = 1;
834 }
835
836 //added on 980905 by adb from original source to make sfx volume work
837 void digi_set_digi_volume( int dvolume )
838 {
839         dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
840         if ( dvolume > SOUND_MAX_VOLUME )
841                 digi_volume = SOUND_MAX_VOLUME;
842         else if ( dvolume < 0 )
843                 digi_volume = 0;
844         else
845                 digi_volume = dvolume;
846
847         if ( !digi_initialised ) return;
848
849         digi_sync_sounds();
850 }
851 //end edit by adb
852
853 void digi_set_volume( int dvolume, int mvolume ) { }
854
855 int digi_is_sound_playing(int soundno)
856 {
857         int i;
858
859         soundno = digi_xlat_sound(soundno);
860
861         LOCK();
862         for (i = 0; i < MAX_SOUND_SLOTS; i++)
863                   //changed on 980905 by adb: added SoundSlots[i].playing &&
864                   if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
865                   //end changes by adb
866                   { UNLOCK();   return 1; }
867         UNLOCK();
868         return 0;
869 }
870
871
872 void digi_pause_all() { }
873 void digi_resume_all() { }
874 void digi_stop_all() { }
875
876  //added on 980905 by adb to make sound channel setting work
877 void digi_set_max_channels(int n) { 
878         digi_max_channels       = n;
879
880         if ( digi_max_channels < 1 ) 
881                 digi_max_channels = 1;
882         if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) ) 
883                 digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS);
884
885         if ( !digi_initialised ) return;
886
887         digi_reset_digi_sounds();
888 }
889
890 int digi_get_max_channels() { 
891         return digi_max_channels; 
892 }
893 // end edit by adb
894
895 void digi_reset_digi_sounds() {
896  int i;
897
898  LOCK();
899  for (i=0; i< MAX_SOUND_SLOTS; i++)
900   SoundSlots[i].playing=0;
901  UNLOCK();
902  
903  //added on 980905 by adb to reset sound kill system
904  memset(SampleHandles, 255, sizeof(SampleHandles));
905  next_handle = 0;
906  //end edit by adb
907 }
908
909
910 // MIDI stuff follows.
911 //added/killed on 11/25/98 by Matthew Mueller
912 //void digi_set_midi_volume( int mvolume ) { }
913 //void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
914 //void digi_stop_current_song()
915 //{
916 //#ifdef HMIPLAY
917 //        char buf[10];
918 //    
919 //        sprintf(buf,"s");
920 //        send_ipc(buf);
921 //#endif
922 //}
923 //end this section kill - MM