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