1 /* $Id: alsadigi.c,v 1.3 2005-02-25 07:02:46 btb Exp $ */
4 * ALSA digital audio support
11 #include <alsa/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)
179 snd_pcm_t *snd_devhandle;
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];
230 *sp = mix8[*sp + fixmul(v, vr) + 0x80];
233 sl->position = sldata - sl->samples;
239 void *mixer_thread(void *data)
242 ubyte buffer[SOUND_BUFFER_SIZE];
244 /* Allow ourselves to be asynchronously cancelled */
245 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
248 memset(buffer, 0x80, SOUND_BUFFER_SIZE);
250 audio_mixcallback(NULL,buffer,512);
253 err = snd_pcm_writei(snd_devhandle, buffer, SOUND_BUFFER_SIZE / 2);
257 // Sound buffer underrun
258 err = snd_pcm_prepare(snd_devhandle);
261 fprintf(stderr, "Can't recover from underrun: %s\n", snd_strerror(err));
264 else if (err == -EAGAIN)
268 else if (err != SOUND_BUFFER_SIZE / 2)
270 // Each frame has size 2 bytes - hence we expect SOUND_BUFFER_SIZE/2
271 // frames to be written.
272 fprintf(stderr, "Unknown err %d: %s\n", err, snd_strerror(err));
279 /* Initialise audio devices. */
283 char *device = "plughw:0,0";
284 snd_pcm_hw_params_t *params;
286 pthread_mutexattr_t mutexattr;
288 //added on 980905 by adb to init sound kill system
289 memset(SampleHandles, 255, sizeof(SampleHandles));
292 /* Open the ALSA sound device */
293 if ((err = snd_pcm_open(&snd_devhandle, device, SND_PCM_STREAM_PLAYBACK)) < 0)
295 fprintf(stderr, "open failed: %s\n", snd_strerror( err ));
299 snd_pcm_hw_params_alloca(¶ms);
300 err = snd_pcm_hw_params_any(snd_devhandle, params);
303 printf("ALSA: Error %s\n", snd_strerror(err));
306 err = snd_pcm_hw_params_set_access(snd_devhandle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
309 printf("ALSA: Error %s\n", snd_strerror(err));
312 err = snd_pcm_hw_params_set_format(snd_devhandle, params, SND_PCM_FORMAT_U8);
315 printf("ALSA: Error %s\n", snd_strerror(err));
318 err = snd_pcm_hw_params_set_channels(snd_devhandle, params, 2);
321 printf("ALSA: Error %s\n", snd_strerror(err));
325 err = snd_pcm_hw_params_set_rate_near(snd_devhandle, params, &tmp, NULL);
328 printf("ALSA: Error %s\n", snd_strerror(err));
331 snd_pcm_hw_params_set_periods(snd_devhandle, params, 3, 0);
332 snd_pcm_hw_params_set_buffer_size(snd_devhandle,params, (SOUND_BUFFER_SIZE*3)/2);
334 err = snd_pcm_hw_params(snd_devhandle, params);
337 printf("ALSA: Error %s\n", snd_strerror(err));
341 /* Start the mixer thread */
343 /* We really should check the results of these */
344 pthread_mutexattr_init(&mutexattr);
345 pthread_mutex_init(&mutex,&mutexattr);
346 pthread_mutexattr_destroy(&mutexattr);
348 if (pthread_attr_init(&attr) != 0) {
349 fprintf(stderr, "failed to init attr\n");
350 snd_pcm_close( snd_devhandle );
354 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
356 pthread_create(&thread_id,&attr,mixer_thread,NULL);
357 pthread_attr_destroy(&attr);
360 digi_initialised = 1;
365 void digi_reset() { }
367 /* Shut down audio */
370 if (!digi_initialised) return;
371 pthread_cancel(thread_id);
372 digi_initialised = 0;
373 pthread_mutex_destroy(&mutex);
374 snd_pcm_close(snd_devhandle);
377 /* Find the sound which actually equates to a sound number */
378 int digi_xlat_sound(int soundno)
380 if ( soundno < 0 ) return -1;
383 soundno = AltSounds[soundno];
384 if ( soundno == 255 ) return -1;
386 return Sounds[soundno];
389 static int get_free_slot()
392 for (i=0; i<MAX_SOUND_SLOTS; i++)
394 if (!SoundSlots[i].playing) return i;
399 int digi_start_sound(int soundnum, fix volume, fix pan)
404 if (!digi_initialised) return -1;
406 //added on 980905 by adb from original source to add sound kill system
407 // play at most digi_max_channel samples, if possible kill sample with low volume
411 if ( (SampleHandles[next_handle] >= 0) && (SoundSlots[SampleHandles[next_handle]].playing) )
413 if ( (SoundSlots[SampleHandles[next_handle]].volume > digi_volume) && (ntries<digi_max_channels) )
415 //mprintf(( 0, "Not stopping loud sound %d.\n", next_handle ));
417 if ( next_handle >= digi_max_channels )
422 //mprintf(( 0, "[SS:%d]", next_handle ));
423 SoundSlots[SampleHandles[next_handle]].playing = 0;
424 SampleHandles[next_handle] = -1;
428 slot = get_free_slot();
429 if (slot<0) return -1;
431 SoundSlots[slot].soundno = soundnum;
432 SoundSlots[slot].samples = GameSounds[soundnum].data;
433 SoundSlots[slot].length = GameSounds[soundnum].length;
434 SoundSlots[slot].volume = fixmul(digi_volume, volume);
435 SoundSlots[slot].pan = pan;
436 SoundSlots[slot].position = 0;
437 SoundSlots[slot].looped = 0;
438 SoundSlots[slot].playing = 1;
440 //added on 980905 by adb to add sound kill system from original sos digi.c
441 reset_sounds_on_channel(slot);
442 SampleHandles[next_handle] = slot;
444 if ( next_handle >= digi_max_channels )
451 //added on 980905 by adb to add sound kill system from original sos digi.c
452 void reset_sounds_on_channel( int channel )
456 for (i=0; i<digi_max_channels; i++)
457 if (SampleHandles[i] == channel)
458 SampleHandles[i] = -1;
462 int digi_start_sound_object(int obj)
466 if (!digi_initialised) return -1;
468 slot = get_free_slot();
470 if (slot<0) { UNLOCK(); return -1; }
473 SoundSlots[slot].soundno = SoundObjects[obj].soundnum;
474 SoundSlots[slot].samples = GameSounds[SoundObjects[obj].soundnum].data;
475 SoundSlots[slot].length = GameSounds[SoundObjects[obj].soundnum].length;
476 SoundSlots[slot].volume = fixmul(digi_volume, SoundObjects[obj].volume);
477 SoundSlots[slot].pan = SoundObjects[obj].pan;
478 SoundSlots[slot].position = 0;
479 SoundSlots[slot].looped = (SoundObjects[obj].flags & SOF_PLAY_FOREVER);
480 SoundSlots[slot].playing = 1;
482 SoundObjects[obj].signature = next_signature++;
483 SoundObjects[obj].handle = slot;
485 SoundObjects[obj].flags |= SOF_PLAYING;
486 //added on 980905 by adb to add sound kill system from original sos digi.c
487 reset_sounds_on_channel(slot);
495 // Play the given sound number.
496 // Volume is max at F1_0.
497 void digi_play_sample( int soundno, fix max_volume )
500 if ( Newdemo_state == ND_STATE_RECORDING )
501 newdemo_record_sound( soundno );
503 soundno = digi_xlat_sound(soundno);
505 if (!digi_initialised) return;
507 if (soundno < 0 ) return;
509 digi_start_sound(soundno, max_volume, F0_5);
512 // Play the given sound number. If the sound is already playing,
514 void digi_play_sample_once( int soundno, fix max_volume )
519 if ( Newdemo_state == ND_STATE_RECORDING )
520 newdemo_record_sound( soundno );
522 soundno = digi_xlat_sound(soundno);
524 if (!digi_initialised) return;
526 if (soundno < 0 ) return;
529 for (i=0; i < MAX_SOUND_SLOTS; i++)
530 if (SoundSlots[i].soundno == soundno)
531 SoundSlots[i].playing = 0;
533 digi_start_sound(soundno, max_volume, F0_5);
537 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups ) // Volume from 0-0x7fff
542 if ( Newdemo_state == ND_STATE_RECORDING ) {
544 newdemo_record_sound_3d_once( soundno, angle, volume );
546 newdemo_record_sound_3d( soundno, angle, volume );
549 soundno = digi_xlat_sound(soundno);
551 if (!digi_initialised) return;
552 if (soundno < 0 ) return;
554 if (volume < MIN_VOLUME ) return;
555 digi_start_sound(soundno, volume, angle);
558 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 )
560 vms_vector vector_to_sound;
561 fix angle_from_ear, cosang,sinang;
568 max_distance = (max_distance*5)/4; // Make all sounds travel 1.25 times as far.
570 // Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
571 distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
573 if (distance < max_distance ) {
574 int num_search_segs = f2i(max_distance/20);
575 if ( num_search_segs < 1 ) num_search_segs = 1;
577 path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
578 if ( path_distance > -1 ) {
579 *volume = max_volume - fixdiv(path_distance,max_distance);
580 //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
582 angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
583 fix_sincos(angle_from_ear,&sinang,&cosang);
584 //mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
585 if (Config_channels_reversed) cosang *= -1;
586 *pan = (cosang + F1_0)/2;
594 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance )
600 soundnum = digi_xlat_sound(org_soundnum);
602 if ( max_volume < 0 ) return -1;
603 // if ( max_volume > F1_0 ) max_volume = F1_0;
605 if (!digi_initialised) return -1;
606 if (soundnum < 0 ) return -1;
607 if (GameSounds[soundnum].data==NULL) {
611 if ((objnum<0)||(objnum>Highest_object_index))
615 // Hack to keep sounds from building up...
616 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
617 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
621 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
622 if (SoundObjects[i].flags==0)
625 if (i==MAX_SOUND_OBJECTS) {
626 mprintf((1, "Too many sound objects!\n" ));
630 SoundObjects[i].signature=next_signature++;
631 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
633 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
634 SoundObjects[i].lo_objnum = objnum;
635 SoundObjects[i].lo_objsignature = Objects[objnum].signature;
636 SoundObjects[i].max_volume = max_volume;
637 SoundObjects[i].max_distance = max_distance;
638 SoundObjects[i].volume = 0;
639 SoundObjects[i].pan = 0;
640 SoundObjects[i].soundnum = soundnum;
642 objp = &Objects[SoundObjects[i].lo_objnum];
643 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
644 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
645 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
647 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
648 digi_start_sound_object(i);
650 return SoundObjects[i].signature;
653 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
654 { return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0); }
656 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
661 soundnum = digi_xlat_sound(org_soundnum);
663 if ( max_volume < 0 ) return -1;
664 // if ( max_volume > F1_0 ) max_volume = F1_0;
666 if (!digi_initialised) return -1;
667 if (soundnum < 0 ) return -1;
668 if (GameSounds[soundnum].data==NULL) {
673 if ((segnum<0)||(segnum>Highest_segment_index))
677 // Hack to keep sounds from building up...
678 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
679 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
683 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
684 if (SoundObjects[i].flags==0)
687 if (i==MAX_SOUND_OBJECTS) {
688 mprintf((1, "Too many sound objects!\n" ));
693 SoundObjects[i].signature=next_signature++;
694 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
696 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
697 SoundObjects[i].lp_segnum = segnum;
698 SoundObjects[i].lp_sidenum = sidenum;
699 SoundObjects[i].lp_position = *pos;
700 SoundObjects[i].soundnum = soundnum;
701 SoundObjects[i].max_volume = max_volume;
702 SoundObjects[i].max_distance = max_distance;
703 SoundObjects[i].volume = 0;
704 SoundObjects[i].pan = 0;
705 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
706 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
707 SoundObjects[i].max_volume,
708 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
710 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
711 digi_start_sound_object(i);
713 return SoundObjects[i].signature;
716 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
718 return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
721 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
725 soundnum = digi_xlat_sound(soundnum);
727 if (!digi_initialised) return;
731 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
732 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) ) {
733 if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
734 if ( SoundObjects[i].flags & SOF_PLAYING ) {
736 SoundSlots[SoundObjects[i].handle].playing = 0;
739 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
744 // If this assert happens, it means that there were 2 sounds
745 // that got deleted. Weird, get John.
747 mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
751 void digi_kill_sound_linked_to_object( int objnum )
755 if (!digi_initialised) return;
759 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
760 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) ) {
761 if (SoundObjects[i].lo_objnum == objnum) {
762 if ( SoundObjects[i].flags & SOF_PLAYING ) {
764 SoundSlots[SoundObjects[i].handle].playing = 0;
767 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
772 // If this assert happens, it means that there were 2 sounds
773 // that got deleted. Weird, get John.
775 mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
779 void digi_sync_sounds()
782 int oldvolume, oldpan;
784 if (!digi_initialised) return;
786 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
787 if ( SoundObjects[i].flags & SOF_USED ) {
788 oldvolume = SoundObjects[i].volume;
789 oldpan = SoundObjects[i].pan;
791 if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) ) {
792 // Check if its done.
793 if (SoundObjects[i].flags & SOF_PLAYING) {
795 if (!SoundSlots[SoundObjects[i].handle].playing) {
797 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
798 continue; // Go on to next sound...
804 if ( SoundObjects[i].flags & SOF_LINK_TO_POS ) {
805 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
806 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
807 SoundObjects[i].max_volume,
808 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
810 } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) {
813 objp = &Objects[SoundObjects[i].lo_objnum];
815 if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature)) {
816 // The object that this is linked to is dead, so just end this sound if it is looping.
817 if ( (SoundObjects[i].flags & SOF_PLAYING) && (SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
819 SoundSlots[SoundObjects[i].handle].playing = 0;
822 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
823 continue; // Go on to next sound...
825 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
826 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
827 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
831 if (oldvolume != SoundObjects[i].volume) {
832 if ( SoundObjects[i].volume < MIN_VOLUME ) {
833 // Sound is too far away, so stop it from playing.
834 if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
836 SoundSlots[SoundObjects[i].handle].playing = 0;
838 SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing
841 if (!(SoundObjects[i].flags & SOF_PLAYING)) {
842 digi_start_sound_object(i);
845 SoundSlots[SoundObjects[i].handle].volume = fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0);
851 if (oldpan != SoundObjects[i].pan) {
852 if (SoundObjects[i].flags & SOF_PLAYING) {
854 SoundSlots[SoundObjects[i].handle].pan = SoundObjects[i].pan;
862 void digi_init_sounds()
866 if (!digi_initialised) return;
868 digi_reset_digi_sounds();
870 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
871 if (digi_sounds_initialized) {
872 if ( SoundObjects[i].flags & SOF_PLAYING ) {
874 SoundSlots[SoundObjects[i].handle].playing=0;
878 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
880 digi_sounds_initialized = 1;
883 //added on 980905 by adb from original source to make sfx volume work
884 void digi_set_digi_volume( int dvolume )
886 dvolume = fixmuldiv( dvolume, SOUND_MAX_VOLUME, 0x7fff);
887 if ( dvolume > SOUND_MAX_VOLUME )
888 digi_volume = SOUND_MAX_VOLUME;
889 else if ( dvolume < 0 )
892 digi_volume = dvolume;
894 if ( !digi_initialised ) return;
900 void digi_set_volume( int dvolume, int mvolume ) { }
902 int digi_is_sound_playing(int soundno)
906 soundno = digi_xlat_sound(soundno);
909 for (i = 0; i < MAX_SOUND_SLOTS; i++)
910 //changed on 980905 by adb: added SoundSlots[i].playing &&
911 if (SoundSlots[i].playing && SoundSlots[i].soundno == soundno)
913 { UNLOCK(); return 1; }
919 void digi_pause_all() { }
920 void digi_resume_all() { }
921 void digi_stop_all() { }
923 //added on 980905 by adb to make sound channel setting work
924 void digi_set_max_channels(int n) {
925 digi_max_channels = n;
927 if ( digi_max_channels < 1 )
928 digi_max_channels = 1;
929 if ( digi_max_channels > (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS) )
930 digi_max_channels = (MAX_SOUND_SLOTS-MAX_SOUND_OBJECTS);
932 if ( !digi_initialised ) return;
934 digi_reset_digi_sounds();
937 int digi_get_max_channels() {
938 return digi_max_channels;
942 void digi_reset_digi_sounds() {
946 for (i=0; i< MAX_SOUND_SLOTS; i++)
947 SoundSlots[i].playing=0;
950 //added on 980905 by adb to reset sound kill system
951 memset(SampleHandles, 255, sizeof(SampleHandles));
957 // MIDI stuff follows.
958 //added/killed on 11/25/98 by Matthew Mueller
959 //void digi_set_midi_volume( int mvolume ) { }
960 //void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop ) {}
961 //void digi_stop_current_song()
970 //end this section kill - MM