2 * $Source: /cvs/cvsroot/d2x/arch/sdl/digi.c,v $
5 * $Date: 2002-02-16 02:08:30 $
7 * SDL digital audio support
9 * $Log: not supported by cvs2svn $
10 * Revision 1.2 2001/11/14 10:42:15 bradleyb
11 * implemented digi_set_volume
13 * Revision 1.1 2001/10/25 08:25:34 bradleyb
14 * Finished moving stuff to arch/blah. I know, it's ugly, but It'll be easier to sync with d1x.
16 * Revision 1.3 2001/10/12 06:36:55 bradleyb
17 * Fix a gcc 3.0 warning, couple updates from d1x
19 * Revision 1.2 2001/01/29 13:53:28 bradleyb
20 * Fixed build, minor fixes
33 #include <SDL/SDL_audio.h>
35 #ifndef SDL_VERSION_ATLEAST
44 #include "gr.h" // needed for piggy.h
52 int digi_sample_rate=11025;
54 //edited 05/17/99 Matt Mueller - added ifndef NO_ASM
55 //added on 980905 by adb to add inline fixmul for mixer on i386
58 #define do_fixmul(x,y) \
61 asm("imull %2\n\tshrdl %3,%1,%0" \
62 : "=a"(_ax), "=d"(_dx) \
63 : "rm"(y), "i"(16), "0"(x)); \
66 extern inline fix fixmul(fix x, fix y) { return do_fixmul(x,y); }
72 //changed on 980905 by adb to increase number of concurrent sounds
73 #define MAX_SOUND_SLOTS 32
75 #define SOUND_BUFFER_SIZE 512
79 /* This table is used to add two sound values together and pin
80 * the value to avoid overflow. (used with permission from ARDI)
81 * DPH: Taken from SDL/src/SDL_mixer.c.
83 static const Uint8 mix8[] =
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
97 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
98 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
99 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
100 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
101 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
102 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
103 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
104 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B,
105 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
106 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
107 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
108 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
109 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
110 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,
111 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
112 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
113 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
114 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
115 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4,
116 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
117 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
118 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
119 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xFF,
120 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
121 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
122 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
123 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
124 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
125 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
126 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
127 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
128 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
129 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
130 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
131 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
134 #define SOF_USED 1 // Set if this sample is used
135 #define SOF_PLAYING 2 // Set if this sample is playing on a channel
136 #define SOF_LINK_TO_OBJ 4 // Sound is linked to a moving object. If object dies, then finishes play and quits.
137 #define SOF_LINK_TO_POS 8 // Sound is linked to segment, pos
138 #define SOF_PLAY_FOREVER 16 // Play forever (or until level is stopped), otherwise plays once
140 typedef struct sound_object {
141 short signature; // A unique signature to this sound
142 ubyte flags; // Used to tell if this slot is used and/or currently playing, and how long.
143 fix max_volume; // Max volume that this sound is playing at
144 fix max_distance; // The max distance that this sound can be heard at...
145 int volume; // Volume that this sound is playing at
146 int pan; // Pan value that this sound is playing at
147 int handle; // What handle this sound is playing on. Valid only if SOF_PLAYING is set.
148 short soundnum; // The sound number that is playing
151 short segnum; // Used if SOF_LINK_TO_POS field is used
156 short objnum; // Used if SOF_LINK_TO_OBJ field is used
161 #define lp_segnum link.pos.segnum
162 #define lp_sidenum link.pos.sidenum
163 #define lp_position link.pos.position
165 #define lo_objnum link.obj.objnum
166 #define lo_objsignature link.obj.objsignature
168 #define MAX_SOUND_OBJECTS 16
169 sound_object SoundObjects[MAX_SOUND_OBJECTS];
170 short next_signature=0;
172 //added/changed on 980905 by adb to make sfx volume work, on 990221 by adb changed F1_0 to F1_0 / 2
173 #define SOUND_MAX_VOLUME (F1_0 / 2)
175 int digi_volume = SOUND_MAX_VOLUME;
180 static int digi_initialised = 0;
184 int playing; // Is there a sample playing on this channel?
185 int looped; // Play this sample looped?
186 fix pan; // 0 = far left, 1 = far right
187 fix volume; // 0 = nothing, 1 = fully on
188 //changed on 980905 by adb from char * to unsigned char *
189 unsigned char *samples;
191 unsigned int length; // Length of the sample
192 unsigned int position; // Position we are at at the moment.
193 } SoundSlots[MAX_SOUND_SLOTS];
195 static SDL_AudioSpec WaveSpec;
196 static int digi_sounds_initialized = 0;
198 //added on 980905 by adb to add rotating/volume based sound kill system
199 static int digi_max_channels = 16;
200 static int next_handle = 0;
201 int SampleHandles[32];
202 void reset_sounds_on_channel(int channel);
205 void digi_reset_digi_sounds(void);
207 /* Audio mixing callback */
208 //changed on 980905 by adb to cleanup, add pan support and optimize mixer
209 static void audio_mixcallback(void *userdata, Uint8 *stream, int len)
211 Uint8 *streamend = stream + len;
212 struct sound_slot *sl;
214 for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++)
218 Uint8 *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length;
219 Uint8 *sp = stream, s;
224 if ((x = sl->pan) & 0x8000)
226 vl = 0x20000 - x * 2;
234 vl = fixmul(vl, (x = sl->volume));
236 while (sp < streamend)
245 sldata = sl->samples;
247 v = *(sldata++) - 0x80;
249 *(sp++) = mix8[ s + fixmul(v, vl) + 0x80 ];
251 *(sp++) = mix8[ s + fixmul(v, vr) + 0x80 ];
253 sl->position = sldata - sl->samples;
259 /* Initialise audio devices. */
262 #if SDL_VERSION_ATLEAST(1,1,0)
263 if (SDL_InitSubSystem(SDL_INIT_AUDIO)<0){
264 Error("SDL audio initialisation failed: %s.",SDL_GetError());
267 //added on 980905 by adb to init sound kill system
268 memset(SampleHandles, 255, sizeof(SampleHandles));
271 WaveSpec.freq = 11025;
272 //added/changed by Sam Lantinga on 12/01/98 for new SDL version
273 WaveSpec.format = AUDIO_U8;
274 WaveSpec.channels = 2;
275 //end this section addition/change - SL
276 WaveSpec.samples = SOUND_BUFFER_SIZE;
277 WaveSpec.callback = audio_mixcallback;
279 if ( SDL_OpenAudio(&WaveSpec, NULL) < 0 ) {
280 //edited on 10/05/98 by Matt Mueller - should keep running, just with no sound.
281 Warning("\nError: Couldn't open audio: %s\n", SDL_GetError());
289 digi_initialised = 1;
294 void digi_reset() { }
296 /* Shut down audio */
299 if (!digi_initialised) return;
300 digi_initialised = 0;
304 /* Find the sound which actually equates to a sound number */
305 int digi_xlat_sound(int soundno)
307 if ( soundno < 0 ) return -1;
310 soundno = AltSounds[soundno];
311 if ( soundno == 255 ) return -1;
313 return Sounds[soundno];
316 static int get_free_slot()
319 for (i=0; i<MAX_SOUND_SLOTS; i++)
321 if (!SoundSlots[i].playing) return i;
326 int digi_start_sound(int soundnum, fix volume, fix pan, int unknown1, int unknown2, int unknown3, int unknown4)
331 if (!digi_initialised) return -1;
333 //added on 980905 by adb from original source to add sound kill system
334 // play at most digi_max_channel samples, if possible kill sample with low volume
338 if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing) )
340 if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries<digi_max_channels) )
342 //mprintf(( 0, "Not stopping loud sound %d.\n", next_handle ));
344 if ( next_handle >= digi_max_channels )
349 //mprintf(( 0, "[SS:%d]", next_handle ));
350 SoundSlots[SampleHandles[next_handle]].playing = 0;
351 SampleHandles[next_handle] = -1;
355 slot = get_free_slot();
356 if (slot<0) return -1;
358 SoundSlots[slot].soundno = soundnum;
359 SoundSlots[slot].samples = GameSounds[soundnum].data;
360 SoundSlots[slot].length = GameSounds[soundnum].length;
361 SoundSlots[slot].volume = fixmul(digi_volume, volume);
362 SoundSlots[slot].pan = pan;
363 SoundSlots[slot].position = 0;
364 SoundSlots[slot].looped = 0;
365 SoundSlots[slot].playing = 1;
367 //added on 980905 by adb to add sound kill system from original sos digi.c
368 reset_sounds_on_channel(slot);
369 SampleHandles[next_handle] = slot;
371 if ( next_handle >= digi_max_channels )
378 //added on 980905 by adb to add sound kill system from original sos digi.c
379 void reset_sounds_on_channel( int channel )
383 for (i=0; i<digi_max_channels; i++)
384 if (SampleHandles[i] == channel)
385 SampleHandles[i] = -1;
389 int digi_start_sound_object(int obj)
393 if (!digi_initialised) return -1;
394 slot = get_free_slot();
396 if (slot<0) return -1;
399 SoundSlots[slot].soundno = SoundObjects[obj].soundnum;
400 SoundSlots[slot].samples = GameSounds[SoundObjects[obj].soundnum].data;
401 SoundSlots[slot].length = GameSounds[SoundObjects[obj].soundnum].length;
402 SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume);
403 SoundSlots[slot].pan = SoundObjects[obj].pan;
404 SoundSlots[slot].position = 0;
405 SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER);
406 SoundSlots[slot].playing = 1;
408 SoundObjects[obj].signature = next_signature++;
409 SoundObjects[obj].handle = slot;
411 SoundObjects[obj].flags |= SOF_PLAYING;
412 //added on 980905 by adb to add sound kill system from original sos digi.c
413 reset_sounds_on_channel(slot);
420 // Play the given sound number.
421 // Volume is max at F1_0.
422 void digi_play_sample( int soundno, fix max_volume )
425 if ( Newdemo_state == ND_STATE_RECORDING )
426 newdemo_record_sound( soundno );
428 soundno = digi_xlat_sound(soundno);
430 if (!digi_initialised) return;
432 if (soundno < 0 ) return;
434 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
437 // Play the given sound number. If the sound is already playing,
439 void digi_play_sample_once( int soundno, fix max_volume )
444 if ( Newdemo_state == ND_STATE_RECORDING )
445 newdemo_record_sound( soundno );
447 soundno = digi_xlat_sound(soundno);
449 if (!digi_initialised) return;
451 if (soundno < 0 ) return;
453 for (i=0; i < MAX_SOUND_SLOTS; i++)
454 if (SoundSlots[i].soundno == soundno)
455 SoundSlots[i].playing = 0;
456 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
460 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) // Volume from 0-0x7fff
465 if ( Newdemo_state == ND_STATE_RECORDING ) {
467 newdemo_record_sound_3d_once( soundno, angle, volume );
469 newdemo_record_sound_3d( soundno, angle, volume );
472 soundno = digi_xlat_sound(soundno);
474 if (!digi_initialised) return;
475 if (soundno < 0 ) return;
477 if (volume < MIN_VOLUME ) return;
478 digi_start_sound(soundno, volume, angle, 0, 0, 0, 0);
481 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 )
483 vms_vector vector_to_sound;
484 fix angle_from_ear, cosang,sinang;
491 max_distance = (max_distance*5)/4; // Make all sounds travel 1.25 times as far.
493 // Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
494 distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
496 if (distance < max_distance ) {
497 int num_search_segs = f2i(max_distance/20);
498 if ( num_search_segs < 1 ) num_search_segs = 1;
500 path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
501 if ( path_distance > -1 ) {
502 *volume = max_volume - fixdiv(path_distance,max_distance);
503 //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
505 angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
506 fix_sincos(angle_from_ear,&sinang,&cosang);
507 //mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
508 if (Config_channels_reversed) cosang *= -1;
509 *pan = (cosang + F1_0)/2;
517 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance )
523 soundnum = digi_xlat_sound(org_soundnum);
525 if ( max_volume < 0 ) return -1;
526 // if ( max_volume > F1_0 ) max_volume = F1_0;
528 if (!digi_initialised) return -1;
529 if (soundnum < 0 ) return -1;
530 if (GameSounds[soundnum].data==NULL) {
534 if ((objnum<0)||(objnum>Highest_object_index))
538 // Hack to keep sounds from building up...
539 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
540 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
544 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
545 if (SoundObjects[i].flags==0)
548 if (i==MAX_SOUND_OBJECTS) {
549 mprintf((1, "Too many sound objects!\n" ));
553 SoundObjects[i].signature=next_signature++;
554 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
556 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
557 SoundObjects[i].lo_objnum = objnum;
558 SoundObjects[i].lo_objsignature = Objects[objnum].signature;
559 SoundObjects[i].max_volume = max_volume;
560 SoundObjects[i].max_distance = max_distance;
561 SoundObjects[i].volume = 0;
562 SoundObjects[i].pan = 0;
563 SoundObjects[i].soundnum = soundnum;
565 objp = &Objects[SoundObjects[i].lo_objnum];
566 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
567 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
568 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
570 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
571 digi_start_sound_object(i);
573 return SoundObjects[i].signature;
576 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
577 { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); }
579 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
584 soundnum = digi_xlat_sound(org_soundnum);
586 if ( max_volume < 0 ) return -1;
587 // if ( max_volume > F1_0 ) max_volume = F1_0;
589 if (!digi_initialised) return -1;
590 if (soundnum < 0 ) return -1;
591 if (GameSounds[soundnum].data==NULL) {
596 if ((segnum<0)||(segnum>Highest_segment_index))
600 // Hack to keep sounds from building up...
601 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
602 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
606 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
607 if (SoundObjects[i].flags==0)
610 if (i==MAX_SOUND_OBJECTS) {
611 mprintf((1, "Too many sound objects!\n" ));
616 SoundObjects[i].signature=next_signature++;
617 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
619 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
620 SoundObjects[i].lp_segnum = segnum;
621 SoundObjects[i].lp_sidenum = sidenum;
622 SoundObjects[i].lp_position = *pos;
623 SoundObjects[i].soundnum = soundnum;
624 SoundObjects[i].max_volume = max_volume;
625 SoundObjects[i].max_distance = max_distance;
626 SoundObjects[i].volume = 0;
627 SoundObjects[i].pan = 0;
628 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
629 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
630 SoundObjects[i].max_volume,
631 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
633 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
634 digi_start_sound_object(i);
636 return SoundObjects[i].signature;
639 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
641 return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
644 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
648 soundnum = digi_xlat_sound(soundnum);
650 if (!digi_initialised) return;
654 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
655 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) ) {
656 if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
657 if ( SoundObjects[i].flags & SOF_PLAYING ) {
658 SoundSlots[SoundObjects[i].handle].playing = 0;
660 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
665 // If this assert happens, it means that there were 2 sounds
666 // that got deleted. Weird, get John.
668 mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
672 void digi_kill_sound_linked_to_object( int objnum )
676 if (!digi_initialised) return;
680 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
681 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) ) {
682 if (SoundObjects[i].lo_objnum == objnum) {
683 if ( SoundObjects[i].flags & SOF_PLAYING ) {
684 SoundSlots[SoundObjects[i].handle].playing = 0;
686 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
691 // If this assert happens, it means that there were 2 sounds
692 // that got deleted. Weird, get John.
694 mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
698 void digi_sync_sounds()
701 int oldvolume, oldpan;
703 if (!digi_initialised) return;
705 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
706 if ( SoundObjects[i].flags & SOF_USED ) {
707 oldvolume = SoundObjects[i].volume;
708 oldpan = SoundObjects[i].pan;
710 if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) ) {
711 // Check if its done.
712 if (SoundObjects[i].flags & SOF_PLAYING) {
713 if (!SoundSlots[SoundObjects[i].handle].playing) {
714 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
715 continue; // Go on to next sound...
720 if ( SoundObjects[i].flags & SOF_LINK_TO_POS ) {
721 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
722 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
723 SoundObjects[i].max_volume,
724 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
726 } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) {
729 objp = &Objects[SoundObjects[i].lo_objnum];
731 if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature)) {
732 // The object that this is linked to is dead, so just end this sound if it is looping.
733 if ( (SoundObjects[i].flags & SOF_PLAYING) && (SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
734 SoundSlots[SoundObjects[i].handle].playing = 0;
736 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
737 continue; // Go on to next sound...
739 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
740 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
741 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
745 if (oldvolume != SoundObjects[i].volume) {
746 if ( SoundObjects[i].volume < MIN_VOLUME ) {
747 // Sound is too far away, so stop it from playing.
748 if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
749 SoundSlots[SoundObjects[i].handle].playing = 0;
750 SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing
753 if (!(SoundObjects[i].flags & SOF_PLAYING)) {
754 digi_start_sound_object(i);
756 SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0);
761 if (oldpan != SoundObjects[i].pan) {
762 if (SoundObjects[i].flags & SOF_PLAYING)
763 SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan;
769 void digi_init_sounds()
773 if (!digi_initialised) return;
775 digi_reset_digi_sounds();
777 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
778 if (digi_sounds_initialized) {
779 if ( SoundObjects[i].flags & SOF_PLAYING ) {
780 SoundSlots[SoundObjects[i].handle].playing=0;
783 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
785 digi_sounds_initialized = 1;
788 //added on 980905 by adb from original source to make sfx volume work
789 void digi_set_digi_volume( int dvolume )
791 dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
792 if ( dvolume > SOUND_MAX_VOLUME )
793 digi_volume = SOUND_MAX_VOLUME;
794 else if ( dvolume < 0 )
797 digi_volume = dvolume;
799 if ( !digi_initialised ) return;
805 void digi_set_volume( int dvolume, int mvolume )
807 digi_set_digi_volume(dvolume);
808 digi_set_midi_volume(mvolume);
809 // mprintf(( 1, "Volume: 0x%x and 0x%x\n", digi_volume, midi_volume ));
812 int digi_is_sound_playing(int soundno)
816 soundno = digi_xlat_sound(soundno);
818 for (i = 0; i < MAX_SOUND_SLOTS; i++)
819 //changed on 980905 by adb: added SoundSlots[i].playing &&
820 if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
827 void digi_pause_all() { }
828 void digi_resume_all() { }
829 void digi_stop_all() {
831 // ... Ano. The lack of this was causing ambient sounds to crash.
832 // fixed, added digi_stop_all 07/19/01 - bluecow
834 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
835 if ( SoundObjects[i].flags & SOF_USED ) {
836 SoundSlots[SoundObjects[i].handle].playing = 0;
837 SoundObjects[i].flags = 0;
842 //added on 980905 by adb to make sound channel setting work
843 void digi_set_max_channels(int n) {
844 digi_max_channels = n;
846 if ( digi_max_channels < 1 )
847 digi_max_channels = 1;
848 if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) )
849 digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS);
851 if ( !digi_initialised ) return;
853 digi_reset_digi_sounds();
856 int digi_get_max_channels() {
857 return digi_max_channels;
861 void digi_reset_digi_sounds() {
864 for (i=0; i< MAX_SOUND_SLOTS; i++)
865 SoundSlots[i].playing=0;
867 //added on 980905 by adb to reset sound kill system
868 memset(SampleHandles, 255, sizeof(SampleHandles));
874 // MIDI stuff follows.
875 //added/killed on 11/25/98 by Matthew Mueller
876 //void digi_set_midi_volume( int mvolume ) { }
877 //void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
878 //void digi_stop_current_song()
887 //end this section kill - MM