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.
33 #define _DIGI_MAX_VOLUME 128 // set lower to have difference with > F1_0 sounds
35 #define MIN_VOLUME 10 // minimal volume to be played (in 0-F1_0(?) range)
38 #define _MELODIC_PATCH "melodic.bnk"
39 #define _DRUM_PATCH "drum.bnk"
40 #define _DIGDRUM_PATCH "drum32.dig"
43 static int Digi_initialized = 0;
44 static int digi_atexit_called = 0; // Set to 1 if atexit(digi_close) was called
46 int digi_driver_board = 0;
47 int digi_driver_port = 0;
48 int digi_driver_irq = 0;
49 int digi_driver_dma = 0;
50 //int digi_midi_type = 0; // Midi driver type
51 //int digi_midi_port = 0; // Midi driver port
52 static int digi_max_channels = 8;
53 //static int digi_driver_rate = 11025; // rate to use driver at
54 //static int digi_dma_buffersize = 4096; // size of the dma buffer to use (4k)
55 int digi_timer_rate = 9943; // rate for the timer to go off to handle the driver system (120 Hz)
56 static int digi_volume = _DIGI_MAX_VOLUME; // Max volume
57 //static int midi_volume = 128/2; // Max volume
58 //static int midi_system_initialized = 0;
59 //static int digi_system_initialized = 0;
60 static int timer_system_initialized = 0;
61 static int digi_sound_locks[MAX_SOUNDS];
62 //char digi_last_midi_song[16] = "";
63 //char digi_last_melodic_bank[16] = "";
64 //char digi_last_drum_bank[16] = "";
65 char *digi_driver_path = NULL;
67 extern int midi_volume;
69 //static void * lpInstruments = NULL; // pointer to the instrument file
70 //static int InstrumentSize = 0;
71 //static void * lpDrums = NULL; // pointer to the drum file
72 //static int DrumSize = 0;
74 // handle for the initialized MIDI song
75 //MIDI *SongHandle = NULL;
78 // a channel (voice) id is an int in Allegro
80 #define VALID_CHANNEL(ch) (ch >= 0)
81 #define INVALID_CHANNEL -1
83 #define DIGI_SLOTS DIGI_VOICES
85 // next_handle is a Descent internal number (hereafter reffered to as slot),
86 // which indexes into SampleHandles, SoundNums and SoundVolumes.
87 // only digi_max_channels entries are used.
88 // SampleHandles points to sounddriver handles (voices)
89 static int next_handle = 0;
90 static CHANNEL SampleHandles[DIGI_SLOTS] = {
91 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
92 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
93 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
94 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
95 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
96 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
97 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
98 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL };
99 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 };
100 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 };
102 void digi_reset_digi_sounds();
103 int verify_channel_not_used_by_soundobjects( int channel );
106 if (!Digi_initialized) return;
109 Digi_initialized = 0;
111 if ( timer_system_initialized ) {
113 timer_set_function( NULL );
115 timer_system_initialized = 0;
118 /* initialize sound system. 0=ok, 1=error */
122 if (!timer_system_initialized)
125 timer_system_initialized = 1;
127 if (!Digi_initialized) {
128 // amount of voices we need
129 // 16 for normal sounds and 16 for SoundObjects (fan, boss)
130 // for DIGMID we sacrify some sounds (32 is the max).
131 // reserve_voices(allegro_using_digmid() ? 16 : 32, -1);
132 if (install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, NULL))
135 digi_driver_board = digi_card; // only for 0, !=0
136 digi_midi_type = midi_card; // only for 0, !=0
138 Digi_initialized = 1;
141 if (!digi_atexit_called) {
142 atexit( digi_close );
143 digi_atexit_called = 1;
147 digi_set_midi_volume( midi_volume );
149 for (i=0; i<MAX_SOUNDS; i++ )
150 digi_sound_locks[i] = 0;
151 digi_reset_digi_sounds();
156 // Toggles sound system on/off
159 if ( Digi_initialized ) {
160 digi_reset_digi_sounds();
162 mprintf( (0, "Sound system DISABLED.\n" ));
165 mprintf( (0, "Sound system ENABLED.\n" ));
169 int digi_total_locks = 0;
171 ubyte * digi_lock_sound_data( int soundnum )
175 if ( !Digi_initialized ) return NULL;
176 if ( digi_driver_board <= 0 ) return NULL;
178 if ( digi_sound_locks[soundnum] == 0 ) {
180 //mprintf(( 0, "Total sound locks = %d\n", digi_total_locks ));
181 i = dpmi_lock_region( GameSounds[soundnum].data, GameSounds[soundnum].len );
182 if ( !i ) Error( "Error locking sound %d\n", soundnum );
184 digi_sound_locks[soundnum]++;
185 return GameSounds[soundnum].data;
188 void digi_unlock_sound_data( int soundnum )
192 if ( !Digi_initialized ) return;
193 if ( digi_driver_board <= 0 ) return;
195 Assert( digi_sound_locks[soundnum] > 0 );
197 if ( digi_sound_locks[soundnum] == 1 ) {
199 //mprintf(( 0, "Total sound locks = %d\n", digi_total_locks ));
200 i = dpmi_unlock_region( GameSounds[soundnum].data, GameSounds[soundnum].len );
201 if ( !i ) Error( "Error unlocking sound %d\n", soundnum );
203 digi_sound_locks[soundnum]--;
207 void digi_reset_digi_sounds() {
210 for (i = 0; i < DIGI_SLOTS; i++) {
211 if (VALID_CHANNEL(SampleHandles[i])) {
212 deallocate_voice(SampleHandles[i]);
213 SampleHandles[i] = INVALID_CHANNEL;
215 if (SoundNums[i] != -1) {
216 digi_unlock_sound_data(SoundNums[i]);
220 for (i=0; i<MAX_SOUNDS; i++ ) {
221 Assert( digi_sound_locks[i] == 0 );
225 void digi_set_max_channels(int n) {
226 digi_max_channels = n;
228 if ( digi_max_channels < 1 )
229 digi_max_channels = 1;
230 if ( digi_max_channels > DIGI_VOICES)
231 digi_max_channels = DIGI_VOICES;
234 int digi_get_max_channels()
236 return digi_max_channels;
239 void digi_stop_all_channels()
243 for (i = 0; i < MAX_SOUND_SLOTS; i++)
247 int get_free_slot() {
252 // sound playing on slot <next_handle>?
253 if ( (VALID_CHANNEL(SampleHandles[next_handle])) &&
254 (voice_check(SampleHandles[next_handle])) ) {
255 // don't use this slot if loud sound
256 if ( (SoundVolumes[next_handle] > digi_volume) &&
257 (ntries<digi_max_channels) ) {
258 mprintf(( 0, "Not stopping loud sound %d (%d).\n", next_handle, SoundNums[next_handle]));
260 if ( next_handle >= digi_max_channels )
265 //mprintf(( 0, "[SS:%d]", next_handle ));
266 if (voice_check(next_handle))
267 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));
268 deallocate_voice(SampleHandles[next_handle]);
269 SampleHandles[next_handle] = INVALID_CHANNEL;
272 if ( SoundNums[next_handle] != -1 ) {
273 digi_unlock_sound_data(SoundNums[next_handle]);
274 SoundNums[next_handle] = -1;
276 ret_slot = next_handle;
278 if ( next_handle >= digi_max_channels )
283 CHANNEL digi_start_sound(int soundnum, int volume, int pan) {
288 volume = fixmul(volume, digi_volume);
289 slot = get_free_slot();
291 digi_lock_sound_data(soundnum);
292 channel = play_sample(&GameSounds[soundnum], volume, pan >> 8, 1000, 0);
294 mprintf(( 1, "NOT ENOUGH SOUND SLOTS!!!\n" ));
295 digi_unlock_sound_data(soundnum);
298 release_voice(channel);
300 //mprintf(( 0, "Starting sound on channel %d\n", channel ));
302 verify_channel_not_used_by_soundobjects(channel);
305 // find slots pointing to just allocated channel and kill sounds on it
306 // (because they can't be playing right now)
307 for (i=0; i<digi_max_channels; i++ ) {
308 if (SampleHandles[i] == channel) {
309 SampleHandles[i] = INVALID_CHANNEL;
310 if (SoundNums[i] != -1) {
311 digi_unlock_sound_data(SoundNums[i]);
317 // fill slot with data of just started sample
318 SampleHandles[slot] = channel;
319 SoundNums[slot] = soundnum;
320 SoundVolumes[slot] = volume;
325 // Returns the channel a sound number is playing on, or
327 int digi_find_channel(int soundno)
329 if (!Digi_initialized)
335 if (GameSounds[soundno].data == NULL)
341 //FIXME: not implemented
345 int digi_is_sound_playing(int soundno)
349 soundno = digi_xlat_sound(soundno);
351 for (i = 0; i < DIGI_VOICES; i++)
352 if (voice_check(i) == &GameSounds[soundno])
357 //-killed- void digi_set_midi_volume( int mvolume )
359 //-killed- int old_volume = midi_volume;
361 //-killed- if ( mvolume > 127 )
362 //-killed- midi_volume = 127;
363 //-killed- else if ( mvolume < 0 )
364 //-killed- midi_volume = 0;
366 //-killed- midi_volume = mvolume;
368 //-killed- if ( (digi_midi_type > 0) ) {
369 //-killed- if ( (old_volume < 1) && ( midi_volume > 1 ) ) {
370 //-killed- if (SongHandle == NULL )
371 //-killed- digi_play_midi_song( digi_last_midi_song, digi_last_melodic_bank, digi_last_drum_bank, 1 );
373 //-killed- set_volume(-1, midi_volume * 2 + (midi_volume & 1));
377 void digi_set_digi_volume( int dvolume )
379 dvolume = fixmuldiv( dvolume, _DIGI_MAX_VOLUME, 0x7fff);
380 if ( dvolume > _DIGI_MAX_VOLUME )
381 digi_volume = _DIGI_MAX_VOLUME;
382 else if ( dvolume < 0 )
385 digi_volume = dvolume;
387 if ( !Digi_initialized ) return;
388 if ( digi_driver_board <= 0 ) return;
394 void digi_set_volume( int dvolume, int mvolume )
396 digi_set_midi_volume( mvolume );
397 digi_set_digi_volume( dvolume );
398 // mprintf(( 1, "Volume: 0x%x and 0x%x\n", digi_volume, midi_volume ));
401 int digi_is_channel_playing(int channel)
405 if (!Digi_initialized)
408 //FIXME: not implemented
412 void digi_set_channel_volume(int channel, int volume)
414 if (!Digi_initialized)
417 //FIXME: not implemented
420 void digi_set_channel_pan(int channel, int pan)
422 if (!Digi_initialized)
425 //FIXME: not implemented
428 void digi_stop_sound(int channel)
430 //FIXME: not implemented
433 void digi_end_sound(int channel)
435 if (!Digi_initialized)
438 //FIXME: not implemented
441 //-killed- void digi_stop_current_song()
443 //-killed- if (SongHandle) {
444 //-killed- destroy_midi(SongHandle);
445 //-killed- SongHandle = NULL;
449 //-killed- void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop )
451 //-killed- //char fname[128];
453 //-killed- if (!Digi_initialized) return;
454 //-killed- if ( digi_midi_type <= 0 ) return;
456 //-killed- digi_stop_current_song();
458 //-killed- if ( filename == NULL ) return;
460 //-killed- strcpy( digi_last_midi_song, filename );
461 //-killed- strcpy( digi_last_melodic_bank, melodic_bank );
462 //-killed- strcpy( digi_last_drum_bank, drum_bank );
464 //-killed- if ( midi_volume < 1 )
466 //-killed- SongHandle = NULL;
468 //-killed- #if 0 /* needs bank loading to sound right */
469 //-killed- if (midi_card <= 4) { /* FM cards */
471 //-killed- sl = strlen( filename );
472 //-killed- strcpy( fname, filename );
473 //-killed- fname[sl-1] = 'q';
474 //-killed- SongHandle = load_hmp(fname);
478 //-killed- if ( !SongHandle )
479 //-killed- SongHandle = load_hmp(filename);
481 //-killed- if (SongHandle) {
482 //-killed- if (play_midi(SongHandle, loop)) {
483 //-killed- destroy_midi(SongHandle);
484 //-killed- SongHandle = NULL;
487 //-killed- if (!SongHandle) {
488 //-killed- mprintf( (1, "\nAllegro Error : %s", allegro_error ));
499 if (!Digi_initialized)
502 for (i = 0; i < digi_max_channels; i++)
504 if (digi_is_channel_playing(i))
508 mprintf_at((0, 2, 0, "DIGI: Active Sound Channels: %d/%d (HMI says %d/32) ", n_voices, digi_max_channels, -1));
509 //mprintf_at((0, 3, 0, "DIGI: Number locked sounds: %d ", digi_total_locks ));
512 int verify_channel_not_used_by_soundobjects( int channel )
515 if (digi_driver_board>0) {
516 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
517 if ( SoundObjects[i].flags & SOF_USED ) {
518 if ( SoundObjects[i].flags & SOF_PLAYING ) {
519 if ( SoundObjects[i].handle == channel ) {
520 mprintf(( 0, "ERROR STARTING SOUND CHANNEL ON USED SLOT!!\n" ));
531 #if 0 // hud sound debug info
533 #include "gamefont.h"
534 #define VIRTUAL_VOICES 256
535 void show_digi_info() {
536 int i, active_slots = 0, done_slots = 0, allg_used = 0;
538 for (i=0; i<DIGI_SLOTS; i++)
539 if (VALID_CHANNEL(SampleHandles[i])) {
541 if (!voice_check(SampleHandles[i]))
544 for (i=0; i<VIRTUAL_VOICES; i++)
549 gr_set_curfont( GAME_FONT );
550 gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
551 gr_printf(0,32,"voices: real:%d exp:%d locks:%d sluse:%d sldone:%d aused:%d slnxt:%d",
552 digi_driver->voices, digi_max_channels, digi_total_locks,
553 active_slots,done_slots,allg_used, next_handle);