1 /* $Id: digi.c,v 1.16 2004-05-19 03:13:44 btb Exp $ */
4 * SDL digital audio support
24 #include "gr.h" // needed for piggy.h
32 int digi_sample_rate = SAMPLE_RATE_11K;
34 //edited 05/17/99 Matt Mueller - added ifndef NO_ASM
35 //added on 980905 by adb to add inline fixmul for mixer on i386
38 #define do_fixmul(x,y) \
41 asm("imull %2\n\tshrdl %3,%1,%0" \
42 : "=a"(_ax), "=d"(_dx) \
43 : "rm"(y), "i"(16), "0"(x)); \
46 extern inline fix fixmul(fix x, fix y) { return do_fixmul(x,y); }
52 //changed on 980905 by adb to increase number of concurrent sounds
53 #define MAX_SOUND_SLOTS 32
55 #define SOUND_BUFFER_SIZE 512
59 /* This table is used to add two sound values together and pin
60 * the value to avoid overflow. (used with permission from ARDI)
61 * DPH: Taken from SDL/src/SDL_mixer.c.
63 static const Uint8 mix8[] =
65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
77 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
78 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
79 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
80 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
81 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
82 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
83 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
84 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B,
85 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
86 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
87 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
88 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
89 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
90 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,
91 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
92 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
93 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
94 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
95 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4,
96 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
97 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
98 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
99 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xFF,
100 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
101 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
102 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
103 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
104 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
105 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
106 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
107 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
108 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
109 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
110 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
111 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
114 #define SOF_USED 1 // Set if this sample is used
115 #define SOF_PLAYING 2 // Set if this sample is playing on a channel
116 #define SOF_LINK_TO_OBJ 4 // Sound is linked to a moving object. If object dies, then finishes play and quits.
117 #define SOF_LINK_TO_POS 8 // Sound is linked to segment, pos
118 #define SOF_PLAY_FOREVER 16 // Play forever (or until level is stopped), otherwise plays once
119 #define SOF_PERMANANT 32 // Part of the level, like a waterfall or fan
121 typedef struct sound_object {
122 short signature; // A unique signature to this sound
123 ubyte flags; // Used to tell if this slot is used and/or currently playing, and how long.
125 ubyte pad; // needed for alignment
127 fix max_volume; // Max volume that this sound is playing at
128 fix max_distance; // The max distance that this sound can be heard at...
129 int volume; // Volume that this sound is playing at
130 int pan; // Pan value that this sound is playing at
131 int handle; // What handle this sound is playing on. Valid only if SOF_PLAYING is set.
132 short soundnum; // The sound number that is playing
134 short pad2; // needed for alignment
136 int loop_start; // The start point of the loop. -1 means no loop
137 int loop_end; // The end point of the loop
140 short segnum; // Used if SOF_LINK_TO_POS field is used
145 short objnum; // Used if SOF_LINK_TO_OBJ field is used
150 #define lp_segnum link.pos.segnum
151 #define lp_sidenum link.pos.sidenum
152 #define lp_position link.pos.position
154 #define lo_objnum link.obj.objnum
155 #define lo_objsignature link.obj.objsignature
157 #define MAX_SOUND_OBJECTS 16
158 sound_object SoundObjects[MAX_SOUND_OBJECTS];
159 short next_signature=0;
161 //added/changed on 980905 by adb to make sfx volume work, on 990221 by adb changed F1_0 to F1_0 / 2
162 #define SOUND_MAX_VOLUME (F1_0 / 2)
164 int digi_volume = SOUND_MAX_VOLUME;
169 static int digi_initialised = 0;
173 int playing; // Is there a sample playing on this channel?
174 int looped; // Play this sample looped?
175 fix pan; // 0 = far left, 1 = far right
176 fix volume; // 0 = nothing, 1 = fully on
177 //changed on 980905 by adb from char * to unsigned char *
178 unsigned char *samples;
180 unsigned int length; // Length of the sample
181 unsigned int position; // Position we are at at the moment.
182 } SoundSlots[MAX_SOUND_SLOTS];
184 static SDL_AudioSpec WaveSpec;
185 static int digi_sounds_initialized = 0;
187 //added on 980905 by adb to add rotating/volume based sound kill system
188 static int digi_max_channels = 16;
189 static int next_handle = 0;
190 int SampleHandles[32];
191 void reset_sounds_on_channel(int channel);
194 void digi_reset_digi_sounds(void);
196 /* Audio mixing callback */
197 //changed on 980905 by adb to cleanup, add pan support and optimize mixer
198 static void audio_mixcallback(void *userdata, Uint8 *stream, int len)
200 Uint8 *streamend = stream + len;
201 struct sound_slot *sl;
203 if (!digi_initialised)
206 memset(stream, 0x80, len); // fix "static" sound bug on Mac OS X
208 for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++) {
210 Uint8 *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length;
211 Uint8 *sp = stream, s;
216 if ((x = sl->pan) & 0x8000) {
217 vl = 0x20000 - x * 2;
223 vl = fixmul(vl, (x = sl->volume));
225 while (sp < streamend) {
226 if (sldata == slend) {
231 sldata = sl->samples;
233 v = *(sldata++) - 0x80;
235 *(sp++) = mix8[ s + fixmul(v, vl) + 0x80 ];
237 *(sp++) = mix8[ s + fixmul(v, vr) + 0x80 ];
239 sl->position = sldata - sl->samples;
245 /* Initialise audio devices. */
248 if (SDL_InitSubSystem(SDL_INIT_AUDIO)<0) {
249 Error("SDL audio initialisation failed: %s.",SDL_GetError());
251 //added on 980905 by adb to init sound kill system
252 memset(SampleHandles, 255, sizeof(SampleHandles));
255 WaveSpec.freq = digi_sample_rate;
256 //added/changed by Sam Lantinga on 12/01/98 for new SDL version
257 WaveSpec.format = AUDIO_U8;
258 WaveSpec.channels = 2;
259 //end this section addition/change - SL
260 WaveSpec.samples = SOUND_BUFFER_SIZE;
261 WaveSpec.callback = audio_mixcallback;
263 if ( SDL_OpenAudio(&WaveSpec, NULL) < 0 ) {
264 //edited on 10/05/98 by Matt Mueller - should keep running, just with no sound.
265 Warning("\nError: Couldn't open audio: %s\n", SDL_GetError());
273 digi_initialised = 1;
278 void digi_reset() { }
280 /* Shut down audio */
283 if (!digi_initialised) return;
284 digi_initialised = 0;
288 /* Find the sound which actually equates to a sound number */
289 int digi_xlat_sound(int soundno)
291 if ( soundno < 0 ) return -1;
294 soundno = AltSounds[soundno];
295 if ( soundno == 255 ) return -1;
297 if (Sounds[soundno] == 255) return -1;
299 return Sounds[soundno];
302 static int get_free_slot()
305 for (i=0; i<MAX_SOUND_SLOTS; i++) {
306 if (!SoundSlots[i].playing) return i;
311 int digi_start_sound(int soundnum, fix volume, fix pan, int looping, int loop_start, int loop_end, int soundobj)
316 if (!digi_initialised) return -1;
318 if (soundnum < 0) return -1;
320 //added on 980905 by adb from original source to add sound kill system
321 // play at most digi_max_channel samples, if possible kill sample with low volume
325 if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing) ) {
326 if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries<digi_max_channels) ) {
327 //mprintf(( 0, "Not stopping loud sound %d.\n", next_handle ));
329 if ( next_handle >= digi_max_channels )
334 //mprintf(( 0, "[SS:%d]", next_handle ));
335 SoundSlots[SampleHandles[next_handle]].playing = 0;
336 SampleHandles[next_handle] = -1;
340 slot = get_free_slot();
341 if (slot<0) return -1;
343 SoundSlots[slot].soundno = soundnum;
344 SoundSlots[slot].samples = GameSounds[soundnum].data;
345 SoundSlots[slot].length = GameSounds[soundnum].length;
346 SoundSlots[slot].volume = fixmul(digi_volume, volume);
347 SoundSlots[slot].pan = pan;
348 SoundSlots[slot].position = 0;
349 SoundSlots[slot].looped = looping;
350 SoundSlots[slot].playing = 1;
352 //added on 980905 by adb to add sound kill system from original sos digi.c
353 reset_sounds_on_channel(slot);
354 SampleHandles[next_handle] = slot;
356 if ( next_handle >= digi_max_channels )
363 //added on 980905 by adb to add sound kill system from original sos digi.c
364 void reset_sounds_on_channel( int channel )
368 for (i=0; i<digi_max_channels; i++)
369 if (SampleHandles[i] == channel)
370 SampleHandles[i] = -1;
374 int digi_start_sound_object(int obj)
378 if (!digi_initialised) return -1;
379 slot = get_free_slot();
381 if (slot<0) return -1;
384 // only use up to half the sound channels for "permanant" sounts
385 if ((SoundObjects[i].flags & SOF_PERMANANT) && (N_active_sound_objects >= max(1,digi_get_max_channels()/4)) )
389 SoundSlots[slot].soundno = SoundObjects[obj].soundnum;
390 SoundSlots[slot].samples = GameSounds[SoundObjects[obj].soundnum].data;
391 SoundSlots[slot].length = GameSounds[SoundObjects[obj].soundnum].length;
392 SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume);
393 SoundSlots[slot].pan = SoundObjects[obj].pan;
394 SoundSlots[slot].position = 0;
395 SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER);
396 SoundSlots[slot].playing = 1;
398 SoundObjects[obj].signature = next_signature++;
399 SoundObjects[obj].handle = slot;
401 SoundObjects[obj].flags |= SOF_PLAYING;
402 //added on 980905 by adb to add sound kill system from original sos digi.c
403 reset_sounds_on_channel(slot);
410 // Play the given sound number.
411 // Volume is max at F1_0.
412 void digi_play_sample( int soundno, fix max_volume )
415 if ( Newdemo_state == ND_STATE_RECORDING )
416 newdemo_record_sound( soundno );
418 soundno = digi_xlat_sound(soundno);
420 if (!digi_initialised) return;
422 if (soundno < 0 ) return;
424 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
427 // Play the given sound number. If the sound is already playing,
429 void digi_play_sample_once( int soundno, fix max_volume )
434 if ( Newdemo_state == ND_STATE_RECORDING )
435 newdemo_record_sound( soundno );
437 soundno = digi_xlat_sound(soundno);
439 if (!digi_initialised) return;
441 if (soundno < 0 ) return;
443 for (i=0; i < MAX_SOUND_SLOTS; i++)
444 if (SoundSlots[i].soundno == soundno)
445 SoundSlots[i].playing = 0;
446 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
450 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) // Volume from 0-0x7fff
455 if ( Newdemo_state == ND_STATE_RECORDING ) {
457 newdemo_record_sound_3d_once( soundno, angle, volume );
459 newdemo_record_sound_3d( soundno, angle, volume );
462 soundno = digi_xlat_sound(soundno);
464 if (!digi_initialised) return;
465 if (soundno < 0 ) return;
467 if (volume < MIN_VOLUME ) return;
468 digi_start_sound(soundno, volume, angle, 0, 0, 0, 0);
471 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 )
473 vms_vector vector_to_sound;
474 fix angle_from_ear, cosang,sinang;
481 max_distance = (max_distance*5)/4; // Make all sounds travel 1.25 times as far.
483 // Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
484 distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
486 if (distance < max_distance ) {
487 int num_search_segs = f2i(max_distance/20);
488 if ( num_search_segs < 1 ) num_search_segs = 1;
490 path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
491 if ( path_distance > -1 ) {
492 *volume = max_volume - fixdiv(path_distance,max_distance);
493 //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
495 angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
496 fix_sincos(angle_from_ear,&sinang,&cosang);
497 //mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
498 if (Config_channels_reversed) cosang *= -1;
499 *pan = (cosang + F1_0)/2;
507 //hack to not start object when loading level
508 int Dont_start_sound_objects = 0;
510 int digi_link_sound_to_object3( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance, int loop_start, int loop_end )
516 soundnum = digi_xlat_sound(org_soundnum);
518 if ( max_volume < 0 ) return -1;
519 // if ( max_volume > F1_0 ) max_volume = F1_0;
521 if (!digi_initialised) return -1;
522 if (soundnum < 0 ) return -1;
523 if (GameSounds[soundnum].data==NULL) {
527 if ((objnum<0)||(objnum>Highest_object_index))
531 // Hack to keep sounds from building up...
532 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
533 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
538 if ( Newdemo_state == ND_STATE_RECORDING ) {
539 newdemo_record_link_sound_to_object3( org_soundnum, objnum, max_volume, max_distance, loop_start, loop_end );
543 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
544 if (SoundObjects[i].flags==0)
547 if (i==MAX_SOUND_OBJECTS) {
548 mprintf((1, "Too many sound objects!\n" ));
552 SoundObjects[i].signature=next_signature++;
553 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
555 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
556 SoundObjects[i].lo_objnum = objnum;
557 SoundObjects[i].lo_objsignature = Objects[objnum].signature;
558 SoundObjects[i].max_volume = max_volume;
559 SoundObjects[i].max_distance = max_distance;
560 SoundObjects[i].volume = 0;
561 SoundObjects[i].pan = 0;
562 SoundObjects[i].soundnum = soundnum;
563 SoundObjects[i].loop_start = loop_start;
564 SoundObjects[i].loop_end = loop_end;
566 if (Dont_start_sound_objects) { //started at level start
568 SoundObjects[i].flags |= SOF_PERMANANT;
569 SoundObjects[i].handle = -1;
571 objp = &Objects[SoundObjects[i].lo_objnum];
572 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
573 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
574 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
576 //if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
577 digi_start_sound_object(i);
579 // If it's a one-shot sound effect, and it can't start right away, then
580 // just cancel it and be done with it.
581 if ( (SoundObjects[i].handle < 0) && (!(SoundObjects[i].flags & SOF_PLAY_FOREVER)) ) {
582 SoundObjects[i].flags = 0;
587 return SoundObjects[i].signature;
591 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance )
593 return digi_link_sound_to_object3( org_soundnum, objnum, forever, max_volume, max_distance, -1, -1 );
597 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
598 { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); }
600 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
605 soundnum = digi_xlat_sound(org_soundnum);
607 if ( max_volume < 0 ) return -1;
608 // if ( max_volume > F1_0 ) max_volume = F1_0;
610 if (!digi_initialised) return -1;
611 if (soundnum < 0 ) return -1;
612 if (GameSounds[soundnum].data==NULL) {
617 if ((segnum<0)||(segnum>Highest_segment_index))
621 // Hack to keep sounds from building up...
622 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
623 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
627 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
628 if (SoundObjects[i].flags==0)
631 if (i==MAX_SOUND_OBJECTS) {
632 mprintf((1, "Too many sound objects!\n" ));
637 SoundObjects[i].signature=next_signature++;
638 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
640 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
641 SoundObjects[i].lp_segnum = segnum;
642 SoundObjects[i].lp_sidenum = sidenum;
643 SoundObjects[i].lp_position = *pos;
644 SoundObjects[i].soundnum = soundnum;
645 SoundObjects[i].max_volume = max_volume;
646 SoundObjects[i].max_distance = max_distance;
647 SoundObjects[i].volume = 0;
648 SoundObjects[i].pan = 0;
649 SoundObjects[i].loop_start = SoundObjects[i].loop_end = -1;
651 if (Dont_start_sound_objects) { //started at level start
653 SoundObjects[i].flags |= SOF_PERMANANT;
655 SoundObjects[i].handle = -1;
658 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
659 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
660 SoundObjects[i].max_volume,
661 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
663 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
664 digi_start_sound_object(i);
666 // If it's a one-shot sound effect, and it can't start right away, then
667 // just cancel it and be done with it.
668 if ( (SoundObjects[i].handle < 0) && (!(SoundObjects[i].flags & SOF_PLAY_FOREVER)) ) {
669 SoundObjects[i].flags = 0;
674 return SoundObjects[i].signature;
677 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
679 return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
682 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
686 soundnum = digi_xlat_sound(soundnum);
688 if (!digi_initialised) return;
692 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
693 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) ) {
694 if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
695 if ( SoundObjects[i].flags & SOF_PLAYING ) {
696 SoundSlots[SoundObjects[i].handle].playing = 0;
698 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
703 // If this assert happens, it means that there were 2 sounds
704 // that got deleted. Weird, get John.
706 mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
710 void digi_kill_sound_linked_to_object( int objnum )
714 if (!digi_initialised) return;
718 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
719 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) ) {
720 if (SoundObjects[i].lo_objnum == objnum) {
721 if ( SoundObjects[i].flags & SOF_PLAYING ) {
722 SoundSlots[SoundObjects[i].handle].playing = 0;
724 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
729 // If this assert happens, it means that there were 2 sounds
730 // that got deleted. Weird, get John.
732 mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
736 void digi_sync_sounds()
739 int oldvolume, oldpan;
741 if (!digi_initialised) return;
743 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
744 if ( SoundObjects[i].flags & SOF_USED ) {
745 oldvolume = SoundObjects[i].volume;
746 oldpan = SoundObjects[i].pan;
748 if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) ) {
749 // Check if its done.
750 if (SoundObjects[i].flags & SOF_PLAYING) {
751 if (!SoundSlots[SoundObjects[i].handle].playing) {
752 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
753 continue; // Go on to next sound...
758 if ( SoundObjects[i].flags & SOF_LINK_TO_POS ) {
759 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
760 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
761 SoundObjects[i].max_volume,
762 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
764 } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) {
767 objp = &Objects[SoundObjects[i].lo_objnum];
769 if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature)) {
770 // The object that this is linked to is dead, so just end this sound if it is looping.
771 if ( (SoundObjects[i].flags & SOF_PLAYING) && (SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
772 SoundSlots[SoundObjects[i].handle].playing = 0;
774 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
775 continue; // Go on to next sound...
777 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
778 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
779 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
783 if (oldvolume != SoundObjects[i].volume) {
784 if ( SoundObjects[i].volume < MIN_VOLUME ) {
785 // Sound is too far away, so stop it from playing.
786 if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
787 SoundSlots[SoundObjects[i].handle].playing = 0;
788 SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing
791 if (!(SoundObjects[i].flags & SOF_PLAYING)) {
792 digi_start_sound_object(i);
794 SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0);
799 if (oldpan != SoundObjects[i].pan) {
800 if (SoundObjects[i].flags & SOF_PLAYING)
801 SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan;
807 void digi_init_sounds()
811 if (!digi_initialised) return;
813 digi_reset_digi_sounds();
815 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
816 if (digi_sounds_initialized) {
817 if ( SoundObjects[i].flags & SOF_PLAYING ) {
818 SoundSlots[SoundObjects[i].handle].playing=0;
821 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
823 digi_sounds_initialized = 1;
826 //added on 980905 by adb from original source to make sfx volume work
827 void digi_set_digi_volume( int dvolume )
829 dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
830 if ( dvolume > SOUND_MAX_VOLUME )
831 digi_volume = SOUND_MAX_VOLUME;
832 else if ( dvolume < 0 )
835 digi_volume = dvolume;
837 if ( !digi_initialised ) return;
843 void digi_set_volume( int dvolume, int mvolume )
845 digi_set_digi_volume(dvolume);
846 digi_set_midi_volume(mvolume);
847 // mprintf(( 1, "Volume: 0x%x and 0x%x\n", digi_volume, midi_volume ));
850 int digi_is_sound_playing(int soundno)
854 soundno = digi_xlat_sound(soundno);
856 for (i = 0; i < MAX_SOUND_SLOTS; i++)
857 //changed on 980905 by adb: added SoundSlots[i].playing &&
858 if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
865 void digi_pause_all() { }
866 void digi_resume_all() { }
867 void digi_stop_all() {
869 // ... Ano. The lack of this was causing ambient sounds to crash.
870 // fixed, added digi_stop_all 07/19/01 - bluecow
872 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
873 if ( SoundObjects[i].flags & SOF_USED ) {
874 SoundSlots[SoundObjects[i].handle].playing = 0;
875 SoundObjects[i].flags = 0;
880 //added on 980905 by adb to make sound channel setting work
881 void digi_set_max_channels(int n) {
882 digi_max_channels = n;
884 if ( digi_max_channels < 1 )
885 digi_max_channels = 1;
886 if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) )
887 digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS);
889 if ( !digi_initialised ) return;
891 digi_reset_digi_sounds();
894 int digi_get_max_channels() {
895 return digi_max_channels;
899 void digi_stop_sound(int channel)
901 //FIXME: Is this correct? I dunno, it works.
902 SoundSlots[channel].playing=0;
905 void digi_reset_digi_sounds() {
908 for (i=0; i< MAX_SOUND_SLOTS; i++)
909 SoundSlots[i].playing=0;
911 //added on 980905 by adb to reset sound kill system
912 memset(SampleHandles, 255, sizeof(SampleHandles));
918 #if 0 //added/killed on 11/25/98 by Matthew Mueller
919 // MIDI stuff follows.
920 void digi_set_midi_volume( int mvolume ) { }
921 void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
922 void digi_stop_current_song()
931 #endif // end this section kill - MM