1 /* $Id: digi.c,v 1.8 2003-03-20 03:21:11 btb Exp $ */
4 * SDL digital audio support
24 #include "gr.h" // needed for piggy.h
32 int digi_sample_rate=11025;
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.
124 fix max_volume; // Max volume that this sound is playing at
125 fix max_distance; // The max distance that this sound can be heard at...
126 int volume; // Volume that this sound is playing at
127 int pan; // Pan value that this sound is playing at
128 int handle; // What handle this sound is playing on. Valid only if SOF_PLAYING is set.
129 short soundnum; // The sound number that is playing
130 int loop_start; // The start point of the loop. -1 means no loop
131 int loop_end; // The end point of the loop
134 short segnum; // Used if SOF_LINK_TO_POS field is used
139 short objnum; // Used if SOF_LINK_TO_OBJ field is used
144 #define lp_segnum link.pos.segnum
145 #define lp_sidenum link.pos.sidenum
146 #define lp_position link.pos.position
148 #define lo_objnum link.obj.objnum
149 #define lo_objsignature link.obj.objsignature
151 #define MAX_SOUND_OBJECTS 16
152 sound_object SoundObjects[MAX_SOUND_OBJECTS];
153 short next_signature=0;
155 //added/changed on 980905 by adb to make sfx volume work, on 990221 by adb changed F1_0 to F1_0 / 2
156 #define SOUND_MAX_VOLUME (F1_0 / 2)
158 int digi_volume = SOUND_MAX_VOLUME;
163 static int digi_initialised = 0;
167 int playing; // Is there a sample playing on this channel?
168 int looped; // Play this sample looped?
169 fix pan; // 0 = far left, 1 = far right
170 fix volume; // 0 = nothing, 1 = fully on
171 //changed on 980905 by adb from char * to unsigned char *
172 unsigned char *samples;
174 unsigned int length; // Length of the sample
175 unsigned int position; // Position we are at at the moment.
176 } SoundSlots[MAX_SOUND_SLOTS];
178 static SDL_AudioSpec WaveSpec;
179 static int digi_sounds_initialized = 0;
181 //added on 980905 by adb to add rotating/volume based sound kill system
182 static int digi_max_channels = 16;
183 static int next_handle = 0;
184 int SampleHandles[32];
185 void reset_sounds_on_channel(int channel);
188 void digi_reset_digi_sounds(void);
190 /* Audio mixing callback */
191 //changed on 980905 by adb to cleanup, add pan support and optimize mixer
192 static void audio_mixcallback(void *userdata, Uint8 *stream, int len)
194 Uint8 *streamend = stream + len;
195 struct sound_slot *sl;
197 for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++)
201 Uint8 *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length;
202 Uint8 *sp = stream, s;
207 if ((x = sl->pan) & 0x8000)
209 vl = 0x20000 - x * 2;
217 vl = fixmul(vl, (x = sl->volume));
219 while (sp < streamend)
228 sldata = sl->samples;
230 v = *(sldata++) - 0x80;
232 *(sp++) = mix8[ s + fixmul(v, vl) + 0x80 ];
234 *(sp++) = mix8[ s + fixmul(v, vr) + 0x80 ];
236 sl->position = sldata - sl->samples;
242 /* Initialise audio devices. */
245 if (SDL_InitSubSystem(SDL_INIT_AUDIO)<0){
246 Error("SDL audio initialisation failed: %s.",SDL_GetError());
248 //added on 980905 by adb to init sound kill system
249 memset(SampleHandles, 255, sizeof(SampleHandles));
252 WaveSpec.freq = 11025;
253 //added/changed by Sam Lantinga on 12/01/98 for new SDL version
254 WaveSpec.format = AUDIO_U8;
255 WaveSpec.channels = 2;
256 //end this section addition/change - SL
257 WaveSpec.samples = SOUND_BUFFER_SIZE;
258 WaveSpec.callback = audio_mixcallback;
260 if ( SDL_OpenAudio(&WaveSpec, NULL) < 0 ) {
261 //edited on 10/05/98 by Matt Mueller - should keep running, just with no sound.
262 Warning("\nError: Couldn't open audio: %s\n", SDL_GetError());
270 digi_initialised = 1;
275 void digi_reset() { }
277 /* Shut down audio */
280 if (!digi_initialised) return;
281 digi_initialised = 0;
285 /* Find the sound which actually equates to a sound number */
286 int digi_xlat_sound(int soundno)
288 if ( soundno < 0 ) return -1;
291 soundno = AltSounds[soundno];
292 if ( soundno == 255 ) return -1;
294 if (Sounds[soundno] == 255) return -1;
296 return Sounds[soundno];
299 static int get_free_slot()
302 for (i=0; i<MAX_SOUND_SLOTS; i++)
304 if (!SoundSlots[i].playing) return i;
309 int digi_start_sound(int soundnum, fix volume, fix pan, int looping, int loop_start, int loop_end, int soundobj)
314 if (!digi_initialised) return -1;
316 if (soundnum < 0) return -1;
318 //added on 980905 by adb from original source to add sound kill system
319 // play at most digi_max_channel samples, if possible kill sample with low volume
323 if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing) )
325 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 SoundSlots[slot].soundno = SoundObjects[obj].soundnum;
385 SoundSlots[slot].samples = GameSounds[SoundObjects[obj].soundnum].data;
386 SoundSlots[slot].length = GameSounds[SoundObjects[obj].soundnum].length;
387 SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume);
388 SoundSlots[slot].pan = SoundObjects[obj].pan;
389 SoundSlots[slot].position = 0;
390 SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER);
391 SoundSlots[slot].playing = 1;
393 SoundObjects[obj].signature = next_signature++;
394 SoundObjects[obj].handle = slot;
396 SoundObjects[obj].flags |= SOF_PLAYING;
397 //added on 980905 by adb to add sound kill system from original sos digi.c
398 reset_sounds_on_channel(slot);
405 // Play the given sound number.
406 // Volume is max at F1_0.
407 void digi_play_sample( int soundno, fix max_volume )
410 if ( Newdemo_state == ND_STATE_RECORDING )
411 newdemo_record_sound( soundno );
413 soundno = digi_xlat_sound(soundno);
415 if (!digi_initialised) return;
417 if (soundno < 0 ) return;
419 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
422 // Play the given sound number. If the sound is already playing,
424 void digi_play_sample_once( int soundno, fix max_volume )
429 if ( Newdemo_state == ND_STATE_RECORDING )
430 newdemo_record_sound( soundno );
432 soundno = digi_xlat_sound(soundno);
434 if (!digi_initialised) return;
436 if (soundno < 0 ) return;
438 for (i=0; i < MAX_SOUND_SLOTS; i++)
439 if (SoundSlots[i].soundno == soundno)
440 SoundSlots[i].playing = 0;
441 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
445 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) // Volume from 0-0x7fff
450 if ( Newdemo_state == ND_STATE_RECORDING ) {
452 newdemo_record_sound_3d_once( soundno, angle, volume );
454 newdemo_record_sound_3d( soundno, angle, volume );
457 soundno = digi_xlat_sound(soundno);
459 if (!digi_initialised) return;
460 if (soundno < 0 ) return;
462 if (volume < MIN_VOLUME ) return;
463 digi_start_sound(soundno, volume, angle, 0, 0, 0, 0);
466 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 )
468 vms_vector vector_to_sound;
469 fix angle_from_ear, cosang,sinang;
476 max_distance = (max_distance*5)/4; // Make all sounds travel 1.25 times as far.
478 // Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
479 distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
481 if (distance < max_distance ) {
482 int num_search_segs = f2i(max_distance/20);
483 if ( num_search_segs < 1 ) num_search_segs = 1;
485 path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
486 if ( path_distance > -1 ) {
487 *volume = max_volume - fixdiv(path_distance,max_distance);
488 //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
490 angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
491 fix_sincos(angle_from_ear,&sinang,&cosang);
492 //mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
493 if (Config_channels_reversed) cosang *= -1;
494 *pan = (cosang + F1_0)/2;
502 //hack to not start object when loading level
503 int Dont_start_sound_objects = 0;
505 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 )
511 soundnum = digi_xlat_sound(org_soundnum);
513 if ( max_volume < 0 ) return -1;
514 // if ( max_volume > F1_0 ) max_volume = F1_0;
516 if (!digi_initialised) return -1;
517 if (soundnum < 0 ) return -1;
518 if (GameSounds[soundnum].data==NULL) {
522 if ((objnum<0)||(objnum>Highest_object_index))
526 // Hack to keep sounds from building up...
527 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
528 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
533 if ( Newdemo_state == ND_STATE_RECORDING ) {
534 newdemo_record_link_sound_to_object3( org_soundnum, objnum, max_volume, max_distance, loop_start, loop_end );
538 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
539 if (SoundObjects[i].flags==0)
542 if (i==MAX_SOUND_OBJECTS) {
543 mprintf((1, "Too many sound objects!\n" ));
547 SoundObjects[i].signature=next_signature++;
548 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
550 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
551 SoundObjects[i].lo_objnum = objnum;
552 SoundObjects[i].lo_objsignature = Objects[objnum].signature;
553 SoundObjects[i].max_volume = max_volume;
554 SoundObjects[i].max_distance = max_distance;
555 SoundObjects[i].volume = 0;
556 SoundObjects[i].pan = 0;
557 SoundObjects[i].soundnum = soundnum;
558 SoundObjects[i].loop_start = loop_start;
559 SoundObjects[i].loop_end = loop_end;
561 if (Dont_start_sound_objects) { //started at level start
563 SoundObjects[i].flags |= SOF_PERMANANT;
564 SoundObjects[i].handle = -1;
567 objp = &Objects[SoundObjects[i].lo_objnum];
568 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
569 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
570 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
572 //if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
573 digi_start_sound_object(i);
575 // If it's a one-shot sound effect, and it can't start right away, then
576 // just cancel it and be done with it.
577 if ( (SoundObjects[i].handle < 0) && (!(SoundObjects[i].flags & SOF_PLAY_FOREVER)) ) {
578 SoundObjects[i].flags = 0;
583 return SoundObjects[i].signature;
587 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance )
589 return digi_link_sound_to_object3( org_soundnum, objnum, forever, max_volume, max_distance, -1, -1 );
593 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
594 { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); }
596 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
601 soundnum = digi_xlat_sound(org_soundnum);
603 if ( max_volume < 0 ) return -1;
604 // if ( max_volume > F1_0 ) max_volume = F1_0;
606 if (!digi_initialised) return -1;
607 if (soundnum < 0 ) return -1;
608 if (GameSounds[soundnum].data==NULL) {
613 if ((segnum<0)||(segnum>Highest_segment_index))
617 // Hack to keep sounds from building up...
618 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
619 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
623 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
624 if (SoundObjects[i].flags==0)
627 if (i==MAX_SOUND_OBJECTS) {
628 mprintf((1, "Too many sound objects!\n" ));
633 SoundObjects[i].signature=next_signature++;
634 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
636 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
637 SoundObjects[i].lp_segnum = segnum;
638 SoundObjects[i].lp_sidenum = sidenum;
639 SoundObjects[i].lp_position = *pos;
640 SoundObjects[i].soundnum = soundnum;
641 SoundObjects[i].max_volume = max_volume;
642 SoundObjects[i].max_distance = max_distance;
643 SoundObjects[i].volume = 0;
644 SoundObjects[i].pan = 0;
645 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
646 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
647 SoundObjects[i].max_volume,
648 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
650 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
651 digi_start_sound_object(i);
653 return SoundObjects[i].signature;
656 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
658 return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
661 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
665 soundnum = digi_xlat_sound(soundnum);
667 if (!digi_initialised) return;
671 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
672 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) ) {
673 if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
674 if ( SoundObjects[i].flags & SOF_PLAYING ) {
675 SoundSlots[SoundObjects[i].handle].playing = 0;
677 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
682 // If this assert happens, it means that there were 2 sounds
683 // that got deleted. Weird, get John.
685 mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
689 void digi_kill_sound_linked_to_object( int objnum )
693 if (!digi_initialised) return;
697 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
698 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) ) {
699 if (SoundObjects[i].lo_objnum == objnum) {
700 if ( SoundObjects[i].flags & SOF_PLAYING ) {
701 SoundSlots[SoundObjects[i].handle].playing = 0;
703 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
708 // If this assert happens, it means that there were 2 sounds
709 // that got deleted. Weird, get John.
711 mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
715 void digi_sync_sounds()
718 int oldvolume, oldpan;
720 if (!digi_initialised) return;
722 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
723 if ( SoundObjects[i].flags & SOF_USED ) {
724 oldvolume = SoundObjects[i].volume;
725 oldpan = SoundObjects[i].pan;
727 if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) ) {
728 // Check if its done.
729 if (SoundObjects[i].flags & SOF_PLAYING) {
730 if (!SoundSlots[SoundObjects[i].handle].playing) {
731 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
732 continue; // Go on to next sound...
737 if ( SoundObjects[i].flags & SOF_LINK_TO_POS ) {
738 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
739 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
740 SoundObjects[i].max_volume,
741 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
743 } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) {
746 objp = &Objects[SoundObjects[i].lo_objnum];
748 if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature)) {
749 // The object that this is linked to is dead, so just end this sound if it is looping.
750 if ( (SoundObjects[i].flags & SOF_PLAYING) && (SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
751 SoundSlots[SoundObjects[i].handle].playing = 0;
753 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
754 continue; // Go on to next sound...
756 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
757 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
758 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
762 if (oldvolume != SoundObjects[i].volume) {
763 if ( SoundObjects[i].volume < MIN_VOLUME ) {
764 // Sound is too far away, so stop it from playing.
765 if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
766 SoundSlots[SoundObjects[i].handle].playing = 0;
767 SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing
770 if (!(SoundObjects[i].flags & SOF_PLAYING)) {
771 digi_start_sound_object(i);
773 SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0);
778 if (oldpan != SoundObjects[i].pan) {
779 if (SoundObjects[i].flags & SOF_PLAYING)
780 SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan;
786 void digi_init_sounds()
790 if (!digi_initialised) return;
792 digi_reset_digi_sounds();
794 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
795 if (digi_sounds_initialized) {
796 if ( SoundObjects[i].flags & SOF_PLAYING ) {
797 SoundSlots[SoundObjects[i].handle].playing=0;
800 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
802 digi_sounds_initialized = 1;
805 //added on 980905 by adb from original source to make sfx volume work
806 void digi_set_digi_volume( int dvolume )
808 dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
809 if ( dvolume > SOUND_MAX_VOLUME )
810 digi_volume = SOUND_MAX_VOLUME;
811 else if ( dvolume < 0 )
814 digi_volume = dvolume;
816 if ( !digi_initialised ) return;
822 void digi_set_volume( int dvolume, int mvolume )
824 digi_set_digi_volume(dvolume);
825 digi_set_midi_volume(mvolume);
826 // mprintf(( 1, "Volume: 0x%x and 0x%x\n", digi_volume, midi_volume ));
829 int digi_is_sound_playing(int soundno)
833 soundno = digi_xlat_sound(soundno);
835 for (i = 0; i < MAX_SOUND_SLOTS; i++)
836 //changed on 980905 by adb: added SoundSlots[i].playing &&
837 if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
844 void digi_pause_all() { }
845 void digi_resume_all() { }
846 void digi_stop_all() {
848 // ... Ano. The lack of this was causing ambient sounds to crash.
849 // fixed, added digi_stop_all 07/19/01 - bluecow
851 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
852 if ( SoundObjects[i].flags & SOF_USED ) {
853 SoundSlots[SoundObjects[i].handle].playing = 0;
854 SoundObjects[i].flags = 0;
859 //added on 980905 by adb to make sound channel setting work
860 void digi_set_max_channels(int n) {
861 digi_max_channels = n;
863 if ( digi_max_channels < 1 )
864 digi_max_channels = 1;
865 if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) )
866 digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS);
868 if ( !digi_initialised ) return;
870 digi_reset_digi_sounds();
873 int digi_get_max_channels() {
874 return digi_max_channels;
878 void digi_stop_sound(int channel)
880 //FIXME: Is this correct? I dunno, it works.
881 SoundSlots[channel].playing=0;
884 void digi_reset_digi_sounds() {
887 for (i=0; i< MAX_SOUND_SLOTS; i++)
888 SoundSlots[i].playing=0;
890 //added on 980905 by adb to reset sound kill system
891 memset(SampleHandles, 255, sizeof(SampleHandles));
897 // MIDI stuff follows.
898 //added/killed on 11/25/98 by Matthew Mueller
899 //void digi_set_midi_volume( int mvolume ) { }
900 //void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
901 //void digi_stop_current_song()
910 //end this section kill - MM