1 /*
2 * $Source: /cvs/cvsroot/d2x/arch/dos/digi.c,v $
3 * $Revision: 1.3 $
4 * $Author: bradleyb $
5 * $Date: 2001/10/25 08:25:33 $
6 *
7 * DOS digital audio support
8 *
9 * $Log: digi.c,v $
10 * Revision 1.3 2001/10/25 08:25:33 bradleyb
11 * Finished moving stuff to arch/blah. I know, it's ugly, but It'll be easier to sync with d1x.
12 *
13 * Revision 1.3 2001/01/31 14:04:45 bradleyb
14 * Fix compiler warnings
15 *
16 * Revision 1.2 2001/01/29 13:53:28 bradleyb
17 * Fixed build, minor fixes
18 *
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <conf.h>
23 #endif
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28
29 #include "pstypes.h"
30 #include "error.h"
31 #include "mono.h"
32 #include "fix.h"
33 #include "vecmat.h"
34 #include "gr.h" // needed for piggy.h
35 #include "piggy.h"
36 #include "digi.h"
37 #include "sounds.h"
38 #include "wall.h"
39 #include "newdemo.h"
40 #include "kconfig.h"
41
42 int digi_sample_rate=11025;
43 int digi_timer_rate = 9943; // rate for the timer to go off to handle the driver system (120 Hz)
44
45 //edited 05/17/99 Matt Mueller - added ifndef NO_ASM
46 //added on 980905 by adb to add inline fixmul for mixer on i386
47 #ifndef NO_ASM
48 #ifdef __i386__
49 #define do_fixmul(x,y) \
50 ({ \
51 int _ax, _dx; \
52 asm("imull %2\n\tshrdl %3,%1,%0" \
53 : "=a"(_ax), "=d"(_dx) \
54 : "rm"(y), "i"(16), "0"(x)); \
55 _ax; \
56 })
fixmul(fix x,fix y)57 extern inline fix fixmul(fix x, fix y) { return do_fixmul(x,y); }
58 #endif
59 #endif
60 //end edit by adb
61 //end edit -MM
62
63 //changed on 980905 by adb to increase number of concurrent sounds
64 #define MAX_SOUND_SLOTS 32
65 //end changes by adb
66 #define SOUND_BUFFER_SIZE 512
67
68 #define MIN_VOLUME 10
69
70 /* This table is used to add two sound values together and pin
71 * the value to avoid overflow. (used with permission from ARDI)
72 * DPH: Taken from SDL/src/SDL_mixer.c.
73 */
74 static const unsigned char mix8[] =
75 {
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, 0x00, 0x00, 0x00,
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
88 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
89 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
90 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
91 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
92 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
93 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
94 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
95 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B,
96 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
97 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
98 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
99 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
100 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
101 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,
102 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
103 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
104 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
105 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
106 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4,
107 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
108 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
109 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
110 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
122 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
123 };
124
125 #define SOF_USED 1 // Set if this sample is used
126 #define SOF_PLAYING 2 // Set if this sample is playing on a channel
127 #define SOF_LINK_TO_OBJ 4 // Sound is linked to a moving object. If object dies, then finishes play and quits.
128 #define SOF_LINK_TO_POS 8 // Sound is linked to segment, pos
129 #define SOF_PLAY_FOREVER 16 // Play forever (or until level is stopped), otherwise plays once
130
131 typedef struct sound_object {
132 short signature; // A unique signature to this sound
133 ubyte flags; // Used to tell if this slot is used and/or currently playing, and how long.
134 fix max_volume; // Max volume that this sound is playing at
135 fix max_distance; // The max distance that this sound can be heard at...
136 int volume; // Volume that this sound is playing at
137 int pan; // Pan value that this sound is playing at
138 int handle; // What handle this sound is playing on. Valid only if SOF_PLAYING is set.
139 short soundnum; // The sound number that is playing
140 union {
141 struct {
142 short segnum; // Used if SOF_LINK_TO_POS field is used
143 short sidenum;
144 vms_vector position;
145 }pos;
146 struct {
147 short objnum; // Used if SOF_LINK_TO_OBJ field is used
148 short objsignature;
149 }obj;
150 }link;
151 } sound_object;
152 #define lp_segnum link.pos.segnum
153 #define lp_sidenum link.pos.sidenum
154 #define lp_position link.pos.position
155
156 #define lo_objnum link.obj.objnum
157 #define lo_objsignature link.obj.objsignature
158
159 #define MAX_SOUND_OBJECTS 16
160 sound_object SoundObjects[MAX_SOUND_OBJECTS];
161 short next_signature=0;
162
163 //added/changed on 980905 by adb to make sfx volume work, on 990221 by adb changed F1_0 to F1_0 / 2
164 #define SOUND_MAX_VOLUME (F1_0 / 2)
165
166 int digi_volume = SOUND_MAX_VOLUME;
167 //end edit by adb
168
169 int digi_lomem = 0;
170
171 static int digi_initialised = 0;
172
173 struct sound_slot {
174 int soundno;
175 int playing; // Is there a sample playing on this channel?
176 int looped; // Play this sample looped?
177 fix pan; // 0 = far left, 1 = far right
178 fix volume; // 0 = nothing, 1 = fully on
179 //changed on 980905 by adb from char * to unsigned char *
180 unsigned char *samples;
181 //end changes by adb
182 unsigned int length; // Length of the sample
183 unsigned int position; // Position we are at at the moment.
184 } SoundSlots[MAX_SOUND_SLOTS];
185
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
audio_mixcallback(void * userdata,unsigned char * stream,int len)199 static void audio_mixcallback(void *userdata, unsigned char *stream, int len)
200 {
201 unsigned char *streamend = stream + len;
202 struct sound_slot *sl;
203
204 for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++)
205 {
206 if (sl->playing)
207 {
208 unsigned char *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length;
209 unsigned char *sp = stream;
210 signed char v;
211 fix vl, vr;
212 int x;
213
214 if ((x = sl->pan) & 0x8000)
215 {
216 vl = 0x20000 - x * 2;
217 vr = 0x10000;
218 }
219 else
220 {
221 vl = 0x10000;
222 vr = x * 2;
223 }
224 vl = fixmul(vl, (x = sl->volume));
225 vr = fixmul(vr, x);
226 while (sp < streamend)
227 {
228 if (sldata == slend)
229 {
230 if (!sl->looped)
231 {
232 sl->playing = 0;
233 break;
234 }
235 sldata = sl->samples;
236 }
237 v = *(sldata++) - 0x80;
238 *(sp++) = mix8[ *sp + fixmul(v, vl) + 0x80 ];
239 *(sp++) = mix8[ *sp + fixmul(v, vr) + 0x80 ];
240 }
241 sl->position = sldata - sl->samples;
242 }
243 }
244 }
245 //end changes by adb
246
247 /* Initialise audio devices. */
digi_init()248 int digi_init()
249 {
250 /* this is just here now to stop gcc from complaining about
251 * audio_mixcallback being declared static and not used...
252 */
253 if (0) audio_mixcallback(NULL,NULL,0);
254
255 return 1;
256 }
257
258 /* Toggle audio */
digi_reset()259 void digi_reset() { }
260
261 /* Shut down audio */
digi_close()262 void digi_close()
263 {
264 if (!digi_initialised) return;
265 digi_initialised = 0;
266 }
267
268 /* Find the sound which actually equates to a sound number */
digi_xlat_sound(int soundno)269 int digi_xlat_sound(int soundno)
270 {
271 if ( soundno < 0 ) return -1;
272
273 if ( digi_lomem ) {
274 soundno = AltSounds[soundno];
275 if ( soundno == 255 ) return -1;
276 }
277 return Sounds[soundno];
278 }
279
get_free_slot()280 static int get_free_slot()
281 {
282 int i;
283 for (i=0; i<MAX_SOUND_SLOTS; i++)
284 {
285 if (!SoundSlots[i].playing) return i;
286 }
287 return -1;
288 }
289
digi_start_sound(int soundnum,fix volume,fix pan,int unknown1,int unknown2,int unknown3,int unknown4)290 int digi_start_sound(int soundnum, fix volume, fix pan, int unknown1, int unknown2, int unknown3, int unknown4)
291 {
292 int ntries;
293 int slot;
294
295 if (!digi_initialised) return -1;
296
297 //added on 980905 by adb from original source to add sound kill system
298 // play at most digi_max_channel samples, if possible kill sample with low volume
299 ntries = 0;
300
301 TryNextChannel:
302 if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing) )
303 {
304 if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries<digi_max_channels) )
305 {
306 //mprintf(( 0, "Not stopping loud sound %d.\n", next_handle ));
307 next_handle++;
308 if ( next_handle >= digi_max_channels )
309 next_handle = 0;
310 ntries++;
311 goto TryNextChannel;
312 }
313 //mprintf(( 0, "[SS:%d]", next_handle ));
314 SoundSlots[SampleHandles[next_handle]].playing = 0;
315 SampleHandles[next_handle] = -1;
316 }
317 //end edit by adb
318
319 slot = get_free_slot();
320 if (slot<0) return -1;
321
322 SoundSlots[slot].soundno = soundnum;
323 SoundSlots[slot].samples = GameSounds[soundnum].data;
324 SoundSlots[slot].length = GameSounds[soundnum].length;
325 SoundSlots[slot].volume = fixmul(digi_volume, volume);
326 SoundSlots[slot].pan = pan;
327 SoundSlots[slot].position = 0;
328 SoundSlots[slot].looped = 0;
329 SoundSlots[slot].playing = 1;
330
331 //added on 980905 by adb to add sound kill system from original sos digi.c
332 reset_sounds_on_channel(slot);
333 SampleHandles[next_handle] = slot;
334 next_handle++;
335 if ( next_handle >= digi_max_channels )
336 next_handle = 0;
337 //end edit by adb
338
339 return slot;
340 }
341
342 //added on 980905 by adb to add sound kill system from original sos digi.c
reset_sounds_on_channel(int channel)343 void reset_sounds_on_channel( int channel )
344 {
345 int i;
346
347 for (i=0; i<digi_max_channels; i++)
348 if (SampleHandles[i] == channel)
349 SampleHandles[i] = -1;
350 }
351 //end edit by adb
352
digi_start_sound_object(int obj)353 int digi_start_sound_object(int obj)
354 {
355 int slot;
356
357 if (!digi_initialised) return -1;
358 slot = get_free_slot();
359
360 if (slot<0) return -1;
361
362
363 SoundSlots[slot].soundno = SoundObjects[obj].soundnum;
364 SoundSlots[slot].samples = GameSounds[SoundObjects[obj].soundnum].data;
365 SoundSlots[slot].length = GameSounds[SoundObjects[obj].soundnum].length;
366 SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume);
367 SoundSlots[slot].pan = SoundObjects[obj].pan;
368 SoundSlots[slot].position = 0;
369 SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER);
370 SoundSlots[slot].playing = 1;
371
372 SoundObjects[obj].signature = next_signature++;
373 SoundObjects[obj].handle = slot;
374
375 SoundObjects[obj].flags |= SOF_PLAYING;
376 //added on 980905 by adb to add sound kill system from original sos digi.c
377 reset_sounds_on_channel(slot);
378 //end edit by adb
379
380 return 0;
381 }
382
383
384 // Play the given sound number.
385 // Volume is max at F1_0.
digi_play_sample(int soundno,fix max_volume)386 void digi_play_sample( int soundno, fix max_volume )
387 {
388 #ifdef NEWDEMO
389 if ( Newdemo_state == ND_STATE_RECORDING )
390 newdemo_record_sound( soundno );
391 #endif
392 soundno = digi_xlat_sound(soundno);
393
394 if (!digi_initialised) return;
395
396 if (soundno < 0 ) return;
397
398 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
399 }
400
401 // Play the given sound number. If the sound is already playing,
402 // restart it.
digi_play_sample_once(int soundno,fix max_volume)403 void digi_play_sample_once( int soundno, fix max_volume )
404 {
405 int i;
406
407 #ifdef NEWDEMO
408 if ( Newdemo_state == ND_STATE_RECORDING )
409 newdemo_record_sound( soundno );
410 #endif
411 soundno = digi_xlat_sound(soundno);
412
413 if (!digi_initialised) return;
414
415 if (soundno < 0 ) return;
416
417 for (i=0; i < MAX_SOUND_SLOTS; i++)
418 if (SoundSlots[i].soundno == soundno)
419 SoundSlots[i].playing = 0;
420 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
421
422 }
423
digi_play_sample_3d(int soundno,int angle,int volume,int no_dups)424 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) // Volume from 0-0x7fff
425 {
426 no_dups = 1;
427
428 #ifdef NEWDEMO
429 if ( Newdemo_state == ND_STATE_RECORDING ) {
430 if ( no_dups )
431 newdemo_record_sound_3d_once( soundno, angle, volume );
432 else
433 newdemo_record_sound_3d( soundno, angle, volume );
434 }
435 #endif
436 soundno = digi_xlat_sound(soundno);
437
438 if (!digi_initialised) return;
439 if (soundno < 0 ) return;
440
441 if (volume < MIN_VOLUME ) return;
442 digi_start_sound(soundno, volume, angle, 0, 0, 0, 0);
443 }
444
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)445 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 )
446 {
447 vms_vector vector_to_sound;
448 fix angle_from_ear, cosang,sinang;
449 fix distance;
450 fix path_distance;
451
452 *volume = 0;
453 *pan = 0;
454
455 max_distance = (max_distance*5)/4; // Make all sounds travel 1.25 times as far.
456
457 // Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
458 distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
459
460 if (distance < max_distance ) {
461 int num_search_segs = f2i(max_distance/20);
462 if ( num_search_segs < 1 ) num_search_segs = 1;
463
464 path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
465 if ( path_distance > -1 ) {
466 *volume = max_volume - fixdiv(path_distance,max_distance);
467 //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
468 if (*volume > 0 ) {
469 angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
470 fix_sincos(angle_from_ear,&sinang,&cosang);
471 //mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
472 if (Config_channels_reversed) cosang *= -1;
473 *pan = (cosang + F1_0)/2;
474 } else {
475 *volume = 0;
476 }
477 }
478 }
479 }
480
digi_link_sound_to_object2(int org_soundnum,short objnum,int forever,fix max_volume,fix max_distance)481 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance )
482 {
483 int i,volume,pan;
484 object * objp;
485 int soundnum;
486
487 soundnum = digi_xlat_sound(org_soundnum);
488
489 if ( max_volume < 0 ) return -1;
490 // if ( max_volume > F1_0 ) max_volume = F1_0;
491
492 if (!digi_initialised) return -1;
493 if (soundnum < 0 ) return -1;
494 if (GameSounds[soundnum].data==NULL) {
495 Int3();
496 return -1;
497 }
498 if ((objnum<0)||(objnum>Highest_object_index))
499 return -1;
500
501 if ( !forever ) {
502 // Hack to keep sounds from building up...
503 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
504 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
505 return -1;
506 }
507
508 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
509 if (SoundObjects[i].flags==0)
510 break;
511
512 if (i==MAX_SOUND_OBJECTS) {
513 mprintf((1, "Too many sound objects!\n" ));
514 return -1;
515 }
516
517 SoundObjects[i].signature=next_signature++;
518 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
519 if ( forever )
520 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
521 SoundObjects[i].lo_objnum = objnum;
522 SoundObjects[i].lo_objsignature = Objects[objnum].signature;
523 SoundObjects[i].max_volume = max_volume;
524 SoundObjects[i].max_distance = max_distance;
525 SoundObjects[i].volume = 0;
526 SoundObjects[i].pan = 0;
527 SoundObjects[i].soundnum = soundnum;
528
529 objp = &Objects[SoundObjects[i].lo_objnum];
530 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
531 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
532 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
533
534 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
535 digi_start_sound_object(i);
536
537 return SoundObjects[i].signature;
538 }
539
digi_link_sound_to_object(int soundnum,short objnum,int forever,fix max_volume)540 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
541 { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); }
542
digi_link_sound_to_pos2(int org_soundnum,short segnum,short sidenum,vms_vector * pos,int forever,fix max_volume,fix max_distance)543 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
544 {
545 int i, volume, pan;
546 int soundnum;
547
548 soundnum = digi_xlat_sound(org_soundnum);
549
550 if ( max_volume < 0 ) return -1;
551 // if ( max_volume > F1_0 ) max_volume = F1_0;
552
553 if (!digi_initialised) return -1;
554 if (soundnum < 0 ) return -1;
555 if (GameSounds[soundnum].data==NULL) {
556 Int3();
557 return -1;
558 }
559
560 if ((segnum<0)||(segnum>Highest_segment_index))
561 return -1;
562
563 if ( !forever ) {
564 // Hack to keep sounds from building up...
565 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
566 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
567 return -1;
568 }
569
570 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
571 if (SoundObjects[i].flags==0)
572 break;
573
574 if (i==MAX_SOUND_OBJECTS) {
575 mprintf((1, "Too many sound objects!\n" ));
576 return -1;
577 }
578
579
580 SoundObjects[i].signature=next_signature++;
581 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
582 if ( forever )
583 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
584 SoundObjects[i].lp_segnum = segnum;
585 SoundObjects[i].lp_sidenum = sidenum;
586 SoundObjects[i].lp_position = *pos;
587 SoundObjects[i].soundnum = soundnum;
588 SoundObjects[i].max_volume = max_volume;
589 SoundObjects[i].max_distance = max_distance;
590 SoundObjects[i].volume = 0;
591 SoundObjects[i].pan = 0;
592 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
593 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
594 SoundObjects[i].max_volume,
595 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
596
597 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
598 digi_start_sound_object(i);
599
600 return SoundObjects[i].signature;
601 }
602
digi_link_sound_to_pos(int soundnum,short segnum,short sidenum,vms_vector * pos,int forever,fix max_volume)603 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
604 {
605 return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
606 }
607
digi_kill_sound_linked_to_segment(int segnum,int sidenum,int soundnum)608 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
609 {
610 int i,killed;
611
612 soundnum = digi_xlat_sound(soundnum);
613
614 if (!digi_initialised) return;
615
616 killed = 0;
617
618 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
619 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) ) {
620 if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
621 if ( SoundObjects[i].flags & SOF_PLAYING ) {
622 SoundSlots[SoundObjects[i].handle].playing = 0;
623 }
624 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
625 killed++;
626 }
627 }
628 }
629 // If this assert happens, it means that there were 2 sounds
630 // that got deleted. Weird, get John.
631 if ( killed > 1 ) {
632 mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
633 }
634 }
635
digi_kill_sound_linked_to_object(int objnum)636 void digi_kill_sound_linked_to_object( int objnum )
637 {
638 int i,killed;
639
640 if (!digi_initialised) return;
641
642 killed = 0;
643
644 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
645 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) ) {
646 if (SoundObjects[i].lo_objnum == objnum) {
647 if ( SoundObjects[i].flags & SOF_PLAYING ) {
648 SoundSlots[SoundObjects[i].handle].playing = 0;
649 }
650 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
651 killed++;
652 }
653 }
654 }
655 // If this assert happens, it means that there were 2 sounds
656 // that got deleted. Weird, get John.
657 if ( killed > 1 ) {
658 mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
659 }
660 }
661
digi_sync_sounds()662 void digi_sync_sounds()
663 {
664 int i;
665 int oldvolume, oldpan;
666
667 if (!digi_initialised) return;
668
669 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
670 if ( SoundObjects[i].flags & SOF_USED ) {
671 oldvolume = SoundObjects[i].volume;
672 oldpan = SoundObjects[i].pan;
673
674 if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) ) {
675 // Check if its done.
676 if (SoundObjects[i].flags & SOF_PLAYING) {
677 if (!SoundSlots[SoundObjects[i].handle].playing) {
678 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
679 continue; // Go on to next sound...
680 }
681 }
682 }
683
684 if ( SoundObjects[i].flags & SOF_LINK_TO_POS ) {
685 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
686 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
687 SoundObjects[i].max_volume,
688 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
689
690 } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) {
691 object * objp;
692
693 objp = &Objects[SoundObjects[i].lo_objnum];
694
695 if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature)) {
696 // The object that this is linked to is dead, so just end this sound if it is looping.
697 if ( (SoundObjects[i].flags & SOF_PLAYING) && (SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
698 SoundSlots[SoundObjects[i].handle].playing = 0;
699 }
700 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
701 continue; // Go on to next sound...
702 } else {
703 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
704 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
705 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
706 }
707 }
708
709 if (oldvolume != SoundObjects[i].volume) {
710 if ( SoundObjects[i].volume < MIN_VOLUME ) {
711 // Sound is too far away, so stop it from playing.
712 if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
713 SoundSlots[SoundObjects[i].handle].playing = 0;
714 SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing
715 }
716 } else {
717 if (!(SoundObjects[i].flags & SOF_PLAYING)) {
718 digi_start_sound_object(i);
719 } else {
720 SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0);
721 }
722 }
723 }
724
725 if (oldpan != SoundObjects[i].pan) {
726 if (SoundObjects[i].flags & SOF_PLAYING)
727 SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan;
728 }
729 }
730 }
731 }
732
digi_init_sounds()733 void digi_init_sounds()
734 {
735 int i;
736
737 if (!digi_initialised) return;
738
739 digi_reset_digi_sounds();
740
741 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
742 if (digi_sounds_initialized) {
743 if ( SoundObjects[i].flags & SOF_PLAYING ) {
744 SoundSlots[SoundObjects[i].handle].playing=0;
745 }
746 }
747 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
748 }
749 digi_sounds_initialized = 1;
750 }
751
752 //added on 980905 by adb from original source to make sfx volume work
digi_set_digi_volume(int dvolume)753 void digi_set_digi_volume( int dvolume )
754 {
755 dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
756 if ( dvolume > SOUND_MAX_VOLUME )
757 digi_volume = SOUND_MAX_VOLUME;
758 else if ( dvolume < 0 )
759 digi_volume = 0;
760 else
761 digi_volume = dvolume;
762
763 if ( !digi_initialised ) return;
764
765 digi_sync_sounds();
766 }
767 //end edit by adb
768
digi_set_volume(int dvolume,int mvolume)769 void digi_set_volume( int dvolume, int mvolume ) { }
770
digi_is_sound_playing(int soundno)771 int digi_is_sound_playing(int soundno)
772 {
773 int i;
774
775 soundno = digi_xlat_sound(soundno);
776
777 for (i = 0; i < MAX_SOUND_SLOTS; i++)
778 //changed on 980905 by adb: added SoundSlots[i].playing &&
779 if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
780 //end changes by adb
781 return 1;
782 return 0;
783 }
784
785
digi_pause_all()786 void digi_pause_all() { }
digi_resume_all()787 void digi_resume_all() { }
digi_stop_all()788 void digi_stop_all() { }
789
790 //added on 980905 by adb to make sound channel setting work
digi_set_max_channels(int n)791 void digi_set_max_channels(int n) {
792 digi_max_channels = n;
793
794 if ( digi_max_channels < 1 )
795 digi_max_channels = 1;
796 if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) )
797 digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS);
798
799 if ( !digi_initialised ) return;
800
801 digi_reset_digi_sounds();
802 }
803
digi_get_max_channels()804 int digi_get_max_channels() {
805 return digi_max_channels;
806 }
807 // end edit by adb
808
digi_reset_digi_sounds()809 void digi_reset_digi_sounds() {
810 int i;
811
812 for (i=0; i< MAX_SOUND_SLOTS; i++)
813 SoundSlots[i].playing=0;
814
815 //added on 980905 by adb to reset sound kill system
816 memset(SampleHandles, 255, sizeof(SampleHandles));
817 next_handle = 0;
818 //end edit by adb
819 }
820
821
822 // MIDI stuff follows.
823 //added/killed on 11/25/98 by Matthew Mueller
824 //void digi_set_midi_volume( int mvolume ) { }
825 //void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
826 //void digi_stop_current_song()
827 //{
828 //#ifdef HMIPLAY
829 // char buf[10];
830 //
831 // sprintf(buf,"s");
832 // send_ipc(buf);
833 //#endif
834 //}
835 //end this section kill - MM
836