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