2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
41 #define _DIGI_MAX_VOLUME 128 // set lower to have difference with > F1_0 sounds
43 #define MIN_VOLUME 10 // minimal volume to be played (in 0-F1_0(?) range)
46 #define _MELODIC_PATCH "melodic.bnk"
47 #define _DRUM_PATCH "drum.bnk"
48 #define _DIGDRUM_PATCH "drum32.dig"
51 static int Digi_initialized = 0;
52 static int digi_atexit_called = 0; // Set to 1 if atexit(digi_close) was called
54 int digi_driver_board = 0;
55 int digi_driver_port = 0;
56 int digi_driver_irq = 0;
57 int digi_driver_dma = 0;
58 //int digi_midi_type = 0; // Midi driver type
59 //int digi_midi_port = 0; // Midi driver port
60 static int digi_max_channels = 8;
61 //static int digi_driver_rate = 11025; // rate to use driver at
62 //static int digi_dma_buffersize = 4096; // size of the dma buffer to use (4k)
63 int digi_timer_rate = 9943; // rate for the timer to go off to handle the driver system (120 Hz)
65 static int digi_volume = _DIGI_MAX_VOLUME; // Max volume
66 //static int midi_volume = 128/2; // Max volume
67 //static int midi_system_initialized = 0;
68 //static int digi_system_initialized = 0;
69 static int timer_system_initialized = 0;
70 static int digi_sound_locks[MAX_SOUNDS];
71 //char digi_last_midi_song[16] = "";
72 //char digi_last_melodic_bank[16] = "";
73 //char digi_last_drum_bank[16] = "";
74 char *digi_driver_path = NULL;
76 extern int midi_volume;
78 //static void * lpInstruments = NULL; // pointer to the instrument file
79 //static int InstrumentSize = 0;
80 //static void * lpDrums = NULL; // pointer to the drum file
81 //static int DrumSize = 0;
83 // handle for the initialized MIDI song
84 //MIDI *SongHandle = NULL;
86 #define SOF_USED 1 // Set if this sample is used
87 #define SOF_PLAYING 2 // Set if this sample is playing on a channel
88 #define SOF_LINK_TO_OBJ 4 // Sound is linked to a moving object. If object dies, then finishes play and quits.
89 #define SOF_LINK_TO_POS 8 // Sound is linked to segment, pos
90 #define SOF_PLAY_FOREVER 16 // Play forever (or until level is stopped), otherwise plays once
94 typedef struct sound_object {
95 short signature; // A unique signature to this sound
96 ubyte flags; // Used to tell if this slot is used and/or currently playing, and how long.
97 fix max_volume; // Max volume that this sound is playing at
98 fix max_distance; // The max distance that this sound can be heard at...
99 int volume; // Volume that this sound is playing at
100 int pan; // Pan value that this sound is playing at
101 WORD handle; // What handle this sound is playing on. Valid only if SOF_PLAYING is set.
102 short soundnum; // The sound number that is playing
105 short segnum; // Used if SOF_LINK_TO_POS field is used
110 short objnum; // Used if SOF_LINK_TO_OBJ field is used
115 #define lp_segnum link.pos.segnum
116 #define lp_sidenum link.pos.sidenum
117 #define lp_position link.pos.position
119 #define lo_objnum link.obj.objnum
120 #define lo_objsignature link.obj.objsignature
122 #define MAX_SOUND_OBJECTS 16
123 sound_object SoundObjects[MAX_SOUND_OBJECTS];
124 short next_signature=0;
126 int digi_sounds_initialized=0;
129 // a channel (voice) id is an int in Allegro
131 #define VALID_CHANNEL(ch) (ch >= 0)
132 #define INVALID_CHANNEL -1
134 #define DIGI_SLOTS DIGI_VOICES
136 // next_handle is a Descent internal number (hereafter reffered to as slot),
137 // which indexes into SampleHandles, SoundNums and SoundVolumes.
138 // only digi_max_channels entries are used.
139 // SampleHandles points to sounddriver handles (voices)
140 static int next_handle = 0;
141 static CHANNEL SampleHandles[DIGI_SLOTS] = {
142 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
143 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
144 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
145 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
146 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
147 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
148 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
149 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL };
150 static int SoundNums[DIGI_SLOTS] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 };
151 static uint SoundVolumes[DIGI_SLOTS] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 };
153 void digi_reset_digi_sounds();
154 int verify_channel_not_used_by_soundobjects( int channel );
156 int digi_xlat_sound(int soundno)
158 if ( soundno < 0 ) return -1;
161 soundno = AltSounds[soundno];
162 if ( soundno == 255 ) return -1;
164 return Sounds[soundno];
168 if (!Digi_initialized) return;
171 Digi_initialized = 0;
173 if ( timer_system_initialized ) {
175 timer_set_function( NULL );
177 timer_system_initialized = 0;
180 /* initialize sound system. 0=ok, 1=error */
184 if (!timer_system_initialized)
187 timer_system_initialized = 1;
189 if (!Digi_initialized) {
190 // amount of voices we need
191 // 16 for normal sounds and 16 for SoundObjects (fan, boss)
192 // for DIGMID we sacrify some sounds (32 is the max).
193 // reserve_voices(allegro_using_digmid() ? 16 : 32, -1);
194 if (install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, NULL))
197 digi_driver_board = digi_card; // only for 0, !=0
198 digi_midi_type = midi_card; // only for 0, !=0
200 Digi_initialized = 1;
203 if (!digi_atexit_called) {
204 atexit( digi_close );
205 digi_atexit_called = 1;
209 digi_set_midi_volume( midi_volume );
211 for (i=0; i<MAX_SOUNDS; i++ )
212 digi_sound_locks[i] = 0;
213 digi_reset_digi_sounds();
218 // Toggles sound system on/off
221 if ( Digi_initialized ) {
222 digi_reset_digi_sounds();
224 mprintf( (0, "Sound system DISABLED.\n" ));
227 mprintf( (0, "Sound system ENABLED.\n" ));
231 int digi_total_locks = 0;
233 ubyte * digi_lock_sound_data( int soundnum )
237 if ( !Digi_initialized ) return NULL;
238 if ( digi_driver_board <= 0 ) return NULL;
240 if ( digi_sound_locks[soundnum] == 0 ) {
242 //mprintf(( 0, "Total sound locks = %d\n", digi_total_locks ));
243 i = dpmi_lock_region( GameSounds[soundnum].data, GameSounds[soundnum].len );
244 if ( !i ) Error( "Error locking sound %d\n", soundnum );
246 digi_sound_locks[soundnum]++;
247 return GameSounds[soundnum].data;
250 void digi_unlock_sound_data( int soundnum )
254 if ( !Digi_initialized ) return;
255 if ( digi_driver_board <= 0 ) return;
257 Assert( digi_sound_locks[soundnum] > 0 );
259 if ( digi_sound_locks[soundnum] == 1 ) {
261 //mprintf(( 0, "Total sound locks = %d\n", digi_total_locks ));
262 i = dpmi_unlock_region( GameSounds[soundnum].data, GameSounds[soundnum].len );
263 if ( !i ) Error( "Error unlocking sound %d\n", soundnum );
265 digi_sound_locks[soundnum]--;
269 void digi_reset_digi_sounds() {
272 for (i = 0; i < DIGI_SLOTS; i++) {
273 if (VALID_CHANNEL(SampleHandles[i])) {
274 deallocate_voice(SampleHandles[i]);
275 SampleHandles[i] = INVALID_CHANNEL;
277 if (SoundNums[i] != -1) {
278 digi_unlock_sound_data(SoundNums[i]);
282 for (i=0; i<MAX_SOUNDS; i++ ) {
283 Assert( digi_sound_locks[i] == 0 );
287 void reset_slots_on_channel( int channel ) {
290 if ( !Digi_initialized ) return;
291 if ( digi_driver_board <= 0 ) return;
293 for (i=0; i<DIGI_SLOTS; i++) {
294 if (SampleHandles[i] == channel) {
295 SampleHandles[i] = INVALID_CHANNEL;
296 if (SoundNums[i] != -1) {
297 digi_unlock_sound_data(SoundNums[i]);
304 void digi_set_max_channels(int n) {
305 digi_max_channels = n;
307 if ( digi_max_channels < 1 )
308 digi_max_channels = 1;
309 if ( digi_max_channels > DIGI_VOICES)
310 digi_max_channels = DIGI_VOICES;
313 int digi_get_max_channels()
315 return digi_max_channels;
318 int get_free_slot() {
323 // sound playing on slot <next_handle>?
324 if ( (VALID_CHANNEL(SampleHandles[next_handle])) &&
325 (voice_check(SampleHandles[next_handle])) ) {
326 // don't use this slot if loud sound
327 if ( (SoundVolumes[next_handle] > digi_volume) &&
328 (ntries<digi_max_channels) ) {
329 mprintf(( 0, "Not stopping loud sound %d (%d).\n", next_handle, SoundNums[next_handle]));
331 if ( next_handle >= digi_max_channels )
336 //mprintf(( 0, "[SS:%d]", next_handle ));
337 if (voice_check(next_handle))
338 mprintf((0,"Sound: deallocating used voice %d sound %d vol %d pos %d/%d\n", next_handle, SoundNums[next_handle], SoundVolumes[next_handle], voice_get_position(next_handle), GameSounds[SoundNums[next_handle]].len));
339 deallocate_voice(SampleHandles[next_handle]);
340 SampleHandles[next_handle] = INVALID_CHANNEL;
343 if ( SoundNums[next_handle] != -1 ) {
344 digi_unlock_sound_data(SoundNums[next_handle]);
345 SoundNums[next_handle] = -1;
347 ret_slot = next_handle;
349 if ( next_handle >= digi_max_channels )
354 CHANNEL digi_start_sound(int soundnum, int volume, int pan) {
359 volume = fixmul(volume, digi_volume);
360 slot = get_free_slot();
362 digi_lock_sound_data(soundnum);
363 channel = play_sample(&GameSounds[soundnum], volume, pan >> 8, 1000, 0);
365 mprintf(( 1, "NOT ENOUGH SOUND SLOTS!!!\n" ));
366 digi_unlock_sound_data(soundnum);
369 release_voice(channel);
371 //mprintf(( 0, "Starting sound on channel %d\n", channel ));
373 verify_channel_not_used_by_soundobjects(channel);
376 // find slots pointing to just allocated channel and kill sounds on it
377 // (because they can't be playing right now)
378 for (i=0; i<digi_max_channels; i++ ) {
379 if (SampleHandles[i] == channel) {
380 SampleHandles[i] = INVALID_CHANNEL;
381 if (SoundNums[i] != -1) {
382 digi_unlock_sound_data(SoundNums[i]);
388 // fill slot with data of just started sample
389 SampleHandles[slot] = channel;
390 SoundNums[slot] = soundnum;
391 SoundVolumes[slot] = volume;
396 int digi_is_sound_playing(int soundno)
400 soundno = digi_xlat_sound(soundno);
402 for (i = 0; i < DIGI_VOICES; i++)
403 if (voice_check(i) == &GameSounds[soundno])
408 void digi_play_sample_once( int soundno, fix max_volume ) {
412 if ( Newdemo_state == ND_STATE_RECORDING )
413 newdemo_record_sound( soundno );
415 soundno = digi_xlat_sound(soundno);
417 if (!Digi_initialized) return;
418 if (digi_driver_board<1) return;
420 if (soundno < 0 ) return;
422 for (i = 0; i < DIGI_VOICES; i++)
423 if (voice_check(i) == &GameSounds[soundno])
426 digi_start_sound(soundno, max_volume, F0_5);
429 void digi_play_sample( int soundno, fix max_volume ) {
431 if ( Newdemo_state == ND_STATE_RECORDING )
432 newdemo_record_sound( soundno );
434 soundno = digi_xlat_sound(soundno);
436 if (!Digi_initialized) return;
437 if (digi_driver_board<1) return;
439 if (soundno < 0 ) return;
441 digi_start_sound(soundno, max_volume, F0_5);
444 void digi_play_sample_3d( int soundno, int angle, int volume, int no_dups )
449 if ( Newdemo_state == ND_STATE_RECORDING ) {
451 newdemo_record_sound_3d_once( soundno, angle, volume );
453 newdemo_record_sound_3d( soundno, angle, volume );
456 soundno = digi_xlat_sound(soundno);
458 if (!Digi_initialized) return;
459 if (digi_driver_board<1) return;
460 if (soundno < 0 ) return;
462 if (volume < MIN_VOLUME ) return;
464 digi_start_sound(soundno, volume, angle);
467 //-killed- void digi_set_midi_volume( int mvolume )
469 //-killed- int old_volume = midi_volume;
471 //-killed- if ( mvolume > 127 )
472 //-killed- midi_volume = 127;
473 //-killed- else if ( mvolume < 0 )
474 //-killed- midi_volume = 0;
476 //-killed- midi_volume = mvolume;
478 //-killed- if ( (digi_midi_type > 0) ) {
479 //-killed- if ( (old_volume < 1) && ( midi_volume > 1 ) ) {
480 //-killed- if (SongHandle == NULL )
481 //-killed- digi_play_midi_song( digi_last_midi_song, digi_last_melodic_bank, digi_last_drum_bank, 1 );
483 //-killed- set_volume(-1, midi_volume * 2 + (midi_volume & 1));
487 void digi_set_digi_volume( int dvolume )
489 dvolume = fixmuldiv( dvolume, _DIGI_MAX_VOLUME, 0x7fff);
490 if ( dvolume > _DIGI_MAX_VOLUME )
491 digi_volume = _DIGI_MAX_VOLUME;
492 else if ( dvolume < 0 )
495 digi_volume = dvolume;
497 if ( !Digi_initialized ) return;
498 if ( digi_driver_board <= 0 ) return;
504 void digi_set_volume( int dvolume, int mvolume )
506 digi_set_midi_volume( mvolume );
507 digi_set_digi_volume( dvolume );
508 // mprintf(( 1, "Volume: 0x%x and 0x%x\n", digi_volume, midi_volume ));
511 //-killed- void digi_stop_current_song()
513 //-killed- if (SongHandle) {
514 //-killed- destroy_midi(SongHandle);
515 //-killed- SongHandle = NULL;
519 //-killed- void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop )
521 //-killed- //char fname[128];
523 //-killed- if (!Digi_initialized) return;
524 //-killed- if ( digi_midi_type <= 0 ) return;
526 //-killed- digi_stop_current_song();
528 //-killed- if ( filename == NULL ) return;
530 //-killed- strcpy( digi_last_midi_song, filename );
531 //-killed- strcpy( digi_last_melodic_bank, melodic_bank );
532 //-killed- strcpy( digi_last_drum_bank, drum_bank );
534 //-killed- if ( midi_volume < 1 )
536 //-killed- SongHandle = NULL;
538 //-killed- #if 0 /* needs bank loading to sound right */
539 //-killed- if (midi_card <= 4) { /* FM cards */
541 //-killed- sl = strlen( filename );
542 //-killed- strcpy( fname, filename );
543 //-killed- fname[sl-1] = 'q';
544 //-killed- SongHandle = load_hmp(fname);
548 //-killed- if ( !SongHandle )
549 //-killed- SongHandle = load_hmp(filename);
551 //-killed- if (SongHandle) {
552 //-killed- if (play_midi(SongHandle, loop)) {
553 //-killed- destroy_midi(SongHandle);
554 //-killed- SongHandle = NULL;
557 //-killed- if (!SongHandle) {
558 //-killed- mprintf( (1, "\nAllegro Error : %s", allegro_error ));
562 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 )
564 vms_vector vector_to_sound;
565 fix angle_from_ear, cosang,sinang;
572 max_distance = (max_distance*5)/4; // Make all sounds travel 1.25 times as far.
574 // Warning: Made the vm_vec_normalized_dir be vm_vec_normalized_dir_quick and got illegal values to acos in the fang computation.
575 distance = vm_vec_normalized_dir_quick( &vector_to_sound, sound_pos, listener_pos );
577 if (distance < max_distance ) {
578 int num_search_segs = f2i(max_distance/20);
579 if ( num_search_segs < 1 ) num_search_segs = 1;
581 path_distance = find_connected_distance(listener_pos, listener_seg, sound_pos, sound_seg, num_search_segs, WID_RENDPAST_FLAG );
582 if ( path_distance > -1 ) {
583 *volume = max_volume - fixdiv(path_distance,max_distance);
584 //mprintf( (0, "Sound path distance %.2f, volume is %d / %d\n", f2fl(distance), *volume, max_volume ));
586 angle_from_ear = vm_vec_delta_ang_norm(&listener->rvec,&vector_to_sound,&listener->uvec);
587 fix_sincos(angle_from_ear,&sinang,&cosang);
588 //mprintf( (0, "volume is %.2f\n", f2fl(*volume) ));
589 if (Config_channels_reversed) cosang *= -1;
590 *pan = (cosang + F1_0)/2;
598 void digi_init_sounds()
602 if (!Digi_initialized) return;
603 if (digi_driver_board<1) return;
605 digi_reset_digi_sounds();
607 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
608 if (digi_sounds_initialized) {
609 if ( SoundObjects[i].flags & SOF_PLAYING ) {
610 deallocate_voice(SoundObjects[i].handle);
613 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
615 digi_sounds_initialized = 1;
618 void digi_start_sound_object(int i)
620 if (!Digi_initialized) return;
621 if (digi_driver_board<1) return;
623 // this doesn't use digi_lock_sound because these sounds are
624 // never unlocked, so we couldn't check if we unlocked all other sounds then
625 if (!dpmi_lock_region( GameSounds[SoundObjects[i].soundnum].data, GameSounds[SoundObjects[i].soundnum].len ))
626 Error( "Error locking sound object %d\n", SoundObjects[i].soundnum );
628 SoundObjects[i].signature=next_signature++;
630 SoundObjects[i].handle = play_sample(&GameSounds[SoundObjects[i].soundnum],
631 fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0), /* 0-255 */
632 SoundObjects[i].pan >> 8, /* 0-255 */
634 (SoundObjects[i].flags & SOF_PLAY_FOREVER) ? 1 : 0
636 if (SoundObjects[i].handle < 0) {
637 mprintf(( 1, "NOT ENOUGH SOUND SLOTS!!! (SoundObject)\n" ));
638 //digi_unlock_sound(SoundObjects[i].soundnum); //never unlocked...
640 SoundObjects[i].flags |= SOF_PLAYING;
641 reset_slots_on_channel( SoundObjects[i].handle );
645 int digi_link_sound_to_object2( int org_soundnum, short objnum, int forever, fix max_volume, fix max_distance )
651 soundnum = digi_xlat_sound(org_soundnum);
653 if ( max_volume < 0 ) return -1;
654 // if ( max_volume > F1_0 ) max_volume = F1_0;
656 if (!Digi_initialized) return -1;
657 if (soundnum < 0 ) return -1;
658 if (GameSounds[soundnum].data==NULL) {
662 if ((objnum<0)||(objnum>Highest_object_index))
664 if (digi_driver_board<1) return -1;
667 // Hack to keep sounds from building up...
668 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, &Objects[objnum].pos, Objects[objnum].segnum, max_volume,&volume, &pan, max_distance );
669 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
673 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
674 if (SoundObjects[i].flags==0)
677 if (i==MAX_SOUND_OBJECTS) {
678 mprintf((1, "Too many sound objects!\n" ));
682 SoundObjects[i].signature=next_signature++;
683 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_OBJ;
685 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
686 SoundObjects[i].lo_objnum = objnum;
687 SoundObjects[i].lo_objsignature = Objects[objnum].signature;
688 SoundObjects[i].max_volume = max_volume;
689 SoundObjects[i].max_distance = max_distance;
690 SoundObjects[i].volume = 0;
691 SoundObjects[i].pan = 0;
692 SoundObjects[i].soundnum = soundnum;
694 objp = &Objects[SoundObjects[i].lo_objnum];
695 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
696 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
697 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
699 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
700 digi_start_sound_object(i);
702 return SoundObjects[i].signature;
705 int digi_link_sound_to_object( int soundnum, short objnum, int forever, fix max_volume )
707 return digi_link_sound_to_object2( soundnum, objnum, forever, max_volume, 256*F1_0 );
710 int digi_link_sound_to_pos2( int org_soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume, fix max_distance )
715 soundnum = digi_xlat_sound(org_soundnum);
717 if ( max_volume < 0 ) return -1;
718 // if ( max_volume > F1_0 ) max_volume = F1_0;
720 if (!Digi_initialized) return -1;
721 if (soundnum < 0 ) return -1;
722 if (GameSounds[soundnum].data==NULL) {
726 if (digi_driver_board<1) return -1;
728 if ((segnum<0)||(segnum>Highest_segment_index))
732 // Hack to keep sounds from building up...
733 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum, pos, segnum, max_volume, &volume, &pan, max_distance );
734 digi_play_sample_3d( org_soundnum, pan, volume, 0 );
738 for (i=0; i<MAX_SOUND_OBJECTS; i++ )
739 if (SoundObjects[i].flags==0)
742 if (i==MAX_SOUND_OBJECTS) {
743 mprintf((1, "Too many sound objects!\n" ));
748 SoundObjects[i].signature=next_signature++;
749 SoundObjects[i].flags = SOF_USED | SOF_LINK_TO_POS;
751 SoundObjects[i].flags |= SOF_PLAY_FOREVER;
752 SoundObjects[i].lp_segnum = segnum;
753 SoundObjects[i].lp_sidenum = sidenum;
754 SoundObjects[i].lp_position = *pos;
755 SoundObjects[i].soundnum = soundnum;
756 SoundObjects[i].max_volume = max_volume;
757 SoundObjects[i].max_distance = max_distance;
758 SoundObjects[i].volume = 0;
759 SoundObjects[i].pan = 0;
760 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
761 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
762 SoundObjects[i].max_volume,
763 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
765 if (!forever || SoundObjects[i].volume >= MIN_VOLUME)
766 digi_start_sound_object(i);
768 return SoundObjects[i].signature;
771 int digi_link_sound_to_pos( int soundnum, short segnum, short sidenum, vms_vector * pos, int forever, fix max_volume )
773 return digi_link_sound_to_pos2( soundnum, segnum, sidenum, pos, forever, max_volume, F1_0 * 256 );
776 void digi_kill_sound_linked_to_segment( int segnum, int sidenum, int soundnum )
780 soundnum = digi_xlat_sound(soundnum);
782 if (!Digi_initialized) return;
783 if (digi_driver_board<1) return;
787 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
788 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_POS) ) {
789 if ((SoundObjects[i].lp_segnum == segnum) && (SoundObjects[i].soundnum==soundnum ) && (SoundObjects[i].lp_sidenum==sidenum) ) {
790 if ( SoundObjects[i].flags & SOF_PLAYING ) {
791 deallocate_voice(SoundObjects[i].handle);
793 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
798 // If this assert happens, it means that there were 2 sounds
799 // that got deleted. Weird, get John.
801 mprintf( (1, "ERROR: More than 1 sounds were deleted from seg %d\n", segnum ));
805 void digi_kill_sound_linked_to_object( int objnum )
809 if (!Digi_initialized) return;
810 if (digi_driver_board<1) return;
814 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
815 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_LINK_TO_OBJ ) ) {
816 if (SoundObjects[i].lo_objnum == objnum) {
817 if ( SoundObjects[i].flags & SOF_PLAYING ) {
818 deallocate_voice(SoundObjects[i].handle );
820 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
825 // If this assert happens, it means that there were 2 sounds
826 // that got deleted. Weird, get John.
828 mprintf( (1, "ERROR: More than 1 sounds were deleted from object %d\n", objnum ));
832 void digi_sync_sounds()
835 int oldvolume, oldpan;
837 if (!Digi_initialized) return;
838 if (digi_driver_board<1) return;
840 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
841 if ( SoundObjects[i].flags & SOF_USED ) {
842 oldvolume = SoundObjects[i].volume;
843 oldpan = SoundObjects[i].pan;
845 if ( !(SoundObjects[i].flags & SOF_PLAY_FOREVER) ) {
846 // Check if its done.
847 if (SoundObjects[i].flags & SOF_PLAYING) {
848 if (voice_get_position(SoundObjects[i].handle) < 0) {
849 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
850 continue; // Go on to next sound...
855 if ( SoundObjects[i].flags & SOF_LINK_TO_POS ) {
856 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
857 &SoundObjects[i].lp_position, SoundObjects[i].lp_segnum,
858 SoundObjects[i].max_volume,
859 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
861 } else if ( SoundObjects[i].flags & SOF_LINK_TO_OBJ ) {
864 objp = &Objects[SoundObjects[i].lo_objnum];
866 if ((objp->type==OBJ_NONE) || (objp->signature!=SoundObjects[i].lo_objsignature)) {
867 // The object that this is linked to is dead, so just end this sound if it is looping.
868 if ( (SoundObjects[i].flags & SOF_PLAYING) && (SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
869 deallocate_voice(SoundObjects[i].handle);
871 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
872 continue; // Go on to next sound...
874 digi_get_sound_loc( &Viewer->orient, &Viewer->pos, Viewer->segnum,
875 &objp->pos, objp->segnum, SoundObjects[i].max_volume,
876 &SoundObjects[i].volume, &SoundObjects[i].pan, SoundObjects[i].max_distance );
880 if (oldvolume != SoundObjects[i].volume) {
881 if ( SoundObjects[i].volume < MIN_VOLUME ) {
882 // Sound is too far away, so stop it from playing.
883 if ((SoundObjects[i].flags & SOF_PLAYING)&&(SoundObjects[i].flags & SOF_PLAY_FOREVER)) {
884 deallocate_voice(SoundObjects[i].handle);
885 SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing
888 if (!(SoundObjects[i].flags & SOF_PLAYING)) {
889 digi_start_sound_object(i);
891 voice_set_volume(SoundObjects[i].handle, fixmuldiv(SoundObjects[i].volume,digi_volume,F1_0));
896 if (oldpan != SoundObjects[i].pan) {
897 if (SoundObjects[i].flags & SOF_PLAYING)
898 voice_set_pan(SoundObjects[i].handle, SoundObjects[i].pan >> 8);
904 int sound_paused = 0;
906 void digi_pause_all()
910 if (!Digi_initialized) return;
912 if (sound_paused==0) {
913 // if ( digi_midi_type > 0 ) {
918 if (digi_driver_board>0) {
919 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
920 if ( (SoundObjects[i].flags & SOF_USED) && (SoundObjects[i].flags & SOF_PLAYING)&& (SoundObjects[i].flags & SOF_PLAY_FOREVER) ) {
921 deallocate_voice(SoundObjects[i].handle );
922 SoundObjects[i].flags &= ~SOF_PLAYING; // Mark sound as not playing
930 void digi_resume_all()
932 if (!Digi_initialized) return;
934 Assert( sound_paused > 0 );
936 if (sound_paused==1) {
938 // if ( digi_midi_type > 0 ) {
951 if (!Digi_initialized) return;
953 // if ( digi_midi_type > 0 ) {
955 // destroy_midi(SongHandle);
956 // SongHandle = NULL;
961 if (digi_driver_board>0) {
962 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
963 if ( SoundObjects[i].flags & SOF_USED ) {
964 if ( SoundObjects[i].flags & SOF_PLAYING ) {
965 deallocate_voice(SoundObjects[i].handle );
967 SoundObjects[i].flags = 0; // Mark as dead, so some other sound can use this sound
974 int verify_channel_not_used_by_soundobjects( int channel )
977 if (digi_driver_board>0) {
978 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
979 if ( SoundObjects[i].flags & SOF_USED ) {
980 if ( SoundObjects[i].flags & SOF_PLAYING ) {
981 if ( SoundObjects[i].handle == channel ) {
982 mprintf(( 0, "ERROR STARTING SOUND CHANNEL ON USED SLOT!!\n" ));
993 #if 0 // hud sound debug info
995 #include "gamefont.h"
996 #define VIRTUAL_VOICES 256
997 void show_digi_info() {
998 int i, active_slots = 0, done_slots = 0, allg_used = 0;
1000 for (i=0; i<DIGI_SLOTS; i++)
1001 if (VALID_CHANNEL(SampleHandles[i])) {
1003 if (!voice_check(SampleHandles[i]))
1006 for (i=0; i<VIRTUAL_VOICES; i++)
1011 gr_set_curfont( GAME_FONT );
1012 gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
1013 gr_printf(0,32,"voices: real:%d exp:%d locks:%d sluse:%d sldone:%d aused:%d slnxt:%d",
1014 digi_driver->voices, digi_max_channels, digi_total_locks,
1015 active_slots,done_slots,allg_used, next_handle);