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