1 /* $Id: digi.c,v 1.5 2003-01-15 02:42:41 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 return Sounds[soundno];
294 static int get_free_slot()
297 for (i=0; i<MAX_SOUND_SLOTS; i++)
299 if (!SoundSlots[i].playing) return i;
304 int digi_start_sound(int soundnum, fix volume, fix pan, int unknown1, int unknown2, int unknown3, int unknown4)
309 if (!digi_initialised) return -1;
311 //added on 980905 by adb from original source to add sound kill system
312 // play at most digi_max_channel samples, if possible kill sample with low volume
316 if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing) )
318 if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries<digi_max_channels) )
320 //mprintf(( 0, "Not stopping loud sound %d.\n", next_handle ));
322 if ( next_handle >= digi_max_channels )
327 //mprintf(( 0, "[SS:%d]", next_handle ));
328 SoundSlots[SampleHandles[next_handle]].playing = 0;
329 SampleHandles[next_handle] = -1;
333 slot = get_free_slot();
334 if (slot<0) return -1;
336 SoundSlots[slot].soundno = soundnum;
337 SoundSlots[slot].samples = GameSounds[soundnum].data;
338 SoundSlots[slot].length = GameSounds[soundnum].length;
339 SoundSlots[slot].volume = fixmul(digi_volume, volume);
340 SoundSlots[slot].pan = pan;
341 SoundSlots[slot].position = 0;
342 SoundSlots[slot].looped = 0;
343 SoundSlots[slot].playing = 1;
345 //added on 980905 by adb to add sound kill system from original sos digi.c
346 reset_sounds_on_channel(slot);
347 SampleHandles[next_handle] = slot;
349 if ( next_handle >= digi_max_channels )
356 //added on 980905 by adb to add sound kill system from original sos digi.c
357 void reset_sounds_on_channel( int channel )
361 for (i=0; i<digi_max_channels; i++)
362 if (SampleHandles[i] == channel)
363 SampleHandles[i] = -1;
367 int digi_start_sound_object(int obj)
371 if (!digi_initialised) return -1;
372 slot = get_free_slot();
374 if (slot<0) return -1;
377 SoundSlots[slot].soundno = SoundObjects[obj].soundnum;
378 SoundSlots[slot].samples = GameSounds[SoundObjects[obj].soundnum].data;
379 SoundSlots[slot].length = GameSounds[SoundObjects[obj].soundnum].length;
380 SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume);
381 SoundSlots[slot].pan = SoundObjects[obj].pan;
382 SoundSlots[slot].position = 0;
383 SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER);
384 SoundSlots[slot].playing = 1;
386 SoundObjects[obj].signature = next_signature++;
387 SoundObjects[obj].handle = slot;
389 SoundObjects[obj].flags |= SOF_PLAYING;
390 //added on 980905 by adb to add sound kill system from original sos digi.c
391 reset_sounds_on_channel(slot);
398 // Play the given sound number.
399 // Volume is max at F1_0.
400 void digi_play_sample( int soundno, fix max_volume )
403 if ( Newdemo_state == ND_STATE_RECORDING )
404 newdemo_record_sound( soundno );
406 soundno = digi_xlat_sound(soundno);
408 if (!digi_initialised) return;
410 if (soundno < 0 ) return;
412 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
415 // Play the given sound number. If the sound is already playing,
417 void digi_play_sample_once( int soundno, fix max_volume )
422 if ( Newdemo_state == ND_STATE_RECORDING )
423 newdemo_record_sound( soundno );
425 soundno = digi_xlat_sound(soundno);
427 if (!digi_initialised) return;
429 if (soundno < 0 ) return;
431 for (i=0; i < MAX_SOUND_SLOTS; i++)
432 if (SoundSlots[i].soundno == soundno)
433 SoundSlots[i].playing = 0;
434 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
438 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) // Volume from 0-0x7fff
443 if ( Newdemo_state == ND_STATE_RECORDING ) {
445 newdemo_record_sound_3d_once( soundno, angle, volume );
447 newdemo_record_sound_3d( soundno, angle, volume );
450 soundno = digi_xlat_sound(soundno);
452 if (!digi_initialised) return;
453 if (soundno < 0 ) return;
455 if (volume < MIN_VOLUME ) return;
456 digi_start_sound(soundno, volume, angle, 0, 0, 0, 0);
459 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 )
461 vms_vector vector_to_sound;
462 fix angle_from_ear, cosang,sinang;
469 max_distance = (max_distance*5)/4; // Make all sounds travel 1.25 times as far.
471 // Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
472 distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
474 if (distance < max_distance ) {
475 int num_search_segs = f2i(max_distance/20);
476 if ( num_search_segs < 1 ) num_search_segs = 1;
478 path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
479 if ( path_distance > -1 ) {
480 *volume = max_volume - fixdiv(path_distance,max_distance);
481 //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
483 angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
484 fix_sincos(angle_from_ear,&sinang,&cosang);
485 //mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
486 if (Config_channels_reversed) cosang *= -1;
487 *pan = (cosang + F1_0)/2;
495 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance )
501 soundnum = digi_xlat_sound(org_soundnum);
503 if ( max_volume < 0 ) return -1;
504 // if ( max_volume > F1_0 ) max_volume = F1_0;
506 if (!digi_initialised) return -1;
507 if (soundnum < 0 ) return -1;
508 if (GameSounds[soundnum].data==NULL) {
512 if ((objnum<0)||(objnum>Highest_object_index))
516 // Hack to keep sounds from building up...
517 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
518 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
522 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
523 if (SoundObjects[i].flags==0)
526 if (i==MAX_SOUND_OBJECTS) {
527 mprintf((1, "Too many sound objects!\n" ));
531 SoundObjects[i].signature=next_signature++;
532 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
534 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
535 SoundObjects[i].lo_objnum = objnum;
536 SoundObjects[i].lo_objsignature = Objects[objnum].signature;
537 SoundObjects[i].max_volume = max_volume;
538 SoundObjects[i].max_distance = max_distance;
539 SoundObjects[i].volume = 0;
540 SoundObjects[i].pan = 0;
541 SoundObjects[i].soundnum = soundnum;
543 objp = &Objects[SoundObjects[i].lo_objnum];
544 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
545 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
546 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
548 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
549 digi_start_sound_object(i);
551 return SoundObjects[i].signature;
554 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
555 { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); }
557 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
562 soundnum = digi_xlat_sound(org_soundnum);
564 if ( max_volume < 0 ) return -1;
565 // if ( max_volume > F1_0 ) max_volume = F1_0;
567 if (!digi_initialised) return -1;
568 if (soundnum < 0 ) return -1;
569 if (GameSounds[soundnum].data==NULL) {
574 if ((segnum<0)||(segnum>Highest_segment_index))
578 // Hack to keep sounds from building up...
579 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
580 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
584 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
585 if (SoundObjects[i].flags==0)
588 if (i==MAX_SOUND_OBJECTS) {
589 mprintf((1, "Too many sound objects!\n" ));
594 SoundObjects[i].signature=next_signature++;
595 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
597 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
598 SoundObjects[i].lp_segnum = segnum;
599 SoundObjects[i].lp_sidenum = sidenum;
600 SoundObjects[i].lp_position = *pos;
601 SoundObjects[i].soundnum = soundnum;
602 SoundObjects[i].max_volume = max_volume;
603 SoundObjects[i].max_distance = max_distance;
604 SoundObjects[i].volume = 0;
605 SoundObjects[i].pan = 0;
606 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
607 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
608 SoundObjects[i].max_volume,
609 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
611 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
612 digi_start_sound_object(i);
614 return SoundObjects[i].signature;
617 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
619 return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
622 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
626 soundnum = digi_xlat_sound(soundnum);
628 if (!digi_initialised) return;
632 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
633 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) ) {
634 if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
635 if ( SoundObjects[i].flags & SOF_PLAYING ) {
636 SoundSlots[SoundObjects[i].handle].playing = 0;
638 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
643 // If this assert happens, it means that there were 2 sounds
644 // that got deleted. Weird, get John.
646 mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
650 void digi_kill_sound_linked_to_object( int objnum )
654 if (!digi_initialised) return;
658 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
659 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) ) {
660 if (SoundObjects[i].lo_objnum == objnum) {
661 if ( SoundObjects[i].flags & SOF_PLAYING ) {
662 SoundSlots[SoundObjects[i].handle].playing = 0;
664 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
669 // If this assert happens, it means that there were 2 sounds
670 // that got deleted. Weird, get John.
672 mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
676 void digi_sync_sounds()
679 int oldvolume, oldpan;
681 if (!digi_initialised) return;
683 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
684 if ( SoundObjects[i].flags & SOF_USED ) {
685 oldvolume = SoundObjects[i].volume;
686 oldpan = SoundObjects[i].pan;
688 if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) ) {
689 // Check if its done.
690 if (SoundObjects[i].flags & SOF_PLAYING) {
691 if (!SoundSlots[SoundObjects[i].handle].playing) {
692 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
693 continue; // Go on to next sound...
698 if ( SoundObjects[i].flags & SOF_LINK_TO_POS ) {
699 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
700 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
701 SoundObjects[i].max_volume,
702 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
704 } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) {
707 objp = &Objects[SoundObjects[i].lo_objnum];
709 if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature)) {
710 // The object that this is linked to is dead, so just end this sound if it is looping.
711 if ( (SoundObjects[i].flags & SOF_PLAYING) && (SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
712 SoundSlots[SoundObjects[i].handle].playing = 0;
714 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
715 continue; // Go on to next sound...
717 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
718 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
719 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
723 if (oldvolume != SoundObjects[i].volume) {
724 if ( SoundObjects[i].volume < MIN_VOLUME ) {
725 // Sound is too far away, so stop it from playing.
726 if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
727 SoundSlots[SoundObjects[i].handle].playing = 0;
728 SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing
731 if (!(SoundObjects[i].flags & SOF_PLAYING)) {
732 digi_start_sound_object(i);
734 SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0);
739 if (oldpan != SoundObjects[i].pan) {
740 if (SoundObjects[i].flags & SOF_PLAYING)
741 SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan;
747 void digi_init_sounds()
751 if (!digi_initialised) return;
753 digi_reset_digi_sounds();
755 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
756 if (digi_sounds_initialized) {
757 if ( SoundObjects[i].flags & SOF_PLAYING ) {
758 SoundSlots[SoundObjects[i].handle].playing=0;
761 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
763 digi_sounds_initialized = 1;
766 //added on 980905 by adb from original source to make sfx volume work
767 void digi_set_digi_volume( int dvolume )
769 dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
770 if ( dvolume > SOUND_MAX_VOLUME )
771 digi_volume = SOUND_MAX_VOLUME;
772 else if ( dvolume < 0 )
775 digi_volume = dvolume;
777 if ( !digi_initialised ) return;
783 void digi_set_volume( int dvolume, int mvolume )
785 digi_set_digi_volume(dvolume);
786 digi_set_midi_volume(mvolume);
787 // mprintf(( 1, "Volume: 0x%x and 0x%x\n", digi_volume, midi_volume ));
790 int digi_is_sound_playing(int soundno)
794 soundno = digi_xlat_sound(soundno);
796 for (i = 0; i < MAX_SOUND_SLOTS; i++)
797 //changed on 980905 by adb: added SoundSlots[i].playing &&
798 if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
805 void digi_pause_all() { }
806 void digi_resume_all() { }
807 void digi_stop_all() {
809 // ... Ano. The lack of this was causing ambient sounds to crash.
810 // fixed, added digi_stop_all 07/19/01 - bluecow
812 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
813 if ( SoundObjects[i].flags & SOF_USED ) {
814 SoundSlots[SoundObjects[i].handle].playing = 0;
815 SoundObjects[i].flags = 0;
820 //added on 980905 by adb to make sound channel setting work
821 void digi_set_max_channels(int n) {
822 digi_max_channels = n;
824 if ( digi_max_channels < 1 )
825 digi_max_channels = 1;
826 if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) )
827 digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS);
829 if ( !digi_initialised ) return;
831 digi_reset_digi_sounds();
834 int digi_get_max_channels() {
835 return digi_max_channels;
839 void digi_reset_digi_sounds() {
842 for (i=0; i< MAX_SOUND_SLOTS; i++)
843 SoundSlots[i].playing=0;
845 //added on 980905 by adb to reset sound kill system
846 memset(SampleHandles, 255, sizeof(SampleHandles));
852 // MIDI stuff follows.
853 //added/killed on 11/25/98 by Matthew Mueller
854 //void digi_set_midi_volume( int mvolume ) { }
855 //void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
856 //void digi_stop_current_song()
865 //end this section kill - MM