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