1 /* $Id: digi.c,v 1.13 2004-05-08 18:56:04 schaffner 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 memset(stream, 0x80, len); // fix "static" sound bug on Mac OS X
205 for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++)
209 Uint8 *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length;
210 Uint8 *sp = stream, s;
215 if ((x = sl->pan) & 0x8000)
217 vl = 0x20000 - x * 2;
225 vl = fixmul(vl, (x = sl->volume));
227 while (sp < streamend)
236 sldata = sl->samples;
238 v = *(sldata++) - 0x80;
240 *(sp++) = mix8[ s + fixmul(v, vl) + 0x80 ];
242 *(sp++) = mix8[ s + fixmul(v, vr) + 0x80 ];
244 sl->position = sldata - sl->samples;
250 /* Initialise audio devices. */
253 if (SDL_InitSubSystem(SDL_INIT_AUDIO)<0){
254 Error("SDL audio initialisation failed: %s.",SDL_GetError());
256 //added on 980905 by adb to init sound kill system
257 memset(SampleHandles, 255, sizeof(SampleHandles));
260 WaveSpec.freq = digi_sample_rate;
261 //added/changed by Sam Lantinga on 12/01/98 for new SDL version
262 WaveSpec.format = AUDIO_U8;
263 WaveSpec.channels = 2;
264 //end this section addition/change - SL
265 WaveSpec.samples = SOUND_BUFFER_SIZE;
266 WaveSpec.callback = audio_mixcallback;
268 if ( SDL_OpenAudio(&WaveSpec, NULL) < 0 ) {
269 //edited on 10/05/98 by Matt Mueller - should keep running, just with no sound.
270 Warning("\nError: Couldn't open audio: %s\n", SDL_GetError());
278 digi_initialised = 1;
283 void digi_reset() { }
285 /* Shut down audio */
288 if (!digi_initialised) return;
289 digi_initialised = 0;
293 /* Find the sound which actually equates to a sound number */
294 int digi_xlat_sound(int soundno)
296 if ( soundno < 0 ) return -1;
299 soundno = AltSounds[soundno];
300 if ( soundno == 255 ) return -1;
302 if (Sounds[soundno] == 255) return -1;
304 return Sounds[soundno];
307 static int get_free_slot()
310 for (i=0; i<MAX_SOUND_SLOTS; i++)
312 if (!SoundSlots[i].playing) return i;
317 int digi_start_sound(int soundnum, fix volume, fix pan, int looping, int loop_start, int loop_end, int soundobj)
322 if (!digi_initialised) return -1;
324 if (soundnum < 0) return -1;
326 //added on 980905 by adb from original source to add sound kill system
327 // play at most digi_max_channel samples, if possible kill sample with low volume
331 if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing) )
333 if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries<digi_max_channels) )
335 //mprintf(( 0, "Not stopping loud sound %d.\n", next_handle ));
337 if ( next_handle >= digi_max_channels )
342 //mprintf(( 0, "[SS:%d]", next_handle ));
343 SoundSlots[SampleHandles[next_handle]].playing = 0;
344 SampleHandles[next_handle] = -1;
348 slot = get_free_slot();
349 if (slot<0) return -1;
351 SoundSlots[slot].soundno = soundnum;
352 SoundSlots[slot].samples = GameSounds[soundnum].data;
353 SoundSlots[slot].length = GameSounds[soundnum].length;
354 SoundSlots[slot].volume = fixmul(digi_volume, volume);
355 SoundSlots[slot].pan = pan;
356 SoundSlots[slot].position = 0;
357 SoundSlots[slot].looped = looping;
358 SoundSlots[slot].playing = 1;
360 //added on 980905 by adb to add sound kill system from original sos digi.c
361 reset_sounds_on_channel(slot);
362 SampleHandles[next_handle] = slot;
364 if ( next_handle >= digi_max_channels )
371 //added on 980905 by adb to add sound kill system from original sos digi.c
372 void reset_sounds_on_channel( int channel )
376 for (i=0; i<digi_max_channels; i++)
377 if (SampleHandles[i] == channel)
378 SampleHandles[i] = -1;
382 int digi_start_sound_object(int obj)
386 if (!digi_initialised) return -1;
387 slot = get_free_slot();
389 if (slot<0) return -1;
392 // only use up to half the sound channels for "permanant" sounts
393 if ((SoundObjects[i].flags & SOF_PERMANANT) && (N_active_sound_objects >= max(1,digi_get_max_channels()/4)) )
397 SoundSlots[slot].soundno = SoundObjects[obj].soundnum;
398 SoundSlots[slot].samples = GameSounds[SoundObjects[obj].soundnum].data;
399 SoundSlots[slot].length = GameSounds[SoundObjects[obj].soundnum].length;
400 SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume);
401 SoundSlots[slot].pan = SoundObjects[obj].pan;
402 SoundSlots[slot].position = 0;
403 SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER);
404 SoundSlots[slot].playing = 1;
406 SoundObjects[obj].signature = next_signature++;
407 SoundObjects[obj].handle = slot;
409 SoundObjects[obj].flags |= SOF_PLAYING;
410 //added on 980905 by adb to add sound kill system from original sos digi.c
411 reset_sounds_on_channel(slot);
418 // Play the given sound number.
419 // Volume is max at F1_0.
420 void digi_play_sample( int soundno, fix max_volume )
423 if ( Newdemo_state == ND_STATE_RECORDING )
424 newdemo_record_sound( soundno );
426 soundno = digi_xlat_sound(soundno);
428 if (!digi_initialised) return;
430 if (soundno < 0 ) return;
432 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
435 // Play the given sound number. If the sound is already playing,
437 void digi_play_sample_once( int soundno, fix max_volume )
442 if ( Newdemo_state == ND_STATE_RECORDING )
443 newdemo_record_sound( soundno );
445 soundno = digi_xlat_sound(soundno);
447 if (!digi_initialised) return;
449 if (soundno < 0 ) return;
451 for (i=0; i < MAX_SOUND_SLOTS; i++)
452 if (SoundSlots[i].soundno == soundno)
453 SoundSlots[i].playing = 0;
454 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
458 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) // Volume from 0-0x7fff
463 if ( Newdemo_state == ND_STATE_RECORDING ) {
465 newdemo_record_sound_3d_once( soundno, angle, volume );
467 newdemo_record_sound_3d( soundno, angle, volume );
470 soundno = digi_xlat_sound(soundno);
472 if (!digi_initialised) return;
473 if (soundno < 0 ) return;
475 if (volume < MIN_VOLUME ) return;
476 digi_start_sound(soundno, volume, angle, 0, 0, 0, 0);
479 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 )
481 vms_vector vector_to_sound;
482 fix angle_from_ear, cosang,sinang;
489 max_distance = (max_distance*5)/4; // Make all sounds travel 1.25 times as far.
491 // Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
492 distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
494 if (distance < max_distance ) {
495 int num_search_segs = f2i(max_distance/20);
496 if ( num_search_segs < 1 ) num_search_segs = 1;
498 path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
499 if ( path_distance > -1 ) {
500 *volume = max_volume - fixdiv(path_distance,max_distance);
501 //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
503 angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
504 fix_sincos(angle_from_ear,&sinang,&cosang);
505 //mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
506 if (Config_channels_reversed) cosang *= -1;
507 *pan = (cosang + F1_0)/2;
515 //hack to not start object when loading level
516 int Dont_start_sound_objects = 0;
518 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 )
524 soundnum = digi_xlat_sound(org_soundnum);
526 if ( max_volume < 0 ) return -1;
527 // if ( max_volume > F1_0 ) max_volume = F1_0;
529 if (!digi_initialised) return -1;
530 if (soundnum < 0 ) return -1;
531 if (GameSounds[soundnum].data==NULL) {
535 if ((objnum<0)||(objnum>Highest_object_index))
539 // Hack to keep sounds from building up...
540 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
541 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
546 if ( Newdemo_state == ND_STATE_RECORDING ) {
547 newdemo_record_link_sound_to_object3( org_soundnum, objnum, max_volume, max_distance, loop_start, loop_end );
551 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
552 if (SoundObjects[i].flags==0)
555 if (i==MAX_SOUND_OBJECTS) {
556 mprintf((1, "Too many sound objects!\n" ));
560 SoundObjects[i].signature=next_signature++;
561 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
563 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
564 SoundObjects[i].lo_objnum = objnum;
565 SoundObjects[i].lo_objsignature = Objects[objnum].signature;
566 SoundObjects[i].max_volume = max_volume;
567 SoundObjects[i].max_distance = max_distance;
568 SoundObjects[i].volume = 0;
569 SoundObjects[i].pan = 0;
570 SoundObjects[i].soundnum = soundnum;
571 SoundObjects[i].loop_start = loop_start;
572 SoundObjects[i].loop_end = loop_end;
574 if (Dont_start_sound_objects) { //started at level start
576 SoundObjects[i].flags |= SOF_PERMANANT;
577 SoundObjects[i].handle = -1;
580 objp = &Objects[SoundObjects[i].lo_objnum];
581 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
582 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
583 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
585 //if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
586 digi_start_sound_object(i);
588 // If it's a one-shot sound effect, and it can't start right away, then
589 // just cancel it and be done with it.
590 if ( (SoundObjects[i].handle < 0) && (!(SoundObjects[i].flags & SOF_PLAY_FOREVER)) ) {
591 SoundObjects[i].flags = 0;
596 return SoundObjects[i].signature;
600 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance )
602 return digi_link_sound_to_object3( org_soundnum, objnum, forever, max_volume, max_distance, -1, -1 );
606 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
607 { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); }
609 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
614 soundnum = digi_xlat_sound(org_soundnum);
616 if ( max_volume < 0 ) return -1;
617 // if ( max_volume > F1_0 ) max_volume = F1_0;
619 if (!digi_initialised) return -1;
620 if (soundnum < 0 ) return -1;
621 if (GameSounds[soundnum].data==NULL) {
626 if ((segnum<0)||(segnum>Highest_segment_index))
630 // Hack to keep sounds from building up...
631 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
632 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
636 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
637 if (SoundObjects[i].flags==0)
640 if (i==MAX_SOUND_OBJECTS) {
641 mprintf((1, "Too many sound objects!\n" ));
646 SoundObjects[i].signature=next_signature++;
647 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
649 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
650 SoundObjects[i].lp_segnum = segnum;
651 SoundObjects[i].lp_sidenum = sidenum;
652 SoundObjects[i].lp_position = *pos;
653 SoundObjects[i].soundnum = soundnum;
654 SoundObjects[i].max_volume = max_volume;
655 SoundObjects[i].max_distance = max_distance;
656 SoundObjects[i].volume = 0;
657 SoundObjects[i].pan = 0;
658 SoundObjects[i].loop_start = SoundObjects[i].loop_end = -1;
660 if (Dont_start_sound_objects) { //started at level start
662 SoundObjects[i].flags |= SOF_PERMANANT;
664 SoundObjects[i].handle = -1;
668 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
669 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
670 SoundObjects[i].max_volume,
671 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
673 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
674 digi_start_sound_object(i);
676 // If it's a one-shot sound effect, and it can't start right away, then
677 // just cancel it and be done with it.
678 if ( (SoundObjects[i].handle < 0) && (!(SoundObjects[i].flags & SOF_PLAY_FOREVER)) ) {
679 SoundObjects[i].flags = 0;
684 return SoundObjects[i].signature;
687 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
689 return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
692 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
696 soundnum = digi_xlat_sound(soundnum);
698 if (!digi_initialised) return;
702 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
703 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) ) {
704 if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
705 if ( SoundObjects[i].flags & SOF_PLAYING ) {
706 SoundSlots[SoundObjects[i].handle].playing = 0;
708 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
713 // If this assert happens, it means that there were 2 sounds
714 // that got deleted. Weird, get John.
716 mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
720 void digi_kill_sound_linked_to_object( int objnum )
724 if (!digi_initialised) return;
728 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
729 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) ) {
730 if (SoundObjects[i].lo_objnum == objnum) {
731 if ( SoundObjects[i].flags & SOF_PLAYING ) {
732 SoundSlots[SoundObjects[i].handle].playing = 0;
734 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
739 // If this assert happens, it means that there were 2 sounds
740 // that got deleted. Weird, get John.
742 mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
746 void digi_sync_sounds()
749 int oldvolume, oldpan;
751 if (!digi_initialised) return;
753 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
754 if ( SoundObjects[i].flags & SOF_USED ) {
755 oldvolume = SoundObjects[i].volume;
756 oldpan = SoundObjects[i].pan;
758 if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) ) {
759 // Check if its done.
760 if (SoundObjects[i].flags & SOF_PLAYING) {
761 if (!SoundSlots[SoundObjects[i].handle].playing) {
762 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
763 continue; // Go on to next sound...
768 if ( SoundObjects[i].flags & SOF_LINK_TO_POS ) {
769 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
770 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
771 SoundObjects[i].max_volume,
772 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
774 } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) {
777 objp = &Objects[SoundObjects[i].lo_objnum];
779 if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature)) {
780 // The object that this is linked to is dead, so just end this sound if it is looping.
781 if ( (SoundObjects[i].flags & SOF_PLAYING) && (SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
782 SoundSlots[SoundObjects[i].handle].playing = 0;
784 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
785 continue; // Go on to next sound...
787 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
788 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
789 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
793 if (oldvolume != SoundObjects[i].volume) {
794 if ( SoundObjects[i].volume < MIN_VOLUME ) {
795 // Sound is too far away, so stop it from playing.
796 if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
797 SoundSlots[SoundObjects[i].handle].playing = 0;
798 SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing
801 if (!(SoundObjects[i].flags & SOF_PLAYING)) {
802 digi_start_sound_object(i);
804 SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0);
809 if (oldpan != SoundObjects[i].pan) {
810 if (SoundObjects[i].flags & SOF_PLAYING)
811 SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan;
817 void digi_init_sounds()
821 if (!digi_initialised) return;
823 digi_reset_digi_sounds();
825 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
826 if (digi_sounds_initialized) {
827 if ( SoundObjects[i].flags & SOF_PLAYING ) {
828 SoundSlots[SoundObjects[i].handle].playing=0;
831 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
833 digi_sounds_initialized = 1;
836 //added on 980905 by adb from original source to make sfx volume work
837 void digi_set_digi_volume( int dvolume )
839 dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
840 if ( dvolume > SOUND_MAX_VOLUME )
841 digi_volume = SOUND_MAX_VOLUME;
842 else if ( dvolume < 0 )
845 digi_volume = dvolume;
847 if ( !digi_initialised ) return;
853 void digi_set_volume( int dvolume, int mvolume )
855 digi_set_digi_volume(dvolume);
856 digi_set_midi_volume(mvolume);
857 // mprintf(( 1, "Volume: 0x%x and 0x%x\n", digi_volume, midi_volume ));
860 int digi_is_sound_playing(int soundno)
864 soundno = digi_xlat_sound(soundno);
866 for (i = 0; i < MAX_SOUND_SLOTS; i++)
867 //changed on 980905 by adb: added SoundSlots[i].playing &&
868 if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
875 void digi_pause_all() { }
876 void digi_resume_all() { }
877 void digi_stop_all() {
879 // ... Ano. The lack of this was causing ambient sounds to crash.
880 // fixed, added digi_stop_all 07/19/01 - bluecow
882 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
883 if ( SoundObjects[i].flags & SOF_USED ) {
884 SoundSlots[SoundObjects[i].handle].playing = 0;
885 SoundObjects[i].flags = 0;
890 //added on 980905 by adb to make sound channel setting work
891 void digi_set_max_channels(int n) {
892 digi_max_channels = n;
894 if ( digi_max_channels < 1 )
895 digi_max_channels = 1;
896 if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) )
897 digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS);
899 if ( !digi_initialised ) return;
901 digi_reset_digi_sounds();
904 int digi_get_max_channels() {
905 return digi_max_channels;
909 void digi_stop_sound(int channel)
911 //FIXME: Is this correct? I dunno, it works.
912 SoundSlots[channel].playing=0;
915 void digi_reset_digi_sounds() {
918 for (i=0; i< MAX_SOUND_SLOTS; i++)
919 SoundSlots[i].playing=0;
921 //added on 980905 by adb to reset sound kill system
922 memset(SampleHandles, 255, sizeof(SampleHandles));
928 // MIDI stuff follows.
929 //added/killed on 11/25/98 by Matthew Mueller
930 //void digi_set_midi_volume( int mvolume ) { }
931 //void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
932 //void digi_stop_current_song()
941 //end this section kill - MM