1 // SDL digital audio support
2 
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <string.h>
6 
7 #include "mm_drv.h"
8 #include "timer.h"
9 
10 //#include "SDL.h"
11 //#include "SDL_audio.h"
12 
13 #include "error.h"
14 #include "mono.h"
15 #include "fix.h"
16 #include "vecmat.h"
17 #include "gr.h" // needed for piggy.h
18 #include "piggy.h"
19 #include "digi.h"
20 #include "sounds.h"
21 #include "wall.h"
22 #include "newdemo.h"
23 #include "kconfig.h"
24 #include "midiallg.h"
25 
26 int digi_driver_board                                   = 0;
27 int digi_driver_port					= 0;
28 int digi_driver_irq					= 0;
29 int digi_driver_dma					= 0;
30 //int digi_midi_type                                    = 0;                    // Midi driver type
31 //int digi_midi_port                                    = 0;                    // Midi driver port
32 int digi_timer_rate					= 9943;			// rate for the timer to go off to handle the driver system (120 Hz)
33 
34 #ifndef ALLG_MIDI
35 /* stub vars/functions for midi */
36 int digi_midi_type                                      = 0;
37 int digi_midi_port                                     = 0;
38 
digi_set_midi_volume(int mvolume)39 void digi_set_midi_volume( int mvolume ) {}
digi_play_midi_song(char * filename,char * melodic_bank,char * drum_bank,int loop)40 void digi_play_midi_song( char * filename, char * melodic_bank,
41 char * drum_bank, int loop ) {}
digi_midi_pause()42 void digi_midi_pause() {}
digi_midi_resume()43 void digi_midi_resume() {}
digi_midi_stop()44 void digi_midi_stop() {}
45 #endif
46 
47 
48 //added on 980905 by adb to add inline fixmul for mixer on i386
49 #ifdef __i386__
50 #define do_fixmul(x,y)				\
51 ({						\
52 	int _ax, _dx;				\
53 	asm("imull %2\n\tshrdl %3,%1,%0"	\
54 	    : "=a"(_ax), "=d"(_dx)		\
55 	    : "rm"(y), "i"(16), "0"(x));	\
56 	_ax;					\
57 })
fixmul(fix x,fix y)58 extern inline fix fixmul(fix x, fix y) { return do_fixmul(x,y); }
59 #endif
60 //end edit by adb
61 
62 //changed on 980905 by adb to increase number of concurrent sounds
63 #define MAX_SOUND_SLOTS 32
64 //end changes by adb
65 #define SOUND_BUFFER_SIZE 512
66 
67 #define MIN_VOLUME 10
68 
69 /* This table is used to add two sound values together and pin
70  * the value to avoid overflow.  (used with permission from ARDI)
71  * DPH: Taken from SDL/src/SDL_mixer.c.
72  */
73 static const unsigned char mix8[] =
74 {
75   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
87   0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
88   0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
89   0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
90   0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
91   0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
92   0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
93   0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
94   0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B,
95   0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
96   0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
97   0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
98   0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
99   0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
100   0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,
101   0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
102   0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
103   0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
104   0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
105   0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4,
106   0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
107   0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
108   0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
109   0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xFF,
110   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
111   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
112   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
113   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
114   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
115   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
116   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
117   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
118   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
119   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
120   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
121   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
122 };
123 
124 #define SOF_USED			1		// Set if this sample is used
125 #define SOF_PLAYING			2		// Set if this sample is playing on a channel
126 #define SOF_LINK_TO_OBJ		4		// Sound is linked to a moving object. If object dies, then finishes play and quits.
127 #define SOF_LINK_TO_POS		8		// Sound is linked to segment, pos
128 #define SOF_PLAY_FOREVER	16		// Play forever (or until level is stopped), otherwise plays once
129 
130 typedef struct sound_object {
131 	short		signature;		// A unique signature to this sound
132 	ubyte		flags;			// Used to tell if this slot is used and/or currently playing, and how long.
133 	fix		max_volume;		// Max volume that this sound is playing at
134 	fix		max_distance;	        // The max distance that this sound can be heard at...
135 	int		volume;			// Volume that this sound is playing at
136 	int 		pan;			// Pan value that this sound is playing at
137 	int		handle; 		// What handle this sound is playing on.  Valid only if SOF_PLAYING is set.
138 	short		soundnum;		// The sound number that is playing
139 	union {
140 		struct {
141 			short		segnum; 			// Used if SOF_LINK_TO_POS field is used
142 			short		sidenum;
143 			vms_vector	position;
144 		}pos;
145 		struct {
146 			short		 objnum;			 // Used if SOF_LINK_TO_OBJ field is used
147 			short		 objsignature;
148 		}obj;
149 	}link;
150 } sound_object;
151 #define lp_segnum link.pos.segnum
152 #define lp_sidenum link.pos.sidenum
153 #define lp_position link.pos.position
154 
155 #define lo_objnum link.obj.objnum
156 #define lo_objsignature link.obj.objsignature
157 
158 #define MAX_SOUND_OBJECTS 16
159 sound_object SoundObjects[MAX_SOUND_OBJECTS];
160 short next_signature=0;
161 
162 //added/changed on 980905 by adb to make sfx volume work
163 #define SOUND_MAX_VOLUME (F1_0/2) // don't use real max like in original
164 int digi_volume = SOUND_MAX_VOLUME;
165 //end edit by adb
166 
167 int digi_lomem = 0;
168 
169 static int digi_initialised = 0;
170 static int timer_system_initialized = 0;
171 
172 struct sound_slot {
173  int soundno;
174  int playing;   // Is there a sample playing on this channel?
175  int looped;    // Play this sample looped?
176  fix pan;       // 0 = far left, 1 = far right
177  fix volume;    // 0 = nothing, 1 = fully on
178  //changed on 980905 by adb from char * to unsigned char *
179  unsigned char *samples;
180  //end changes by adb
181  unsigned int length; // Length of the sample
182  unsigned int position; // Position we are at at the moment.
183 } SoundSlots[MAX_SOUND_SLOTS];
184 
185 //static SDL_AudioSpec WaveSpec;
186 static int digi_sounds_initialized = 0;
187 
188 //added on 980905 by adb to add rotating/volume based sound kill system
189 static int digi_max_channels = 16;
190 static int next_handle = 0;
191 int SampleHandles[32];
192 void reset_sounds_on_channel(int channel);
193 //end edit by adb
194 
195 void digi_reset_digi_sounds(void);
196 
197 /* Audio mixing callback */
198 //changed on 980905 by adb to cleanup, add pan support and optimize mixer
VC_WriteBytes(SBYTE * stream,ULONG len)199 ULONG VC_WriteBytes(SBYTE *stream, ULONG len)
200 {
201  unsigned char *streamend;
202  struct sound_slot *sl;
203 
204 //    if (grd_curscreen)
205 //	  grd_curscreen->sc_canvas.cv_bitmap.bm_data[8]++;
206  len &= ~1; /* stereo -> always write 2 byte pairs */
207  streamend = stream + len;
208 
209 #if 0
210 {
211  static int n = 0;
212  while(stream < streamend) {
213     *(stream++) = (n & 256) ? 256 - (n & 255) : (n & 255);
214     n++;
215  }
216  return len;
217 }
218 #endif
219 
220  memset(stream, 0x80, len);
221 
222  for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++)
223  {
224   if (sl->playing)
225   {
226    unsigned char *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length;
227    unsigned char *sp = stream;
228    signed char v;
229    fix vl, vr;
230    int x;
231 
232    if ((x = sl->pan) & 0x8000)
233    {
234     vl = 0x20000 - x * 2;
235     vr = 0x10000;
236    }
237    else
238    {
239     vl = 0x10000;
240     vr = x * 2;
241    }
242    vl = fixmul(vl, (x = sl->volume));
243    vr = fixmul(vr, x);
244    while (sp < streamend)
245    {
246     if (sldata == slend)
247     {
248      if (!sl->looped)
249      {
250       sl->playing = 0;
251       break;
252      }
253      sldata = sl->samples;
254     }
255     v = *(sldata++) - 0x80;
256     *(sp++) = mix8[ *sp + fixmul(v, vl) + 0x80 ];
257     *(sp++) = mix8[ *sp + fixmul(v, vr) + 0x80 ];
258    }
259    sl->position = sldata - sl->samples;
260   }
261  }
262  return len;
263 }
264 //end changes by adb
265 
266 extern MDRIVER drv_sb;
267 MDRIVER *drv = &drv_sb;
268 char allegro_error[128];
269 
270 int md_mode = DMODE_STEREO;
271 int md_mixfreq = digi_sample_rate; //11025;
272 int md_dmabufsize = 1024;
273 
274 void install_int_ex(void (*)(), long speed);
275 void remove_int(void(*)());
276 
mm_timer()277 void mm_timer() {
278     drv->Update();
279 //    if (grd_curscreen)
280 //	  (*grd_curscreen->sc_canvas.cv_bitmap.bm_data)++;
281 }
282 
283 /* Initialise audio devices. */
digi_init()284 int digi_init()
285 {
286  //added on 980905 by adb to init sound kill system
287  memset(SampleHandles, 255, sizeof(SampleHandles));
288  //end edit by adb
289 
290  #if 0
291  WaveSpec.freq = digi_sample_rate; //11025;
292  WaveSpec.format = AUDIO_U8 | AUDIO_STEREO;
293  WaveSpec.samples = SOUND_BUFFER_SIZE;
294  WaveSpec.callback = audio_mixcallback;
295 
296  if ( SDL_OpenAudio(&WaveSpec, NULL) < 0 ) {
297   printf("Couldn't open audio: %s\n", SDL_GetError());
298   exit(2);
299  }
300  SDL_PauseAudio(0);
301 #endif
302  if (!drv->Init()) {
303 	printf("Couldn't open audio: %s", myerr);
304 	return -1;
305  }
306  drv->PlayStart();
307 
308  if (!timer_system_initialized)
309  {
310   #ifdef ALLG_MIDI
311   install_int_ex(mm_timer, digi_timer_rate);
312   #else
313   timer_set_function(mm_timer);
314   #endif
315   timer_system_initialized = 1;
316  }
317 
318  #ifdef ALLG_MIDI
319  digi_midi_init();
320  #endif
321 
322  atexit(digi_close);
323  digi_initialised = 1;
324  return 0;
325 }
326 
327 /* Toggle audio */
digi_reset()328 void digi_reset() { }
329 
330 /* Shut down audio */
digi_close()331 void digi_close()
332 {
333  if (!digi_initialised) return;
334  digi_initialised = 0;
335  drv->PlayStop();
336  drv->Exit();
337  if (timer_system_initialized)
338  {
339   #ifdef ALLG_MIDI
340   remove_int(mm_timer);
341   #else
342   timer_set_function(NULL);
343   #endif
344   timer_system_initialized = 0;
345  }
346  #ifdef ALLG_MIDI
347  digi_midi_close();
348  #endif
349 }
350 
351 /* Find the sound which actually equates to a sound number */
digi_xlat_sound(int soundno)352 int digi_xlat_sound(int soundno)
353 {
354 	if ( soundno < 0 ) return -1;
355 
356 	if ( digi_lomem )	{
357 		soundno = AltSounds[soundno];
358 		if ( soundno == 255 ) return -1;
359 	}
360 	return Sounds[soundno];
361 }
362 
get_free_slot()363 static int get_free_slot()
364 {
365  int i;
366  for (i=0; i<MAX_SOUND_SLOTS; i++)
367  {
368   if (!SoundSlots[i].playing) return i;
369  }
370  return -1;
371 }
372 
digi_start_sound(int soundnum,fix volume,fix pan)373 int digi_start_sound(int soundnum, fix volume, fix pan)
374 {
375  int ntries;
376  int slot;
377 
378  if (!digi_initialised) return -1;
379 
380  //added on 980905 by adb from original source to add sound kill system
381  // play at most digi_max_channel samples, if possible kill sample with low volume
382  ntries = 0;
383 
384 TryNextChannel:
385  if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing)  )
386  {
387   if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries<digi_max_channels) )
388   {
389    //mprintf(( 0, "Not stopping loud sound %d.\n", next_handle ));
390    next_handle++;
391    if ( next_handle >= digi_max_channels )
392     next_handle = 0;
393    ntries++;
394    goto TryNextChannel;
395   }
396   //mprintf(( 0, "[SS:%d]", next_handle ));
397   SoundSlots[SampleHandles[next_handle]].playing = 0;
398   SampleHandles[next_handle] = -1;
399  }
400  //end edit by adb
401 
402  slot = get_free_slot();
403  if (slot<0) return -1;
404 
405  if (volume > F2_0)
406   volume = F2_0;
407  SoundSlots[slot].soundno = soundnum;
408  SoundSlots[slot].samples = GameSounds[soundnum].data;
409  SoundSlots[slot].length = GameSounds[soundnum].length;
410  SoundSlots[slot].volume = fixmul(digi_volume, volume);
411  SoundSlots[slot].pan = pan;
412  SoundSlots[slot].position = 0;
413  SoundSlots[slot].looped = 0;
414  SoundSlots[slot].playing = 1;
415 
416  //added on 980905 by adb to add sound kill system from original sos digi.c
417  reset_sounds_on_channel(slot);
418  SampleHandles[next_handle] = slot;
419  next_handle++;
420  if ( next_handle >= digi_max_channels )
421   next_handle = 0;
422  //end edit by adb
423 
424  return slot;
425 }
426 
427  //added on 980905 by adb to add sound kill system from original sos digi.c
reset_sounds_on_channel(int channel)428 void reset_sounds_on_channel( int channel )
429 {
430  int i;
431 
432  for (i=0; i<digi_max_channels; i++)
433   if (SampleHandles[i] == channel)
434    SampleHandles[i] = -1;
435 }
436 //end edit by adb
437 
digi_start_sound_object(int obj)438 int digi_start_sound_object(int obj)
439 {
440  int slot;
441 
442  if (!digi_initialised) return -1;
443  slot = get_free_slot();
444 
445  if (slot<0) return -1;
446 
447 
448  SoundSlots[slot].soundno = SoundObjects[obj].soundnum;
449  SoundSlots[slot].samples = GameSounds[SoundObjects[obj].soundnum].data;
450  SoundSlots[slot].length = GameSounds[SoundObjects[obj].soundnum].length;
451  SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume);
452  SoundSlots[slot].pan = SoundObjects[obj].pan;
453  SoundSlots[slot].position = 0;
454  SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER);
455  SoundSlots[slot].playing = 1;
456 
457  SoundObjects[obj].signature = next_signature++;
458  SoundObjects[obj].handle = slot;
459 
460  SoundObjects[obj].flags |= SOF_PLAYING;
461  //added on 980905 by adb to add sound kill system from original sos digi.c
462  reset_sounds_on_channel(slot);
463  //end edit by adb
464 
465  return 0;
466 }
467 
468 
469 // Play the given sound number.
470 // Volume is max at F1_0.
digi_play_sample(int soundno,fix max_volume)471 void digi_play_sample( int soundno, fix max_volume )
472 {
473 #ifdef NEWDEMO
474 	if ( Newdemo_state == ND_STATE_RECORDING )
475 		newdemo_record_sound( soundno );
476 #endif
477 	soundno = digi_xlat_sound(soundno);
478 
479 	if (!digi_initialised) return;
480 
481 	if (soundno < 0 ) return;
482 
483 	digi_start_sound(soundno, max_volume, F0_5);
484 }
485 
486 // Play the given sound number. If the sound is already playing,
487 // restart it.
digi_play_sample_once(int soundno,fix max_volume)488 void digi_play_sample_once( int soundno, fix max_volume )
489 {
490 	int i;
491 
492 #ifdef NEWDEMO
493 	if ( Newdemo_state == ND_STATE_RECORDING )
494 		newdemo_record_sound( soundno );
495 #endif
496 	soundno = digi_xlat_sound(soundno);
497 
498 	if (!digi_initialised) return;
499 
500 	if (soundno < 0 ) return;
501 
502         for (i=0; i < MAX_SOUND_SLOTS; i++)
503           if (SoundSlots[i].soundno == soundno)
504             SoundSlots[i].playing = 0;
505 	digi_start_sound(soundno, max_volume, F0_5);
506 
507 }
508 
digi_play_sample_3d(int soundno,int angle,int volume,int no_dups)509 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) // Volume from 0-0x7fff
510 {
511 	no_dups = 1;
512 
513 #ifdef NEWDEMO
514 	if ( Newdemo_state == ND_STATE_RECORDING )		{
515 		if ( no_dups )
516 			newdemo_record_sound_3d_once( soundno, angle, volume );
517 		else
518 			newdemo_record_sound_3d( soundno, angle, volume );
519 	}
520 #endif
521 	soundno = digi_xlat_sound(soundno);
522 
523 	if (!digi_initialised) return;
524 	if (soundno < 0 ) return;
525 
526 	if (volume < MIN_VOLUME ) return;
527 	digi_start_sound(soundno, volume, angle);
528 }
529 
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)530 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 )
531 {
532 	vms_vector	vector_to_sound;
533 	fix angle_from_ear, cosang,sinang;
534 	fix distance;
535 	fix path_distance;
536 
537 	*volume = 0;
538 	*pan = 0;
539 
540 	max_distance = (max_distance*5)/4;		// Make all sounds travel 1.25 times as far.
541 
542 	//	Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
543 	distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
544 
545 	if (distance < max_distance )	{
546 		int num_search_segs = f2i(max_distance/20);
547 		if ( num_search_segs < 1 ) num_search_segs = 1;
548 
549 		path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
550 		if ( path_distance > -1 )	{
551 			*volume = max_volume - fixdiv(path_distance,max_distance);
552 			//mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
553 			if (*volume > 0 )	{
554 				angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
555 				fix_sincos(angle_from_ear,&sinang,&cosang);
556 				//mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
557 				if (Config_channels_reversed) cosang *= -1;
558 				*pan = (cosang + F1_0)/2;
559 			} else {
560 				*volume = 0;
561 			}
562 		}
563 	}
564 }
565 
digi_link_sound_to_object2(int org_soundnum,short objnum,int forever,fix max_volume,fix max_distance)566 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix  max_distance )
567 {
568 	int i,volume,pan;
569 	object * objp;
570 	int soundnum;
571 
572 	soundnum = digi_xlat_sound(org_soundnum);
573 
574 	if ( max_volume < 0 ) return -1;
575 //	if ( max_volume > F1_0 ) max_volume = F1_0;
576 
577 	if (!digi_initialised) return -1;
578 	if (soundnum < 0 ) return -1;
579 	if (GameSounds[soundnum].data==NULL) {
580 		Int3();
581 		return -1;
582 	}
583 	if ((objnum<0)||(objnum>Highest_object_index))
584 		return -1;
585 
586 	if ( !forever )	{
587 		// Hack to keep sounds from building up...
588 		digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
589 		digi_play_sample_3d( org_soundnum, pan, volume, 0 );
590 		return -1;
591 	}
592 
593        	for (i=0; i<MAX_SOUND_OBJECTS; i++ )
594         	if (SoundObjects[i].flags==0)
595 	           break;
596 
597 	if (i==MAX_SOUND_OBJECTS) {
598 		mprintf((1, "Too many sound objects!\n" ));
599 		return -1;
600 	}
601 
602 	SoundObjects[i].signature=next_signature++;
603 	SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
604 	if ( forever )
605 		SoundObjects[i].flags |= SOF_PLAY_FOREVER;
606 	SoundObjects[i].lo_objnum = objnum;
607 	SoundObjects[i].lo_objsignature = Objects[objnum].signature;
608 	SoundObjects[i].max_volume = max_volume;
609 	SoundObjects[i].max_distance = max_distance;
610 	SoundObjects[i].volume = 0;
611 	SoundObjects[i].pan = 0;
612 	SoundObjects[i].soundnum = soundnum;
613 
614 	objp = &Objects[SoundObjects[i].lo_objnum];
615 	digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
616                        &objp->pos, objp->segnum, SoundObjects[i].max_volume,
617                        &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
618 
619 	if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
620 	       digi_start_sound_object(i);
621 
622 	return SoundObjects[i].signature;
623 }
624 
digi_link_sound_to_object(int soundnum,short objnum,int forever,fix max_volume)625 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
626 { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); }
627 
digi_link_sound_to_pos2(int org_soundnum,short segnum,short sidenum,vms_vector * pos,int forever,fix max_volume,fix max_distance)628 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
629 {
630 	int i, volume, pan;
631 	int soundnum;
632 
633 	soundnum = digi_xlat_sound(org_soundnum);
634 
635 	if ( max_volume < 0 ) return -1;
636 //	if ( max_volume > F1_0 ) max_volume = F1_0;
637 
638 	if (!digi_initialised) return -1;
639 	if (soundnum < 0 ) return -1;
640 	if (GameSounds[soundnum].data==NULL) {
641 		Int3();
642 		return -1;
643 	}
644 
645 	if ((segnum<0)||(segnum>Highest_segment_index))
646 		return -1;
647 
648 	if ( !forever )	{
649 		// Hack to keep sounds from building up...
650 		digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
651 		digi_play_sample_3d( org_soundnum, pan, volume, 0 );
652 		return -1;
653 	}
654 
655 	for (i=0; i<MAX_SOUND_OBJECTS; i++ )
656 		if (SoundObjects[i].flags==0)
657 			break;
658 
659 	if (i==MAX_SOUND_OBJECTS) {
660 		mprintf((1, "Too many sound objects!\n" ));
661 		return -1;
662 	}
663 
664 
665 	SoundObjects[i].signature=next_signature++;
666 	SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
667 	if ( forever )
668 		SoundObjects[i].flags |= SOF_PLAY_FOREVER;
669 	SoundObjects[i].lp_segnum = segnum;
670 	SoundObjects[i].lp_sidenum = sidenum;
671 	SoundObjects[i].lp_position = *pos;
672 	SoundObjects[i].soundnum = soundnum;
673 	SoundObjects[i].max_volume = max_volume;
674 	SoundObjects[i].max_distance = max_distance;
675 	SoundObjects[i].volume = 0;
676 	SoundObjects[i].pan = 0;
677 	digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
678 					   &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
679 					   SoundObjects[i].max_volume,
680                        &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
681 
682 	if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
683 		digi_start_sound_object(i);
684 
685 	return SoundObjects[i].signature;
686 }
687 
digi_link_sound_to_pos(int soundnum,short segnum,short sidenum,vms_vector * pos,int forever,fix max_volume)688 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
689 {
690 	return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
691 }
692 
digi_kill_sound_linked_to_segment(int segnum,int sidenum,int soundnum)693 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
694 {
695 	int i,killed;
696 
697 	soundnum = digi_xlat_sound(soundnum);
698 
699 	if (!digi_initialised) return;
700 
701 	killed = 0;
702 
703 	for (i=0; i<MAX_SOUND_OBJECTS; i++ )	{
704 		if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) )	{
705 			if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
706 				if ( SoundObjects[i].flags & SOF_PLAYING )	{
707 				        SoundSlots[SoundObjects[i].handle].playing = 0;
708 				}
709 				SoundObjects[i].flags = 0;	// Mark as dead, so some other sound can use this sound
710 				killed++;
711 			}
712 		}
713 	}
714 	// If this assert happens, it means that there were 2 sounds
715 	// that got deleted. Weird, get John.
716 	if ( killed > 1 )	{
717 		mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
718 	}
719 }
720 
digi_kill_sound_linked_to_object(int objnum)721 void digi_kill_sound_linked_to_object( int objnum )
722 {
723 	int i,killed;
724 
725 	if (!digi_initialised) return;
726 
727 	killed = 0;
728 
729 	for (i=0; i<MAX_SOUND_OBJECTS; i++ )	{
730 		if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) )	{
731 			if (SoundObjects[i].lo_objnum == objnum)   {
732 				if ( SoundObjects[i].flags & SOF_PLAYING )	{
733                                      SoundSlots[SoundObjects[i].handle].playing = 0;
734 				}
735 				SoundObjects[i].flags = 0;	// Mark as dead, so some other sound can use this sound
736 				killed++;
737 			}
738 		}
739 	}
740 	// If this assert happens, it means that there were 2 sounds
741 	// that got deleted. Weird, get John.
742 	if ( killed > 1 )	{
743 		mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
744 	}
745 }
746 
digi_sync_sounds()747 void digi_sync_sounds()
748 {
749 	int i;
750 	int oldvolume, oldpan;
751 
752 	if (!digi_initialised) return;
753 
754 	for (i=0; i<MAX_SOUND_OBJECTS; i++ )	{
755 		if ( SoundObjects[i].flags & SOF_USED )	{
756 			oldvolume = SoundObjects[i].volume;
757 			oldpan = SoundObjects[i].pan;
758 
759 			if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) )	{
760 			 	// Check if its done.
761 				if (SoundObjects[i].flags & SOF_PLAYING) {
762 					if (!SoundSlots[SoundObjects[i].handle].playing) {
763 						SoundObjects[i].flags = 0;	// Mark as dead, so some other sound can use this sound
764 						continue;		// Go on to next sound...
765 					}
766 				}
767 			}
768 
769 			if ( SoundObjects[i].flags & SOF_LINK_TO_POS )	{
770 				digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
771 								&SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
772 								SoundObjects[i].max_volume,
773                                 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
774 
775 			} else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ )	{
776 				object * objp;
777 
778 				objp = &Objects[SoundObjects[i].lo_objnum];
779 
780 				if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature))  {
781 					// The object that this is linked to is dead, so just end this sound if it is looping.
782 					if ( (SoundObjects[i].flags & SOF_PLAYING)  && (SoundObjects[i].flags & SOF_PLAY_FOREVER))	{
783 					     SoundSlots[SoundObjects[i].handle].playing = 0;
784 					}
785 					SoundObjects[i].flags = 0;	// Mark as dead, so some other sound can use this sound
786 					continue;		// Go on to next sound...
787 				} else {
788 					digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
789 	                                &objp->pos, objp->segnum, SoundObjects[i].max_volume,
790                                    &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
791 				}
792 			}
793 
794 			if (oldvolume != SoundObjects[i].volume) 	{
795 				if ( SoundObjects[i].volume < MIN_VOLUME )	 {
796 					// Sound is too far away, so stop it from playing.
797 					if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER))	{
798                                         	SoundSlots[SoundObjects[i].handle].playing = 0;
799 						SoundObjects[i].flags &= ~SOF_PLAYING;		// Mark sound as not playing
800 					}
801 				} else {
802 					if (!(SoundObjects[i].flags & SOF_PLAYING))	{
803 						digi_start_sound_object(i);
804 					} else {
805 					        SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0);
806 					}
807 				}
808 			}
809 
810 			if (oldpan != SoundObjects[i].pan) 	{
811 				if (SoundObjects[i].flags & SOF_PLAYING)
812                                         SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan;
813 			}
814 		}
815 	}
816 }
817 
digi_stop_soundobjects()818 void digi_stop_soundobjects() {
819         int i;
820 
821         for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
822                 if (digi_sounds_initialized) {
823                         if ( SoundObjects[i].flags & SOF_PLAYING )      {
824                                 SoundSlots[SoundObjects[i].handle].playing=0;
825                         }
826                 }
827                 SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
828         }
829 }
830 
digi_init_sounds()831 void digi_init_sounds()
832 {
833 //        int i;
834 
835 	if (!digi_initialised) return;
836 
837         digi_reset_digi_sounds();
838 
839 //        for (i=0; i<MAX_SOUND_OBJECTS; i++ )    {
840 //                if (digi_sounds_initialized) {
841 //                        if ( SoundObjects[i].flags & SOF_PLAYING )      {
842 //                                SoundSlots[SoundObjects[i].handle].playing=0;
843 //                        }
844 //                }
845 //                SoundObjects[i].flags = 0;      // Mark as dead, so some other sound can use this sound
846 //        }
847         digi_stop_soundobjects();
848 
849         digi_sounds_initialized = 1;
850 }
851 
852 //added on 980905 by adb from original source to make sfx volume work
digi_set_digi_volume(int dvolume)853 void digi_set_digi_volume( int dvolume )
854 {
855 	dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
856 	if ( dvolume > SOUND_MAX_VOLUME )
857 		digi_volume = SOUND_MAX_VOLUME;
858 	else if ( dvolume < 0 )
859 		digi_volume = 0;
860 	else
861 		digi_volume = dvolume;
862 
863 	if ( !digi_initialised ) return;
864 
865 	digi_sync_sounds();
866 }
867 //end edit by adb
868 
869 //void digi_set_volume( int dvolume, int mvolume ) {}
digi_set_volume(int dvolume,int mvolume)870 void digi_set_volume( int dvolume, int mvolume )
871 {
872  digi_set_midi_volume(mvolume);
873  digi_set_digi_volume(dvolume);
874 }
875 
876 
digi_is_sound_playing(int soundno)877 int digi_is_sound_playing(int soundno)
878 {
879 	int i;
880 
881 	soundno = digi_xlat_sound(soundno);
882 
883 	for (i = 0; i < MAX_SOUND_SLOTS; i++)
884 		  //changed on 980905 by adb: added SoundSlots[i].playing &&
885 		  if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
886 		  //end changes by adb
887 			return 1;
888 	return 0;
889 }
890 
891 
892 //void digi_pause_all() { }
893 //void digi_resume_all() { }
894 //void digi_stop_all() { }
895 
896  //added on 980905 by adb to make sound channel setting work
digi_set_max_channels(int n)897 void digi_set_max_channels(int n) {
898 	digi_max_channels	= n;
899 
900 	if ( digi_max_channels < 1 )
901 		digi_max_channels = 1;
902 	if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) )
903 		digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS);
904 
905 	if ( !digi_initialised ) return;
906 
907 	digi_reset_digi_sounds();
908 }
909 
digi_get_max_channels()910 int digi_get_max_channels() {
911 	return digi_max_channels;
912 }
913 // end edit by adb
914 
digi_reset_digi_sounds()915 void digi_reset_digi_sounds()
916 {
917  int i;
918 
919  for (i=0; i< MAX_SOUND_SLOTS; i++)
920   SoundSlots[i].playing=0;
921 
922  //added on 980905 by adb to reset sound kill system
923  memset(SampleHandles, 255, sizeof(SampleHandles));
924  next_handle = 0;
925  //end edit by adb
926 }
927 
928 int sound_paused = 0;
929 
digi_pause_all()930 void digi_pause_all()
931 {
932        if (!digi_initialised) return;
933        if (sound_paused==0)   {
934                digi_midi_pause();
935                digi_stop_soundobjects();
936        }
937        sound_paused++;
938 }
939 
digi_resume_all()940 void digi_resume_all()
941 {
942        if (!digi_initialised) return;
943 
944        Assert( sound_paused > 0 );
945 
946        if (sound_paused==1)    {
947                digi_midi_resume();
948        }
949        sound_paused--;
950 }
951 
digi_stop_all()952 void digi_stop_all()
953 {
954        if (!digi_initialised) return;
955 
956        digi_midi_stop();
957 
958        digi_stop_soundobjects();
959 }
960 
961 // mikmod stubs...
VC_Init(void)962 BOOL	VC_Init(void) { return 1; }
VC_Exit(void)963 void    VC_Exit(void) { }
VC_SetNumVoices(void)964 BOOL    VC_SetNumVoices(void) { return 0; }
VC_SampleSpace(int type)965 ULONG   VC_SampleSpace(int type) { return 0; }
VC_SampleLength(int type,SAMPLE * s)966 ULONG   VC_SampleLength(int type, SAMPLE *s) { return 0; }
967 
VC_PlayStart(void)968 BOOL    VC_PlayStart(void) { return 0; }
VC_PlayStop(void)969 void    VC_PlayStop(void) { }
970 
971 #if 0
972 SWORD   VC_SampleLoad(SAMPLOAD *sload, int type, FILE *fp) { return 0; }
973 #else
VC_SampleLoad(FILE * fp,ULONG size,ULONG reppos,ULONG repend,UWORD flags)974 SWORD	VC_SampleLoad(FILE *fp,ULONG size,ULONG reppos,ULONG repend,UWORD flags) { return 0; }
975 #endif
VC_SampleUnload(SWORD handle)976 void    VC_SampleUnload(SWORD handle) { }
977 
VC_WriteSamples(SBYTE * buf,ULONG todo)978 void    VC_WriteSamples(SBYTE *buf,ULONG todo) { }
VC_SilenceBytes(SBYTE * buf,ULONG todo)979 void    VC_SilenceBytes(SBYTE *buf,ULONG todo) { }
980 
981 #if 0
982 void	VC_VoiceSetVolume(UBYTE voice, UWORD vol) { }
983 void    VC_VoiceSetPanning(UBYTE voice, ULONG pan) { }
984 #else
VC_VoiceSetVolume(UBYTE voice,UBYTE vol)985 void	VC_VoiceSetVolume(UBYTE voice, UBYTE vol) { }
VC_VoiceSetPanning(UBYTE voice,UBYTE pan)986 void	VC_VoiceSetPanning(UBYTE voice, UBYTE pan) { }
987 #endif
VC_VoiceSetFrequency(UBYTE voice,ULONG frq)988 void    VC_VoiceSetFrequency(UBYTE voice, ULONG frq) { }
VC_VoicePlay(UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags)989 void    VC_VoicePlay(UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags) { }
990 
VC_VoiceStop(UBYTE voice)991 void    VC_VoiceStop(UBYTE voice) { }
VC_VoiceStopped(UBYTE voice)992 BOOL    VC_VoiceStopped(UBYTE voice) { return 0; }
VC_VoiceReleaseSustain(UBYTE voice)993 void    VC_VoiceReleaseSustain(UBYTE voice) { }
VC_VoiceGetPosition(UBYTE voice)994 SLONG   VC_VoiceGetPosition(UBYTE voice) { return 0; }
VC_VoiceRealVolume(UBYTE voice)995 ULONG   VC_VoiceRealVolume(UBYTE voice) { return 0; }
996 char *myerr;
997