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