1 /* $Id: digi.c,v 1.11 2003-04-12 00:11:46 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.
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 = digi_sample_rate;
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 // 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;
572 objp = &Objects[SoundObjects[i].lo_objnum];
573 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
574 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
575 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
577 //if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
578 digi_start_sound_object(i);
580 // If it's a one-shot sound effect, and it can't start right away, then
581 // just cancel it and be done with it.
582 if ( (SoundObjects[i].handle < 0) && (!(SoundObjects[i].flags & SOF_PLAY_FOREVER)) ) {
583 SoundObjects[i].flags = 0;
588 return SoundObjects[i].signature;
592 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance )
594 return digi_link_sound_to_object3( org_soundnum, objnum, forever, max_volume, max_distance, -1, -1 );
598 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
599 { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); }
601 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
606 soundnum = digi_xlat_sound(org_soundnum);
608 if ( max_volume < 0 ) return -1;
609 // if ( max_volume > F1_0 ) max_volume = F1_0;
611 if (!digi_initialised) return -1;
612 if (soundnum < 0 ) return -1;
613 if (GameSounds[soundnum].data==NULL) {
618 if ((segnum<0)||(segnum>Highest_segment_index))
622 // Hack to keep sounds from building up...
623 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
624 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
628 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
629 if (SoundObjects[i].flags==0)
632 if (i==MAX_SOUND_OBJECTS) {
633 mprintf((1, "Too many sound objects!\n" ));
638 SoundObjects[i].signature=next_signature++;
639 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
641 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
642 SoundObjects[i].lp_segnum = segnum;
643 SoundObjects[i].lp_sidenum = sidenum;
644 SoundObjects[i].lp_position = *pos;
645 SoundObjects[i].soundnum = soundnum;
646 SoundObjects[i].max_volume = max_volume;
647 SoundObjects[i].max_distance = max_distance;
648 SoundObjects[i].volume = 0;
649 SoundObjects[i].pan = 0;
650 SoundObjects[i].loop_start = SoundObjects[i].loop_end = -1;
652 if (Dont_start_sound_objects) { //started at level start
654 SoundObjects[i].flags |= SOF_PERMANANT;
656 SoundObjects[i].handle = -1;
660 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
661 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
662 SoundObjects[i].max_volume,
663 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
665 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
666 digi_start_sound_object(i);
668 // If it's a one-shot sound effect, and it can't start right away, then
669 // just cancel it and be done with it.
670 if ( (SoundObjects[i].handle < 0) && (!(SoundObjects[i].flags & SOF_PLAY_FOREVER)) ) {
671 SoundObjects[i].flags = 0;
676 return SoundObjects[i].signature;
679 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
681 return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
684 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
688 soundnum = digi_xlat_sound(soundnum);
690 if (!digi_initialised) return;
694 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
695 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) ) {
696 if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
697 if ( SoundObjects[i].flags & SOF_PLAYING ) {
698 SoundSlots[SoundObjects[i].handle].playing = 0;
700 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
705 // If this assert happens, it means that there were 2 sounds
706 // that got deleted. Weird, get John.
708 mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
712 void digi_kill_sound_linked_to_object( int objnum )
716 if (!digi_initialised) return;
720 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
721 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) ) {
722 if (SoundObjects[i].lo_objnum == objnum) {
723 if ( SoundObjects[i].flags & SOF_PLAYING ) {
724 SoundSlots[SoundObjects[i].handle].playing = 0;
726 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
731 // If this assert happens, it means that there were 2 sounds
732 // that got deleted. Weird, get John.
734 mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
738 void digi_sync_sounds()
741 int oldvolume, oldpan;
743 if (!digi_initialised) return;
745 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
746 if ( SoundObjects[i].flags & SOF_USED ) {
747 oldvolume = SoundObjects[i].volume;
748 oldpan = SoundObjects[i].pan;
750 if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) ) {
751 // Check if its done.
752 if (SoundObjects[i].flags & SOF_PLAYING) {
753 if (!SoundSlots[SoundObjects[i].handle].playing) {
754 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
755 continue; // Go on to next sound...
760 if ( SoundObjects[i].flags & SOF_LINK_TO_POS ) {
761 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
762 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
763 SoundObjects[i].max_volume,
764 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
766 } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) {
769 objp = &Objects[SoundObjects[i].lo_objnum];
771 if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature)) {
772 // The object that this is linked to is dead, so just end this sound if it is looping.
773 if ( (SoundObjects[i].flags & SOF_PLAYING) && (SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
774 SoundSlots[SoundObjects[i].handle].playing = 0;
776 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
777 continue; // Go on to next sound...
779 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
780 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
781 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
785 if (oldvolume != SoundObjects[i].volume) {
786 if ( SoundObjects[i].volume < MIN_VOLUME ) {
787 // Sound is too far away, so stop it from playing.
788 if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
789 SoundSlots[SoundObjects[i].handle].playing = 0;
790 SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing
793 if (!(SoundObjects[i].flags & SOF_PLAYING)) {
794 digi_start_sound_object(i);
796 SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0);
801 if (oldpan != SoundObjects[i].pan) {
802 if (SoundObjects[i].flags & SOF_PLAYING)
803 SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan;
809 void digi_init_sounds()
813 if (!digi_initialised) return;
815 digi_reset_digi_sounds();
817 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
818 if (digi_sounds_initialized) {
819 if ( SoundObjects[i].flags & SOF_PLAYING ) {
820 SoundSlots[SoundObjects[i].handle].playing=0;
823 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
825 digi_sounds_initialized = 1;
828 //added on 980905 by adb from original source to make sfx volume work
829 void digi_set_digi_volume( int dvolume )
831 dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
832 if ( dvolume > SOUND_MAX_VOLUME )
833 digi_volume = SOUND_MAX_VOLUME;
834 else if ( dvolume < 0 )
837 digi_volume = dvolume;
839 if ( !digi_initialised ) return;
845 void digi_set_volume( int dvolume, int mvolume )
847 digi_set_digi_volume(dvolume);
848 digi_set_midi_volume(mvolume);
849 // mprintf(( 1, "Volume: 0x%x and 0x%x\n", digi_volume, midi_volume ));
852 int digi_is_sound_playing(int soundno)
856 soundno = digi_xlat_sound(soundno);
858 for (i = 0; i < MAX_SOUND_SLOTS; i++)
859 //changed on 980905 by adb: added SoundSlots[i].playing &&
860 if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
867 void digi_pause_all() { }
868 void digi_resume_all() { }
869 void digi_stop_all() {
871 // ... Ano. The lack of this was causing ambient sounds to crash.
872 // fixed, added digi_stop_all 07/19/01 - bluecow
874 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
875 if ( SoundObjects[i].flags & SOF_USED ) {
876 SoundSlots[SoundObjects[i].handle].playing = 0;
877 SoundObjects[i].flags = 0;
882 //added on 980905 by adb to make sound channel setting work
883 void digi_set_max_channels(int n) {
884 digi_max_channels = n;
886 if ( digi_max_channels < 1 )
887 digi_max_channels = 1;
888 if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) )
889 digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS);
891 if ( !digi_initialised ) return;
893 digi_reset_digi_sounds();
896 int digi_get_max_channels() {
897 return digi_max_channels;
901 void digi_stop_sound(int channel)
903 //FIXME: Is this correct? I dunno, it works.
904 SoundSlots[channel].playing=0;
907 void digi_reset_digi_sounds() {
910 for (i=0; i< MAX_SOUND_SLOTS; i++)
911 SoundSlots[i].playing=0;
913 //added on 980905 by adb to reset sound kill system
914 memset(SampleHandles, 255, sizeof(SampleHandles));
920 // MIDI stuff follows.
921 //added/killed on 11/25/98 by Matthew Mueller
922 //void digi_set_midi_volume( int mvolume ) { }
923 //void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
924 //void digi_stop_current_song()
933 //end this section kill - MM