fixed a major memory leak and removed a bit of redundancy (d1x r1.5)
[btb/d2x.git] / arch / win32 / digi.c
1 #define DIGI_SOUND
2 #define MIDI_SOUND
3
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <string.h>
7 #define WIN32_LEAN_AND_MEAN
8 #include <windows.h>
9 #include <mmsystem.h>
10 #include <dsound.h>
11
12 #include <math.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 #include "hmpfile.h"
26 hmp_file *hmp = NULL;
27
28 #ifdef DIGI_SOUND
29 #define MAX_SOUND_SLOTS 32
30 #define MIN_VOLUME 10
31
32
33 #define SOF_USED                        1               // Set if this sample is used
34 #define SOF_PLAYING                     2               // Set if this sample is playing on a channel
35 #define SOF_LINK_TO_OBJ         4               // Sound is linked to a moving object. If object dies, then finishes play and quits.
36 #define SOF_LINK_TO_POS         8               // Sound is linked to segment, pos
37 #define SOF_PLAY_FOREVER        16              // Play forever (or until level is stopped), otherwise plays once
38
39 typedef struct sound_object {
40         short           signature;              // A unique signature to this sound
41         ubyte           flags;                  // Used to tell if this slot is used and/or currently playing, and how long.
42         fix             max_volume;             // Max volume that this sound is playing at
43         fix             max_distance;           // The max distance that this sound can be heard at...
44         int             volume;                 // Volume that this sound is playing at
45         int             pan;                    // Pan value that this sound is playing at
46         int             handle;                 // What handle this sound is playing on.  Valid only if SOF_PLAYING is set.
47         short           soundnum;               // The sound number that is playing
48         union { 
49                 struct {
50                         short           segnum;                         // Used if SOF_LINK_TO_POS field is used
51                         short           sidenum;
52                         vms_vector      position;
53                 }pos;
54                 struct {
55                         short            objnum;                         // Used if SOF_LINK_TO_OBJ field is used
56                         short            objsignature;
57                 }obj;
58         }link;
59 } sound_object;
60 #define lp_segnum link.pos.segnum
61 #define lp_sidenum link.pos.sidenum
62 #define lp_position link.pos.position
63
64 #define lo_objnum link.obj.objnum
65 #define lo_objsignature link.obj.objsignature
66
67 #define MAX_SOUND_OBJECTS 16
68 sound_object SoundObjects[MAX_SOUND_OBJECTS];
69 short next_signature=0;
70
71
72 //added/changed on 980905 by adb to make sfx volume work
73 #define SOUND_MAX_VOLUME F1_0
74 int digi_volume = SOUND_MAX_VOLUME;
75 //end edit by adb
76
77 LPDIRECTSOUND lpds;
78 WAVEFORMATEX waveformat;
79 DSBUFFERDESC dsbd;
80
81 extern HWND g_hWnd;
82
83 struct sound_slot {
84  int soundno;
85  int playing;   // Is there a sample playing on this channel?
86  int looped;    // Play this sample looped?
87  fix pan;       // 0 = far left, 1 = far right
88  fix volume;    // 0 = nothing, 1 = fully on
89  //changed on 980905 by adb from char * to unsigned char * 
90  unsigned char *samples;
91  //end changes by adb
92  unsigned int length; // Length of the sample
93  unsigned int position; // Position we are at at the moment.
94  LPDIRECTSOUNDBUFFER lpsb;
95 } SoundSlots[MAX_SOUND_SLOTS];
96
97
98 int digi_lomem = 0;
99 int midi_volume = 255;
100 int digi_midi_song_playing = 0;
101 int digi_last_midi_song = 0;
102 int digi_last_midi_song_loop = 0;
103
104 static int digi_initialised = 0;
105 static int digi_atexit_initialised=0;
106
107 static int digi_sounds_initialized = 0;
108
109 //added on 980905 by adb to add rotating/volume based sound kill system
110 static int digi_max_channels = 16;
111 static int next_handle = 0;
112 int SampleHandles[32];
113 void reset_sounds_on_channel(int channel);
114 //end edit by adb
115
116 void digi_reset_digi_sounds(void);
117
118 void digi_reset() { }
119
120 void digi_close(void)
121 {
122         if(digi_initialised)
123         {
124                 digi_reset_digi_sounds();
125                 IDirectSound_Release(lpds);
126         }
127         digi_initialised = 0;
128 }
129
130 /* Initialise audio devices. */
131 int digi_init()
132 {
133  HRESULT hr;
134  
135  if (!digi_initialised && g_hWnd){
136
137          memset(&waveformat, 0, sizeof(waveformat));
138          waveformat.wFormatTag=WAVE_FORMAT_PCM;
139          waveformat.wBitsPerSample=8;
140          waveformat.nChannels = 1;
141          waveformat.nSamplesPerSec = digi_sample_rate; //11025;
142          waveformat.nBlockAlign =
143          waveformat.nChannels * (waveformat.wBitsPerSample/8);
144          waveformat.nAvgBytesPerSec =
145          waveformat.nSamplesPerSec * waveformat.nBlockAlign;    
146
147           if ((hr = DirectSoundCreate(NULL, &lpds, NULL)) != DS_OK)
148            return -1;
149
150           if ((hr = IDirectSound_SetCooperativeLevel(lpds, g_hWnd, DSSCL_PRIORITY)) //hWndMain
151                != DS_OK)
152            {
153             IDirectSound_Release(lpds);
154             return -1;
155            }
156         
157          memset(&dsbd, 0, sizeof(dsbd));
158          dsbd.dwSize = sizeof(dsbd);
159          dsbd.dwFlags = DSBCAPS_CTRLDEFAULT | DSBCAPS_GETCURRENTPOSITION2;
160          dsbd.dwBufferBytes = 8192;
161          dsbd.dwReserved=0;
162          dsbd.lpwfxFormat = &waveformat;
163
164          digi_initialised = 1;
165 }
166
167         if (!digi_atexit_initialised){
168                 atexit(digi_close);
169                 digi_atexit_initialised=1;
170         }
171  return 0;
172 }
173
174 /* Find the sound which actually equates to a sound number */
175 int digi_xlat_sound(int soundno)
176 {
177         if ( soundno < 0 ) return -1;
178
179         if ( digi_lomem )       {
180                 soundno = AltSounds[soundno];
181                 if ( soundno == 255 ) return -1;
182         }
183         return Sounds[soundno];
184 }
185
186 // added 2000/01/15 Matt Mueller -- remove some duplication (and fix a big memory leak, in the kill=0 one case)
187 static int DS_release_slot(int slot, int kill)
188 {
189         if (SoundSlots[slot].lpsb)
190         {
191                 unsigned int s;
192
193                 IDirectSoundBuffer_GetStatus(SoundSlots[slot].lpsb, &s);
194                 if (s & DSBSTATUS_PLAYING)
195                 {
196                         if (kill)
197                                 IDirectSoundBuffer_Stop(SoundSlots[slot].lpsb);
198                         else
199                                 return 0;
200                 }
201                 IDirectSoundBuffer_Release(SoundSlots[slot].lpsb);
202                 SoundSlots[slot].playing = 0;
203                 SoundSlots[slot].lpsb = NULL;
204
205                 return 1;
206         }
207
208         return 0;
209 }
210
211 static int get_free_slot()
212 {
213  int i;
214
215  for (i=0; i<MAX_SOUND_SLOTS; i++)
216  {
217   if (!SoundSlots[i].playing) return i;
218                 if (DS_release_slot(i, 0))
219                         return i;
220  }
221  return -1;
222 }
223
224 int D1vol2DSvol(fix d1v){
225 //multiplying by 1.5 doesn't help.  DirectSound uses dB for volume, rather than a linear scale like d1 wants.
226 //I had to pull out a math book, but here is the code to fix it :)  -Matt Mueller
227 //log x=y  <==>  x=a^y  
228 //   a
229          if (d1v<=0)
230                  return -10000;
231          else
232 //               return log2(f2fl(d1v))*1000;//no log2? hm.
233                  return log(f2fl(d1v))/log(2)*1000.0;
234 }
235
236 int digi_start_sound(int soundnum, fix volume, fix pan)
237 {
238  int ntries;
239  int slot;
240  HRESULT hr;
241
242  if (!digi_initialised) return -1;
243
244  //added on 980905 by adb from original source to add sound kill system
245  // play at most digi_max_channel samples, if possible kill sample with low volume
246  ntries = 0;
247
248 TryNextChannel:
249  if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing)  )
250  {
251   if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries<digi_max_channels) )
252   {
253    //mprintf(( 0, "Not stopping loud sound %d.\n", next_handle ));
254    next_handle++;
255    if ( next_handle >= digi_max_channels )
256     next_handle = 0;
257    ntries++;
258    goto TryNextChannel;
259   }
260   //mprintf(( 0, "[SS:%d]", next_handle ));
261   SoundSlots[SampleHandles[next_handle]].playing = 0;
262         DS_release_slot(SampleHandles[next_handle], 1);
263   SampleHandles[next_handle] = -1;
264  }
265  //end edit by adb
266
267  slot = get_free_slot();
268  if (slot<0) return -1;
269
270  SoundSlots[slot].soundno = soundnum;
271  SoundSlots[slot].samples = GameSounds[soundnum].data;
272  SoundSlots[slot].length = GameSounds[soundnum].length;
273  SoundSlots[slot].volume = fixmul(digi_volume, volume);
274  SoundSlots[slot].pan = pan;
275  SoundSlots[slot].position = 0;
276  SoundSlots[slot].looped = 0;
277  SoundSlots[slot].playing = 1;
278
279  memset(&waveformat, 0, sizeof(waveformat));
280  waveformat.wFormatTag=WAVE_FORMAT_PCM;
281  waveformat.wBitsPerSample=8;
282  waveformat.nChannels = 1;
283  waveformat.nSamplesPerSec = digi_sample_rate; //11025;
284  waveformat.nBlockAlign =
285    waveformat.nChannels * (waveformat.wBitsPerSample/8);
286  waveformat.nAvgBytesPerSec =
287    waveformat.nSamplesPerSec * waveformat.nBlockAlign;
288
289  memset(&dsbd, 0, sizeof(dsbd));
290  dsbd.dwSize = sizeof(dsbd);
291  dsbd.dwFlags = DSBCAPS_CTRLDEFAULT | DSBCAPS_GETCURRENTPOSITION2;
292  dsbd.dwReserved=0;
293  dsbd.dwBufferBytes = SoundSlots[slot].length;
294  dsbd.lpwfxFormat = &waveformat;
295
296  hr = IDirectSound_CreateSoundBuffer(lpds, &dsbd, &SoundSlots[slot].lpsb, NULL);
297  if ( hr != DS_OK ) {
298   printf("Createsoundbuffer failed! hr=0x%X\n", (int)hr);
299   abort();
300  }
301  {
302   char *ptr1, *ptr2;
303   int len1, len2;
304   IDirectSoundBuffer_Lock(SoundSlots[slot].lpsb, 0, GameSounds[soundnum].length,
305          (void **)&ptr1, &len1, (void **)&ptr2, &len2, 0);
306   memcpy(ptr1,GameSounds[soundnum].data, MIN(len1, GameSounds[soundnum].length));
307   IDirectSoundBuffer_Unlock(SoundSlots[slot].lpsb, ptr1, len1, ptr2, len2);
308  }
309  IDirectSoundBuffer_SetPan(SoundSlots[slot].lpsb, ((int)(f2fl(pan) * 20000.0))-10000);
310 // IDirectSoundBuffer_SetVolume(SoundSlots[slot].lpsb, MIN(((int)(f2fl(SoundSlots[slot].volume) * 15000.0)) - 10000, 0));//nope
311  IDirectSoundBuffer_SetVolume(SoundSlots[slot].lpsb, D1vol2DSvol(SoundSlots[slot].volume));
312  
313  IDirectSoundBuffer_Play(SoundSlots[slot].lpsb, 0, 0, 0);
314
315  //added on 980905 by adb to add sound kill system from original sos digi.c
316  reset_sounds_on_channel(slot);
317  SampleHandles[next_handle] = slot;
318  next_handle++;
319  if ( next_handle >= digi_max_channels )
320   next_handle = 0;
321  //end edit by adb
322
323  return slot;
324 }
325
326  //added on 980905 by adb to add sound kill system from original sos digi.c
327 void reset_sounds_on_channel( int channel )
328 {
329  int i;
330
331  for (i=0; i<digi_max_channels; i++)
332   if (SampleHandles[i] == channel)
333    SampleHandles[i] = -1;
334 }
335 //end edit by adb
336
337 int digi_start_sound_object(int obj)
338 {
339  int slot;
340  HRESULT hr;
341
342  if (!digi_initialised) return -1;
343  slot = get_free_slot();
344
345  if (slot<0) return -1;
346
347
348  SoundSlots[slot].soundno = SoundObjects[obj].soundnum;
349  SoundSlots[slot].samples = GameSounds[SoundObjects[obj].soundnum].data;
350  SoundSlots[slot].length = GameSounds[SoundObjects[obj].soundnum].length;
351  SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume);
352  SoundSlots[slot].pan = SoundObjects[obj].pan;
353  SoundSlots[slot].position = 0;
354  SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER);
355  SoundSlots[slot].playing = 1;
356
357  memset(&waveformat, 0, sizeof(waveformat));
358  waveformat.wFormatTag=WAVE_FORMAT_PCM;
359  waveformat.wBitsPerSample=8;
360  waveformat.nChannels = 1;
361  waveformat.nSamplesPerSec = digi_sample_rate; // 11025;
362  waveformat.nBlockAlign =
363  waveformat.nChannels * (waveformat.wBitsPerSample/8);
364  waveformat.nAvgBytesPerSec =
365  waveformat.nSamplesPerSec * waveformat.nBlockAlign;
366
367  memset(&dsbd, 0, sizeof(dsbd));
368  dsbd.dwSize = sizeof(dsbd);
369  dsbd.dwFlags = DSBCAPS_CTRLDEFAULT | DSBCAPS_GETCURRENTPOSITION2;
370  dsbd.dwReserved=0;
371  dsbd.dwBufferBytes = SoundSlots[slot].length;
372  dsbd.lpwfxFormat = &waveformat;
373
374  hr = IDirectSound_CreateSoundBuffer(lpds, &dsbd, &SoundSlots[slot].lpsb, NULL);
375  if ( hr != DS_OK ) {
376   abort();
377  }
378  {
379   char *ptr1, *ptr2;
380   int len1, len2;
381   IDirectSoundBuffer_Lock(SoundSlots[slot].lpsb, 0, SoundSlots[slot].length,
382          (void **)&ptr1, &len1, (void **)&ptr2, &len2, 0);
383   memcpy(ptr1, SoundSlots[slot].samples, MIN(len1,(int)SoundSlots[slot].length));
384   IDirectSoundBuffer_Unlock(SoundSlots[slot].lpsb, (void *)ptr1, len1, (void *)ptr2, len2);
385  }
386  IDirectSoundBuffer_SetPan(SoundSlots[slot].lpsb, ((int)(f2fl(SoundSlots[slot].pan) * 20000))-10000);
387 // IDirectSoundBuffer_SetVolume(SoundSlots[slot].lpsb, MIN(((int)(f2fl(SoundSlots[slot].volume) * 15000.0)) - 10000, 0));//nope
388  IDirectSoundBuffer_SetVolume(SoundSlots[slot].lpsb,D1vol2DSvol(SoundSlots[slot].volume));
389  IDirectSoundBuffer_Play(SoundSlots[slot].lpsb, 0, 0, SoundSlots[slot].looped?DSBPLAY_LOOPING:0);
390
391  SoundObjects[obj].signature = next_signature++;
392  SoundObjects[obj].handle = slot;
393
394  SoundObjects[obj].flags |= SOF_PLAYING;
395  //added on 980905 by adb to add sound kill system from original sos digi.c
396  reset_sounds_on_channel(slot);
397  //end edit by adb
398  
399  return 0;
400 }
401
402
403 // Play the given sound number.
404 // Volume is max at F1_0.
405 void digi_play_sample( int soundno, fix max_volume )
406 {
407 #ifdef NEWDEMO
408         if ( Newdemo_state == ND_STATE_RECORDING )
409                 newdemo_record_sound( soundno );
410 #endif
411         soundno = digi_xlat_sound(soundno);
412
413         if (!digi_initialised) return;
414
415         if (soundno < 0 ) return;
416
417         digi_start_sound(soundno, max_volume, F0_5);
418 }
419
420 // Play the given sound number. If the sound is already playing,
421 // restart it.
422 void digi_play_sample_once( int soundno, fix max_volume )
423 {
424         int i;
425
426 #ifdef NEWDEMO
427         if ( Newdemo_state == ND_STATE_RECORDING )
428                 newdemo_record_sound( soundno );
429 #endif
430         soundno = digi_xlat_sound(soundno);
431
432         if (!digi_initialised) return;
433
434         if (soundno < 0 ) return;
435
436         for (i=0; i < MAX_SOUND_SLOTS; i++)
437           if (SoundSlots[i].soundno == soundno) {
438              SoundSlots[i].playing = 0;
439                                 DS_release_slot(i, 1);
440           }
441         digi_start_sound(soundno, max_volume, F0_5);
442
443 }
444
445 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) // Volume from 0-0x7fff
446 {
447         no_dups = 1;
448
449 #ifdef NEWDEMO
450         if ( Newdemo_state == ND_STATE_RECORDING )              {
451                 if ( no_dups )
452                         newdemo_record_sound_3d_once( soundno, angle, volume );
453                 else
454                         newdemo_record_sound_3d( soundno, angle, volume );
455         }
456 #endif
457         soundno = digi_xlat_sound(soundno);
458
459         if (!digi_initialised) return;
460         if (soundno < 0 ) return;
461
462         if (volume < MIN_VOLUME ) return;
463         digi_start_sound(soundno, volume, angle);
464 }
465
466 void digi_get_sound_loc( vms_matrix * listener, vms_vector * listener_pos, int listener_seg, vms_vector * sound_pos, int sound_seg, fix max_volume, int *volume, int *pan, fix max_distance )
467 {         
468         vms_vector      vector_to_sound;
469         fix angle_from_ear, cosang,sinang;
470         fix distance;
471         fix path_distance;
472
473         *volume = 0;
474         *pan = 0;
475
476         max_distance = (max_distance*5)/4;              // Make all sounds travel 1.25 times as far.
477
478         //      Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
479         distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
480                 
481         if (distance < max_distance )   {
482                 int num_search_segs = f2i(max_distance/20);
483                 if ( num_search_segs < 1 ) num_search_segs = 1;
484
485                 path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
486                 if ( path_distance > -1 )       {
487                         *volume = max_volume - fixdiv(path_distance,max_distance);
488                         //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
489                         if (*volume > 0 )       {
490                                 angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
491                                 fix_sincos(angle_from_ear,&sinang,&cosang);
492                                 //mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
493                                 if (Config_channels_reversed) cosang *= -1;
494                                 *pan = (cosang + F1_0)/2;
495                         } else {
496                                 *volume = 0;
497                         }
498                 }
499         }                                                                                                                                                                         
500 }
501
502 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix  max_distance )
503 {
504         int i,volume,pan;
505         object * objp;
506         int soundnum;
507
508         soundnum = digi_xlat_sound(org_soundnum);
509
510         if ( max_volume < 0 ) return -1;
511 //      if ( max_volume > F1_0 ) max_volume = F1_0;
512
513         if (!digi_initialised) return -1;
514         if (soundnum < 0 ) return -1;
515         if (GameSounds[soundnum].data==NULL) {
516                 Int3();
517                 return -1;
518         }
519         if ((objnum<0)||(objnum>Highest_object_index))
520                 return -1;
521
522         if ( !forever ) {
523                 // Hack to keep sounds from building up...
524                 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
525                 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
526                 return -1;
527         }
528
529         for (i=0; i<MAX_SOUND_OBJECTS; i++ )
530                 if (SoundObjects[i].flags==0)
531                    break;
532
533         if (i==MAX_SOUND_OBJECTS) {
534                 mprintf((1, "Too many sound objects!\n" ));
535                 return -1;
536         }
537
538         SoundObjects[i].signature=next_signature++;
539         SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
540         if ( forever )
541                 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
542         SoundObjects[i].lo_objnum = objnum;
543         SoundObjects[i].lo_objsignature = Objects[objnum].signature;
544         SoundObjects[i].max_volume = max_volume;
545         SoundObjects[i].max_distance = max_distance;
546         SoundObjects[i].volume = 0;
547         SoundObjects[i].pan = 0;
548         SoundObjects[i].soundnum = soundnum;
549
550         objp = &Objects[SoundObjects[i].lo_objnum];
551         digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
552                        &objp->pos, objp->segnum, SoundObjects[i].max_volume,
553                        &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
554
555         if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
556                digi_start_sound_object(i);
557
558         return SoundObjects[i].signature;
559 }
560
561 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
562 { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); }
563
564 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
565 {
566         int i, volume, pan;
567         int soundnum;
568
569         soundnum = digi_xlat_sound(org_soundnum);
570
571         if ( max_volume < 0 ) return -1;
572 //      if ( max_volume > F1_0 ) max_volume = F1_0;
573
574         if (!digi_initialised) return -1;
575         if (soundnum < 0 ) return -1;
576         if (GameSounds[soundnum].data==NULL) {
577                 Int3();
578                 return -1;
579         }
580
581         if ((segnum<0)||(segnum>Highest_segment_index))
582                 return -1;
583
584         if ( !forever ) {
585                 // Hack to keep sounds from building up...
586                 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
587                 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
588                 return -1;
589         }
590
591         for (i=0; i<MAX_SOUND_OBJECTS; i++ )
592                 if (SoundObjects[i].flags==0)
593                         break;
594         
595         if (i==MAX_SOUND_OBJECTS) {
596                 mprintf((1, "Too many sound objects!\n" ));
597                 return -1;
598         }
599
600
601         SoundObjects[i].signature=next_signature++;
602         SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
603         if ( forever )
604                 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
605         SoundObjects[i].lp_segnum = segnum;
606         SoundObjects[i].lp_sidenum = sidenum;
607         SoundObjects[i].lp_position = *pos;
608         SoundObjects[i].soundnum = soundnum;
609         SoundObjects[i].max_volume = max_volume;
610         SoundObjects[i].max_distance = max_distance;
611         SoundObjects[i].volume = 0;
612         SoundObjects[i].pan = 0;
613         digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
614                                            &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
615                                            SoundObjects[i].max_volume,
616                        &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
617         
618         if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
619                 digi_start_sound_object(i);
620
621         return SoundObjects[i].signature;
622 }
623
624 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
625 {
626         return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
627 }
628
629 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
630 {
631         int i,killed;
632
633         soundnum = digi_xlat_sound(soundnum);
634
635         if (!digi_initialised) return;
636
637         killed = 0;
638
639         for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
640                 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) )  {
641                         if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
642                                 if ( SoundObjects[i].flags & SOF_PLAYING )      {
643                                         SoundSlots[SoundObjects[i].handle].playing = 0;
644                                         DS_release_slot(SoundObjects[i].handle, 1);
645                                 }
646                                 SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
647                                 killed++;
648                         }
649                 }
650         }
651         // If this assert happens, it means that there were 2 sounds
652         // that got deleted. Weird, get John.
653         if ( killed > 1 )       {
654                 mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
655         }
656 }
657
658 void digi_kill_sound_linked_to_object( int objnum )
659 {
660         int i,killed;
661
662         if (!digi_initialised) return;
663
664         killed = 0;
665
666         for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
667                 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) ) {
668                         if (SoundObjects[i].lo_objnum == objnum)   {
669                                 if ( SoundObjects[i].flags & SOF_PLAYING )      {
670                                         SoundSlots[SoundObjects[i].handle].playing = 0;
671                                         DS_release_slot(SoundObjects[i].handle, 1);
672                                 }
673                                 SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
674                                 killed++;
675                         }
676                 }
677         }
678         // If this assert happens, it means that there were 2 sounds
679         // that got deleted. Weird, get John.
680         if ( killed > 1 )       {
681                 mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
682         }
683 }
684
685 void digi_sync_sounds()
686 {
687         int i;
688         int oldvolume, oldpan;
689
690         if (!digi_initialised) return;
691
692         for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
693                 if ( SoundObjects[i].flags & SOF_USED ) {
694                         oldvolume = SoundObjects[i].volume;
695                         oldpan = SoundObjects[i].pan;
696
697                         if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) )      {
698                                 // Check if its done.
699                                 if (SoundObjects[i].flags & SOF_PLAYING) {
700                                         if (!SoundSlots[SoundObjects[i].handle].playing) {
701                                                 SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
702                                                 continue;               // Go on to next sound...
703                                         }
704                                 }
705                         }                       
706                 
707                         if ( SoundObjects[i].flags & SOF_LINK_TO_POS )  {
708                                 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
709                                                                 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
710                                                                 SoundObjects[i].max_volume,
711                                 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
712
713                         } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ )   {
714                                 object * objp;
715         
716                                 objp = &Objects[SoundObjects[i].lo_objnum];
717                 
718                                 if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature))  {
719                                         // The object that this is linked to is dead, so just end this sound if it is looping.
720                                         if ( (SoundObjects[i].flags & SOF_PLAYING)  && (SoundObjects[i].flags & SOF_PLAY_FOREVER))      {
721                                              SoundSlots[SoundObjects[i].handle].playing = 0;
722                                                 DS_release_slot(SoundObjects[i].handle, 1);
723                                         }
724                                         SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
725                                         continue;               // Go on to next sound...
726                                 } else {
727                                         digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, 
728                                         &objp->pos, objp->segnum, SoundObjects[i].max_volume,
729                                    &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
730                                 }
731                         }
732                          
733                         if (oldvolume != SoundObjects[i].volume)        {
734                                 if ( SoundObjects[i].volume < MIN_VOLUME )       {
735                                         // Sound is too far away, so stop it from playing.
736                                         if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER))  {
737                                                 SoundSlots[SoundObjects[i].handle].playing = 0;
738                                                 DS_release_slot(SoundObjects[i].handle, 1);
739                                                 SoundObjects[i].flags &= ~SOF_PLAYING;          // Mark sound as not playing
740                                         }
741                                 } else {
742                                         if (!(SoundObjects[i].flags & SOF_PLAYING))     {
743                                                 digi_start_sound_object(i);
744                                         } else {
745                                                 SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0);
746                                         }
747                                 }
748                         }
749                                 
750                         if (oldpan != SoundObjects[i].pan)      {
751                                 if (SoundObjects[i].flags & SOF_PLAYING)
752                                         SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan;
753                         }
754                 }
755         }
756 }
757
758 void digi_init_sounds()
759 {
760         int i;
761
762         if (!digi_initialised) return;
763
764         digi_reset_digi_sounds();
765
766         for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
767                 if (digi_sounds_initialized) {
768                         if ( SoundObjects[i].flags & SOF_PLAYING )      {
769                                 SoundSlots[SoundObjects[i].handle].playing=0;
770                                 DS_release_slot(SoundObjects[i].handle, 1);
771                         }
772                 }
773                 SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
774         }
775         digi_sounds_initialized = 1;
776 }
777
778 //added on 980905 by adb from original source to make sfx volume work
779 void digi_set_digi_volume( int dvolume )
780 {
781         dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
782         if ( dvolume > SOUND_MAX_VOLUME )
783                 digi_volume = SOUND_MAX_VOLUME;
784         else if ( dvolume < 0 )
785                 digi_volume = 0;
786         else
787                 digi_volume = dvolume;
788
789         if ( !digi_initialised ) return;
790
791         digi_sync_sounds();
792 }
793 //end edit by adb
794
795 void digi_set_volume( int dvolume, int mvolume ) 
796
797         digi_set_digi_volume(dvolume);
798         digi_set_midi_volume(mvolume);
799 }
800
801 int digi_is_sound_playing(int soundno)
802 {
803         int i;
804
805         soundno = digi_xlat_sound(soundno);
806
807         for (i = 0; i < MAX_SOUND_SLOTS; i++)
808                   //changed on 980905 by adb: added SoundSlots[i].playing &&
809                   if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
810                   //end changes by adb
811                         return 1;
812         return 0;
813 }
814
815
816 void digi_pause_all() { }
817 void digi_resume_all() { }
818 void digi_stop_all() { }
819
820  //added on 980905 by adb to make sound channel setting work
821 void digi_set_max_channels(int n) { 
822         digi_max_channels       = n;
823
824         if ( digi_max_channels < 1 ) 
825                 digi_max_channels = 1;
826         if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) ) 
827                 digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS);
828
829         if ( !digi_initialised ) return;
830
831         digi_reset_digi_sounds();
832 }
833
834 int digi_get_max_channels() { 
835         return digi_max_channels; 
836 }
837 // end edit by adb
838
839 void digi_reset_digi_sounds() {
840  int i;
841
842  for (i=0; i< MAX_SOUND_SLOTS; i++) {
843   SoundSlots[i].playing=0;
844                 DS_release_slot(i, 1);
845  }
846  
847  //added on 980905 by adb to reset sound kill system
848  memset(SampleHandles, 255, sizeof(SampleHandles));
849  next_handle = 0;
850  //end edit by adb
851 }
852 #else
853 int digi_lomem = 0;
854 int digi_midi_song_playing = 0;
855 static int digi_initialised = 0;
856 int midi_volume = 255;
857
858 int digi_get_settings() { return 0; }
859 int digi_init() { digi_initialised = 1; return 0; }
860 void digi_reset() {}
861 void digi_close() {}
862
863 void digi_play_sample( int sndnum, fix max_volume ) {}
864 void digi_play_sample_once( int sndnum, fix max_volume ) {}
865 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume ) { return 0; }
866 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume ) { return 0; }
867 // Same as above, but you pass the max distance sound can be heard.  The old way uses f1_0*256 for max_distance.
868 int digi_link_sound_to_object2( int soundnum, short objnum, int forever, fix max_volume, fix  max_distance ) { return 0; }
869 int digi_link_sound_to_pos2( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance ) { return 0; }
870
871 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) {} // Volume from 0-0x7fff
872
873 void digi_init_sounds() {}
874 void digi_sync_sounds() {}
875 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum ) {}
876 void digi_kill_sound_linked_to_object( int objnum ) {}
877
878 void digi_set_digi_volume( int dvolume ) {}
879 void digi_set_volume( int dvolume, int mvolume ) {}
880
881 int digi_is_sound_playing(int soundno) { return 0; }
882
883 void digi_pause_all() {}
884 void digi_resume_all() {}
885 void digi_stop_all() {}
886
887 void digi_set_max_channels(int n) {}
888 int digi_get_max_channels() { return 0; }
889
890 #endif
891
892 #ifdef MIDI_SOUND
893 // MIDI stuff follows.
894
895 void digi_stop_current_song()
896 {
897         if ( digi_midi_song_playing ) {
898             hmp_close(hmp);
899             hmp = NULL;
900             digi_midi_song_playing = 0;
901         }
902 }
903
904 void digi_set_midi_volume( int n )
905 {
906         int mm_volume;
907
908         if (n < 0)
909                 midi_volume = 0;
910         else if (n > 127)
911                 midi_volume = 127;
912         else
913                 midi_volume = n;
914
915         // scale up from 0-127 to 0-0xffff
916         mm_volume = (midi_volume << 1) | (midi_volume & 1);
917         mm_volume |= (mm_volume << 8);
918
919         if (hmp)
920                 midiOutSetVolume((HMIDIOUT)hmp->hmidi, mm_volume | mm_volume << 16);
921 }
922
923 void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop )
924 {       
925         if (!digi_initialised) return;
926
927         digi_stop_current_song();
928
929        //added on 5/20/99 by Victor Rachels to fix crash/etc
930         if(filename == NULL) return;
931         if(midi_volume < 1) return;
932        //end this section addition - VR
933
934         if ((hmp = hmp_open(filename))) {
935             hmp_play(hmp);
936             digi_midi_song_playing = 1;
937             digi_set_midi_volume(midi_volume);
938         }
939         else
940                 printf("hmp_open failed\n");
941 }
942 #else
943 void digi_stop_current_song() {}
944 void digi_set_midi_volume( int n ) {}
945 void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
946 #endif