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)
64 static int digi_volume = _DIGI_MAX_VOLUME; // Max volume
65 //static int midi_volume = 128/2; // Max volume
66 //static int midi_system_initialized = 0;
67 //static int digi_system_initialized = 0;
68 static int timer_system_initialized = 0;
69 static int digi_sound_locks[MAX_SOUNDS];
70 //char digi_last_midi_song[16] = "";
71 //char digi_last_melodic_bank[16] = "";
72 //char digi_last_drum_bank[16] = "";
73 char *digi_driver_path = NULL;
75 extern int midi_volume;
77 //static void * lpInstruments = NULL; // pointer to the instrument file
78 //static int InstrumentSize = 0;
79 //static void * lpDrums = NULL; // pointer to the drum file
80 //static int DrumSize = 0;
82 // handle for the initialized MIDI song
83 //MIDI *SongHandle = NULL;
86 // a channel (voice) id is an int in Allegro
88 #define VALID_CHANNEL(ch) (ch >= 0)
89 #define INVALID_CHANNEL -1
91 #define DIGI_SLOTS DIGI_VOICES
93 // next_handle is a Descent internal number (hereafter reffered to as slot),
94 // which indexes into SampleHandles, SoundNums and SoundVolumes.
95 // only digi_max_channels entries are used.
96 // SampleHandles points to sounddriver handles (voices)
97 static int next_handle = 0;
98 static CHANNEL SampleHandles[DIGI_SLOTS] = {
99 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
100 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
101 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
102 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
103 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
104 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
105 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL,
106 INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL, INVALID_CHANNEL };
107 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 };
108 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 };
110 void digi_reset_digi_sounds();
111 int verify_channel_not_used_by_soundobjects( int channel );
114 if (!Digi_initialized) return;
117 Digi_initialized = 0;
119 if ( timer_system_initialized ) {
121 timer_set_function( NULL );
123 timer_system_initialized = 0;
126 /* initialize sound system. 0=ok, 1=error */
130 if (!timer_system_initialized)
133 timer_system_initialized = 1;
135 if (!Digi_initialized) {
136 // amount of voices we need
137 // 16 for normal sounds and 16 for SoundObjects (fan, boss)
138 // for DIGMID we sacrify some sounds (32 is the max).
139 // reserve_voices(allegro_using_digmid() ? 16 : 32, -1);
140 if (install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, NULL))
143 digi_driver_board = digi_card; // only for 0, !=0
144 digi_midi_type = midi_card; // only for 0, !=0
146 Digi_initialized = 1;
149 if (!digi_atexit_called) {
150 atexit( digi_close );
151 digi_atexit_called = 1;
155 digi_set_midi_volume( midi_volume );
157 for (i=0; i<MAX_SOUNDS; i++ )
158 digi_sound_locks[i] = 0;
159 digi_reset_digi_sounds();
164 // Toggles sound system on/off
167 if ( Digi_initialized ) {
168 digi_reset_digi_sounds();
170 mprintf( (0, "Sound system DISABLED.\n" ));
173 mprintf( (0, "Sound system ENABLED.\n" ));
177 int digi_total_locks = 0;
179 ubyte * digi_lock_sound_data( int soundnum )
183 if ( !Digi_initialized ) return NULL;
184 if ( digi_driver_board <= 0 ) return NULL;
186 if ( digi_sound_locks[soundnum] == 0 ) {
188 //mprintf(( 0, "Total sound locks = %d\n", digi_total_locks ));
189 i = dpmi_lock_region( GameSounds[soundnum].data, GameSounds[soundnum].len );
190 if ( !i ) Error( "Error locking sound %d\n", soundnum );
192 digi_sound_locks[soundnum]++;
193 return GameSounds[soundnum].data;
196 void digi_unlock_sound_data( int soundnum )
200 if ( !Digi_initialized ) return;
201 if ( digi_driver_board <= 0 ) return;
203 Assert( digi_sound_locks[soundnum] > 0 );
205 if ( digi_sound_locks[soundnum] == 1 ) {
207 //mprintf(( 0, "Total sound locks = %d\n", digi_total_locks ));
208 i = dpmi_unlock_region( GameSounds[soundnum].data, GameSounds[soundnum].len );
209 if ( !i ) Error( "Error unlocking sound %d\n", soundnum );
211 digi_sound_locks[soundnum]--;
215 void digi_reset_digi_sounds() {
218 for (i = 0; i < DIGI_SLOTS; i++) {
219 if (VALID_CHANNEL(SampleHandles[i])) {
220 deallocate_voice(SampleHandles[i]);
221 SampleHandles[i] = INVALID_CHANNEL;
223 if (SoundNums[i] != -1) {
224 digi_unlock_sound_data(SoundNums[i]);
228 for (i=0; i<MAX_SOUNDS; i++ ) {
229 Assert( digi_sound_locks[i] == 0 );
233 void digi_set_max_channels(int n) {
234 digi_max_channels = n;
236 if ( digi_max_channels < 1 )
237 digi_max_channels = 1;
238 if ( digi_max_channels > DIGI_VOICES)
239 digi_max_channels = DIGI_VOICES;
242 int digi_get_max_channels()
244 return digi_max_channels;
247 void digi_stop_all_channels()
251 for (i = 0; i < MAX_SOUND_SLOTS; i++)
255 int get_free_slot() {
260 // sound playing on slot <next_handle>?
261 if ( (VALID_CHANNEL(SampleHandles[next_handle])) &&
262 (voice_check(SampleHandles[next_handle])) ) {
263 // don't use this slot if loud sound
264 if ( (SoundVolumes[next_handle] > digi_volume) &&
265 (ntries<digi_max_channels) ) {
266 mprintf(( 0, "Not stopping loud sound %d (%d).\n", next_handle, SoundNums[next_handle]));
268 if ( next_handle >= digi_max_channels )
273 //mprintf(( 0, "[SS:%d]", next_handle ));
274 if (voice_check(next_handle))
275 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));
276 deallocate_voice(SampleHandles[next_handle]);
277 SampleHandles[next_handle] = INVALID_CHANNEL;
280 if ( SoundNums[next_handle] != -1 ) {
281 digi_unlock_sound_data(SoundNums[next_handle]);
282 SoundNums[next_handle] = -1;
284 ret_slot = next_handle;
286 if ( next_handle >= digi_max_channels )
291 CHANNEL digi_start_sound(int soundnum, int volume, int pan) {
296 volume = fixmul(volume, digi_volume);
297 slot = get_free_slot();
299 digi_lock_sound_data(soundnum);
300 channel = play_sample(&GameSounds[soundnum], volume, pan >> 8, 1000, 0);
302 mprintf(( 1, "NOT ENOUGH SOUND SLOTS!!!\n" ));
303 digi_unlock_sound_data(soundnum);
306 release_voice(channel);
308 //mprintf(( 0, "Starting sound on channel %d\n", channel ));
310 verify_channel_not_used_by_soundobjects(channel);
313 // find slots pointing to just allocated channel and kill sounds on it
314 // (because they can't be playing right now)
315 for (i=0; i<digi_max_channels; i++ ) {
316 if (SampleHandles[i] == channel) {
317 SampleHandles[i] = INVALID_CHANNEL;
318 if (SoundNums[i] != -1) {
319 digi_unlock_sound_data(SoundNums[i]);
325 // fill slot with data of just started sample
326 SampleHandles[slot] = channel;
327 SoundNums[slot] = soundnum;
328 SoundVolumes[slot] = volume;
333 // Returns the channel a sound number is playing on, or
335 int digi_find_channel(int soundno)
337 if (!digi_initialised)
343 if (GameSounds[soundno].data == NULL)
349 //FIXME: not implemented
353 int digi_is_sound_playing(int soundno)
357 soundno = digi_xlat_sound(soundno);
359 for (i = 0; i < DIGI_VOICES; i++)
360 if (voice_check(i) == &GameSounds[soundno])
365 //-killed- void digi_set_midi_volume( int mvolume )
367 //-killed- int old_volume = midi_volume;
369 //-killed- if ( mvolume > 127 )
370 //-killed- midi_volume = 127;
371 //-killed- else if ( mvolume < 0 )
372 //-killed- midi_volume = 0;
374 //-killed- midi_volume = mvolume;
376 //-killed- if ( (digi_midi_type > 0) ) {
377 //-killed- if ( (old_volume < 1) && ( midi_volume > 1 ) ) {
378 //-killed- if (SongHandle == NULL )
379 //-killed- digi_play_midi_song( digi_last_midi_song, digi_last_melodic_bank, digi_last_drum_bank, 1 );
381 //-killed- set_volume(-1, midi_volume * 2 + (midi_volume & 1));
385 void digi_set_digi_volume( int dvolume )
387 dvolume = fixmuldiv( dvolume, _DIGI_MAX_VOLUME, 0x7fff);
388 if ( dvolume > _DIGI_MAX_VOLUME )
389 digi_volume = _DIGI_MAX_VOLUME;
390 else if ( dvolume < 0 )
393 digi_volume = dvolume;
395 if ( !Digi_initialized ) return;
396 if ( digi_driver_board <= 0 ) return;
402 void digi_set_volume( int dvolume, int mvolume )
404 digi_set_midi_volume( mvolume );
405 digi_set_digi_volume( dvolume );
406 // mprintf(( 1, "Volume: 0x%x and 0x%x\n", digi_volume, midi_volume ));
409 int digi_is_channel_playing(int channel)
413 if (!digi_initialised)
416 //FIXME: not implemented
420 void digi_set_channel_volume(int channel, int volume)
422 if (!digi_initialised)
425 //FIXME: not implemented
428 void digi_set_channel_pan(int channel, int pan)
430 if (!digi_initialised)
433 //FIXME: not implemented
436 void digi_stop_sound(int channel)
438 //FIXME: not implemented
441 void digi_end_sound(int channel)
443 if (!digi_initialised)
446 //FIXME: not implemented
449 //-killed- void digi_stop_current_song()
451 //-killed- if (SongHandle) {
452 //-killed- destroy_midi(SongHandle);
453 //-killed- SongHandle = NULL;
457 //-killed- void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop )
459 //-killed- //char fname[128];
461 //-killed- if (!Digi_initialized) return;
462 //-killed- if ( digi_midi_type <= 0 ) return;
464 //-killed- digi_stop_current_song();
466 //-killed- if ( filename == NULL ) return;
468 //-killed- strcpy( digi_last_midi_song, filename );
469 //-killed- strcpy( digi_last_melodic_bank, melodic_bank );
470 //-killed- strcpy( digi_last_drum_bank, drum_bank );
472 //-killed- if ( midi_volume < 1 )
474 //-killed- SongHandle = NULL;
476 //-killed- #if 0 /* needs bank loading to sound right */
477 //-killed- if (midi_card <= 4) { /* FM cards */
479 //-killed- sl = strlen( filename );
480 //-killed- strcpy( fname, filename );
481 //-killed- fname[sl-1] = 'q';
482 //-killed- SongHandle = load_hmp(fname);
486 //-killed- if ( !SongHandle )
487 //-killed- SongHandle = load_hmp(filename);
489 //-killed- if (SongHandle) {
490 //-killed- if (play_midi(SongHandle, loop)) {
491 //-killed- destroy_midi(SongHandle);
492 //-killed- SongHandle = NULL;
495 //-killed- if (!SongHandle) {
496 //-killed- mprintf( (1, "\nAllegro Error : %s", allegro_error ));
507 if (!digi_initialised)
510 for (i = 0; i < digi_max_channels; i++)
512 if (digi_is_channel_playing(i))
516 mprintf_at((0, 2, 0, "DIGI: Active Sound Channels: %d/%d (HMI says %d/32) ", n_voices, digi_max_channels, -1));
517 //mprintf_at((0, 3, 0, "DIGI: Number locked sounds: %d ", digi_total_locks ));
520 int verify_channel_not_used_by_soundobjects( int channel )
523 if (digi_driver_board>0) {
524 for (i=0; i<MAX_SOUND_OBJECTS; i++ ) {
525 if ( SoundObjects[i].flags & SOF_USED ) {
526 if ( SoundObjects[i].flags & SOF_PLAYING ) {
527 if ( SoundObjects[i].handle == channel ) {
528 mprintf(( 0, "ERROR STARTING SOUND CHANNEL ON USED SLOT!!\n" ));
539 #if 0 // hud sound debug info
541 #include "gamefont.h"
542 #define VIRTUAL_VOICES 256
543 void show_digi_info() {
544 int i, active_slots = 0, done_slots = 0, allg_used = 0;
546 for (i=0; i<DIGI_SLOTS; i++)
547 if (VALID_CHANNEL(SampleHandles[i])) {
549 if (!voice_check(SampleHandles[i]))
552 for (i=0; i<VIRTUAL_VOICES; i++)
557 gr_set_curfont( GAME_FONT );
558 gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
559 gr_printf(0,32,"voices: real:%d exp:%d locks:%d sluse:%d sldone:%d aused:%d slnxt:%d",
560 digi_driver->voices, digi_max_channels, digi_total_locks,
561 active_slots,done_slots,allg_used, next_handle);