1 /* $Id: alsadigi.c,v 1.2 2003-03-13 00:20:21 btb Exp $ */
4 * ALSA digital audio support
11 #include <sys/asoundlib.h>
18 #include "gr.h" // needed for piggy.h
26 //edited 05/17/99 Matt Mueller - added ifndef NO_ASM
27 //added on 980905 by adb to add inline fixmul for mixer on i386
30 #define do_fixmul(x,y) \
33 asm("imull %2\n\tshrdl %3,%1,%0" \
34 : "=a"(_ax), "=d"(_dx) \
35 : "rm"(y), "i"(16), "0"(x)); \
38 extern inline fix fixmul(fix x, fix y) { return do_fixmul(x,y); }
44 //changed on 980905 by adb to increase number of concurrent sounds
45 #define MAX_SOUND_SLOTS 32
47 #define SOUND_BUFFER_SIZE 512
51 /* This table is used to add two sound values together and pin
52 * the value to avoid overflow. (used with permission from ARDI)
53 * DPH: Taken from SDL/src/SDL_mixer.c.
55 static const ubyte mix8[] =
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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, 0x01, 0x02, 0x03,
69 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
70 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
71 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
72 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
73 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
74 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
75 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
76 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B,
77 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
78 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
79 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
80 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
81 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
82 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,
83 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
84 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
85 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
86 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
87 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4,
88 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
89 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
90 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
91 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xFF,
92 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
93 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
94 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
95 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
96 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
97 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
98 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
99 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 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,
106 #define SOF_USED 1 // Set if this sample is used
107 #define SOF_PLAYING 2 // Set if this sample is playing on a channel
108 #define SOF_LINK_TO_OBJ 4 // Sound is linked to a moving object. If object dies, then finishes play and quits.
109 #define SOF_LINK_TO_POS 8 // Sound is linked to segment, pos
110 #define SOF_PLAY_FOREVER 16 // Play forever (or until level is stopped), otherwise plays once
112 typedef struct sound_object {
113 short signature; // A unique signature to this sound
114 ubyte flags; // Used to tell if this slot is used and/or currently playing, and how long.
115 fix max_volume; // Max volume that this sound is playing at
116 fix max_distance; // The max distance that this sound can be heard at...
117 int volume; // Volume that this sound is playing at
118 int pan; // Pan value that this sound is playing at
119 int handle; // What handle this sound is playing on. Valid only if SOF_PLAYING is set.
120 short soundnum; // The sound number that is playing
123 short segnum; // Used if SOF_LINK_TO_POS field is used
128 short objnum; // Used if SOF_LINK_TO_OBJ field is used
133 #define lp_segnum link.pos.segnum
134 #define lp_sidenum link.pos.sidenum
135 #define lp_position link.pos.position
137 #define lo_objnum link.obj.objnum
138 #define lo_objsignature link.obj.objsignature
140 #define MAX_SOUND_OBJECTS 16
141 sound_object SoundObjects[MAX_SOUND_OBJECTS];
142 short next_signature=0;
144 //added/changed on 980905 by adb to make sfx volume work, on 990221 by adb changed F1_0 to F1_0 / 2
145 #define SOUND_MAX_VOLUME (F1_0 / 2)
147 int digi_volume = SOUND_MAX_VOLUME;
152 static int digi_initialised = 0;
156 int playing; // Is there a sample playing on this channel?
157 int looped; // Play this sample looped?
158 fix pan; // 0 = far left, 1 = far right
159 fix volume; // 0 = nothing, 1 = fully on
160 //changed on 980905 by adb from char * to unsigned char *
161 unsigned char *samples;
163 unsigned int length; // Length of the sample
164 unsigned int position; // Position we are at at the moment.
165 } SoundSlots[MAX_SOUND_SLOTS];
167 static int digi_sounds_initialized = 0;
169 //added on 980905 by adb to add rotating/volume based sound kill system
170 static int digi_max_channels = 16;
171 static int next_handle = 0;
172 int SampleHandles[32];
173 void reset_sounds_on_channel(int channel);
176 /* Threading/ALSA stuff */
177 #define LOCK() pthread_mutex_lock(&mutex)
178 #define UNLOCK() pthread_mutex_unlock(&mutex)
181 pthread_mutex_t mutex;
184 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, ubyte *stream, int len)
191 ubyte *streamend = stream + len;
192 struct sound_slot *sl;
194 for (sl = SoundSlots; sl < SoundSlots + MAX_SOUND_SLOTS; sl++)
198 ubyte *sldata = sl->samples + sl->position, *slend = sl->samples + sl->length;
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;
228 *(sp++) = mix8[ *sp + fixmul(v, vl) + 0x80 ];
229 *(sp++) = mix8[ *sp + fixmul(v, vr) + 0x80 ];
231 sl->position = sldata - sl->samples;
237 void *mixer_thread(void *data) {
240 /* Allow ourselves to be asynchronously cancelled */
241 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
243 // printf("i=%d\n",i++);
244 memset(buffer, 0x80, 512);
246 audio_mixcallback(NULL,buffer,512);
248 snd_pcm_write(snd_devhandle, buffer, 512);
254 /* Initialise audio devices. */
257 int card=0, device=0, err;
258 snd_pcm_format_t format;
259 snd_pcm_playback_params_t params;
261 pthread_mutexattr_t mutexattr;
263 //added on 980905 by adb to init sound kill system
264 memset(SampleHandles, 255, sizeof(SampleHandles));
267 /* Open the ALSA sound device */
268 if ((err = snd_pcm_open(&snd_devhandle, card, device,
269 SND_PCM_OPEN_PLAYBACK)) < 0) {
270 fprintf(stderr, "open failed: %s\n", snd_strerror( err ));
274 memset(&format, 0, sizeof(format));
275 format.format = SND_PCM_SFMT_U8;
278 if ((err = snd_pcm_playback_format(snd_devhandle, &format)) < 0) {
279 fprintf(stderr, "format setup failed: %s\n", snd_strerror( err ));
280 snd_pcm_close( snd_devhandle );
284 memset(¶ms, 0, sizeof(params));
285 params.fragment_size=512;
286 params.fragments_max=2;
287 params.fragments_room=1;
288 if ((err = snd_pcm_playback_params(snd_devhandle, ¶ms)) < 0) {
289 fprintf(stderr, "params setup failed: %s\n", snd_strerror( err ));
290 snd_pcm_close( snd_devhandle );
294 /* Start the mixer thread */
296 /* We really should check the results of these */
297 pthread_mutexattr_init(&mutexattr);
298 pthread_mutex_init(&mutex,&mutexattr);
299 pthread_mutexattr_destroy(&mutexattr);
301 if (pthread_attr_init(&attr) != 0) {
302 fprintf(stderr, "failed to init attr\n");
303 snd_pcm_close( snd_devhandle );
307 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
309 pthread_create(&thread_id,&attr,mixer_thread,NULL);
310 pthread_attr_destroy(&attr);
313 digi_initialised = 1;
318 void digi_reset() { }
320 /* Shut down audio */
323 if (!digi_initialised) return;
324 digi_initialised = 0;
325 snd_pcm_close(snd_devhandle);
326 pthread_mutex_destroy(&mutex);
327 pthread_cancel(thread_id);
330 /* Find the sound which actually equates to a sound number */
331 int digi_xlat_sound(int soundno)
333 if ( soundno < 0 ) return -1;
336 soundno = AltSounds[soundno];
337 if ( soundno == 255 ) return -1;
339 return Sounds[soundno];
342 static int get_free_slot()
345 for (i=0; i<MAX_SOUND_SLOTS; i++)
347 if (!SoundSlots[i].playing) return i;
352 int digi_start_sound(int soundnum, fix volume, fix pan)
357 if (!digi_initialised) return -1;
359 //added on 980905 by adb from original source to add sound kill system
360 // play at most digi_max_channel samples, if possible kill sample with low volume
364 if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing) )
366 if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries<digi_max_channels) )
368 //mprintf(( 0, "Not stopping loud sound %d.\n", next_handle ));
370 if ( next_handle >= digi_max_channels )
375 //mprintf(( 0, "[SS:%d]", next_handle ));
376 SoundSlots[SampleHandles[next_handle]].playing = 0;
377 SampleHandles[next_handle] = -1;
381 slot = get_free_slot();
382 if (slot<0) return -1;
384 SoundSlots[slot].soundno = soundnum;
385 SoundSlots[slot].samples = GameSounds[soundnum].data;
386 SoundSlots[slot].length = GameSounds[soundnum].length;
387 SoundSlots[slot].volume = fixmul(digi_volume, volume);
388 SoundSlots[slot].pan = pan;
389 SoundSlots[slot].position = 0;
390 SoundSlots[slot].looped = 0;
391 SoundSlots[slot].playing = 1;
393 //added on 980905 by adb to add sound kill system from original sos digi.c
394 reset_sounds_on_channel(slot);
395 SampleHandles[next_handle] = slot;
397 if ( next_handle >= digi_max_channels )
404 //added on 980905 by adb to add sound kill system from original sos digi.c
405 void reset_sounds_on_channel( int channel )
409 for (i=0; i<digi_max_channels; i++)
410 if (SampleHandles[i] == channel)
411 SampleHandles[i] = -1;
415 int digi_start_sound_object(int obj)
419 if (!digi_initialised) return -1;
421 slot = get_free_slot();
423 if (slot<0) { UNLOCK(); return -1; }
426 SoundSlots[slot].soundno = SoundObjects[obj].soundnum;
427 SoundSlots[slot].samples = GameSounds[SoundObjects[obj].soundnum].data;
428 SoundSlots[slot].length = GameSounds[SoundObjects[obj].soundnum].length;
429 SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume);
430 SoundSlots[slot].pan = SoundObjects[obj].pan;
431 SoundSlots[slot].position = 0;
432 SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER);
433 SoundSlots[slot].playing = 1;
435 SoundObjects[obj].signature = next_signature++;
436 SoundObjects[obj].handle = slot;
438 SoundObjects[obj].flags |= SOF_PLAYING;
439 //added on 980905 by adb to add sound kill system from original sos digi.c
440 reset_sounds_on_channel(slot);
448 // Play the given sound number.
449 // Volume is max at F1_0.
450 void digi_play_sample( int soundno, fix max_volume )
453 if ( Newdemo_state == ND_STATE_RECORDING )
454 newdemo_record_sound( soundno );
456 soundno = digi_xlat_sound(soundno);
458 if (!digi_initialised) return;
460 if (soundno < 0 ) return;
462 digi_start_sound(soundno, max_volume, F0_5);
465 // Play the given sound number. If the sound is already playing,
467 void digi_play_sample_once( int soundno, fix max_volume )
472 if ( Newdemo_state == ND_STATE_RECORDING )
473 newdemo_record_sound( soundno );
475 soundno = digi_xlat_sound(soundno);
477 if (!digi_initialised) return;
479 if (soundno < 0 ) return;
482 for (i=0; i < MAX_SOUND_SLOTS; i++)
483 if (SoundSlots[i].soundno == soundno)
484 SoundSlots[i].playing = 0;
486 digi_start_sound(soundno, max_volume, F0_5);
490 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) // Volume from 0-0x7fff
495 if ( Newdemo_state == ND_STATE_RECORDING ) {
497 newdemo_record_sound_3d_once( soundno, angle, volume );
499 newdemo_record_sound_3d( soundno, angle, volume );
502 soundno = digi_xlat_sound(soundno);
504 if (!digi_initialised) return;
505 if (soundno < 0 ) return;
507 if (volume < MIN_VOLUME ) return;
508 digi_start_sound(soundno, volume, angle);
511 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 )
513 vms_vector vector_to_sound;
514 fix angle_from_ear, cosang,sinang;
521 max_distance = (max_distance*5)/4; // Make all sounds travel 1.25 times as far.
523 // Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
524 distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
526 if (distance < max_distance ) {
527 int num_search_segs = f2i(max_distance/20);
528 if ( num_search_segs < 1 ) num_search_segs = 1;
530 path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
531 if ( path_distance > -1 ) {
532 *volume = max_volume - fixdiv(path_distance,max_distance);
533 //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
535 angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
536 fix_sincos(angle_from_ear,&sinang,&cosang);
537 //mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
538 if (Config_channels_reversed) cosang *= -1;
539 *pan = (cosang + F1_0)/2;
547 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance )
553 soundnum = digi_xlat_sound(org_soundnum);
555 if ( max_volume < 0 ) return -1;
556 // if ( max_volume > F1_0 ) max_volume = F1_0;
558 if (!digi_initialised) return -1;
559 if (soundnum < 0 ) return -1;
560 if (GameSounds[soundnum].data==NULL) {
564 if ((objnum<0)||(objnum>Highest_object_index))
568 // Hack to keep sounds from building up...
569 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
570 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
574 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
575 if (SoundObjects[i].flags==0)
578 if (i==MAX_SOUND_OBJECTS) {
579 mprintf((1, "Too many sound objects!\n" ));
583 SoundObjects[i].signature=next_signature++;
584 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
586 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
587 SoundObjects[i].lo_objnum = objnum;
588 SoundObjects[i].lo_objsignature = Objects[objnum].signature;
589 SoundObjects[i].max_volume = max_volume;
590 SoundObjects[i].max_distance = max_distance;
591 SoundObjects[i].volume = 0;
592 SoundObjects[i].pan = 0;
593 SoundObjects[i].soundnum = soundnum;
595 objp = &Objects[SoundObjects[i].lo_objnum];
596 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
597 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
598 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
600 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
601 digi_start_sound_object(i);
603 return SoundObjects[i].signature;
606 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
607 { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); }
609 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
614 soundnum = digi_xlat_sound(org_soundnum);
616 if ( max_volume < 0 ) return -1;
617 // if ( max_volume > F1_0 ) max_volume = F1_0;
619 if (!digi_initialised) return -1;
620 if (soundnum < 0 ) return -1;
621 if (GameSounds[soundnum].data==NULL) {
626 if ((segnum<0)||(segnum>Highest_segment_index))
630 // Hack to keep sounds from building up...
631 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
632 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
636 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
637 if (SoundObjects[i].flags==0)
640 if (i==MAX_SOUND_OBJECTS) {
641 mprintf((1, "Too many sound objects!\n" ));
646 SoundObjects[i].signature=next_signature++;
647 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
649 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
650 SoundObjects[i].lp_segnum = segnum;
651 SoundObjects[i].lp_sidenum = sidenum;
652 SoundObjects[i].lp_position = *pos;
653 SoundObjects[i].soundnum = soundnum;
654 SoundObjects[i].max_volume = max_volume;
655 SoundObjects[i].max_distance = max_distance;
656 SoundObjects[i].volume = 0;
657 SoundObjects[i].pan = 0;
658 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
659 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
660 SoundObjects[i].max_volume,
661 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
663 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
664 digi_start_sound_object(i);
666 return SoundObjects[i].signature;
669 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
671 return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
674 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
678 soundnum = digi_xlat_sound(soundnum);
680 if (!digi_initialised) return;
684 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
685 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) ) {
686 if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
687 if ( SoundObjects[i].flags & SOF_PLAYING ) {
689 SoundSlots[SoundObjects[i].handle].playing = 0;
692 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
697 // If this assert happens, it means that there were 2 sounds
698 // that got deleted. Weird, get John.
700 mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
704 void digi_kill_sound_linked_to_object( int objnum )
708 if (!digi_initialised) return;
712 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
713 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) ) {
714 if (SoundObjects[i].lo_objnum == objnum) {
715 if ( SoundObjects[i].flags & SOF_PLAYING ) {
717 SoundSlots[SoundObjects[i].handle].playing = 0;
720 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
725 // If this assert happens, it means that there were 2 sounds
726 // that got deleted. Weird, get John.
728 mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
732 void digi_sync_sounds()
735 int oldvolume, oldpan;
737 if (!digi_initialised) return;
739 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
740 if ( SoundObjects[i].flags & SOF_USED ) {
741 oldvolume = SoundObjects[i].volume;
742 oldpan = SoundObjects[i].pan;
744 if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) ) {
745 // Check if its done.
746 if (SoundObjects[i].flags & SOF_PLAYING) {
748 if (!SoundSlots[SoundObjects[i].handle].playing) {
750 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
751 continue; // Go on to next sound...
757 if ( SoundObjects[i].flags & SOF_LINK_TO_POS ) {
758 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
759 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
760 SoundObjects[i].max_volume,
761 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
763 } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) {
766 objp = &Objects[SoundObjects[i].lo_objnum];
768 if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature)) {
769 // The object that this is linked to is dead, so just end this sound if it is looping.
770 if ( (SoundObjects[i].flags & SOF_PLAYING) && (SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
772 SoundSlots[SoundObjects[i].handle].playing = 0;
775 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
776 continue; // Go on to next sound...
778 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
779 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
780 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
784 if (oldvolume != SoundObjects[i].volume) {
785 if ( SoundObjects[i].volume < MIN_VOLUME ) {
786 // Sound is too far away, so stop it from playing.
787 if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
789 SoundSlots[SoundObjects[i].handle].playing = 0;
791 SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing
794 if (!(SoundObjects[i].flags & SOF_PLAYING)) {
795 digi_start_sound_object(i);
798 SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0);
804 if (oldpan != SoundObjects[i].pan) {
805 if (SoundObjects[i].flags & SOF_PLAYING) {
807 SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan;
815 void digi_init_sounds()
819 if (!digi_initialised) return;
821 digi_reset_digi_sounds();
823 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
824 if (digi_sounds_initialized) {
825 if ( SoundObjects[i].flags & SOF_PLAYING ) {
827 SoundSlots[SoundObjects[i].handle].playing=0;
831 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
833 digi_sounds_initialized = 1;
836 //added on 980905 by adb from original source to make sfx volume work
837 void digi_set_digi_volume( int dvolume )
839 dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
840 if ( dvolume > SOUND_MAX_VOLUME )
841 digi_volume = SOUND_MAX_VOLUME;
842 else if ( dvolume < 0 )
845 digi_volume = dvolume;
847 if ( !digi_initialised ) return;
853 void digi_set_volume( int dvolume, int mvolume ) { }
855 int digi_is_sound_playing(int soundno)
859 soundno = digi_xlat_sound(soundno);
862 for (i = 0; i < MAX_SOUND_SLOTS; i++)
863 //changed on 980905 by adb: added SoundSlots[i].playing &&
864 if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
866 { UNLOCK(); return 1; }
872 void digi_pause_all() { }
873 void digi_resume_all() { }
874 void digi_stop_all() { }
876 //added on 980905 by adb to make sound channel setting work
877 void digi_set_max_channels(int n) {
878 digi_max_channels = n;
880 if ( digi_max_channels < 1 )
881 digi_max_channels = 1;
882 if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) )
883 digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS);
885 if ( !digi_initialised ) return;
887 digi_reset_digi_sounds();
890 int digi_get_max_channels() {
891 return digi_max_channels;
895 void digi_reset_digi_sounds() {
899 for (i=0; i< MAX_SOUND_SLOTS; i++)
900 SoundSlots[i].playing=0;
903 //added on 980905 by adb to reset sound kill system
904 memset(SampleHandles, 255, sizeof(SampleHandles));
910 // MIDI stuff follows.
911 //added/killed on 11/25/98 by Matthew Mueller
912 //void digi_set_midi_volume( int mvolume ) { }
913 //void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
914 //void digi_stop_current_song()
923 //end this section kill - MM