1 /* $Id: digi.c,v 1.14 2004-05-13 12:31:34 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++) {
207 Uint8 *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length;
208 Uint8 *sp = stream, s;
213 if ((x = sl->pan) & 0x8000) {
214 vl = 0x20000 - x * 2;
220 vl = fixmul(vl, (x = sl->volume));
222 while (sp < streamend) {
223 if (sldata == slend) {
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++) {
303 if (!SoundSlots[i].playing) return i;
308 int digi_start_sound(int soundnum, fix volume, fix pan, int looping, int loop_start, int loop_end, int soundobj)
313 if (!digi_initialised) return -1;
315 if (soundnum < 0) return -1;
317 //added on 980905 by adb from original source to add sound kill system
318 // play at most digi_max_channel samples, if possible kill sample with low volume
322 if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing) ) {
323 if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries<digi_max_channels) ) {
324 //mprintf(( 0, "Not stopping loud sound %d.\n", next_handle ));
326 if ( next_handle >= digi_max_channels )
331 //mprintf(( 0, "[SS:%d]", next_handle ));
332 SoundSlots[SampleHandles[next_handle]].playing = 0;
333 SampleHandles[next_handle] = -1;
337 slot = get_free_slot();
338 if (slot<0) return -1;
340 SoundSlots[slot].soundno = soundnum;
341 SoundSlots[slot].samples = GameSounds[soundnum].data;
342 SoundSlots[slot].length = GameSounds[soundnum].length;
343 SoundSlots[slot].volume = fixmul(digi_volume, volume);
344 SoundSlots[slot].pan = pan;
345 SoundSlots[slot].position = 0;
346 SoundSlots[slot].looped = looping;
347 SoundSlots[slot].playing = 1;
349 //added on 980905 by adb to add sound kill system from original sos digi.c
350 reset_sounds_on_channel(slot);
351 SampleHandles[next_handle] = slot;
353 if ( next_handle >= digi_max_channels )
360 //added on 980905 by adb to add sound kill system from original sos digi.c
361 void reset_sounds_on_channel( int channel )
365 for (i=0; i<digi_max_channels; i++)
366 if (SampleHandles[i] == channel)
367 SampleHandles[i] = -1;
371 int digi_start_sound_object(int obj)
375 if (!digi_initialised) return -1;
376 slot = get_free_slot();
378 if (slot<0) return -1;
381 // only use up to half the sound channels for "permanant" sounts
382 if ((SoundObjects[i].flags & SOF_PERMANANT) && (N_active_sound_objects >= max(1,digi_get_max_channels()/4)) )
386 SoundSlots[slot].soundno = SoundObjects[obj].soundnum;
387 SoundSlots[slot].samples = GameSounds[SoundObjects[obj].soundnum].data;
388 SoundSlots[slot].length = GameSounds[SoundObjects[obj].soundnum].length;
389 SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume);
390 SoundSlots[slot].pan = SoundObjects[obj].pan;
391 SoundSlots[slot].position = 0;
392 SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER);
393 SoundSlots[slot].playing = 1;
395 SoundObjects[obj].signature = next_signature++;
396 SoundObjects[obj].handle = slot;
398 SoundObjects[obj].flags |= SOF_PLAYING;
399 //added on 980905 by adb to add sound kill system from original sos digi.c
400 reset_sounds_on_channel(slot);
407 // Play the given sound number.
408 // Volume is max at F1_0.
409 void digi_play_sample( int soundno, fix max_volume )
412 if ( Newdemo_state == ND_STATE_RECORDING )
413 newdemo_record_sound( soundno );
415 soundno = digi_xlat_sound(soundno);
417 if (!digi_initialised) return;
419 if (soundno < 0 ) return;
421 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
424 // Play the given sound number. If the sound is already playing,
426 void digi_play_sample_once( int soundno, fix max_volume )
431 if ( Newdemo_state == ND_STATE_RECORDING )
432 newdemo_record_sound( soundno );
434 soundno = digi_xlat_sound(soundno);
436 if (!digi_initialised) return;
438 if (soundno < 0 ) return;
440 for (i=0; i < MAX_SOUND_SLOTS; i++)
441 if (SoundSlots[i].soundno == soundno)
442 SoundSlots[i].playing = 0;
443 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
447 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) // Volume from 0-0x7fff
452 if ( Newdemo_state == ND_STATE_RECORDING ) {
454 newdemo_record_sound_3d_once( soundno, angle, volume );
456 newdemo_record_sound_3d( soundno, angle, volume );
459 soundno = digi_xlat_sound(soundno);
461 if (!digi_initialised) return;
462 if (soundno < 0 ) return;
464 if (volume < MIN_VOLUME ) return;
465 digi_start_sound(soundno, volume, angle, 0, 0, 0, 0);
468 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 )
470 vms_vector vector_to_sound;
471 fix angle_from_ear, cosang,sinang;
478 max_distance = (max_distance*5)/4; // Make all sounds travel 1.25 times as far.
480 // Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
481 distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
483 if (distance < max_distance ) {
484 int num_search_segs = f2i(max_distance/20);
485 if ( num_search_segs < 1 ) num_search_segs = 1;
487 path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
488 if ( path_distance > -1 ) {
489 *volume = max_volume - fixdiv(path_distance,max_distance);
490 //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
492 angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
493 fix_sincos(angle_from_ear,&sinang,&cosang);
494 //mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
495 if (Config_channels_reversed) cosang *= -1;
496 *pan = (cosang + F1_0)/2;
504 //hack to not start object when loading level
505 int Dont_start_sound_objects = 0;
507 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 )
513 soundnum = digi_xlat_sound(org_soundnum);
515 if ( max_volume < 0 ) return -1;
516 // if ( max_volume > F1_0 ) max_volume = F1_0;
518 if (!digi_initialised) return -1;
519 if (soundnum < 0 ) return -1;
520 if (GameSounds[soundnum].data==NULL) {
524 if ((objnum<0)||(objnum>Highest_object_index))
528 // Hack to keep sounds from building up...
529 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
530 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
535 if ( Newdemo_state == ND_STATE_RECORDING ) {
536 newdemo_record_link_sound_to_object3( org_soundnum, objnum, max_volume, max_distance, loop_start, loop_end );
540 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
541 if (SoundObjects[i].flags==0)
544 if (i==MAX_SOUND_OBJECTS) {
545 mprintf((1, "Too many sound objects!\n" ));
549 SoundObjects[i].signature=next_signature++;
550 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
552 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
553 SoundObjects[i].lo_objnum = objnum;
554 SoundObjects[i].lo_objsignature = Objects[objnum].signature;
555 SoundObjects[i].max_volume = max_volume;
556 SoundObjects[i].max_distance = max_distance;
557 SoundObjects[i].volume = 0;
558 SoundObjects[i].pan = 0;
559 SoundObjects[i].soundnum = soundnum;
560 SoundObjects[i].loop_start = loop_start;
561 SoundObjects[i].loop_end = loop_end;
563 if (Dont_start_sound_objects) { //started at level start
565 SoundObjects[i].flags |= SOF_PERMANANT;
566 SoundObjects[i].handle = -1;
568 objp = &Objects[SoundObjects[i].lo_objnum];
569 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
570 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
571 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
573 //if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
574 digi_start_sound_object(i);
576 // If it's a one-shot sound effect, and it can't start right away, then
577 // just cancel it and be done with it.
578 if ( (SoundObjects[i].handle < 0) && (!(SoundObjects[i].flags & SOF_PLAY_FOREVER)) ) {
579 SoundObjects[i].flags = 0;
584 return SoundObjects[i].signature;
588 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance )
590 return digi_link_sound_to_object3( org_soundnum, objnum, forever, max_volume, max_distance, -1, -1 );
594 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
595 { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); }
597 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
602 soundnum = digi_xlat_sound(org_soundnum);
604 if ( max_volume < 0 ) return -1;
605 // if ( max_volume > F1_0 ) max_volume = F1_0;
607 if (!digi_initialised) return -1;
608 if (soundnum < 0 ) return -1;
609 if (GameSounds[soundnum].data==NULL) {
614 if ((segnum<0)||(segnum>Highest_segment_index))
618 // Hack to keep sounds from building up...
619 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
620 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
624 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
625 if (SoundObjects[i].flags==0)
628 if (i==MAX_SOUND_OBJECTS) {
629 mprintf((1, "Too many sound objects!\n" ));
634 SoundObjects[i].signature=next_signature++;
635 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
637 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
638 SoundObjects[i].lp_segnum = segnum;
639 SoundObjects[i].lp_sidenum = sidenum;
640 SoundObjects[i].lp_position = *pos;
641 SoundObjects[i].soundnum = soundnum;
642 SoundObjects[i].max_volume = max_volume;
643 SoundObjects[i].max_distance = max_distance;
644 SoundObjects[i].volume = 0;
645 SoundObjects[i].pan = 0;
646 SoundObjects[i].loop_start = SoundObjects[i].loop_end = -1;
648 if (Dont_start_sound_objects) { //started at level start
650 SoundObjects[i].flags |= SOF_PERMANANT;
652 SoundObjects[i].handle = -1;
655 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
656 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
657 SoundObjects[i].max_volume,
658 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
660 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
661 digi_start_sound_object(i);
663 // If it's a one-shot sound effect, and it can't start right away, then
664 // just cancel it and be done with it.
665 if ( (SoundObjects[i].handle < 0) && (!(SoundObjects[i].flags & SOF_PLAY_FOREVER)) ) {
666 SoundObjects[i].flags = 0;
671 return SoundObjects[i].signature;
674 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
676 return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
679 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
683 soundnum = digi_xlat_sound(soundnum);
685 if (!digi_initialised) return;
689 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
690 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) ) {
691 if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
692 if ( SoundObjects[i].flags & SOF_PLAYING ) {
693 SoundSlots[SoundObjects[i].handle].playing = 0;
695 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
700 // If this assert happens, it means that there were 2 sounds
701 // that got deleted. Weird, get John.
703 mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
707 void digi_kill_sound_linked_to_object( int objnum )
711 if (!digi_initialised) return;
715 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
716 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) ) {
717 if (SoundObjects[i].lo_objnum == objnum) {
718 if ( SoundObjects[i].flags & SOF_PLAYING ) {
719 SoundSlots[SoundObjects[i].handle].playing = 0;
721 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
726 // If this assert happens, it means that there were 2 sounds
727 // that got deleted. Weird, get John.
729 mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
733 void digi_sync_sounds()
736 int oldvolume, oldpan;
738 if (!digi_initialised) return;
740 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
741 if ( SoundObjects[i].flags & SOF_USED ) {
742 oldvolume = SoundObjects[i].volume;
743 oldpan = SoundObjects[i].pan;
745 if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) ) {
746 // Check if its done.
747 if (SoundObjects[i].flags & SOF_PLAYING) {
748 if (!SoundSlots[SoundObjects[i].handle].playing) {
749 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
750 continue; // Go on to next sound...
755 if ( SoundObjects[i].flags & SOF_LINK_TO_POS ) {
756 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
757 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
758 SoundObjects[i].max_volume,
759 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
761 } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) {
764 objp = &Objects[SoundObjects[i].lo_objnum];
766 if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature)) {
767 // The object that this is linked to is dead, so just end this sound if it is looping.
768 if ( (SoundObjects[i].flags & SOF_PLAYING) && (SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
769 SoundSlots[SoundObjects[i].handle].playing = 0;
771 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
772 continue; // Go on to next sound...
774 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
775 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
776 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
780 if (oldvolume != SoundObjects[i].volume) {
781 if ( SoundObjects[i].volume < MIN_VOLUME ) {
782 // Sound is too far away, so stop it from playing.
783 if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
784 SoundSlots[SoundObjects[i].handle].playing = 0;
785 SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing
788 if (!(SoundObjects[i].flags & SOF_PLAYING)) {
789 digi_start_sound_object(i);
791 SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0);
796 if (oldpan != SoundObjects[i].pan) {
797 if (SoundObjects[i].flags & SOF_PLAYING)
798 SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan;
804 void digi_init_sounds()
808 if (!digi_initialised) return;
810 digi_reset_digi_sounds();
812 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
813 if (digi_sounds_initialized) {
814 if ( SoundObjects[i].flags & SOF_PLAYING ) {
815 SoundSlots[SoundObjects[i].handle].playing=0;
818 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
820 digi_sounds_initialized = 1;
823 //added on 980905 by adb from original source to make sfx volume work
824 void digi_set_digi_volume( int dvolume )
826 dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
827 if ( dvolume > SOUND_MAX_VOLUME )
828 digi_volume = SOUND_MAX_VOLUME;
829 else if ( dvolume < 0 )
832 digi_volume = dvolume;
834 if ( !digi_initialised ) return;
840 void digi_set_volume( int dvolume, int mvolume )
842 digi_set_digi_volume(dvolume);
843 digi_set_midi_volume(mvolume);
844 // mprintf(( 1, "Volume: 0x%x and 0x%x\n", digi_volume, midi_volume ));
847 int digi_is_sound_playing(int soundno)
851 soundno = digi_xlat_sound(soundno);
853 for (i = 0; i < MAX_SOUND_SLOTS; i++)
854 //changed on 980905 by adb: added SoundSlots[i].playing &&
855 if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
862 void digi_pause_all() { }
863 void digi_resume_all() { }
864 void digi_stop_all() {
866 // ... Ano. The lack of this was causing ambient sounds to crash.
867 // fixed, added digi_stop_all 07/19/01 - bluecow
869 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
870 if ( SoundObjects[i].flags & SOF_USED ) {
871 SoundSlots[SoundObjects[i].handle].playing = 0;
872 SoundObjects[i].flags = 0;
877 //added on 980905 by adb to make sound channel setting work
878 void digi_set_max_channels(int n) {
879 digi_max_channels = n;
881 if ( digi_max_channels < 1 )
882 digi_max_channels = 1;
883 if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) )
884 digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS);
886 if ( !digi_initialised ) return;
888 digi_reset_digi_sounds();
891 int digi_get_max_channels() {
892 return digi_max_channels;
896 void digi_stop_sound(int channel)
898 //FIXME: Is this correct? I dunno, it works.
899 SoundSlots[channel].playing=0;
902 void digi_reset_digi_sounds() {
905 for (i=0; i< MAX_SOUND_SLOTS; i++)
906 SoundSlots[i].playing=0;
908 //added on 980905 by adb to reset sound kill system
909 memset(SampleHandles, 255, sizeof(SampleHandles));
915 #if 0 //added/killed on 11/25/98 by Matthew Mueller
916 // MIDI stuff follows.
917 void digi_set_midi_volume( int mvolume ) { }
918 void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
919 void digi_stop_current_song()
928 #endif // end this section kill - MM