1 /* $Id: digi.c,v 1.7 2003-02-24 06:16:17 btb Exp $ */
4 * SDL digital audio support
24 #include "gr.h" // needed for piggy.h
32 int digi_sample_rate=11025;
34 //edited 05/17/99 Matt Mueller - added ifndef NO_ASM
35 //added on 980905 by adb to add inline fixmul for mixer on i386
38 #define do_fixmul(x,y) \
41 asm("imull %2\n\tshrdl %3,%1,%0" \
42 : "=a"(_ax), "=d"(_dx) \
43 : "rm"(y), "i"(16), "0"(x)); \
46 extern inline fix fixmul(fix x, fix y) { return do_fixmul(x,y); }
52 //changed on 980905 by adb to increase number of concurrent sounds
53 #define MAX_SOUND_SLOTS 32
55 #define SOUND_BUFFER_SIZE 512
59 /* This table is used to add two sound values together and pin
60 * the value to avoid overflow. (used with permission from ARDI)
61 * DPH: Taken from SDL/src/SDL_mixer.c.
63 static const Uint8 mix8[] =
65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
77 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
78 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
79 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
80 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
81 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
82 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
83 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
84 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B,
85 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
86 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
87 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
88 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
89 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
90 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,
91 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
92 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
93 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
94 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
95 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4,
96 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
97 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
98 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
99 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xFF,
100 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
101 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
102 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
103 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
104 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
105 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
106 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
107 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
108 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
109 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
110 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
111 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
114 #define SOF_USED 1 // Set if this sample is used
115 #define SOF_PLAYING 2 // Set if this sample is playing on a channel
116 #define SOF_LINK_TO_OBJ 4 // Sound is linked to a moving object. If object dies, then finishes play and quits.
117 #define SOF_LINK_TO_POS 8 // Sound is linked to segment, pos
118 #define SOF_PLAY_FOREVER 16 // Play forever (or until level is stopped), otherwise plays once
120 typedef struct sound_object {
121 short signature; // A unique signature to this sound
122 ubyte flags; // Used to tell if this slot is used and/or currently playing, and how long.
123 fix max_volume; // Max volume that this sound is playing at
124 fix max_distance; // The max distance that this sound can be heard at...
125 int volume; // Volume that this sound is playing at
126 int pan; // Pan value that this sound is playing at
127 int handle; // What handle this sound is playing on. Valid only if SOF_PLAYING is set.
128 short soundnum; // The sound number that is playing
131 short segnum; // Used if SOF_LINK_TO_POS field is used
136 short objnum; // Used if SOF_LINK_TO_OBJ field is used
141 #define lp_segnum link.pos.segnum
142 #define lp_sidenum link.pos.sidenum
143 #define lp_position link.pos.position
145 #define lo_objnum link.obj.objnum
146 #define lo_objsignature link.obj.objsignature
148 #define MAX_SOUND_OBJECTS 16
149 sound_object SoundObjects[MAX_SOUND_OBJECTS];
150 short next_signature=0;
152 //added/changed on 980905 by adb to make sfx volume work, on 990221 by adb changed F1_0 to F1_0 / 2
153 #define SOUND_MAX_VOLUME (F1_0 / 2)
155 int digi_volume = SOUND_MAX_VOLUME;
160 static int digi_initialised = 0;
164 int playing; // Is there a sample playing on this channel?
165 int looped; // Play this sample looped?
166 fix pan; // 0 = far left, 1 = far right
167 fix volume; // 0 = nothing, 1 = fully on
168 //changed on 980905 by adb from char * to unsigned char *
169 unsigned char *samples;
171 unsigned int length; // Length of the sample
172 unsigned int position; // Position we are at at the moment.
173 } SoundSlots[MAX_SOUND_SLOTS];
175 static SDL_AudioSpec WaveSpec;
176 static int digi_sounds_initialized = 0;
178 //added on 980905 by adb to add rotating/volume based sound kill system
179 static int digi_max_channels = 16;
180 static int next_handle = 0;
181 int SampleHandles[32];
182 void reset_sounds_on_channel(int channel);
185 void digi_reset_digi_sounds(void);
187 /* Audio mixing callback */
188 //changed on 980905 by adb to cleanup, add pan support and optimize mixer
189 static void audio_mixcallback(void *userdata, Uint8 *stream, int len)
191 Uint8 *streamend = stream + len;
192 struct sound_slot *sl;
194 for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++)
198 Uint8 *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length;
199 Uint8 *sp = stream, s;
204 if ((x = sl->pan) & 0x8000)
206 vl = 0x20000 - x * 2;
214 vl = fixmul(vl, (x = sl->volume));
216 while (sp < streamend)
225 sldata = sl->samples;
227 v = *(sldata++) - 0x80;
229 *(sp++) = mix8[ s + fixmul(v, vl) + 0x80 ];
231 *(sp++) = mix8[ s + fixmul(v, vr) + 0x80 ];
233 sl->position = sldata - sl->samples;
239 /* Initialise audio devices. */
242 if (SDL_InitSubSystem(SDL_INIT_AUDIO)<0){
243 Error("SDL audio initialisation failed: %s.",SDL_GetError());
245 //added on 980905 by adb to init sound kill system
246 memset(SampleHandles, 255, sizeof(SampleHandles));
249 WaveSpec.freq = 11025;
250 //added/changed by Sam Lantinga on 12/01/98 for new SDL version
251 WaveSpec.format = AUDIO_U8;
252 WaveSpec.channels = 2;
253 //end this section addition/change - SL
254 WaveSpec.samples = SOUND_BUFFER_SIZE;
255 WaveSpec.callback = audio_mixcallback;
257 if ( SDL_OpenAudio(&WaveSpec, NULL) < 0 ) {
258 //edited on 10/05/98 by Matt Mueller - should keep running, just with no sound.
259 Warning("\nError: Couldn't open audio: %s\n", SDL_GetError());
267 digi_initialised = 1;
272 void digi_reset() { }
274 /* Shut down audio */
277 if (!digi_initialised) return;
278 digi_initialised = 0;
282 /* Find the sound which actually equates to a sound number */
283 int digi_xlat_sound(int soundno)
285 if ( soundno < 0 ) return -1;
288 soundno = AltSounds[soundno];
289 if ( soundno == 255 ) return -1;
291 if (Sounds[soundno] == 255) return -1;
293 return Sounds[soundno];
296 static int get_free_slot()
299 for (i=0; i<MAX_SOUND_SLOTS; i++)
301 if (!SoundSlots[i].playing) return i;
306 int digi_start_sound(int soundnum, fix volume, fix pan, int looping, int loop_start, int loop_end, int soundobj)
311 if (!digi_initialised) return -1;
313 if (soundnum < 0) return -1;
315 //added on 980905 by adb from original source to add sound kill system
316 // play at most digi_max_channel samples, if possible kill sample with low volume
320 if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing) )
322 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 SoundSlots[slot].soundno = SoundObjects[obj].soundnum;
382 SoundSlots[slot].samples = GameSounds[SoundObjects[obj].soundnum].data;
383 SoundSlots[slot].length = GameSounds[SoundObjects[obj].soundnum].length;
384 SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume);
385 SoundSlots[slot].pan = SoundObjects[obj].pan;
386 SoundSlots[slot].position = 0;
387 SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER);
388 SoundSlots[slot].playing = 1;
390 SoundObjects[obj].signature = next_signature++;
391 SoundObjects[obj].handle = slot;
393 SoundObjects[obj].flags |= SOF_PLAYING;
394 //added on 980905 by adb to add sound kill system from original sos digi.c
395 reset_sounds_on_channel(slot);
402 // Play the given sound number.
403 // Volume is max at F1_0.
404 void digi_play_sample( int soundno, fix max_volume )
407 if ( Newdemo_state == ND_STATE_RECORDING )
408 newdemo_record_sound( soundno );
410 soundno = digi_xlat_sound(soundno);
412 if (!digi_initialised) return;
414 if (soundno < 0 ) return;
416 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
419 // Play the given sound number. If the sound is already playing,
421 void digi_play_sample_once( int soundno, fix max_volume )
426 if ( Newdemo_state == ND_STATE_RECORDING )
427 newdemo_record_sound( soundno );
429 soundno = digi_xlat_sound(soundno);
431 if (!digi_initialised) return;
433 if (soundno < 0 ) return;
435 for (i=0; i < MAX_SOUND_SLOTS; i++)
436 if (SoundSlots[i].soundno == soundno)
437 SoundSlots[i].playing = 0;
438 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
442 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) // Volume from 0-0x7fff
447 if ( Newdemo_state == ND_STATE_RECORDING ) {
449 newdemo_record_sound_3d_once( soundno, angle, volume );
451 newdemo_record_sound_3d( soundno, angle, volume );
454 soundno = digi_xlat_sound(soundno);
456 if (!digi_initialised) return;
457 if (soundno < 0 ) return;
459 if (volume < MIN_VOLUME ) return;
460 digi_start_sound(soundno, volume, angle, 0, 0, 0, 0);
463 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 )
465 vms_vector vector_to_sound;
466 fix angle_from_ear, cosang,sinang;
473 max_distance = (max_distance*5)/4; // Make all sounds travel 1.25 times as far.
475 // Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
476 distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
478 if (distance < max_distance ) {
479 int num_search_segs = f2i(max_distance/20);
480 if ( num_search_segs < 1 ) num_search_segs = 1;
482 path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
483 if ( path_distance > -1 ) {
484 *volume = max_volume - fixdiv(path_distance,max_distance);
485 //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
487 angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
488 fix_sincos(angle_from_ear,&sinang,&cosang);
489 //mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
490 if (Config_channels_reversed) cosang *= -1;
491 *pan = (cosang + F1_0)/2;
499 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance )
505 soundnum = digi_xlat_sound(org_soundnum);
507 if ( max_volume < 0 ) return -1;
508 // if ( max_volume > F1_0 ) max_volume = F1_0;
510 if (!digi_initialised) return -1;
511 if (soundnum < 0 ) return -1;
512 if (GameSounds[soundnum].data==NULL) {
516 if ((objnum<0)||(objnum>Highest_object_index))
520 // Hack to keep sounds from building up...
521 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
522 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
526 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
527 if (SoundObjects[i].flags==0)
530 if (i==MAX_SOUND_OBJECTS) {
531 mprintf((1, "Too many sound objects!\n" ));
535 SoundObjects[i].signature=next_signature++;
536 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
538 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
539 SoundObjects[i].lo_objnum = objnum;
540 SoundObjects[i].lo_objsignature = Objects[objnum].signature;
541 SoundObjects[i].max_volume = max_volume;
542 SoundObjects[i].max_distance = max_distance;
543 SoundObjects[i].volume = 0;
544 SoundObjects[i].pan = 0;
545 SoundObjects[i].soundnum = soundnum;
547 objp = &Objects[SoundObjects[i].lo_objnum];
548 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
549 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
550 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
552 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
553 digi_start_sound_object(i);
555 return SoundObjects[i].signature;
558 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
559 { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); }
561 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
566 soundnum = digi_xlat_sound(org_soundnum);
568 if ( max_volume < 0 ) return -1;
569 // if ( max_volume > F1_0 ) max_volume = F1_0;
571 if (!digi_initialised) return -1;
572 if (soundnum < 0 ) return -1;
573 if (GameSounds[soundnum].data==NULL) {
578 if ((segnum<0)||(segnum>Highest_segment_index))
582 // Hack to keep sounds from building up...
583 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
584 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
588 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
589 if (SoundObjects[i].flags==0)
592 if (i==MAX_SOUND_OBJECTS) {
593 mprintf((1, "Too many sound objects!\n" ));
598 SoundObjects[i].signature=next_signature++;
599 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
601 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
602 SoundObjects[i].lp_segnum = segnum;
603 SoundObjects[i].lp_sidenum = sidenum;
604 SoundObjects[i].lp_position = *pos;
605 SoundObjects[i].soundnum = soundnum;
606 SoundObjects[i].max_volume = max_volume;
607 SoundObjects[i].max_distance = max_distance;
608 SoundObjects[i].volume = 0;
609 SoundObjects[i].pan = 0;
610 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
611 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
612 SoundObjects[i].max_volume,
613 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
615 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
616 digi_start_sound_object(i);
618 return SoundObjects[i].signature;
621 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
623 return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
626 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
630 soundnum = digi_xlat_sound(soundnum);
632 if (!digi_initialised) return;
636 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
637 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) ) {
638 if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
639 if ( SoundObjects[i].flags & SOF_PLAYING ) {
640 SoundSlots[SoundObjects[i].handle].playing = 0;
642 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
647 // If this assert happens, it means that there were 2 sounds
648 // that got deleted. Weird, get John.
650 mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
654 void digi_kill_sound_linked_to_object( int objnum )
658 if (!digi_initialised) return;
662 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
663 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) ) {
664 if (SoundObjects[i].lo_objnum == objnum) {
665 if ( SoundObjects[i].flags & SOF_PLAYING ) {
666 SoundSlots[SoundObjects[i].handle].playing = 0;
668 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
673 // If this assert happens, it means that there were 2 sounds
674 // that got deleted. Weird, get John.
676 mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
680 void digi_sync_sounds()
683 int oldvolume, oldpan;
685 if (!digi_initialised) return;
687 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
688 if ( SoundObjects[i].flags & SOF_USED ) {
689 oldvolume = SoundObjects[i].volume;
690 oldpan = SoundObjects[i].pan;
692 if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) ) {
693 // Check if its done.
694 if (SoundObjects[i].flags & SOF_PLAYING) {
695 if (!SoundSlots[SoundObjects[i].handle].playing) {
696 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
697 continue; // Go on to next sound...
702 if ( SoundObjects[i].flags & SOF_LINK_TO_POS ) {
703 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
704 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
705 SoundObjects[i].max_volume,
706 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
708 } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) {
711 objp = &Objects[SoundObjects[i].lo_objnum];
713 if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature)) {
714 // The object that this is linked to is dead, so just end this sound if it is looping.
715 if ( (SoundObjects[i].flags & SOF_PLAYING) && (SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
716 SoundSlots[SoundObjects[i].handle].playing = 0;
718 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
719 continue; // Go on to next sound...
721 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
722 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
723 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
727 if (oldvolume != SoundObjects[i].volume) {
728 if ( SoundObjects[i].volume < MIN_VOLUME ) {
729 // Sound is too far away, so stop it from playing.
730 if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
731 SoundSlots[SoundObjects[i].handle].playing = 0;
732 SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing
735 if (!(SoundObjects[i].flags & SOF_PLAYING)) {
736 digi_start_sound_object(i);
738 SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0);
743 if (oldpan != SoundObjects[i].pan) {
744 if (SoundObjects[i].flags & SOF_PLAYING)
745 SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan;
751 void digi_init_sounds()
755 if (!digi_initialised) return;
757 digi_reset_digi_sounds();
759 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
760 if (digi_sounds_initialized) {
761 if ( SoundObjects[i].flags & SOF_PLAYING ) {
762 SoundSlots[SoundObjects[i].handle].playing=0;
765 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
767 digi_sounds_initialized = 1;
770 //added on 980905 by adb from original source to make sfx volume work
771 void digi_set_digi_volume( int dvolume )
773 dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
774 if ( dvolume > SOUND_MAX_VOLUME )
775 digi_volume = SOUND_MAX_VOLUME;
776 else if ( dvolume < 0 )
779 digi_volume = dvolume;
781 if ( !digi_initialised ) return;
787 void digi_set_volume( int dvolume, int mvolume )
789 digi_set_digi_volume(dvolume);
790 digi_set_midi_volume(mvolume);
791 // mprintf(( 1, "Volume: 0x%x and 0x%x\n", digi_volume, midi_volume ));
794 int digi_is_sound_playing(int soundno)
798 soundno = digi_xlat_sound(soundno);
800 for (i = 0; i < MAX_SOUND_SLOTS; i++)
801 //changed on 980905 by adb: added SoundSlots[i].playing &&
802 if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
809 void digi_pause_all() { }
810 void digi_resume_all() { }
811 void digi_stop_all() {
813 // ... Ano. The lack of this was causing ambient sounds to crash.
814 // fixed, added digi_stop_all 07/19/01 - bluecow
816 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
817 if ( SoundObjects[i].flags & SOF_USED ) {
818 SoundSlots[SoundObjects[i].handle].playing = 0;
819 SoundObjects[i].flags = 0;
824 //added on 980905 by adb to make sound channel setting work
825 void digi_set_max_channels(int n) {
826 digi_max_channels = n;
828 if ( digi_max_channels < 1 )
829 digi_max_channels = 1;
830 if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) )
831 digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS);
833 if ( !digi_initialised ) return;
835 digi_reset_digi_sounds();
838 int digi_get_max_channels() {
839 return digi_max_channels;
843 void digi_stop_sound(int channel)
845 //FIXME: Is this correct? I dunno, it works.
846 SoundSlots[channel].playing=0;
849 void digi_reset_digi_sounds() {
852 for (i=0; i< MAX_SOUND_SLOTS; i++)
853 SoundSlots[i].playing=0;
855 //added on 980905 by adb to reset sound kill system
856 memset(SampleHandles, 255, sizeof(SampleHandles));
862 // MIDI stuff follows.
863 //added/killed on 11/25/98 by Matthew Mueller
864 //void digi_set_midi_volume( int mvolume ) { }
865 //void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
866 //void digi_stop_current_song()
875 //end this section kill - MM