2 * $Source: /cvs/cvsroot/d2x/arch/sdl/digi.c,v $
5 * $Date: 2001-11-14 10:42:15 $
7 * SDL digital audio support
9 * $Log: not supported by cvs2svn $
10 * Revision 1.1 2001/10/25 08:25:34 bradleyb
11 * Finished moving stuff to arch/blah. I know, it's ugly, but It'll be easier to sync with d1x.
13 * Revision 1.3 2001/10/12 06:36:55 bradleyb
14 * Fix a gcc 3.0 warning, couple updates from d1x
16 * Revision 1.2 2001/01/29 13:53:28 bradleyb
17 * Fixed build, minor fixes
30 #include <SDL/SDL_audio.h>
37 #include "gr.h" // needed for piggy.h
45 int digi_sample_rate=11025;
47 //edited 05/17/99 Matt Mueller - added ifndef NO_ASM
48 //added on 980905 by adb to add inline fixmul for mixer on i386
51 #define do_fixmul(x,y) \
54 asm("imull %2\n\tshrdl %3,%1,%0" \
55 : "=a"(_ax), "=d"(_dx) \
56 : "rm"(y), "i"(16), "0"(x)); \
59 extern inline fix fixmul(fix x, fix y) { return do_fixmul(x,y); }
65 //changed on 980905 by adb to increase number of concurrent sounds
66 #define MAX_SOUND_SLOTS 32
68 #define SOUND_BUFFER_SIZE 512
72 /* This table is used to add two sound values together and pin
73 * the value to avoid overflow. (used with permission from ARDI)
74 * DPH: Taken from SDL/src/SDL_mixer.c.
76 static const Uint8 mix8[] =
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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, 0x01, 0x02, 0x03,
90 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
91 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
92 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
93 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
94 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
95 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
96 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
97 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B,
98 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
99 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
100 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
101 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
102 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
103 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,
104 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
105 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
106 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
107 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
108 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4,
109 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
110 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
111 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
112 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xFF,
113 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
114 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
115 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
116 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
117 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
118 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
119 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 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,
127 #define SOF_USED 1 // Set if this sample is used
128 #define SOF_PLAYING 2 // Set if this sample is playing on a channel
129 #define SOF_LINK_TO_OBJ 4 // Sound is linked to a moving object. If object dies, then finishes play and quits.
130 #define SOF_LINK_TO_POS 8 // Sound is linked to segment, pos
131 #define SOF_PLAY_FOREVER 16 // Play forever (or until level is stopped), otherwise plays once
133 typedef struct sound_object {
134 short signature; // A unique signature to this sound
135 ubyte flags; // Used to tell if this slot is used and/or currently playing, and how long.
136 fix max_volume; // Max volume that this sound is playing at
137 fix max_distance; // The max distance that this sound can be heard at...
138 int volume; // Volume that this sound is playing at
139 int pan; // Pan value that this sound is playing at
140 int handle; // What handle this sound is playing on. Valid only if SOF_PLAYING is set.
141 short soundnum; // The sound number that is playing
144 short segnum; // Used if SOF_LINK_TO_POS field is used
149 short objnum; // Used if SOF_LINK_TO_OBJ field is used
154 #define lp_segnum link.pos.segnum
155 #define lp_sidenum link.pos.sidenum
156 #define lp_position link.pos.position
158 #define lo_objnum link.obj.objnum
159 #define lo_objsignature link.obj.objsignature
161 #define MAX_SOUND_OBJECTS 16
162 sound_object SoundObjects[MAX_SOUND_OBJECTS];
163 short next_signature=0;
165 //added/changed on 980905 by adb to make sfx volume work, on 990221 by adb changed F1_0 to F1_0 / 2
166 #define SOUND_MAX_VOLUME (F1_0 / 2)
168 int digi_volume = SOUND_MAX_VOLUME;
173 static int digi_initialised = 0;
177 int playing; // Is there a sample playing on this channel?
178 int looped; // Play this sample looped?
179 fix pan; // 0 = far left, 1 = far right
180 fix volume; // 0 = nothing, 1 = fully on
181 //changed on 980905 by adb from char * to unsigned char *
182 unsigned char *samples;
184 unsigned int length; // Length of the sample
185 unsigned int position; // Position we are at at the moment.
186 } SoundSlots[MAX_SOUND_SLOTS];
188 static SDL_AudioSpec WaveSpec;
189 static int digi_sounds_initialized = 0;
191 //added on 980905 by adb to add rotating/volume based sound kill system
192 static int digi_max_channels = 16;
193 static int next_handle = 0;
194 int SampleHandles[32];
195 void reset_sounds_on_channel(int channel);
198 void digi_reset_digi_sounds(void);
200 /* Audio mixing callback */
201 //changed on 980905 by adb to cleanup, add pan support and optimize mixer
202 static void audio_mixcallback(void *userdata, Uint8 *stream, int len)
204 Uint8 *streamend = stream + len;
205 struct sound_slot *sl;
207 for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++)
211 Uint8 *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length;
212 Uint8 *sp = stream, s;
217 if ((x = sl->pan) & 0x8000)
219 vl = 0x20000 - x * 2;
227 vl = fixmul(vl, (x = sl->volume));
229 while (sp < streamend)
238 sldata = sl->samples;
240 v = *(sldata++) - 0x80;
242 *(sp++) = mix8[ s + fixmul(v, vl) + 0x80 ];
244 *(sp++) = mix8[ s + fixmul(v, vr) + 0x80 ];
246 sl->position = sldata - sl->samples;
252 /* Initialise audio devices. */
255 if (SDL_InitSubSystem(SDL_INIT_AUDIO)<0){
256 Error("SDL audio initialisation failed: %s.",SDL_GetError());
258 //added on 980905 by adb to init sound kill system
259 memset(SampleHandles, 255, sizeof(SampleHandles));
262 WaveSpec.freq = 11025;
263 //added/changed by Sam Lantinga on 12/01/98 for new SDL version
264 WaveSpec.format = AUDIO_U8;
265 WaveSpec.channels = 2;
266 //end this section addition/change - SL
267 WaveSpec.samples = SOUND_BUFFER_SIZE;
268 WaveSpec.callback = audio_mixcallback;
270 if ( SDL_OpenAudio(&WaveSpec, NULL) < 0 ) {
271 //edited on 10/05/98 by Matt Mueller - should keep running, just with no sound.
272 Warning("\nError: Couldn't open audio: %s\n", SDL_GetError());
280 digi_initialised = 1;
285 void digi_reset() { }
287 /* Shut down audio */
290 if (!digi_initialised) return;
291 digi_initialised = 0;
295 /* Find the sound which actually equates to a sound number */
296 int digi_xlat_sound(int soundno)
298 if ( soundno < 0 ) return -1;
301 soundno = AltSounds[soundno];
302 if ( soundno == 255 ) return -1;
304 return Sounds[soundno];
307 static int get_free_slot()
310 for (i=0; i<MAX_SOUND_SLOTS; i++)
312 if (!SoundSlots[i].playing) return i;
317 int digi_start_sound(int soundnum, fix volume, fix pan, int unknown1, int unknown2, int unknown3, int unknown4)
322 if (!digi_initialised) return -1;
324 //added on 980905 by adb from original source to add sound kill system
325 // play at most digi_max_channel samples, if possible kill sample with low volume
329 if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing) )
331 if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries<digi_max_channels) )
333 //mprintf(( 0, "Not stopping loud sound %d.\n", next_handle ));
335 if ( next_handle >= digi_max_channels )
340 //mprintf(( 0, "[SS:%d]", next_handle ));
341 SoundSlots[SampleHandles[next_handle]].playing = 0;
342 SampleHandles[next_handle] = -1;
346 slot = get_free_slot();
347 if (slot<0) return -1;
349 SoundSlots[slot].soundno = soundnum;
350 SoundSlots[slot].samples = GameSounds[soundnum].data;
351 SoundSlots[slot].length = GameSounds[soundnum].length;
352 SoundSlots[slot].volume = fixmul(digi_volume, volume);
353 SoundSlots[slot].pan = pan;
354 SoundSlots[slot].position = 0;
355 SoundSlots[slot].looped = 0;
356 SoundSlots[slot].playing = 1;
358 //added on 980905 by adb to add sound kill system from original sos digi.c
359 reset_sounds_on_channel(slot);
360 SampleHandles[next_handle] = slot;
362 if ( next_handle >= digi_max_channels )
369 //added on 980905 by adb to add sound kill system from original sos digi.c
370 void reset_sounds_on_channel( int channel )
374 for (i=0; i<digi_max_channels; i++)
375 if (SampleHandles[i] == channel)
376 SampleHandles[i] = -1;
380 int digi_start_sound_object(int obj)
384 if (!digi_initialised) return -1;
385 slot = get_free_slot();
387 if (slot<0) return -1;
390 SoundSlots[slot].soundno = SoundObjects[obj].soundnum;
391 SoundSlots[slot].samples = GameSounds[SoundObjects[obj].soundnum].data;
392 SoundSlots[slot].length = GameSounds[SoundObjects[obj].soundnum].length;
393 SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume);
394 SoundSlots[slot].pan = SoundObjects[obj].pan;
395 SoundSlots[slot].position = 0;
396 SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER);
397 SoundSlots[slot].playing = 1;
399 SoundObjects[obj].signature = next_signature++;
400 SoundObjects[obj].handle = slot;
402 SoundObjects[obj].flags |= SOF_PLAYING;
403 //added on 980905 by adb to add sound kill system from original sos digi.c
404 reset_sounds_on_channel(slot);
411 // Play the given sound number.
412 // Volume is max at F1_0.
413 void digi_play_sample( int soundno, fix max_volume )
416 if ( Newdemo_state == ND_STATE_RECORDING )
417 newdemo_record_sound( soundno );
419 soundno = digi_xlat_sound(soundno);
421 if (!digi_initialised) return;
423 if (soundno < 0 ) return;
425 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
428 // Play the given sound number. If the sound is already playing,
430 void digi_play_sample_once( int soundno, fix max_volume )
435 if ( Newdemo_state == ND_STATE_RECORDING )
436 newdemo_record_sound( soundno );
438 soundno = digi_xlat_sound(soundno);
440 if (!digi_initialised) return;
442 if (soundno < 0 ) return;
444 for (i=0; i < MAX_SOUND_SLOTS; i++)
445 if (SoundSlots[i].soundno == soundno)
446 SoundSlots[i].playing = 0;
447 digi_start_sound(soundno, max_volume, F0_5, 0, 0, 0, 0);
451 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) // Volume from 0-0x7fff
456 if ( Newdemo_state == ND_STATE_RECORDING ) {
458 newdemo_record_sound_3d_once( soundno, angle, volume );
460 newdemo_record_sound_3d( soundno, angle, volume );
463 soundno = digi_xlat_sound(soundno);
465 if (!digi_initialised) return;
466 if (soundno < 0 ) return;
468 if (volume < MIN_VOLUME ) return;
469 digi_start_sound(soundno, volume, angle, 0, 0, 0, 0);
472 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 )
474 vms_vector vector_to_sound;
475 fix angle_from_ear, cosang,sinang;
482 max_distance = (max_distance*5)/4; // Make all sounds travel 1.25 times as far.
484 // Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
485 distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
487 if (distance < max_distance ) {
488 int num_search_segs = f2i(max_distance/20);
489 if ( num_search_segs < 1 ) num_search_segs = 1;
491 path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
492 if ( path_distance > -1 ) {
493 *volume = max_volume - fixdiv(path_distance,max_distance);
494 //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
496 angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
497 fix_sincos(angle_from_ear,&sinang,&cosang);
498 //mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
499 if (Config_channels_reversed) cosang *= -1;
500 *pan = (cosang + F1_0)/2;
508 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance )
514 soundnum = digi_xlat_sound(org_soundnum);
516 if ( max_volume < 0 ) return -1;
517 // if ( max_volume > F1_0 ) max_volume = F1_0;
519 if (!digi_initialised) return -1;
520 if (soundnum < 0 ) return -1;
521 if (GameSounds[soundnum].data==NULL) {
525 if ((objnum<0)||(objnum>Highest_object_index))
529 // Hack to keep sounds from building up...
530 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
531 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
535 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
536 if (SoundObjects[i].flags==0)
539 if (i==MAX_SOUND_OBJECTS) {
540 mprintf((1, "Too many sound objects!\n" ));
544 SoundObjects[i].signature=next_signature++;
545 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
547 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
548 SoundObjects[i].lo_objnum = objnum;
549 SoundObjects[i].lo_objsignature = Objects[objnum].signature;
550 SoundObjects[i].max_volume = max_volume;
551 SoundObjects[i].max_distance = max_distance;
552 SoundObjects[i].volume = 0;
553 SoundObjects[i].pan = 0;
554 SoundObjects[i].soundnum = soundnum;
556 objp = &Objects[SoundObjects[i].lo_objnum];
557 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
558 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
559 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
561 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
562 digi_start_sound_object(i);
564 return SoundObjects[i].signature;
567 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
568 { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); }
570 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
575 soundnum = digi_xlat_sound(org_soundnum);
577 if ( max_volume < 0 ) return -1;
578 // if ( max_volume > F1_0 ) max_volume = F1_0;
580 if (!digi_initialised) return -1;
581 if (soundnum < 0 ) return -1;
582 if (GameSounds[soundnum].data==NULL) {
587 if ((segnum<0)||(segnum>Highest_segment_index))
591 // Hack to keep sounds from building up...
592 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
593 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
597 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
598 if (SoundObjects[i].flags==0)
601 if (i==MAX_SOUND_OBJECTS) {
602 mprintf((1, "Too many sound objects!\n" ));
607 SoundObjects[i].signature=next_signature++;
608 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
610 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
611 SoundObjects[i].lp_segnum = segnum;
612 SoundObjects[i].lp_sidenum = sidenum;
613 SoundObjects[i].lp_position = *pos;
614 SoundObjects[i].soundnum = soundnum;
615 SoundObjects[i].max_volume = max_volume;
616 SoundObjects[i].max_distance = max_distance;
617 SoundObjects[i].volume = 0;
618 SoundObjects[i].pan = 0;
619 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
620 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
621 SoundObjects[i].max_volume,
622 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
624 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
625 digi_start_sound_object(i);
627 return SoundObjects[i].signature;
630 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
632 return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
635 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
639 soundnum = digi_xlat_sound(soundnum);
641 if (!digi_initialised) return;
645 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
646 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) ) {
647 if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
648 if ( SoundObjects[i].flags & SOF_PLAYING ) {
649 SoundSlots[SoundObjects[i].handle].playing = 0;
651 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
656 // If this assert happens, it means that there were 2 sounds
657 // that got deleted. Weird, get John.
659 mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
663 void digi_kill_sound_linked_to_object( int objnum )
667 if (!digi_initialised) return;
671 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
672 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) ) {
673 if (SoundObjects[i].lo_objnum == objnum) {
674 if ( SoundObjects[i].flags & SOF_PLAYING ) {
675 SoundSlots[SoundObjects[i].handle].playing = 0;
677 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
682 // If this assert happens, it means that there were 2 sounds
683 // that got deleted. Weird, get John.
685 mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
689 void digi_sync_sounds()
692 int oldvolume, oldpan;
694 if (!digi_initialised) return;
696 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
697 if ( SoundObjects[i].flags & SOF_USED ) {
698 oldvolume = SoundObjects[i].volume;
699 oldpan = SoundObjects[i].pan;
701 if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) ) {
702 // Check if its done.
703 if (SoundObjects[i].flags & SOF_PLAYING) {
704 if (!SoundSlots[SoundObjects[i].handle].playing) {
705 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
706 continue; // Go on to next sound...
711 if ( SoundObjects[i].flags & SOF_LINK_TO_POS ) {
712 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
713 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
714 SoundObjects[i].max_volume,
715 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
717 } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) {
720 objp = &Objects[SoundObjects[i].lo_objnum];
722 if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature)) {
723 // The object that this is linked to is dead, so just end this sound if it is looping.
724 if ( (SoundObjects[i].flags & SOF_PLAYING) && (SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
725 SoundSlots[SoundObjects[i].handle].playing = 0;
727 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
728 continue; // Go on to next sound...
730 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
731 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
732 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
736 if (oldvolume != SoundObjects[i].volume) {
737 if ( SoundObjects[i].volume < MIN_VOLUME ) {
738 // Sound is too far away, so stop it from playing.
739 if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
740 SoundSlots[SoundObjects[i].handle].playing = 0;
741 SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing
744 if (!(SoundObjects[i].flags & SOF_PLAYING)) {
745 digi_start_sound_object(i);
747 SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0);
752 if (oldpan != SoundObjects[i].pan) {
753 if (SoundObjects[i].flags & SOF_PLAYING)
754 SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan;
760 void digi_init_sounds()
764 if (!digi_initialised) return;
766 digi_reset_digi_sounds();
768 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
769 if (digi_sounds_initialized) {
770 if ( SoundObjects[i].flags & SOF_PLAYING ) {
771 SoundSlots[SoundObjects[i].handle].playing=0;
774 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
776 digi_sounds_initialized = 1;
779 //added on 980905 by adb from original source to make sfx volume work
780 void digi_set_digi_volume( int dvolume )
782 dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
783 if ( dvolume > SOUND_MAX_VOLUME )
784 digi_volume = SOUND_MAX_VOLUME;
785 else if ( dvolume < 0 )
788 digi_volume = dvolume;
790 if ( !digi_initialised ) return;
796 void digi_set_volume( int dvolume, int mvolume )
798 digi_set_digi_volume(dvolume);
799 digi_set_midi_volume(mvolume);
800 // mprintf(( 1, "Volume: 0x%x and 0x%x\n", digi_volume, midi_volume ));
803 int digi_is_sound_playing(int soundno)
807 soundno = digi_xlat_sound(soundno);
809 for (i = 0; i < MAX_SOUND_SLOTS; i++)
810 //changed on 980905 by adb: added SoundSlots[i].playing &&
811 if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
818 void digi_pause_all() { }
819 void digi_resume_all() { }
820 void digi_stop_all() {
822 // ... Ano. The lack of this was causing ambient sounds to crash.
823 // fixed, added digi_stop_all 07/19/01 - bluecow
825 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
826 if ( SoundObjects[i].flags & SOF_USED ) {
827 SoundSlots[SoundObjects[i].handle].playing = 0;
828 SoundObjects[i].flags = 0;
833 //added on 980905 by adb to make sound channel setting work
834 void digi_set_max_channels(int n) {
835 digi_max_channels = n;
837 if ( digi_max_channels < 1 )
838 digi_max_channels = 1;
839 if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) )
840 digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS);
842 if ( !digi_initialised ) return;
844 digi_reset_digi_sounds();
847 int digi_get_max_channels() {
848 return digi_max_channels;
852 void digi_reset_digi_sounds() {
855 for (i=0; i< MAX_SOUND_SLOTS; i++)
856 SoundSlots[i].playing=0;
858 //added on 980905 by adb to reset sound kill system
859 memset(SampleHandles, 255, sizeof(SampleHandles));
865 // MIDI stuff follows.
866 //added/killed on 11/25/98 by Matthew Mueller
867 //void digi_set_midi_volume( int mvolume ) { }
868 //void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
869 //void digi_stop_current_song()
878 //end this section kill - MM