1 /* $Id: digi.c,v 1.12 2003-11-27 09:10:52 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 for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++)
207 Uint8 *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length;
208 Uint8 *sp = stream, s;
213 if ((x = sl->pan) & 0x8000)
215 vl = 0x20000 - x * 2;
223 vl = fixmul(vl, (x = sl->volume));
225 while (sp < streamend)
234 sldata = sl->samples;
236 v = *(sldata++) - 0x80;
238 *(sp++) = mix8[ s + fixmul(v, vl) + 0x80 ];
240 *(sp++) = mix8[ s + fixmul(v, vr) + 0x80 ];
242 sl->position = sldata - sl->samples;
248 /* Initialise audio devices. */
251 if (SDL_InitSubSystem(SDL_INIT_AUDIO)<0){
252 Error("SDL audio initialisation failed: %s.",SDL_GetError());
254 //added on 980905 by adb to init sound kill system
255 memset(SampleHandles, 255, sizeof(SampleHandles));
258 WaveSpec.freq = digi_sample_rate;
259 //added/changed by Sam Lantinga on 12/01/98 for new SDL version
260 WaveSpec.format = AUDIO_U8;
261 WaveSpec.channels = 2;
262 //end this section addition/change - SL
263 WaveSpec.samples = SOUND_BUFFER_SIZE;
264 WaveSpec.callback = audio_mixcallback;
266 if ( SDL_OpenAudio(&WaveSpec, NULL) < 0 ) {
267 //edited on 10/05/98 by Matt Mueller - should keep running, just with no sound.
268 Warning("\nError: Couldn't open audio: %s\n", SDL_GetError());
276 digi_initialised = 1;
281 void digi_reset() { }
283 /* Shut down audio */
286 if (!digi_initialised) return;
287 digi_initialised = 0;
291 /* Find the sound which actually equates to a sound number */
292 int digi_xlat_sound(int soundno)
294 if ( soundno < 0 ) return -1;
297 soundno = AltSounds[soundno];
298 if ( soundno == 255 ) return -1;
300 if (Sounds[soundno] == 255) return -1;
302 return Sounds[soundno];
305 static int get_free_slot()
308 for (i=0; i<MAX_SOUND_SLOTS; i++)
310 if (!SoundSlots[i].playing) return i;
315 int digi_start_sound(int soundnum, fix volume, fix pan, int looping, int loop_start, int loop_end, int soundobj)
320 if (!digi_initialised) return -1;
322 if (soundnum < 0) return -1;
324 //added on 980905 by adb from original source to add sound kill system
325 // play at most digi_max_channel samples, if possible kill sample with low volume
329 if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing) )
331 if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries<digi_max_channels) )
333 //mprintf(( 0, "Not stopping loud sound %d.\n", next_handle ));
335 if ( next_handle >= digi_max_channels )
340 //mprintf(( 0, "[SS:%d]", next_handle ));
341 SoundSlots[SampleHandles[next_handle]].playing = 0;
342 SampleHandles[next_handle] = -1;
346 slot = get_free_slot();
347 if (slot<0) return -1;
349 SoundSlots[slot].soundno = soundnum;
350 SoundSlots[slot].samples = GameSounds[soundnum].data;
351 SoundSlots[slot].length = GameSounds[soundnum].length;
352 SoundSlots[slot].volume = fixmul(digi_volume, volume);
353 SoundSlots[slot].pan = pan;
354 SoundSlots[slot].position = 0;
355 SoundSlots[slot].looped = looping;
356 SoundSlots[slot].playing = 1;
358 //added on 980905 by adb to add sound kill system from original sos digi.c
359 reset_sounds_on_channel(slot);
360 SampleHandles[next_handle] = slot;
362 if ( next_handle >= digi_max_channels )
369 //added on 980905 by adb to add sound kill system from original sos digi.c
370 void reset_sounds_on_channel( int channel )
374 for (i=0; i<digi_max_channels; i++)
375 if (SampleHandles[i] == channel)
376 SampleHandles[i] = -1;
380 int digi_start_sound_object(int obj)
384 if (!digi_initialised) return -1;
385 slot = get_free_slot();
387 if (slot<0) return -1;
390 // only use up to half the sound channels for "permanant" sounts
391 if ((SoundObjects[i].flags & SOF_PERMANANT) && (N_active_sound_objects >= max(1,digi_get_max_channels()/4)) )
395 SoundSlots[slot].soundno = SoundObjects[obj].soundnum;
396 SoundSlots[slot].samples = GameSounds[SoundObjects[obj].soundnum].data;
397 SoundSlots[slot].length = GameSounds[SoundObjects[obj].soundnum].length;
398 SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume);
399 SoundSlots[slot].pan = SoundObjects[obj].pan;
400 SoundSlots[slot].position = 0;
401 SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER);
402 SoundSlots[slot].playing = 1;
404 SoundObjects[obj].signature = next_signature++;
405 SoundObjects[obj].handle = slot;
407 SoundObjects[obj].flags |= SOF_PLAYING;
408 //added on 980905 by adb to add sound kill system from original sos digi.c
409 reset_sounds_on_channel(slot);
416 // Play the given sound number.
417 // Volume is max at F1_0.
418 void digi_play_sample( int soundno, fix max_volume )
421 if ( Newdemo_state == ND_STATE_RECORDING )
422 newdemo_record_sound( soundno );
424 soundno = digi_xlat_sound(soundno);
426 if (!digi_initialised) return;
428 if (soundno < 0 ) return;
430 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
433 // Play the given sound number. If the sound is already playing,
435 void digi_play_sample_once( int soundno, fix max_volume )
440 if ( Newdemo_state == ND_STATE_RECORDING )
441 newdemo_record_sound( soundno );
443 soundno = digi_xlat_sound(soundno);
445 if (!digi_initialised) return;
447 if (soundno < 0 ) return;
449 for (i=0; i < MAX_SOUND_SLOTS; i++)
450 if (SoundSlots[i].soundno == soundno)
451 SoundSlots[i].playing = 0;
452 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
456 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) // Volume from 0-0x7fff
461 if ( Newdemo_state == ND_STATE_RECORDING ) {
463 newdemo_record_sound_3d_once( soundno, angle, volume );
465 newdemo_record_sound_3d( soundno, angle, volume );
468 soundno = digi_xlat_sound(soundno);
470 if (!digi_initialised) return;
471 if (soundno < 0 ) return;
473 if (volume < MIN_VOLUME ) return;
474 digi_start_sound(soundno, volume, angle, 0, 0, 0, 0);
477 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 )
479 vms_vector vector_to_sound;
480 fix angle_from_ear, cosang,sinang;
487 max_distance = (max_distance*5)/4; // Make all sounds travel 1.25 times as far.
489 // Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
490 distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
492 if (distance < max_distance ) {
493 int num_search_segs = f2i(max_distance/20);
494 if ( num_search_segs < 1 ) num_search_segs = 1;
496 path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
497 if ( path_distance > -1 ) {
498 *volume = max_volume - fixdiv(path_distance,max_distance);
499 //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
501 angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
502 fix_sincos(angle_from_ear,&sinang,&cosang);
503 //mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
504 if (Config_channels_reversed) cosang *= -1;
505 *pan = (cosang + F1_0)/2;
513 //hack to not start object when loading level
514 int Dont_start_sound_objects = 0;
516 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 )
522 soundnum = digi_xlat_sound(org_soundnum);
524 if ( max_volume < 0 ) return -1;
525 // if ( max_volume > F1_0 ) max_volume = F1_0;
527 if (!digi_initialised) return -1;
528 if (soundnum < 0 ) return -1;
529 if (GameSounds[soundnum].data==NULL) {
533 if ((objnum<0)||(objnum>Highest_object_index))
537 // Hack to keep sounds from building up...
538 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
539 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
544 if ( Newdemo_state == ND_STATE_RECORDING ) {
545 newdemo_record_link_sound_to_object3( org_soundnum, objnum, max_volume, max_distance, loop_start, loop_end );
549 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
550 if (SoundObjects[i].flags==0)
553 if (i==MAX_SOUND_OBJECTS) {
554 mprintf((1, "Too many sound objects!\n" ));
558 SoundObjects[i].signature=next_signature++;
559 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
561 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
562 SoundObjects[i].lo_objnum = objnum;
563 SoundObjects[i].lo_objsignature = Objects[objnum].signature;
564 SoundObjects[i].max_volume = max_volume;
565 SoundObjects[i].max_distance = max_distance;
566 SoundObjects[i].volume = 0;
567 SoundObjects[i].pan = 0;
568 SoundObjects[i].soundnum = soundnum;
569 SoundObjects[i].loop_start = loop_start;
570 SoundObjects[i].loop_end = loop_end;
572 if (Dont_start_sound_objects) { //started at level start
574 SoundObjects[i].flags |= SOF_PERMANANT;
575 SoundObjects[i].handle = -1;
578 objp = &Objects[SoundObjects[i].lo_objnum];
579 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
580 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
581 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
583 //if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
584 digi_start_sound_object(i);
586 // If it's a one-shot sound effect, and it can't start right away, then
587 // just cancel it and be done with it.
588 if ( (SoundObjects[i].handle < 0) && (!(SoundObjects[i].flags & SOF_PLAY_FOREVER)) ) {
589 SoundObjects[i].flags = 0;
594 return SoundObjects[i].signature;
598 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance )
600 return digi_link_sound_to_object3( org_soundnum, objnum, forever, max_volume, max_distance, -1, -1 );
604 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
605 { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); }
607 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
612 soundnum = digi_xlat_sound(org_soundnum);
614 if ( max_volume < 0 ) return -1;
615 // if ( max_volume > F1_0 ) max_volume = F1_0;
617 if (!digi_initialised) return -1;
618 if (soundnum < 0 ) return -1;
619 if (GameSounds[soundnum].data==NULL) {
624 if ((segnum<0)||(segnum>Highest_segment_index))
628 // Hack to keep sounds from building up...
629 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
630 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
634 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
635 if (SoundObjects[i].flags==0)
638 if (i==MAX_SOUND_OBJECTS) {
639 mprintf((1, "Too many sound objects!\n" ));
644 SoundObjects[i].signature=next_signature++;
645 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
647 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
648 SoundObjects[i].lp_segnum = segnum;
649 SoundObjects[i].lp_sidenum = sidenum;
650 SoundObjects[i].lp_position = *pos;
651 SoundObjects[i].soundnum = soundnum;
652 SoundObjects[i].max_volume = max_volume;
653 SoundObjects[i].max_distance = max_distance;
654 SoundObjects[i].volume = 0;
655 SoundObjects[i].pan = 0;
656 SoundObjects[i].loop_start = SoundObjects[i].loop_end = -1;
658 if (Dont_start_sound_objects) { //started at level start
660 SoundObjects[i].flags |= SOF_PERMANANT;
662 SoundObjects[i].handle = -1;
666 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
667 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
668 SoundObjects[i].max_volume,
669 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
671 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
672 digi_start_sound_object(i);
674 // If it's a one-shot sound effect, and it can't start right away, then
675 // just cancel it and be done with it.
676 if ( (SoundObjects[i].handle < 0) && (!(SoundObjects[i].flags & SOF_PLAY_FOREVER)) ) {
677 SoundObjects[i].flags = 0;
682 return SoundObjects[i].signature;
685 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
687 return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
690 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
694 soundnum = digi_xlat_sound(soundnum);
696 if (!digi_initialised) return;
700 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
701 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) ) {
702 if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
703 if ( SoundObjects[i].flags & SOF_PLAYING ) {
704 SoundSlots[SoundObjects[i].handle].playing = 0;
706 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
711 // If this assert happens, it means that there were 2 sounds
712 // that got deleted. Weird, get John.
714 mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
718 void digi_kill_sound_linked_to_object( int objnum )
722 if (!digi_initialised) return;
726 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
727 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) ) {
728 if (SoundObjects[i].lo_objnum == objnum) {
729 if ( SoundObjects[i].flags & SOF_PLAYING ) {
730 SoundSlots[SoundObjects[i].handle].playing = 0;
732 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
737 // If this assert happens, it means that there were 2 sounds
738 // that got deleted. Weird, get John.
740 mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
744 void digi_sync_sounds()
747 int oldvolume, oldpan;
749 if (!digi_initialised) return;
751 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
752 if ( SoundObjects[i].flags & SOF_USED ) {
753 oldvolume = SoundObjects[i].volume;
754 oldpan = SoundObjects[i].pan;
756 if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) ) {
757 // Check if its done.
758 if (SoundObjects[i].flags & SOF_PLAYING) {
759 if (!SoundSlots[SoundObjects[i].handle].playing) {
760 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
761 continue; // Go on to next sound...
766 if ( SoundObjects[i].flags & SOF_LINK_TO_POS ) {
767 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
768 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
769 SoundObjects[i].max_volume,
770 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
772 } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) {
775 objp = &Objects[SoundObjects[i].lo_objnum];
777 if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature)) {
778 // The object that this is linked to is dead, so just end this sound if it is looping.
779 if ( (SoundObjects[i].flags & SOF_PLAYING) && (SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
780 SoundSlots[SoundObjects[i].handle].playing = 0;
782 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
783 continue; // Go on to next sound...
785 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
786 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
787 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
791 if (oldvolume != SoundObjects[i].volume) {
792 if ( SoundObjects[i].volume < MIN_VOLUME ) {
793 // Sound is too far away, so stop it from playing.
794 if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
795 SoundSlots[SoundObjects[i].handle].playing = 0;
796 SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing
799 if (!(SoundObjects[i].flags & SOF_PLAYING)) {
800 digi_start_sound_object(i);
802 SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0);
807 if (oldpan != SoundObjects[i].pan) {
808 if (SoundObjects[i].flags & SOF_PLAYING)
809 SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan;
815 void digi_init_sounds()
819 if (!digi_initialised) return;
821 digi_reset_digi_sounds();
823 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
824 if (digi_sounds_initialized) {
825 if ( SoundObjects[i].flags & SOF_PLAYING ) {
826 SoundSlots[SoundObjects[i].handle].playing=0;
829 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
831 digi_sounds_initialized = 1;
834 //added on 980905 by adb from original source to make sfx volume work
835 void digi_set_digi_volume( int dvolume )
837 dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
838 if ( dvolume > SOUND_MAX_VOLUME )
839 digi_volume = SOUND_MAX_VOLUME;
840 else if ( dvolume < 0 )
843 digi_volume = dvolume;
845 if ( !digi_initialised ) return;
851 void digi_set_volume( int dvolume, int mvolume )
853 digi_set_digi_volume(dvolume);
854 digi_set_midi_volume(mvolume);
855 // mprintf(( 1, "Volume: 0x%x and 0x%x\n", digi_volume, midi_volume ));
858 int digi_is_sound_playing(int soundno)
862 soundno = digi_xlat_sound(soundno);
864 for (i = 0; i < MAX_SOUND_SLOTS; i++)
865 //changed on 980905 by adb: added SoundSlots[i].playing &&
866 if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
873 void digi_pause_all() { }
874 void digi_resume_all() { }
875 void digi_stop_all() {
877 // ... Ano. The lack of this was causing ambient sounds to crash.
878 // fixed, added digi_stop_all 07/19/01 - bluecow
880 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
881 if ( SoundObjects[i].flags & SOF_USED ) {
882 SoundSlots[SoundObjects[i].handle].playing = 0;
883 SoundObjects[i].flags = 0;
888 //added on 980905 by adb to make sound channel setting work
889 void digi_set_max_channels(int n) {
890 digi_max_channels = n;
892 if ( digi_max_channels < 1 )
893 digi_max_channels = 1;
894 if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) )
895 digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS);
897 if ( !digi_initialised ) return;
899 digi_reset_digi_sounds();
902 int digi_get_max_channels() {
903 return digi_max_channels;
907 void digi_stop_sound(int channel)
909 //FIXME: Is this correct? I dunno, it works.
910 SoundSlots[channel].playing=0;
913 void digi_reset_digi_sounds() {
916 for (i=0; i< MAX_SOUND_SLOTS; i++)
917 SoundSlots[i].playing=0;
919 //added on 980905 by adb to reset sound kill system
920 memset(SampleHandles, 255, sizeof(SampleHandles));
926 // MIDI stuff follows.
927 //added/killed on 11/25/98 by Matthew Mueller
928 //void digi_set_midi_volume( int mvolume ) { }
929 //void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
930 //void digi_stop_current_song()
939 //end this section kill - MM